dart2dart: Fix a scoping bug in the translation of loops.

Side effects to local variables in the condition must be visible after
the loop exit.  Thus the translation of the statements following a
loop must be in the scope of the condition.

R=sigurdm@google.com
BUG=

Review URL: https://codereview.chromium.org//459763003

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@39121 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
kmillikin@google.com 2014-08-12 08:55:15 +00:00
parent 7b516974b2
commit 61d8882842
3 changed files with 41 additions and 34 deletions

View file

@ -546,10 +546,6 @@ class IrBuilder extends ResolvedVisitor<ir.Primitive> {
context.add(new ir.InvokeContinuation(join, args, recursive: true));
context.current = null;
}
assert(environment.index2value.length <= join.parameters.length);
for (int i = 0; i < environment.index2value.length; ++i) {
environment.index2value[i] = join.parameters[i];
}
}
ir.Primitive visitFor(ast.For node) {
@ -571,9 +567,9 @@ class IrBuilder extends ResolvedVisitor<ir.Primitive> {
//
// [[initializer]];
// let cont loop(x, ...) =
// let prim cond = [[condition]] in
// let cont exit() = [[successor]] in
// let cont body() = [[body]]; [[update]]; loop(v, ...) in
// let prim cond = [[condition]] in
// branch cond (body, exit) in
// loop(v, ...)
@ -600,28 +596,25 @@ class IrBuilder extends ResolvedVisitor<ir.Primitive> {
// continuation if control flow reaches the end of the body (update).
ir.Continuation bodyContinuation = new ir.Continuation([]);
ir.Continuation exitContinuation = new ir.Continuation([]);
condBuilder.add(new ir.Branch(new ir.IsTrue(condition),
bodyContinuation,
exitContinuation));
condBuilder.add(
new ir.LetCont(exitContinuation,
new ir.LetCont(bodyContinuation,
new ir.Branch(new ir.IsTrue(condition),
bodyContinuation,
exitContinuation))));
List<ir.Parameter> parameters = condBuilder.parameters;
ir.Continuation loopContinuation = new ir.Continuation(parameters);
// Copy the environment here because invokeJoin will update it for the
// join-point continuation.
List<ir.Primitive> entryArguments =
new List<ir.Primitive>.from(environment.index2value);
if (bodyBuilder.isOpen) {
invokeRecursiveJoin(loopContinuation, [bodyBuilder]);
}
bodyContinuation.body = bodyBuilder.root;
ir.Expression resultContext =
new ir.LetCont(exitContinuation,
new ir.LetCont(bodyContinuation,
condBuilder.root));
loopContinuation.body = resultContext;
loopContinuation.body = condBuilder.root;
add(new ir.LetCont(loopContinuation,
new ir.InvokeContinuation(loopContinuation, entryArguments)));
current = resultContext;
new ir.InvokeContinuation(loopContinuation,
environment.index2value)));
current = condBuilder.current;
environment = condBuilder.environment;
return null;
}
@ -692,9 +685,9 @@ class IrBuilder extends ResolvedVisitor<ir.Primitive> {
// The CPS translation of [[while (condition) body; successor]] is:
//
// let cont loop(x, ...) =
// let prim cond = [[condition]] in
// let cont exit() = [[successor]] in
// let cont body() = [[body]]; continue(v, ...) in
// let prim cond = [[condition]] in
// branch cond (body, exit) in
// loop(v, ...)
@ -709,28 +702,25 @@ class IrBuilder extends ResolvedVisitor<ir.Primitive> {
// continuation if control flow reaches the end of the body.
ir.Continuation bodyContinuation = new ir.Continuation([]);
ir.Continuation exitContinuation = new ir.Continuation([]);
condBuilder.add(new ir.Branch(new ir.IsTrue(condition),
bodyContinuation,
exitContinuation));
condBuilder.add(
new ir.LetCont(exitContinuation,
new ir.LetCont(bodyContinuation,
new ir.Branch(new ir.IsTrue(condition),
bodyContinuation,
exitContinuation))));
List<ir.Parameter> parameters = condBuilder.parameters;
ir.Continuation loopContinuation = new ir.Continuation(parameters);
// Copy the environment here because invokeJoin will update it for the
// join-point continuation.
List<ir.Primitive> entryArguments =
new List<ir.Primitive>.from(environment.index2value);
if (bodyBuilder.isOpen) {
invokeRecursiveJoin(loopContinuation, [bodyBuilder]);
}
bodyContinuation.body = bodyBuilder.root;
ir.Expression resultContext =
new ir.LetCont(exitContinuation,
new ir.LetCont(bodyContinuation,
condBuilder.root));
loopContinuation.body = resultContext;
loopContinuation.body = condBuilder.root;
add(new ir.LetCont(loopContinuation,
new ir.InvokeContinuation(loopContinuation, entryArguments)));
current = resultContext;
new ir.InvokeContinuation(loopContinuation,
environment.index2value)));
current = condBuilder.current;
environment = condBuilder.environment;
return null;
}

View file

@ -45,6 +45,13 @@ class Helper {
}
status = 1;
}
static int f6() {
// Verify that side effects in the condition are visible after the loop.
int i = 0;
for (; ++i < 3; ) {}
return i;
}
}
class ForTest {
@ -67,6 +74,8 @@ class ForTest {
Helper.f5();
Expect.equals(1, Helper.status);
Expect.equals(3, Helper.f6());
}
}

View file

@ -27,6 +27,13 @@ class Helper {
}
return i;
}
static int f4() {
// Verify that side effects in the condition are visible after the loop.
int i = 0;
while (++i < 3) {}
return i;
}
}
class WhileTest {
@ -40,6 +47,7 @@ class WhileTest {
Expect.equals(0, Helper.f3(0));
Expect.equals(1, Helper.f3(1));
Expect.equals(2, Helper.f3(2));
Expect.equals(3, Helper.f4());
}
}