Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(173)

Unified Diff: pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart

Issue 1001793002: dart2js: Add support for do/while loops to the CPS backend. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Ummm, semicolon? Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
index 4d4e98a76151fd66653b4ea698c045e0795fb3ef..87203a2b1e5b13c412e29782d33cdc19f7a66513 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
@@ -1225,11 +1225,11 @@ abstract class IrBuilder {
//
// let cont continue(x, ...) =
// let prim cond = [[condition]] in
- // let cont break() = [[successor]] in
- // let cont exit() = break(v, ...) in
- // let cont body() = [[body]]; continue(v, ...) in
- // branch cond (body, exit) in
- // continue(v, ...)
+ // let cont break(x, ...) = [[successor]] in
+ // let cont exit() = break(v, ...)
+ // and body() = [[body]]; continue(v, ...)
+ // in branch cond (body, exit)
+ // in continue(v, ...)
//
// If there are no breaks in the body, the break continuation is inlined
// in the exit continuation (i.e., the translation of the successor
@@ -1297,6 +1297,125 @@ abstract class IrBuilder {
}
}
+
+ /// Creates a do-while loop.
+ ///
+ /// The body and condition are created by [buildBody] and [buildCondition].
+ /// The jump target [target] is the target of `break` and `continue`
+ /// statements in the body that have the loop as their target.
+ /// [closureScope] contains all the variables declared in the loop (but not
+ /// declared in some inner closure scope).
+ void buildDoWhile({SubbuildFunction buildBody,
+ SubbuildFunction buildCondition,
+ JumpTarget target,
+ ClosureScope closureScope}) {
+ assert(isOpen);
+ // The CPS translation of [[do body; while (condition); successor]] is:
+ //
+ // let cont break(x, ...) = [[successor]] in
+ // let cont rec loop(x, ...) =
+ // let cont continue(x, ...) =
+ // let prim cond = [[condition]] in
+ // let cont exit() = break(v, ...)
+ // and repeat() = loop(v, ...)
+ // in branch cond (repeat, exit)
+ // in [[body]]; continue(v, ...)
+ // in loop(v, ...)
+ IrBuilder bodyBuilder = makeRecursiveBuilder();
+ IrBuilder continueBuilder = bodyBuilder.makeRecursiveBuilder();
+
+ // Construct the continue continuation (i.e., the condition).
+ // <Continue> =
+ // let prim cond = [[condition]] in
+ // let cont exit() = break(v, ...)
+ // and repeat() = loop(v, ...)
+ // in branch cond (repeat, exit)
+ ir.Primitive condition = buildCondition(continueBuilder);
+ // Use a delimited IrBuilder for the exit continuation's body so that
+ // we can capture the break with the body's break collector.
+ ir.Continuation exitContinuation = new ir.Continuation([]);
+ IrBuilder exitBuilder = continueBuilder.makeDelimitedBuilder();
+ ir.Continuation repeatContinuation = new ir.Continuation([]);
+ ir.InvokeContinuation invokeLoop =
+ new ir.InvokeContinuation.uninitialized(recursive: true);
+ invokeLoop.arguments =
+ continueBuilder.environment.index2value.map(
+ (ir.Primitive value) => new ir.Reference(value)).toList();
+ repeatContinuation.body = invokeLoop;
+ continueBuilder.add(
+ new ir.LetCont.many(<ir.Continuation>[exitContinuation,
+ repeatContinuation],
+ new ir.Branch(new ir.IsTrue(condition),
+ repeatContinuation,
+ exitContinuation)));
+ ir.Continuation continueContinuation =
+ new ir.Continuation(continueBuilder._parameters);
+ continueContinuation.body = continueBuilder._root;
+
+ // Construct the loop continuation (i.e., the body and condition).
+ // <Loop> =
+ // let cont continue(x, ...) =
+ // <Continue>
+ // in [[body]]; continue(v, ...)
+ JumpCollector breakCollector = new JumpCollector(target);
+ JumpCollector continueCollector = new JumpCollector(target);
+ state.breakCollectors.add(breakCollector);
+ state.continueCollectors.add(continueCollector);
+ bodyBuilder._enterScope(closureScope);
+ buildBody(bodyBuilder);
+ assert(state.breakCollectors.last == breakCollector);
+ assert(state.continueCollectors.last == continueCollector);
+ state.breakCollectors.removeLast();
+ state.continueCollectors.removeLast();
+ // Add the jump from the loop's exit to the break condition. It is only
+ // here where the exitBuilder's root is non-null and we can set the
+ // exitContinuation's body.
+ breakCollector.addJump(exitBuilder);
+ exitContinuation.body = exitBuilder._root;
+ if (bodyBuilder.isOpen) {
+ continueCollector.addJump(bodyBuilder);
+ }
+ invokeFullJoin(continueContinuation, continueCollector, recursive: false);
+ ir.Continuation loopContinuation =
+ new ir.Continuation(bodyBuilder._parameters);
+ loopContinuation.isRecursive = true;
+ loopContinuation.body =
+ new ir.LetCont(continueContinuation, bodyBuilder._root);
+ invokeLoop.continuation =
+ new ir.Reference<ir.Continuation>(loopContinuation);
+ ir.LetCont letLoop =
+ new ir.LetCont(loopContinuation,
+ new ir.InvokeContinuation(loopContinuation,
+ environment.index2value));
+
+ // Add the break condition.
+ ir.Continuation breakContinuation;
+ if (breakCollector.length == 1) {
+ // createJoin only works when there is more than one jump to a join-point
+ // continuation. This is to potentially catch errors in the case that
+ // a join was intended and at least one jump is missing. Unfortunately
+ // we have the explicit code below for the (common?) case that the
+ // only break from the do-while is the implicit one when the condition
+ // is false.
+ List<ir.Parameter> parameters = <ir.Parameter>[];
+ List<ir.Reference> arguments = <ir.Reference>[];
+ for (int i = 0; i < environment.length; ++i) {
+ ir.Parameter parameter =
+ new ir.Parameter(environment.index2variable[i]);
+ parameters.add(parameter);
+ environment.index2value[i] = parameter;
+ arguments.add(new ir.Reference(breakCollector.environments.first[i]));
+ }
+ breakContinuation = new ir.Continuation(parameters);
+ breakCollector.invocations.first.arguments = arguments;
+ breakCollector.invocations.first.continuation =
+ new ir.Reference(breakContinuation);
+ } else {
+ breakContinuation = createJoin(environment.length, breakCollector);
+ }
+ add(new ir.LetCont(breakContinuation, letLoop));
+ }
+
/// Creates a try-statement.
///
/// [tryInfo] provides information on local variables declared and boxed
« no previous file with comments | « no previous file | pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698