Index: generic/nsf.c =================================================================== diff -u -rdcee5f2f7bac79f3fb2b966d68360cdfcef8002a -rf3127511bec503add89e7a691f33213b1999274d --- generic/nsf.c (.../nsf.c) (revision dcee5f2f7bac79f3fb2b966d68360cdfcef8002a) +++ generic/nsf.c (.../nsf.c) (revision f3127511bec503add89e7a691f33213b1999274d) @@ -8471,9 +8471,20 @@ } /* + * Make sure, that the current call is marked as an ensemble call, both + * for dispatching to the defaultmethod and for dispatching the method + * interface of the given object. Otherwise, current introspection + * specific to submethods fails (e.g., a [current methodpath] in the + * defaultmethod). + */ + cscPtr->flags |= NSF_CSC_CALL_IS_ENSEMBLE; + + /* * The client data cp is still the obj of the called method */ + /*fprintf(stderr, "ensemble dispatch %s objc %d\n", methodName, objc);*/ + if (objc < 2) { CallFrame frame, *framePtr = &frame; Nsf_PushFrameCsc(interp, cscPtr, framePtr); @@ -8486,7 +8497,6 @@ cscPtr->objc = objc; cscPtr->objv = objv; - cscPtr->flags |= NSF_CSC_CALL_IS_ENSEMBLE; Nsf_PushFrameCsc(interp, cscPtr, framePtr); if (self->nsPtr) { @@ -18168,8 +18178,7 @@ case CurrentoptionMethodpathIdx: cscPtr = CallStackGetTopFrame(interp, &framePtr); - Tcl_SetObjResult(interp, - CallStackMethodPath(interp, framePtr, Tcl_NewListObj(0, NULL))); + Tcl_SetObjResult(interp, CallStackMethodPath(interp, framePtr, Tcl_NewListObj(0, NULL))); break; case CurrentoptionClassIdx: /* class subcommand */ @@ -18223,9 +18232,31 @@ case CurrentoptionCallingmethodIdx: case CurrentoptionCallingprocIdx: - cscPtr = NsfCallStackFindLastInvocation(interp, 1, NULL); - Tcl_SetResult(interp, cscPtr ? (char *)Tcl_GetCommandName(interp, cscPtr->cmdPtr) : "", - TCL_VOLATILE); + cscPtr = NsfCallStackFindLastInvocation(interp, 1, &framePtr); + Tcl_Obj *resultObj = NsfGlobalObjs[NSF_EMPTY]; + if (cscPtr && cscPtr->cmdPtr) { + Tcl_Obj *methodNameObj = NULL; + + methodNameObj = resultObj = + Tcl_NewStringObj((char *)Tcl_GetCommandName(interp, cscPtr->cmdPtr), -1); + /* + * By checking the characteristic frame and call type pattern for "leaf" + * ensemble dispatches, we make sure that the method path is only + * reported for these cases. Otherwise, we constrain the result to the + * method name. + */ + if ((cscPtr->frameType & NSF_CSC_TYPE_ENSEMBLE) && + (cscPtr->flags & NSF_CSC_CALL_IS_COMPILE) == 0) { + resultObj = CallStackMethodPath(interp, framePtr, Tcl_NewListObj(0, NULL)); + result = Tcl_ListObjAppendElement(interp, resultObj, methodNameObj); + if (result != TCL_OK) { + DECR_REF_COUNT(resultObj); + DECR_REF_COUNT(methodNameObj); + break; + } + } + } + Tcl_SetObjResult(interp, resultObj); break; case CurrentoptionCallingclassIdx: Index: generic/nsfStack.c =================================================================== diff -u -rab5097b110d11556bd7b32faace2fd6cae23b6e5 -rf3127511bec503add89e7a691f33213b1999274d --- generic/nsfStack.c (.../nsfStack.c) (revision ab5097b110d11556bd7b32faace2fd6cae23b6e5) +++ generic/nsfStack.c (.../nsfStack.c) (revision f3127511bec503add89e7a691f33213b1999274d) @@ -618,6 +618,14 @@ (cscPtr->flags & NSF_CSC_CALL_IS_ENSEMBLE) != 0, (cscPtr->frameType & NSF_CSC_TYPE_INACTIVE) != 0);*/ + /* + * The "ensemble" call type, we find applied to all intermediate and leaf + * ensemble frames. By filtering according to the ensemble call type, we + * effectively omit leaf ensemble and non-ensemble frames from being + * reported. + */ + if ((cscPtr->flags & NSF_CSC_CALL_IS_ENSEMBLE) == 0) break; + /* Do not record any INACTIVE frames in the method path */ if ((cscPtr->frameType & NSF_CSC_TYPE_INACTIVE)) continue; @@ -628,11 +636,10 @@ /* * The "root" frame in a callstack branch resulting from an ensemble * dispatch is not typed as an NSF_CSC_TYPE_ENSEMBLE frame, the call type - * /is/ NSF_CSC_CALL_IS_ENSEMBLE. + * /is/ NSF_CSC_CALL_IS_ENSEMBLE (as checked above). */ - if ((cscPtr->frameType & NSF_CSC_TYPE_ENSEMBLE) == 0 && - (cscPtr->flags & NSF_CSC_CALL_IS_ENSEMBLE)) break; + if ((cscPtr->frameType & NSF_CSC_TYPE_ENSEMBLE) == 0) break; } /* Index: library/nx/nx.tcl =================================================================== diff -u -rfe643dd6330cf3deb036335f20ce4113a2e2aee3 -rf3127511bec503add89e7a691f33213b1999274d --- library/nx/nx.tcl (.../nx.tcl) (revision fe643dd6330cf3deb036335f20ce4113a2e2aee3) +++ library/nx/nx.tcl (.../nx.tcl) (revision f3127511bec503add89e7a691f33213b1999274d) @@ -501,8 +501,8 @@ } :protected method defaultmethod {} { - set obj [uplevel {self}] - set path [current methodpath] + set obj [uplevel {::nsf::current}] + set path [::nsf::current methodpath] set l [string length $path] set submethods [$obj ::nsf::methods::object::info::lookupmethods -path "$path *"] foreach sm $submethods {set results([lindex [string range $sm $l+1 end] 0]) 1} Index: tests/disposition.test =================================================================== diff -u -r1b0a690f760447d8fc63aeded3e62c723e592c64 -rf3127511bec503add89e7a691f33213b1999274d --- tests/disposition.test (.../disposition.test) (revision 1b0a690f760447d8fc63aeded3e62c723e592c64) +++ tests/disposition.test (.../disposition.test) (revision f3127511bec503add89e7a691f33213b1999274d) @@ -1124,23 +1124,26 @@ } ::proc foo {} { - error [::nsf::current]-[::nsf::current methodpath] + error [::nsf::current]-[::nsf::current methodpath]-[::nsf::current method] } + # + # TODO: Currently, [current method] resolves to the name of the + # aliased, not the alias cmd. So, we do not have "alias + # transparency". Revise? + # ::nsf::method::alias C FOO ::foo - ? {[C create c] FOO} "::c-FOO" + ? {[C create c] FOO} "::c--foo" C setObjectParams [list [list FOO:alias,noarg ""]] - # UNPATCHED: - # ? {C create c} "::c-{} FOO" - ? {C create c} "::c-FOO" + ? {C create c} "::c--foo" C public method "show me" {} { - set :msg [::nsf::current]-[::nsf::current methodpath] + set :msg [::nsf::current]-[::nsf::current methodpath]-[::nsf::current method] } C setObjectParams [list -show:alias] ? {[C create c -show me] eval {info exists :msg}} 1 # UNPATCHED: # ? {[C create c -show me] eval {set :msg}} "::c-{} show" - ? {[C create c -show me] eval {set :msg}} "::c-show" - + ? {[C create c -show me] eval {set :msg}} "::c-show-me" + exit # # ... with mixin indirection # Index: tests/submethods.test =================================================================== diff -u -r3ab1e160c5e9832a4d69c6f999a63d9706c4c956 -rf3127511bec503add89e7a691f33213b1999274d --- tests/submethods.test (.../submethods.test) (revision 3ab1e160c5e9832a4d69c6f999a63d9706c4c956) +++ tests/submethods.test (.../submethods.test) (revision f3127511bec503add89e7a691f33213b1999274d) @@ -375,10 +375,58 @@ o mixin ::M1 ? {o FOO foo} -::o-::M1-::o-- - + + o mixin {} + C mixin {} + # - # TODO: [current callingmethod], [current calledmethod] + # limit [current methodpath] to collect only ensemble methods? # + + o eval { + :public method faz {} {return [concat [current methodpath] [current method]]} + ? [list set _ [:faz]] "faz" + } + + # + # [current callingmethod] & [current callingclass] + # + + o eval { + set body {? [list set _ [:bar]] [current class]-[current]-[concat [current methodpath] [current method]]} + :public method "FOO foo" {} $body + :public method "BAR BUU boo" {} $body + :public method baz {} $body + + :method bar {} { + return "[current callingclass]-[current callingobject]-[current callingmethod]" + } + + :FOO foo + :BAR BUU boo + :baz + } + + C eval { + set body {? [list set _ [:bar]] [current class]-[current]-[concat [current methodpath] [current method]]} + :public method "FOO foo" {} $body + :public method "BAR BUU boo" {} $body + :public method baz {} $body + + :method bar {} { + return "[current callingclass]-[current callingobject]-[current callingmethod]" + } + + set c [:new] + $c FOO foo + $c BAR BUU boo + $c baz + } + + # + # [current calledmethod] + # + }