summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--generic/tclCompCmds.c42
-rw-r--r--generic/tclCompile.c1
-rw-r--r--generic/tclCompile.h3
-rw-r--r--generic/tclExecute.c19
4 files changed, 36 insertions, 29 deletions
diff --git a/generic/tclCompCmds.c b/generic/tclCompCmds.c
index bdab2ff..cd43cfc 100644
--- a/generic/tclCompCmds.c
+++ b/generic/tclCompCmds.c
@@ -2458,8 +2458,6 @@ CompileEachloopCmd(
ForeachInfo *infoPtr; /* Points to the structure describing this
* foreach command. Stored in a AuxData
* record in the ByteCode. */
- int collectVar = -1; /* Index of temp var holding the result var
- * index. */
Tcl_Token *tokenPtr, *bodyTokenPtr;
int jumpBackOffset, infoIndex, range;
@@ -2575,13 +2573,6 @@ CompileEachloopCmd(
* We will compile the foreach command.
*/
- if (collect == TCL_EACH_COLLECT) {
- collectVar = AnonymousLocal(envPtr);
- if (collectVar < 0) {
- return TCL_ERROR;
- }
- }
-
code = TCL_OK;
/*
@@ -2612,6 +2603,14 @@ CompileEachloopCmd(
infoIndex = TclCreateAuxData(infoPtr, &tclNewForeachInfoType, envPtr);
/*
+ * Create the collecting object, unshared.
+ */
+
+ if (collect == TCL_EACH_COLLECT) {
+ TclEmitInstInt4(INST_LIST, 0, envPtr);
+ }
+
+ /*
* Evaluate each value list and leave it on stack.
*/
@@ -2623,16 +2622,6 @@ CompileEachloopCmd(
}
}
- /*
- * Create temporary variable to capture return values from loop body.
- */
-
- if (collect == TCL_EACH_COLLECT) {
- PushStringLiteral(envPtr, "");
- Emit14Inst( INST_STORE_SCALAR, collectVar, envPtr);
- TclEmitOpcode( INST_POP, envPtr);
- }
-
TclEmitInstInt4(INST_FOREACH_START, infoIndex, envPtr);
/*
@@ -2646,9 +2635,10 @@ CompileEachloopCmd(
ExceptionRangeEnds(envPtr, range);
if (collect == TCL_EACH_COLLECT) {
- Emit14Inst( INST_LAPPEND_SCALAR, collectVar,envPtr);
+ TclEmitOpcode(INST_LMAP_COLLECT, envPtr);
+ } else {
+ TclEmitOpcode( INST_POP, envPtr);
}
- TclEmitOpcode( INST_POP, envPtr);
/*
* Bottom of loop code: assign each loop variable and check whether
@@ -2672,15 +2662,11 @@ CompileEachloopCmd(
infoPtr->loopCtTemp = -jumpBackOffset;
/*
- * The command's result is an empty string if not collecting, or the
- * list of results from evaluating the loop body.
+ * The command's result is an empty string if not collecting. If
+ * collecting, it is automatically left on stack after FOREACH_END.
*/
- if (collect == TCL_EACH_COLLECT) {
- Emit14Inst( INST_LOAD_SCALAR, collectVar, envPtr);
- TclEmitInstInt1(INST_UNSET_SCALAR, 0, envPtr);
- TclEmitInt4( collectVar, envPtr);
- } else {
+ if (collect != TCL_EACH_COLLECT) {
PushStringLiteral(envPtr, "");
}
diff --git a/generic/tclCompile.c b/generic/tclCompile.c
index 7cd9796..c7b7875 100644
--- a/generic/tclCompile.c
+++ b/generic/tclCompile.c
@@ -554,6 +554,7 @@ InstructionDesc const tclInstructionTable[] = {
{"foreach_step", 1, 0, 0, {OPERAND_NONE}},
/* "Step" or begin next iteration of foreach loop. */
{"foreach_end", 1, 0, 0, {OPERAND_NONE}},
+ {"lmap_collect", 1, 0, 0, {OPERAND_NONE}},
{NULL, 0, 0, 0, {OPERAND_NONE}}
};
diff --git a/generic/tclCompile.h b/generic/tclCompile.h
index 8b1724b..7f62849 100644
--- a/generic/tclCompile.h
+++ b/generic/tclCompile.h
@@ -773,9 +773,10 @@ typedef struct ByteCode {
#define INST_FOREACH_START 166
#define INST_FOREACH_STEP 167
#define INST_FOREACH_END 168
+#define INST_LMAP_COLLECT 169
/* The last opcode */
-#define LAST_INST_OPCODE 168
+#define LAST_INST_OPCODE 169
/*
* Table describing the Tcl bytecode instructions: their name (for displaying
diff --git a/generic/tclExecute.c b/generic/tclExecute.c
index a3083bc..9261f19 100644
--- a/generic/tclExecute.c
+++ b/generic/tclExecute.c
@@ -6345,6 +6345,25 @@ TEBCresume(
infoPtr = tmpPtr->internalRep.otherValuePtr;
numLists = infoPtr->numLists;
NEXT_INST_V(1, numLists+2, 0);
+
+ case INST_LMAP_COLLECT:
+ /*
+ * This instruction is only issued by lmap. The stack is:
+ * - result
+ * - infoPtr
+ * - loop counters
+ * - valLists
+ * - collecting obj (unshared)
+ * The instruction lappends the result to the collecting obj.
+ */
+
+ tmpPtr = OBJ_AT_DEPTH(1);
+ infoPtr = tmpPtr->internalRep.otherValuePtr;
+ numLists = infoPtr->numLists;
+
+ objPtr = OBJ_AT_DEPTH(3 + numLists);
+ Tcl_ListObjAppendElement(NULL, objPtr, OBJ_AT_TOS);
+ NEXT_INST_F(1, 1, 0);
}
case INST_BEGIN_CATCH4: