diff options
Diffstat (limited to 'generic/tclBasic.c')
-rw-r--r-- | generic/tclBasic.c | 87 |
1 files changed, 49 insertions, 38 deletions
diff --git a/generic/tclBasic.c b/generic/tclBasic.c index 11da4cc..3d777d3 100644 --- a/generic/tclBasic.c +++ b/generic/tclBasic.c @@ -16,7 +16,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclBasic.c,v 1.417 2009/12/08 14:18:34 dkf Exp $ + * RCS: @(#) $Id: tclBasic.c,v 1.418 2009/12/08 20:56:29 msofer Exp $ */ #include "tclInt.h" @@ -143,7 +143,8 @@ static Tcl_NRPostProc NRRunObjProc; static Tcl_NRPostProc TailcallCleanup; static Tcl_NRPostProc NRTailcallEval; -static Tcl_NRPostProc YieldCallback; +static Tcl_NRPostProc RewindCoroutineCallback; +static Tcl_NRPostProc YieldToCallback; /* * The following structure define the commands in the Tcl core. @@ -8417,29 +8418,24 @@ static const CorContext NULL_CONTEXT = {NULL, NULL, NULL, NULL}; #define iPtr ((Interp *) interp) static int -YieldCallback( +YieldToCallback( ClientData data[], Tcl_Interp *interp, int result) { - CoroutineData *corPtr = data[0]; + /* CoroutineData *corPtr = data[0];*/ Tcl_Obj *listPtr = data[1]; + ClientData nsPtr = data[2]; - corPtr->stackLevel = NULL; /* mark suspended */ - iPtr->execEnvPtr = corPtr->callerEEPtr; - - if (listPtr) { - /* yieldTo: invoke the command using tailcall tech */ - TEOV_callback *cbPtr; - ClientData nsPtr = data[2]; - - TclNRAddCallback(interp, NRTailcallEval, listPtr, nsPtr, - NULL, NULL); - cbPtr = TOP_CB(interp); - TOP_CB(interp) = cbPtr->nextPtr; - - TclSpliceTailcall(interp, cbPtr); - } + /* yieldTo: invoke the command using tailcall tech */ + TEOV_callback *cbPtr; + + TclNRAddCallback(interp, NRTailcallEval, listPtr, nsPtr, + NULL, NULL); + cbPtr = TOP_CB(interp); + TOP_CB(interp) = cbPtr->nextPtr; + + TclSpliceTailcall(interp, cbPtr); return TCL_OK; } @@ -8471,7 +8467,6 @@ TclNRYieldObjCmd( iPtr->numLevels = corPtr->auxNumLevels; corPtr->auxNumLevels = numLevels - corPtr->auxNumLevels; - TclNRAddCallback(interp, YieldCallback, corPtr, NULL, NULL, NULL); TclNRAddCallback(interp, NRCallTEBC, INT2PTR(TCL_NR_YIELD_TYPE), NULL, NULL, NULL); return TCL_OK; @@ -8518,8 +8513,15 @@ TclNRYieldToObjCmd( Tcl_Panic("yieldTo failed to find the proper namespace"); } Tcl_IncrRefCount(nsObjPtr); + + /* + * Add the callback in the caller's env, then instruct TEBC to yield + */ - TclNRAddCallback(interp, YieldCallback, corPtr, listPtr, nsObjPtr, NULL); + iPtr->execEnvPtr = corPtr->callerEEPtr; + TclNRAddCallback(interp, YieldToCallback, corPtr, listPtr, nsObjPtr, NULL); + iPtr->execEnvPtr = corPtr->eePtr; + TclNRAddCallback(interp, NRCallTEBC, INT2PTR(TCL_NR_YIELD_TYPE), NULL, NULL, NULL); return TCL_OK; @@ -8527,11 +8529,19 @@ TclNRYieldToObjCmd( static int +RewindCoroutineCallback( + ClientData data[], + Tcl_Interp *interp, + int result) +{ + return Tcl_RestoreInterpState(interp, data[0]); +} + +static int RewindCoroutine( CoroutineData *corPtr, int result) { - Tcl_Obj *objPtr; Tcl_Interp *interp = corPtr->eePtr->interp; Tcl_InterpState state = Tcl_SaveInterpState(interp, result); @@ -8540,17 +8550,10 @@ RewindCoroutine( NRE_ASSERT(corPtr->eePtr->bottomPtr != NULL); NRE_ASSERT(corPtr->eePtr != iPtr->execEnvPtr); - TclNewObj(objPtr); - Tcl_IncrRefCount(objPtr); - corPtr->eePtr->rewind = 1; - result = NRInterpCoroutine(corPtr, interp, 1, &objPtr); - - NRE_ASSERT(iPtr->execEnvPtr == corPtr->eePtr); - - Tcl_DecrRefCount(objPtr); - result = Tcl_RestoreInterpState(interp, state); - return result; + TclNRAddCallback(interp, RewindCoroutineCallback, state, + NULL, NULL, NULL); + return NRInterpCoroutine(corPtr, interp, 0, NULL); } static void @@ -8718,7 +8721,11 @@ NRInterpCoroutine( CoroutineData *corPtr = clientData; int nestNumLevels = corPtr->auxNumLevels; - if ((objc != 1) && (objc != 2)) { + /* + * objc==0 indicates a call to rewind the coroutine + */ + + if (objc > 2) { Tcl_WrongNumArgs(interp, 1, objv, "?arg?"); return TCL_ERROR; } @@ -8750,9 +8757,13 @@ NRInterpCoroutine( TclNRAddCallback(interp, NRCoroutineCallerCallback, corPtr, NULL, NULL, NULL); + corPtr->callerBP = NULL;; corPtr->callerEEPtr = iPtr->execEnvPtr; iPtr->execEnvPtr = corPtr->eePtr; - return TclExecuteByteCode(interp, NULL); + + TclNRAddCallback(interp, NRCallTEBC, INT2PTR(TCL_NR_BC_TYPE), NULL, + NULL, NULL); + return TCL_OK; } int @@ -8771,7 +8782,6 @@ TclNRCoroutineObjCmd( const char *procName; Namespace *nsPtr, *altNsPtr, *cxtNsPtr; Tcl_DString ds; - int result; if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "name cmd ?arg ...?"); @@ -8810,7 +8820,8 @@ TclNRCoroutineObjCmd( corPtr->callerEEPtr = iPtr->execEnvPtr; corPtr->eePtr->corPtr = corPtr; corPtr->stackLevel = NULL; - + corPtr->callerBP = NULL; + /* * On first run just set a 0 level-offset, the natural numbering is * correct. The offset will be fixed for later runs. @@ -8924,9 +8935,9 @@ TclNRCoroutineObjCmd( TclNRAddCallback(interp, NRCoroutineExitCallback, corPtr, NULL,NULL,NULL); iPtr->evalFlags |= TCL_EVAL_REDIRECT; - result = TclNREvalObjEx(interp, cmdObjPtr, 0, NULL, 0); + TclNREvalObjEx(interp, cmdObjPtr, 0, NULL, 0); - return TclNRRunCallbacks(interp, result, rootPtr, 0); + return TclNRRunCallbacks(interp, TCL_OK, rootPtr, 0); } /* |