mirror of
https://github.com/dart-lang/sdk
synced 2024-09-19 15:01:29 +00:00
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:
parent
7b516974b2
commit
61d8882842
|
@ -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),
|
||||
condBuilder.add(
|
||||
new ir.LetCont(exitContinuation,
|
||||
new ir.LetCont(bodyContinuation,
|
||||
new ir.Branch(new ir.IsTrue(condition),
|
||||
bodyContinuation,
|
||||
exitContinuation));
|
||||
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),
|
||||
condBuilder.add(
|
||||
new ir.LetCont(exitContinuation,
|
||||
new ir.LetCont(bodyContinuation,
|
||||
new ir.Branch(new ir.IsTrue(condition),
|
||||
bodyContinuation,
|
||||
exitContinuation));
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue