Index: TODO =================================================================== diff -u -re2fe47226a0bb0c420173a9590309645e5a0592a -r8e08d180ae5161c0ef4410ba3fda6b4de613a391 --- TODO (.../TODO) (revision e2fe47226a0bb0c420173a9590309645e5a0592a) +++ TODO (.../TODO) (revision 8e08d180ae5161c0ef4410ba3fda6b4de613a391) @@ -1386,6 +1386,13 @@ from the implicit next in ensemble methods - made NsfNextMethod() obsolete to ease different noarg handling policies +- new nsf::next cmd. receives 0 or 1 argument, which might be a list + of arguments. This avoids ambiguity of ::xotcl::next with "--noArgs". +- renamed namespace_copycmds and namespace_copyvars to + nscopycmds and nscopyvars (we don't use "_" in nsf::*-names as delimiters + elsewhere) +- renamed __qualify to qualify (it is a non-exported cmd) + TODO: - subcmd * handle sucmd for other method factories Index: generic/gentclAPI.decls =================================================================== diff -u -r38f8651fe4c101ee7ad98aa46bcadc32459bfdc7 -r8e08d180ae5161c0ef4410ba3fda6b4de613a391 --- generic/gentclAPI.decls (.../gentclAPI.decls) (revision 38f8651fe4c101ee7ad98aa46bcadc32459bfdc7) +++ generic/gentclAPI.decls (.../gentclAPI.decls) (revision 8e08d180ae5161c0ef4410ba3fda6b4de613a391) @@ -115,16 +115,18 @@ {-argName "method" -required 1 -type tclobj} {-argName "args" -type args} } - -nsfCmd namespace_copycmds NsfNSCopyCmds { +nsfCmd next NsfNextCmd { + {-argName "arguments" -required 0 -type tclobj} +} +nsfCmd nscopycmds NsfNSCopyCmdsCmd { {-argName "fromNs" -required 1 -type tclobj} {-argName "toNs" -required 1 -type tclobj} } -nsfCmd namespace_copyvars NsfNSCopyVars { +nsfCmd nscopyvars NsfNSCopyVarsCmd { {-argName "fromNs" -required 1 -type tclobj} {-argName "toNs" -required 1 -type tclobj} } -nsfCmd __qualify NsfQualifyObjCmd { +nsfCmd qualify NsfQualifyObjCmd { {-argName "name" -required 1 -type tclobj} } nsfCmd relation NsfRelationCmd { Index: generic/nsf.c =================================================================== diff -u -re2fe47226a0bb0c420173a9590309645e5a0592a -r8e08d180ae5161c0ef4410ba3fda6b4de613a391 --- generic/nsf.c (.../nsf.c) (revision e2fe47226a0bb0c420173a9590309645e5a0592a) +++ generic/nsf.c (.../nsf.c) (revision 8e08d180ae5161c0ef4410ba3fda6b4de613a391) @@ -163,7 +163,6 @@ */ /* prototypes for method defintions */ -static int NsfNextMethod(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); static int NsfForwardMethod(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); static int NsfObjscopedMethod(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); static int NsfSetterMethod(ClientData clientData, Tcl_Interp *interp, int objc,Tcl_Obj *CONST objv[]); @@ -6428,10 +6427,6 @@ */ fprintf(stderr, "call next instead of unknown %s.%s \n", objectName(cscPtr->self),methodName); -#if 0 - result = NsfNextMethod(interp, 0, NULL); -#else - /* zzz */ { Tcl_CallFrame *framePtr1; NsfCallStackContent *cscPtr1 = CallStackGetTopFrame(interp, &framePtr1); @@ -6449,7 +6444,7 @@ result = NextSearchAndInvoke(interp, ObjStr(cscPtr1->objv[0]), cscPtr1->objc, cscPtr1->objv, cscPtr1); } -#endif + fprintf(stderr, "==> next %s csc %p returned %d unknown %d\n", methodName, cscPtr, result, rst->unknown); if (rst->unknown) { @@ -8006,43 +8001,36 @@ objectName(object), *methodNamePtr, objc, useCallstackObjs,framePtr);*/ - if (objc < 2) { + if (objc > -1) { /* - * no arguments were provided + * We have arguments. We hve to construct an argument vector with + * the first argument as the method name. */ - if (cscPtr->objv) { - nobjv = cscPtr->objv; - nobjc = cscPtr->objc; - } else { - nobjc = Tcl_CallFrame_objc(framePtr); - nobjv = (Tcl_Obj **)Tcl_CallFrame_objv(framePtr); - } - } else { - /* - * We have arguments. However, we do not want to have "next" as - * the procname (objv[0]), since this can lead to report - * e.g. "next" in a forwarder using %proc. So, we replace (if - * possible) the first word with the value from the callstack. - */ - nobjc = objc; - nobjv = (Tcl_Obj **)objv; + nobjc = objc+1; + nobjv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj*)*(objc+1)); + memcpy(nobjv+1, objv, sizeof(Tcl_Obj *) * (objc)); + if (cscPtr->objv) { nobjv[0] = cscPtr->objv[0]; } else if (Tcl_CallFrame_objv(framePtr)) { nobjv[0] = Tcl_CallFrame_objv(framePtr)[0]; } INCR_REF_COUNT(nobjv[0]); /* we seem to need this here */ *decrObjv0 = 1; - } - - /* cut the flag, that no stdargs should be used, if it is there */ - if (nobjc > 1) { - CONST char *arg1String = ObjStr(nobjv[1]); - if (*arg1String == '-' && !strcmp(arg1String, "--noArgs")) { - nobjc = 1; + } else { + /* + * no arguments were provided + */ + if (cscPtr->objv) { + nobjv = cscPtr->objv; + nobjc = cscPtr->objc; + } else { + nobjc = Tcl_CallFrame_objc(framePtr); + nobjv = (Tcl_Obj **)Tcl_CallFrame_objv(framePtr); } } + *cscPtrPtr = cscPtr; *outObjc = nobjc; *outObjv = nobjv; @@ -8170,11 +8158,12 @@ /* *---------------------------------------------------------------------- - * NsfNextMethod -- + * NsfNextCmd -- * - * The function combines NextGetArguments() and - * NextSearchAndInvoke(). It is called either be the Tcl command - * "next" or internally after an unsuccessful ensemble invocation. + * nsf::next calls the next shadowed method. It might get a single + * argument which is used as argument vector for that method. If no + * argument is provided, the argument vector of the last invocation + * is used. * * Results: * Tcl return code @@ -8184,47 +8173,97 @@ * *---------------------------------------------------------------------- */ +/* +nsfCmd next NsfNextCmd { + {-argName "arguments" -required 0 -type tclobj} +} +*/ static int -NsfNextMethod(Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { +NsfNextCmd(Tcl_Interp *interp, Tcl_Obj *arguments) { + int result, decrObjv0 = 0, oc, nobjc; NsfCallStackContent *cscPtr; - int result, decrObjv0; - Tcl_Obj **nobjv; - int nobjc; CONST char *methodName; + Tcl_Obj **nobjv, **ov; - result = NextGetArguments(interp, objc, objv, &cscPtr, &methodName, &nobjc, &nobjv, &decrObjv0); + if (arguments) { + /* Arguments were provided. */ + result = Tcl_ListObjGetElements(interp, arguments, &oc, &ov); + if (result != TCL_OK) {return result;} + } else { + /* No arguments were provided. */ + oc = -1; + } + + result = NextGetArguments(interp, oc, ov, &cscPtr, &methodName, &nobjc, &nobjv, &decrObjv0); if (result == TCL_OK) { result = NextSearchAndInvoke(interp, methodName, nobjc, nobjv, cscPtr); } if (decrObjv0) { INCR_REF_COUNT(nobjv[0]); + ckfree((char *)nobjv); } + if (result == TCL_ERROR && RUNTIME_STATE(interp)->unknown) { + fprintf(stderr, "don't report unknown error\n"); + /* + * Don't report "unknown" errors via next. + */ + result = TCL_OK; + } return result; } +/* + *---------------------------------------------------------------------- + * NsfNextObjCmd -- + * + * nsf::xotclnext is for backwards compatibility to the next + * implementation in XOTcl. It receives an argument vector which + * is used for the invocation. if no argument vector is provided, + * the argument vector of the last invocation is used. If the + * argument vector starts with "--noArgs", then no arguments are + * passed to the shadowed method. + * + * TODO: On the longer range, this function should go into an external + * library (e.g. XOTcl compatibility library) + * + * Results: + * Tcl return code + * + * Side effects: + * The invoked method might produce side effects + * + *---------------------------------------------------------------------- + */ int NsfNextObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { - int result; -#if 1 + int result, decrObjv0, nobjc; NsfCallStackContent *cscPtr; - int decrObjv0, nobjc; - Tcl_Obj **nobjv; CONST char *methodName; + Tcl_Obj **nobjv; - result = NextGetArguments(interp, objc, objv, &cscPtr, &methodName, &nobjc, &nobjv, &decrObjv0); + if (objc < 2) { + /* No arguments were provided */ + objc = 0; + } else { + /* in case --noargs is used, remove the flag and provide an empty argument list */ + CONST char *arg1String = ObjStr(objv[1]); + if (*arg1String == '-' && !strcmp(arg1String, "--noArgs")) { + objc = 1; + } + } + + result = NextGetArguments(interp, objc-1, &objv[1], &cscPtr, &methodName, &nobjc, &nobjv, &decrObjv0); if (result == TCL_OK) { result = NextSearchAndInvoke(interp, methodName, nobjc, nobjv, cscPtr); } if (decrObjv0) { INCR_REF_COUNT(nobjv[0]); + ckfree((char *)nobjv); } -#else - result = NsfNextMethod(interp, objc, objv); -#endif if (result == TCL_ERROR && RUNTIME_STATE(interp)->unknown) { fprintf(stderr, "don't report unknown error\n"); /* @@ -12369,13 +12408,13 @@ } /* -nsfCmd namespace_copycmds NsfNSCopyCmds { +nsfCmd namespace_copycmds NsfNSCopyCmdsCmd { {-argName "fromNs" -required 1 -type tclobj} {-argName "toNs" -required 1 -type tclobj} } */ static int -NsfNSCopyCmds(Tcl_Interp *interp, Tcl_Obj *fromNs, Tcl_Obj *toNs) { +NsfNSCopyCmdsCmd(Tcl_Interp *interp, Tcl_Obj *fromNs, Tcl_Obj *toNs) { Tcl_Command cmd; Tcl_Obj *newFullCmdName, *oldFullCmdName; CONST char *newName, *oldName, *name; @@ -12577,7 +12616,7 @@ } */ static int -NsfNSCopyVars(Tcl_Interp *interp, Tcl_Obj *fromNs, Tcl_Obj *toNs) { +NsfNSCopyVarsCmd(Tcl_Interp *interp, Tcl_Obj *fromNs, Tcl_Obj *toNs) { Tcl_Namespace *fromNsPtr, *toNsPtr; Var *varPtr = NULL; Tcl_HashSearch hSrch; @@ -15745,7 +15784,7 @@ #ifdef NSF_BYTECODE instructions[INST_NEXT].cmdPtr = (Command *) #endif - Tcl_CreateObjCommand(interp, "::nsf::next", NsfNextObjCmd, 0, 0); + Tcl_CreateObjCommand(interp, "::nsf::xotclnext", NsfNextObjCmd, 0, 0); #ifdef NSF_BYTECODE instructions[INST_SELF].cmdPtr = (Command *)Tcl_FindCommand(interp, "::nsf::current", 0, 0); #endif Index: generic/tclAPI.h =================================================================== diff -u -r38f8651fe4c101ee7ad98aa46bcadc32459bfdc7 -r8e08d180ae5161c0ef4410ba3fda6b4de613a391 --- generic/tclAPI.h (.../tclAPI.h) (revision 38f8651fe4c101ee7ad98aa46bcadc32459bfdc7) +++ generic/tclAPI.h (.../tclAPI.h) (revision 8e08d180ae5161c0ef4410ba3fda6b4de613a391) @@ -173,8 +173,9 @@ static int NsfMethodCmdStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv []); static int NsfMethodPropertyCmdStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv []); static int NsfMyCmdStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv []); -static int NsfNSCopyCmdsStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv []); -static int NsfNSCopyVarsStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv []); +static int NsfNSCopyCmdsCmdStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv []); +static int NsfNSCopyVarsCmdStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv []); +static int NsfNextCmdStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv []); static int NsfQualifyObjCmdStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv []); static int NsfRelationCmdStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv []); static int NsfSetVarCmdStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv []); @@ -253,8 +254,9 @@ static int NsfMethodCmd(Tcl_Interp *interp, NsfObject *object, int withInner_namespace, int withPer_object, int withPublic, Tcl_Obj *name, Tcl_Obj *args, Tcl_Obj *body, Tcl_Obj *withPrecondition, Tcl_Obj *withPostcondition); static int NsfMethodPropertyCmd(Tcl_Interp *interp, NsfObject *object, int withPer_object, Tcl_Obj *methodName, int methodproperty, Tcl_Obj *value); static int NsfMyCmd(Tcl_Interp *interp, int withLocal, Tcl_Obj *method, int nobjc, Tcl_Obj *CONST nobjv[]); -static int NsfNSCopyCmds(Tcl_Interp *interp, Tcl_Obj *fromNs, Tcl_Obj *toNs); -static int NsfNSCopyVars(Tcl_Interp *interp, Tcl_Obj *fromNs, Tcl_Obj *toNs); +static int NsfNSCopyCmdsCmd(Tcl_Interp *interp, Tcl_Obj *fromNs, Tcl_Obj *toNs); +static int NsfNSCopyVarsCmd(Tcl_Interp *interp, Tcl_Obj *fromNs, Tcl_Obj *toNs); +static int NsfNextCmd(Tcl_Interp *interp, Tcl_Obj *arguments); static int NsfQualifyObjCmd(Tcl_Interp *interp, Tcl_Obj *name); static int NsfRelationCmd(Tcl_Interp *interp, NsfObject *object, int relationtype, Tcl_Obj *value); static int NsfSetVarCmd(Tcl_Interp *interp, NsfObject *object, Tcl_Obj *variable, Tcl_Obj *value); @@ -334,8 +336,9 @@ NsfMethodCmdIdx, NsfMethodPropertyCmdIdx, NsfMyCmdIdx, - NsfNSCopyCmdsIdx, - NsfNSCopyVarsIdx, + NsfNSCopyCmdsCmdIdx, + NsfNSCopyVarsCmdIdx, + NsfNextCmdIdx, NsfQualifyObjCmdIdx, NsfRelationCmdIdx, NsfSetVarCmdIdx, @@ -1184,44 +1187,62 @@ } static int -NsfNSCopyCmdsStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { +NsfNSCopyCmdsCmdStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { ParseContext pc; if (ArgumentParse(interp, objc, objv, NULL, objv[0], - method_definitions[NsfNSCopyCmdsIdx].paramDefs, - method_definitions[NsfNSCopyCmdsIdx].nrParameters, 1, + method_definitions[NsfNSCopyCmdsCmdIdx].paramDefs, + method_definitions[NsfNSCopyCmdsCmdIdx].nrParameters, 1, &pc) != TCL_OK) { return TCL_ERROR; } else { Tcl_Obj *fromNs = (Tcl_Obj *)pc.clientData[0]; Tcl_Obj *toNs = (Tcl_Obj *)pc.clientData[1]; ParseContextRelease(&pc); - return NsfNSCopyCmds(interp, fromNs, toNs); + return NsfNSCopyCmdsCmd(interp, fromNs, toNs); } } static int -NsfNSCopyVarsStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { +NsfNSCopyVarsCmdStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { ParseContext pc; if (ArgumentParse(interp, objc, objv, NULL, objv[0], - method_definitions[NsfNSCopyVarsIdx].paramDefs, - method_definitions[NsfNSCopyVarsIdx].nrParameters, 1, + method_definitions[NsfNSCopyVarsCmdIdx].paramDefs, + method_definitions[NsfNSCopyVarsCmdIdx].nrParameters, 1, &pc) != TCL_OK) { return TCL_ERROR; } else { Tcl_Obj *fromNs = (Tcl_Obj *)pc.clientData[0]; Tcl_Obj *toNs = (Tcl_Obj *)pc.clientData[1]; ParseContextRelease(&pc); - return NsfNSCopyVars(interp, fromNs, toNs); + return NsfNSCopyVarsCmd(interp, fromNs, toNs); } } static int +NsfNextCmdStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { + ParseContext pc; + + if (ArgumentParse(interp, objc, objv, NULL, objv[0], + method_definitions[NsfNextCmdIdx].paramDefs, + method_definitions[NsfNextCmdIdx].nrParameters, 1, + &pc) != TCL_OK) { + return TCL_ERROR; + } else { + Tcl_Obj *arguments = (Tcl_Obj *)pc.clientData[0]; + + ParseContextRelease(&pc); + return NsfNextCmd(interp, arguments); + + } +} + +static int NsfQualifyObjCmdStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { ParseContext pc; @@ -2132,15 +2153,18 @@ {"method", 1, 0, ConvertToTclobj}, {"args", 0, 0, ConvertToNothing}} }, -{"::nsf::namespace_copycmds", NsfNSCopyCmdsStub, 2, { +{"::nsf::nscopycmds", NsfNSCopyCmdsCmdStub, 2, { {"fromNs", 1, 0, ConvertToTclobj}, {"toNs", 1, 0, ConvertToTclobj}} }, -{"::nsf::namespace_copyvars", NsfNSCopyVarsStub, 2, { +{"::nsf::nscopyvars", NsfNSCopyVarsCmdStub, 2, { {"fromNs", 1, 0, ConvertToTclobj}, {"toNs", 1, 0, ConvertToTclobj}} }, -{"::nsf::__qualify", NsfQualifyObjCmdStub, 1, { +{"::nsf::next", NsfNextCmdStub, 1, { + {"arguments", 0, 0, ConvertToTclobj}} +}, +{"::nsf::qualify", NsfQualifyObjCmdStub, 1, { {"name", 1, 0, ConvertToTclobj}} }, {"::nsf::relation", NsfRelationCmdStub, 3, { Index: library/nx/nx.tcl =================================================================== diff -u -r8d13fd583c573bffbc4b627edc74c608bcb71845 -r8e08d180ae5161c0ef4410ba3fda6b4de613a391 --- library/nx/nx.tcl (.../nx.tcl) (revision 8d13fd583c573bffbc4b627edc74c608bcb71845) +++ library/nx/nx.tcl (.../nx.tcl) (revision 8e08d180ae5161c0ef4410ba3fda6b4de613a391) @@ -1263,7 +1263,7 @@ if {![::nsf::isobject $object]} { $withclass create $object } - ::nsf::next -childof $object {*}$args + ::nsf::next [list -childof $object {*}$args] } } } @@ -1345,8 +1345,8 @@ } :method copyNSVarsAndCmds {orig dest} { - ::nsf::namespace_copyvars $orig $dest - ::nsf::namespace_copycmds $orig $dest + ::nsf::nscopyvars $orig $dest + ::nsf::nscopycmds $orig $dest } # construct destination obj name from old qualified ns name Index: library/xotcl/library/xotcl2.tcl =================================================================== diff -u -rdb040438a3c030830d17aff502ca7bff91eba9b7 -r8e08d180ae5161c0ef4410ba3fda6b4de613a391 --- library/xotcl/library/xotcl2.tcl (.../xotcl2.tcl) (revision db040438a3c030830d17aff502ca7bff91eba9b7) +++ library/xotcl/library/xotcl2.tcl (.../xotcl2.tcl) (revision 8e08d180ae5161c0ef4410ba3fda6b4de613a391) @@ -43,8 +43,9 @@ # # get frequenly used primitiva into the ::xotcl namespace # - namespace import ::nsf::configure ::nsf::my ::nsf::next ::nsf::finalize ::nsf::interp + namespace import ::nsf::configure ::nsf::my ::nsf::finalize ::nsf::interp namespace import ::nsf::alias ::nsf::is ::nsf::relation + interp alias {} ::xotcl::next {} ::nsf::xotclnext #namespace import ::nx::Attribute # if we do this, "::xotcl::Class create Role -superclass Attribute" will fail. Index: tests/returns.tcl =================================================================== diff -u -rf93a860bacabe371e1f01bd3f3841015c6b14a21 -r8e08d180ae5161c0ef4410ba3fda6b4de613a391 --- tests/returns.tcl (.../returns.tcl) (revision f93a860bacabe371e1f01bd3f3841015c6b14a21) +++ tests/returns.tcl (.../returns.tcl) (revision 8e08d180ae5161c0ef4410ba3fda6b4de613a391) @@ -151,7 +151,7 @@ # ::nsf::configure checkresults false -Test parameter count 10000 +Test parameter count 1000 Test case int-returns-nocheck { nx::Class create C { # scripted method without paramdefs @@ -176,7 +176,7 @@ ? {c1 bar-nok 1 2} a ? {c1 incr x} 1 - ? {c1 incr x} 10002 + ? {c1 incr x} 1002 ? {c1 lappend l e1} e1