Index: TODO =================================================================== diff -u -rbd4aa15282abe386464ef276b78f2708f249f333 -r67591822465e64d9051583c9aa71f8d3a4ef5c96 --- TODO (.../TODO) (revision bd4aa15282abe386464ef276b78f2708f249f333) +++ TODO (.../TODO) (revision 67591822465e64d9051583c9aa71f8d3a4ef5c96) @@ -2880,9 +2880,14 @@ - new function NsfCallUnkownHandler() - moved mixin reg type converter to a new file (nsfObj.c) +- added NsfFilterregObjType, to provide a converter for filter + registration similar to mixin registrations +- replaced dummy dupIntRepProc and updateStringProc in nsfObj.c by NULL + TODO: +- fix memory leak in info-method test - in method-require.test # TODO: make me more pretty set ::nsf::unknown(nx) {::nx::Class __unknown} Index: generic/nsf.c =================================================================== diff -u -rbd4aa15282abe386464ef276b78f2708f249f333 -r67591822465e64d9051583c9aa71f8d3a4ef5c96 --- generic/nsf.c (.../nsf.c) (revision bd4aa15282abe386464ef276b78f2708f249f333) +++ generic/nsf.c (.../nsf.c) (revision 67591822465e64d9051583c9aa71f8d3a4ef5c96) @@ -6700,28 +6700,36 @@ * append a filter command to the 'filterList' of an obj/class */ static int -FilterAdd(Tcl_Interp *interp, NsfCmdList **filterList, Tcl_Obj *nameObj, +FilterAdd(Tcl_Interp *interp, NsfCmdList **filterList, Tcl_Obj *filterregObj, NsfObject *startingObject, NsfClass *startingClass) { - Tcl_Command cmd; - int ocName; Tcl_Obj **ovName; + Tcl_Obj *filterObj = NULL; Tcl_Obj *guardObj = NULL; + Tcl_Command cmd; NsfCmdList *new; NsfClass *cl; - if (Tcl_ListObjGetElements(interp, nameObj, &ocName, &ovName) == TCL_OK && ocName > 1) { - if (ocName == 3 && !strcmp(ObjStr(ovName[1]), NsfGlobalStrings[NSF_GUARD_OPTION])) { - nameObj = ovName[0]; - guardObj = ovName[2]; + /* + * When the provided nameObj is of type NsfFilterregObjType, the nsf specific + * converter was called already; otherwise call the converter here. + */ + if (filterregObj->typePtr != &NsfFilterregObjType) { + /*fprintf(stderr, "FilterAdd: convert %s in FilterAdd\n", ObjStr(filterregObj));*/ + if (Tcl_ConvertToType(interp, filterregObj, &NsfFilterregObjType) != TCL_OK) { + return TCL_ERROR; } + } else { + /*fprintf(stderr, "FilterAdd: %s already converted\n", ObjStr(filterregObj));*/ } - if (!(cmd = FilterSearch(ObjStr(nameObj), startingObject, startingClass, &cl))) { + NsfFilterregGet(filterregObj, &filterObj, &guardObj); + + if (!(cmd = FilterSearch(ObjStr(filterObj), startingObject, startingClass, &cl))) { if (startingObject) { return NsfPrintError(interp, "object filter: can't find filterproc '%s' on %s ", - ObjStr(nameObj), ObjectName(startingObject)); + ObjStr(filterObj), ObjectName(startingObject)); } else { return NsfPrintError(interp, "class filter: can't find filterproc '%s' on %s ", - ObjStr(nameObj), ClassName(startingClass)); + ObjStr(filterObj), ClassName(startingClass)); } } @@ -9512,6 +9520,37 @@ /* *---------------------------------------------------------------------- + * Nsf_ConvertToFilterreg -- + * + * Nsf_TypeConverter setting the client data (passed to C functions) to the + * Tcl_Obj. This nsf type converter checks the passed value via the + * NsfFilterregObjType tcl_obj converter, which provides an internal + * representation for the client function. + * + * Results: + * Tcl result code, *clientData and **outObjPtr + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +Nsf_ConvertToFilterreg(Tcl_Interp *interp, Tcl_Obj *objPtr, Nsf_Param CONST *pPtr, + ClientData *clientData, Tcl_Obj **outObjPtr) { + int result; + *outObjPtr = objPtr; + result = Tcl_ConvertToType(interp, objPtr, &NsfFilterregObjType); + if (result == TCL_OK) { + *clientData = objPtr; + return result; + } + return NsfObjErrType(interp, NULL, objPtr, "filterreg", (Nsf_Param *)pPtr); +} + +/* + *---------------------------------------------------------------------- * Nsf_ConvertToMixinreg -- * * Nsf_TypeConverter setting the client data (passed to C functions) to the @@ -9857,6 +9896,9 @@ } else if (strncmp(option, "mixinreg", 8) == 0) { result = ParamOptionSetConverter(interp, paramPtr, "mixinreg", Nsf_ConvertToMixinreg); + } else if (strncmp(option, "filterreg", 9) == 0) { + result = ParamOptionSetConverter(interp, paramPtr, "filterreg", Nsf_ConvertToFilterreg); + } else if (strncmp(option, "parameter", 9) == 0) { result = ParamOptionSetConverter(interp, paramPtr, "parameter", Nsf_ConvertToParameter); Index: generic/nsfInt.h =================================================================== diff -u -rbd4aa15282abe386464ef276b78f2708f249f333 -r67591822465e64d9051583c9aa71f8d3a4ef5c96 --- generic/nsfInt.h (.../nsfInt.h) (revision bd4aa15282abe386464ef276b78f2708f249f333) +++ generic/nsfInt.h (.../nsfInt.h) (revision 67591822465e64d9051583c9aa71f8d3a4ef5c96) @@ -627,6 +627,9 @@ extern Tcl_ObjType NsfMixinregObjType; int NsfMixinregGet(Tcl_Obj *obj, NsfClass **clPtr, Tcl_Obj **guardObj); +extern Tcl_ObjType NsfFilterregObjType; +int NsfFilterregGet(Tcl_Obj *obj, Tcl_Obj **filterObj, Tcl_Obj **guardObj); + /* Next Scripting ShadowTclCommands */ typedef struct NsfShadowTclCommandInfo { TclObjCmdProcType proc; Index: generic/nsfObj.c =================================================================== diff -u -rbd4aa15282abe386464ef276b78f2708f249f333 -r67591822465e64d9051583c9aa71f8d3a4ef5c96 --- generic/nsfObj.c (.../nsfObj.c) (revision bd4aa15282abe386464ef276b78f2708f249f333) +++ generic/nsfObj.c (.../nsfObj.c) (revision 67591822465e64d9051583c9aa71f8d3a4ef5c96) @@ -14,51 +14,35 @@ #include "nsfInt.h" /* - * Mixinreg type + *---------------------------------------------------------------------- * - * The mixin reg type is an Tcl_Obj type carrying a class and a guard - * object. The string representation might have the form "/cls/" or "/cls/ - * -guard /expr/". When no guard expression is provided (first form), the - * guard entry is NULL. + * Mixinreg Tcl_Obj type -- + * + * The mixin registration type is an Tcl_Obj type carrying a + * class and a guard object. The string representation might have + * the form "/cls/" or "/cls/ -guard /expr/". When no guard + * expression is provided (first form), the guard entry is NULL. + * + *---------------------------------------------------------------------- */ typedef struct { NsfClass *mixin; Tcl_Obj *guardObj; } MixinReg; -static Tcl_DupInternalRepProc MixinregDupInteralRep; static Tcl_FreeInternalRepProc MixinregFreeInternalRep; -static Tcl_UpdateStringProc MixinregUpdateString; static Tcl_SetFromAnyProc MixinregSetFromAny; Tcl_ObjType NsfMixinregObjType = { "nsfMixinreg", /* name */ MixinregFreeInternalRep, /* freeIntRepProc */ - MixinregDupInteralRep, /* dupIntRepProc */ - MixinregUpdateString, /* updateStringProc */ + NULL, /* dupIntRepProc */ + NULL, /* updateStringProc */ MixinregSetFromAny /* setFromAnyProc */ }; /* - * Dummy placeholder, should never be called. - */ -static void -MixinregUpdateString(Tcl_Obj *objPtr) { - Tcl_Panic("MixinregUpdateString %s of type %s should not be called", "updateStringProc", - objPtr->typePtr->name); -} - -/* - * Dummy placeholder, should never be called. - */ -static void -MixinregDupInteralRep(Tcl_Obj *srcPtr, Tcl_Obj *UNUSED(dupPtr)) { - Tcl_Panic("MixinregDupInteralRep %s of type %s should not be called", "dupStringProc", - srcPtr->typePtr->name); -} - -/* * freeIntRepProc */ static void @@ -94,8 +78,8 @@ { NsfClass *mixin = NULL; Tcl_Obj *guardObj = NULL, *nameObj; - int oc; Tcl_Obj **ov; MixinReg *mixinRegPtr; + int oc; Tcl_Obj **ov; if (Tcl_ListObjGetElements(interp, objPtr, &oc, &ov) == TCL_OK) { if (oc == 3 && !strcmp(ObjStr(ov[1]), NsfGlobalStrings[NSF_GUARD_OPTION])) { @@ -174,6 +158,149 @@ return TCL_ERROR; } + /* - * Mixinreg type end + *---------------------------------------------------------------------- + * + * Filterreg Tcl_Obj type -- + * + * The filter registration type is an Tcl_Obj type carrying a the + * name of a filter and a guard object. The string representation + * might have the form "/filter/" or "/filter/ -guard + * /expr/". When no guard expression is provided (first form), + * the guard entry is NULL. The primary purpose of this converter + * is to provide symmetry to mixinregs and to provide meaningful + * type names for introspection. + * + *---------------------------------------------------------------------- */ + +typedef struct { + Tcl_Obj *filterObj; + Tcl_Obj *guardObj; +} Filterreg; + +static Tcl_FreeInternalRepProc FilterregFreeInternalRep; +static Tcl_SetFromAnyProc FilterregSetFromAny; + +Tcl_ObjType NsfFilterregObjType = { + "nsfFilterreg", /* name */ + FilterregFreeInternalRep, /* freeIntRepProc */ + NULL, /* dupIntRepProc */ + NULL, /* updateStringProc */ + FilterregSetFromAny /* setFromAnyProc */ +}; + + +/* + * freeIntRepProc + */ +static void +FilterregFreeInternalRep( + register Tcl_Obj *objPtr) /* Filterreg structure object with internal + * representation to free. */ +{ + Filterreg *filterregPtr = (Filterreg *)objPtr->internalRep.twoPtrValue.ptr1; + + if (filterregPtr != NULL) { + /*fprintf(stderr, "FilterregFreeInternalRep freeing filterreg %p class %p guard %p\n", + filterregPtr, filterregPtr->class, filterregPtr->guardObj);*/ + /* + * Decrement refCounts + */ + DECR_REF_COUNT(filterregPtr->filterObj); + if (filterregPtr->guardObj) {DECR_REF_COUNT(filterregPtr->guardObj);} + + /* + * ... and free structure + */ + FREE(Filterreg, filterregPtr); + } +} + +/* + * setFromAnyProc + */ +static int +FilterregSetFromAny( + Tcl_Interp *interp, /* Used for error reporting if not NULL. */ + register Tcl_Obj *objPtr) /* The object to convert. */ +{ + Tcl_Obj *guardObj = NULL, *filterObj; + Filterreg *filterregPtr; + int oc; Tcl_Obj **ov; + + if (Tcl_ListObjGetElements(interp, objPtr, &oc, &ov) == TCL_OK) { + if (oc == 3 && !strcmp(ObjStr(ov[1]), NsfGlobalStrings[NSF_GUARD_OPTION])) { + filterObj = ov[0]; + guardObj = ov[2]; + /*fprintf(stderr, "mixinadd name = '%s', guard = '%s'\n", ObjStr(name), ObjStr(guard));*/ + } else if (oc == 1) { + filterObj = ov[0]; + } else { + return TCL_ERROR; + } + } else { + return TCL_ERROR; + } + + /* + * Conversion was ok. + * Allocate structure ... + */ + filterregPtr = NEW(Filterreg); + + /* + * ... and increment refCounts + */ + INCR_REF_COUNT(filterObj); + if (guardObj) {INCR_REF_COUNT(guardObj);} + + filterregPtr->filterObj = filterObj; + filterregPtr->guardObj = guardObj; + + /*fprintf(stderr, "FilterregSetFromAny alloc filterreg %p class %p guard %p\n", + filterregPtr, filterregPtr->mixin, filterregPtr->guardObj);*/ + + /* + * Free the old interal representation and store own structure as internal + * representation. + */ + TclFreeIntRep(objPtr); + objPtr->internalRep.twoPtrValue.ptr1 = (void *)filterregPtr; + objPtr->internalRep.twoPtrValue.ptr2 = NULL; + objPtr->typePtr = &NsfFilterregObjType; + + return TCL_OK; +} +/* + *---------------------------------------------------------------------- + * + * NsfFilterregGet -- + * + * Return the internal representation of a filterreg obj type to + * keep internal rep local to this file. + * + * Results: + * Tcl result code, arg two and three on success. + * + * Side effects: + * None + * + *---------------------------------------------------------------------- + */ + +int +NsfFilterregGet(Tcl_Obj *obj, Tcl_Obj **filterObj, Tcl_Obj **guardObj) { + if (obj->typePtr == &NsfFilterregObjType) { + Filterreg *filterregPtr = obj->internalRep.twoPtrValue.ptr1; + *filterObj = filterregPtr->filterObj; + *guardObj = filterregPtr->guardObj; + return TCL_OK; + } + + return TCL_ERROR; +} +/* + * Filterreg type end + */ Index: library/nx/nx.tcl =================================================================== diff -u -r756a5ed4e51921ada898fdf69cc7bd2c5c616828 -r67591822465e64d9051583c9aa71f8d3a4ef5c96 --- library/nx/nx.tcl (.../nx.tcl) (revision 756a5ed4e51921ada898fdf69cc7bd2c5c616828) +++ library/nx/nx.tcl (.../nx.tcl) (revision 67591822465e64d9051583c9aa71f8d3a4ef5c96) @@ -1020,7 +1020,7 @@ # Obtain a list of parameter options from slot object # set options [list] - if {[info exists :elementtype] && ${:elementtype} ni {{} mixin}} { + if {[info exists :elementtype] && ${:elementtype} ne {}} { lappend options ${:elementtype} #puts stderr "+++ [self] added elementtype ${:elementtype}" } @@ -1138,7 +1138,7 @@ # # Value contains globbing meta characters. # - if {[info exists :elementtype] && ${:elementtype} ne "" + if {[info exists :elementtype] && ${:elementtype} eq "mixinreg" && ![string match ::* $value]} { # # Prefix glob pattern with ::, since all object names have @@ -1147,10 +1147,10 @@ set value ::$value } return [lsearch -all -not -glob -inline $old $value] - } elseif {[info exists :elementtype] && ${:elementtype} ne ""} { + } elseif {[info exists :elementtype] && ${:elementtype} eq "mixinreg"} { # - # Value contains no globbing meta characters, but elementtype is - # given. + # Value contains no globbing meta characters, and elementtype could be + # fully qualified # if {[string first :: $value] == -1} { # @@ -1216,12 +1216,12 @@ ::nx::RelationSlot create ${os}::Object::slot::mixin \ -forwardername object-mixin -elementtype mixinreg ::nx::RelationSlot create ${os}::Object::slot::filter \ - -forwardername object-filter + -forwardername object-filter -elementtype filterreg ::nx::RelationSlot create ${os}::Class::slot::mixin \ -forwardername class-mixin -elementtype mixinreg ::nx::RelationSlot create ${os}::Class::slot::filter \ - -forwardername class-filter + -forwardername class-filter -elementtype filterreg # # Create two convenience object parameters to allow configuration @@ -1230,7 +1230,7 @@ ::nx::ObjectParameterSlot create ${os}::Class::slot::object-mixin \ -methodname "::nsf::classes::nx::Object::mixin" -elementtype mixinreg ::nx::ObjectParameterSlot create ${os}::Class::slot::object-filter \ - -methodname "::nsf::classes::nx::Object::filter" + -methodname "::nsf::classes::nx::Object::filter" -elementtype filterreg # # Create object parameter slots for "attributes", "noninit" and "volatile" Index: tests/info-method.test =================================================================== diff -u -r03990ee9d7185ded72b0fa05e81f848e866451c2 -r67591822465e64d9051583c9aa71f8d3a4ef5c96 --- tests/info-method.test (.../info-method.test) (revision 03990ee9d7185ded72b0fa05e81f848e866451c2) +++ tests/info-method.test (.../info-method.test) (revision 67591822465e64d9051583c9aa71f8d3a4ef5c96) @@ -493,10 +493,10 @@ :method "sub foo" args {;} } - ? {C info parameter syntax} "?-a value? ?-b value? ?-volatile? ?-noinit? ?-mixin mixinreg ...? ?-class class? ?-filter value ...? ?__initcmd?" + ? {C info parameter syntax} "?-a value? ?-b value? ?-volatile? ?-noinit? ?-mixin mixinreg ...? ?-class class? ?-filter filterreg ...? ?__initcmd?" ? {C info parameter syntax a} "?-a value?" - ? {C info parameter spec} "-a {-b 1} -volatile:alias,noarg -noinit:alias,method=::nsf::methods::object::noinit,noarg -mixin:mixinreg,alias,1..n -class:class,alias,method=::nsf::methods::object::class -filter:alias,1..n __initcmd:initcmd,optional" + ? {C info parameter spec} "-a {-b 1} -volatile:alias,noarg -noinit:alias,method=::nsf::methods::object::noinit,noarg -mixin:mixinreg,alias,1..n -class:class,alias,method=::nsf::methods::object::class -filter:filterreg,alias,1..n __initcmd:initcmd,optional" ? {C info parameter list} "-a -b -volatile -noinit -mixin -class -filter __initcmd" ? {C info parameter name} "a b volatile noinit mixin class filter __initcmd" Index: tests/interceptor-slot.test =================================================================== diff -u -rb3018d3be0f1524a3f1709edc0e2ddb5d8bc4c0b -r67591822465e64d9051583c9aa71f8d3a4ef5c96 --- tests/interceptor-slot.test (.../interceptor-slot.test) (revision b3018d3be0f1524a3f1709edc0e2ddb5d8bc4c0b) +++ tests/interceptor-slot.test (.../interceptor-slot.test) (revision 67591822465e64d9051583c9aa71f8d3a4ef5c96) @@ -9,109 +9,121 @@ } Class create M2 Class create C - -? {C info lookup method mixin} "::nsf::classes::nx::Class::mixin" -C mixin M -? {C info precedence} "::nx::Class ::nx::Object" -? {C mixin} "::M" -? {C info mixin classes} "::M" C create c1 -? {c1 info precedence} "::M ::C ::nx::Object" -C mixin add M2 -? {c1 info precedence} "::M2 ::M ::C ::nx::Object" -C mixin delete M2 -? {c1 info precedence} "::M ::C ::nx::Object" -C mixin delete M -? {C info mixin classes} "" -C mixin ::M -C mixin {} -? {C info mixin classes} "" # +# test mixin method +# +Test case mixin-method { + ? {C info lookup method mixin} "::nsf::classes::nx::Class::mixin" + ? {C mixin M} ::M + ? {C info precedence} "::nx::Class ::nx::Object" + ? {C mixin} "::M" + ? {C info mixin classes} "::M" + ? {c1 info precedence} "::M ::C ::nx::Object" + ? {C mixin add M2} "::M2 ::M" + ? {c1 info precedence} "::M2 ::M ::C ::nx::Object" + ? {C mixin delete M2} "::M" + ? {c1 info precedence} "::M ::C ::nx::Object" + ? {C mixin delete M} "" + ? {C info mixin classes} "" + ? {C mixin ::M} "::M" + ? {C mixin {}} "" + ? {C info mixin classes} "" +} + +# # test nsf::mixin interface # -::nsf::mixin C ::M -? {C info mixin classes} "::M" -::nsf::mixin C ::M2 -? {C info mixin classes} "::M2 ::M" -::nsf::mixin C "" -? {C info mixin classes} "" +Test case nsf-mixin { + ? {::nsf::mixin C ::M} "::M" + ? {C info mixin classes} "::M" + ? {::nsf::mixin C ::M2} "::M2 ::M" + ? {C info mixin classes} "::M2 ::M" + ? {::nsf::mixin C ""} "" + ? {C info mixin classes} "" +} +# # per-object mixins -? {c1 info precedence} "::C ::nx::Object" -c1 mixin add M -? {::nsf::relation c1 object-mixin} ::M -? {catch {c1 mixin UNKNOWN}} 1 -? {::nsf::relation c1 object-mixin} "::M" +# +Test case per-object-mixin { + ? {c1 info precedence} "::C ::nx::Object" + ? {c1 mixin add M} ::M + ? {::nsf::relation c1 object-mixin} ::M + ? {catch {c1 mixin UNKNOWN}} 1 + ? {::nsf::relation c1 object-mixin} "::M" -# add again the same mixin -c1 mixin add M -? {c1 info precedence} "::M ::C ::nx::Object" -c1 mixin add M2 -? {c1 info precedence} "::M2 ::M ::C ::nx::Object" -c1 mixin delete M -? {c1 info precedence} "::M2 ::C ::nx::Object" -c1 mixin delete M2 -? {c1 info precedence} "::C ::nx::Object" + # add again the same mixin + ? {c1 mixin add M} {::M} + ? {c1 info precedence} "::M ::C ::nx::Object" + ? {c1 mixin add M2} "::M2 ::M" + ? {c1 info precedence} "::M2 ::M ::C ::nx::Object" + ? {c1 mixin delete M} "::M2" + ? {c1 info precedence} "::M2 ::C ::nx::Object" + ? {c1 mixin delete M2} "" + ? {c1 info precedence} "::C ::nx::Object" +} # # adding, removing per-object mixins for classes through relation # "object-mixin" # -::nsf::relation C object-mixin M -? {C info precedence} "::M ::nx::Class ::nx::Object" -? {C class info mixin classes} "::M" -::nsf::relation C object-mixin "" -? {C info precedence} "::nx::Class ::nx::Object" +Test case object-mixin-relation { + ? {::nsf::relation C object-mixin M} ::M + ? {C info precedence} "::M ::nx::Class ::nx::Object" + ? {C class info mixin classes} "::M" + ? {::nsf::relation C object-mixin ""} "" + ? {C info precedence} "::nx::Class ::nx::Object" +} # # adding, removing per-object mixins for classes through slot # "object-mixin" # -# C object-mixin M -# ? {C info precedence} "::M ::nx::Class ::nx::Object" -# ? {C class info mixin classes} "::M" -# C object-mixin "" -# ? {C info precedence} "::nx::Class ::nx::Object" + # C object-mixin M + # ? {C info precedence} "::M ::nx::Class ::nx::Object" + # ? {C class info mixin classes} "::M" + # C object-mixin "" + # ? {C info precedence} "::nx::Class ::nx::Object" # -# add and remove class mixin for classes via modifier "object" and +# add and remove class mixin for classes via modifier "class" and # "mixin" # -C class mixin M -? {C info precedence} "::M ::nx::Class ::nx::Object" -? {C class info mixin classes} "::M" -C class mixin "" -? {C info precedence} "::nx::Class ::nx::Object" +Test case class+mixin { + ? {C class mixin M} ::M + ? {C info precedence} "::M ::nx::Class ::nx::Object" + ? {C class info mixin classes} "::M" + ? {C class mixin ""} "" + ? {C info precedence} "::nx::Class ::nx::Object" +} # # add and remove class mixin for classes via class mixin add # -C class mixin add M -? {C info precedence} "::M ::nx::Class ::nx::Object" -? {C class info mixin classes} "::M" -C class mixin "" -? {C info precedence} "::nx::Class ::nx::Object" +Test case class+mixin-add { + ? {C class mixin add M} ::M + ? {C info precedence} "::M ::nx::Class ::nx::Object" + ? {C class info mixin classes} "::M" + ? {C class mixin ""} "" + ? {C info precedence} "::nx::Class ::nx::Object" + + ? {C class mixin add M} ::M + ? {C info precedence} "::M ::nx::Class ::nx::Object" + ? {::nsf::relation C object-mixin} ::M + ? {catch {C class mixin add UNKNOWN}} 1 + ? {::nsf::relation C object-mixin} "::M" + ? {C class mixin ""} "" + ? {C info precedence} "::nx::Class ::nx::Object" -# -# adding per-object mixins for classes via "object mixin add M" -# -C class mixin add M -? {C info precedence} "::M ::nx::Class ::nx::Object" -? {::nsf::relation C object-mixin} ::M -? {catch {C class mixin add UNKNOWN}} 1 -? {::nsf::relation C object-mixin} "::M" -C class mixin "" -? {C info precedence} "::nx::Class ::nx::Object" + ? {C class mixin M} ::M + ? {C info precedence} "::M ::nx::Class ::nx::Object" -# -# adding per-object mixins for classes via "object mixin M" -# -C class mixin M -? {C info precedence} "::M ::nx::Class ::nx::Object" + # forwarder with 0 arguments + flag + ? {C class mixin} "::M" +} -# forwarder with 0 arguments + flag -? {C class mixin} "::M" Test case mixin-add { Index: tests/parameters.test =================================================================== diff -u -r03990ee9d7185ded72b0fa05e81f848e866451c2 -r67591822465e64d9051583c9aa71f8d3a4ef5c96 --- tests/parameters.test (.../parameters.test) (revision 03990ee9d7185ded72b0fa05e81f848e866451c2) +++ tests/parameters.test (.../parameters.test) (revision 67591822465e64d9051583c9aa71f8d3a4ef5c96) @@ -249,7 +249,7 @@ C create c1 ? {C eval :objectparameter} \ - "-a -b:boolean {-c 1} -volatile:alias,noarg -noinit:alias,method=::nsf::methods::object::noinit,noarg -mixin:mixinreg,alias,1..n -class:class,alias,method=::nsf::methods::object::class -filter:alias,1..n __initcmd:initcmd,optional" + "-a -b:boolean {-c 1} -volatile:alias,noarg -noinit:alias,method=::nsf::methods::object::noinit,noarg -mixin:mixinreg,alias,1..n -class:class,alias,method=::nsf::methods::object::class -filter:filterreg,alias,1..n __initcmd:initcmd,optional" ? {c1 eval :objectparameter} \ "::c1: unable to dispatch method 'objectparameter'" @@ -276,7 +276,7 @@ "::D::slot::d ::C::slot::a ::C::slot::b ::C::slot::c" ? {D eval :objectparameter} \ - "-d:required -a -b:boolean {-c 1} -volatile:alias,noarg -noinit:alias,method=::nsf::methods::object::noinit,noarg -mixin:mixinreg,alias,1..n -class:class,alias,method=::nsf::methods::object::class -filter:alias,1..n __initcmd:initcmd,optional" + "-d:required -a -b:boolean {-c 1} -volatile:alias,noarg -noinit:alias,method=::nsf::methods::object::noinit,noarg -mixin:mixinreg,alias,1..n -class:class,alias,method=::nsf::methods::object::class -filter:filterreg,alias,1..n __initcmd:initcmd,optional" } ####################################################### @@ -293,29 +293,29 @@ D mixin M ? {D eval :objectparameter} \ - "-b -m1 -m2 -d:required -a {-c 1} -volatile:alias,noarg -noinit:alias,method=::nsf::methods::object::noinit,noarg -mixin:mixinreg,alias,1..n -class:class,alias,method=::nsf::methods::object::class -filter:alias,1..n __initcmd:initcmd,optional" \ + "-b -m1 -m2 -d:required -a {-c 1} -volatile:alias,noarg -noinit:alias,method=::nsf::methods::object::noinit,noarg -mixin:mixinreg,alias,1..n -class:class,alias,method=::nsf::methods::object::class -filter:filterreg,alias,1..n __initcmd:initcmd,optional" \ "mixin added" M mixin M2 ? {D eval :objectparameter} \ - "-b2 -b -m1 -m2 -d:required -a {-c 1} -volatile:alias,noarg -noinit:alias,method=::nsf::methods::object::noinit,noarg -mixin:mixinreg,alias,1..n -class:class,alias,method=::nsf::methods::object::class -filter:alias,1..n __initcmd:initcmd,optional" \ + "-b2 -b -m1 -m2 -d:required -a {-c 1} -volatile:alias,noarg -noinit:alias,method=::nsf::methods::object::noinit,noarg -mixin:mixinreg,alias,1..n -class:class,alias,method=::nsf::methods::object::class -filter:filterreg,alias,1..n __initcmd:initcmd,optional" \ "transitive mixin added" D mixin "" #we should have again the old interface ? {D eval :objectparameter} \ - "-d:required -a -b:boolean {-c 1} -volatile:alias,noarg -noinit:alias,method=::nsf::methods::object::noinit,noarg -mixin:mixinreg,alias,1..n -class:class,alias,method=::nsf::methods::object::class -filter:alias,1..n __initcmd:initcmd,optional" + "-d:required -a -b:boolean {-c 1} -volatile:alias,noarg -noinit:alias,method=::nsf::methods::object::noinit,noarg -mixin:mixinreg,alias,1..n -class:class,alias,method=::nsf::methods::object::class -filter:filterreg,alias,1..n __initcmd:initcmd,optional" C mixin M ? {D eval :objectparameter} \ - "-b2 -b -m1 -m2 -d:required -a {-c 1} -volatile:alias,noarg -noinit:alias,method=::nsf::methods::object::noinit,noarg -mixin:mixinreg,alias,1..n -class:class,alias,method=::nsf::methods::object::class -filter:alias,1..n __initcmd:initcmd,optional" \ + "-b2 -b -m1 -m2 -d:required -a {-c 1} -volatile:alias,noarg -noinit:alias,method=::nsf::methods::object::noinit,noarg -mixin:mixinreg,alias,1..n -class:class,alias,method=::nsf::methods::object::class -filter:filterreg,alias,1..n __initcmd:initcmd,optional" \ "mixin added" C mixin "" #we should have again the old interface ? {D eval :objectparameter} \ - "-d:required -a -b:boolean {-c 1} -volatile:alias,noarg -noinit:alias,method=::nsf::methods::object::noinit,noarg -mixin:mixinreg,alias,1..n -class:class,alias,method=::nsf::methods::object::class -filter:alias,1..n __initcmd:initcmd,optional" + "-d:required -a -b:boolean {-c 1} -volatile:alias,noarg -noinit:alias,method=::nsf::methods::object::noinit,noarg -mixin:mixinreg,alias,1..n -class:class,alias,method=::nsf::methods::object::class -filter:filterreg,alias,1..n __initcmd:initcmd,optional" } ####################################################### @@ -1617,7 +1617,7 @@ ? {C info slots -closure} "::C::slot::a1 ::nx::Object::slot::volatile ::nx::Object::slot::noinit ::nx::Object::slot::mixin ::nx::Object::slot::__initcmd ::nx::Object::slot::class ::nx::Object::slot::filter" - ? {C eval :objectparameter} "-a1 -volatile:alias,noarg -noinit:alias,method=::nsf::methods::object::noinit,noarg -mixin:mixinreg,alias,1..n -class:class,alias,method=::nsf::methods::object::class -filter:alias,1..n __initcmd:initcmd,optional" + ? {C eval :objectparameter} "-a1 -volatile:alias,noarg -noinit:alias,method=::nsf::methods::object::noinit,noarg -mixin:mixinreg,alias,1..n -class:class,alias,method=::nsf::methods::object::class -filter:filterreg,alias,1..n __initcmd:initcmd,optional" # # invalidate object parameter and expect that the per-class mixin @@ -1631,7 +1631,7 @@ ? {C info slots -closure} "::C::slot::a1 ::nx::Object::slot::volatile ::nx::Object::slot::noinit ::nx::Object::slot::mixin ::nx::Object::slot::__initcmd ::nx::Object::slot::class ::nx::Object::slot::filter" - ? {C eval :objectparameter} "-a1 -volatile:alias,noarg -noinit:alias,method=::nsf::methods::object::noinit,noarg -mixin:mixinreg,alias,1..n -class:class,alias,method=::nsf::methods::object::class -filter:alias,1..n __initcmd:initcmd,optional" + ? {C eval :objectparameter} "-a1 -volatile:alias,noarg -noinit:alias,method=::nsf::methods::object::noinit,noarg -mixin:mixinreg,alias,1..n -class:class,alias,method=::nsf::methods::object::class -filter:filterreg,alias,1..n __initcmd:initcmd,optional" # should not require b1 ? {C create c2} ::c2