Index: TODO =================================================================== diff -u -r0807007e0812c229eb9d6bce7d9480a26982085c -ra588ad9e5d66f12c4b2a5baf9153b652932a5912 --- TODO (.../TODO) (revision 0807007e0812c229eb9d6bce7d9480a26982085c) +++ TODO (.../TODO) (revision a588ad9e5d66f12c4b2a5baf9153b652932a5912) @@ -1098,9 +1098,18 @@ - used for the time being in nx only for Class.info, but would apply as well for methods defined on both Object and Class. +- use now class-only for all methods methods of meta-classes. + Methods of meta-classes are inteded to be applied on classes, + one should not change this via per-object mixins. +- respect class-only in "info callable methods|method" +- extended regression test +- provided relation name "object-filter" to slot filter. + + TODO: -- complete class-only, or remove it +- interfaces in documentation for slots (see for more details + ::nx::Class#superclass in nx.tcl). - nameing * self/current: - overthink general replacement of "self" by "current". Index: generic/xotcl.c =================================================================== diff -u -r84af56591a1cc4ac7a3779ec44f6978203ef016a -ra588ad9e5d66f12c4b2a5baf9153b652932a5912 --- generic/xotcl.c (.../xotcl.c) (revision 84af56591a1cc4ac7a3779ec44f6978203ef016a) +++ generic/xotcl.c (.../xotcl.c) (revision a588ad9e5d66f12c4b2a5baf9153b652932a5912) @@ -1048,6 +1048,10 @@ for (mixinList = object->mixinOrder; mixinList; mixinList = mixinList->nextPtr) { XOTclClass *mixin = XOTclGetClassFromCmdPtr(mixinList->cmdPtr); if (mixin && (*pcl = SearchCMethod(mixin, name, &cmd))) { + if (Tcl_Command_flags(cmd) & XOTCL_CMD_CLASS_ONLY_METHOD && !XOTclObjectIsClass(object)) { + cmd = NULL; + continue; + } break; } } @@ -4030,7 +4034,7 @@ continue; } - if (Tcl_Command_flags(cmd) & XOTCL_CMD_CLASS_SPECIFIC_METHOD) { + if (Tcl_Command_flags(cmd) & XOTCL_CMD_CLASS_ONLY_METHOD) { /*fprintf(stderr, "we found class specific method %s on class %s object %s, isclass %d\n", methodName, className(cls), objectName(object), XOTclObjectIsClass(object));*/ if (!XOTclObjectIsClass(object)) { @@ -10383,6 +10387,10 @@ key = Tcl_GetHashKey(table, hPtr); cmd = (Tcl_Command)Tcl_GetHashValue(hPtr); + if (Tcl_Command_flags(cmd) & XOTCL_CMD_CLASS_ONLY_METHOD && !XOTclObjectIsClass(object)) { + return TCL_OK; + } + if (ProtectionMatches(interp, withCallprotection, cmd) && MethodTypeMatches(interp, methodType, cmd, object, key, withPer_object)) { if (dups) { @@ -10404,6 +10412,7 @@ key = Tcl_GetHashKey(table, hPtr); cmd = (Tcl_Command)Tcl_GetHashValue(hPtr); + if (Tcl_Command_flags(cmd) & XOTCL_CMD_CLASS_ONLY_METHOD && !XOTclObjectIsClass(object)) continue; if (pattern && !Tcl_StringMatch(key, pattern)) continue; if (!ProtectionMatches(interp, withCallprotection, cmd) || !MethodTypeMatches(interp, methodType, cmd, object, key, withPer_object) @@ -10545,6 +10554,8 @@ for (ml = object->mixinOrder; ml; ml = ml->nextPtr) { int guardOk = TCL_OK; mixin = XOTclGetClassFromCmdPtr(ml->cmdPtr); + assert(mixin); + if (inContext) { if (!RUNTIME_STATE(interp)->guardCount) { guardOk = GuardCall(object, 0, 0, interp, ml->clientData, NULL); @@ -11498,7 +11509,7 @@ XOTCL_CMD_PROTECTED_METHOD : methodproperty == MethodpropertyRedefine_protectedIdx ? XOTCL_CMD_REDEFINE_PROTECTED_METHOD - :XOTCL_CMD_CLASS_SPECIFIC_METHOD; + :XOTCL_CMD_CLASS_ONLY_METHOD; if (valueObj) { int bool, result; Index: generic/xotclInt.h =================================================================== diff -u -r84af56591a1cc4ac7a3779ec44f6978203ef016a -ra588ad9e5d66f12c4b2a5baf9153b652932a5912 --- generic/xotclInt.h (.../xotclInt.h) (revision 84af56591a1cc4ac7a3779ec44f6978203ef016a) +++ generic/xotclInt.h (.../xotclInt.h) (revision a588ad9e5d66f12c4b2a5baf9153b652932a5912) @@ -329,7 +329,7 @@ #define XOTCL_CMD_REDEFINE_PROTECTED_METHOD 0x00020000 /* XOTCL_CMD_NONLEAF_METHOD is used to flag, if a Method implemented via cmd calls "next" */ #define XOTCL_CMD_NONLEAF_METHOD 0x00040000 -#define XOTCL_CMD_CLASS_SPECIFIC_METHOD 0x00080000 +#define XOTCL_CMD_CLASS_ONLY_METHOD 0x00080000 /* * object flags ... */ Index: library/nx/nx.tcl =================================================================== diff -u -r84af56591a1cc4ac7a3779ec44f6978203ef016a -ra588ad9e5d66f12c4b2a5baf9153b652932a5912 --- library/nx/nx.tcl (.../nx.tcl) (revision 84af56591a1cc4ac7a3779ec44f6978203ef016a) +++ library/nx/nx.tcl (.../nx.tcl) (revision a588ad9e5d66f12c4b2a5baf9153b652932a5912) @@ -410,30 +410,7 @@ # register method "info" on Object and Class Object forward info -onerror ::nsf::infoError ::nx::objectInfo %1 {%@2 %self} Class forward info -onerror ::nsf::infoError ::nx::classInfo %1 {%@2 %self} - ::nsf::methodproperty nx::Class info class-only true - #Class method info args { - # # In case Class.info is applied on an object (via mixins), do "next" - # if {![::nsf::objectproperty [::nsf::current object] class]} next else { - # if {[catch {::nx::classInfo [lindex $args 0] [::nsf::current object] {*}[lrange $args 1 end]} result]} { -# ::nsf::infoError $result -# } -# return $result -# } -# } - Class method filterguard {filter guard} { - # In case Class.filterguard is applied on an object (via mixins), do "next" - if {![::nsf::objectproperty [::nsf::current object] class]} next else { - ::nsf::dispatch [::nsf::current object] ::nsf::cmd::Class::filterguard $filter $guard - } - } - Class method mixinguard {mixin guard} { - # In case Class.mixinguard is applied on an object (via mixins), do "next" - if {![::nsf::objectproperty [::nsf::current object] class]} next else { - ::nsf::dispatch [::nsf::current object] ::nsf::cmd::Class::mixinguard $mixin $guard - } - } - # # definition of "abstract method foo ...." # @@ -940,9 +917,19 @@ # @param ::nx::Class#superclass # - # Specifies superclasses for a given class. As a setter, - # {{{superclass}}} changes the list of superclasses. When used as - # a getter, the method returns the current superclasses. + # Specifies superclasses for a given class. As a setter *** + # generell: setter kann hier mit der methode namens "setter" + # verwechselt werden; wir sollten hier die paramter syntax + # anfuehren, die allerdings in zwei varianten kommt: + #{{{ + # obj superclass ?value? + # obj superclass add|assign|delete|get value + #}}} + # Das gilt allgemein, nicht nur für die relation-slots, sondern + # für alle incremental slots. + # **** {{{superclass}}} changes the list + # of superclasses. When used as a getter, the method returns the + # current superclasses. # # @return :list If called as a getter (without arguments), # {{{superclass}}} returns the current superclasses of the object @@ -966,7 +953,8 @@ # can retrieve the list of mixins active for the given object. # # @return :list If called as a getter (without arguments), {{{mixin}}} returns the list of current mixin classes registered with the object - ::nx::RelationSlot create ${os}::Object::slot::mixin -methodname object-mixin + ::nx::RelationSlot create ${os}::Object::slot::mixin \ + -methodname object-mixin # @param ::nx::Object#filter # @@ -978,7 +966,8 @@ # @return :list If called as a getter (without arguments), # {{{filter}}} returns the list of current filters # registered with the object - ::nx::RelationSlot create ${os}::Object::slot::filter -elementtype "" + ::nx::RelationSlot create ${os}::Object::slot::filter -elementtype "" \ + -methodname object-filter # @param ::nx::Class#mixin # @@ -1174,10 +1163,7 @@ # Define method "attribute" for convenience ############################################ Class method attribute {spec {-slotclass ::nx::Attribute} {initblock ""}} { - # In case Class.attribute is applied on an object (via mixins), do "next" - if {![::nsf::objectproperty [::nsf::current object] class]} next else { - $slotclass createFromParameterSyntax [::nsf::current object] -initblock $initblock {*}$spec - } + $slotclass createFromParameterSyntax [::nsf::current object] -initblock $initblock {*}$spec } Object method attribute {spec {-slotclass ::nx::Attribute} {initblock ""}} { @@ -1453,7 +1439,19 @@ } } + ####################################################### + # Methods of metaclasses are methods intended for + # classes. Make sure, these methods are only applied + # on classes. + ####################################################### + + #puts stderr Class-methods=[lsort [Class info methods]] + foreach m [Class info methods] { + ::nsf::methodproperty Class $m class-only true + } + + ####################################################### # some utilities ####################################################### Index: tests/info-method.tcl =================================================================== diff -u -r39a142bba1228a228ab72054aa7a7bd64333db3c -ra588ad9e5d66f12c4b2a5baf9153b652932a5912 --- tests/info-method.tcl (.../info-method.tcl) (revision 39a142bba1228a228ab72054aa7a7bd64333db3c) +++ tests/info-method.tcl (.../info-method.tcl) (revision a588ad9e5d66f12c4b2a5baf9153b652932a5912) @@ -89,6 +89,9 @@ ? {lsort [o info methods]} "foo is x" o method f args ::nx::next + ? {o info callable methods superclass} "" + ? {o info callable methods filter} "filter" + ? {o info callable method filter} "::nsf::classes::nx::Object::filter" ? {o filter f} "" ? {o filterguard f { 1 }} "" o filter "" Index: tests/parameters.tcl =================================================================== diff -u -re548a952433b4d26794f535995c9ed1ababe8807 -ra588ad9e5d66f12c4b2a5baf9153b652932a5912 --- tests/parameters.tcl (.../parameters.tcl) (revision e548a952433b4d26794f535995c9ed1ababe8807) +++ tests/parameters.tcl (.../parameters.tcl) (revision a588ad9e5d66f12c4b2a5baf9153b652932a5912) @@ -171,7 +171,7 @@ ? {c1 eval {:objectparameter}} \ - "-a:slot=::C::slot::a -b:boolean,slot=::C::slot::b {-c:slot=::C::slot::c 1} -mixin:relation,arg=object-mixin,slot=::nx::Object::slot::mixin -filter:relation,slot=::nx::Object::slot::filter -class:relation,slot=::nx::Object::slot::class -noinit:method,optional,noarg -volatile:method,optional,noarg __initcmd:initcmd,optional" + "-a:slot=::C::slot::a -b:boolean,slot=::C::slot::b {-c:slot=::C::slot::c 1} -mixin:relation,arg=object-mixin,slot=::nx::Object::slot::mixin -filter:relation,arg=object-filter,slot=::nx::Object::slot::filter -class:relation,slot=::nx::Object::slot::class -noinit:method,optional,noarg -volatile:method,optional,noarg __initcmd:initcmd,optional" } ####################################################### @@ -184,13 +184,13 @@ c1 class Object ? {c1 eval :objectparameter} \ - "-mixin:relation,arg=object-mixin,slot=::nx::Object::slot::mixin -filter:relation,slot=::nx::Object::slot::filter -class:relation,slot=::nx::Object::slot::class -noinit:method,optional,noarg -volatile:method,optional,noarg __initcmd:initcmd,optional" + "-mixin:relation,arg=object-mixin,slot=::nx::Object::slot::mixin -filter:relation,arg=object-filter,slot=::nx::Object::slot::filter -class:relation,slot=::nx::Object::slot::class -noinit:method,optional,noarg -volatile:method,optional,noarg __initcmd:initcmd,optional" Class create D -superclass C -parameter {d:required} D create d1 -d 100 ? {d1 eval :objectparameter} \ - "-d:required,slot=::D::slot::d -a:slot=::C::slot::a -b:boolean,slot=::C::slot::b {-c:slot=::C::slot::c 1} -mixin:relation,arg=object-mixin,slot=::nx::Object::slot::mixin -filter:relation,slot=::nx::Object::slot::filter -class:relation,slot=::nx::Object::slot::class -noinit:method,optional,noarg -volatile:method,optional,noarg __initcmd:initcmd,optional" + "-d:required,slot=::D::slot::d -a:slot=::C::slot::a -b:boolean,slot=::C::slot::b {-c:slot=::C::slot::c 1} -mixin:relation,arg=object-mixin,slot=::nx::Object::slot::mixin -filter:relation,arg=object-filter,slot=::nx::Object::slot::filter -class:relation,slot=::nx::Object::slot::class -noinit:method,optional,noarg -volatile:method,optional,noarg __initcmd:initcmd,optional" } ####################################################### @@ -206,28 +206,27 @@ Class create M2 -parameter {b2} D mixin M ? {d1 eval :objectparameter} \ - "-b:slot=::M::slot::b -m1:slot=::M::slot::m1 -m2:slot=::M::slot::m2 -d:required,slot=::D::slot::d -a:slot=::C::slot::a {-c:slot=::C::slot::c 1} -mixin:relation,arg=object-mixin,slot=::nx::Object::slot::mixin -filter:relation,slot=::nx::Object::slot::filter -class:relation,slot=::nx::Object::slot::class -noinit:method,optional,noarg -volatile:method,optional,noarg __initcmd:initcmd,optional" \ + "-b:slot=::M::slot::b -m1:slot=::M::slot::m1 -m2:slot=::M::slot::m2 -d:required,slot=::D::slot::d -a:slot=::C::slot::a {-c:slot=::C::slot::c 1} -mixin:relation,arg=object-mixin,slot=::nx::Object::slot::mixin -filter:relation,arg=object-filter,slot=::nx::Object::slot::filter -class:relation,slot=::nx::Object::slot::class -noinit:method,optional,noarg -volatile:method,optional,noarg __initcmd:initcmd,optional" \ "mixin added" M mixin M2 ? {d1 eval :objectparameter} \ - "-b2:slot=::M2::slot::b2 -b:slot=::M::slot::b -m1:slot=::M::slot::m1 -m2:slot=::M::slot::m2 -d:required,slot=::D::slot::d -a:slot=::C::slot::a {-c:slot=::C::slot::c 1} -mixin:relation,arg=object-mixin,slot=::nx::Object::slot::mixin -filter:relation,slot=::nx::Object::slot::filter -class:relation,slot=::nx::Object::slot::class -noinit:method,optional,noarg -volatile:method,optional,noarg __initcmd:initcmd,optional" \ + "-b2:slot=::M2::slot::b2 -b:slot=::M::slot::b -m1:slot=::M::slot::m1 -m2:slot=::M::slot::m2 -d:required,slot=::D::slot::d -a:slot=::C::slot::a {-c:slot=::C::slot::c 1} -mixin:relation,arg=object-mixin,slot=::nx::Object::slot::mixin -filter:relation,arg=object-filter,slot=::nx::Object::slot::filter -class:relation,slot=::nx::Object::slot::class -noinit:method,optional,noarg -volatile:method,optional,noarg __initcmd:initcmd,optional" \ "transitive mixin added" D mixin "" #we should have again the old interface ? {d1 eval :objectparameter} \ - "-d:required,slot=::D::slot::d -a:slot=::C::slot::a -b:boolean,slot=::C::slot::b {-c:slot=::C::slot::c 1} -mixin:relation,arg=object-mixin,slot=::nx::Object::slot::mixin -filter:relation,slot=::nx::Object::slot::filter -class:relation,slot=::nx::Object::slot::class -noinit:method,optional,noarg -volatile:method,optional,noarg __initcmd:initcmd,optional" + "-d:required,slot=::D::slot::d -a:slot=::C::slot::a -b:boolean,slot=::C::slot::b {-c:slot=::C::slot::c 1} -mixin:relation,arg=object-mixin,slot=::nx::Object::slot::mixin -filter:relation,arg=object-filter,slot=::nx::Object::slot::filter -class:relation,slot=::nx::Object::slot::class -noinit:method,optional,noarg -volatile:method,optional,noarg __initcmd:initcmd,optional" C mixin M ? {d1 eval :objectparameter} \ - "-b2:slot=::M2::slot::b2 -b:slot=::M::slot::b -m1:slot=::M::slot::m1 -m2:slot=::M::slot::m2 -d:required,slot=::D::slot::d -a:slot=::C::slot::a {-c:slot=::C::slot::c 1} -mixin:relation,arg=object-mixin,slot=::nx::Object::slot::mixin -filter:relation,slot=::nx::Object::slot::filter -class:relation,slot=::nx::Object::slot::class -noinit:method,optional,noarg -volatile:method,optional,noarg __initcmd:initcmd,optional" \ + "-b2:slot=::M2::slot::b2 -b:slot=::M::slot::b -m1:slot=::M::slot::m1 -m2:slot=::M::slot::m2 -d:required,slot=::D::slot::d -a:slot=::C::slot::a {-c:slot=::C::slot::c 1} -mixin:relation,arg=object-mixin,slot=::nx::Object::slot::mixin -filter:relation,arg=object-filter,slot=::nx::Object::slot::filter -class:relation,slot=::nx::Object::slot::class -noinit:method,optional,noarg -volatile:method,optional,noarg __initcmd:initcmd,optional" \ "mixin added" C mixin "" #we should have again the old interface - ? {d1 eval :objectparameter} \ - "-d:required,slot=::D::slot::d -a:slot=::C::slot::a -b:boolean,slot=::C::slot::b {-c:slot=::C::slot::c 1} -mixin:relation,arg=object-mixin,slot=::nx::Object::slot::mixin -filter:relation,slot=::nx::Object::slot::filter -class:relation,slot=::nx::Object::slot::class -noinit:method,optional,noarg -volatile:method,optional,noarg __initcmd:initcmd,optional" + "-d:required,slot=::D::slot::d -a:slot=::C::slot::a -b:boolean,slot=::C::slot::b {-c:slot=::C::slot::c 1} -mixin:relation,arg=object-mixin,slot=::nx::Object::slot::mixin -filter:relation,arg=object-filter,slot=::nx::Object::slot::filter -class:relation,slot=::nx::Object::slot::class -noinit:method,optional,noarg -volatile:method,optional,noarg __initcmd:initcmd,optional" } #######################################################