Index: TODO =================================================================== diff -u -r102a1a9f4f678f98e7bcf7648ad1714147a29a47 -r60dc0dde60e22fb2b74bc6c3b15e0148af7d0fa5 --- TODO (.../TODO) (revision 102a1a9f4f678f98e7bcf7648ad1714147a29a47) +++ TODO (.../TODO) (revision 60dc0dde60e22fb2b74bc6c3b15e0148af7d0fa5) @@ -4220,13 +4220,18 @@ - rename invalidateobjobjectparameter -> parameter:invalidate::objectcache - bring cmds into alphabetical order +- NsfObjInfoObjectparameterMethod(): return not only the first matching + parameter, but the list of all matching ones. The last optional + argument was renamed from "name" to "pattern" accordingly + ======================================================================== TODO: - invalidation of per-object parameter cache for mixins and deletion/adding of per-object slots - regression tests for "/obj/ info lookup parameter ...." - handling of "required" in reconfigure (see parameter-object-mixin-dependency in parameters.test) +- handling of recreate (see regression test for class-level properties) - check noconfig - "/obj/ configure" returns values which can't be read via "/obj/ cget" (but altered properly via "configure"). @@ -4241,7 +4246,6 @@ should be ? {o __alloc x} {method alloc not dispatched on valid class} -- recreate for slots - document "private property" - document new setable object properties perobjectdispatch and keepcallerself Index: generic/nsf.c =================================================================== diff -u -r102a1a9f4f678f98e7bcf7648ad1714147a29a47 -r60dc0dde60e22fb2b74bc6c3b15e0148af7d0fa5 --- generic/nsf.c (.../nsf.c) (revision 102a1a9f4f678f98e7bcf7648ad1714147a29a47) +++ generic/nsf.c (.../nsf.c) (revision 60dc0dde60e22fb2b74bc6c3b15e0148af7d0fa5) @@ -21027,9 +21027,14 @@ CmdListFree(&objopt->objMixins, GuardDel); } + /* + * Invalidate per-object infos + */ + NsfParameterInvalidateObjectCacheCmd(interp, object); object->flags &= ~NSF_MIXIN_ORDER_VALID; /* - * Since mixin procs may be used as filters -> we have to invalidate. + * Since mixin procs may be used as filters -> we have to invalidate + * filters as well. */ object->flags &= ~NSF_FILTER_ORDER_VALID; @@ -23867,16 +23872,16 @@ /* objectInfoMethod objectparameter NsfObjInfoObjectparameterMethod { - {-argName "infoobjectparametersubcmd" -type "definition|list|name|syntax" -required 1} - {-argName "name" -required 0} + {-argName "infoobjectparametersubcmd" -type "definitions|list|names|syntax" -required 1} + {-argName "pattern" -required 0} } */ static int -NsfObjInfoObjectparameterMethod(Tcl_Interp *interp, NsfObject *object, int subcmd, CONST char *name) { +NsfObjInfoObjectparameterMethod(Tcl_Interp *interp, NsfObject *object, int subcmd, CONST char *pattern) { NsfParsedParam parsedParam; Tcl_Obj *listObj = NULL; Nsf_Param CONST *paramsPtr; - Nsf_Param paramList[2]; + Nsf_Param *paramList = NULL; int result; result = GetObjectParameterDefinition(interp, NsfGlobalObjs[NSF_EMPTY], @@ -23890,46 +23895,62 @@ /* * If a single parameter name is given, we construct a filtered parameter - * list on the fly and provide it to the output functions. Note, that the - * first matching parameter is queried. + * list on the fly and provide it to the output functions. */ - if (name) { + if (pattern) { Nsf_Param CONST *pPtr; - - for (pPtr = paramsPtr; pPtr->name; pPtr++) { - if (Tcl_StringMatch( ObjStr(pPtr->nameObj), name)) { - paramsPtr = (Nsf_Param CONST *)¶mList; - paramList[0] = *pPtr; - paramList[1].name = NULL; - break; + int maxParams, nrMatchingParams; + + /* + * Count the parameters + */ + for (pPtr = paramsPtr, maxParams = 0; pPtr->name; pPtr++, maxParams++); + /* + * Allocate the number of potentional matches + */ + paramList = ParamsNew(maxParams); + + for (pPtr = paramsPtr, nrMatchingParams = 0; pPtr->name; pPtr++) { + if (Tcl_StringMatch( ObjStr(pPtr->nameObj), pattern)) { + paramList[nrMatchingParams] = *pPtr; + nrMatchingParams++; } } - if (paramsPtr == parsedParam.paramDefs->paramsPtr) { + + if (nrMatchingParams == 0) { /* - * The named parameter was NOT found, so return "". + * The named parameter were NOT found, so return "". */ Tcl_SetObjResult(interp, NsfGlobalObjs[NSF_EMPTY]); + FREE(Nsf_Param*, paramList); return TCL_OK; } + /* iterate over the computed selection */ + paramsPtr = paramList; } switch (subcmd) { - case InfoobjectparametersubcmdDefinitionIdx: + case InfoobjectparametersubcmdDefinitionsIdx: listObj = ParamDefsFormat(interp, paramsPtr); break; case InfoobjectparametersubcmdListIdx: listObj = ParamDefsList(interp, paramsPtr); break; - case InfoobjectparametersubcmdNameIdx: + case InfoobjectparametersubcmdNamesIdx: listObj = ParamDefsNames(interp, paramsPtr); break; case InfoobjectparametersubcmdSyntaxIdx: listObj = NsfParamDefsSyntax(paramsPtr); break; } assert(listObj); + Tcl_SetObjResult(interp, listObj); + DECR_REF_COUNT2("paramDefsObj", listObj); + if (paramList) { + FREE(Nsf_Param*, paramList); + } return TCL_OK; } Index: generic/nsf.h =================================================================== diff -u -rabc6afbec5bf2984e6480f32f91829b54c1d8c91 -r60dc0dde60e22fb2b74bc6c3b15e0148af7d0fa5 --- generic/nsf.h (.../nsf.h) (revision abc6afbec5bf2984e6480f32f91829b54c1d8c91) +++ generic/nsf.h (.../nsf.h) (revision 60dc0dde60e22fb2b74bc6c3b15e0148af7d0fa5) @@ -143,7 +143,7 @@ #define NSF_STACKCHECK 1 */ -// #define PER_OBJECT_PARAMETER_CACHING 1 +//#define PER_OBJECT_PARAMETER_CACHING 1 /* * Sanity checks and dependencies for optional compile flags Index: generic/nsfAPI.decls =================================================================== diff -u -r102a1a9f4f678f98e7bcf7648ad1714147a29a47 -r60dc0dde60e22fb2b74bc6c3b15e0148af7d0fa5 --- generic/nsfAPI.decls (.../nsfAPI.decls) (revision 102a1a9f4f678f98e7bcf7648ad1714147a29a47) +++ generic/nsfAPI.decls (.../nsfAPI.decls) (revision 60dc0dde60e22fb2b74bc6c3b15e0148af7d0fa5) @@ -431,8 +431,8 @@ objectInfoMethod parent NsfObjInfoParentMethod { } objectInfoMethod objectparameter NsfObjInfoObjectparameterMethod { - {-argName "infoobjectparametersubcmd" -type "definition|list|name|syntax" -required 1} - {-argName "name" -required 0} + {-argName "infoobjectparametersubcmd" -type "definitions|list|names|syntax" -required 1} + {-argName "pattern" -required 0} } objectInfoMethod precedence NsfObjInfoPrecedenceMethod { {-argName "-intrinsic" -nrargs 0} Index: generic/nsfAPI.h =================================================================== diff -u -r102a1a9f4f678f98e7bcf7648ad1714147a29a47 -r60dc0dde60e22fb2b74bc6c3b15e0148af7d0fa5 --- generic/nsfAPI.h (.../nsfAPI.h) (revision 102a1a9f4f678f98e7bcf7648ad1714147a29a47) +++ generic/nsfAPI.h (.../nsfAPI.h) (revision 60dc0dde60e22fb2b74bc6c3b15e0148af7d0fa5) @@ -201,12 +201,12 @@ return result; } -enum InfoobjectparametersubcmdIdx {InfoobjectparametersubcmdNULL, InfoobjectparametersubcmdDefinitionIdx, InfoobjectparametersubcmdListIdx, InfoobjectparametersubcmdNameIdx, InfoobjectparametersubcmdSyntaxIdx}; +enum InfoobjectparametersubcmdIdx {InfoobjectparametersubcmdNULL, InfoobjectparametersubcmdDefinitionsIdx, InfoobjectparametersubcmdListIdx, InfoobjectparametersubcmdNamesIdx, InfoobjectparametersubcmdSyntaxIdx}; static int ConvertToInfoobjectparametersubcmd(Tcl_Interp *interp, Tcl_Obj *objPtr, Nsf_Param CONST *pPtr, ClientData *clientData, Tcl_Obj **outObjPtr) { int index, result; - static CONST char *opts[] = {"definition", "list", "name", "syntax", NULL}; + static CONST char *opts[] = {"definitions", "list", "names", "syntax", NULL}; (void)pPtr; result = Tcl_GetIndexFromObj(interp, objPtr, opts, "infoobjectparametersubcmd", 0, &index); *clientData = (ClientData) INT2PTR(index + 1); @@ -216,7 +216,7 @@ static enumeratorConverterEntry enumeratorConverterEntries[] = { - {ConvertToInfoobjectparametersubcmd, "definition|list|name|syntax"}, + {ConvertToInfoobjectparametersubcmd, "definitions|list|names|syntax"}, {ConvertToScope, "all|class|object"}, {ConvertToInfomethodsubcmd, "args|body|definition|exists|registrationhandle|definitionhandle|handle|origin|parameter|syntax|type|precondition|postcondition|submethods|returns"}, {ConvertToCallprotection, "all|public|protected|private"}, @@ -448,7 +448,7 @@ static int NsfObjInfoMixinclassesMethod(Tcl_Interp *interp, NsfObject *obj, int withGuards, int withHeritage, CONST char *patternString, NsfObject *patternObject); static int NsfObjInfoMixinguardMethod(Tcl_Interp *interp, NsfObject *obj, CONST char *mixin); static int NsfObjInfoNameMethod(Tcl_Interp *interp, NsfObject *obj); -static int NsfObjInfoObjectparameterMethod(Tcl_Interp *interp, NsfObject *obj, int infoobjectparametersubcmd, CONST char *name); +static int NsfObjInfoObjectparameterMethod(Tcl_Interp *interp, NsfObject *obj, int infoobjectparametersubcmd, CONST char *pattern); static int NsfObjInfoParentMethod(Tcl_Interp *interp, NsfObject *obj); static int NsfObjInfoPrecedenceMethod(Tcl_Interp *interp, NsfObject *obj, int withIntrinsic, CONST char *pattern); static int NsfObjInfoSlotobjectsMethod(Tcl_Interp *interp, NsfObject *obj, NsfClass *withType, CONST char *pattern); @@ -2506,10 +2506,10 @@ method_definitions[NsfObjInfoObjectparameterMethodIdx].nrParameters, 0, NSF_ARGPARSE_BUILTIN, &pc) == TCL_OK)) { int infoobjectparametersubcmd = (int )PTR2INT(pc.clientData[0]); - CONST char *name = (CONST char *)pc.clientData[1]; + CONST char *pattern = (CONST char *)pc.clientData[1]; assert(pc.status == 0); - return NsfObjInfoObjectparameterMethod(interp, obj, infoobjectparametersubcmd, name); + return NsfObjInfoObjectparameterMethod(interp, obj, infoobjectparametersubcmd, pattern); } else { return TCL_ERROR; @@ -3015,7 +3015,7 @@ }, {"::nsf::methods::object::info::objectparameter", NsfObjInfoObjectparameterMethodStub, 2, { {"infoobjectparametersubcmd", NSF_ARG_REQUIRED|NSF_ARG_IS_ENUMERATION, 1, ConvertToInfoobjectparametersubcmd, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}, - {"name", 0, 1, Nsf_ConvertToString, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}} + {"pattern", 0, 1, Nsf_ConvertToString, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}} }, {"::nsf::methods::object::info::parent", NsfObjInfoParentMethodStub, 0, { {NULL, 0, 0, NULL, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}} Index: library/nx/nx.tcl =================================================================== diff -u -r102a1a9f4f678f98e7bcf7648ad1714147a29a47 -r60dc0dde60e22fb2b74bc6c3b15e0148af7d0fa5 --- library/nx/nx.tcl (.../nx.tcl) (revision 102a1a9f4f678f98e7bcf7648ad1714147a29a47) +++ library/nx/nx.tcl (.../nx.tcl) (revision 60dc0dde60e22fb2b74bc6c3b15e0148af7d0fa5) @@ -670,12 +670,12 @@ return [: {*}$cmd] } :method "info lookup parameter definitions" {pattern:optional} { - set cmd [list ::nsf::methods::object::info::objectparameter definition] + set cmd [list ::nsf::methods::object::info::objectparameter definitions] if {[info exists pattern]} {lappend cmd $pattern} return [: {*}$cmd] } :method "info lookup parameter names" {pattern:optional} { - set cmd [list ::nsf::methods::object::info::objectparameter name] + set cmd [list ::nsf::methods::object::info::objectparameter names] if {[info exists pattern]} {lappend cmd $pattern} return [: {*}$cmd] } Index: tests/parameters.test =================================================================== diff -u -r102a1a9f4f678f98e7bcf7648ad1714147a29a47 -r60dc0dde60e22fb2b74bc6c3b15e0148af7d0fa5 --- tests/parameters.test (.../parameters.test) (revision 102a1a9f4f678f98e7bcf7648ad1714147a29a47) +++ tests/parameters.test (.../parameters.test) (revision 60dc0dde60e22fb2b74bc6c3b15e0148af7d0fa5) @@ -1840,13 +1840,14 @@ :create c1 } nx::Class create D -superclass C - nx::Class create M {:property b1:required} + nx::Class create M1 {:property b1:required} + nx::Class create M2 {:property b2:required} ? {c1 eval :__objectparameter} "-a1 -volatile:alias,noarg -properties:alias,method=::nx::internal::addProperties -noinit:alias,method=::nsf::methods::object::noinit,noarg -mixin:mixinreg,alias,0..n -class:class,alias,method=::nsf::methods::object::class -filter:filterreg,alias,0..n __initcmd:initcmd,optional,noleadingdash" - c1 mixin M + c1 mixin M1 - ? {c1 info precedence} "::M ::C ::nx::Object" + ? {c1 info precedence} "::M1 ::C ::nx::Object" ? {c1 eval :__objectparameter} "-b1:required -a1 -volatile:alias,noarg -properties:alias,method=::nx::internal::addProperties -noinit:alias,method=::nsf::methods::object::noinit,noarg -mixin:mixinreg,alias,0..n -class:class,alias,method=::nsf::methods::object::class -filter:filterreg,alias,0..n __initcmd:initcmd,optional,noleadingdash" @@ -1877,11 +1878,23 @@ ? {C create c2} ::c2 # - # the same should hold for subcles + # the same should hold for subclasses # ? {D create d1} ::d1 + # + # we have now per-object mixin of M1, we should have "-b1" but no + # "-b2" + # + ? {c1 info mixin classes} ::M1 + ? {c1 info lookup parameter names b*} "b1" + c1 mixin add ::M2 + ? {c1 info mixin classes} {::M2 ::M1} + ? {c1 info lookup parameter syntax b1} "-b1 value" + ? {c1 info lookup parameter syntax b2} "-b2 value" + ? {lsort [c1 info lookup parameter names b*]} "b1 b2" + } @@ -2448,7 +2461,6 @@ ? {o2 info methods} "p0 p3" # all properties with slots show up in "info slot" - # TODO: object slots will change when we allow true object properties ? {o2 info slot objects} "::o2::per-object-slot::p0 ::o2::per-object-slot::p1 ::o2::per-object-slot::p3" ? {o2 info slot definition} "{p0 200} {p1 201} {p3:noconfig 203}" ? {o2 info properties} "{p0 200} {p1 201} {p3:noconfig 203}"