diff options
author | dkf <donal.k.fellows@manchester.ac.uk> | 2013-05-15 10:38:25 (GMT) |
---|---|---|
committer | dkf <donal.k.fellows@manchester.ac.uk> | 2013-05-15 10:38:25 (GMT) |
commit | 1eacac1aa2e8e1f6a11ad280d4d5ac4774672c81 (patch) | |
tree | 91f996a24941dbc19754fafc12aa722dfe281445 /generic/tclCompCmds.c | |
parent | d7477a9621b19997f770d8df75b8a071704973d0 (diff) | |
download | tcl-1eacac1aa2e8e1f6a11ad280d4d5ac4774672c81.zip tcl-1eacac1aa2e8e1f6a11ad280d4d5ac4774672c81.tar.gz tcl-1eacac1aa2e8e1f6a11ad280d4d5ac4774672c81.tar.bz2 |
A better technique for [list {*}blah]. Remove the INST_LIST_EXPANDED opcode (and the complex machinery associated with it) as as it is no longer needed.
Diffstat (limited to 'generic/tclCompCmds.c')
-rw-r--r-- | generic/tclCompCmds.c | 39 |
1 files changed, 37 insertions, 2 deletions
diff --git a/generic/tclCompCmds.c b/generic/tclCompCmds.c index c2495bd..a5678bf 100644 --- a/generic/tclCompCmds.c +++ b/generic/tclCompCmds.c @@ -4466,7 +4466,7 @@ TclCompileListCmd( { DefineLineInformation; /* TIP #280 */ Tcl_Token *valueTokenPtr; - int i, numWords; + int i, numWords, concat, build; Tcl_Obj *listObj, *objPtr; if (parsePtr->numWords == 1) { @@ -4521,11 +4521,46 @@ TclCompileListCmd( numWords = parsePtr->numWords; valueTokenPtr = TokenAfter(parsePtr->tokenPtr); + concat = build = 0; for (i = 1; i < numWords; i++) { + if (valueTokenPtr->type == TCL_TOKEN_EXPAND_WORD && build > 0) { + TclEmitInstInt4( INST_LIST, build, envPtr); + if (concat) { + TclEmitOpcode( INST_LIST_CONCAT, envPtr); + } + build = 0; + concat = 1; + } CompileWord(envPtr, valueTokenPtr, interp, i); + if (valueTokenPtr->type == TCL_TOKEN_EXPAND_WORD) { + if (concat) { + TclEmitOpcode( INST_LIST_CONCAT, envPtr); + } else { + concat = 1; + } + } else { + build++; + } valueTokenPtr = TokenAfter(valueTokenPtr); } - TclEmitInstInt4( INST_LIST, numWords - 1, envPtr); + if (build > 0) { + TclEmitInstInt4( INST_LIST, build, envPtr); + if (concat) { + TclEmitOpcode( INST_LIST_CONCAT, envPtr); + } + } + + /* + * If there was just one expanded word, we must ensure that it is a list + * at this point. We use an [lrange ... 0 end] for this (instead of + * [llength], as with literals) as we must drop any string representation + * that might be hanging around. + */ + + if (concat && numWords == 2) { + TclEmitInstInt4( INST_LIST_RANGE_IMM, 0, envPtr); + TclEmitInt4( -2, envPtr); + } return TCL_OK; } |