aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Bennett <steveb@workware.net.au>2011-09-30 16:08:57 +1000
committerSteve Bennett <steveb@workware.net.au>2011-10-21 11:43:06 +1000
commita61b052f4cf1f52c014879935f1a6db7fc5631be (patch)
tree252e9fccf225f0cb18bc9f102d8f15f7b8797f80
parent50525ae1adbd8b6fab322a47c5df744781e054fb (diff)
downloadjimtcl-a61b052f4cf1f52c014879935f1a6db7fc5631be.zip
jimtcl-a61b052f4cf1f52c014879935f1a6db7fc5631be.tar.gz
jimtcl-a61b052f4cf1f52c014879935f1a6db7fc5631be.tar.bz2
Return from tailcall should be passed through
If a proc invokes a command via a tailcall and that command invokes "return", the return should be passed back to the caller of the proc. Signed-off-by: Steve Bennett <steveb@workware.net.au>
-rw-r--r--jim.c31
-rw-r--r--tests/tailcall.test13
2 files changed, 30 insertions, 14 deletions
diff --git a/jim.c b/jim.c
index dd6c77b..23d249b 100644
--- a/jim.c
+++ b/jim.c
@@ -9879,21 +9879,18 @@ static Jim_Obj *JimInterpolateTokens(Jim_Interp *interp, const ScriptToken * tok
*/
static int JimEvalObjList(Jim_Interp *interp, Jim_Obj *listPtr, Jim_Obj *fileNameObj, int linenr)
{
- if (!Jim_IsList(listPtr)) {
- return Jim_EvalObj(interp, listPtr);
- }
- else {
- int retcode = JIM_OK;
+ int retcode = JIM_OK;
- if (listPtr->internalRep.listValue.len) {
- Jim_IncrRefCount(listPtr);
- retcode = JimEvalObjVector(interp,
- listPtr->internalRep.listValue.len,
- listPtr->internalRep.listValue.ele, fileNameObj, linenr);
- Jim_DecrRefCount(interp, listPtr);
- }
- return retcode;
+ JimPanic((!Jim_IsList(listPtr), "JimEvalObjList() called without list arg"));
+
+ if (listPtr->internalRep.listValue.len) {
+ Jim_IncrRefCount(listPtr);
+ retcode = JimEvalObjVector(interp,
+ listPtr->internalRep.listValue.len,
+ listPtr->internalRep.listValue.ele, fileNameObj, linenr);
+ Jim_DecrRefCount(interp, listPtr);
}
+ return retcode;
}
int Jim_EvalObj(Jim_Interp *interp, Jim_Obj *scriptObjPtr)
@@ -10309,8 +10306,14 @@ badargset:
Jim_Obj *resultScriptObjPtr = Jim_GetResult(interp);
Jim_IncrRefCount(resultScriptObjPtr);
- /* Should be a list! */
+ /* Result must be a list */
retcode = JimEvalObjList(interp, resultScriptObjPtr, fileNameObj, linenr);
+ if (retcode == JIM_RETURN) {
+ /* If the result of the tailcall invokes 'return', push
+ * it up to the caller
+ */
+ interp->returnLevel++;
+ }
Jim_DecrRefCount(interp, resultScriptObjPtr);
}
/* Handle the JIM_RETURN return code */
diff --git a/tests/tailcall.test b/tests/tailcall.test
index b7dab81..262ab0f 100644
--- a/tests/tailcall.test
+++ b/tests/tailcall.test
@@ -52,4 +52,17 @@ test tailcall-1.5 {interaction of uplevel and tailcall} {
a b
} {c c}
+test tailcall-1.6 {tailcall pass through return} {
+ proc a {script} {
+ # return from $script should pass through back to the caller
+ tailcall foreach i {1 2 3} $script
+ }
+ proc b {} {
+ a {return ok}
+ # Should not get here
+ return bad
+ }
+ b
+} {ok}
+
testreport