summaryrefslogtreecommitdiffstats
path: root/generic/tclNamesp.c
diff options
context:
space:
mode:
authorMiguel Sofer <miguel.sofer@gmail.com>2009-12-05 21:30:05 (GMT)
committerMiguel Sofer <miguel.sofer@gmail.com>2009-12-05 21:30:05 (GMT)
commit90bd6886192a7f8aba161a9c45eb000b9e59e69c (patch)
tree364580df13345c4b42788e63d9c681325eb910a9 /generic/tclNamesp.c
parent2aa99d284d6f4194676a3e2f5aac6ad2197a7714 (diff)
downloadtcl-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.c25
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;
+ }
}
}