Index: TODO =================================================================== diff -u -r9ab6a86b4aee196f04363d13e5eadbdfdb814a06 -rf32527e58ada02a9089fa17e2d1a99bac89f9be9 --- TODO (.../TODO) (revision 9ab6a86b4aee196f04363d13e5eadbdfdb814a06) +++ TODO (.../TODO) (revision f32527e58ada02a9089fa17e2d1a99bac89f9be9) @@ -3664,40 +3664,17 @@ - added per-object traits (and per-class-object traits) - added tk-spread and tk-locomotive to example scripts +- altered default handling to honor side effects of aliased object + parameters. This slows down evaluation a little. Side-effects from + aliased parameters are discouraged, since the order of the + evaluation should not matter of an declarative evaluation of the + argument vector. +- extended regression test TODO: -- ISSUE: Default-setting mechanism seems to be keen on the relative - order of non-pos params once processed; for an example, run: - -package req nx -package req nx::test - -nx::Class create C { - :public class method setObjectParams {spec} { - set :objectparams $spec - ::nsf::invalidateobjectparameter [current] - } - :class method objectparameter {} { - return ${:objectparams} - } - :setObjectParams "" -} - -C method second {arg} { - set :first $arg -} - -C setObjectParams {{-first "X"} -second:alias} -? {[C new -second Y] eval {set :first}} Y; # OK! - -C setObjectParams {-second:alias {-first "X"}} -? {[C new -second Y] eval {set :first}} X; # NOT OK! should be 'Y'! - - - allow traits to be added to objects (maybe use :trait - instead of "useTrait" and allow modifier "class") - naming of traits. Predefined traits have a leading "T" (convetion by ducasse); how should the package and file be named? currently nx::trait nx-trait.tcl. Index: generic/nsf.c =================================================================== diff -u -ra390a38437dec2a7c3461f9fadef108ebf74b928 -rf32527e58ada02a9089fa17e2d1a99bac89f9be9 --- generic/nsf.c (.../nsf.c) (revision a390a38437dec2a7c3461f9fadef108ebf74b928) +++ generic/nsf.c (.../nsf.c) (revision f32527e58ada02a9089fa17e2d1a99bac89f9be9) @@ -20371,27 +20371,26 @@ (pc.flags[i-1] & NSF_PC_IS_DEFAULT), ObjStr(pc.full_objv[i]), paramPtr->nrArgs);*/ - if ((object->flags & NSF_INIT_CALLED) && (pc.flags[i-1] & NSF_PC_IS_DEFAULT)) { + if (/*(object->flags & NSF_INIT_CALLED) &&*/ (pc.flags[i-1] & NSF_PC_IS_DEFAULT)) { Tcl_Obj *varObj; /* * Object parameter method calls (when the flag * NSF_ARG_METHOD_INVOCATION is set) do not set instance variables, so * we do not have to check for existing variables. */ - if (paramPtr->flags & NSF_ARG_METHOD_INVOCATION) { - continue; + if ((paramPtr->flags & NSF_ARG_METHOD_INVOCATION) == 0) { + varObj = Tcl_ObjGetVar2(interp, paramPtr->nameObj, NULL, TCL_PARSE_PART1); + if (varObj) { + /* + * The value exists already, ignore this parameter. + */ + /*fprintf(stderr, "a variable for %s exists already, " + "ignore param flags %.6x valueObj %p\n", + paramPtr->name, paramPtr->flags, pc.full_objv[i]);*/ + continue; + } } - - varObj = Tcl_ObjGetVar2(interp, paramPtr->nameObj, NULL, TCL_PARSE_PART1); - if (varObj) { - /* - * The value exists already, ignore this parameter. - */ - /*fprintf(stderr, "a variable for %s exists already, ignore param flags %.6x valueObj %p\n", - paramPtr->name, paramPtr->flags, pc.full_objv[i]);*/ - continue; - } } newValue = pc.full_objv[i]; @@ -20524,8 +20523,8 @@ } else { /*fprintf(stderr, "call alias %s with methodObj %s.%s oc %d, nrArgs %d '%s'\n", - paramPtr->name, ObjectName(object), ObjStr(methodObj), oc, - paramPtr->nrArgs, ObjStr(newValue));*/ + paramPtr->name, ObjectName(object), ObjStr(methodObj), oc, + paramPtr->nrArgs, ObjStr(newValue));*/ result = NsfCallMethodWithArgs(interp, (Nsf_Object*)object, methodObj, ov0, oc, ovPtr, NSF_CSC_IMMEDIATE); @@ -20633,10 +20632,11 @@ */ if (i < paramDefs->nrParams || !pc.varArgs) { #if defined(CONFIGURE_ARGS_TRACE) - fprintf(stderr, "*** %s SET %s '%s'\n", ObjectName(object), ObjStr(paramPtr->nameObj), ObjStr(newValue)); + fprintf(stderr, "*** %s SET %s '%s'\n", + ObjectName(object), ObjStr(paramPtr->nameObj), ObjStr(newValue)); #endif /* - * Actually set instance variable with the provided or default value. + * Actually set instance variable with the provided value or default value. */ Tcl_ObjSetVar2(interp, paramPtr->nameObj, NULL, newValue, TCL_LEAVE_ERR_MSG|TCL_PARSE_PART1); } Index: tests/parameters.test =================================================================== diff -u -rd62bca12731d1c7a1a5cf63f950275852c5b05a2 -rf32527e58ada02a9089fa17e2d1a99bac89f9be9 --- tests/parameters.test (.../parameters.test) (revision d62bca12731d1c7a1a5cf63f950275852c5b05a2) +++ tests/parameters.test (.../parameters.test) (revision f32527e58ada02a9089fa17e2d1a99bac89f9be9) @@ -2259,4 +2259,37 @@ } ? {Foo info properties} "objs:object,1..n {ints:integer,0..n {}} obj:object,0..1" +} + +# +# The following test case sets a value of an instance variable via a +# side-effect of an aliased parameter. Side-effects from aliased +# parameters are discouraged, since the order of the evaluation should +# not matter of an declarative evaluation of the argument vector. +# +# Note that the order, in which is the arguments are provided is not +# significant for the evaluation order. +# +nx::Test case side-effect-set-value { + + nx::Class create C { + :public class method setObjectParams {spec} { + set :objectparams $spec + ::nsf::invalidateobjectparameter [self] + } + :class method objectparameter {} { + return ${:objectparams} + } + :setObjectParams "" + } + + C method second {arg} { + set :first $arg + } + + C setObjectParams {{-first "X"} -second:alias} + ? {[C new -second Y] eval {set :first}} Y "side-effect overwrites default" + + C setObjectParams {-second:alias {-first "X"}} + ? {[C new -second Y] eval {set :first}} Y "side-effect determines value" } \ No newline at end of file