Index: generic/predefined.h =================================================================== diff -u -rd56d2a8ee3f246c9891783abb09bd820dbc508e4 -r2454ab78913d0686b2ec5feeb401a051dc6a6164 --- generic/predefined.h (.../predefined.h) (revision d56d2a8ee3f246c9891783abb09bd820dbc508e4) +++ generic/predefined.h (.../predefined.h) (revision 2454ab78913d0686b2ec5feeb401a051dc6a6164) @@ -41,7 +41,9 @@ "if {$what in [list \"alias\" \"forward\" \"method\" \"setter\"]} {\n" "return [::xotcl::dispatch [self] ::xotcl::classes::xotcl2::Object::$what {*}$args]}\n" "if {$what in [list \"info\"]} {\n" -"::xotcl2::objectInfo [lindex $args 0] [self] {*}[lrange $args 1 end]}}\n" +"return [::xotcl2::objectInfo [lindex $args 0] [self] {*}[lrange $args 1 end]]}\n" +"if {$what in [list \"filter\" \"mixin\"]} {\n" +"return [.object-$what {*}$args]}}\n" ".method unknown {m args} {\n" "error \"Method '$m' unknown for [self].\\\n" "Consider '[self] create $m $args' instead of '[self] $m $args'\"}}\n" @@ -81,7 +83,7 @@ "::xotcl::setter [self] $methodName -per-object}}\n" "Class public method setter {methodName value:optional} {\n" "if {[info exists value]} {\n" -"::xotcl::setter [self] $methodName $value} else {\n" +"::xotcl::setter [self] $methodName $value} else {\n" "::xotcl::setter [self] $methodName}}\n" "Object create ::xotcl2::objectInfo\n" "Object create ::xotcl2::classInfo\n" @@ -200,6 +202,7 @@ "$class __invalidateobjectparameter}\n" "createBootstrapAttributeSlots ::xotcl::Slot {\n" "{name \"[namespace tail [::xotcl::self]]\"}\n" +"{methodname \"[namespace tail [::xotcl::self]]\"}\n" "{domain \"[lindex [regexp -inline {^(.*)::slot::[^:]+$} [::xotcl::self]] 1]\"}\n" "{defaultmethods {get assign}}\n" "{manager \"[::xotcl::self]\"}\n" @@ -241,8 +244,7 @@ "set cl [expr {${.per-object} ? \"Object\" : \"Class\"}]\n" "::xotcl::dispatch ${.domain} ::xotcl::classes::xotcl2::${cl}::forward \\\n" "${.name} ${.manager} [list %1 [${.manager} defaultmethods]] %self \\\n" -"\"%-per-object [info exists .forward-per-object]\" \\\n" -"%proc}}\n" +"${.methodname}}}\n" "::xotcl::MetaSlot create ::xotcl::InfoSlot\n" "createBootstrapAttributeSlots ::xotcl::InfoSlot {\n" "{multivalued true}\n" @@ -253,15 +255,12 @@ "::xotcl::InfoSlot public method add {obj prop value {pos 0}} {\n" "if {![set .multivalued]} {\n" "error \"Property $prop of ${.domain}->$obj ist not multivalued\"}\n" -"puts stderr \"adding infoslot: $obj $prop [linsert [$obj info $prop] $pos $value]\"\n" "$obj $prop [linsert [$obj info $prop] $pos $value]}\n" -"::xotcl::InfoSlot public method delete {-nocomplain:switch obj prop value} {\n" -"puts stderr infoslot-delete-[self args]\n" -"set old [$obj info $prop]\n" +"::xotcl::InfoSlot protected method delete_value {obj prop old value} {\n" "if {[string first * $value] > -1 || [string first \\[ $value] > -1} {\n" "if {${.elementtype} ne \"\" && ![string match ::* $value]} {\n" "set value ::$value}\n" -"return [$obj $prop [lsearch -all -not -glob -inline $old $value]]} elseif {${.elementtype} ne \"\"} {\n" +"return [lsearch -all -not -glob -inline $old $value]} elseif {${.elementtype} ne \"\"} {\n" "if {[string first :: $value] == -1} {\n" "if {![::xotcl::is $value object]} {\n" "error \"$value does not appear to be an object\"}\n" @@ -270,20 +269,23 @@ "error \"$value does not appear to be of type ${.elementtype}\"}}\n" "set p [lsearch -exact $old $value]\n" "if {$p > -1} {\n" -"$obj $prop [lreplace $old $p $p]} else {\n" +"return [lreplace $old $p $p]} else {\n" "error \"$value is not a $prop of $obj (valid are: $old)\"}}\n" +"::xotcl::InfoSlot public method delete {-nocomplain:switch obj prop value} {\n" +"$obj $prop [.delete_value $obj $prop [$obj info $prop] $value]}\n" "::xotcl::MetaSlot alloc ::xotcl::InterceptorSlot\n" "::xotcl::relation ::xotcl::InterceptorSlot superclass ::xotcl::InfoSlot\n" "::xotcl::alias ::xotcl::InterceptorSlot set ::xotcl::relation ;# for backwards compatibility\n" "::xotcl::alias ::xotcl::InterceptorSlot assign ::xotcl::relation\n" -"::xotcl::InterceptorSlot public method get {obj -per-object:switch prop} {\n" -"::xotcl::relation $obj {*}[expr {${per-object} ? \"-per-object\" : \"\"}] $prop}\n" -"::xotcl::InterceptorSlot public method add {obj -per-object:switch prop value {pos 0}} {\n" +"::xotcl::InterceptorSlot public method get {obj prop} {\n" +"::xotcl::relation $obj $prop}\n" +"::xotcl::InterceptorSlot public method add {obj prop value {pos 0}} {\n" "if {![set .multivalued]} {\n" "error \"Property $prop of ${.domain}->$obj ist not multivalued\"}\n" -"set perObject [expr {${per-object} ? \"-per-object\" : \"\"}]\n" -"set oldSetting [::xotcl::relation $obj {*}$perObject $prop]\n" -"::xotcl::relation $obj {*}$perObject $prop [linsert $oldSetting $pos $value]}\n" +"set oldSetting [::xotcl::relation $obj $prop]\n" +"::xotcl::relation $obj $prop [linsert $oldSetting $pos $value]}\n" +"::xotcl::InterceptorSlot public method delete {-nocomplain:switch obj prop value} {\n" +"::xotcl::relation $obj $prop [.delete_value $obj $prop [::xotcl::relation $obj $prop] $value]}\n" "proc ::xotcl::register_system_slots {os} {\n" "${os}::Object alloc ${os}::Class::slot\n" "${os}::Object alloc ${os}::Object::slot\n" @@ -292,8 +294,16 @@ "::xotcl::InfoSlot create ${os}::Object::slot::class -type relation\n" "::xotcl::alias ${os}::Object::slot::class assign ::xotcl::relation\n" "::xotcl::InterceptorSlot create ${os}::Object::slot::mixin \\\n" -"-type relation\n" +"-type relation -methodname object-mixin\n" "::xotcl::InterceptorSlot create ${os}::Object::slot::filter \\\n" +"-elementtype \"\" -type relation\n" +"::xotcl::InterceptorSlot create ${os}::Class::slot::mixin \\\n" +"-type relation -methodname class-mixin\n" +"::xotcl::InterceptorSlot create ${os}::Class::slot::filter \\\n" +"-type relation -methodname filter-mixin\n" +"::xotcl::InterceptorSlot create ${os}::Class::slot::object-mixin \\\n" +"-type relation\n" +"::xotcl::InterceptorSlot create ${os}::Class::slot::object-filter \\\n" "-elementtype \"\" -type relation}\n" "::xotcl::register_system_slots ::xotcl2\n" "::xotcl::MetaSlot __invalidateobjectparameter\n" Index: generic/predefined.xotcl =================================================================== diff -u -rd56d2a8ee3f246c9891783abb09bd820dbc508e4 -r2454ab78913d0686b2ec5feeb401a051dc6a6164 --- generic/predefined.xotcl (.../predefined.xotcl) (revision d56d2a8ee3f246c9891783abb09bd820dbc508e4) +++ generic/predefined.xotcl (.../predefined.xotcl) (revision 2454ab78913d0686b2ec5feeb401a051dc6a6164) @@ -82,8 +82,11 @@ return [::xotcl::dispatch [self] ::xotcl::classes::xotcl2::Object::$what {*}$args] } if {$what in [list "info"]} { - ::xotcl2::objectInfo [lindex $args 0] [self] {*}[lrange $args 1 end] + return [::xotcl2::objectInfo [lindex $args 0] [self] {*}[lrange $args 1 end]] } + if {$what in [list "filter" "mixin"]} { + return [.object-$what {*}$args] + } } # define unknown handler for class @@ -170,7 +173,7 @@ Class public method setter {methodName value:optional} { if {[info exists value]} { - ::xotcl::setter [self] $methodName $value + ::xotcl::setter [self] $methodName $value } else { ::xotcl::setter [self] $methodName } @@ -222,13 +225,8 @@ } unset cmd - #Object forward info -onerror ::xotcl::infoError ::xotcl2::objectInfo %1 {%@2 %self} - #Class forward info -onerror ::xotcl::infoError ::xotcl2::classInfo %1 {%@2 %self} - Object forward info -onerror ::xotcl::infoError ::xotcl2::objectInfo %1 {%@2 %self} Class forward info -onerror ::xotcl::infoError ::xotcl2::classInfo %1 {%@2 %self} -# ::xotcl::dispatch ::xotcl2::classInfo ::xotcl::cmd::Object::forward \ -# "-per-object" -verbose ::xotcl2::objectInfo {%@2 %1} proc ::xotcl::infoError msg { #puts stderr "INFO ERROR: <$msg>\n$::errorInfo" @@ -416,6 +414,7 @@ ############################################ createBootstrapAttributeSlots ::xotcl::Slot { {name "[namespace tail [::xotcl::self]]"} + {methodname "[namespace tail [::xotcl::self]]"} {domain "[lindex [regexp -inline {^(.*)::slot::[^:]+$} [::xotcl::self]] 1]"} {defaultmethods {get assign}} {manager "[::xotcl::self]"} @@ -475,13 +474,11 @@ } if {${.domain} ne ""} { ${.domain} __invalidateobjectparameter - # since the domain object might be xotcl1 or xotcl2, use dispatch - set cl [expr {${.per-object} ? "Object" : "Class"}] + # since the domain object might be xotcl1 or xotcl2, use dispatch ::xotcl::dispatch ${.domain} ::xotcl::classes::xotcl2::${cl}::forward \ ${.name} ${.manager} [list %1 [${.manager} defaultmethods]] %self \ - "%-per-object [info exists .forward-per-object]" \ - %proc + ${.methodname} } } @@ -501,19 +498,17 @@ if {![set .multivalued]} { error "Property $prop of ${.domain}->$obj ist not multivalued" } - puts stderr "adding infoslot: $obj $prop [linsert [$obj info $prop] $pos $value]" + #puts stderr "adding infoslot: $obj $prop [linsert [$obj info $prop] $pos $value]" $obj $prop [linsert [$obj info $prop] $pos $value] } -::xotcl::InfoSlot public method delete {-nocomplain:switch obj prop value} { - puts stderr infoslot-delete-[self args] - set old [$obj info $prop] +::xotcl::InfoSlot protected method delete_value {obj prop old value} { if {[string first * $value] > -1 || [string first \[ $value] > -1} { # string contains meta characters if {${.elementtype} ne "" && ![string match ::* $value]} { # prefix string with ::, since all object names have leading :: set value ::$value } - return [$obj $prop [lsearch -all -not -glob -inline $old $value]] + return [lsearch -all -not -glob -inline $old $value] } elseif {${.elementtype} ne ""} { if {[string first :: $value] == -1} { if {![::xotcl::is $value object]} { @@ -527,12 +522,17 @@ } set p [lsearch -exact $old $value] if {$p > -1} { - $obj $prop [lreplace $old $p $p] + return [lreplace $old $p $p] } else { error "$value is not a $prop of $obj (valid are: $old)" } } +::xotcl::InfoSlot public method delete {-nocomplain:switch obj prop value} { + #puts stderr infoslot-delete-[self args] + $obj $prop [.delete_value $obj $prop [$obj info $prop] $value] +} + ############################################ # InterceptorSlot ############################################ @@ -542,17 +542,19 @@ ::xotcl::alias ::xotcl::InterceptorSlot set ::xotcl::relation ;# for backwards compatibility ::xotcl::alias ::xotcl::InterceptorSlot assign ::xotcl::relation -::xotcl::InterceptorSlot public method get {obj -per-object:switch prop} { - ::xotcl::relation $obj {*}[expr {${per-object} ? "-per-object" : ""}] $prop +::xotcl::InterceptorSlot public method get {obj prop} { + ::xotcl::relation $obj $prop } -::xotcl::InterceptorSlot public method add {obj -per-object:switch prop value {pos 0}} { +::xotcl::InterceptorSlot public method add {obj prop value {pos 0}} { if {![set .multivalued]} { error "Property $prop of ${.domain}->$obj ist not multivalued" } - set perObject [expr {${per-object} ? "-per-object" : ""}] - set oldSetting [::xotcl::relation $obj {*}$perObject $prop] - ::xotcl::relation $obj {*}$perObject $prop [linsert $oldSetting $pos $value] + set oldSetting [::xotcl::relation $obj $prop] + ::xotcl::relation $obj $prop [linsert $oldSetting $pos $value] } +::xotcl::InterceptorSlot public method delete {-nocomplain:switch obj prop value} { + ::xotcl::relation $obj $prop [.delete_value $obj $prop [::xotcl::relation $obj $prop] $value] +} ############################################ # system slots @@ -567,13 +569,27 @@ ::xotcl::alias ${os}::Object::slot::class assign ::xotcl::relation ::xotcl::InterceptorSlot create ${os}::Object::slot::mixin \ - -type relation + -type relation -methodname object-mixin ::xotcl::InterceptorSlot create ${os}::Object::slot::filter \ -elementtype "" -type relation -# ::xotcl::InterceptorSlot create ${os}::Class::slot::object-mixin \ -# -type relation + ::xotcl::InterceptorSlot create ${os}::Class::slot::mixin \ + -type relation -methodname class-mixin + ::xotcl::InterceptorSlot create ${os}::Class::slot::filter \ + -type relation -methodname filter-mixin + + # create tho conveniance slots to allow configuration of + # object-slots for classes via object-mixin + ::xotcl::InterceptorSlot create ${os}::Class::slot::object-mixin \ + -type relation + ::xotcl::InterceptorSlot create ${os}::Class::slot::object-filter \ + -elementtype "" -type relation + + # We could define a mixin on class, the calls always class-mixin. + # therfore, + #::xotcl::InterceptorSlot create ${os}::Class::slot::mixin \ + # -type relation -methodname class-mixin } ::xotcl::register_system_slots ::xotcl2 Index: generic/xotcl.c =================================================================== diff -u -rd56d2a8ee3f246c9891783abb09bd820dbc508e4 -r2454ab78913d0686b2ec5feeb401a051dc6a6164 --- generic/xotcl.c (.../xotcl.c) (revision d56d2a8ee3f246c9891783abb09bd820dbc508e4) +++ generic/xotcl.c (.../xotcl.c) (revision 2454ab78913d0686b2ec5feeb401a051dc6a6164) @@ -11067,7 +11067,14 @@ /*fprintf(stderr, "XOTclRelationCmd %s %d rel=%d val='%s'\n", objectName(object),withPer_object,relationtype,value?ObjStr(value):"NULL");*/ - + /* set withPer_object according to object- or class- */ + switch (relationtype) { + case RelationtypeObject_mixinIdx: withPer_object = 1; break; + case RelationtypeObject_filterIdx: withPer_object = 1; break; + case RelationtypeClass_mixinIdx: withPer_object = 0; break; + case RelationtypeClass_filterIdx: withPer_object = 0; break; + } + if (withPer_object) { switch (relationtype) { case RelationtypeClass_mixinIdx: Index: library/lib/xotcl1.xotcl =================================================================== diff -u -rd56d2a8ee3f246c9891783abb09bd820dbc508e4 -r2454ab78913d0686b2ec5feeb401a051dc6a6164 --- library/lib/xotcl1.xotcl (.../xotcl1.xotcl) (revision d56d2a8ee3f246c9891783abb09bd820dbc508e4) +++ library/lib/xotcl1.xotcl (.../xotcl1.xotcl) (revision 2454ab78913d0686b2ec5feeb401a051dc6a6164) @@ -135,16 +135,15 @@ ::xotcl::alias ${os}::Object::slot::class assign ::xotcl::relation ::xotcl::InterceptorSlot create ${os}::Object::slot::mixin \ - -forward-per-object true \ - -type relation + -type relation -methodname object-mixin ::xotcl::InterceptorSlot create ${os}::Object::slot::filter \ - -forward-per-object true \ - -elementtype "" -type relation + -type relation -methodname object-filter \ + -elementtype "" ::xotcl::InterceptorSlot create ${os}::Class::slot::instmixin \ - -type relation + -type relation -methodname class-mixin ::xotcl::InterceptorSlot create ${os}::Class::slot::instfilter \ - -elementtype "" \ - -type relation + -type relation -methodname class-filter \ + -elementtype "" } ::xotcl::register_system_slots1 ::xotcl Index: tests/interceptor-slot.xotcl =================================================================== diff -u -rd56d2a8ee3f246c9891783abb09bd820dbc508e4 -r2454ab78913d0686b2ec5feeb401a051dc6a6164 --- tests/interceptor-slot.xotcl (.../interceptor-slot.xotcl) (revision d56d2a8ee3f246c9891783abb09bd820dbc508e4) +++ tests/interceptor-slot.xotcl (.../interceptor-slot.xotcl) (revision 2454ab78913d0686b2ec5feeb401a051dc6a6164) @@ -1,7 +1,7 @@ package require XOTcl package require xotcl::test +::xotcl::use xotcl2 - proc ? {cmd expected {msg ""}} { set count 10 if {$msg ne ""} { @@ -13,15 +13,14 @@ $t run } -::xotcl::use xotcl2 puts stderr START Class create M { .method mfoo {} {puts [self proc]} } Class create M2 Class create C -? {C info callable -which mixin} "::xotcl2::Object forward mixin ::xotcl2::Object::slot::mixin {%1 {get assign}} %self {%-per-object 0} %proc" -#? {C info callable -which mixin} "::xotcl2::Object forward mixin ::xotcl2::Object::slot::mixin {%1 {get assign}} %self %proc" + +? {C info callable -which mixin} "::xotcl2::Class forward mixin ::xotcl2::Class::slot::mixin {%1 {get assign}} %self class-mixin" C mixin M ? {C info precedence} "::xotcl2::Class ::xotcl2::Object" ? {C mixin} "::M" @@ -33,12 +32,14 @@ C mixin delete M2 ? {c1 info precedence} "::M ::C ::xotcl2::Object" C mixin delete M + # per-object mixins ? {c1 info precedence} "::C ::xotcl2::Object" c1 mixin add M ? {::xotcl::relation c1 mixin} ::M ? {catch {c1 mixin UNKNOWN}} 1 ? {::xotcl::relation c1 mixin} "::M" + # add again the same mixin c1 mixin add M ? {c1 info precedence} "::M ::C ::xotcl2::Object" @@ -49,9 +50,9 @@ c1 mixin delete M2 ? {c1 info precedence} "::C ::xotcl2::Object" - # -# adding, removing per-object mixins for classes through relation +# adding, removing per-object mixins for classes through relation +# "mixin" and "-per-object" (deprecated) # ::xotcl::relation C -per-object mixin M ? {C info precedence} "::M ::xotcl2::Class ::xotcl2::Object" @@ -60,24 +61,63 @@ ? {C info precedence} "::xotcl2::Class ::xotcl2::Object" # -# adding per-object mixins for classes via "mixin -per-object add M" +# adding, removing per-object mixins for classes through relation +# "object-mixin" # -C mixin -per-object add M +::xotcl::relation C object-mixin M ? {C info precedence} "::M ::xotcl2::Class ::xotcl2::Object" -? {::xotcl::relation C -per-object mixin} ::M -? {catch {C mixin -per-object add UNKNOWN}} 1 -? {::xotcl::relation C -per-object mixin} "::M" -C mixin -per-object "" +? {C object info mixin} "::M" +::xotcl::relation C object-mixin "" ? {C info precedence} "::xotcl2::Class ::xotcl2::Object" # -# adding per-object mixins for classes via "mixin -per-object M" +# adding, removing per-object mixins for classes through slot +# "object-mixin" # -C mixin -per-object M +C object-mixin M ? {C info precedence} "::M ::xotcl2::Class ::xotcl2::Object" +? {C object info mixin} "::M" +C object-mixin "" +? {C info precedence} "::xotcl2::Class ::xotcl2::Object" +# +# add and remove object mixin for classes via modifier "object" and +# "mixin" +# +C object mixin M +? {C info precedence} "::M ::xotcl2::Class ::xotcl2::Object" +? {C object info mixin} "::M" +C object mixin "" +? {C info precedence} "::xotcl2::Class ::xotcl2::Object" + +# +# add and remove object mixin for classes via object mixin add +# +C object mixin add M +? {C info precedence} "::M ::xotcl2::Class ::xotcl2::Object" +? {C object info mixin} "::M" +C object mixin "" +? {C info precedence} "::xotcl2::Class ::xotcl2::Object" + +# +# adding per-object mixins for classes via "object mixin add M" +# +C object mixin add M +? {C info precedence} "::M ::xotcl2::Class ::xotcl2::Object" +? {::xotcl::relation C object-mixin} ::M +? {catch {C object mixin add UNKNOWN}} 1 +? {::xotcl::relation C object-mixin} "::M" +C object mixin "" +? {C info precedence} "::xotcl2::Class ::xotcl2::Object" + +# +# adding per-object mixins for classes via "object mixin M" +# +C object mixin M +? {C info precedence} "::M ::xotcl2::Class ::xotcl2::Object" + # forwarder with 0 arguments + flag -? {C mixin -per-object} "::M" +? {C object-mixin} "::M" puts stderr "==================== XOTcl 1" ::xotcl::use xotcl1