diff options
author | Steve Bennett <steveb@workware.net.au> | 2011-09-30 16:08:57 +1000 |
---|---|---|
committer | Steve Bennett <steveb@workware.net.au> | 2011-10-21 11:43:06 +1000 |
commit | a61b052f4cf1f52c014879935f1a6db7fc5631be (patch) | |
tree | 252e9fccf225f0cb18bc9f102d8f15f7b8797f80 | |
parent | 50525ae1adbd8b6fab322a47c5df744781e054fb (diff) | |
download | jimtcl-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.c | 31 | ||||
-rw-r--r-- | tests/tailcall.test | 13 |
2 files changed, 30 insertions, 14 deletions
@@ -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 |