Index: TODO =================================================================== diff -u -rdedef29f68094a6083cbc91cb0803c3b1f0c0e68 -re528761906857b0f8307d5bc9b94878168234965 --- TODO (.../TODO) (revision dedef29f68094a6083cbc91cb0803c3b1f0c0e68) +++ TODO (.../TODO) (revision e528761906857b0f8307d5bc9b94878168234965) @@ -3020,8 +3020,13 @@ - new regression test file volatile.test - fix the comparison with "unknown" in residual args - (2 places marked with "//yyyy" ) +- provide backward compatibility for unknwon method (when + method contains spaces). +- some minor cleanup +- extended regression test + + TODO: - Revise callstack introspection/intercession, i.e., [current Index: generic/nsf.c =================================================================== diff -u -rdedef29f68094a6083cbc91cb0803c3b1f0c0e68 -re528761906857b0f8307d5bc9b94878168234965 --- generic/nsf.c (.../nsf.c) (revision dedef29f68094a6083cbc91cb0803c3b1f0c0e68) +++ generic/nsf.c (.../nsf.c) (revision e528761906857b0f8307d5bc9b94878168234965) @@ -8559,17 +8559,17 @@ * handler. Call data include the calling object (delegator), the * method path, and the unknown final method. */ - /*fprintf(stderr, "next calls DispatchUnknownMethod\n");*/ - Tcl_Obj *callInfoObj = Tcl_NewListObj(0,NULL); - Tcl_ListObjAppendList(interp, - callInfoObj, - object->cmdName); + Tcl_Obj *callInfoObj = Tcl_NewListObj(1, &object->cmdName); Tcl_Obj *methodPathObj = CallStackMethodPath(interp, (Tcl_CallFrame *)framePtr, Tcl_NewListObj(0, NULL)); + + /*fprintf(stderr, "next calls DispatchUnknownMethod\n");*/ Tcl_ListObjAppendList(interp, callInfoObj, methodPathObj); DECR_REF_COUNT(methodPathObj); - Tcl_ListObjAppendElement(interp,callInfoObj,objv[0]); + Tcl_ListObjAppendElement(interp, callInfoObj, objv[0]); + Tcl_ListObjAppendElement(interp, callInfoObj, objv[1]); + result = DispatchUnknownMethod(interp, self, objc-1, objv+1, callInfoObj, objv[1], NSF_CM_NO_OBJECT_METHOD|NSF_CSC_IMMEDIATE); } @@ -9283,37 +9283,34 @@ * back off and try unknown; */ int mustCopy = *(ObjStr(methodObj)) == ':'; + ALLOC_ON_STACK(Tcl_Obj*, objc+3, tov); if (callInfoObj == NULL) { - callInfoObj = Tcl_NewListObj(0,NULL); + callInfoObj = mustCopy ? Tcl_NewStringObj(methodName, -1) : methodObj; } - result = Tcl_ListObjAppendElement(interp, callInfoObj, - mustCopy ? Tcl_NewStringObj(methodName, -1) : methodObj); INCR_REF_COUNT(callInfoObj); - if (result == TCL_OK) { - ALLOC_ON_STACK(Tcl_Obj*, objc+3, tov); - - /*fprintf(stderr, "calling unknown for %s %s, flgs=%.6x,%.6x/%.6x isClass=%d %p %s objc %d\n", - ObjectName(object), ObjStr(methodObj), flags, NSF_CM_NO_UNKNOWN,NSF_CSC_CALL_NO_UNKNOWN, - NsfObjectIsClass(object), object, ObjectName(object), objc);*/ - - tov[0] = object->cmdName; - tov[1] = unknownObj; - tov[2] = callInfoObj; - if (objc>1) { - memcpy(tov + 3, objv + 1, sizeof(Tcl_Obj *) * (objc - 1)); - } - - flags &= ~NSF_CM_NO_SHIFT; - - /*fprintf(stderr, "call unknown via dispatch mustCopy %d delegator %p method %s (%s)\n", - mustCopy, delegator, ObjStr(tov[offset]), ObjStr(methodObj));*/ - - result = ObjectDispatch(object, interp, objc+2, tov, flags|NSF_CM_NO_UNKNOWN); - FREE_ON_STACK(Tcl_Obj*, tov); + /*fprintf(stderr, "calling unknown for %s %s, flgs=%.6x,%.6x/%.6x isClass=%d %p %s objc %d\n", + ObjectName(object), ObjStr(methodObj), flags, NSF_CM_NO_UNKNOWN,NSF_CSC_CALL_NO_UNKNOWN, + NsfObjectIsClass(object), object, ObjectName(object), objc);*/ + + tov[0] = object->cmdName; + tov[1] = unknownObj; + tov[2] = callInfoObj; + if (objc > 1) { + memcpy(tov + 3, objv + 1, sizeof(Tcl_Obj *) * (objc - 1)); } + + flags &= ~NSF_CM_NO_SHIFT; + + /*fprintf(stderr, "call unknown via dispatch mustCopy %d delegator %p method %s (%s)\n", + mustCopy, delegator, ObjStr(tov[offset]), ObjStr(methodObj));*/ + + result = ObjectDispatch(object, interp, objc+2, tov, flags|NSF_CM_NO_UNKNOWN); + DECR_REF_COUNT(callInfoObj); + FREE_ON_STACK(Tcl_Obj*, tov); + } else { /* no unknown called, this is the built-in unknown handler */ Tcl_Obj *tailMethodObj; if (objc > 1) { Index: tests/methods.test =================================================================== diff -u -r0585d441caad26de7a81eb2c3c07f00d3f3db256 -re528761906857b0f8307d5bc9b94878168234965 --- tests/methods.test (.../methods.test) (revision 0585d441caad26de7a81eb2c3c07f00d3f3db256) +++ tests/methods.test (.../methods.test) (revision e528761906857b0f8307d5bc9b94878168234965) @@ -645,3 +645,35 @@ ? {C info methods -path} "" } +# +# simple unknown tests; +# ensemble unknown tests are in submethods.test +# +nx::Test case test-simple-unknown { + + # + # calling unknown with a plain "method" without arguments + # + ::nx::Class create A { + :class method unknown args {? [list set _ $args] "hello"} + } + A hello + + # + # calling unknown with a plain "method" with arguments + # + ::nx::Class create B { + :class method unknown args {? [list set _ $args] "hello world"} + } + B hello world + + # + # calling unknown with a method with spaces + # + ::nx::Class create C { + :class method unknown args {? [list set _ $args] "{hello world}"} + } + C {hello world} + + +} \ No newline at end of file