Index: generic/nsf.c =================================================================== diff -u -rfce5c6b5a1c71088660c2d1335ac9752afb7193c -rebbef5d4096b8d73e42fd8242998380887a0f202 --- generic/nsf.c (.../nsf.c) (revision fce5c6b5a1c71088660c2d1335ac9752afb7193c) +++ generic/nsf.c (.../nsf.c) (revision ebbef5d4096b8d73e42fd8242998380887a0f202) @@ -4306,6 +4306,7 @@ assert(methodName); if (framePtr) { + fprintf(stderr,"---- NsfMethodNamePath starting frame %p\n", framePtr); Tcl_ListObjAppendList(interp, resultObj, CallStackMethodPath(interp, framePtr)); } @@ -12521,8 +12522,8 @@ Tcl_CallFrame *framePtr1; NsfCallStackContent *cscPtr1 = CallStackGetTopFrame(interp, &framePtr1); - /*fprintf(stderr, "call next instead of unknown %s.%s \n", - ObjectName(cscPtr->self), methodName);*/ + fprintf(stderr, "call next instead of unknown %s.%s methodName %p cscPtr1 %p\n", + ObjectName(cscPtr->self), methodName, framePtr1, cscPtr1); assert(cscPtr1); if ((cscPtr1->frameType & NSF_CSC_TYPE_ENSEMBLE)) { @@ -12544,11 +12545,11 @@ cscPtr1->objc, cscPtr1->objv, cscPtr1, 0); - /*fprintf(stderr, "==> next %s.%s (obj %s) csc %p returned %d unknown %d\n", - ObjectName(self), methodName, ObjectName(object), cscPtr, result, - RUNTIME_STATE(interp)->unknown); */ + fprintf(stderr, "==> next %s.%s (obj %s) csc %p returned %d unknown %d framePtr1 %p cscPtr1 %p\n", + ObjectName(callerSelf), methodName, ObjectName(invokedObject), cscPtr, result, + RUNTIME_STATE(interp)->unknown, framePtr1, cscPtr1); - if (RUNTIME_STATE(interp)->unknown) { + if (RUNTIME_STATE(interp)->unknown /*&& ((cscPtr1->flags & NSF_CSC_CALL_IS_ENSEMBLE) == 0 || (cscPtr1->flags & NSF_CSC_IMMEDIATE) == 0)*/ /*&& (cscPtr->frameType & NSF_CSC_TYPE_ENSEMBLE) == 0*/) { /* * Unknown handling: We trigger a dispatch to an unknown method. The * appropriate unknown handler is either provided for the current @@ -12568,9 +12569,11 @@ Tcl_ListObjAppendList(interp, callInfoObj, methodPathObj); Tcl_ListObjAppendElement(interp, callInfoObj, objv[1]); - /* fprintf(stderr, "DispatchUnknownMethod is called with callinfo <%s> \n", ObjStr(callInfoObj)); */ + fprintf(stderr, "DispatchUnknownMethod is called with callinfo <%s> startFrame %p lastEl <%s> methodPathObj <%s>\n", ObjStr(callInfoObj), framePtr, MethodName(objv[0]), ObjStr(methodPathObj)); + NsfShowStack(interp); result = DispatchUnknownMethod(interp, invokedObject, objc-1, objv+1, callInfoObj, objv[1], NSF_CM_NO_OBJECT_METHOD|NSF_CSC_IMMEDIATE); + RUNTIME_STATE(interp)->unknown = 0; DECR_REF_COUNT(callInfoObj); } } @@ -17472,8 +17475,8 @@ result = NextSearchMethod(object, interp, cscPtr, &cl, &methodName, &cmd, &isMixinEntry, &isFilterEntry, &endOfFilterChain, ¤tCmd); - /*fprintf(stderr, "NEXT search on %s.%s cl %p cmd %p endOfFilterChain %d result %d IS OK %d\n", - ObjectName(object), methodName, cl, cmd, endOfFilterChain, result, (result == TCL_OK));*/ + fprintf(stderr, "NEXT search on %s.%s cl %p cmd %p endOfFilterChain %d result %d IS OK %d isMixinEntry %d\n", + ObjectName(object), methodName, cl, cmd, endOfFilterChain, result, (result == TCL_OK), isMixinEntry); if (unlikely(result != TCL_OK)) { goto next_search_and_invoke_cleanup; @@ -17555,6 +17558,7 @@ #endif } else if (likely(result == TCL_OK)) { NsfCallStackContent *topCscPtr; + Tcl_CallFrame *framePtr; int isLeafNext; /* @@ -17574,17 +17578,29 @@ * for dispatching to unknown. */ - topCscPtr = CallStackGetTopFrame(interp, NULL); + /* frameType 0000 flags 000104 */ + /* frameType 0000 flags 000104 */ + + topCscPtr = CallStackGetTopFrame(interp, NULL) ; + /*if ((cscPtr->flags & NSF_CSC_CALL_IS_ENSEMBLE)) { + topCscPtr = NsfCallStackFindLastInvocation(interp, 0, NULL); + }*/ + assert(topCscPtr); /* case 2 */ - isLeafNext = (cscPtr != topCscPtr) && (topCscPtr->frameType & NSF_CSC_TYPE_ENSEMBLE) && + isLeafNext = topCscPtr && (cscPtr != topCscPtr) && (topCscPtr->frameType & NSF_CSC_TYPE_ENSEMBLE) && (topCscPtr->flags & NSF_CSC_CALL_IS_ENSEMBLE) == 0; + NsfShowStack(interp); + fprintf(stderr, "!!!!!! isLeafNext --- %d cscPtr %p topCscPtr %p NSF_CSC_TYPE_ENSEMBLE %d NSF_CSC_CALL_IS_ENSEMBLE %d last-leaf (non-next) frame %p\n", isLeafNext, cscPtr, + topCscPtr, topCscPtr ? (topCscPtr->frameType & NSF_CSC_TYPE_ENSEMBLE) != 0 : NULL, + topCscPtr ? (topCscPtr->flags & NSF_CSC_CALL_IS_ENSEMBLE) != 0 : NULL, NsfCallStackFindLastInvocation(interp, 0, NULL)); + rst->unknown = /* case 1 */ endOfFilterChain || /* case 3 */ (!isLeafNext && (cscPtr->flags & NSF_CSC_CALL_IS_ENSEMBLE)); - /*fprintf(stderr, "******** setting unknown to %d\n", rst->unknown );*/ + fprintf(stderr, "******** setting unknown to %d\n", rst->unknown ); } next_search_and_invoke_cleanup: Index: library/nx/nx.tcl =================================================================== diff -u -r14dd62afced4b677c75a9ac6e3bc71497c6c746d -rebbef5d4096b8d73e42fd8242998380887a0f202 --- library/nx/nx.tcl (.../nx.tcl) (revision 14dd62afced4b677c75a9ac6e3bc71497c6c746d) +++ library/nx/nx.tcl (.../nx.tcl) (revision ebbef5d4096b8d73e42fd8242998380887a0f202) @@ -471,6 +471,7 @@ } :protected method unknown {callInfo args} { set path [lrange $callInfo 1 end-1] + ## set path $callInfo set m [lindex $callInfo end] set obj [lindex $callInfo 0] ::nsf::__db_show_stack @@ -840,7 +841,7 @@ } ###################################################################### - # Define "info info" and "info unknown" + # Define "info info" ###################################################################### proc ::nx::internal::infoOptions {obj} { @@ -853,10 +854,10 @@ return "valid options are: [join [lsort $methods] {, }]" } - Object protected method "info unknown" {method obj:object args} { - return -code error \ - "[::nsf::self] unknown info option \"$method\"; [$obj info info]" - } + # Object protected method "info unknown" {method obj:object args} { + # return -code error \ + # "[::nsf::self] unknown info option \"$method\"; [$obj info info]" + # } Object method "info info" {} {::nx::internal::infoOptions ::nx::Object::slot::__info} Class method "info info" {} {::nx::internal::infoOptions ::nx::Class::slot::__info} Index: tests/submethods.test =================================================================== diff -u -r0f881e4bc45e927c8d84c1b1b468ef7537cb9b03 -rebbef5d4096b8d73e42fd8242998380887a0f202 --- tests/submethods.test (.../submethods.test) (revision 0f881e4bc45e927c8d84c1b1b468ef7537cb9b03) +++ tests/submethods.test (.../submethods.test) (revision ebbef5d4096b8d73e42fd8242998380887a0f202) @@ -228,10 +228,10 @@ # call a submethod, which is only defined in the mixin, and which # does a next (which should not complain) ? {o1 info has something better} better - # yet another missing case - ? {o1 info has something wrong} \ - {unable to dispatch sub-method "wrong" of ::o1 info has something; valid are: info has something better, info has something else, info has something path} + + # ? {o1 info has something wrong} \ + # {unable to dispatch sub-method "wrong" of ::o1 info has something; valid are: info has something better, info has something else, info has something path} # call defaultcmds on ensembles ? {lsort [o1 info has something]} "valid submethods of ::o1 info has something: better else path" @@ -367,7 +367,9 @@ incr :x; next; # a "filter next" } :object filters set intercept + puts stderr ========== :FOO bar + exit # Rationale: A call count > 2 would indicate that the leaf next # triggers a further call into filter ... ? [list set _ ${:x}] 2