From 504aaad8ad50f859a3898bbc0f7e098a035a2479 Mon Sep 17 00:00:00 2001 From: dkf Date: Wed, 21 Nov 2007 23:30:32 +0000 Subject: Generalize the ensemble compiler further. Still doesn't precopile rewrites, but now handles many other things making the compiler at least useful. --- ChangeLog | 8 +++ generic/tclCompCmds.c | 188 ++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 146 insertions(+), 50 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7d9ae95..4e1b706 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2007-11-21 Donal K. Fellows + + * generic/tclCompCmds.c (TclCompileEnsemble): Rewrote the ensemble + compiler to remove many of the limitations. Can now compile scripts + that use unique prefixes of subcommands, and which have mappings of a + command to multiple words (provided the first is a compilable command + of course). + 2007-11-21 Donal K. Fellows * generic/tclNamesp.c (TclMakeEnsemble): Factor out the code to set up diff --git a/generic/tclCompCmds.c b/generic/tclCompCmds.c index ba85435..2f203e74 100644 --- a/generic/tclCompCmds.c +++ b/generic/tclCompCmds.c @@ -12,7 +12,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclCompCmds.c,v 1.128 2007/11/16 14:11:52 dkf Exp $ + * RCS: @(#) $Id: tclCompCmds.c,v 1.129 2007/11/21 23:30:39 dkf Exp $ */ #include "tclInt.h" @@ -5863,7 +5863,7 @@ TclCompileEnsemble( Tcl_Obj *mapObj, *subcmdObj, *targetCmdObj, *listObj, **elems; Tcl_Command ensemble = (Tcl_Command) cmdPtr; Tcl_Parse synthetic; - int len, numBytes, result; + int len, numBytes, result, flags = 0, i; const char *word; if (parsePtr->numWords < 2) { @@ -5898,30 +5898,11 @@ TclCompileEnsemble( return TCL_ERROR; } - TclNewStringObj(subcmdObj, word, numBytes); - if (Tcl_DictObjGet(NULL, mapObj, subcmdObj, &targetCmdObj) != TCL_OK - || targetCmdObj == NULL) { - /* - * We've not got a valid subcommand. - */ - - TclDecrRefCount(subcmdObj); - return TCL_ERROR; - } - TclDecrRefCount(subcmdObj); - /* - * The command we map to is the first word out of the map element. Note - * that we reject dealing with lists that are multiple elements long here; - * our rewriting-fu is not yet strong enough. + * Next, get the flags. We need them on several code paths. */ - if (Tcl_ListObjGetElements(NULL, targetCmdObj, &len, &elems) != TCL_OK - || len != 1) { - return TCL_ERROR; - } - targetCmdObj = elems[0]; - Tcl_IncrRefCount(targetCmdObj); + (void) Tcl_GetEnsembleFlags(NULL, ensemble, &flags); /* * Check to see if there's also a subcommand list; must check to see if @@ -5931,29 +5912,134 @@ TclCompileEnsemble( (void) Tcl_GetEnsembleSubcommandList(NULL, ensemble, &listObj); if (listObj != NULL) { - int i, sclen; - char *str; + int sclen; + const char *str; + Tcl_Obj *matchObj = NULL; - if (Tcl_ListObjGetElements(NULL, listObj, &len,&elems) != TCL_OK){ - TclDecrRefCount(targetCmdObj); + if (Tcl_ListObjGetElements(NULL, listObj, &len, &elems) != TCL_OK) { return TCL_ERROR; } for (i=0 ; i 1 && Tcl_IsSafe(interp)) { + return TCL_ERROR; + } + targetCmdObj = elems[0]; + + Tcl_IncrRefCount(targetCmdObj); cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, targetCmdObj); TclDecrRefCount(targetCmdObj); if (cmdPtr == NULL || cmdPtr->compileProc == NULL) { @@ -5966,20 +6052,15 @@ TclCompileEnsemble( } /* - * Should check if we mapped to another ensemble here, and go round the - * peek-inside scheme above if so. [TO-DO] - */ - - /* * Now we've done the mapping process, can now actually try to compile. * We do this by handing off to the subcommand's actual compiler. But to - * do that, we have to perform some trickery to rewrite the arguments. + * do that, we have to perform some trickery to rewrite the arguments. */ argTokensPtr = TokenAfter(tokenPtr); memcpy(&synthetic, parsePtr, sizeof(Tcl_Parse)); - synthetic.numWords--; - synthetic.numTokens -= (argTokensPtr - parsePtr->tokenPtr) - 2; + synthetic.numWords -= 2 - len; + synthetic.numTokens -= (argTokensPtr - parsePtr->tokenPtr) - 2*len; if (synthetic.numTokens <= NUM_STATIC_TOKENS) { synthetic.tokenPtr = synthetic.staticTokens; synthetic.tokensAvailable = NUM_STATIC_TOKENS; @@ -5990,19 +6071,26 @@ TclCompileEnsemble( } /* - * Now we have the space to work in, install something rewritten. + * Now we have the space to work in, install something rewritten. Note + * that we are here praying for all our might that none of these words are + * a script; the error detection code will crash if that happens and there + * is nothing we can do to avoid it! */ - synthetic.tokenPtr[0].type = TCL_TOKEN_SIMPLE_WORD; - synthetic.tokenPtr[0].start = parsePtr->tokenPtr[0].start; - synthetic.tokenPtr[0].size = (tokenPtr->start + tokenPtr->size) - - parsePtr->tokenPtr[0].start; - synthetic.tokenPtr[0].numComponents = 1; + for (i=0 ; i