Index: TODO =================================================================== diff -u -r3a246dd237252e81aa7f4a37cba2affb0b9ecf00 -r58c1880b874484f218afa0275b0998e25d4282f0 --- TODO (.../TODO) (revision 3a246dd237252e81aa7f4a37cba2affb0b9ecf00) +++ TODO (.../TODO) (revision 58c1880b874484f218afa0275b0998e25d4282f0) @@ -2848,8 +2848,13 @@ * changed specification of name of method from arg= to method= * this way "type" info in "info parameter syntax" is handled automatically +- nsf.c: + * added a new converter for converting mixins with guards (named mixinspec) + * used mixinspec in nx.tcl and xotcl2.tcl + * extended nx regression test. + + TODO: -- maybe: define a type for converting mixins+guards - add explicit regression tests for disposition + types - check refcounting for dispo+types - maybe: add a dispoition=pipe Index: generic/nsf.c =================================================================== diff -u -r3a246dd237252e81aa7f4a37cba2affb0b9ecf00 -r58c1880b874484f218afa0275b0998e25d4282f0 --- generic/nsf.c (.../nsf.c) (revision 3a246dd237252e81aa7f4a37cba2affb0b9ecf00) +++ generic/nsf.c (.../nsf.c) (revision 58c1880b874484f218afa0275b0998e25d4282f0) @@ -5054,11 +5054,139 @@ +/*********************************************************************** + * Mixin support + ***********************************************************************/ + /* - * Per-Object-Mixins + * Mixinspec type begin */ +typedef struct { + NsfClass *class; + Tcl_Obj *guardObj; +} MixinSpec; +static Tcl_DupInternalRepProc MixinspecDupInteralRep; +static Tcl_FreeInternalRepProc MixinspecFreeInternalRep; +static Tcl_UpdateStringProc MixinspecUpdateString; +static Tcl_SetFromAnyProc MixinspecSetFromAny; + +static Tcl_ObjType mixinspecObjType = { + "nsfMixinspec", /* name */ + MixinspecFreeInternalRep, /* freeIntRepProc */ + MixinspecDupInteralRep, /* dupIntRepProc */ + MixinspecUpdateString, /* updateStringProc */ + MixinspecSetFromAny /* setFromAnyProc */ +}; + +/* + * Dummy placeholder, should never be called. + */ +static void +MixinspecUpdateString(Tcl_Obj *objPtr) { + Tcl_Panic("MixinspecUpdateString %s of type %s should not be called", "updateStringProc", + objPtr->typePtr->name); +} + +/* + * Dummy placeholder, should never be called. + */ +static void +MixinspecDupInteralRep(Tcl_Obj *srcPtr, Tcl_Obj *UNUSED(dupPtr)) { + Tcl_Panic("MixinspecDupInteralRep %s of type %s should not be called", "dupStringProc", + srcPtr->typePtr->name); +} + +/* + * freeIntRepProc + */ +static void +MixinspecFreeInternalRep( + register Tcl_Obj *objPtr) /* Mixinspec structure object with internal + * representation to free. */ +{ + MixinSpec *mixinSpecPtr = (MixinSpec *)objPtr->internalRep.twoPtrValue.ptr1; + + if (mixinSpecPtr != NULL) { + /*fprintf(stderr, "MixinspecFreeInternalRep freeing mixinSpec %p class %p guard %p\n", + mixinSpecPtr, mixinSpecPtr->class, mixinSpecPtr->guardObj);*/ + /* + * Decrement refCounts + */ + NsfObjectRefCountDecr(&(mixinSpecPtr->class)->object); + if (mixinSpecPtr->guardObj) {DECR_REF_COUNT(mixinSpecPtr->guardObj);} + + /* + * ... and free structure + */ + FREE(MixinSpec, mixinSpecPtr); + } +} + +/* + * setFromAnyProc + */ +static int +MixinspecSetFromAny( + Tcl_Interp *interp, /* Used for error reporting if not NULL. */ + register Tcl_Obj *objPtr) /* The object to convert. */ +{ + NsfClass *mixin = NULL; + Tcl_Obj *guardObj = NULL, *nameObj; + int oc; Tcl_Obj **ov; + MixinSpec *mixinSpecPtr; + + if (Tcl_ListObjGetElements(interp, objPtr, &oc, &ov) == TCL_OK) { + if (oc == 3 && !strcmp(ObjStr(ov[1]), NsfGlobalStrings[NSF_GUARD_OPTION])) { + nameObj = ov[0]; + guardObj = ov[2]; + /*fprintf(stderr, "mixinadd name = '%s', guard = '%s'\n", ObjStr(name), ObjStr(guard));*/ + } else if (oc == 1) { + nameObj = ov[0]; + } else { + return TCL_ERROR; + } + } else { + return TCL_ERROR; + } + + /* we have no baseclass, we have to pass NULL as last argument */ + if (GetClassFromObj(interp, nameObj, &mixin, NULL) != TCL_OK) { + return NsfObjErrType(interp, "mixin", nameObj, "a class as mixin", NULL); + } + + /* + * Conversion was ok. + * Allocate structure ... + */ + mixinSpecPtr = NEW(MixinSpec); + /* + * ... and increment refCounts + */ + NsfObjectRefCountIncr((&mixin->object)); + if (guardObj) {INCR_REF_COUNT(guardObj);} + + mixinSpecPtr->class = mixin; + mixinSpecPtr->guardObj = guardObj; + + /*fprintf(stderr, "MixinspecSetFromAny alloc mixinSpec %p class %p guard %p\n", + mixinSpecPtr, mixinSpecPtr->class, mixinSpecPtr->guardObj);*/ + + /* + * Free origninal rep and store structure as internal representation. + */ + TclFreeIntRep(objPtr); + objPtr->internalRep.twoPtrValue.ptr1 = (void *)mixinSpecPtr; + objPtr->internalRep.twoPtrValue.ptr2 = NULL; + objPtr->typePtr = &mixinspecObjType; + + return TCL_OK; +} /* + * Mixinspec type end + */ + +/* * push a mixin stack information on this object */ static int @@ -5104,9 +5232,10 @@ if ((pl->cl->object.flags & NSF_IS_ROOT_CLASS) == 0) { NsfClassOpt *opt = pl->cl->opt; - //fprintf(stderr, "find %p %s in checklist 1 %p\n", pl->cl, ClassName(pl->cl), *checkList); + /* fprintf(stderr, "find %p %s in checklist 1 %p\n", + pl->cl, ClassName(pl->cl), *checkList);*/ if (NsfClassListFind(*checkList, pl->cl)) { - //fprintf(stderr, "+++ never add %s\n", ClassName(pl->cl)); + /*fprintf(stderr, "+++ never add %s\n", ClassName(pl->cl));*/ } else { if (opt && opt->classmixins) { /* @@ -5127,16 +5256,26 @@ } } - //NsfClassListPrint("MixinComputeOrderFullList final", *mixinClasses); - //NsfClassListPrint("MixinComputeOrderFullList check", *checkList); - if (level == 0 && *checkList) { NsfClassListFree(*checkList); *checkList = NULL; } - } +/* + *---------------------------------------------------------------------- + * MixinResetOrder -- + * + * Free the mixin order of the provided object if it exists. + * + * Results: + * void + * + * Side effects: + * Frees potentially the mixinOrder list. + * + *---------------------------------------------------------------------- + */ static void MixinResetOrder(NsfObject *object) { /*fprintf(stderr, "MixinResetOrder for object %s \n", ObjectName(object));*/ @@ -5161,7 +5300,7 @@ */ static void NsfClassListAddPerClassMixins(Tcl_Interp *interp, NsfClass *cl, - NsfClasses **classList, NsfClasses **checkList) { + NsfClasses **classList, NsfClasses **checkList) { NsfClasses *pl; for (pl = ComputeOrder(cl, cl->order, Super); pl; pl = pl->nextPtr) { @@ -5279,8 +5418,21 @@ /*CmdListPrint(interp, "mixin order\n", obj->mixinOrder);*/ } + /* - * add a mixin class to 'mixinList' by appending it + *---------------------------------------------------------------------- + * MixinAdd -- + * + * Add a mixinspec (mixin class with a potential guard) provided as a + * Tcl_Obj* to 'mixinList' by appending it to the provided cmdList. + * + * Results: + * Tcl result code. + * + * Side effects: + * Potentially allocating cmd list elements added to the mixinList + * + *---------------------------------------------------------------------- */ static int MixinAdd(Tcl_Interp *interp, NsfCmdList **mixinList, Tcl_Obj *nameObj, NsfClass *baseClass) { @@ -5289,17 +5441,32 @@ int ocName; Tcl_Obj **ovName; NsfCmdList *new; - 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]; - /*fprintf(stderr, "mixinadd name = '%s', guard = '%s'\n", ObjStr(name), ObjStr(guard));*/ - } /*else return NsfPrintError(interp, "mixin registration '%s' has too many elements", - ObjStr(name));*/ - } + /*fprintf(stderr, "MixinAdd gets obj %p type %p %s\n", nameObj, nameObj->typePtr, + nameObj->typePtr?nameObj->typePtr->name : "NULL");*/ + /* + * When the provided nameObj is of type mixinspecObjType, the nsf specific + * converter was called already and we can simply obtain the mixin class and + * the guard from the internal representation. + */ + if (nameObj->typePtr == &mixinspecObjType) { + MixinSpec *mixinSpecPtr = nameObj->internalRep.twoPtrValue.ptr1; + + guardObj = mixinSpecPtr->guardObj; + mixin = mixinSpecPtr->class; - if (GetClassFromObj(interp, nameObj, &mixin, baseClass) != TCL_OK) { - return NsfObjErrType(interp, "mixin", nameObj, "a class as mixin", NULL); + } else { + 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]; + /*fprintf(stderr, "mixinadd name = '%s', guard = '%s'\n", ObjStr(name), ObjStr(guard));*/ + } /*else return NsfPrintError(interp, "mixin registration '%s' has too many elements", + ObjStr(name));*/ + } + + if (GetClassFromObj(interp, nameObj, &mixin, baseClass) != TCL_OK) { + return NsfObjErrType(interp, "mixin", nameObj, "a class as mixin", NULL); + } } new = CmdListAdd(mixinList, mixin->object.id, NULL, /*noDuplicates*/ 1); @@ -9214,6 +9381,19 @@ } int +Nsf_ConvertToMixinspec(Tcl_Interp *interp, Tcl_Obj *objPtr, Nsf_Param CONST *pPtr, + ClientData *clientData, Tcl_Obj **outObjPtr) { + int result; + *outObjPtr = objPtr; + ///yyyyy + result = Tcl_ConvertToType(interp, objPtr, &mixinspecObjType); + if (result == TCL_OK) { + return result; + } + return NsfObjErrType(interp, NULL, objPtr, "mixinspec", (Nsf_Param *)pPtr); +} + +int Nsf_ConvertToParameter(Tcl_Interp *interp, Tcl_Obj *objPtr, Nsf_Param CONST *pPtr, ClientData *clientData, Tcl_Obj **outObjPtr) { CONST char *value = ObjStr(objPtr); @@ -9491,6 +9671,9 @@ result = ParamOptionSetConverter(interp, paramPtr, "class", Nsf_ConvertToClass); paramPtr->flags |= NSF_ARG_BASECLASS; + } else if (strncmp(option, "mixinspec", 9) == 0) { + result = ParamOptionSetConverter(interp, paramPtr, "mixinspec", Nsf_ConvertToMixinspec); + } else if (strncmp(option, "parameter", 9) == 0) { result = ParamOptionSetConverter(interp, paramPtr, "parameter", Nsf_ConvertToParameter); @@ -15439,8 +15622,8 @@ } assert(object); - assert(object->refCount>0); - assert(object->cmdName->refCount>0); + assert(object->refCount > 0); + assert(object->cmdName->refCount > 0); assert(object->activationCount >= 0); @@ -17587,7 +17770,7 @@ } static Tcl_ObjType paramObjType = { - "nsfParam", /* name */ + "nsfParam", /* name */ ParamFreeInternalRep, /* freeIntRepProc */ ParamDupInteralRep, /* dupIntRepProc */ ParamUpdateString, /* updateStringProc */ Index: generic/nsfDecls.h =================================================================== diff -u -r1b551b5aef49944bda6cb78a8a5c5d09c3e76d5a -r58c1880b874484f218afa0275b0998e25d4282f0 --- generic/nsfDecls.h (.../nsfDecls.h) (revision 1b551b5aef49944bda6cb78a8a5c5d09c3e76d5a) +++ generic/nsfDecls.h (.../nsfDecls.h) (revision 58c1880b874484f218afa0275b0998e25d4282f0) @@ -181,7 +181,7 @@ struct NsfStubHooks *hooks; int (*nsf_Init) (Tcl_Interp *interp); /* 0 */ - void *reserved1; + VOID *reserved1; struct Nsf_Class * (*nsfIsClass) (Tcl_Interp *interp, ClientData cd); /* 2 */ struct Nsf_Object * (*nsfGetObject) (Tcl_Interp *interp, CONST char *name); /* 3 */ struct Nsf_Class * (*nsfGetClass) (Tcl_Interp *interp, CONST char *name); /* 4 */ Index: library/nx/nx.tcl =================================================================== diff -u -r3a246dd237252e81aa7f4a37cba2affb0b9ecf00 -r58c1880b874484f218afa0275b0998e25d4282f0 --- library/nx/nx.tcl (.../nx.tcl) (revision 3a246dd237252e81aa7f4a37cba2affb0b9ecf00) +++ library/nx/nx.tcl (.../nx.tcl) (revision 58c1880b874484f218afa0275b0998e25d4282f0) @@ -1216,12 +1216,12 @@ ${os}::Class::slot::dummy destroy ::nx::RelationSlot create ${os}::Object::slot::mixin \ - -forwardername object-mixin -elementtype class + -forwardername object-mixin -elementtype mixinspec ::nx::RelationSlot create ${os}::Object::slot::filter \ -forwardername object-filter ::nx::RelationSlot create ${os}::Class::slot::mixin \ - -forwardername class-mixin -elementtype class + -forwardername class-mixin -elementtype mixinspec ::nx::RelationSlot create ${os}::Class::slot::filter \ -forwardername class-filter @@ -1230,7 +1230,7 @@ # of per-object mixins and filters for classes. # ::nx::ObjectParameterSlot create ${os}::Class::slot::object-mixin \ - -methodname "::nsf::classes::nx::Object::mixin" -elementtype class + -methodname "::nsf::classes::nx::Object::mixin" -elementtype mixinspec ::nx::ObjectParameterSlot create ${os}::Class::slot::object-filter \ -methodname "::nsf::classes::nx::Object::filter" Index: library/xotcl/library/xotcl2.tcl =================================================================== diff -u -r3a246dd237252e81aa7f4a37cba2affb0b9ecf00 -r58c1880b874484f218afa0275b0998e25d4282f0 --- library/xotcl/library/xotcl2.tcl (.../xotcl2.tcl) (revision 3a246dd237252e81aa7f4a37cba2affb0b9ecf00) +++ library/xotcl/library/xotcl2.tcl (.../xotcl2.tcl) (revision 58c1880b874484f218afa0275b0998e25d4282f0) @@ -403,11 +403,11 @@ ::nx::RelationSlot create ${oSlotContainer}::class -elementtype class -multiplicity 1..1 ::nsf::method::alias ${oSlotContainer}::class assign ::nsf::relation ::nx::RelationSlot create ${oSlotContainer}::mixin -forwardername object-mixin \ - -elementtype mixin -multiplicity 0..n + -elementtype mixinspec -multiplicity 0..n ::nx::RelationSlot create ${oSlotContainer}::filter -forwardername object-filter \ -multiplicity 0..n ::nx::RelationSlot create ${cSlotContainer}::instmixin -forwardername class-mixin \ - -elementtype mixin -multiplicity 0..n + -elementtype mixinspec -multiplicity 0..n ::nx::RelationSlot create ${cSlotContainer}::instfilter -forwardername class-filter \ -multiplicity 0..n } Index: library/xotcl/tests/slottest.xotcl =================================================================== diff -u -r3a246dd237252e81aa7f4a37cba2affb0b9ecf00 -r58c1880b874484f218afa0275b0998e25d4282f0 --- library/xotcl/tests/slottest.xotcl (.../slottest.xotcl) (revision 3a246dd237252e81aa7f4a37cba2affb0b9ecf00) +++ library/xotcl/tests/slottest.xotcl (.../slottest.xotcl) (revision 58c1880b874484f218afa0275b0998e25d4282f0) @@ -112,7 +112,7 @@ ? {o1 class} "::O" o1 class Object ? {o1 class} "::xotcl::Object" -? {Object objectparameter} "-mixin:alias,0..n -filter:alias,0..n -class:class,alias args" +? {Object objectparameter} "-mixin:mixinspec,alias,0..n -filter:alias,0..n -class:class,alias args" ? {o1 class add M} {class: expected a class but got "M ::xotcl::Object"} Index: library/xotcl/tests/testx.xotcl =================================================================== diff -u -r1915597e6ad2a44c3f33b80e7f530920db2a6001 -r58c1880b874484f218afa0275b0998e25d4282f0 --- library/xotcl/tests/testx.xotcl (.../testx.xotcl) (revision 1915597e6ad2a44c3f33b80e7f530920db2a6001) +++ library/xotcl/tests/testx.xotcl (.../testx.xotcl) (revision 58c1880b874484f218afa0275b0998e25d4282f0) @@ -772,8 +772,8 @@ B instproc f1 args {next} B instproc f2 args {next} B b - B instfilter {{f1 -guard {[self] eq "::b"}} {f2 -guard 0} f1} - b filter {{f1 -guard {[self] eq "::b"}} {f2 -guard 0}} + B instfilter {{f1 -guard {[self] eq "::b"}} {f2 -guard 0} f1} + b filter {{f1 -guard {[self] eq "::b"}} {f2 -guard 0}} ::errorCheck [B info instfilter] {f1 f2} "info filter order a" ::errorCheck [B info instfilter -guards] {f1 {f2 -guard 0}} "info filter order b" Index: tests/info-method.test =================================================================== diff -u -r3a246dd237252e81aa7f4a37cba2affb0b9ecf00 -r58c1880b874484f218afa0275b0998e25d4282f0 --- tests/info-method.test (.../info-method.test) (revision 3a246dd237252e81aa7f4a37cba2affb0b9ecf00) +++ tests/info-method.test (.../info-method.test) (revision 58c1880b874484f218afa0275b0998e25d4282f0) @@ -493,10 +493,10 @@ :method "sub foo" args {;} } - ? {C info parameter syntax} "?-a value? ?-b value? ?-volatile? ?-noinit? ?-mixin class ...? ?-class class? ?-filter value ...? ?__initcmd?" + ? {C info parameter syntax} "?-a value? ?-b value? ?-volatile? ?-noinit? ?-mixin mixinspec ...? ?-class class? ?-filter value ...? ?__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:class,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:mixinspec,alias,1..n -class:class,alias,method=::nsf::methods::object::class -filter: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/parameters.test =================================================================== diff -u -r3a246dd237252e81aa7f4a37cba2affb0b9ecf00 -r58c1880b874484f218afa0275b0998e25d4282f0 --- tests/parameters.test (.../parameters.test) (revision 3a246dd237252e81aa7f4a37cba2affb0b9ecf00) +++ tests/parameters.test (.../parameters.test) (revision 58c1880b874484f218afa0275b0998e25d4282f0) @@ -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:class,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:mixinspec,alias,1..n -class:class,alias,method=::nsf::methods::object::class -filter: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:class,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:mixinspec,alias,1..n -class:class,alias,method=::nsf::methods::object::class -filter: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:class,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:mixinspec,alias,1..n -class:class,alias,method=::nsf::methods::object::class -filter: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:class,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:mixinspec,alias,1..n -class:class,alias,method=::nsf::methods::object::class -filter: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:class,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:mixinspec,alias,1..n -class:class,alias,method=::nsf::methods::object::class -filter: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:class,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:mixinspec,alias,1..n -class:class,alias,method=::nsf::methods::object::class -filter: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:class,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:mixinspec,alias,1..n -class:class,alias,method=::nsf::methods::object::class -filter:alias,1..n __initcmd:initcmd,optional" } ####################################################### @@ -688,10 +688,33 @@ Class create D -superclass C -attributes d Class create M + Class create M2 D create d1 -d 1 C create c1 -mixin M + C create c2 -mixin {{M -guard true}} + C create c3 -mixin {M ::M2} + C create c4 -mixin {{M -guard 1} M2} + C create c5 -mixin {M {M2 -guard 2}} Object create o - + + ? {c1 info mixin classes} ::M + ? {c1 info mixin guard ::M} "" + + ? {c2 info mixin classes} ::M + ? {c2 info mixin guard ::M} "true" + + ? {c3 info mixin classes} {::M ::M2} + ? {c3 info mixin guard M} "" + ? {c3 info mixin guard M2} "" + + ? {c4 info mixin classes} {::M ::M2} + ? {c4 info mixin guard M} "1" + ? {c4 info mixin guard M2} "" + + ? {c5 info mixin classes} {::M ::M2} + ? {c5 info mixin guard M} "" + ? {c5 info mixin guard M2} "2" + D public method foo-base {x:baseclass} {return $x} D public method foo-class {x:class} {return $x} D public method foo-object {x:object} {return $x} @@ -1596,7 +1619,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:class,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:mixinspec,alias,1..n -class:class,alias,method=::nsf::methods::object::class -filter:alias,1..n __initcmd:initcmd,optional" # # invalidate object parameter and expect that the per-class mixin @@ -1610,7 +1633,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:class,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:mixinspec,alias,1..n -class:class,alias,method=::nsf::methods::object::class -filter:alias,1..n __initcmd:initcmd,optional" # should not require b1 ? {C create c2} ::c2