Index: TODO =================================================================== diff -u -N -r46c536260f793729feb23fff02cc15e3867ae0ee -rbf363a408bfa522970f24b06967f2091604b6d02 --- TODO (.../TODO) (revision 46c536260f793729feb23fff02cc15e3867ae0ee) +++ TODO (.../TODO) (revision bf363a408bfa522970f24b06967f2091604b6d02) @@ -3083,7 +3083,16 @@ * regularized the interface of "variable" and "attribute" * extended regression test +- nsf.c: + * added flag "-array" to nsf::var::set such we have + now "::nsf::var::set ?-array? object varName ?value?" + With "-array", nsf::var::set behaves like "array get" + or "array set" (on instance variables) + * use "::nsf::var::set -array" in serializer symmetrically + to scalar case + * extended regression test + TODO: - add "delete variable" analogous to "delete attribute" - interface of "variable" and "attribute": @@ -3106,12 +3115,7 @@ (e) others? - call user defined setter in object parameters? -#::nsf::var::exists ?-array? object varName -#::nsf::var::import object ?arg ...? -#::nsf::var::set ?-array? object varName ?value? -#::nsf::var::unset ?-array? object varName - - Revise callstack introspection/intercession, i.e., [current activelevel] vs. [current callinglevel] vs. uplevel()/upvar(): Index: generic/nsf.c =================================================================== diff -u -N -r46c536260f793729feb23fff02cc15e3867ae0ee -rbf363a408bfa522970f24b06967f2091604b6d02 --- generic/nsf.c (.../nsf.c) (revision 46c536260f793729feb23fff02cc15e3867ae0ee) +++ generic/nsf.c (.../nsf.c) (revision bf363a408bfa522970f24b06967f2091604b6d02) @@ -13512,6 +13512,59 @@ /* *---------------------------------------------------------------------- + * SetInstArray -- + * + * Set an instance variable array of the specified object to the given + * value. This function performs essentially an "array set" or "array get" + * operation. + * + * Results: + * Tcl result code. + * + * Side effects: + * Set instance variable. + * + *---------------------------------------------------------------------- + */ +static int +SetInstArray(Tcl_Interp *interp, NsfObject *object, Tcl_Obj *nameObj, Tcl_Obj *valueObj) { + CallFrame frame, *framePtr = &frame; + int result; + Tcl_Obj *ov[4]; + + assert(object); + //flags = (object->nsPtr) ? TCL_LEAVE_ERR_MSG|TCL_NAMESPACE_ONLY : TCL_LEAVE_ERR_MSG; + Nsf_PushFrameObj(interp, object, framePtr); + + ov[0] = NsfGlobalObjs[NSF_ARRAY]; + ov[2] = nameObj; + + INCR_REF_COUNT(nameObj); + if (valueObj == NULL) { + /* + * perform an array get + */ + ov[1] = NsfGlobalObjs[NSF_GET]; + result = Tcl_EvalObjv(interp, 3, ov, 0); + } else { + /* + * perform an array get + */ + ov[1] = NsfGlobalObjs[NSF_SET]; + ov[3] = valueObj; + INCR_REF_COUNT(valueObj); + result = Tcl_EvalObjv(interp, 4, ov, 0); + DECR_REF_COUNT(valueObj); + } + DECR_REF_COUNT(nameObj); + Nsf_PopFrameObj(interp, framePtr); + + return result; +} + + +/* + *---------------------------------------------------------------------- * UnsetInstVar -- * * Unset an instance variable of the specified object. @@ -18406,19 +18459,24 @@ /* cmd var::set NsfVarSetCmd { + {-argName "-array" -required 0 -nrargs 0} {-argName "object" -required 1 -type object} {-argName "varname" -required 1 -type tclobj} {-argName "value" -required 0 -type tclobj} } */ static int -NsfVarSetCmd(Tcl_Interp *interp, NsfObject *object, Tcl_Obj *varname, Tcl_Obj *valueObj) { +NsfVarSetCmd(Tcl_Interp *interp, int withArray, + NsfObject *object, Tcl_Obj *varname, Tcl_Obj *valueObj) { if (CheckVarName(interp, ObjStr(varname)) != TCL_OK) { return TCL_ERROR; } - - return SetInstVar(interp, object, varname, valueObj); + if (withArray) { + return SetInstArray(interp, object, varname, valueObj); + } else { + return SetInstVar(interp, object, varname, valueObj); + } } /* Index: generic/nsfAPI.decls =================================================================== diff -u -N -rdcee5f2f7bac79f3fb2b966d68360cdfcef8002a -rbf363a408bfa522970f24b06967f2091604b6d02 --- generic/nsfAPI.decls (.../nsfAPI.decls) (revision dcee5f2f7bac79f3fb2b966d68360cdfcef8002a) +++ generic/nsfAPI.decls (.../nsfAPI.decls) (revision bf363a408bfa522970f24b06967f2091604b6d02) @@ -181,6 +181,7 @@ {-argName "args" -type args} } cmd "var::set" NsfVarSetCmd { + {-argName "-array" -required 0 -nrargs 0} {-argName "object" -required 1 -type object} {-argName "varName" -required 1 -type tclobj} {-argName "value" -required 0 -type tclobj} Index: generic/nsfAPI.h =================================================================== diff -u -N -rdcee5f2f7bac79f3fb2b966d68360cdfcef8002a -rbf363a408bfa522970f24b06967f2091604b6d02 --- generic/nsfAPI.h (.../nsfAPI.h) (revision dcee5f2f7bac79f3fb2b966d68360cdfcef8002a) +++ generic/nsfAPI.h (.../nsfAPI.h) (revision bf363a408bfa522970f24b06967f2091604b6d02) @@ -361,7 +361,7 @@ static int NsfUnsetUnknownArgsCmd(Tcl_Interp *interp); static int NsfVarExistsCmd(Tcl_Interp *interp, int withArray, NsfObject *object, CONST char *varName); static int NsfVarImportCmd(Tcl_Interp *interp, NsfObject *object, int nobjc, Tcl_Obj *CONST nobjv[]); -static int NsfVarSetCmd(Tcl_Interp *interp, NsfObject *object, Tcl_Obj *varName, Tcl_Obj *value); +static int NsfVarSetCmd(Tcl_Interp *interp, int withArray, NsfObject *object, Tcl_Obj *varName, Tcl_Obj *value); static int NsfVarUnsetCmd(Tcl_Interp *interp, NsfObject *object, Tcl_Obj *varName); static int NsfOAutonameMethod(Tcl_Interp *interp, NsfObject *obj, int withInstance, int withReset, Tcl_Obj *name); static int NsfOClassMethod(Tcl_Interp *interp, NsfObject *obj, Tcl_Obj *class); @@ -1647,12 +1647,13 @@ &pc) != TCL_OK) { return TCL_ERROR; } else { - NsfObject *object = (NsfObject *)pc.clientData[0]; - Tcl_Obj *varName = (Tcl_Obj *)pc.clientData[1]; - Tcl_Obj *value = (Tcl_Obj *)pc.clientData[2]; + int withArray = (int )PTR2INT(pc.clientData[0]); + NsfObject *object = (NsfObject *)pc.clientData[1]; + Tcl_Obj *varName = (Tcl_Obj *)pc.clientData[2]; + Tcl_Obj *value = (Tcl_Obj *)pc.clientData[3]; assert(pc.status == 0); - return NsfVarSetCmd(interp, object, varName, value); + return NsfVarSetCmd(interp, withArray, object, varName, value); } } @@ -2570,7 +2571,8 @@ {"object", NSF_ARG_REQUIRED, 1, Nsf_ConvertToObject, NULL,NULL,"object",NULL,NULL,NULL,NULL,NULL}, {"args", 0, 1, ConvertToNothing, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}} }, -{"::nsf::var::set", NsfVarSetCmdStub, 3, { +{"::nsf::var::set", NsfVarSetCmdStub, 4, { + {"-array", 0, 0, Nsf_ConvertToString, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}, {"object", NSF_ARG_REQUIRED, 1, Nsf_ConvertToObject, NULL,NULL,"object",NULL,NULL,NULL,NULL,NULL}, {"varName", NSF_ARG_REQUIRED, 1, Nsf_ConvertToTclobj, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}, {"value", 0, 1, Nsf_ConvertToTclobj, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}} Index: generic/nsfInt.h =================================================================== diff -u -N -r46c536260f793729feb23fff02cc15e3867ae0ee -rbf363a408bfa522970f24b06967f2091604b6d02 --- generic/nsfInt.h (.../nsfInt.h) (revision 46c536260f793729feb23fff02cc15e3867ae0ee) +++ generic/nsfInt.h (.../nsfInt.h) (revision bf363a408bfa522970f24b06967f2091604b6d02) @@ -600,7 +600,7 @@ /* constants */ NSF_ALIAS, NSF_ARGS, NSF_CMD, NSF_FILTER, NSF_FORWARD, NSF_METHOD, NSF_OBJECT, NSF_SETTER, NSF_VALUECHECK, - NSF_GUARD_OPTION, NSF___UNKNOWN__, + NSF_GUARD_OPTION, NSF___UNKNOWN__, NSF_ARRAY, NSF_GET, NSF_SET, NSF_UNKNOWN_HANDLER, /* Partly redefined Tcl commands; leave them together at the end */ NSF_EXPR, NSF_FORMAT, NSF_INFO_BODY, NSF_INFO_FRAME, NSF_INTERP, NSF_IS, @@ -621,7 +621,7 @@ /* constants */ "alias", "args", "cmd", "filter", "forward", "method", "object", "setter", "valuecheck", - "-guard", "__unknown__", + "-guard", "__unknown__", "::array", "get", "set", /* nsf tcl commands */ "::nsf::object::unknown", /* tcl commands */ Index: library/serialize/serializer.tcl =================================================================== diff -u -N -rc6057c18970d5bc19fe0f1f760ef0d29898ecfdd -rbf363a408bfa522970f24b06967f2091604b6d02 --- library/serialize/serializer.tcl (.../serializer.tcl) (revision c6057c18970d5bc19fe0f1f760ef0d29898ecfdd) +++ library/serialize/serializer.tcl (.../serializer.tcl) (revision bf363a408bfa522970f24b06967f2091604b6d02) @@ -589,7 +589,7 @@ continue } if {[::nsf::var::exists -array $o $v]} { - lappend setcmd [list array set :$v [$o eval [list array get :$v]]] + lappend setcmd [list array set :$v [::nsf::var::set -array $o $v]] } else { lappend setcmd [list set :$v [::nsf::var::set $o $v]] } Index: tests/var-access.test =================================================================== diff -u -N -re02cb00ae815bd6f8561a6a03fceacc13fd91903 -rbf363a408bfa522970f24b06967f2091604b6d02 --- tests/var-access.test (.../var-access.test) (revision e02cb00ae815bd6f8561a6a03fceacc13fd91903) +++ tests/var-access.test (.../var-access.test) (revision bf363a408bfa522970f24b06967f2091604b6d02) @@ -17,6 +17,46 @@ :alias set ::nsf::var::set } + +nx::Test case set+array { + nx::Object create o1 + + # first set a scalar variable + ? {nsf::var::set o1 x 100} "100" + ? {nsf::var::set o1 x} "100" + + # now, set an array variable; "nsf::var::set -array" is a wrapper + # around "array set" or "array get" + ? {nsf::var::set -array o1 a {a 1 y 2}} "" + ? {nsf::var::set -array o1 a} "y 2 a 1" + + # We have now a scalar and an array variable set. + ? {lsort [o1 info vars]} "a x" + + # "x" is a variable, but not an array + ? {nsf::var::exists o1 x} 1 + ? {nsf::var::exists -array o1 x} 0 + + # "a" is a variable and an array + ? {nsf::var::exists -array o1 a} 1 + ? {nsf::var::exists o1 a} 1 + + # we unset the array + ? {nsf::var::unset o1 a} "" + ? {nsf::var::exists o1 a} 0 + ? {nsf::var::exists -array o1 a} 0 + + # now, just the scalar is left + ? {o1 info vars} "x" + ? {nsf::var::exists o1 x} 1 + ? {nsf::var::exists -array o1 x} 0 + + # we unset the scalar + ? {nsf::var::unset o1 x} "" + ? {nsf::var::exists o1 x} 0 + ? {nsf::var::exists -array o1 x} 0 +} + nx::Test parameter count 10000 nx::Test case dummy { nx::Object create o {