Index: pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart |
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart |
index 6c8100ae44ae0513e2cd1949567d19abbdb29448..b4f111a98f3607b3778de5dc8cc8020083b9d610 100644 |
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart |
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart |
@@ -310,8 +310,7 @@ class ConcatenateStrings extends Expression { |
accept(Visitor visitor) => visitor.visitConcatenateStrings(this); |
} |
-/// Gets the value from a closure variable. The identity of the variable is |
-/// determined by a [Local]. |
+/// Gets the value from a closure variable. |
/// |
/// Closure variables can be seen as ref cells that are not first-class values. |
/// A [LetPrim] with a [GetClosureVariable] can then be seen as: |
@@ -319,17 +318,15 @@ class ConcatenateStrings extends Expression { |
/// let prim p = ![variable] in [body] |
/// |
class GetClosureVariable extends Primitive { |
- final Local variable; |
+ final Reference<ClosureVariable> variable; |
- GetClosureVariable(this.variable) { |
- assert(variable != null); |
- } |
+ GetClosureVariable(ClosureVariable variable) |
+ : this.variable = new Reference<ClosureVariable>(variable); |
accept(Visitor visitor) => visitor.visitGetClosureVariable(this); |
} |
-/// Assign or declare a closure variable. The identity of the variable is |
-/// determined by a [Local]. |
+/// Assign or declare a closure variable. |
/// |
/// Closure variables can be seen as ref cells that are not first-class values. |
/// If [isDeclaration], this can seen as a let binding: |
@@ -343,7 +340,7 @@ class GetClosureVariable extends Primitive { |
/// Closure variables without a declaring [SetClosureVariable] are implicitly |
/// declared at the entry to the [variable]'s enclosing function. |
class SetClosureVariable extends Expression implements InteriorNode { |
- final Local variable; |
+ final Reference<ClosureVariable> variable; |
final Reference<Primitive> value; |
Expression body; |
@@ -355,11 +352,10 @@ class SetClosureVariable extends Expression implements InteriorNode { |
/// avoid declaring closure variables if it is not necessary. |
final bool isDeclaration; |
- SetClosureVariable(this.variable, Primitive value, |
+ SetClosureVariable(ClosureVariable variable, Primitive value, |
{this.isDeclaration : false }) |
- : this.value = new Reference<Primitive>(value) { |
- assert(variable != null); |
- } |
+ : this.value = new Reference<Primitive>(value), |
+ this.variable = new Reference<ClosureVariable>(variable); |
accept(Visitor visitor) => visitor.visitSetClosureVariable(this); |
@@ -378,11 +374,12 @@ class SetClosureVariable extends Expression implements InteriorNode { |
/// let rec [variable] = [definition] in [body] |
/// |
class DeclareFunction extends Expression implements InteriorNode { |
- final Local variable; |
+ final Reference<ClosureVariable> variable; |
final FunctionDefinition definition; |
Expression body; |
- DeclareFunction(this.variable, this.definition); |
+ DeclareFunction(ClosureVariable variable, this.definition) |
+ : this.variable = new Reference<ClosureVariable>(variable); |
Expression plug(Expression expr) { |
assert(body == null); |
@@ -594,28 +591,44 @@ class FieldDefinition extends Node |
bool get hasInitializer => body != null; |
} |
+/// Identifies a closure variable. |
+class ClosureVariable extends Definition { |
+ /// Body of code that declares this closure variable. |
+ ExecutableElement host; |
+ Entity hint; |
+ |
+ ClosureVariable(this.host, this.hint); |
+ |
+ accept(Visitor v) => v.visitClosureVariable(this); |
+} |
+ |
/// A function definition, consisting of parameters and a body. The parameters |
/// include a distinguished continuation parameter. |
class FunctionDefinition extends Node |
implements InteriorNode, ExecutableDefinition { |
final FunctionElement element; |
final Continuation returnContinuation; |
- final List<Parameter> parameters; |
+ /// Mixed list of [Parameter]s and [ClosureVariable]s. |
+ final List<Definition> parameters; |
Expression body; |
final List<ConstDeclaration> localConstants; |
/// Values for optional parameters. |
final List<ConstantExpression> defaultParameterValues; |
+ /// Closure variables declared by this function. |
+ final List<ClosureVariable> closureVariables; |
+ |
FunctionDefinition(this.element, this.returnContinuation, |
this.parameters, this.body, this.localConstants, |
- this.defaultParameterValues); |
+ this.defaultParameterValues, this.closureVariables); |
FunctionDefinition.abstract(this.element, |
this.parameters, |
this.defaultParameterValues) |
: this.returnContinuation = null, |
- this.localConstants = const <ConstDeclaration>[]; |
+ this.localConstants = const <ConstDeclaration>[], |
+ this.closureVariables = const <ClosureVariable>[]; |
accept(Visitor visitor) => visitor.visitFunctionDefinition(this); |
applyPass(Pass pass) => pass.rewriteFunctionDefinition(this); |
@@ -670,6 +683,7 @@ abstract class Visitor<T> { |
T visitGetClosureVariable(GetClosureVariable node) => visitPrimitive(node); |
T visitParameter(Parameter node) => visitPrimitive(node); |
T visitContinuation(Continuation node) => visitDefinition(node); |
+ T visitClosureVariable(ClosureVariable node) => visitDefinition(node); |
// Conditions. |
T visitIsTrue(IsTrue node) => visitCondition(node); |
@@ -704,7 +718,7 @@ abstract class RecursiveVisitor extends Visitor { |
processFunctionDefinition(FunctionDefinition node) {} |
visitFunctionDefinition(FunctionDefinition node) { |
processFunctionDefinition(node); |
- node.parameters.forEach(visitParameter); |
+ node.parameters.forEach(visit); |
if (!node.isAbstract) { |
visit(node.body); |
} |
@@ -830,9 +844,15 @@ abstract class RecursiveVisitor extends Visitor { |
visit(node.definition); |
} |
+ processClosureVariable(node) {} |
+ visitClosureVariable(ClosureVariable node) { |
+ processClosureVariable(node); |
+ } |
+ |
processGetClosureVariable(GetClosureVariable node) {} |
- visitGetClosureVariable(GetClosureVariable node) => |
- processGetClosureVariable(node); |
+ visitGetClosureVariable(GetClosureVariable node) { |
+ processGetClosureVariable(node); |
+ } |
processParameter(Parameter node) {} |
visitParameter(Parameter node) => processParameter(node); |
@@ -929,7 +949,12 @@ class RegisterAllocator extends Visitor { |
if (!node.isAbstract) { |
visit(node.body); |
} |
- node.parameters.forEach(allocate); // Assign indices to unused parameters. |
+ // Assign indices to unused parameters. |
+ for (Definition param in node.parameters) { |
+ if (param is Primitive) { |
+ allocate(param); |
+ } |
+ } |
} |
void visitLetPrim(LetPrim node) { |