| Index: sdk/lib/_internal/compiler/implementation/ir/ir_nodes.dart
|
| diff --git a/sdk/lib/_internal/compiler/implementation/ir/ir_nodes.dart b/sdk/lib/_internal/compiler/implementation/ir/ir_nodes.dart
|
| index 2ce6ed8219baeea21e4ea76aeca365718f27587d..f2159de6fefae57779b0a5f1dce3b2f96b02c410 100644
|
| --- a/sdk/lib/_internal/compiler/implementation/ir/ir_nodes.dart
|
| +++ b/sdk/lib/_internal/compiler/implementation/ir/ir_nodes.dart
|
| @@ -32,6 +32,18 @@ abstract class Definition extends Node {
|
| bool get hasAtMostOneUse => firstRef == null || firstRef.nextRef == null;
|
| bool get hasExactlyOneUse => firstRef != null && firstRef.nextRef == null;
|
| bool get hasAtLeastOneUse => firstRef != null;
|
| +
|
| + void substituteFor(Definition other) {
|
| + if (other.firstRef == null) return;
|
| + Reference previous, current = other.firstRef;
|
| + do {
|
| + current.definition = this;
|
| + previous = current;
|
| + current = current.nextRef;
|
| + } while (current != null);
|
| + previous.nextRef = firstRef;
|
| + firstRef = other.firstRef;
|
| + }
|
| }
|
|
|
| abstract class Primitive extends Definition {
|
| @@ -115,15 +127,39 @@ class InvokeStatic extends Expression {
|
| /// Invoke a continuation in tail position.
|
| class InvokeContinuation extends Expression {
|
| final Reference continuation;
|
| - final Reference argument;
|
| + final List<Reference> arguments;
|
|
|
| - InvokeContinuation(Continuation cont, Definition arg)
|
| + InvokeContinuation(Continuation cont, List<Definition> args)
|
| : continuation = new Reference(cont),
|
| - argument = new Reference(arg);
|
| -
|
| + arguments = args.map((t) => new Reference(t)).toList(growable: false);
|
| accept(Visitor visitor) => visitor.visitInvokeContinuation(this);
|
| }
|
|
|
| +/// The base class of things which can be tested and branched on.
|
| +abstract class Condition extends Node {
|
| +}
|
| +
|
| +class IsTrue extends Condition {
|
| + final Reference value;
|
| +
|
| + IsTrue(Definition val) : value = new Reference(val);
|
| +
|
| + accept(Visitor visitor) => visitor.visitIsTrue(this);
|
| +}
|
| +
|
| +/// Choose between a pair of continuations based on a condition value.
|
| +class Branch extends Expression {
|
| + final Condition condition;
|
| + final Reference trueContinuation;
|
| + final Reference falseContinuation;
|
| +
|
| + Branch(this.condition, Continuation trueCont, Continuation falseCont)
|
| + : trueContinuation = new Reference(trueCont),
|
| + falseContinuation = new Reference(falseCont);
|
| +
|
| + accept(Visitor visitor) => visitor.visitBranch(this);
|
| +}
|
| +
|
| class Constant extends Primitive {
|
| final dart2js.Constant value;
|
|
|
| @@ -177,18 +213,25 @@ abstract class Visitor<T> {
|
| T visitExpression(Expression node) => visitNode(node);
|
| T visitDefinition(Definition node) => visitNode(node);
|
| T visitPrimitive(Primitive node) => visitDefinition(node);
|
| + T visitCondition(Condition node) => visitNode(node);
|
|
|
| // Concrete classes.
|
| T visitFunctionDefinition(FunctionDefinition node) => visitNode(node);
|
|
|
| + // Expressions.
|
| T visitLetPrim(LetPrim node) => visitExpression(node);
|
| T visitLetCont(LetCont node) => visitExpression(node);
|
| T visitInvokeStatic(InvokeStatic node) => visitExpression(node);
|
| T visitInvokeContinuation(InvokeContinuation node) => visitExpression(node);
|
| + T visitBranch(Branch node) => visitExpression(node);
|
|
|
| + // Definitions.
|
| T visitConstant(Constant node) => visitPrimitive(node);
|
| T visitParameter(Parameter node) => visitPrimitive(node);
|
| T visitContinuation(Continuation node) => visitDefinition(node);
|
| +
|
| + // Conditions.
|
| + T visitIsTrue(IsTrue node) => visitCondition(node);
|
| }
|
|
|
| /// Generate a Lisp-like S-expression representation of an IR node as a string.
|
| @@ -213,56 +256,68 @@ class SExpressionStringifier extends Visitor<String> {
|
| return name;
|
| })
|
| .join(' ');
|
| - return '(FunctionDefinition ($parameters) ${node.body.accept(this)})';
|
| + return '(FunctionDefinition ($parameters) ${visit(node.body)})';
|
| }
|
|
|
| - String visitLetPrim(LetPrim expr) {
|
| + String visitLetPrim(LetPrim node) {
|
| String name = newValueName();
|
| - names[expr.primitive] = name;
|
| - String value = expr.primitive.accept(this);
|
| - String body = expr.body.accept(this);
|
| + names[node.primitive] = name;
|
| + String value = visit(node.primitive);
|
| + String body = visit(node.body);
|
| return '(LetPrim $name $value) $body';
|
| }
|
|
|
| - String visitLetCont(LetCont expr) {
|
| + String visitLetCont(LetCont node) {
|
| String cont = newContinuationName();
|
| - names[expr.continuation] = cont;
|
| - String parameters = expr.continuation.parameters
|
| + names[node.continuation] = cont;
|
| + String parameters = node.continuation.parameters
|
| .map((p) {
|
| String name = newValueName();
|
| names[p] = name;
|
| - return name;
|
| + return ' $name';
|
| })
|
| - .join(' ');
|
| - String contBody = expr.continuation.body.accept(this);
|
| - String body = expr.body.accept(this);
|
| - return '(LetCont ($cont $parameters) $contBody) $body';
|
| + .join('');
|
| + String contBody = visit(node.continuation.body);
|
| + String body = visit(node.body);
|
| + return '(LetCont ($cont$parameters) $contBody) $body';
|
| }
|
|
|
| - String visitInvokeStatic(InvokeStatic expr) {
|
| - String name = expr.target.name;
|
| - String cont = names[expr.continuation.definition];
|
| - String args = expr.arguments.map((v) => names[v.definition]).join(' ');
|
| + String visitInvokeStatic(InvokeStatic node) {
|
| + String name = node.target.name;
|
| + String cont = names[node.continuation.definition];
|
| + String args = node.arguments.map((v) => names[v.definition]).join(' ');
|
| return '(InvokeStatic $name $cont $args)';
|
| }
|
|
|
| - String visitInvokeContinuation(InvokeContinuation expr) {
|
| - String cont = names[expr.continuation.definition];
|
| - String arg = names[expr.argument.definition];
|
| - return '(InvokeContinuation $cont $arg)';
|
| + String visitInvokeContinuation(InvokeContinuation node) {
|
| + String cont = names[node.continuation.definition];
|
| + String args = node.arguments.map((v) => names[v.definition]).join(' ');
|
| + return '(InvokeContinuation $cont $args)';
|
| + }
|
| +
|
| + String visitBranch(Branch node) {
|
| + String condition = visit(node.condition);
|
| + String trueCont = names[node.trueContinuation.definition];
|
| + String falseCont = names[node.falseContinuation.definition];
|
| + return '(Branch $condition $trueCont $falseCont)';
|
| }
|
|
|
| - String visitConstant(Constant triv) {
|
| - return '(Constant ${triv.value})';
|
| + String visitConstant(Constant node) {
|
| + return '(Constant ${node.value})';
|
| }
|
|
|
| - String visitParameter(Parameter triv) {
|
| + String visitParameter(Parameter node) {
|
| // Parameters are visited directly in visitLetCont.
|
| return '(Unexpected Parameter)';
|
| }
|
|
|
| - String visitContinuation(Continuation triv) {
|
| + String visitContinuation(Continuation node) {
|
| // Continuations are visited directly in visitLetCont.
|
| return '(Unexpected Continuation)';
|
| }
|
| +
|
| + String visitIsTrue(IsTrue node) {
|
| + String value = names[node.value.definition];
|
| + return '(IsTrue $value)';
|
| + }
|
| }
|
|
|