summaryrefslogtreecommitdiffstats
path: root/generic/tclCompile.c
diff options
context:
space:
mode:
authordkf <donal.k.fellows@manchester.ac.uk>2012-11-05 14:34:36 (GMT)
committerdkf <donal.k.fellows@manchester.ac.uk>2012-11-05 14:34:36 (GMT)
commitcd1f27f0cf22ec6b5b83f2fd48c1ba93e5c27be2 (patch)
tree72d036a8e1b318a022447f968b7a58b12d6e9598 /generic/tclCompile.c
parent259635cd9b7b5e6be9e1bc44a5d2a7d3a2536743 (diff)
downloadtcl-cd1f27f0cf22ec6b5b83f2fd48c1ba93e5c27be2.zip
tcl-cd1f27f0cf22ec6b5b83f2fd48c1ba93e5c27be2.tar.gz
tcl-cd1f27f0cf22ec6b5b83f2fd48c1ba93e5c27be2.tar.bz2
Added compilation of [array exists], [array set] and [array unset]. Fixed a whole bunch of issues with opcode issuing that were causing problems with stack depth calculations.merge_to_trunk
Diffstat (limited to 'generic/tclCompile.c')
-rw-r--r--generic/tclCompile.c48
1 files changed, 45 insertions, 3 deletions
diff --git a/generic/tclCompile.c b/generic/tclCompile.c
index 2c87b34..309682d 100644
--- a/generic/tclCompile.c
+++ b/generic/tclCompile.c
@@ -372,13 +372,13 @@ InstructionDesc const tclInstructionTable[] = {
* Stack: ... value => ...
* Note that the jump table contains offsets relative to the PC when
* it points to this instruction; the code is relocatable. */
- {"upvar", 5, 0, 1, {OPERAND_LVT4}},
+ {"upvar", 5, -1, 1, {OPERAND_LVT4}},
/* finds level and otherName in stack, links to local variable at
* index op1. Leaves the level on stack. */
- {"nsupvar", 5, 0, 1, {OPERAND_LVT4}},
+ {"nsupvar", 5, -1, 1, {OPERAND_LVT4}},
/* finds namespace and otherName in stack, links to local variable at
* index op1. Leaves the namespace on stack. */
- {"variable", 5, 0, 1, {OPERAND_LVT4}},
+ {"variable", 5, -1, 1, {OPERAND_LVT4}},
/* finds namespace and otherName in stack, links to local variable at
* index op1. Leaves the namespace on stack. */
{"syntax", 9, -1, 2, {OPERAND_INT4, OPERAND_UINT4}},
@@ -509,6 +509,26 @@ InstructionDesc const tclInstructionTable[] = {
* context.
* Stack: ... value => ... boolean */
+ {"arrayExistsStk", 1, 0, 0, {OPERAND_NONE}},
+ /* Looks up the element on the top of the stack and tests whether it
+ * is an array. Pushes a boolean describing whether this is the
+ * case. Also runs the whole-array trace on the named variable, so can
+ * throw anything.
+ * Stack: ... varName => ... boolean */
+ {"arrayExistsImm", 5, +1, 1, {OPERAND_UINT4}},
+ /* Looks up the variable indexed by opnd and tests whether it is an
+ * array. Pushes a boolean describing whether this is the case. Also
+ * runs the whole-array trace on the named variable, so can throw
+ * anything.
+ * Stack: ... => ... boolean */
+ {"arrayMakeStk", 1, -1, 0, {OPERAND_NONE}},
+ /* Forces the element on the top of the stack to be the name of an
+ * array.
+ * Stack: ... varName => ... */
+ {"arrayMakeImm", 5, 0, 1, {OPERAND_UINT4}},
+ /* Forces the variable indexed by opnd to be an array. Does not touch
+ * the stack. */
+
{NULL, 0, 0, 0, {OPERAND_NONE}}
};
@@ -1751,6 +1771,9 @@ TclCompileScript(
unsigned savedCodeNext =
envPtr->codeNext - envPtr->codeStart;
int update = 0;
+#ifdef TCL_COMPILE_DEBUG
+ int startStackDepth = envPtr->currStackDepth;
+#endif
/*
* Mark the start of the command; the proper bytecode
@@ -1794,6 +1817,25 @@ TclCompileScript(
envPtr);
if (code == TCL_OK) {
+ /*
+ * Confirm that the command compiler generated a
+ * single value on the stack as its result. This
+ * is only done in debugging mode, as it *should*
+ * be correct and normal users have no reasonable
+ * way to fix it anyway.
+ */
+
+#ifdef TCL_COMPILE_DEBUG
+ int diff = envPtr->currStackDepth-startStackDepth;
+
+ if (diff != 1 && (diff != 0 ||
+ *(envPtr->codeNext-1) != INST_DONE)) {
+ Tcl_Panic("bad stack adjustment when compiling"
+ " %.*s (was %d instead of 1)",
+ parsePtr->tokenPtr->size,
+ parsePtr->tokenPtr->start, diff);
+ }
+#endif
if (update) {
/*
* Fix the bytecode length.