Index: TODO =================================================================== diff -u -rbd69e3a318c530a893bcf86b2d6d41f7064d3c07 -r2ec475906a0ef436eebe94921b1a887c1a11d7cb --- TODO (.../TODO) (revision bd69e3a318c530a893bcf86b2d6d41f7064d3c07) +++ TODO (.../TODO) (revision 2ec475906a0ef436eebe94921b1a887c1a11d7cb) @@ -2765,6 +2765,16 @@ - nsf.c: fix and document GetMatchObject() - extend regression test +- nx.tcl: + * splitted method "delete" into a "delete method" and + "delete attribute" + * remove flag "-per-object" in method "delete" + * delete per-object methods of classes with + "/cls/ class delete method name" and + "/cls/ class delete attribute name" + * extended regression test + + TODO: - missing in c-based "info slots": @@ -2778,12 +2788,8 @@ - if the check on eg. info-heritage-circular in test/info.method.tcl fails, we get an exception. -- what to do with "info heritage" - a) keep the new version (slightly incompatible in XOTcl) - b) provide a scripted compatible version in "info superclass" - (might be confusing, when using XOTcl and nx in the same script) - c) provide an additional flag to obtain mixins (not nice, since base - version is useless) +- what to do with "info heritage": + document changed results in cases of per-class mixins in migratin guide - ::nsf::method::exists /handle/ -> check, if handle is a handle of a registered method (to be be used in serializer alias-dependency) Index: library/nx/nx.tcl =================================================================== diff -u -r4e0a14b67ffc6ac5087eacf53207f877c33d599f -r2ec475906a0ef436eebe94921b1a887c1a11d7cb --- library/nx/nx.tcl (.../nx.tcl) (revision 4e0a14b67ffc6ac5087eacf53207f877c33d599f) +++ library/nx/nx.tcl (.../nx.tcl) (revision 2ec475906a0ef436eebe94921b1a887c1a11d7cb) @@ -237,9 +237,16 @@ } } } + if {$what in [list "filterguard" "mixinguard"]} { return [::nsf::dispatch [::nsf::self] ::nsf::methods::object::$what {*}$args] } + + if {$what eq "delete"} { + return [::nsf::dispatch [::nsf::self] \ + ::nx::Object::slot::__delete::[lindex $args 0] {*}[lrange $args 1 end]] + } + error "'$what' not allowed to be modified by 'class'" } # define unknown handler for class @@ -368,43 +375,7 @@ return $r } - # - # Deletion method for attributes and plain methods - # - Object public method delete {methodName} { - # call explicitly the per-object variant of "info slots" - set slot [::nsf::my "::nx::Object::slot::__info::slots" $methodName] - # - # If we have a slot (e.g. an attribute) we simply delete it. The - # destructor of the slot removes the accessor. - # - if {$slot ne ""} { - $slot destroy - } else { - array set "" [:__resolve_method_path -per-object $methodName] - ::nsf::method::delete $(object) -per-object $(methodName) - } - } - Class public method delete {-per-object:switch methodName} { - if {${per-object}} { - # call explicitly the per-object variant of "delete" - return [::nsf::my ::nsf::classes::nx::Object::delete $methodName] - } else { - set slot [:info slots $methodName] - # - # If we have a slot (e.g. an attribute) we simply delete it. The - # destructor of the slot removes the accessor. - # - if {$slot ne ""} { - $slot destroy - } else { - array set "" [:__resolve_method_path $methodName] - ::nsf::method::delete $(object) $(methodName) - } - } - } - # Add method "require" # Object method require {what args} { @@ -424,9 +395,13 @@ } } + + ###################################################################### + # Basic definitions for slots + ###################################################################### # - # isSlotContainer tests, whether the provided object is a slot - # container based on the methodproperty slotcontainer, used + # The function isSlotContainer tests, whether the provided object is + # a slot container based on the methodproperty slotcontainer, used # internally by nsf. # proc ::nx::isSlotContainer {object} { @@ -438,6 +413,12 @@ return 0 } + # + # The function slotObj ensures that the slot container for the provided + # baseObject exists. It returns either the name of the slotContainer + # (when no slot name was provided) or the fully qualified name of + # the slot object. + # proc ::nx::slotObj {baseObject {name ""}} { # Create slot container object if needed set slotContainer ${baseObject}::slot @@ -453,8 +434,10 @@ } return ${slotContainer}::$name } - - # allocate system slot parents + + # + # Allocate system slot containers + # ::nx::slotObj ::nx::Class ::nx::slotObj ::nx::Object @@ -502,8 +485,37 @@ # end of EnsembleObject } - + ###################################################################### + # Now we are able to create ensemble methods + ###################################################################### + + # + # Deletion method for attributes and plain methods + # + + Object public method "delete attribute" {name} { + # call explicitly the per-object variant of "info slots" + set slot [::nsf::my "::nx::Object::slot::__info::slots" $name] + if {$slot eq ""} {error "[self]: cannot delete object specific attribute '$name'"} + $slot destroy + } + Object public method "delete method" {name} { + array set "" [:__resolve_method_path -per-object $name] + ::nsf::method::delete $(object) -per-object $(methodName) + } + + Class public method "delete attribute" {name} { + set slot [:info slots $name] + if {$slot eq ""} {error "[self]: cannot delete attribute '$name'"} + $slot destroy + } + Class public method "delete method" {name} { + array set "" [:__resolve_method_path $name] + ::nsf::method::delete $(object) $(methodName) + } + + ######################## # Info definition ######################## Index: tests/methods.test =================================================================== diff -u -r4e0a14b67ffc6ac5087eacf53207f877c33d599f -r2ec475906a0ef436eebe94921b1a887c1a11d7cb --- tests/methods.test (.../methods.test) (revision 4e0a14b67ffc6ac5087eacf53207f877c33d599f) +++ tests/methods.test (.../methods.test) (revision 2ec475906a0ef436eebe94921b1a887c1a11d7cb) @@ -525,35 +525,50 @@ } # -# Test deletion of object-specific methods/attributes via delete -# method +# Test deletion of object-specific methods/attributes via "delete +# method" and "delete attribute" +# # a) test attributes # b) test simple methods # c) test ensemble methods # nx::Test case delete-per-object { Object create o1 { :attribute a1 + :attribute a2 :public method foo {} {return [namespace current]-[namespace which info]} :public method "info foo" {} {return [namespace current]-[namespace which info]} :public method "info bar foo" {} {return [namespace current]-[namespace which info]} } - ? {o1 info methods -path} "{info foo} {info bar foo} foo a1" + ? {o1 info methods -path} "{info foo} {info bar foo} foo a1 a2" ? {o1 info children} "::o1::info ::o1::slot" - ? {o1 delete bar} "::o1: cannot delete object specific method 'bar'" + ? {o1 delete method bar} "::o1: cannot delete object specific method 'bar'" + # For a1, we have a method and an attribute. We can delete the + # method without the slot. + ? {o1 delete method a1} "" + # After the deletion of the accessor, the slot exists still + ? {o1::slot info children} "::o1::slot::a1 ::o1::slot::a2" + # If we perform now a "delete attribute", the slot will be removed. + ? {o1 delete attribute a1} "" + ? {o1::slot info children} "::o1::slot::a2" - ? {o1 delete a1} "" + # try to delete the attribute again: + ? {o1 delete attribute a1} "::o1: cannot delete object specific attribute 'a1'" + + + ? {o1 info methods -path} "{info foo} {info bar foo} foo a2" + ? {o1 delete attribute a2} "" ? {o1 info methods -path} "{info foo} {info bar foo} foo" - ? {o1 delete foo} "" + ? {o1 delete method foo} "" ? {o1 info methods -path} "{info foo} {info bar foo}" - ? {o1 delete "info foo"} "" + ? {o1 delete method "info foo"} "" ? {o1 info methods -path} "{info bar foo}" - ? {o1 delete "info bar foo"} "" + ? {o1 delete method "info bar foo"} "" ? {o1 info methods -path} "" } @@ -575,18 +590,19 @@ ? {C class info methods -path} "{info foo} {info bar foo} foo a1" ? {C info children} "::C::info ::C::slot" - ? {C delete -per-object bar} "::C: cannot delete object specific method 'bar'" + ? {C class delete method bar} "::C: cannot delete object specific method 'bar'" - ? {C delete -per-object a1} "" + ? {C class delete attribute a1} "" ? {C class info methods -path} "{info foo} {info bar foo} foo" + ? {C class delete attribute a1} "::C: cannot delete object specific attribute 'a1'" - ? {C delete -per-object foo} "" + ? {C class delete method foo} "" ? {C class info methods -path} "{info foo} {info bar foo}" - ? {C delete -per-object "info foo"} "" + ? {C class delete method "info foo"} "" ? {C class info methods -path} "{info bar foo}" - ? {C delete -per-object "info bar foo"} "" + ? {C class delete method "info bar foo"} "" ? {C class info methods -path} "" } @@ -609,18 +625,20 @@ ? {C info methods -path} "{info foo} {info bar foo} foo a1" ? {C info children} "::C::slot" - ? {C delete bar} "::C: cannot delete method 'bar'" + ? {C delete method bar} "::C: cannot delete method 'bar'" - ? {C delete a1} "" + ? {C delete attribute a1} "" ? {C info methods -path} "{info foo} {info bar foo} foo" - ? {C delete foo} "" + ? {C delete attribute a1} "::C: cannot delete attribute 'a1'" + + ? {C delete method foo} "" ? {C info methods -path} "{info foo} {info bar foo}" - ? {C delete "info foo"} "" + ? {C delete method "info foo"} "" ? {C info methods -path} "{info bar foo}" - ? {C delete "info bar foo"} "" + ? {C delete method "info bar foo"} "" ? {C info methods -path} "" }