Index: TODO =================================================================== diff -u -r2fbf1bf87402e8639e772781c5719164e7e55555 -r551a41a1d6502070f966b5f0be2559cf3fe12804 --- TODO (.../TODO) (revision 2fbf1bf87402e8639e772781c5719164e7e55555) +++ TODO (.../TODO) (revision 551a41a1d6502070f966b5f0be2559cf3fe12804) @@ -3007,6 +3007,15 @@ to add some additional metadata (e.g. dublin core meta data) and how to retrieve this via the gridfile interface +- nsf.c: + * report only fully initialized slot objects via "info slots" to + avoid chicken-egg problem during method "objectparameter" + * added flag -array to ::nsf::var::exists to check, whether + the variable is an array (to avoid "o eval {array exists ...}" + in the serializer. + * provided flags to VarExists instead of multiple args + * don't add new pointer entries in Nsf_PointerTypeLookup() + TODO: - extend mongo::gridfs::store_file with a switch -metadata to pass metadata together at gridfs file creation time Index: generic/nsf.c =================================================================== diff -u -re174b535c9d737520e28892f750311372f78bd7c -r551a41a1d6502070f966b5f0be2559cf3fe12804 --- generic/nsf.c (.../nsf.c) (revision e174b535c9d737520e28892f750311372f78bd7c) +++ generic/nsf.c (.../nsf.c) (revision 551a41a1d6502070f966b5f0be2559cf3fe12804) @@ -7378,29 +7378,31 @@ static int VarExists(Tcl_Interp *interp, NsfObject *object, CONST char *varName, CONST char *index, - int triggerTrace, int requireDefined) { + int flags) { CallFrame frame, *framePtr = &frame; Var *varPtr, *arrayPtr; int result; Nsf_PushFrameObj(interp, object, framePtr); - if (triggerTrace) { + if (flags & NSF_VAR_TRIGGER_TRACE) { varPtr = TclVarTraceExists(interp, varName); } else { int flags = (index == NULL) ? TCL_PARSE_PART1 : 0; varPtr = TclLookupVar(interp, varName, index, flags, "access", /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); } /* - fprintf(stderr, "VarExists %s varPtr %p requireDefined %d, triggerTrace %d, isundef %d\n", + fprintf(stderr, "VarExists %s varPtr %p flags %.4x isundef %d\n", varName, varPtr, - requireDefined, triggerTrace, + flags, varPtr ? TclIsVarUndefined(varPtr) : NULL); */ - result = (varPtr && (!requireDefined || !TclIsVarUndefined(varPtr))); - + result = (varPtr && ((flags & NSF_VAR_REQUIRE_DEFINED) == 0 || !TclIsVarUndefined(varPtr))); + if (result && (flags & NSF_VAR_ISARRAY) && !TclIsVarArray(varPtr)) { + result = 0; + } Nsf_PopFrameObj(interp, framePtr); return result; @@ -11546,7 +11548,14 @@ */ cmd = (Tcl_Command) Tcl_GetHashValue(hPtr); childObject = NsfGetObjectFromCmdPtr(cmd); - if (!childObject) continue; + + /* + * Report just the already fully initialized slot objects, not the one + * being right now created. + */ + if (!childObject || (childObject->flags & NSF_INIT_CALLED) == 0) { + continue; + } /* * Check the pattern. @@ -16721,7 +16730,6 @@ */ static int NsfInvalidateObjectParameterCmd(Tcl_Interp *UNUSED(interp), NsfClass *cl) { - if (cl->parsedParamPtr) { /*fprintf(stderr, " %s invalidate %p\n", ClassName(cl), cl->parsedParamPtr);*/ ParsedParamFree(cl->parsedParamPtr); @@ -18258,17 +18266,21 @@ /* cmd var::exists NsfVarExistsCmd { + {-argName "-array" -required 0 -nrargs 0} {-argName "object" -required 1 -type object} {-argName "varname" -required 1} } */ static int -NsfVarExistsCmd(Tcl_Interp *interp, NsfObject *object, CONST char *varName) { +NsfVarExistsCmd(Tcl_Interp *interp, int withArray, NsfObject *object, CONST char *varName) { + int flags = + NSF_VAR_TRIGGER_TRACE|NSF_VAR_REQUIRE_DEFINED| + (withArray ? NSF_VAR_ISARRAY : 0); if (CheckVarName(interp, varName) != TCL_OK) { return TCL_ERROR; } - Tcl_SetIntObj(Tcl_GetObjResult(interp), VarExists(interp, object, varName, NULL, 1, 1)); + Tcl_SetIntObj(Tcl_GetObjResult(interp), VarExists(interp, object, varName, NULL, flags)); return TCL_OK; } @@ -18527,6 +18539,7 @@ * Check, if there is already a parameter definition available for * creating objects of this class. */ + if (clParsedParamPtr) { parsedParamPtr->paramDefs = clParsedParamPtr->paramDefs; parsedParamPtr->possibleUnknowns = clParsedParamPtr->possibleUnknowns; @@ -19125,7 +19138,9 @@ */ static int NsfOExistsMethod(Tcl_Interp *interp, NsfObject *object, CONST char *var) { - Tcl_SetIntObj(Tcl_GetObjResult(interp), VarExists(interp, object, var, NULL, 1, 1)); + Tcl_SetIntObj(Tcl_GetObjResult(interp), + VarExists(interp, object, var, NULL, + NSF_VAR_TRIGGER_TRACE|NSF_VAR_REQUIRE_DEFINED)); return TCL_OK; } @@ -20463,7 +20478,7 @@ okList = Tcl_NewListObj(0, NULL); for (i=0; i $r" + # :reconfigure + # return $r + #} + ###################################################################### # Attribute slots @@ -1519,7 +1533,7 @@ Attribute public method add {obj prop value {pos 0}} { if {![:isMultivalued]} { - puts stderr "... vars [[self] info vars] // [[self] eval {set :multiplicity}]" + #puts stderr "... vars [[self] info vars] // [[self] eval {set :multiplicity}]" error "Property $prop of [set :domain] ist not multivalued" } if {[::nsf::var::exists $obj $prop]} { @@ -1603,6 +1617,7 @@ # remove helper proc proc createBootstrapAttributeSlots {} {} + ###################################################################### # Create a mixin class to overload method "new" such it does not # allocate new objects in ::nx::*, but in the specified object Index: library/serialize/serializer.tcl =================================================================== diff -u -rbd92cf0fcf5cb4388749a10ab542bf0199b00761 -r551a41a1d6502070f966b5f0be2559cf3fe12804 --- library/serialize/serializer.tcl (.../serializer.tcl) (revision bd92cf0fcf5cb4388749a10ab542bf0199b00761) +++ library/serialize/serializer.tcl (.../serializer.tcl) (revision 551a41a1d6502070f966b5f0be2559cf3fe12804) @@ -584,7 +584,11 @@ set setcmd [list] foreach v [lsort [$o info vars]] { if {![info exists :ignoreVarsRE] || ![regexp ${:ignoreVarsRE} ${o}::$v]} { - if {[$o eval [list ::array exists :$v]]} { + if {[::nsf::var::exists $o $v] == 0} { + puts stderr "strange, [list $o info vars] returned $v, but it does not seem to exist" + continue + } + if {[::nsf::var::exists -array $o $v]} { lappend setcmd [list array set :$v [$o eval [list array get :$v]]] } else { lappend setcmd [list set :$v [::nsf::var::set $o $v]] Index: tests/disposition.test =================================================================== diff -u -r17b63f15e327dd62f8dcd5e5419b7096b7d858ce -r551a41a1d6502070f966b5f0be2559cf3fe12804 --- tests/disposition.test (.../disposition.test) (revision 17b63f15e327dd62f8dcd5e5419b7096b7d858ce) +++ tests/disposition.test (.../disposition.test) (revision 551a41a1d6502070f966b5f0be2559cf3fe12804) @@ -806,7 +806,7 @@ } -nx::Test parameter count 100000 +nx::Test parameter count 1000 nx::Test case xotcl-residualargs { ::xotcl::Class create XC -parameter {a b c} Index: tests/parameters.test =================================================================== diff -u -r6baac71ced92839d10c87b18acdca3d5e7858d2a -r551a41a1d6502070f966b5f0be2559cf3fe12804 --- tests/parameters.test (.../parameters.test) (revision 6baac71ced92839d10c87b18acdca3d5e7858d2a) +++ tests/parameters.test (.../parameters.test) (revision 551a41a1d6502070f966b5f0be2559cf3fe12804) @@ -1757,4 +1757,42 @@ [o info slots a] reconfigure ? {o eval {info exists :a}} 1 ? {o a} anothervalue + + # + # Object parameters (specified e.g. via attributes) are defined to + # configure fresh objects (therefore, the definition is on the class + # level). Therefore, object-level object parameter do not fulfill + # this purpose, since they can only be defined, *after* the object + # is created. + # + # In general, object parameters have creational aspects (providing + # configurations for the object creation, such as e.g. defaults, and + # configurations) and object-lifetime aspects (valid through the + # lifetime of objects, such as e.g. setters/checkers). + # + # Object-level attributes cannot be used for the creational aspects + # of object parameters. + # + # Strengths of object-level parameters: + # - same interface as class-level attributes + # - can use same meta-data mechanisms as for class-level attributes + # (e.g database types, attribute name in the database, persistence + # information, ...) + # - can use same setters/checkers as for class-level attributes + # - can use as well incremental as for class-level attributes + # + # Shortcomings of object-level parameters: + # - no nice introspection: + # "info parameter ...." is defined on cls, not on obj + # - default handling is not the same as for classes level attributes + # (we have already some special mechanisms to set instance + # attributes, if they do not exist) + # - object-level parameters cannot be used in a "configure" + # of the object, since configure allows the same signature + # as on object creation, all object parameters are cached + # on the class level + # - Since configure does not include object-level parameters, + # positional object level parameters do not make sense, since they + # cannot be called. + } \ No newline at end of file