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

Unified Diff: pkg/compiler/lib/src/js_backend/codegen/codegen.dart

Issue 725293004: Add support for if, while, break, continue to js-cps (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Add test file Created 6 years, 1 month 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
Index: pkg/compiler/lib/src/js_backend/codegen/codegen.dart
diff --git a/pkg/compiler/lib/src/js_backend/codegen/codegen.dart b/pkg/compiler/lib/src/js_backend/codegen/codegen.dart
index 4bef84cff414bbdb6052a757293ebe63698dec34..2158aed71e10bb68964e37cb47d1661cef34d2f4 100644
--- a/pkg/compiler/lib/src/js_backend/codegen/codegen.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen/codegen.dart
@@ -39,19 +39,23 @@ class CodeGenerator extends tree_ir.Visitor<dynamic, js.Expression> {
/// Variable names that have already been used. Used to avoid name clashes.
Set<String> usedVariableNames = new Set<String>();
- List<js.Parameter> parameters = new List<js.Parameter>();
- List<js.Statement> accumulator = new List<js.Statement>();
+ /// Input to [visitStatement]. Denotes the statement that will execute next
+ /// if the statements produced by [visitStatement] complete normally.
+ /// Set to null if control will fall over the end of the method.
+ tree_ir.Statement fallthrough = null;
- js.Block body;
+ Set<tree_ir.Label> usedLabels = new Set<tree_ir.Label>();
+
+ List<js.Statement> accumulator = new List<js.Statement>();
- /// Generates JavaScript code for the body of [function].
- /// The code will be in [body] and the parameters will be in [parameters].
CodeGenerator(this.glue, this.registry);
- void buildFunction(tree_ir.FunctionDefinition function) {
+ /// Generates JavaScript code for the body of [function].
+ js.Fun buildFunction(tree_ir.FunctionDefinition function) {
currentFunction = function.element;
visitStatement(function.body);
+ List<js.Parameter> parameters = new List<js.Parameter>();
Set<tree_ir.Variable> parameterSet = new Set<tree_ir.Variable>();
for (tree_ir.Variable parameter in function.parameters) {
@@ -76,7 +80,7 @@ class CodeGenerator extends tree_ir.Visitor<dynamic, js.Expression> {
accumulator.insert(0, new js.ExpressionStatement(
new js.VariableDeclarationList(jsVariables)));
}
- body = new js.Block(accumulator);
+ return new js.Fun(parameters, new js.Block(accumulator));
}
js.Expression visit(tree_ir.Expression node) {
@@ -216,8 +220,7 @@ class CodeGenerator extends tree_ir.Visitor<dynamic, js.Expression> {
@override
js.Expression visitNot(tree_ir.Not node) {
- return giveup(node);
- // TODO: implement visitNot
+ return new js.Prefix("!", visitExpression(node.operand));
}
@override
@@ -245,8 +248,16 @@ class CodeGenerator extends tree_ir.Visitor<dynamic, js.Expression> {
@override
void visitContinue(tree_ir.Continue node) {
- return giveup(node);
- // TODO: implement visitContinue
+ tree_ir.Statement fallthrough = this.fallthrough;
+ if (node.target.binding == fallthrough) {
+ // Fall through to continue target
+ } else if (fallthrough is tree_ir.Continue &&
+ fallthrough.target == node.target) {
+ // Fall through to equivalent continue
+ } else {
+ usedLabels.add(node.target);
+ accumulator.add(new js.Continue(node.target.name));
+ }
}
@override
@@ -264,14 +275,33 @@ class CodeGenerator extends tree_ir.Visitor<dynamic, js.Expression> {
@override
void visitIf(tree_ir.If node) {
- giveup(node);
- // TODO: implement visitIf
+ js.Statement elseStatement = buildBody(node.elseStatement);
+ accumulator.add(new js.If(visitExpression(node.condition),
+ buildBody(node.thenStatement),
+ elseStatement is js.EmptyStatement
+ ? new js.EmptyStatement()
floitsch 2014/11/24 16:37:47 why? looks like just "elseStatement" would do it.
sigurdm 2014/11/25 08:29:50 Right - I had a null check here, but it was unnece
+ : elseStatement));
}
@override
void visitLabeledStatement(tree_ir.LabeledStatement node) {
- giveup(node);
- // TODO: implement visitLabeledStatement
+ accumulator.add(buildLabeled(() => buildBody(node.body),
+ node.label,
+ node.next));
+ visitStatement(node.next);
+ }
+
+ js.Statement buildLabeled(js.Statement buildBody(),
+ tree_ir.Label label,
+ tree_ir.Statement fallthroughStatement) {
+ tree_ir.Statement savedFallthrough = fallthrough;
+ fallthrough = fallthroughStatement;
+ js.Statement result = buildBody();
+ if (usedLabels.remove(label)) {
+ result = new js.LabeledStatement(label.name, result);
+ }
+ fallthrough = savedFallthrough;
+ return result;
}
@override
@@ -287,20 +317,62 @@ class CodeGenerator extends tree_ir.Visitor<dynamic, js.Expression> {
@override
void visitBreak(tree_ir.Break node) {
- giveup(node);
- // TODO: implement visitBreak
+ tree_ir.Statement fallthrough = this.fallthrough;
+ if (node.target.binding.next == fallthrough) {
+ // Fall through to break target
+ } else if (fallthrough is tree_ir.Break &&
+ fallthrough.target == node.target) {
+ // Fall through to equivalent break
+ } else {
+ usedLabels.add(node.target);
+ accumulator.add(new js.Break(node.target.name));
+ }
+ }
+
+ /// Returns the current [accumulator] wrapped in a block if neccessary.
+ js.Statement _bodyAsStatement() {
+ if (accumulator.length == 0) {
+ return new js.EmptyStatement();
+ }
+ if (accumulator.length == 1) {
+ return accumulator.single;
+ }
+ return new js.Block(accumulator);
+ }
+
+ /// Builds a nested statement.
+ js.Statement buildBody(tree_ir.Statement statement) {
+ List<js.Statement> savedAccumulator = accumulator;
+ accumulator = new List<js.Statement>();
+ visitStatement(statement);
+ js.Statement result = _bodyAsStatement();
+ accumulator = savedAccumulator;
+ return result;
+ }
+
+ js.Statement buildWhile(js.Expression condition,
+ tree_ir.Statement body,
+ tree_ir.Label label,
+ tree_ir.Statement fallthroughStatement) {
+ return buildLabeled(() => new js.While(condition, buildBody(body)),
+ label,
+ fallthroughStatement);
}
@override
void visitWhileCondition(tree_ir.WhileCondition node) {
- giveup(node);
- // TODO: implement visitWhileCondition
+ accumulator.add(
+ buildWhile(visitExpression(node.condition),
+ node.body,
+ node.label,
+ node));
+ visitStatement(node.next);
}
@override
void visitWhileTrue(tree_ir.WhileTrue node) {
- giveup(node);
- // TODO: implement visitWhileTrue
+ accumulator.add(
+ buildWhile(new js.LiteralBool(true), node.body, node.label, node));
}
@override
@@ -308,6 +380,4 @@ class CodeGenerator extends tree_ir.Visitor<dynamic, js.Expression> {
accumulator.add(new js.Return(visitExpression(node.value)));
}
- bool isNullLiteral(js.Expression exp) => exp is js.LiteralNull;
-
}

Powered by Google App Engine
This is Rietveld 408576698