diff options
author | Steve Bennett <steveb@workware.net.au> | 2010-03-03 16:04:06 +1000 |
---|---|---|
committer | Steve Bennett <steveb@workware.net.au> | 2010-10-15 11:02:49 +1000 |
commit | 6f841c80b5a540c7d3cbf8ea73937019eb88656e (patch) | |
tree | 7f6049f2f1cbad8040d0feeb08e5e21ad0ac75da /jim.c | |
parent | 8a21e1c0ea44a829f84e526a8302e6effbc4a9b1 (diff) | |
download | jimtcl-6f841c80b5a540c7d3cbf8ea73937019eb88656e.zip jimtcl-6f841c80b5a540c7d3cbf8ea73937019eb88656e.tar.gz jimtcl-6f841c80b5a540c7d3cbf8ea73937019eb88656e.tar.bz2 |
Implement 'info frame' and some related procs
info frame allows access to source file/line for earler call frames
Implement 'stacktrace' to give a live stacktrace
And 'stackdump' to convert a stack trace to readable form
Update 'errorInfo' to use 'stackdump'
Also fix tailcall to retain source info
And implement alias, lambda and curry with tailcall
Signed-off-by: Steve Bennett <steveb@workware.net.au>
Diffstat (limited to 'jim.c')
-rw-r--r-- | jim.c | 91 |
1 files changed, 62 insertions, 29 deletions
@@ -116,6 +116,8 @@ static Jim_Obj *Jim_ExpandDictSugar(Jim_Interp *interp, Jim_Obj *objPtr); static void SetDictSubstFromAny(Jim_Interp *interp, Jim_Obj *objPtr); static void JimSetFailedEnumResult(Jim_Interp *interp, const char *arg, const char *badtype, const char *prefix, const char * const *tablePtr, const char *name); static void JimDeleteLocalProcs(Jim_Interp *interp); +static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, const char *filename, int linenr, int argc, Jim_Obj *const *argv); +static int JimEvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv, const char *filename, int linenr); static const Jim_HashTableType JimVariablesHashTableType; @@ -8620,11 +8622,8 @@ static void JimPrngSeed(Jim_Interp *interp, const unsigned char *seed, #define JIM_EVAL_SARGV_LEN 8 /* static arguments vector length */ #define JIM_EVAL_SINTV_LEN 8 /* static interpolation vector length */ -static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc, - Jim_Obj *const *argv); - /* Handle calls to the [unknown] command */ -static int JimUnknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +static int JimUnknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv, const char *filename, int linenr) { Jim_Obj **v, *sv[JIM_EVAL_SARGV_LEN]; int retCode; @@ -8652,12 +8651,12 @@ static int JimUnknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv) /* Make a copy of the arguments vector, but shifted on * the right of one position. The command name of the * command will be instead the first argument of the - * [unknonw] call. */ + * [unknown] call. */ memcpy(v+1, argv, sizeof(Jim_Obj*)*argc); v[0] = interp->unknown; /* Call it */ interp->unknown_called++; - retCode = Jim_EvalObjVector(interp, argc+1, v); + retCode = JimEvalObjVector(interp, argc+1, v, filename, linenr); interp->unknown_called--; /* Clean up */ @@ -8675,7 +8674,7 @@ static int JimUnknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv) * list object generated by the UpdateStringOfList is made * in a way that ensures that every list element is a different * command argument. */ -int Jim_EvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv) +static int JimEvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv, const char *filename, int linenr) { int i, retcode; Jim_Cmd *cmdPtr; @@ -8686,7 +8685,7 @@ int Jim_EvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv) /* Command lookup */ cmdPtr = Jim_GetCommand(interp, objv[0], JIM_ERRMSG); if (cmdPtr == NULL) { - retcode = JimUnknown(interp, objc, objv); + retcode = JimUnknown(interp, objc, objv, filename, linenr); } else { /* Call it -- Make sure result is an empty object. */ JimIncrCmdRefCount(cmdPtr); @@ -8695,7 +8694,7 @@ int Jim_EvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv) interp->cmdPrivData = cmdPtr->privData; retcode = cmdPtr->cmdProc(interp, objc, objv); } else { - retcode = JimCallProcedure(interp, cmdPtr, objc, objv); + retcode = JimCallProcedure(interp, cmdPtr, filename, linenr, objc, objv); } JimDecrCmdRefCount(interp, cmdPtr); } @@ -8706,6 +8705,11 @@ int Jim_EvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv) return retcode; } +int Jim_EvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv) +{ + return JimEvalObjVector(interp, objc, objv, NULL, 0); +} + /* Interpolate the given tokens into a unique Jim_Obj returned by reference * via *objPtrPtr. This function is only called by Jim_EvalObj(). * The returned object has refcount = 0. */ @@ -8903,6 +8907,28 @@ static void JimDeleteLocalProcs(Jim_Interp *interp) } } +/* If listPtr is a list, call JimEvalObjVector() with the given source info. + * Otherwise eval with Jim_EvalObj() + */ +int Jim_EvalObjList(Jim_Interp *interp, Jim_Obj *listPtr, const char *filename, int linenr) +{ + if (!Jim_IsList(listPtr)) { + return Jim_EvalObj(interp, listPtr); + } + else { + int retcode = JIM_OK; + + if (listPtr->internalRep.listValue.len) { + Jim_IncrRefCount(listPtr); + retcode = JimEvalObjVector(interp, + listPtr->internalRep.listValue.len, + listPtr->internalRep.listValue.ele, filename, linenr); + Jim_DecrRefCount(interp, listPtr); + } + return retcode; + } +} + int Jim_EvalObj(Jim_Interp *interp, Jim_Obj *scriptObjPtr) { int i, j = 0, len; @@ -8915,16 +8941,10 @@ int Jim_EvalObj(Jim_Interp *interp, Jim_Obj *scriptObjPtr) interp->errorFlag = 0; - /* If the object is of type "list" and there is no - * string representation for this object, we can call + /* If the object is of type "list", we can call * a specialized version of Jim_EvalObj() */ - if (Jim_IsList(scriptObjPtr) && scriptObjPtr->internalRep.listValue.len) { - Jim_IncrRefCount(scriptObjPtr); - retcode = Jim_EvalObjVector(interp, - scriptObjPtr->internalRep.listValue.len, - scriptObjPtr->internalRep.listValue.ele); - Jim_DecrRefCount(interp, scriptObjPtr); - return retcode; + if (Jim_IsList(scriptObjPtr)) { + return Jim_EvalObjList(interp, scriptObjPtr, NULL, 0); } Jim_IncrRefCount(scriptObjPtr); /* Make sure it's shared. */ @@ -9089,12 +9109,12 @@ int Jim_EvalObj(Jim_Interp *interp, Jim_Obj *scriptObjPtr) interp->cmdPrivData = cmd->privData; retcode = cmd->cmdProc(interp, argc, argv); } else { - retcode = JimCallProcedure(interp, cmd, argc, argv); + retcode = JimCallProcedure(interp, cmd, script->fileName, cmdtoken->linenr, argc, argv); } JimDecrCmdRefCount(interp, cmd); } else { /* Call [unknown] */ - retcode = JimUnknown(interp, argc, argv); + retcode = JimUnknown(interp, argc, argv, script->fileName, cmdtoken->linenr); } if (interp->signal_level && interp->sigmask) { /* Check for a signal after each command */ @@ -9141,7 +9161,7 @@ err: * * This can be fixed just implementing callframes caching * in JimCreateCallFrame() and JimFreeCallFrame(). */ -int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc, +int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, const char *filename, int linenr, int argc, Jim_Obj *const *argv) { int i, d, retcode; @@ -9196,6 +9216,8 @@ int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc, callFramePtr->procArgsObjPtr = cmd->argListObjPtr; callFramePtr->procBodyObjPtr = cmd->bodyObjPtr; callFramePtr->staticVars = cmd->staticVars; + callFramePtr->filename = filename; + callFramePtr->line = linenr; Jim_IncrRefCount(cmd->argListObjPtr); Jim_IncrRefCount(cmd->bodyObjPtr); interp->framePtr = callFramePtr; @@ -9286,7 +9308,8 @@ int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc, while (retcode == JIM_EVAL) { Jim_Obj *resultScriptObjPtr = Jim_GetResult(interp); Jim_IncrRefCount(resultScriptObjPtr); - retcode = Jim_EvalObj(interp, resultScriptObjPtr); + /* Should be a list! */ + retcode = Jim_EvalObjList(interp, resultScriptObjPtr, filename, linenr); Jim_DecrRefCount(interp, resultScriptObjPtr); } /* Handle the JIM_RETURN return code */ @@ -9792,7 +9815,7 @@ static Jim_Obj *JimVariablesList(Jim_Interp *interp, Jim_Obj *patternObjPtr, } static int JimInfoLevel(Jim_Interp *interp, Jim_Obj *levelObjPtr, - Jim_Obj **objPtrPtr) + Jim_Obj **objPtrPtr, int info_level_cmd) { Jim_CallFrame *targetCallFrame; @@ -9804,9 +9827,18 @@ static int JimInfoLevel(Jim_Interp *interp, Jim_Obj *levelObjPtr, Jim_SetResultFormatted(interp, "bad level \"%#s\"", levelObjPtr); return JIM_ERR; } - *objPtrPtr = Jim_NewListObj(interp, - targetCallFrame->argv, - targetCallFrame->argc); + if (info_level_cmd) { + *objPtrPtr = Jim_NewListObj(interp, + targetCallFrame->argv, + targetCallFrame->argc); + } + else { + Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0); + Jim_ListAppendElement(interp, listObj, targetCallFrame->argv[0]); + Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, targetCallFrame->filename ?: "", -1)); + Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, targetCallFrame->line)); + *objPtrPtr = listObj; + } return JIM_OK; } @@ -12221,11 +12253,11 @@ static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, int mode = 0; static const char *commands[] = { - "body", "commands", "procs", "exists", "globals", "level", "locals", + "body", "commands", "procs", "exists", "globals", "level", "frame", "locals", "vars", "version", "patchlevel", "complete", "args", "hostname", "script", "source", "stacktrace", "nameofexecutable", "returncodes", NULL }; - enum {INFO_BODY, INFO_COMMANDS, INFO_PROCS, INFO_EXISTS, INFO_GLOBALS, INFO_LEVEL, + enum {INFO_BODY, INFO_COMMANDS, INFO_PROCS, INFO_EXISTS, INFO_GLOBALS, INFO_LEVEL, INFO_FRAME, INFO_LOCALS, INFO_VARS, INFO_VERSION, INFO_PATCHLEVEL, INFO_COMPLETE, INFO_ARGS, INFO_HOSTNAME, INFO_SCRIPT, INFO_SOURCE, INFO_STACKTRACE, INFO_NAMEOFEXECUTABLE, INFO_RETURNCODES }; @@ -12312,13 +12344,14 @@ static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, break; case INFO_LEVEL: + case INFO_FRAME: switch (argc) { case 2: Jim_SetResultInt(interp, interp->numLevels); break; case 3: - if (JimInfoLevel(interp, argv[2], &objPtr) != JIM_OK) { + if (JimInfoLevel(interp, argv[2], &objPtr, cmd == INFO_LEVEL) != JIM_OK) { return JIM_ERR; } Jim_SetResult(interp, objPtr); |