summaryrefslogtreecommitdiffstats
path: root/generic/tclCompile.c
diff options
context:
space:
mode:
authordkf <donal.k.fellows@manchester.ac.uk>2013-06-03 09:37:14 (GMT)
committerdkf <donal.k.fellows@manchester.ac.uk>2013-06-03 09:37:14 (GMT)
commitae411458670d6ca50c9516ed742f9b06855637a9 (patch)
treed80bc0f5102c3fc108c590e5e6011d1a5dcd7c07 /generic/tclCompile.c
parentc72504b5e8f17039d8438be6e3f41d5b8e2928eb (diff)
downloadtcl-ae411458670d6ca50c9516ed742f9b06855637a9.zip
tcl-ae411458670d6ca50c9516ed742f9b06855637a9.tar.gz
tcl-ae411458670d6ca50c9516ed742f9b06855637a9.tar.bz2
Generate [continue] optimally in [for] next clauses. Add tests for Bug 3614226.
Diffstat (limited to 'generic/tclCompile.c')
-rw-r--r--generic/tclCompile.c35
1 files changed, 34 insertions, 1 deletions
diff --git a/generic/tclCompile.c b/generic/tclCompile.c
index 96f8683..f2e9329 100644
--- a/generic/tclCompile.c
+++ b/generic/tclCompile.c
@@ -3463,7 +3463,9 @@ TclCreateExceptRange(
rangePtr->continueOffset = -1;
rangePtr->catchOffset = -1;
auxPtr = &envPtr->exceptAuxArrayPtr[index];
+ auxPtr->supportsContinue = 1;
auxPtr->stackDepth = envPtr->currStackDepth;
+ auxPtr->expandTarget = envPtr->expandCount;
auxPtr->numBreakTargets = 0;
auxPtr->breakTargets = NULL;
auxPtr->allocBreakTargets = 0;
@@ -3490,6 +3492,7 @@ TclCreateExceptRange(
ExceptionRange *
TclGetInnermostExceptionRange(
CompileEnv *envPtr,
+ int returnCode,
ExceptionAux **auxPtrPtr)
{
int exnIdx = -1, i;
@@ -3499,7 +3502,9 @@ TclGetInnermostExceptionRange(
if (CurrentOffset(envPtr) >= rangePtr->codeOffset &&
(rangePtr->numCodeBytes == -1 || CurrentOffset(envPtr) <
- rangePtr->codeOffset+rangePtr->numCodeBytes)) {
+ rangePtr->codeOffset+rangePtr->numCodeBytes) &&
+ (returnCode != TCL_CONTINUE ||
+ envPtr->exceptAuxArrayPtr[i].supportsContinue)) {
exnIdx = i;
}
}
@@ -3512,6 +3517,19 @@ TclGetInnermostExceptionRange(
return &envPtr->exceptArrayPtr[exnIdx];
}
+/*
+ * ---------------------------------------------------------------------
+ *
+ * TclAddLoopBreakFixup, TclAddLoopContinueFixup --
+ *
+ * Adds a place that wants to break/continue to the loop exception range
+ * tracking that will be fixed up once the loop can be finalized. These
+ * functions will generate an INST_JUMP4 that will be fixed up during the
+ * loop finalization.
+ *
+ * ---------------------------------------------------------------------
+ */
+
void
TclAddLoopBreakFixup(
CompileEnv *envPtr,
@@ -3535,6 +3553,7 @@ TclAddLoopBreakFixup(
}
}
auxPtr->breakTargets[auxPtr->numBreakTargets - 1] = CurrentOffset(envPtr);
+ TclEmitInstInt4(INST_JUMP4, 0, envPtr);
}
void
@@ -3561,7 +3580,21 @@ TclAddLoopContinueFixup(
}
auxPtr->continueTargets[auxPtr->numContinueTargets - 1] =
CurrentOffset(envPtr);
+ TclEmitInstInt4(INST_JUMP4, 0, envPtr);
}
+
+/*
+ * ---------------------------------------------------------------------
+ *
+ * TclFinalizeLoopExceptionRange --
+ *
+ * Finalizes a loop exception range, binding the registered [break] and
+ * [continue] implementations so that they jump to the correct place.
+ * Note that this must only be called after *all* the exception range
+ * target offsets have been set.
+ *
+ * ---------------------------------------------------------------------
+ */
void
TclFinalizeLoopExceptionRange(