diff options
author | Miguel Sofer <miguel.sofer@gmail.com> | 2009-12-05 21:30:05 (GMT) |
---|---|---|
committer | Miguel Sofer <miguel.sofer@gmail.com> | 2009-12-05 21:30:05 (GMT) |
commit | 90bd6886192a7f8aba161a9c45eb000b9e59e69c (patch) | |
tree | 364580df13345c4b42788e63d9c681325eb910a9 /generic/tclNamesp.c | |
parent | 2aa99d284d6f4194676a3e2f5aac6ad2197a7714 (diff) | |
download | tcl-90bd6886192a7f8aba161a9c45eb000b9e59e69c.zip tcl-90bd6886192a7f8aba161a9c45eb000b9e59e69c.tar.gz tcl-90bd6886192a7f8aba161a9c45eb000b9e59e69c.tar.bz2 |
* generic/tclBasic.c: Fixed things so that you can tailcall
* generic/tclNamesp.c: properly out of a coroutine.
* tests/tailcall.test:
* generic/tclInterp.c: Fixed tailcalls for same-interp aliases (no
test)
Diffstat (limited to 'generic/tclNamesp.c')
-rw-r--r-- | generic/tclNamesp.c | 25 |
1 files changed, 24 insertions, 1 deletions
diff --git a/generic/tclNamesp.c b/generic/tclNamesp.c index 5d08bcb..99f3f1a 100644 --- a/generic/tclNamesp.c +++ b/generic/tclNamesp.c @@ -23,7 +23,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclNamesp.c,v 1.195 2009/11/16 18:00:11 dgp Exp $ + * RCS: @(#) $Id: tclNamesp.c,v 1.196 2009/12/05 21:30:05 msofer Exp $ */ #include "tclInt.h" @@ -517,13 +517,27 @@ Tcl_PopCallFrame( */ TEOV_callback *tailcallPtr, *runPtr; + ExecEnv *eePtr = NULL; + + restart: for (runPtr = TOP_CB(interp); runPtr; runPtr = runPtr->nextPtr) { if (((runPtr->procPtr) == NRCommand) && !runPtr->data[1]) { break; } } if (!runPtr) { + /* + * If we are tailcalling out of a coroutine, the splicing spot is + * in the caller's execEnv: go find it! + */ + + CoroutineData *corPtr = iPtr->execEnvPtr->corPtr; + if (corPtr) { + eePtr = iPtr->execEnvPtr; + iPtr->execEnvPtr = corPtr->callerEEPtr; + goto restart; + } Tcl_Panic("Tailcall cannot find the right splicing spot: should not happen!"); } @@ -531,6 +545,15 @@ Tcl_PopCallFrame( tailcallPtr->nextPtr = runPtr->nextPtr; runPtr->nextPtr = tailcallPtr; + + if (eePtr) { + /* + * Restore the right execEnv if it was swapped for tailcalling out + * of a coroutine. + */ + + iPtr->execEnvPtr = eePtr; + } } } |