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

Unified Diff: sdk/lib/_internal/compiler/implementation/dart_backend/dart_tree.dart

Issue 366853007: dart2dart: Support for inner functions in new IR. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: SVN rebase Created 6 years, 6 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
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 b17cbd272de773800038ceece4948489c460400a..74142fa3da9bd549cfd2abdf526c72bcd0c43cec 100644
--- a/sdk/lib/_internal/compiler/implementation/dart_backend/dart_tree.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart_backend/dart_tree.dart
@@ -26,6 +26,9 @@ import '../ir/const_expression.dart';
//
// In contrast to the CPS-based IR, non-primitive expressions can be named and
// arguments (to calls, primitives, and blocks) can be arbitrary expressions.
+//
+// Additionally, variables are considered in scope within inner functions;
+// closure variables are thus handled directly instead of using ref cells.
/**
* The base class of all Tree nodes.
@@ -82,13 +85,24 @@ class Label {
* Variables are [Expression]s.
*/
class Variable extends Expression {
+ /// Function that declares this variable.
+ FunctionDefinition host;
+
/// Element used for synthesizing a name for the variable.
/// Different variables may have the same element. May be null.
Element element;
int readCount = 0;
- Variable(this.element);
+ /// Number of places where this variable occurs as:
+ /// - left-hand of an [Assign]
+ /// - left-hand of a [FunctionDeclaration]
+ /// - parameter in a [FunctionDefinition]
+ int writeCount = 0;
+
+ Variable(this.host, this.element) {
+ assert(host != null);
+ }
accept(ExpressionVisitor visitor) => visitor.visitVariable(this);
}
@@ -140,7 +154,7 @@ class InvokeSuperMethod extends Expression implements Invoke {
InvokeSuperMethod(this.selector, this.arguments) ;
- accept(Visitor visitor) => visitor.visitInvokeSuperMethod(this);
+ accept(ExpressionVisitor visitor) => visitor.visitInvokeSuperMethod(this);
}
/**
@@ -192,9 +206,9 @@ class This extends Expression {
}
class ReifyTypeVar extends Expression {
- TypeVariableElement element;
+ TypeVariableElement typeVariable;
- ReifyTypeVar(this.element);
+ ReifyTypeVar(this.typeVariable);
accept(ExpressionVisitor visitor) => visitor.visitReifyTypeVar(this);
}
@@ -264,6 +278,33 @@ class Not extends Expression {
accept(ExpressionVisitor visitor) => visitor.visitNot(this);
}
+class FunctionExpression extends Expression {
+ final FunctionDefinition definition;
+
+ FunctionExpression(this.definition) {
+ assert(definition.element.functionSignature.type.returnType.treatAsDynamic);
+ }
+
+ accept(ExpressionVisitor visitor) => visitor.visitFunctionExpression(this);
+}
+
+/// Declares a local function.
+/// Used for functions that may not occur in expression context due to
+/// being recursive or having a return type.
+/// The [variable] must not occur as the left-hand side of an [Assign] or
+/// any other [FunctionDeclaration].
+class FunctionDeclaration extends Statement {
+ Variable variable;
+ final FunctionDefinition definition;
+ Statement next;
+
+ FunctionDeclaration(this.variable, this.definition, this.next) {
+ ++variable.writeCount;
+ }
+
+ accept(StatementVisitor visitor) => visitor.visitFunctionDeclaration(this);
+}
+
/// A [LabeledStatement] or [WhileTrue] or [WhileCondition].
abstract class JumpTarget extends Statement {
Label get label;
@@ -289,9 +330,6 @@ class LabeledStatement extends JumpTarget {
/// A [WhileTrue] or [WhileCondition] loop.
abstract class Loop extends JumpTarget {
- /// When a [Continue] to a loop is executed, all update expressions are
- /// evaluated right-to-left before control resumes at the head of the loop.
- List<Expression> get updates;
}
/**
@@ -300,7 +338,6 @@ abstract class Loop extends JumpTarget {
class WhileTrue extends Loop {
final Label label;
Statement body;
- final List<Expression> updates = <Expression>[];
WhileTrue(this.label, this.body) {
assert(label.binding == null);
@@ -328,10 +365,9 @@ class WhileCondition extends Loop {
Expression condition;
Statement body;
Statement next;
- final List<Expression> updates;
WhileCondition(this.label, this.condition, this.body,
- this.next, this.updates) {
+ this.next) {
assert(label.binding == null);
label.binding = this;
}
@@ -389,7 +425,15 @@ class Assign extends Statement {
final Variable variable;
Expression definition;
- Assign(this.variable, this.definition, this.next);
+ /// If true, this declares a new copy of the closure variable.
+ /// The consequences are similar to [ir.SetClosureVariable].
+ /// All uses of the variable must be nested inside the [next] statement.
+ bool isDeclaration;
+
+ Assign(this.variable, this.definition, this.next,
+ { this.isDeclaration: false }) {
+ variable.writeCount++;
+ }
bool get hasExactlyOneUse => variable.readCount == 1;
@@ -440,11 +484,13 @@ class ExpressionStatement extends Statement {
}
class FunctionDefinition extends Node {
+ final FunctionElement element;
final List<Variable> parameters;
Statement body;
final List<ConstDeclaration> localConstants;
- FunctionDefinition(this.parameters, this.body, this.localConstants);
+ FunctionDefinition(this.element, this.parameters, this.body,
+ this.localConstants);
}
abstract class ExpressionVisitor<E> {
@@ -464,6 +510,7 @@ abstract class ExpressionVisitor<E> {
E visitLiteralList(LiteralList node);
E visitLiteralMap(LiteralMap node);
E visitTypeOperator(TypeOperator node);
+ E visitFunctionExpression(FunctionExpression node);
}
abstract class StatementVisitor<S> {
@@ -476,6 +523,7 @@ abstract class StatementVisitor<S> {
S visitIf(If node);
S visitWhileTrue(WhileTrue node);
S visitWhileCondition(WhileCondition node);
+ S visitFunctionDeclaration(FunctionDeclaration node);
S visitExpressionStatement(ExpressionStatement node);
}
@@ -485,6 +533,120 @@ abstract class Visitor<S,E> implements ExpressionVisitor<E>,
S visitStatement(Statement s) => s.accept(this);
}
+class RecursiveVisitor extends Visitor {
+ visitFunctionDefinition(FunctionDefinition node) {
+ visitStatement(node.body);
+ }
+
+ visitVariable(Variable node) {}
+
+ visitInvokeStatic(InvokeStatic node) {
+ node.arguments.forEach(visitExpression);
+ }
+
+ visitInvokeMethod(InvokeMethod node) {
+ visitExpression(node.receiver);
+ node.arguments.forEach(visitExpression);
+ }
+
+ visitInvokeSuperMethod(InvokeSuperMethod node) {
+ node.arguments.forEach(visitExpression);
+ }
+
+ visitInvokeConstructor(InvokeConstructor node) {
+ node.arguments.forEach(visitExpression);
+ }
+
+ visitConcatenateStrings(ConcatenateStrings node) {
+ node.arguments.forEach(visitExpression);
+ }
+
+ visitConstant(Constant node) {}
+
+ visitThis(This node) {}
+
+ visitReifyTypeVar(ReifyTypeVar node) {}
+
+ visitConditional(Conditional node) {
+ visitExpression(node.condition);
+ visitExpression(node.thenExpression);
+ visitExpression(node.elseExpression);
+ }
+
+ visitLogicalOperator(LogicalOperator node) {
+ visitExpression(node.left);
+ visitExpression(node.right);
+ }
+
+ visitNot(Not node) {
+ visitExpression(node.operand);
+ }
+
+ visitLiteralList(LiteralList node) {
+ node.values.forEach(visitExpression);
+ }
+
+ visitLiteralMap(LiteralMap node) {
+ for (int i=0; i<node.keys.length; i++) {
+ visitExpression(node.keys[i]);
+ visitExpression(node.values[i]);
+ }
+ }
+
+ visitTypeOperator(TypeOperator node) {
+ visitExpression(node.receiver);
+ }
+
+ visitFunctionExpression(FunctionExpression node) {
+ visitFunctionDefinition(node.definition);
+ }
+
+ visitLabeledStatement(LabeledStatement node) {
+ visitStatement(node.body);
+ visitStatement(node.next);
+ }
+
+ visitAssign(Assign node) {
+ visitExpression(node.definition);
+ visitVariable(node.variable);
+ visitStatement(node.next);
+ }
+
+ visitReturn(Return node) {
+ visitExpression(node.value);
+ }
+
+ visitBreak(Break node) {}
+
+ visitContinue(Continue node) {}
+
+ visitIf(If node) {
+ visitExpression(node.condition);
+ visitStatement(node.thenStatement);
+ visitStatement(node.elseStatement);
+ }
+
+ visitWhileTrue(WhileTrue node) {
+ visitStatement(node.body);
+ }
+
+ visitWhileCondition(WhileCondition node) {
+ visitExpression(node.condition);
+ visitStatement(node.body);
+ visitStatement(node.next);
+ }
+
+ visitFunctionDeclaration(FunctionDeclaration node) {
+ visitFunctionDefinition(node.definition);
+ visitStatement(node.next);
+ }
+
+ visitExpressionStatement(ExpressionStatement node) {
+ visitExpression(node.expression);
+ visitStatement(node.next);
+ }
+}
+
/**
* Builder translates from CPS-based IR to direct-style Tree.
*
@@ -524,6 +686,10 @@ class Builder extends ir.Visitor<Node> {
final Map<Element, List<Variable>> element2variables =
<Element,List<Variable>>{};
+ /// Like [element2variables], except for closure variables. Closure variables
+ /// are not subject to SSA, so at most one variable is used per element.
+ final Map<Element, Variable> element2closure = <Element, Variable>{};
+
// Continuations with more than one use are replaced with Tree labels. This
// is the mapping from continuations to labels.
final Map<ir.Continuation, Label> labels = <ir.Continuation, Label>{};
@@ -531,11 +697,29 @@ class Builder extends ir.Visitor<Node> {
FunctionDefinition function;
ir.Continuation returnContinuation;
+ Builder parent;
+
+ Builder(this.compiler);
+
+ Builder.inner(Builder parent)
+ : this.parent = parent,
+ compiler = parent.compiler;
+
/// Variable used in [buildPhiAssignments] as a temporary when swapping
/// variables.
- final Variable tempVar = new Variable(null);
+ Variable phiTempVar;
- Builder(this.compiler);
+ Variable getClosureVariable(Element element) {
+ if (element.enclosingElement != function.element) {
+ return parent.getClosureVariable(element);
+ }
+ Variable variable = element2closure[element];
+ if (variable == null) {
+ variable = new Variable(function, element);
+ element2closure[element] = variable;
+ }
+ return variable;
+ }
/// Obtains the variable representing the given primitive. Returns null for
/// primitives that have no reference and do not need a variable.
@@ -543,13 +727,13 @@ class Builder extends ir.Visitor<Node> {
if (primitive.registerIndex == null) {
return null; // variable is unused
}
- List<Variable> variables = element2variables[primitive.element];
+ List<Variable> variables = element2variables[primitive.hint];
if (variables == null) {
variables = <Variable>[];
- element2variables[primitive.element] = variables;
+ element2variables[primitive.hint] = variables;
}
while (variables.length <= primitive.registerIndex) {
- variables.add(new Variable(primitive.element));
+ variables.add(new Variable(function, primitive.hint));
}
return variables[primitive.registerIndex];
}
@@ -652,9 +836,9 @@ class Builder extends ir.Visitor<Node> {
// Cycle found; store argument in a temporary variable.
// The temporary will then be used as right-hand side when the
// assignment gets added.
- if (assignmentSrc[i] != tempVar) { // Only move to temporary once.
- assignmentSrc[i] = tempVar;
- addAssignment(tempVar, arg);
+ if (assignmentSrc[i] != phiTempVar) { // Only move to temporary once.
+ assignmentSrc[i] = phiTempVar;
+ addAssignment(phiTempVar, arg);
}
return;
}
@@ -683,24 +867,40 @@ class Builder extends ir.Visitor<Node> {
return first;
}
+ visitNode(ir.Node node) => throw "Unhandled node: $node";
+
Expression visitFunctionDefinition(ir.FunctionDefinition node) {
- returnContinuation = node.returnContinuation;
List<Variable> parameters = <Variable>[];
+ function = new FunctionDefinition(node.element, parameters,
+ null, node.localConstants);
+ returnContinuation = node.returnContinuation;
for (ir.Parameter p in node.parameters) {
Variable parameter = getVariable(p);
assert(parameter != null);
+ ++parameter.writeCount; // Being a parameter counts as a write.
parameters.add(parameter);
}
- function = new FunctionDefinition(parameters, visit(node.body),
- node.localConstants);
+ phiTempVar = new Variable(function, null);
+ function.body = visit(node.body);
return null;
}
Statement visitLetPrim(ir.LetPrim node) {
Variable variable = getVariable(node.primitive);
- return variable == null
- ? visit(node.body)
- : new Assign(variable, visit(node.primitive), visit(node.body));
+
+ // Don't translate unused primitives.
+ if (variable == null) return visit(node.body);
+
+ Node definition = visit(node.primitive);
+
+ // visitPrimitive returns a Statement without successor if it cannot occur
+ // in expression context (currently only the case for FunctionDeclarations).
+ if (definition is Statement) {
+ definition.next = visit(node.body);
+ return definition;
+ } else {
+ return new Assign(variable, definition, visit(node.body));
+ }
}
Statement visitLetCont(ir.LetCont node) {
@@ -726,87 +926,69 @@ class Builder extends ir.Visitor<Node> {
// Calls are translated to direct style.
List<Expression> arguments = translateArguments(node.arguments);
Expression invoke = new InvokeStatic(node.target, node.selector, arguments);
- ir.Continuation cont = node.continuation.definition;
- if (cont == returnContinuation) {
- return new Return(invoke);
- } else {
- assert(cont.hasExactlyOneUse);
- assert(cont.parameters.length == 1);
- return buildContinuationAssignment(cont.parameters.single, invoke,
- () => visit(cont.body));
- }
+ return continueWithExpression(node.continuation, invoke);
}
Statement visitInvokeMethod(ir.InvokeMethod node) {
Expression receiver = getVariableReference(node.receiver);
List<Expression> arguments = translateArguments(node.arguments);
Expression invoke = new InvokeMethod(receiver, node.selector, arguments);
- ir.Continuation cont = node.continuation.definition;
- if (cont == returnContinuation) {
- return new Return(invoke);
- } else {
- assert(cont.hasExactlyOneUse);
- assert(cont.parameters.length == 1);
- return buildContinuationAssignment(cont.parameters.single, invoke,
- () => visit(cont.body));
- }
+ return continueWithExpression(node.continuation, invoke);
}
Statement visitInvokeSuperMethod(ir.InvokeSuperMethod node) {
List<Expression> arguments = translateArguments(node.arguments);
Expression invoke = new InvokeSuperMethod(node.selector, arguments);
- ir.Continuation cont = node.continuation.definition;
- if (cont == returnContinuation) {
- return new Return(invoke);
- } else {
- assert(cont.hasExactlyOneUse);
- assert(cont.parameters.length == 1);
- return buildContinuationAssignment(cont.parameters.single, invoke,
- () => visit(cont.body));
- }
+ return continueWithExpression(node.continuation, invoke);
}
Statement visitConcatenateStrings(ir.ConcatenateStrings node) {
List<Expression> arguments = translateArguments(node.arguments);
Expression concat = new ConcatenateStrings(arguments);
- ir.Continuation cont = node.continuation.definition;
+ return continueWithExpression(node.continuation, concat);
+ }
+
+ Statement continueWithExpression(ir.Reference continuation,
+ Expression expression) {
+ ir.Continuation cont = continuation.definition;
if (cont == returnContinuation) {
- return new Return(concat);
+ return new Return(expression);
} else {
assert(cont.hasExactlyOneUse);
assert(cont.parameters.length == 1);
- return buildContinuationAssignment(cont.parameters.single, concat,
+ return buildContinuationAssignment(cont.parameters.single, expression,
() => visit(cont.body));
}
}
+ Expression visitGetClosureVariable(ir.GetClosureVariable node) {
+ return getClosureVariable(node.variable);
+ }
+
+ Statement visitSetClosureVariable(ir.SetClosureVariable node) {
+ Variable variable = getClosureVariable(node.variable);
+ Expression value = getVariableReference(node.value);
+ return new Assign(variable, value, visit(node.body),
+ isDeclaration: node.isDeclaration);
+ }
+
+ Statement visitDeclareFunction(ir.DeclareFunction node) {
+ Variable variable = getClosureVariable(node.variable);
+ FunctionDefinition function = makeSubFunction(node.definition);
+ return new FunctionDeclaration(variable, function, visit(node.body));
+ }
+
Statement visitAsCast(ir.AsCast node) {
Expression receiver = getVariableReference(node.receiver);
Expression concat = new TypeOperator(receiver, node.type, "as");
- ir.Continuation cont = node.continuation.definition;
- if (cont == returnContinuation) {
- return new Return(concat);
- } else {
- assert(cont.hasExactlyOneUse);
- assert(cont.parameters.length == 1);
- return buildContinuationAssignment(cont.parameters.single, concat,
- () => visit(cont.body));
- }
+ return continueWithExpression(node.continuation, concat);
}
Statement visitInvokeConstructor(ir.InvokeConstructor node) {
List<Expression> arguments = translateArguments(node.arguments);
Expression invoke =
new InvokeConstructor(node.type, node.target, node.selector, arguments);
- ir.Continuation cont = node.continuation.definition;
- if (cont == returnContinuation) {
- return new Return(invoke);
- } else {
- assert(cont.hasExactlyOneUse);
- assert(cont.parameters.length == 1);
- return buildContinuationAssignment(cont.parameters.single, invoke,
- () => visit(cont.body));
- }
+ return continueWithExpression(node.continuation, invoke);
}
Statement visitInvokeContinuation(ir.InvokeContinuation node) {
@@ -870,7 +1052,7 @@ class Builder extends ir.Visitor<Node> {
}
Expression visitReifyTypeVar(ir.ReifyTypeVar node) {
- return new ReifyTypeVar(node.element);
+ return new ReifyTypeVar(node.typeVariable);
}
Expression visitLiteralList(ir.LiteralList node) {
@@ -886,6 +1068,23 @@ class Builder extends ir.Visitor<Node> {
translateArguments(node.values));
}
+ FunctionDefinition makeSubFunction(ir.FunctionDefinition function) {
+ return new Builder.inner(this).build(function);
+ }
+
+ Node visitCreateFunction(ir.CreateFunction node) {
+ FunctionDefinition def = makeSubFunction(node.definition);
+ FunctionSignature signature = node.definition.element.functionSignature;
+ bool hasReturnType = !signature.type.returnType.treatAsDynamic;
+ if (hasReturnType) {
+ // This function cannot occur in expression context.
+ // The successor will be filled in by visitLetPrim.
+ return new FunctionDeclaration(getVariable(node), def, null);
+ } else {
+ return new FunctionExpression(def);
+ }
+ }
+
Expression visitIsCheck(ir.IsCheck node) {
return new TypeOperator(getVariableReference(node.receiver),
node.type,
@@ -911,6 +1110,85 @@ class Builder extends ir.Visitor<Node> {
}
}
+/// Eliminates redundant variables and assignments that occur immediately after
+/// parameters are declared or after a function declaration.
+///
+/// These patterns arise when translating out of CPS where closure variables
+/// live in a separate space. Since function parameters are IR primitives they
+/// must be moved into a separate closure variable for inner functions to access
+/// them. For example:
+///
+/// foo(x) {
+/// let v1 = ref x in BODY
+/// }
+/// ==> (dart_tree Builder)
+/// foo(x) {
+/// var v1 = x;
+/// BODY..
+/// }
+///
+/// This phase attempts to merge v1 and x in the example above.
+/// A similar pattern can occur for local function declarations that are used
+/// from closures.
+class CopyPropagateClosureVariables extends RecursiveVisitor {
+
+ void rewrite(FunctionDefinition definition) {
+ visitFunctionDefinition(definition);
+ }
+
+ /// Performs the rewrite:
+ ///
+ /// foo(x) { var v0 = x; S }
+ /// ==> (move v0 into parameter)
+ /// foo(v0) { S }
+ /// ==> (change the name of v0 to be x, so we preserve the parameter name)
+ /// foo(x) { S[v0\x] }
+ ///
+ /// Condition: x cannot be used anywhere else.
+ visitFunctionDefinition(FunctionDefinition definition) {
+ while (definition.body is Assign) {
+ Assign assign = definition.body;
+ if (assign.definition is! Variable) break;
+
+ Variable rightHand = assign.definition;
+ if (rightHand.readCount != 1) break;
+
+ int paramIndex = definition.parameters.indexOf(rightHand);
+ if (paramIndex == -1) break;
+
+ // A variable may not occur as a parameter more than once.
+ if (definition.parameters.contains(assign.variable)) break;
+
+ definition.parameters[paramIndex] = assign.variable;
+ assign.variable.element = rightHand.element;
+ definition.body = assign.next;
+ }
+
+ visitStatement(definition.body); // Visit nested function definitions.
+ }
+
+ /// Performs the rewrite:
+ ///
+ /// int v0() { S }
+ /// foo = v0;
+ /// ==>
+ /// int foo() { S }
+ ///
+ /// Condition: v0 cannot be used anywhere else.
+ visitFunctionDeclaration(FunctionDeclaration node) {
+ Statement next = node.next;
+ if (next is Assign &&
+ next.definition == node.variable &&
+ node.variable.readCount == 1 &&
+ next.variable.writeCount == 1) {
+ node.variable = next.variable;
+ node.next = next.next;
+ }
+ super.visitFunctionDeclaration(node);
+ }
+
+}
+
/**
* Performs the following transformations on the tree:
* - Assignment propagation
@@ -1123,6 +1401,17 @@ class StatementRewriter extends Visitor<Statement, Expression> {
return node;
}
+ Expression visitFunctionExpression(FunctionExpression node) {
+ new StatementRewriter().rewrite(node.definition);
+ return node;
+ }
+
+ Statement visitFunctionDeclaration(FunctionDeclaration node) {
+ new StatementRewriter().rewrite(node.definition);
+ node.next = visitStatement(node.next);
+ return node;
+ }
+
Statement visitReturn(Return node) {
node.value = visitExpression(node.value);
return node;
@@ -1303,6 +1592,7 @@ class StatementRewriter extends Visitor<Statement, Expression> {
if (s is Assign && t is Assign && s.variable == t.variable) {
Statement next = combineStatements(s.next, t.next);
if (next != null) {
+ --t.variable.writeCount; // Two assignments become one.
return new Assign(s.variable,
combine(s.definition, t.definition),
next);
@@ -1466,7 +1756,7 @@ class StatementRewriter extends Visitor<Statement, Expression> {
///
/// Note that the above pattern needs no iteration since nested ifs
/// have been collapsed previously in the [StatementRewriter] phase.
-class LoopRewriter extends StatementVisitor<Statement> {
+class LoopRewriter extends RecursiveVisitor {
Set<Label> usedContinueLabels = new Set<Label>();
@@ -1481,11 +1771,13 @@ class LoopRewriter extends StatementVisitor<Statement> {
}
Statement visitAssign(Assign node) {
+ visitExpression(node.definition);
node.next = visitStatement(node.next);
return node;
}
Statement visitReturn(Return node) {
+ visitExpression(node.value);
return node;
}
@@ -1499,6 +1791,7 @@ class LoopRewriter extends StatementVisitor<Statement> {
}
Statement visitIf(If node) {
+ visitExpression(node.condition);
node.thenStatement = visitStatement(node.thenStatement);
node.elseStatement = visitStatement(node.elseStatement);
return node;
@@ -1518,16 +1811,14 @@ class LoopRewriter extends StatementVisitor<Statement> {
node.label,
body.condition,
body.thenStatement,
- body.elseStatement,
- node.updates);
+ body.elseStatement);
} else if (!thenHasContinue && elseHasContinue) {
node.label.binding = null;
return new WhileCondition(
node.label,
new Not(body.condition),
body.elseStatement,
- body.thenStatement,
- node.updates);
+ body.thenStatement);
}
} else {
node.body = visitStatement(node.body);
@@ -1538,28 +1829,28 @@ class LoopRewriter extends StatementVisitor<Statement> {
Statement visitWhileCondition(WhileCondition node) {
// Note: not reachable but the implementation is trivial
+ visitExpression(node.condition);
node.body = visitStatement(node.body);
node.next = visitStatement(node.next);
return node;
}
Statement visitExpressionStatement(ExpressionStatement node) {
+ visitExpression(node.expression);
node.next = visitStatement(node.next);
- // for (;;) { ... E; continue* L ... }
- // ==>
- // for(;;E) { ... continue* L ... }
- if (node.next is Continue) {
- Continue jump = node.next;
- if (jump.target.useCount == 1) {
- Loop target = jump.target.binding;
- target.updates.add(node.expression);
- return jump; // Return the continue statement.
- // NOTE: The pattern may reclick in an enclosing expression statement.
- }
- }
return node;
}
+ Statement visitFunctionDeclaration(FunctionDeclaration node) {
+ new LoopRewriter().rewrite(node.definition);
+ node.next = visitStatement(node.next);
+ return node;
+ }
+
+ void visitFunctionExpression(FunctionExpression node) {
+ new LoopRewriter().rewrite(node.definition);
+ }
+
}
@@ -1774,6 +2065,17 @@ class LogicalRewriter extends Visitor<Statement, Expression> {
return node;
}
+ Expression visitFunctionExpression(FunctionExpression node) {
+ new LogicalRewriter().rewrite(node.definition);
+ return node;
+ }
+
+ Statement visitFunctionDeclaration(FunctionDeclaration node) {
+ new LogicalRewriter().rewrite(node.definition);
+ node.next = visitStatement(node.next);
+ return node;
+ }
+
Expression visitNot(Not node) {
return toBoolean(makeCondition(node.operand, false, liftNots: false));
}
@@ -1992,3 +2294,4 @@ class LogicalRewriter extends Visitor<Statement, Expression> {
}
}
}
+

Powered by Google App Engine
This is Rietveld 408576698