From 92d844b187a1a7cd56fc2955b50aa461cd9e0086 Mon Sep 17 00:00:00 2001 From: dkf Date: Wed, 2 Jan 2013 15:10:00 +0000 Subject: Passing more tests. --- generic/tclCompile.c | 2 +- generic/tclEnsemble.c | 119 +++++++++++++++++++++++++++++++++----------------- generic/tclExecute.c | 24 ++++++---- 3 files changed, 94 insertions(+), 51 deletions(-) diff --git a/generic/tclCompile.c b/generic/tclCompile.c index c052531..45a74d7 100644 --- a/generic/tclCompile.c +++ b/generic/tclCompile.c @@ -529,7 +529,7 @@ InstructionDesc const tclInstructionTable[] = { /* Forces the variable indexed by opnd to be an array. Does not touch * the stack. */ - {"invokeReplace", 5, INT_MIN, 1, {OPERAND_UINT4}}, + {"invokeReplace", 6, INT_MIN, 2, {OPERAND_UINT4,OPERAND_UINT1}}, /* Invoke command named objv[0], replacing the first two words with * the word at the top of the stack; * = */ diff --git a/generic/tclEnsemble.c b/generic/tclEnsemble.c index 8f0d4fe..8cd9717 100644 --- a/generic/tclEnsemble.c +++ b/generic/tclEnsemble.c @@ -39,9 +39,9 @@ static int CompileToCompiledCommand(Tcl_Interp *interp, Tcl_Parse *parsePtr, Tcl_Token *tokenPtr, int len, Tcl_Obj **elems, Command *cmdPtr, CompileEnv *envPtr); -static int CompileToInvokedCommand(Tcl_Interp *interp, +static void CompileToInvokedCommand(Tcl_Interp *interp, Tcl_Parse *parsePtr, Tcl_Token *tokenPtr, - int len, Tcl_Obj **elems, Command *cmdPtr, + Tcl_Obj *replacements, Command *cmdPtr, CompileEnv *envPtr); /* @@ -2739,24 +2739,24 @@ TclCompileEnsemble( * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { - Tcl_Token *tokenPtr; + Tcl_Token *tokenPtr = TokenAfter(parsePtr->tokenPtr); Tcl_Obj *mapObj, *subcmdObj, *targetCmdObj, *listObj, **elems; + Tcl_Obj *replaced = Tcl_NewObj(), *replacement; Tcl_Command ensemble = (Tcl_Command) cmdPtr; - int len, result, flags = 0, i; + int len, result, flags = 0, i, depth = 1; unsigned numBytes; const char *word; - if (parsePtr->numWords < 2) { - return TCL_ERROR; + Tcl_IncrRefCount(replaced); + if (parsePtr->numWords < depth + 1) { + goto failed; } - - tokenPtr = TokenAfter(parsePtr->tokenPtr); if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { /* * Too hard. */ - return TCL_ERROR; + goto failed; } word = tokenPtr[1].start; @@ -2775,7 +2775,7 @@ TclCompileEnsemble( * to proceed. */ - return TCL_ERROR; + goto failed; } /* @@ -2789,7 +2789,7 @@ TclCompileEnsemble( * Figuring out how to compile this has become too much. Bail out. */ - return TCL_ERROR; + goto failed; } /* @@ -2812,7 +2812,7 @@ TclCompileEnsemble( Tcl_Obj *matchObj = NULL; if (Tcl_ListObjGetElements(NULL, listObj, &len, &elems) != TCL_OK) { - return TCL_ERROR; + goto failed; } for (i=0 ; i 1 || Tcl_IsSafe(interp)) { - return TCL_ERROR; + goto failed; } targetCmdObj = elems[0]; @@ -2944,7 +2950,12 @@ TclCompileEnsemble( * Cannot compile. */ - return TCL_ERROR; + goto failed; + } + depth++; + + if (cmdPtr->compileProc == TclCompileEnsemble) { + // TODO: Back round the loop to parse the next level down. } /* @@ -2957,10 +2968,23 @@ TclCompileEnsemble( if (cmdPtr->compileProc != NULL && CompileToCompiledCommand(interp, parsePtr, tokenPtr, len, elems, cmdPtr, envPtr) == TCL_OK) { - return TCL_OK; + goto succeeded; + } else if (len != 1) { + goto failed; } - return CompileToInvokedCommand(interp, parsePtr, tokenPtr, - len, elems, cmdPtr, envPtr); + CompileToInvokedCommand(interp, parsePtr, tokenPtr, replaced, + cmdPtr, envPtr); + succeeded: + if (replaced != NULL) { + Tcl_DecrRefCount(replaced); + } + return TCL_OK; + + failed: + if (replaced != NULL) { + Tcl_DecrRefCount(replaced); + } + return TCL_ERROR; } /* @@ -3038,39 +3062,52 @@ CompileToCompiledCommand( return result; } -static int +static void CompileToInvokedCommand( Tcl_Interp *interp, Tcl_Parse *parsePtr, Tcl_Token *tokenPtr, - int len, - Tcl_Obj **elems, + Tcl_Obj *replacements, Command *cmdPtr, CompileEnv *envPtr) /* Holds resulting instructions. */ { - Tcl_Obj *objPtr = Tcl_NewObj(); + Tcl_Token *tokPtr; + Tcl_Obj *objPtr, **words; char *bytes; - int length, i, literal; - - if (len != 1) { - return TCL_ERROR; - } + int length, i, numWords; // TODO: Generate magic (with new instruction) for setting up the ensemble // rewriting... - for (i=0,tokenPtr=parsePtr->tokenPtr ; inumWords ; i++) { - TclCompileTokens(interp, tokenPtr+1, tokenPtr->numComponents, envPtr); - tokenPtr = TokenAfter(tokenPtr); + Tcl_ListObjGetElements(NULL, replacements, &numWords, &words); + for (i=0,tokPtr=parsePtr->tokenPtr ; inumWords ; i++) { + if (i > 0 && i-1 < numWords) { + bytes = Tcl_GetStringFromObj(words[i-1], &length); + PushLiteral(envPtr, bytes, length); + } else { + TclCompileTokens(interp, tokPtr+1, tokPtr->numComponents, envPtr); + } + tokPtr = TokenAfter(tokPtr); } + + /* + * Push the name of the command we're actually dispatching to as part of + * the implementation. + */ + + objPtr = Tcl_NewObj(); Tcl_GetCommandFullName(interp, (Tcl_Command) cmdPtr, objPtr); bytes = Tcl_GetStringFromObj(objPtr, &length); - literal = TclRegisterNewCmdLiteral(envPtr, bytes, length); + PushLiteral(envPtr, bytes, length); TclDecrRefCount(objPtr); - TclEmitPush(literal, envPtr); + + /* + * Do the replacing dispatch. + */ + TclEmitInstInt4(INST_INVOKE_REPLACE, parsePtr->numWords, envPtr); - TclAdjustStackDepth(-1, envPtr); - return TCL_OK; + TclEmitInt1(numWords+1, envPtr); + TclAdjustStackDepth(-1, envPtr); /* Correction to stack depth calcs. */ } /* diff --git a/generic/tclExecute.c b/generic/tclExecute.c index 3fab3cc..b0da17d 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -2974,6 +2974,7 @@ TEBCresume( case INST_INVOKE_REPLACE: objc = TclGetUInt4AtPtr(pc+1); + opnd = TclGetUInt1AtPtr(pc+5); objPtr = POP_OBJECT(); objv = &OBJ_AT_DEPTH(objc-1); cleanup = objc; @@ -2983,8 +2984,7 @@ TEBCresume( if (traceInstructions) { strncpy(cmdNameBuf, TclGetString(objv[0]), 20); - TRACE(("%u => call (implementation %s) ", - objc, O2S(objPtr))); + TRACE(("%u => call (implementation %s) ", objc, O2S(objPtr))); } else { fprintf(stdout, "%d: (%u) invoking (using implementation %s) ", @@ -2992,7 +2992,13 @@ TEBCresume( O2S(objPtr)); } for (i = 0; i < objc; i++) { - TclPrintObject(stdout, objv[i], 15); + if (i < opnd) { + fprintf(stdout, "<"); + TclPrintObject(stdout, objv[i], 15); + fprintf(stdout, ">"); + } else { + TclPrintObject(stdout, objv[i], 15); + } fprintf(stdout, " "); } fprintf(stdout, "\n"); @@ -3000,15 +3006,15 @@ TEBCresume( } #endif /*TCL_COMPILE_DEBUG*/ { - Tcl_Obj *copyPtr = Tcl_NewListObj(objc - 1, NULL); + Tcl_Obj *copyPtr = Tcl_NewListObj(objc - opnd + 1, NULL); register List *listRepPtr = copyPtr->internalRep.twoPtrValue.ptr1; Tcl_Obj **copyObjv = &listRepPtr->elements; int i; - listRepPtr->elemCount = objc - 1; + listRepPtr->elemCount = objc - opnd + 1; copyObjv[0] = objPtr; - memcpy(copyObjv+1, objv+2, sizeof(Tcl_Obj *) * (objc - 2)); - for (i=1 ; icodeStart); } iPtr->ensembleRewrite.sourceObjs = objv; - iPtr->ensembleRewrite.numRemovedObjs = 2; + iPtr->ensembleRewrite.numRemovedObjs = opnd; iPtr->ensembleRewrite.numInsertedObjs = 1; DECACHE_STACK_INFO(); - pc += 5; + pc += 6; TEBC_YIELD(); TclNRAddCallback(interp, TclClearRootEnsemble, NULL,NULL,NULL,NULL); iPtr->evalFlags |= TCL_EVAL_REDIRECT; -- cgit v0.12