Index: TODO =================================================================== diff -u -r4c6c39cd6a1aa703a9a8cf7dc89baf7d4a58d6c5 -r98775245c7eb6eb2662fbccfd9fea1f30bd5f3d8 --- TODO (.../TODO) (revision 4c6c39cd6a1aa703a9a8cf7dc89baf7d4a58d6c5) +++ TODO (.../TODO) (revision 98775245c7eb6eb2662fbccfd9fea1f30bd5f3d8) @@ -4605,15 +4605,24 @@ nsf.c: - when creation with an required configure parameter failed, delete the half-baked object to avoid confusing states. + +- improved handling of required configure parameters + when classes are changed dynamically. + When configure parameter are defined required, checking + for the absence of required parameter was only performed + at creation time. When objects were re-classed or their + classes extended with required parameters, later + calls to configure did not trigger exceptions. Now + we check for the existence of the instance variable + which addresses most of these points, but in future + we might wish a more general solution (see comment + for futures releases) ======================================================================== TODO: -- handling of "required" in reconfigure (see - parameter-object-mixin-dependency in parameters.test) - handling of recreate (see regression test for class-level properties) - - maybe "::nsf::object::property /obj/ volatile 0|1" to alter volatile state. @@ -4880,17 +4889,35 @@ For future releases (after first alpha/beta release) + + * generalizing parameter-specific per-object info + Now we have + __initcmd(varname) for init-cmds of varitable traces + __cmd(varname) for the eval-ed cmds (mostly + for documentation purposes + to postprocess the init block + We could need + __required_satistfied(varname) to handle + required parameter aliases + As generalization, we could use a dict + __parameterstate(varname) + or even + __parameterstate + with a dict to collect the various aspects. + for performance reasons, we do not want to set this + variable too frequent, serialization and blueprint + aspects have to be considered. This would as well + address cases, where the parameter has a different name + than the associated varianle (e.g. private properties) * extend traits (object-specific traits, test cases, etc.) - - Stefan: Still valid, IMHO: todo: don't hard-code registering - command name "method" / NSF_METHOD"; parts of the introspection - machinery in NSF rely on NX/script-level specifics ... how should we - handle this? For the system methods (create, ...), we can resolve - the situation; for the NX or XOTcl method delegates (method) of - ::nsf::method::create & friends, we do not have any - abstraction/handle right now ... should we script those info - subcmds (info method definition), against a performance penalty? + * Reduce / remove hard-code names. Right now, "method"/"alias"/ + "forward" is returend by "info definition" introspection. + This is not serious, since e.g. XOTcl handles this on the + script level by mapping these names to the XOTcl counterparts. + We could as well make this configurable via the object-system + parameters. * Consider alternate method name/place for subcmds (and/or slots) on classes - currently, there are potential conflicts between slots and ensemble objects Index: generic/nsf.c =================================================================== diff -u -r4c6c39cd6a1aa703a9a8cf7dc89baf7d4a58d6c5 -r98775245c7eb6eb2662fbccfd9fea1f30bd5f3d8 --- generic/nsf.c (.../nsf.c) (revision 4c6c39cd6a1aa703a9a8cf7dc89baf7d4a58d6c5) +++ generic/nsf.c (.../nsf.c) (revision 98775245c7eb6eb2662fbccfd9fea1f30bd5f3d8) @@ -22404,20 +22404,24 @@ } } } else if (unlikely(paramPtr->flags & NSF_ARG_REQUIRED - && pc.full_objv[i] == NsfGlobalObjs[NSF___UNKNOWN__] - && (object->flags & NSF_INIT_CALLED) == 0) - ) { - /* - * The checking for required arguments happens only, when the actual - * value is not the default, but the magic __UNKNOWN Tcl_Obj, and the - * object is not jet initialized. Logic behind this: if the object is - * initialized, configure must have been called before, and the required - * action must have been already taken). We might change this to the - * overwriting logic like above, but we have as well to deal with - * aliases. + && pc.full_objv[i] == NsfGlobalObjs[NSF___UNKNOWN__])) { + + /* Previous versions contained a test for + * (object->flags & NSF_INIT_CALLED) + * + * to perform required testing just for in the non-initialized state. We + * switched in 2.0b5 to checking for the existance of the associated + * instance variable, which works under the assumption that the instance + * variable has the same name and that e.g. an required alias parameter + * sets this variable either. Similar assumption is in the default + * handling. Future versions might use a more generneral handling of the + * parameter states. */ + + Tcl_Obj *varObj = Tcl_ObjGetVar2(interp, paramPtr->nameObj, NULL, TCL_PARSE_PART1); + if (varObj == NULL) { Tcl_Obj *paramDefsObj = NsfParamDefsSyntax(paramDefs->paramsPtr); - + NsfPrintError(interp, "required argument '%s' is missing, should be:\n\t%s%s%s %s", paramPtr->nameObj ? ObjStr(paramPtr->nameObj) : paramPtr->name, pc.object ? ObjectName(pc.object) : "", @@ -22429,6 +22433,7 @@ Nsf_PopFrameObj(interp, framePtr); result = TCL_ERROR; goto configure_exit; + } } newValue = pc.full_objv[i]; Index: tests/parameters.test =================================================================== diff -u -r4c6c39cd6a1aa703a9a8cf7dc89baf7d4a58d6c5 -r98775245c7eb6eb2662fbccfd9fea1f30bd5f3d8 --- tests/parameters.test (.../parameters.test) (revision 4c6c39cd6a1aa703a9a8cf7dc89baf7d4a58d6c5) +++ tests/parameters.test (.../parameters.test) (revision 98775245c7eb6eb2662fbccfd9fea1f30bd5f3d8) @@ -1698,8 +1698,32 @@ ? {C create c3 -y 1 -x 0} "::c3" ? {set ::_} "passed args ''" ? {c3 cget -x} "0" + + # + # incremental property adding vs. required + # + nx::Class create D + + ? {D create d1} ::d1 + ? {d1 configure} "" + + D property x:required + ? {d1 info configure} \ + "-x /value/ ?-volatile? ?-noinit? ?-object-mixin /mixinreg .../? ?-class /class/? ?-object-filter /filterreg .../? ?/__initblock/?" + + ? {d1 configure} \ + "required argument 'x' is missing, should be: + ::d1 configure -x /value/ ?-volatile? ?-noinit? ?-object-mixin /mixinreg .../? ?-class /class/? ?-object-filter /filterreg .../? ?/__initblock/?" + + ? {d1 configure -x 123} "" + ? {d1 cget -x} 123 + + ? {d1 configure} "" } + + + ::nsf::configure checkarguments on # @@ -1883,15 +1907,14 @@ # # We have now "-b1:required" in the configure parameters. # - # TODO: Actually we should enforce it. We could check, if the - # associate variable is already set, but this does not work for - # aliases.... we could track, if the slot is already initialized for - # this object. This can be a potentially huge table containing - # potentially all objects (relation slots). Maybe keep the table - # just for "required" parameters? or look for an approach based on - # epoch counting? + # NSF checks, if the associated variable is already set, but + # this does not work for aliases.... we could track whether or + # not a required parameter was already provided, but that + # requires most likely a more general handling. # - ? {c1 configure -a1 x} "" + ? {c1 configure -a1 x} \ +"required argument 'b1' is missing, should be: + ::c1 configure -b1 /value/ ?-a1 /value/? ?-volatile? ?-noinit? ?-object-mixin /mixinreg .../? ?-class /class/? ?-object-filter /filterreg .../? ?/__initblock/?" # # The object parameter based on the per-object-mixin must not be @@ -1983,7 +2006,9 @@ # ::nsf::parameter:invalidate::classcache C - c1 __configure -a1 x + ? {c1 __configure -a1 x} \ +"required argument 'b1' is missing, should be: + ::c1 __configure ?-a2 /value/? -b1 /value/ ?-a1 /value/? ?-volatile? ?-noinit? ?-object-mixin /mixinreg .../? ?-class /class/? ?-object-filter /filterreg .../? ?/__initblock/?" ? {c1 info precedence} "::M ::C ::nx::Object"