Chromium Code Reviews| 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 4fddfd60df509f2220000830ee4e9a37201a7cf2..b891dd99b4d4e659bceb33023cb33a4513ce76ae 100644 |
| --- a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart |
| +++ b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart |
| @@ -13,7 +13,6 @@ import '../elements/elements.dart'; |
| import '../universe/universe.dart' show Selector, SelectorKind; |
| import '../dart_types.dart' show DartType, GenericType; |
| import '../cps_ir/optimizers.dart'; |
| -import '../closure.dart' show ClosureClassElement; |
| abstract class Node { |
| /// A pointer to the parent node. Is null until set by optimization passes. |
| @@ -108,7 +107,7 @@ class Reference<T extends Definition<T>> { |
| /// Binding a value (primitive or constant): 'let val x = V in E'. The bound |
| /// value is in scope in the body. |
| /// During one-pass construction a LetVal with an empty body is used to |
| -/// represent one-level context 'let val x = V in []'. |
| +/// represent the one-hole context 'let val x = V in []'. |
| class LetPrim extends Expression implements InteriorNode { |
| final Primitive primitive; |
| Expression body; |
| @@ -134,7 +133,7 @@ class LetPrim extends Expression implements InteriorNode { |
| /// The bound continuations are in scope in the body and the continuation |
| /// parameters are in scope in the respective continuation bodies. |
| /// During one-pass construction a LetCont whose first continuation has an empty |
| -/// body is used to represent the one-level context |
| +/// body is used to represent the one-hole context |
| /// 'let cont ... k(v) = [] ... in E'. |
| class LetCont extends Expression implements InteriorNode { |
| List<Continuation> continuations; |
| @@ -155,6 +154,30 @@ class LetCont extends Expression implements InteriorNode { |
| accept(Visitor visitor) => visitor.visitLetCont(this); |
| } |
| +/// Binding mutable variables. |
| +/// |
| +/// let mutable v = P in E |
| +/// |
| +/// [MutableVariable]s can be seen as ref cells that are not first-class |
| +/// values. They are therefore not [Primitive]s and not bound by [LetPrim] |
| +/// to prevent unrestricted use of references to them. During one-pass |
|
karlklose
2015/02/03 09:56:16
Would it make sense to share the context (maybe on
Kevin Millikin (Google)
2015/02/03 14:11:48
It's not always a field named body that gets plugg
|
| +/// construction, a [LetMutable} with an empty body is use to represent the |
|
karlklose
2015/02/03 09:56:16
'[LetMutable}' -> '[LetMutable]'.
Kevin Millikin (Google)
2015/02/03 14:11:49
Done.
|
| +/// one-hole context 'let mutable v = P in []'. |
| +class LetMutable extends Expression implements InteriorNode { |
| + final MutableVariable variable; |
| + final Reference<Primitive> value; |
| + Expression body; |
| + |
| + LetMutable(this.variable, Primitive value) |
| + : this.value = new Reference<Primitive>(value); |
| + |
| + Expression plug(Expression expr) { |
| + return body = expr; |
| + } |
| + |
| + accept(Visitor visitor) => visitor.visitLetMutable(this); |
| +} |
| + |
| abstract class Invoke { |
| Selector get selector; |
| List<Reference<Primitive>> get arguments; |
| @@ -351,54 +374,38 @@ class ConcatenateStrings extends Expression { |
| accept(Visitor visitor) => visitor.visitConcatenateStrings(this); |
| } |
| -/// Gets the value from a closure variable. |
| +/// Gets the value from a [MutableVariable]. |
| /// |
| -/// Closure variables can be seen as ref cells that are not first-class values. |
| -/// A [LetPrim] with a [GetClosureVariable] can then be seen as: |
| +/// [MutableVariable]s can be seen as ref cells that are not first-class |
| +/// values. A [LetPrim] with a [GetMutableVariable] can then be seen as: |
| /// |
| /// let prim p = ![variable] in [body] |
| /// |
| -class GetClosureVariable extends Primitive { |
| - final Reference<ClosureVariable> variable; |
| +class GetMutableVariable extends Primitive { |
| + final Reference<MutableVariable> variable; |
| - GetClosureVariable(ClosureVariable variable) |
| - : this.variable = new Reference<ClosureVariable>(variable); |
| + GetMutableVariable(MutableVariable variable) |
| + : this.variable = new Reference<MutableVariable>(variable); |
| - accept(Visitor visitor) => visitor.visitGetClosureVariable(this); |
| + accept(Visitor visitor) => visitor.visitGetMutableVariable(this); |
| } |
| -/// 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: |
| +/// Assign a [MutableVariable]. |
| /// |
| -/// let [variable] = ref [value] in [body] |
| +/// [MutableVariable]s can be seen as ref cells that are not first-class |
| +/// values. This can be seen as a dereferencing assignment: |
| /// |
| -/// And otherwise, it can be seen as a dereferencing assignment: |
| -/// |
| -/// { ![variable] := [value]; [body] } |
| -/// |
| -/// 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 Reference<ClosureVariable> variable; |
| +/// { [variable] := [value]; [body] } |
| +class SetMutableVariable extends Expression implements InteriorNode { |
| + final Reference<MutableVariable> variable; |
| final Reference<Primitive> value; |
| Expression body; |
| - /// If true, this declares a new copy of the closure variable. If so, all |
| - /// uses of the closure variable must occur in the [body]. |
| - /// |
| - /// There can be at most one declaration per closure variable. If there is no |
| - /// declaration, only one copy exists (per function execution). It is best to |
| - /// avoid declaring closure variables if it is not necessary. |
| - final bool isDeclaration; |
| - |
| - SetClosureVariable(ClosureVariable variable, Primitive value, |
| - {this.isDeclaration : false }) |
| - : this.value = new Reference<Primitive>(value), |
| - this.variable = new Reference<ClosureVariable>(variable); |
| + SetMutableVariable(MutableVariable variable, Primitive value) |
| + : this.variable = new Reference<MutableVariable>(variable), |
| + this.value = new Reference<Primitive>(value); |
| - accept(Visitor visitor) => visitor.visitSetClosureVariable(this); |
| + accept(Visitor visitor) => visitor.visitSetMutableVariable(this); |
| Expression plug(Expression expr) { |
| assert(body == null); |
| @@ -406,21 +413,20 @@ class SetClosureVariable extends Expression implements InteriorNode { |
| } |
| } |
| -/// Create a potentially recursive function and store it in a closure variable. |
| -/// The function can access itself using [GetClosureVariable] on [variable]. |
| -/// There must not exist a [SetClosureVariable] to [variable]. |
| +/// Create a potentially recursive function and store it in a [MutableVariable]. |
| +/// The function can access itself using [GetMutableVariable] on [variable]. |
| +/// There must not exist a [SetMutableVariable] to [variable]. |
| /// |
| /// This can be seen as a let rec binding: |
| /// |
| /// let rec [variable] = [definition] in [body] |
| /// |
| class DeclareFunction extends Expression implements InteriorNode { |
| - final Reference<ClosureVariable> variable; |
| + final MutableVariable variable; |
| final FunctionDefinition definition; |
| Expression body; |
| - DeclareFunction(ClosureVariable variable, this.definition) |
| - : this.variable = new Reference<ClosureVariable>(variable); |
| + DeclareFunction(this.variable, this.definition); |
| Expression plug(Expression expr) { |
| assert(body == null); |
| @@ -704,15 +710,15 @@ class FieldDefinition extends Node implements ExecutableDefinition { |
| bool get hasInitializer => body != null; |
| } |
| -/// Identifies a closure variable. |
| -class ClosureVariable extends Definition { |
| - /// Body of code that declares this closure variable. |
| +/// Identifies a mutable variable. |
| +class MutableVariable extends Definition { |
| + /// Body of source code that declares this mutable variable. |
| ExecutableElement host; |
| Entity hint; |
| - ClosureVariable(this.host, this.hint); |
| + MutableVariable(this.host, this.hint); |
| - accept(Visitor v) => v.visitClosureVariable(this); |
| + accept(Visitor v) => v.visitMutableVariable(this); |
| } |
| class RunnableBody extends InteriorNode { |
| @@ -727,7 +733,7 @@ class RunnableBody extends InteriorNode { |
| class FunctionDefinition extends Node |
| implements ExecutableDefinition { |
| final FunctionElement element; |
| - /// Mixed list of [Parameter]s and [ClosureVariable]s. |
| + /// Mixed list of [Parameter]s and [MutableVariable]s. |
| final List<Definition> parameters; |
| final RunnableBody body; |
| final List<ConstDeclaration> localConstants; |
| @@ -830,6 +836,7 @@ abstract class Visitor<T> { |
| // Expressions. |
| T visitLetPrim(LetPrim node) => visitExpression(node); |
| T visitLetCont(LetCont node) => visitExpression(node); |
| + T visitLetMutable(LetMutable node) => visitExpression(node); |
| T visitInvokeStatic(InvokeStatic node) => visitExpression(node); |
| T visitInvokeContinuation(InvokeContinuation node) => visitExpression(node); |
| T visitInvokeMethod(InvokeMethod node) => visitExpression(node); |
| @@ -838,7 +845,7 @@ abstract class Visitor<T> { |
| T visitConcatenateStrings(ConcatenateStrings node) => visitExpression(node); |
| T visitBranch(Branch node) => visitExpression(node); |
| T visitTypeOperator(TypeOperator node) => visitExpression(node); |
| - T visitSetClosureVariable(SetClosureVariable node) => visitExpression(node); |
| + T visitSetMutableVariable(SetMutableVariable node) => visitExpression(node); |
| T visitDeclareFunction(DeclareFunction node) => visitExpression(node); |
| T visitSetField(SetField node) => visitExpression(node); |
| @@ -849,10 +856,10 @@ abstract class Visitor<T> { |
| T visitThis(This node) => visitPrimitive(node); |
| T visitReifyTypeVar(ReifyTypeVar node) => visitPrimitive(node); |
| T visitCreateFunction(CreateFunction node) => visitPrimitive(node); |
| - T visitGetClosureVariable(GetClosureVariable node) => visitPrimitive(node); |
| + T visitGetMutableVariable(GetMutableVariable node) => visitPrimitive(node); |
| T visitParameter(Parameter node) => visitPrimitive(node); |
| T visitContinuation(Continuation node) => visitDefinition(node); |
| - T visitClosureVariable(ClosureVariable node) => visitDefinition(node); |
| + T visitMutableVariable(MutableVariable node) => visitDefinition(node); |
| T visitGetField(GetField node) => visitDefinition(node); |
| T visitCreateBox(CreateBox node) => visitDefinition(node); |
| T visitCreateInstance(CreateInstance node) => visitDefinition(node); |
| @@ -941,6 +948,14 @@ abstract class RecursiveVisitor extends Visitor { |
| visit(node.body); |
| } |
| + processLetMutable(LetMutable node) {} |
| + visitLetMutable(LetMutable node) { |
| + processLetMutable(node); |
| + visit(node.variable); |
| + processReference(node.value); |
| + visit(node.body); |
| + } |
| + |
| processInvokeStatic(InvokeStatic node) {} |
| visitInvokeStatic(InvokeStatic node) { |
| processInvokeStatic(node); |
| @@ -1000,9 +1015,10 @@ abstract class RecursiveVisitor extends Visitor { |
| processReference(node.receiver); |
| } |
| - processSetClosureVariable(SetClosureVariable node) {} |
| - visitSetClosureVariable(SetClosureVariable node) { |
| - processSetClosureVariable(node); |
| + processSetMutableVariable(SetMutableVariable node) {} |
| + visitSetMutableVariable(SetMutableVariable node) { |
| + processSetMutableVariable(node); |
| + processReference(node.variable); |
| processReference(node.value); |
| visit(node.body); |
| } |
| @@ -1010,6 +1026,7 @@ abstract class RecursiveVisitor extends Visitor { |
| processDeclareFunction(DeclareFunction node) {} |
| visitDeclareFunction(DeclareFunction node) { |
| processDeclareFunction(node); |
| + visit(node.variable); |
| visit(node.definition); |
| visit(node.body); |
| } |
| @@ -1046,14 +1063,14 @@ abstract class RecursiveVisitor extends Visitor { |
| visit(node.definition); |
| } |
| - processClosureVariable(node) {} |
| - visitClosureVariable(ClosureVariable node) { |
| - processClosureVariable(node); |
| + processMutableVariable(node) {} |
| + visitMutableVariable(MutableVariable node) { |
| + processMutableVariable(node); |
| } |
| - processGetClosureVariable(GetClosureVariable node) {} |
| - visitGetClosureVariable(GetClosureVariable node) { |
| - processGetClosureVariable(node); |
| + processGetMutableVariable(GetMutableVariable node) {} |
| + visitGetMutableVariable(GetMutableVariable node) { |
| + processGetMutableVariable(node); |
| } |
| processParameter(Parameter node) {} |
| @@ -1225,6 +1242,11 @@ class RegisterAllocator extends Visitor { |
| visit(node.body); |
| } |
| + void visitLetMutable(LetMutable node) { |
| + visit(node.body); |
| + visitReference(node.value); |
| + } |
| + |
| void visitInvokeStatic(InvokeStatic node) { |
| node.arguments.forEach(visitReference); |
| } |
| @@ -1283,10 +1305,10 @@ class RegisterAllocator extends Visitor { |
| new RegisterAllocator().visit(node.definition); |
| } |
| - void visitGetClosureVariable(GetClosureVariable node) { |
| + void visitGetMutableVariable(GetMutableVariable node) { |
| } |
| - void visitSetClosureVariable(SetClosureVariable node) { |
| + void visitSetMutableVariable(SetMutableVariable node) { |
| visit(node.body); |
| visitReference(node.value); |
| } |