aboutsummaryrefslogtreecommitdiff
path: root/jim.c
diff options
context:
space:
mode:
authorSteve Bennett <steveb@workware.net.au>2023-05-18 09:19:43 +1000
committerSteve Bennett <steveb@workware.net.au>2023-06-21 09:17:47 +1000
commitf07c53e38d55f0c7c648b7818798138d91053527 (patch)
treeb80d7f1b40bd61bdaa385e6f1817ea6cfbb511d0 /jim.c
parent9e78cc8a97b7ecf6afbbe9a35305daf3459cead6 (diff)
downloadjimtcl-f07c53e38d55f0c7c648b7818798138d91053527.zip
jimtcl-f07c53e38d55f0c7c648b7818798138d91053527.tar.gz
jimtcl-f07c53e38d55f0c7c648b7818798138d91053527.tar.bz2
core: improve eval frame handling
Now callers to JimInvokeCommand() are expected to push and eval frame. Then we no longer need to carry currentScriptObj, argc, argv in the interp since these are in the current eval frame. Note that this change simply renames some unused fields in Jim_Interp for ABI compatibility, but these will be removed in due course. Signed-off-by: Steve Bennett <steveb@workware.net.au>
Diffstat (limited to 'jim.c')
-rw-r--r--jim.c167
1 files changed, 59 insertions, 108 deletions
diff --git a/jim.c b/jim.c
index d960f54..012c0e4 100644
--- a/jim.c
+++ b/jim.c
@@ -5692,7 +5692,6 @@ Jim_Interp *Jim_CreateInterp(void)
i->unknown = Jim_NewStringObj(i, "unknown", -1);
i->defer = Jim_NewStringObj(i, "jim::defer", -1);
i->errorProc = i->emptyObj;
- i->currentScriptObj = Jim_NewEmptyStringObj(i);
i->nullScriptObj = Jim_NewEmptyStringObj(i);
i->evalFrame = &i->topEvalFrame;
Jim_IncrRefCount(i->emptyObj);
@@ -5701,7 +5700,6 @@ Jim_Interp *Jim_CreateInterp(void)
Jim_IncrRefCount(i->stackTrace);
Jim_IncrRefCount(i->unknown);
Jim_IncrRefCount(i->defer);
- Jim_IncrRefCount(i->currentScriptObj);
Jim_IncrRefCount(i->nullScriptObj);
Jim_IncrRefCount(i->errorProc);
Jim_IncrRefCount(i->trueObj);
@@ -5749,7 +5747,6 @@ void Jim_FreeInterp(Jim_Interp *i)
Jim_DecrRefCount(i, i->unknown);
Jim_DecrRefCount(i, i->defer);
Jim_DecrRefCount(i, i->errorFileNameObj);
- Jim_DecrRefCount(i, i->currentScriptObj);
Jim_DecrRefCount(i, i->nullScriptObj);
/* This will disard any cached commands */
@@ -5903,23 +5900,23 @@ static Jim_CallFrame *JimGetCallFrameByInteger(Jim_Interp *interp, long level)
return NULL;
}
-static Jim_EvalFrame *JimGetEvalFrameByInteger(Jim_Interp *interp, long level)
+static Jim_EvalFrame *JimGetEvalFrameByProcLevel(Jim_Interp *interp, int proclevel)
{
Jim_EvalFrame *evalFrame;
- if (level == 0) {
+ if (proclevel == 0) {
return interp->evalFrame;
}
- if (level < 0) {
+ if (proclevel < 0) {
/* Convert from a relative to an absolute level */
- level = interp->evalFrame->level + level;
+ proclevel = interp->procLevel + proclevel;
}
- if (level > 0) {
+ if (proclevel >= 0) {
/* Lookup */
for (evalFrame = interp->evalFrame; evalFrame; evalFrame = evalFrame->parent) {
- if (evalFrame->level == level) {
+ if (evalFrame->procLevel == proclevel) {
return evalFrame;
}
}
@@ -10647,7 +10644,7 @@ static int JimTraceCallback(Jim_Interp *interp, const char *type, int argc, Jim_
Jim_Obj *traceCmdObj = interp->traceCmdObj;
Jim_Obj *resultObj = Jim_GetResult(interp);
/* Where were we called from? */
- ScriptObj *script = JimGetScript(interp, interp->currentScriptObj);
+ ScriptObj *script = JimGetScript(interp, interp->evalFrame->scriptObj);
nargv[0] = traceCmdObj;
nargv[1] = Jim_NewStringObj(interp, type, -1);
@@ -10706,14 +10703,19 @@ static int JimUnknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
return retcode;
}
-static void JimPushEvalFrame(Jim_Interp *interp, Jim_EvalFrame *frame)
+static void JimPushEvalFrame(Jim_Interp *interp, Jim_EvalFrame *frame, Jim_Obj *scriptObj)
{
memset(frame, 0, sizeof(*frame));
frame->parent = interp->evalFrame;
frame->level = frame->parent->level + 1;
- frame->type = "unknown";
- frame->callFrameLevel = interp->framePtr->level;
- frame->scriptObj = interp->currentScriptObj;
+ frame->procLevel = interp->procLevel;
+ frame->framePtr = interp->framePtr;
+ if (scriptObj) {
+ frame->scriptObj = scriptObj;
+ }
+ else {
+ frame->scriptObj = frame->parent->scriptObj;
+ }
interp->evalFrame = frame;
#if 0
if (frame->scriptObj) {
@@ -10727,15 +10729,13 @@ static void JimPopEvalFrame(Jim_Interp *interp)
interp->evalFrame = interp->evalFrame->parent;
}
+/* This is called from Jim_EvalObj, JimEvalObjList, Jim_EvalObjVector */
static int JimInvokeCommand(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
{
int retcode;
Jim_Cmd *cmdPtr;
void *prevPrivData;
Jim_Obj *tailcallObj = NULL;
- int prev_argc;
- Jim_Obj * const *prev_argv;
- Jim_EvalFrame frame;
#if 0
printf("invoke");
@@ -10763,24 +10763,11 @@ static int JimInvokeCommand(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
* so that the entire call chain can be walked. This would allow 'info frame' to walk
* the full call chain, not just call frames
*/
- prev_argc = interp->argc;
- prev_argv = interp->argv;
-
- JimPushEvalFrame(interp, &frame);
-
tailcall:
- interp->argc = objc;
- interp->argv = objv;
-
- if (cmdPtr->isproc) {
- frame.type = "proc";
- }
- else {
- frame.type = "cmd";
- }
- frame.argc = objc;
- frame.argv = objv;
+ interp->evalFrame->argc = objc;
+ interp->evalFrame->argv = objv;
+ interp->evalFrame->cmd = cmdPtr;
if (!interp->traceCmdObj ||
(retcode = JimTraceCallback(interp, "cmd", objc, objv)) == JIM_OK) {
@@ -10821,11 +10808,6 @@ tailcall:
interp->cmdPrivData = prevPrivData;
interp->evalDepth--;
- interp->argc = prev_argc;
- interp->argv = prev_argv;
-
- JimPopEvalFrame(interp);
-
out:
JimDecrCmdRefCount(interp, cmdPtr);
@@ -10854,13 +10836,18 @@ out:
int Jim_EvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv)
{
int i, retcode;
+ Jim_EvalFrame frame;
/* Incr refcount of arguments. */
for (i = 0; i < objc; i++)
Jim_IncrRefCount(objv[i]);
+ JimPushEvalFrame(interp, &frame, NULL);
+
retcode = JimInvokeCommand(interp, objc, objv);
+ JimPopEvalFrame(interp);
+
/* Decr refcount of arguments and return the retcode */
for (i = 0; i < objc; i++)
Jim_DecrRefCount(interp, objv[i]);
@@ -11069,9 +11056,13 @@ static Jim_Obj *JimInterpolateTokens(Jim_Interp *interp, const ScriptToken * tok
static int JimEvalObjList(Jim_Interp *interp, Jim_Obj *listPtr)
{
int retcode = JIM_OK;
+ Jim_EvalFrame frame;
JimPanic((Jim_IsList(listPtr) == 0, "JimEvalObjList() invoked on non-list."));
+ /* XXX should we pass listPtr as scriptObj here? */
+ JimPushEvalFrame(interp, &frame, NULL);
+
if (listPtr->internalRep.listValue.len) {
Jim_IncrRefCount(listPtr);
retcode = JimInvokeCommand(interp,
@@ -11079,6 +11070,9 @@ static int JimEvalObjList(Jim_Interp *interp, Jim_Obj *listPtr)
listPtr->internalRep.listValue.ele);
Jim_DecrRefCount(interp, listPtr);
}
+
+ JimPopEvalFrame(interp);
+
return retcode;
}
@@ -11095,7 +11089,7 @@ int Jim_EvalObj(Jim_Interp *interp, Jim_Obj *scriptObjPtr)
ScriptToken *token;
int retcode = JIM_OK;
Jim_Obj *sargv[JIM_EVAL_SARGV_LEN], **argv = NULL;
- Jim_Obj *prevScriptObj;
+ Jim_EvalFrame frame;
/* If the object is of type "list", with no string rep we can call
* a specialized version of Jim_EvalObj() */
@@ -11155,9 +11149,7 @@ int Jim_EvalObj(Jim_Interp *interp, Jim_Obj *scriptObjPtr)
* inUse field of the script internal rep structure. */
script->inUse++;
- /* Stash the current script */
- prevScriptObj = interp->currentScriptObj;
- interp->currentScriptObj = scriptObjPtr;
+ JimPushEvalFrame(interp, &frame, scriptObjPtr);
interp->errorFlag = 0;
argv = sargv;
@@ -11317,8 +11309,7 @@ int Jim_EvalObj(Jim_Interp *interp, Jim_Obj *scriptObjPtr)
interp->addStackTrace = 0;
}
- /* Restore the current script */
- interp->currentScriptObj = prevScriptObj;
+ JimPopEvalFrame(interp);
/* Note that we don't have to decrement inUse, because the
* following code transfers our use of the reference again to
@@ -11410,17 +11401,14 @@ int Jim_EvalNamespace(Jim_Interp *interp, Jim_Obj *scriptObj, Jim_Obj *nsObj)
{
Jim_CallFrame *callFramePtr;
int retcode;
- ScriptObj *script = JimGetScript(interp, scriptObj);
/* Create a new callframe */
callFramePtr = JimCreateCallFrame(interp, interp->framePtr, nsObj);
- callFramePtr->argv = interp->argv;
- callFramePtr->argc = interp->argc;
+ callFramePtr->argv = interp->evalFrame->argv;
+ callFramePtr->argc = interp->evalFrame->argc;
callFramePtr->procArgsObjPtr = NULL;
callFramePtr->procBodyObjPtr = scriptObj;
callFramePtr->staticVars = NULL;
- callFramePtr->fileNameObj = script->fileNameObj;
- callFramePtr->line = script->linenr;
Jim_IncrRefCount(scriptObj);
interp->framePtr = callFramePtr;
@@ -11454,7 +11442,6 @@ static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc, Jim_Obj
{
Jim_CallFrame *callFramePtr;
int i, d, retcode, optargs;
- ScriptObj *script;
/* Check arity */
if (argc - 1 < cmd->u.proc.reqArity ||
@@ -11482,10 +11469,7 @@ static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc, Jim_Obj
callFramePtr->procBodyObjPtr = cmd->u.proc.bodyObjPtr;
callFramePtr->staticVars = cmd->u.proc.staticVars;
- /* Remember where we were called from. */
- script = JimGetScript(interp, interp->currentScriptObj);
- callFramePtr->fileNameObj = script->fileNameObj;
- callFramePtr->line = script->linenr;
+ interp->procLevel++;
Jim_IncrRefCount(cmd->u.proc.argListObjPtr);
Jim_IncrRefCount(cmd->u.proc.bodyObjPtr);
@@ -11533,8 +11517,6 @@ static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc, Jim_Obj
}
}
- interp->evalFrame->cmd = cmd;
-
if (interp->traceCmdObj == NULL ||
(retcode = JimTraceCallback(interp, "proc", argc, argv)) == JIM_OK) {
/* Eval the body */
@@ -11562,8 +11544,7 @@ badargset:
interp->errorProc = argv[0];
Jim_IncrRefCount(interp->errorProc);
}
-
- interp->evalFrame->cmd = NULL;
+ interp->procLevel--;
return retcode;
}
@@ -11575,22 +11556,10 @@ int Jim_EvalSource(Jim_Interp *interp, const char *filename, int lineno, const c
scriptObjPtr = Jim_NewStringObj(interp, script, -1);
Jim_IncrRefCount(scriptObjPtr);
-
if (filename) {
- Jim_Obj *prevScriptObj;
-
JimSetSourceInfo(interp, scriptObjPtr, Jim_NewStringObj(interp, filename, -1), lineno);
-
- prevScriptObj = interp->currentScriptObj;
- interp->currentScriptObj = scriptObjPtr;
-
- retval = Jim_EvalObj(interp, scriptObjPtr);
-
- interp->currentScriptObj = prevScriptObj;
- }
- else {
- retval = Jim_EvalObj(interp, scriptObjPtr);
}
+ retval = Jim_EvalObj(interp, scriptObjPtr);
Jim_DecrRefCount(interp, scriptObjPtr);
return retval;
}
@@ -11632,7 +11601,6 @@ int Jim_EvalFile(Jim_Interp *interp, const char *filename)
FILE *fp;
char *buf;
Jim_Obj *scriptObjPtr;
- Jim_Obj *prevScriptObj;
struct stat sb;
int retcode;
int readlen;
@@ -11661,9 +11629,6 @@ int Jim_EvalFile(Jim_Interp *interp, const char *filename)
JimSetSourceInfo(interp, scriptObjPtr, Jim_NewStringObj(interp, filename, -1), 1);
Jim_IncrRefCount(scriptObjPtr);
- prevScriptObj = interp->currentScriptObj;
- interp->currentScriptObj = scriptObjPtr;
-
retcode = Jim_EvalObj(interp, scriptObjPtr);
/* Handle the JIM_RETURN return code */
@@ -11679,8 +11644,6 @@ int Jim_EvalFile(Jim_Interp *interp, const char *filename)
interp->addStackTrace++;
}
- interp->currentScriptObj = prevScriptObj;
-
Jim_DecrRefCount(interp, scriptObjPtr);
return retcode;
@@ -11994,7 +11957,7 @@ static int JimInfoFrame(Jim_Interp *interp, Jim_Obj *levelObjPtr, Jim_Obj **objP
long level;
if (Jim_GetLong(interp, levelObjPtr, &level) == JIM_OK) {
- Jim_EvalFrame *targetEvalFrame = JimGetEvalFrameByInteger(interp, level);
+ Jim_EvalFrame *targetEvalFrame = JimGetEvalFrameByProcLevel(interp, level);
if (targetEvalFrame) {
Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0);
int linenr;
@@ -12020,40 +11983,28 @@ static int JimInfoFrame(Jim_Interp *interp, Jim_Obj *levelObjPtr, Jim_Obj **objP
Jim_ListAppendElement(interp, listObj, cmdObj);
}
#endif
- /* Now determine if this eval frame has a proc caller */
- {
- /* If the target eval frame has proc call frame level >= the previous one
- * we don't set 'proc' (it will be set on the previous one)
- * So first determine if this needs 'proc'
- */
+ /* XXX explain how this works */
+ if (targetEvalFrame == interp->evalFrame || (targetEvalFrame->cmd && targetEvalFrame->cmd->isproc && targetEvalFrame->cmd->cmdNameObj)) {
Jim_EvalFrame *e, *p = NULL;
- for (e = interp->evalFrame; e; e = e->parent) {
- if (e == targetEvalFrame) {
- break;
- }
- if (!p || e->callFrameLevel != p->callFrameLevel) {
+ for (e = targetEvalFrame->parent; e; e = e->parent) {
+ if (e->cmd && e->cmd->isproc && e->cmd->cmdNameObj) {
p = e;
- }
- else {
- p = NULL;
- }
- }
- if (!p || e->callFrameLevel < p->callFrameLevel) {
- /* Find the first proc above this level */
- for (e = targetEvalFrame->parent; e; e = e->parent) {
- if (e->cmd && e->cmd->isproc) {
- /* apply and namespace eval won't provide cmdNameObj */
- if (e->cmd->cmdNameObj) {
- Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "proc", -1));
- Jim_ListAppendElement(interp, listObj, e->cmd->cmdNameObj);
- }
- break;
- }
+ break;
}
}
+ if (p && p->level) {
+ if (p->cmd && p->cmd->isproc) {
+ if (p->cmd->cmdNameObj) {
+ Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "proc", -1));
+ Jim_ListAppendElement(interp, listObj, p->cmd->cmdNameObj);
+ }
+ }
+ }
}
Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "level", -1));
- Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, interp->framePtr->level - targetEvalFrame->callFrameLevel));
+ Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, interp->framePtr->level - targetEvalFrame->framePtr->level));
+ Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "proclevel", -1));
+ Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, targetEvalFrame->procLevel));
*objPtrPtr = listObj;
return JIM_OK;
@@ -15696,7 +15647,7 @@ static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
Jim_WrongNumArgs(interp, 2, argv, "");
return JIM_ERR;
}
- Jim_SetResult(interp, JimGetScript(interp, interp->currentScriptObj)->fileNameObj);
+ Jim_SetResult(interp, JimGetScript(interp, interp->evalFrame->scriptObj)->fileNameObj);
break;
case INFO_SOURCE:{
@@ -15763,7 +15714,7 @@ static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
case INFO_FRAME:
switch (argc) {
case 2:
- Jim_SetResultInt(interp, interp->evalFrame->level);
+ Jim_SetResultInt(interp, interp->procLevel + 1);
break;
case 3: