| Index: sdk/lib/_internal/compiler/implementation/dart_backend/dart_tree.dart
|
| diff --git a/sdk/lib/_internal/compiler/implementation/dart_backend/dart_tree.dart b/sdk/lib/_internal/compiler/implementation/dart_backend/dart_tree.dart
|
| index dcaf7e96cc29f6238ccdad8799335290f3bf3981..178f3bd7e9777ae74632c0eee39a32a49d89b9cd 100644
|
| --- a/sdk/lib/_internal/compiler/implementation/dart_backend/dart_tree.dart
|
| +++ b/sdk/lib/_internal/compiler/implementation/dart_backend/dart_tree.dart
|
| @@ -65,6 +65,19 @@ class Variable extends Expression {
|
| }
|
|
|
| /**
|
| + * A sequence of expressions.
|
| + */
|
| +class Sequence extends Expression {
|
| + final List<Expression> expressions;
|
| +
|
| + Sequence(this.expressions);
|
| +
|
| + bool get isPure => expressions.every((e) => e.isPure);
|
| +
|
| + accept(Visitor visitor) => visitor.visitSequence(this);
|
| +}
|
| +
|
| +/**
|
| * A local binding of a [Variable] to an [Expression].
|
| *
|
| * In contrast to the CPS-based IR, non-primitive expressions can be named
|
| @@ -134,6 +147,7 @@ abstract class Visitor<T> {
|
|
|
| // Concrete classes.
|
| T visitVariable(Variable node) => visitExpression(node);
|
| + T visitSequence(Sequence node) => visitExpression(node);
|
| T visitLetVal(LetVal node) => visitExpression(node);
|
| T visitInvokeStatic(InvokeStatic node) => visitExpression(node);
|
| T visitReturn(Return node) => visitExpression(node);
|
| @@ -197,10 +211,14 @@ class Builder extends ir.Visitor<Expression> {
|
|
|
| Expression visitLetPrim(ir.LetPrim node) {
|
| // LetPrim is translated to LetVal.
|
| - Variable variable = new Variable();
|
| Expression definition = node.primitive.accept(this);
|
| - variables[node.primitive] = variable;
|
| - return new LetVal(variable, definition, node.body.accept(this));
|
| + if (node.primitive.hasAtLeastOneUse) {
|
| + Variable variable = new Variable();
|
| + variables[node.primitive] = variable;
|
| + return new LetVal(variable, definition, node.body.accept(this));
|
| + } else {
|
| + return new Sequence([definition, node.body.accept(this)]);
|
| + }
|
| }
|
|
|
| Expression visitLetCont(ir.LetCont node) {
|
| @@ -220,9 +238,13 @@ class Builder extends ir.Visitor<Expression> {
|
| return new Return(invoke);
|
| } else {
|
| assert(cont.hasExactlyOneUse);
|
| - Variable variable = new Variable();
|
| - variables[cont.parameter] = variable;
|
| - return new LetVal(variable, invoke, cont.body.accept(this));
|
| + if (cont.parameter.hasAtLeastOneUse) {
|
| + Variable variable = new Variable();
|
| + variables[cont.parameter] = variable;
|
| + return new LetVal(variable, invoke, cont.body.accept(this));
|
| + } else {
|
| + return new Sequence([invoke, cont.body.accept(this)]);
|
| + }
|
| }
|
| }
|
|
|
| @@ -320,6 +342,13 @@ class Unnamer extends Visitor<Expression> {
|
| return node;
|
| }
|
|
|
| + Expression visitSequence(Sequence node) {
|
| + for (int i = 0; i < node.expressions.length; ++i) {
|
| + node.expressions[i] = node.expressions[i].accept(this);
|
| + }
|
| + return node;
|
| + }
|
| +
|
| Expression visitLetVal(LetVal node) {
|
| environment.add(node);
|
| Expression body = node.body.accept(this);
|
| @@ -479,6 +508,20 @@ class Emitter extends Visitor<ast.Node> {
|
| semicolon,
|
| value);
|
| }
|
| + } else if (body is ast.Block) {
|
| + // Remove a final 'return null' that ends the body block.
|
| + Link<ast.Node> nodes = (body as ast.Block).statements.nodes;
|
| + ast.Node last;
|
| + for (var n in nodes) {
|
| + last = n;
|
| + }
|
| + if (last is ast.Return
|
| + && (last as ast.Return).expression is ast.LiteralNull) {
|
| + List<ast.Node> statements =
|
| + (body as ast.Block).statements.nodes.toList();
|
| + statements.removeLast();
|
| + body = makeBlock(statements);
|
| + }
|
| }
|
|
|
| return new ast.FunctionExpression(name, parameters, body, returnType,
|
| @@ -534,6 +577,10 @@ class Emitter extends Visitor<ast.Node> {
|
| return new ast.Send(null, node.identifier);
|
| }
|
|
|
| + ast.Node visitSequence(Sequence node) {
|
| + return node.expressions.map((e) => e.accept(this)).reduce(concatenate);
|
| + }
|
| +
|
| ast.Node visitLetVal(LetVal node) {
|
| // Let bindings translate into assignments.
|
| ast.Identifier identifier = node.variable.assignIdentifier();
|
|
|