Index: Makefile.in =================================================================== diff -u -rd1ed482555d4d28dbb41fb9ca2723eabb5e01221 -r2510d1890d89e9b98cfdbf2106c1d4e50c9dba6a --- Makefile.in (.../Makefile.in) (revision d1ed482555d4d28dbb41fb9ca2723eabb5e01221) +++ Makefile.in (.../Makefile.in) (revision 2510d1890d89e9b98cfdbf2106c1d4e50c9dba6a) @@ -394,7 +394,7 @@ $(TCLSH) $(src_test_dir_native)/protected.tcl -libdir $(PLATFORM_DIR) $(TESTFLAGS) $(TCLSH) $(src_test_dir_native)/forwardtest.tcl -libdir $(PLATFORM_DIR) $(TESTFLAGS) $(TCLSH) $(src_test_dir_native)/mixinoftest.tcl -libdir $(PLATFORM_DIR) $(TESTFLAGS) - $(TCLSH) $(src_test_dir_native)/coroutines.tcl -libdir $(PLATFORM_DIR) $(TESTFLAGS) + $(TCLSH) $(src_test_dir_native)/tcl86.tcl -libdir $(PLATFORM_DIR) $(TESTFLAGS) test-xotcl: $(TCLSH_PROG) $(TCLSH) $(xotcl_src_test_dir)/testo.xotcl -libdir $(PLATFORM_DIR) $(TESTFLAGS) Index: TODO =================================================================== diff -u -rde4caf575ba6925970b850e327bbe2df9ab83060 -r2510d1890d89e9b98cfdbf2106c1d4e50c9dba6a --- TODO (.../TODO) (revision de4caf575ba6925970b850e327bbe2df9ab83060) +++ TODO (.../TODO) (revision 2510d1890d89e9b98cfdbf2106c1d4e50c9dba6a) @@ -1463,8 +1463,18 @@ - some cleanup concerning TCL_STACK_ALLOC_TRACE - make ::nsf::next and ::xotcl::next NRE-enabled +- make coloncmd are NRE-enabled +- make every internal method invokation (NsfCallMethodWithArgs() + and CallMethod()) NRE-configurable +- use "Nsf" prefix for global vars to avoid potential conflicts +- minimal support for sane-NRE patch +- failed so far to make my NRE-enabled +- new compile-flag for tracing: NRE_CALLBACK_TRACE +- extended regression test (added test for 8.6 apply) +- renamed tests/coroutines.tcl to tests/tcl86.tcl + TODO: -- check coloncmd and my for NRE-enabling +- check my for NRE-enabling - major coro cleanup, when working - extend coro regression test Index: generic/nsf.c =================================================================== diff -u -re3b213ee799fd3a7ee97d7059e7ed34a0459579c -r2510d1890d89e9b98cfdbf2106c1d4e50c9dba6a --- generic/nsf.c (.../nsf.c) (revision e3b213ee799fd3a7ee97d7059e7ed34a0459579c) +++ generic/nsf.c (.../nsf.c) (revision 2510d1890d89e9b98cfdbf2106c1d4e50c9dba6a) @@ -156,7 +156,10 @@ * Tcl_Obj Types for Next Scripting Objects */ -static Tcl_ObjType CONST86 *byteCodeType = NULL, *tclCmdNameType = NULL, *listType = NULL; +static Tcl_ObjType CONST86 + *Nsf_OT_byteCodeType = NULL, + *Nsf_OT_tclCmdNameType = NULL, + *Nsf_OT_listType = NULL; /* * Function prototypes @@ -399,23 +402,8 @@ {int i; fprintf(stderr, "\t CALL: %s ", ObjStr(methodObj));for(i=0; itypePtr; - if (cmdType == tclCmdNameType) { + if (cmdType == Nsf_OT_tclCmdNameType) { Tcl_Command cmd = Tcl_GetCommandFromObj(interp, objPtr); if (cmd) { NsfObject *object = NsfGetObjectFromCmdPtr(cmd); @@ -741,7 +729,7 @@ className(baseClass), ObjStr(nameObj));*/ result = CallMethod((ClientData) baseClass, interp, methodObj, - 3, &nameObj, NSF_CM_NO_PROTECT); + 3, &nameObj, NSF_CM_NO_PROTECT|NSF_CM_IMMEDIATE); if (result == TCL_OK) { result = GetClassFromObj(interp, objPtr, cl, NULL); } @@ -2584,6 +2572,8 @@ ALLOC_NAME_NS(dsPtr, ns->fullName, methodName); newCmd = Tcl_CreateObjCommand(interp, Tcl_DStringValue(dsPtr), proc, clientData, dp); + //newCmd = Tcl_NRCreateCommand(interp, Tcl_DStringValue(dsPtr), proc, proc, clientData, dp); + if (flags) { ((Command *) newCmd)->flags |= flags; } @@ -2611,6 +2601,7 @@ ALLOC_NAME_NS(dsPtr, cl->nsPtr->fullName, methodName); newCmd = Tcl_CreateObjCommand(interp, Tcl_DStringValue(dsPtr), proc, clientData, dp); + //newCmd = Tcl_NRCreateCommand(interp, Tcl_DStringValue(dsPtr), proc, proc, clientData, dp); if (flags) { ((Command *) newCmd)->flags |= flags; @@ -5506,7 +5497,7 @@ Tcl_Obj *bodyPtr = procPtr->bodyPtr; Namespace *nsPtr = procPtr->cmdPtr->nsPtr; - if (bodyPtr->typePtr == byteCodeType) { + if (bodyPtr->typePtr == Nsf_OT_byteCodeType) { # if defined(HAVE_TCL_COMPILE_H) ByteCode *codePtr; Interp *iPtr = (Interp *) interp; @@ -6062,7 +6053,7 @@ /*fprintf(stderr, "CALL TclNRInterpProcCore %s method '%s'\n", objectName(object), ObjStr(objv[0]));*/ Tcl_NRAddCallback(interp, ProcMethodDispatchFinalize, - releasePc ? pcPtr : NULL, cscPtr, methodName, NULL); + releasePc ? pcPtr : NULL, cscPtr, (ClientData)methodName, NULL); cscPtr->callType |= NSF_CSC_CALL_IS_NRE; result = TclNRInterpProcCore(interp, objv[0], 1, &MakeProcError); #endif @@ -6290,7 +6281,7 @@ if (CallDirectly(interp, object, NSF_o_destroy_idx, &methodObj)) { result = NsfODestroyMethod(interp, object); } else { - result = CallMethod(object, interp, methodObj, 2, 0, flags); + result = CallMethod(object, interp, methodObj, 2, 0, NSF_CM_IMMEDIATE|flags); } if (result != TCL_OK) { @@ -6385,8 +6376,7 @@ NsfCallStackContent *cscPtr, CONST char *methodName, int flags) { - // not needed when no client data - //CscInit(cscPtr, object, cl, cmd, frameType); + // TODO: cscPtr not needed when no client data // do we need to split cscPtr up? Tcl_Command cmd = cscPtr->cmdPtr; NsfObject *object = cscPtr->self; @@ -6415,20 +6405,19 @@ #if defined(NRE) if ((flags & NSF_CM_IMMEDIATE)) { +# if defined(NRE_CALLBACK_TRACE) fprintf(stderr, ".... manual run callbacks rootPtr = %p, result %d methodName %s.%s\n", rootPtr, result, cscPtr->cl?className(cscPtr->cl):"NULL", methodName); - - /* TODO: we should need this only for scriped stuff; maybe it can harm otherwise for coros */ - result = TclNRRunCallbacks(interp, result, rootPtr, 0); +# endif + result = NsfNRRunCallbacks(interp, result, rootPtr); } else { +# if defined(NRE_CALLBACK_TRACE) fprintf(stderr, ".... don't run callbacks rootPtr = %p, result %d methodName %s.%s\n", rootPtr, result, cscPtr->cl?className(cscPtr->cl):"NULL", methodName); +# endif } - /* CscFinish() is performed by the callbacks or in error case base ProcMethodDispatch */ /*fprintf(stderr, "no pop/CscFinish for %s\n", methodName);*/ -#else - //CscFinish(interp, cscPtr); #endif } @@ -6560,7 +6549,20 @@ /* * The cmd has no client data */ - /*fprintf(stderr, "cmdMethodDispatch %s %s, nothing stacked\n",objectName(object), methodName);*/ + //fprintf(stderr, "cmdMethodDispatch %s.%s, nothing stacked, objflags %.6x\n", + // objectName(object), methodName, object->flags); + + // todo: remove if-0 +#if 0 +# if defined(NRE) + { + TEOV_callback *rootPtr = TOP_CB(interp); + result = CmdMethodDispatch(clientData, interp, objc, objv, methodName, object, cmd, NULL); + result = NsfNRRunCallbacks(interp, result, rootPtr); + return result; + } +# endif +#endif return CmdMethodDispatch(clientData, interp, objc, objv, methodName, object, cmd, NULL); } @@ -6688,7 +6690,7 @@ rootPtr, result, methodName); /* TODO: we should need this only for scriped stuff; maybe it can harm otherwise for coros */ - result = TclNRRunCallbacks(interp, result, rootPtr, 0); + result = NsfNRRunCallbacks(interp, result, rootPtr); } else { fprintf(stderr, ".... don't run callbacks rootPtr = %p, result %d methodName %s\n", rootPtr, result, methodName); @@ -6887,7 +6889,6 @@ NsfRuntimeState *rst = RUNTIME_STATE(interp); Tcl_Obj *cmdName = object->cmdName, *methodObj, *cmdObj; NsfCallStackContent csc, *cscPtr = NULL; - register Tcl_ObjCmdProc *proc = Tcl_Command_objProc(cmd); if (flags & NSF_CM_NO_SHIFT) { shift = 0; @@ -8516,10 +8517,11 @@ *---------------------------------------------------------------------- * NextInvokeFinalize -- * - * This finalize method is either called via NRE callback or - * directly. It resets after a successul lookup and invation the - * continuation context (filter flags etc) and cleans up optionally - * the argument vector (inverse operation of NextGetArguments). + * This finalize function is either called via NRE callback or + * directly (from NextSearchAndInvoke). It resets after a successul + * lookup and invation the continuation context (filter flags etc) + * and cleans up optionally the argument vector (inverse operation + * of NextGetArguments). * * Results: * Tcl return code @@ -8534,8 +8536,8 @@ Tcl_Obj **nobjv = data[0]; NsfCallStackContent *cscPtr = data[1]; - //fprintf(stderr, "***** NextCmdFinalize cscPtr %p flags %.6x is next %d\n", - //cscPtr, cscPtr->callType, cscPtr->callType & NSF_CSC_CALL_IS_NEXT); + //fprintf(stderr, "***** NextInvokeFinalize cscPtr %p flags %.6x is next %d\n", + // cscPtr, cscPtr->callType, cscPtr->callType & NSF_CSC_CALL_IS_NEXT); if (cscPtr->callType & NSF_CSC_CALL_IS_NEXT) { //fprintf(stderr, "..... it was a successful next\n"); @@ -8548,7 +8550,7 @@ } if (nobjv) { - //fprintf(stderr, "..... free argument vector\n"); + //fprintf(stderr, "***** ..... free argument vector\n"); INCR_REF_COUNT(nobjv[0]); ckfree((char *)nobjv); } @@ -8652,8 +8654,7 @@ /* * Allow call only without immediate flag, when caller has NRE without immediate */ - flags = (cscPtr->callType & (NSF_CSC_CALL_IS_NRE|NSF_CM_IMMEDIATE)) == NSF_CSC_CALL_IS_NRE ? - 0 : NSF_CM_IMMEDIATE; + flags = NsfImmediateFromCallerFlags(cscPtr->callType); /*fprintf(stderr, "MethodDispatch in next flags %.6x NRE %d immediate %d next-flags %.6x\n", cscPtr->callType, @@ -8954,7 +8955,7 @@ char *resultMsg = NULL; /*fprintf(stderr, "NsfUnsetTrace %s flags %.4x %.4x\n", name, flags, - flags & TCL_INTERP_DESTROYED); */ + flags & TCL_INTERP_DESTROYED); **/ if ((flags & TCL_INTERP_DESTROYED) == 0) { if (GetObjectFromObj(interp, obj, &object) == TCL_OK) { @@ -9709,7 +9710,7 @@ result = NsfOConfigureMethod(interp, object, objc-1, tov); FREE_ON_STACK(Tcl_Obj*, tov); } else { - result = CallMethod((ClientData) object, interp, methodObj, objc, objv+2, 0); + result = CallMethod((ClientData) object, interp, methodObj, objc, objv+2, NSF_CM_IMMEDIATE); } if (result != TCL_OK) { @@ -9734,7 +9735,7 @@ methodObj = NsfMethodObj(interp, object, NSF_o_init_idx); if (methodObj) { result = CallMethod((ClientData) object, interp, methodObj, - nobjc+2, nobjv, NSF_CM_NO_PROTECT); + nobjc+2, nobjv, NSF_CM_NO_PROTECT|NSF_CM_IMMEDIATE); } object->flags |= NSF_INIT_CALLED; DECR_REF_COUNT(resultObj); @@ -9851,7 +9852,7 @@ result = NsfCCreateMethod(interp, cl, ObjStr(nameObj), 1, &nameObj); } else { result = NsfCallMethodWithArgs((ClientData)cl, interp, methodObj, - nameObj, 1, 0, 0); + nameObj, 1, 0, NSF_CM_IMMEDIATE); } DECR_REF_COUNT(nameObj); return result; @@ -10681,7 +10682,7 @@ CONST char *flag; assert(obj); - if (obj->typePtr == listType) { + if (obj->typePtr == Nsf_OT_listType) { if (Tcl_ListObjGetElements(interp, obj, objc, objv) == TCL_OK && *objc>1) { flag = ObjStr(*objv[0]); /*fprintf(stderr, "we have a list starting with '%s'\n", flag);*/ @@ -10728,7 +10729,8 @@ Tcl_ResetResult(interp); INCR_REF_COUNT(methodObj); - result = CallMethod((ClientData)object, interp, methodObj, argc, argv, NSF_CM_NO_UNKNOWN); + result = CallMethod((ClientData)object, interp, methodObj, argc, argv, + NSF_CM_NO_UNKNOWN|NSF_CM_IMMEDIATE); DECR_REF_COUNT(methodObj); /*fprintf(stderr, "method '%s' called args: %d o=%p, result=%d %d\n", @@ -12021,11 +12023,11 @@ static int NsfYiedCheckCmd(Tcl_Interp *interp) { #if defined(NRE) - Interp *iPtr = (Interp *)interp; - CoroutineData *corPtr = iPtr->execEnvPtr->corPtr; + //Interp *iPtr = (Interp *)interp; + //CoroutineData *corPtr = iPtr->execEnvPtr->corPtr; TclShowStack(interp); - fprintf(stderr, "stackLevel: %p %d\n", corPtr->stackLevel, *corPtr->stackLevel); + //fprintf(stderr, "stackLevel: %p %d\n", corPtr->stackLevel, *corPtr->stackLevel); #endif return TCL_OK; } @@ -12491,7 +12493,7 @@ objv = NULL; } result = NsfCallMethodWithArgs((ClientData)object, interp, command, arg, - nobjc, objv, NSF_CM_NO_UNKNOWN); + nobjc, objv, NSF_CM_NO_UNKNOWN|NSF_CM_IMMEDIATE); } return result; @@ -12511,7 +12513,6 @@ } //fprintf(stderr, "Colon dispatch %s on %s\n", ObjStr(nobjv[0]), objectName(self)); - /* we could use NSF_CM_IMMEDIATE here */ return ObjectDispatch(self, interp, nobjc, nobjv, NSF_CM_NO_SHIFT); } @@ -12933,8 +12934,9 @@ int result; if (!self) { - return NsfVarErrMsg(interp, "Cannot resolve 'self', probably called outside the context of an Next Scripting Object", - (char *) NULL); + return NsfVarErrMsg(interp, + "Cannot resolve 'self', probably called outside the context of an Next Scripting Object", + (char *) NULL); } if (withLocal) { @@ -12950,7 +12952,21 @@ result = MethodDispatch((ClientData)self, interp, nobjc+2, nobjv, cmd, self, cl, methodName, 0, 0, 6); } else { - result = CallMethod((ClientData)self, interp, methodObj, nobjc+2, nobjv, 0); +#if 0 + // attempt to make my NRE-enabled, failed so far + int flags; + NsfCallStackContent *cscPtr = CallStackGetFrame(interp, NULL); + if (!cscPtr || self != cscPtr->self) { + flags = NSF_CM_IMMEDIATE; + } else { + flags = NsfImmediateFromCallerFlags(cscPtr->callType); + fprintf(stderr, "XXX MY %s.%s frame has flags %.6x -> next-flags %.6x\n", + objectName(self), ObjStr(methodObj), cscPtr->callType, flags); + } + result = CallMethod((ClientData)self, interp, methodObj, nobjc+2, nobjv, flags); +#else + result = CallMethod((ClientData)self, interp, methodObj, nobjc+2, nobjv, NSF_CM_IMMEDIATE); +#endif } return result; } @@ -13995,7 +14011,7 @@ if (methodObj) { /* fprintf(stderr, "=== calling %s objectparameter\n", objectName(object));*/ result = CallMethod((ClientData) object, interp, methodObj, - 2, 0, NSF_CM_NO_PROTECT); + 2, 0, NSF_CM_NO_PROTECT|NSF_CM_IMMEDIATE); if (result == TCL_OK) { rawConfArgs = Tcl_GetObjResult(interp); @@ -14144,7 +14160,7 @@ oc ++; } result = NsfCallMethodWithArgs((ClientData) object, interp, paramPtr->nameObj, - ov[0], oc, &ov[1], 0); + ov[0], oc, &ov[1], NSF_CM_IMMEDIATE); } /* Pop previously stacked frame for eval context and set the @@ -14197,7 +14213,7 @@ result = NsfOResidualargsMethod(interp, object, remainingArgsc+1, pc.full_objv + i); } else { result = CallMethod((ClientData) object, interp, - methodObj, remainingArgsc+2, pc.full_objv + i-1, 0); + methodObj, remainingArgsc+2, pc.full_objv + i-1, NSF_CM_IMMEDIATE); } if (result != TCL_OK) { ParseContextRelease(&pc); @@ -14244,7 +14260,7 @@ } else { /*fprintf(stderr, "call dealloc\n");*/ result = NsfCallMethodWithArgs((ClientData)object->cl, interp, methodObj, - object->cmdName, 1, NULL, 0); + object->cmdName, 1, NULL, NSF_CM_IMMEDIATE); if (result != TCL_OK) { /* * In case, the call of the dealloc method has failed above (e.g. NS_DYING), @@ -14727,7 +14743,7 @@ result = RecreateObject(interp, cl, newObject, objc, nobjv); } else { result = CallMethod((ClientData) cl, interp, methodObj, - objc+1, nobjv+1, NSF_CM_NO_PROTECT); + objc+1, nobjv+1, NSF_CM_NO_PROTECT|NSF_CM_IMMEDIATE); } if (result != TCL_OK) @@ -14748,7 +14764,7 @@ result = NsfCAllocMethod(interp, cl, nameObj); } else { result = CallMethod((ClientData) cl, interp, methodObj, - 3, &nameObj, 0); + 3, &nameObj, NSF_CM_IMMEDIATE); } if (result != TCL_OK) goto create_method_exit; @@ -14955,7 +14971,7 @@ result = NsfOCleanupMethod(interp, object); } else { result = CallMethod((ClientData) object, interp, methodObj, - 2, 0, NSF_CM_NO_PROTECT); + 2, 0, NSF_CM_NO_PROTECT|NSF_CM_IMMEDIATE); } } @@ -16249,9 +16265,9 @@ /* init global variables for tcl types */ NsfMutexLock(&initMutex); - byteCodeType = Tcl_GetObjType("bytecode"); - tclCmdNameType = Tcl_GetObjType("cmdName"); - listType = Tcl_GetObjType("list"); + Nsf_OT_byteCodeType = Tcl_GetObjType("bytecode"); + Nsf_OT_tclCmdNameType = Tcl_GetObjType("cmdName"); + Nsf_OT_listType = Tcl_GetObjType("list"); NsfMutexUnlock(&initMutex); /* Index: generic/nsf.h =================================================================== diff -u -r1e14e709ba184c6daf7a2f94605a2cff65d7706c -r2510d1890d89e9b98cfdbf2106c1d4e50c9dba6a --- generic/nsf.h (.../nsf.h) (revision 1e14e709ba184c6daf7a2f94605a2cff65d7706c) +++ generic/nsf.h (.../nsf.h) (revision 2510d1890d89e9b98cfdbf2106c1d4e50c9dba6a) @@ -98,6 +98,7 @@ #define TCL_STACK_ALLOC_TRACE 1 #define VAR_RESOLVER_TRACE 1 #define CMD_RESOLVER_TRACE 1 +#define NRE_CALLBACK_TRACE 1 */ #if defined(PARSE_TRACE_FULL) Index: generic/nsfInt.h =================================================================== diff -u -rde4caf575ba6925970b850e327bbe2df9ab83060 -r2510d1890d89e9b98cfdbf2106c1d4e50c9dba6a --- generic/nsfInt.h (.../nsfInt.h) (revision de4caf575ba6925970b850e327bbe2df9ab83060) +++ generic/nsfInt.h (.../nsfInt.h) (revision 2510d1890d89e9b98cfdbf2106c1d4e50c9dba6a) @@ -319,7 +319,7 @@ #define NSF_CMD_PROTECTED_METHOD 0x00010000 #define NSF_CMD_REDEFINE_PROTECTED_METHOD 0x00020000 /* NSF_CMD_NONLEAF_METHOD is used to flag, if a Method implemented via cmd calls "next" */ -#define NSF_CMD_NONLEAF_METHOD 0x00040000 +#define NSF_CMD_NONLEAF_METHOD 0x00040000 #define NSF_CMD_CLASS_ONLY_METHOD 0x00080000 /* * object flags ... @@ -352,18 +352,18 @@ /* flags for NsfParams */ -#define NSF_ARG_REQUIRED 0x0001 -#define NSF_ARG_MULTIVALUED 0x0002 -#define NSF_ARG_NOARG 0x0004 -#define NSF_ARG_CURRENTLY_UNKNOWN 0x0008 -#define NSF_ARG_SUBST_DEFAULT 0x0010 -#define NSF_ARG_ALLOW_EMPTY 0x0020 -#define NSF_ARG_INITCMD 0x0040 -#define NSF_ARG_METHOD 0x0080 -#define NSF_ARG_RELATION 0x0100 -#define NSF_ARG_SWITCH 0x0200 -#define NSF_ARG_HAS_DEFAULT 0x1000 -#define NSF_ARG_IS_CONVERTER 0x2000 +#define NSF_ARG_REQUIRED 0x0001 +#define NSF_ARG_MULTIVALUED 0x0002 +#define NSF_ARG_NOARG 0x0004 +#define NSF_ARG_CURRENTLY_UNKNOWN 0x0008 +#define NSF_ARG_SUBST_DEFAULT 0x0010 +#define NSF_ARG_ALLOW_EMPTY 0x0020 +#define NSF_ARG_INITCMD 0x0040 +#define NSF_ARG_METHOD 0x0080 +#define NSF_ARG_RELATION 0x0100 +#define NSF_ARG_SWITCH 0x0200 +#define NSF_ARG_HAS_DEFAULT 0x1000 +#define NSF_ARG_IS_CONVERTER 0x2000 /* disallowed options */ #define NSF_DISALLOWED_ARG_METHOD_PARAMETER (NSF_ARG_METHOD|NSF_ARG_INITCMD|NSF_ARG_RELATION) @@ -639,6 +639,20 @@ #define NSF_CM_DELGATE 0x10 /* TODO: needed? */ #define NSF_CM_IMMEDIATE 0x20 +#if defined(NRE) +# define NsfImmediateFromCallerFlags(flags) \ + (((flags) & (NSF_CSC_CALL_IS_NRE|NSF_CM_IMMEDIATE)) == NSF_CSC_CALL_IS_NRE ? 0 : NSF_CM_IMMEDIATE) + +//#define NRE_SANE_PATCH 1 + +#if defined(NRE_SANE_PATCH) +# define NsfNRRunCallbacks(interp, result, rootPtr) TclNRRunCallbacks(interp, result, rootPtr) +#else +# define NsfNRRunCallbacks(interp, result, rootPtr) TclNRRunCallbacks(interp, result, rootPtr, 0) +#endif + +#endif + #if defined(NSF_PROFILE) typedef struct NsfProfile { long int overallTime; Index: generic/nsfStack.c =================================================================== diff -u -rd1ed482555d4d28dbb41fb9ca2723eabb5e01221 -r2510d1890d89e9b98cfdbf2106c1d4e50c9dba6a --- generic/nsfStack.c (.../nsfStack.c) (revision d1ed482555d4d28dbb41fb9ca2723eabb5e01221) +++ generic/nsfStack.c (.../nsfStack.c) (revision 2510d1890d89e9b98cfdbf2106c1d4e50c9dba6a) @@ -25,10 +25,10 @@ Tcl_CallFrame_clientData(framePtr), Tcl_CallFrame_level(framePtr), Tcl_CallFrame_nsPtr(framePtr), Tcl_CallFrame_nsPtr(framePtr)->fullName, - Tcl_CallFrame_objc(framePtr) ? ObjStr(Tcl_CallFrame_objv(framePtr)[0]) : "(null)", + Tcl_CallFrame_objc(framePtr) && 0 ? ObjStr(Tcl_CallFrame_objv(framePtr)[0]) : "(null)", Tcl_CallFrame_objc(framePtr) ? Tcl_CallFrame_objc(framePtr) : -1); if (cscPtr) { - fprintf(stderr, " csc %p frameType %d callType %d (%p %s)\n", + fprintf(stderr, " csc %p frameType %.4x callType %.4x (%p %s)\n", cscPtr, cscPtr ? cscPtr->frameType : -1, cscPtr ? cscPtr->callType : -1, Fisheye: Tag 2510d1890d89e9b98cfdbf2106c1d4e50c9dba6a refers to a dead (removed) revision in file `tests/coroutines.tcl'. Fisheye: No comparison available. Pass `N' to diff? Index: tests/tcl86.tcl =================================================================== diff -u --- tests/tcl86.tcl (revision 0) +++ tests/tcl86.tcl (revision 2510d1890d89e9b98cfdbf2106c1d4e50c9dba6a) @@ -0,0 +1,67 @@ +package require nx +package require nx::test + +# just 8.6 or similar +if {[info command yield] eq ""} return + +Test case coro-generator { + # =================================== + # nx coro + # =================================== + nx::Object create numbers { + set :delta 2 + + :public method ++ {} { + yield + set i 0 + while 1 { + yield $i + incr i ${:delta} + } + } + } + + coroutine nextNumber numbers ++ + set ::j 0 + for {set i 0} {$i < 10} {incr i} { + incr ::j [nextNumber] + } + rename nextNumber {} + + ? {set ::j} 90 +} + +# +# apply +# +Test case apply { + + # Register apply as an alias + ::nx::Object public alias apply ::apply + + ::nx::Object create o { + # Set an object variable + set :delta 100 + + # Define a standard map function based on apply + :public method map {lambda list} { + set result {} + foreach item $list { + lappend result [:apply $lambda $item] + } + return $result + } + + } + + # Two examples from the apply man page + ? {o map {x {return [string length $x]:$x}} {a bb ccc dddd}} \ + "1:a 2:bb 3:ccc 4:dddd" + ? {o map {x {expr {$x**2 + 3*$x - 2}}} {-4 -3 -2 -1 0 1 2 3 4}} \ + "2 -2 -4 -4 -2 2 8 16 26" + + # Test case accessing object specific variable + ? {o map {x {expr {$x * ${:delta}}}} {-4 -3 -2 -1 0 1 2 3 4}} \ + "-400 -300 -200 -100 0 100 200 300 400" +} +