Chromium Code Reviews| Index: pkg/compiler/lib/src/tree_ir/tree_ir_nodes.dart |
| diff --git a/pkg/compiler/lib/src/tree_ir/tree_ir_nodes.dart b/pkg/compiler/lib/src/tree_ir/tree_ir_nodes.dart |
| index 4312130deaa2b4bbc058c94fd8199a04fd8c6eff..10176e2acf2bef84def8687ade5ef7d5d5d2b155 100644 |
| --- a/pkg/compiler/lib/src/tree_ir/tree_ir_nodes.dart |
| +++ b/pkg/compiler/lib/src/tree_ir/tree_ir_nodes.dart |
| @@ -84,9 +84,20 @@ class Label { |
| } |
| /** |
| - * Variables are [Expression]s. |
| + * A local variable in the tree IR. |
| + * |
| + * All tree IR variables are mutable, and may in Dart-mode be referenced inside |
| + * nested functions. |
| + * |
| + * To use a variable as an expression, reference it from a [VariableUse], with |
| + * one [VariableUse] per expression. |
| + * |
| + * [Variable]s are reference counted. The node constructors [VariableUse], |
| + * [Assign], [FunctionDefinition] automatically update the reference count |
| + * for their variables, but when transforming the tree, the transformer is |
| + * responsible for updating reference counts. |
| */ |
| -class Variable extends Expression { |
| +class Variable extends Node { |
|
Kevin Millikin (Google)
2015/02/26 12:43:18
Is there any reason to make this a subclass of Nod
asgerf
2015/02/27 12:05:19
Currently tree_ir.Node is just used for stuff like
|
| /// Function that declares this variable. |
| ExecutableElement host; |
| @@ -94,6 +105,7 @@ class Variable extends Expression { |
| /// Different variables may have the same entity. May be null. |
| Entity element; |
| + /// Number of places where this variable occurs in a [VariableUse]. |
| int readCount = 0; |
| /// Number of places where this variable occurs as: |
| @@ -105,9 +117,21 @@ class Variable extends Expression { |
| Variable(this.host, this.element) { |
| assert(host != null); |
| } |
| +} |
| + |
| +/// Read the value of a variable. |
| +class VariableUse extends Expression { |
| + Variable variable; |
| + |
| + /// Creates a use of [variable] and updates its `readCount`. |
| + VariableUse(this.variable) { |
| + variable.readCount++; |
| + } |
| - accept(ExpressionVisitor visitor) => visitor.visitVariable(this); |
| - accept1(ExpressionVisitor1 visitor, arg) => visitor.visitVariable(this, arg); |
| + accept(ExpressionVisitor visitor) => visitor.visitVariableUse(this); |
| + accept1(ExpressionVisitor1 visitor, arg) { |
| + return visitor.visitVariableUse(this, arg); |
| + } |
| } |
| /** |
| @@ -498,6 +522,7 @@ class Assign extends Statement { |
| /// Variable declarations themselves are hoisted to function level. |
| bool isDeclaration; |
| + /// Creates an assignment to [variable] and updates its `writeCount`. |
| Assign(this.variable, this.definition, this.next, |
| { this.isDeclaration: false }) { |
| variable.writeCount++; |
| @@ -602,8 +627,13 @@ class FunctionDefinition extends Node implements ExecutableDefinition { |
| final List<ConstDeclaration> localConstants; |
| final List<ConstantExpression> defaultParameterValues; |
| + /// Creates a function definition and updates `writeCount` for [parameters]. |
| FunctionDefinition(this.element, this.parameters, this.body, |
| - this.localConstants, this.defaultParameterValues); |
| + this.localConstants, this.defaultParameterValues) { |
| + for (Variable param in parameters) { |
| + param.writeCount++; // Being a parameter counts as a write. |
| + } |
| + } |
| /// Returns `true` if this function is abstract. |
| /// |
| @@ -700,7 +730,7 @@ class SetField extends Statement implements JsSpecificNode { |
| abstract class ExpressionVisitor<E> { |
| E visitExpression(Expression e) => e.accept(this); |
| - E visitVariable(Variable node); |
| + E visitVariableUse(VariableUse node); |
| E visitInvokeStatic(InvokeStatic node); |
| E visitInvokeMethod(InvokeMethod node); |
| E visitInvokeMethodDirectly(InvokeMethodDirectly node); |
| @@ -725,7 +755,7 @@ abstract class ExpressionVisitor<E> { |
| abstract class ExpressionVisitor1<E, A> { |
| E visitExpression(Expression e, A arg) => e.accept1(this, arg); |
| - E visitVariable(Variable node, A arg); |
| + E visitVariableUse(VariableUse node, A arg); |
| E visitInvokeStatic(InvokeStatic node, A arg); |
| E visitInvokeMethod(InvokeMethod node, A arg); |
| E visitInvokeMethodDirectly(InvokeMethodDirectly node, A arg); |
| @@ -792,11 +822,16 @@ abstract class Visitor1<S, E, A> implements ExpressionVisitor1<E, A>, |
| class RecursiveVisitor extends Visitor { |
| visitFunctionDefinition(FunctionDefinition node) { |
| + node.parameters.forEach(visitVariable); |
| visitStatement(node.body); |
| } |
| visitVariable(Variable node) {} |
| + visitVariableUse(VariableUse node) { |
| + visitVariable(node.variable); |
| + } |
| + |
| visitInvokeStatic(InvokeStatic node) { |
| node.arguments.forEach(visitExpression); |
| } |