Index: TODO =================================================================== diff -u -r1a05667da4190fc231eb30304adc739d38202bf2 -r9fa2b6fcc1348e36c652d68e06077c43fd14d92b --- TODO (.../TODO) (revision 1a05667da4190fc231eb30304adc739d38202bf2) +++ TODO (.../TODO) (revision 9fa2b6fcc1348e36c652d68e06077c43fd14d92b) @@ -2093,6 +2093,9 @@ - serializer: updated serializer to avoid calls to "setter" - extended regression test +- fixed in bug in ensemble-next (removed colon-prefix from methodname + in next) +- extended regression test TODO: - info method definition for attributes? Index: generic/nsf.c =================================================================== diff -u -rb0d97485503d32672dd3691131ce51bdf3923881 -r9fa2b6fcc1348e36c652d68e06077c43fd14d92b --- generic/nsf.c (.../nsf.c) (revision b0d97485503d32672dd3691131ce51bdf3923881) +++ generic/nsf.c (.../nsf.c) (revision 9fa2b6fcc1348e36c652d68e06077c43fd14d92b) @@ -7013,7 +7013,7 @@ Nsf_PushFrameCsc(interp, cscPtr, framePtr); } - /*fprintf(stderr, "CmdDispatch obj %p %p %s\n", obj, methodName, methodName);*/ + /*fprintf(stderr, "CmdMethodDispatch obj %p %p %s\n", obj, methodName, methodName);*/ result = Tcl_NRCallObjProc(interp, Tcl_Command_objProc(cmdPtr), cp, objc, objv); if (cscPtr) { @@ -7138,6 +7138,7 @@ /* * 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); @@ -7153,11 +7154,9 @@ cscPtr->flags |= NSF_CSC_CALL_IS_ENSEMBLE; Nsf_PushFrameCsc(interp, cscPtr, framePtr); - /*fprintf(stderr, "save self %p %s (ns %p) object %p %s\n", - self, ObjectName(self), self->nsPtr, object, ObjectName(object));*/ if (self->nsPtr) { cmd = FindMethod(self->nsPtr, methodName); - /* fprintf(stderr, "... method %p %s csc %p\n", cmd, methodName, cscPtr); */ + /*fprintf(stderr, "... method %p %s csc %p\n", cmd, methodName, cscPtr); */ if (cmd) { /* * In order to allow next to be called on the @@ -7191,6 +7190,7 @@ { Tcl_CallFrame *framePtr1; NsfCallStackContent *cscPtr1 = CallStackGetTopFrame(interp, &framePtr1); + CONST char *nextMethodName; if ((cscPtr1->frameType & NSF_CSC_TYPE_ENSEMBLE)) { /* @@ -7203,12 +7203,21 @@ assert(cscPtr1); } - result = NextSearchAndInvoke(interp, ObjStr(cscPtr1->objv[0]), + /* + * The method name for next might be colon-prefixed. In + * these cases, we have to skip the single colon. + */ + nextMethodName = ObjStr(cscPtr1->objv[0]); + if (FOR_COLON_RESOLVER(nextMethodName)) { + nextMethodName ++; + } + + result = NextSearchAndInvoke(interp, nextMethodName, 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, rst->unknown); */ + ObjectName(self),methodName, ObjectName(object), cscPtr, result, rst->unknown);*/ if (rst->unknown) { /* * The appropriate unknown class is registered on the @@ -7589,8 +7598,8 @@ /* do we have a object-specific proc? */ if (object->nsPtr && (flags & NSF_CM_NO_OBJECT_METHOD) == 0) { cmd = FindMethod(object->nsPtr, methodName); - /* fprintf(stderr, "lookup for proc in obj %p method %s nsPtr %p => %p\n", - object, methodName, object->nsPtr, cmd);*/ + /*fprintf(stderr, "lookup for proc in obj %p method %s nsPtr %p => %p\n", + object, methodName, object->nsPtr, cmd);*/ } if (cmd == NULL) { Index: tests/submethods.test =================================================================== diff -u -r84c5ee62a46e8fab7b9cc481c87290d387baced9 -r9fa2b6fcc1348e36c652d68e06077c43fd14d92b --- tests/submethods.test (.../submethods.test) (revision 84c5ee62a46e8fab7b9cc481c87290d387baced9) +++ tests/submethods.test (.../submethods.test) (revision 9fa2b6fcc1348e36c652d68e06077c43fd14d92b) @@ -293,3 +293,47 @@ # ensemble depth 2, multiple args, same tcl-objs ? {o e1 e1 e1} {e1 e1 e1} } + +Test parameter count 1 +Test case ensemble-next-with-colon-prefix +namespace eval ::ns1 { + Object create obj { + :public method foo {} { return [:info class] } + :public method ifoo {} { [current] ::nsf::methods::object::info::lookupmethod info} + } + + ? {obj info class} ::nx::Object + ? {obj info lookup method info} ::nsf::classes::nx::Object::info + ? {obj ifoo} ::nsf::classes::nx::Object::info + + ? {obj foo} ::nx::Object + + set infolookup ::nsf::methods::object::info::lookupmethod + set infomethod ::nsf::methods::object::info::method + + ? [list obj $infolookup info] ::nsf::classes::nx::Object::info + ? [list obj $infomethod type ::nsf::classes::nx::Object::info] alias + + obj method info {} {;} + ? [list obj $infolookup info] ::ns1::obj::info + ? [list obj $infomethod type ::ns1::obj::info] scripted + ? {obj ifoo} ::ns1::obj::info + ? {obj foo} {wrong # args: should be ":info"} + + # now we overwrite the object specific method with an object + Object create obj::info + ? [list obj $infolookup info] ::ns1::obj::info + ? [list obj $infomethod type ::ns1::obj::info] object + + ? {obj ifoo} ::ns1::obj::info + # To some surprise, we can can still call info class! + # This works, since we do here an "ensemble-next" + ? {obj info class} ::nx::Object + # The ensemble-next has in case of foo the leading colon on the + # callstack (e.g. ":info"). Make sure that we can still call the + # method via ensemle-next. + ? {obj foo} ::nx::Object +} + + +