diff options
author | dkf <dkf@noemail.net> | 2013-01-02 15:10:00 (GMT) |
---|---|---|
committer | dkf <dkf@noemail.net> | 2013-01-02 15:10:00 (GMT) |
commit | 886c0999aec4e850749bd45ca1feb9cf378a2bf6 (patch) | |
tree | 8390f95edaf4e8f260b6af49e4fb249016cee354 /generic/tclEnsemble.c | |
parent | b9a1d6098ede33adf621c5dd3cdd84cf965668d0 (diff) | |
download | tcl-886c0999aec4e850749bd45ca1feb9cf378a2bf6.zip tcl-886c0999aec4e850749bd45ca1feb9cf378a2bf6.tar.gz tcl-886c0999aec4e850749bd45ca1feb9cf378a2bf6.tar.bz2 |
Passing more tests.
FossilOrigin-Name: f3f4dfddded9ffdf5aa273286f9609f1434826e2
Diffstat (limited to 'generic/tclEnsemble.c')
-rw-r--r-- | generic/tclEnsemble.c | 119 |
1 files changed, 78 insertions, 41 deletions
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<len ; i++) { str = Tcl_GetStringFromObj(elems[i], &sclen); @@ -2823,8 +2823,9 @@ TclCompileEnsemble( result = Tcl_DictObjGet(NULL, mapObj,elems[i], &targetCmdObj); if (result != TCL_OK || targetCmdObj == NULL) { - return TCL_ERROR; + goto failed; } + replacement = elems[i]; goto doneMapLookup; } @@ -2840,18 +2841,19 @@ TclCompileEnsemble( if ((flags & TCL_ENSEMBLE_PREFIX) && strncmp(word, str, numBytes) == 0) { if (matchObj != NULL) { - return TCL_ERROR; + goto failed; } matchObj = elems[i]; } } if (matchObj == NULL) { - return TCL_ERROR; + goto failed; } result = Tcl_DictObjGet(NULL, mapObj, matchObj, &targetCmdObj); if (result != TCL_OK || targetCmdObj == NULL) { - return TCL_ERROR; + goto failed; } + replacement = matchObj; } else { Tcl_DictSearch s; int done, matched; @@ -2863,14 +2865,15 @@ TclCompileEnsemble( TclNewStringObj(subcmdObj, word, (int) numBytes); result = Tcl_DictObjGet(NULL, mapObj, subcmdObj, &targetCmdObj); - TclDecrRefCount(subcmdObj); if (result == TCL_OK && targetCmdObj != NULL) { /* * Got it. Skip the fiddling around with prefixes. */ + replacement = subcmdObj; goto doneMapLookup; } + TclDecrRefCount(subcmdObj); /* * We've not literally got a valid subcommand. But maybe we have a @@ -2878,7 +2881,7 @@ TclCompileEnsemble( */ if (!(flags & TCL_ENSEMBLE_PREFIX)) { - return TCL_ERROR; + goto failed; } /* @@ -2888,6 +2891,7 @@ TclCompileEnsemble( Tcl_DictObjFirst(NULL, mapObj, &s, &subcmdObj, &tmpObj, &done); matched = 0; + replacement = NULL; /* Silence, fool compiler! */ while (!done) { if (strncmp(TclGetString(subcmdObj), word, numBytes) == 0) { if (matched++) { @@ -2898,6 +2902,7 @@ TclCompileEnsemble( break; } + replacement = subcmdObj; targetCmdObj = tmpObj; } Tcl_DictObjNext(&s, &subcmdObj, &tmpObj, &done); @@ -2910,7 +2915,7 @@ TclCompileEnsemble( */ if (matched != 1) { - return TCL_ERROR; + goto failed; } } @@ -2924,11 +2929,12 @@ TclCompileEnsemble( */ doneMapLookup: + Tcl_ListObjAppendElement(NULL, replaced, replacement); if (Tcl_ListObjGetElements(NULL, targetCmdObj, &len, &elems) != TCL_OK) { - return TCL_ERROR; + goto failed; } if (len > 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 ; i<parsePtr->numWords ; i++) { - TclCompileTokens(interp, tokenPtr+1, tokenPtr->numComponents, envPtr); - tokenPtr = TokenAfter(tokenPtr); + Tcl_ListObjGetElements(NULL, replacements, &numWords, &words); + for (i=0,tokPtr=parsePtr->tokenPtr ; i<parsePtr->numWords ; 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. */ } /* |