From a61b052f4cf1f52c014879935f1a6db7fc5631be Mon Sep 17 00:00:00 2001 From: Steve Bennett Date: Fri, 30 Sep 2011 16:08:57 +1000 Subject: 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 --- jim.c | 31 +++++++++++++++++-------------- tests/tailcall.test | 13 +++++++++++++ 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 -- cgit v1.1