summaryrefslogtreecommitdiffstats
path: root/generic/tclCompCmds.c
diff options
context:
space:
mode:
authordkf <donal.k.fellows@manchester.ac.uk>2013-05-15 10:38:25 (GMT)
committerdkf <donal.k.fellows@manchester.ac.uk>2013-05-15 10:38:25 (GMT)
commit1eacac1aa2e8e1f6a11ad280d4d5ac4774672c81 (patch)
tree91f996a24941dbc19754fafc12aa722dfe281445 /generic/tclCompCmds.c
parentd7477a9621b19997f770d8df75b8a071704973d0 (diff)
downloadtcl-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.c39
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;
}