| 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
|
| deleted file mode 100644
|
| index a1fe55edbfcd0802678c4f289ee8aa65e07fe2f4..0000000000000000000000000000000000000000
|
| --- a/pkg/compiler/lib/src/tree_ir/tree_ir_nodes.dart
|
| +++ /dev/null
|
| @@ -1,1607 +0,0 @@
|
| -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
|
| -// for details. All rights reserved. Use of this source code is governed by a
|
| -// BSD-style license that can be found in the LICENSE file.
|
| -
|
| -library tree_ir_nodes;
|
| -
|
| -import '../constants/values.dart' as values;
|
| -import '../dart_types.dart' show DartType, InterfaceType, TypeVariableType;
|
| -import '../elements/elements.dart';
|
| -import '../io/source_information.dart' show SourceInformation;
|
| -import '../types/types.dart' show TypeMask;
|
| -import '../universe/selector.dart' show Selector;
|
| -
|
| -import '../cps_ir/builtin_operator.dart';
|
| -export '../cps_ir/builtin_operator.dart';
|
| -import '../cps_ir/cps_ir_nodes.dart' show TypeExpressionKind;
|
| -export '../cps_ir/cps_ir_nodes.dart' show TypeExpressionKind;
|
| -
|
| -// These imports are only used for the JavaScript specific nodes. If we want to
|
| -// support more than one native backend, we should probably create better
|
| -// abstractions for native code and its type and effect system.
|
| -import '../js/js.dart' as js show Template;
|
| -import '../native/native.dart' as native show NativeBehavior;
|
| -import '../types/types.dart' as types show TypeMask;
|
| -
|
| -// The Tree language is the target of translation out of the CPS-based IR.
|
| -//
|
| -// The translation from CPS to Dart consists of several stages. Among the
|
| -// stages are translation to direct style, translation out of SSA, eliminating
|
| -// unnecessary names, recognizing high-level control constructs. Combining
|
| -// these separate concerns is complicated and the constraints of the CPS-based
|
| -// language do not permit a multi-stage translation.
|
| -//
|
| -// For that reason, CPS is translated to the direct-style language Tree.
|
| -// Translation out of SSA, unnaming, and control-flow, as well as 'instruction
|
| -// selection' are performed on the Tree language.
|
| -//
|
| -// 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.
|
| - */
|
| -abstract class Node {
|
| - /// Workaround for a slow Object.hashCode in the VM.
|
| - static int _usedHashCodes = 0;
|
| - final int hashCode = ++_usedHashCodes;
|
| -}
|
| -
|
| -/**
|
| - * The base class of [Expression]s.
|
| - */
|
| -abstract class Expression extends Node {
|
| - accept(ExpressionVisitor v);
|
| - accept1(ExpressionVisitor1 v, arg);
|
| -
|
| - SourceInformation get sourceInformation => null;
|
| -}
|
| -
|
| -abstract class Statement extends Node {
|
| - Statement get next;
|
| - void set next(Statement s);
|
| - accept(StatementVisitor v);
|
| - accept1(StatementVisitor1 v, arg);
|
| -}
|
| -
|
| -/**
|
| - * Labels name [LabeledStatement]s.
|
| - */
|
| -class Label {
|
| - /// Number of [Break] or [Continue] statements that target this label.
|
| - /// The [Break] constructor will increment this automatically, but the
|
| - /// counter must be decremented by hand when a [Break] becomes orphaned.
|
| - int useCount = 0;
|
| -
|
| - /// The [LabeledStatement] or [WhileTrue] binding this label.
|
| - JumpTarget binding;
|
| -}
|
| -
|
| -/**
|
| - * A local variable in the tree IR.
|
| - *
|
| - * All tree IR variables are mutable.
|
| - *
|
| - * 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], and [Try] automatically update the reference
|
| - * count for their variables, but when transforming the tree, the transformer
|
| - * is responsible for updating reference counts.
|
| - */
|
| -class Variable extends Node {
|
| - /// Function that declares this variable.
|
| - ExecutableElement host;
|
| -
|
| - /// [Entity] used for synthesizing a name for the variable.
|
| - /// 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:
|
| - /// - left-hand of an [Assign]
|
| - /// - parameter in a [FunctionDefinition]
|
| - /// - catch parameter in a [Try]
|
| - int writeCount = 0;
|
| -
|
| - /// True if an inner JS function might access this variable through a
|
| - /// [ForeignCode] node.
|
| - bool isCaptured = false;
|
| -
|
| - Variable(this.host, this.element) {
|
| - assert(host != null);
|
| - }
|
| -
|
| - String toString() =>
|
| - element == null ? 'Variable.${hashCode}' : element.toString();
|
| -}
|
| -
|
| -/// Read the value of a variable.
|
| -class VariableUse extends Expression {
|
| - Variable variable;
|
| - SourceInformation sourceInformation;
|
| -
|
| - /// Creates a use of [variable] and updates its `readCount`.
|
| - VariableUse(this.variable, {this.sourceInformation}) {
|
| - variable.readCount++;
|
| - }
|
| -
|
| - accept(ExpressionVisitor visitor) => visitor.visitVariableUse(this);
|
| - accept1(ExpressionVisitor1 visitor, arg) {
|
| - return visitor.visitVariableUse(this, arg);
|
| - }
|
| -}
|
| -
|
| -class Assign extends Expression {
|
| - Variable variable;
|
| - Expression value;
|
| - SourceInformation sourceInformation;
|
| -
|
| - Assign(this.variable, this.value, {this.sourceInformation}) {
|
| - variable.writeCount++;
|
| - }
|
| -
|
| - accept(ExpressionVisitor v) => v.visitAssign(this);
|
| - accept1(ExpressionVisitor1 v, arg) => v.visitAssign(this, arg);
|
| -
|
| - static ExpressionStatement makeStatement(Variable variable, Expression value,
|
| - [Statement next]) {
|
| - return new ExpressionStatement(new Assign(variable, value), next);
|
| - }
|
| -}
|
| -
|
| -/**
|
| - * Common interface for invocations with arguments.
|
| - */
|
| -abstract class Invoke {
|
| - List<Expression> get arguments;
|
| -}
|
| -
|
| -/**
|
| - * A call to a static function or getter/setter to a static field.
|
| - *
|
| - * In contrast to the CPS-based IR, the arguments can be arbitrary expressions.
|
| - */
|
| -class InvokeStatic extends Expression implements Invoke {
|
| - final Entity target;
|
| - final List<Expression> arguments;
|
| - final Selector selector;
|
| - final SourceInformation sourceInformation;
|
| -
|
| - InvokeStatic(this.target, this.selector, this.arguments,
|
| - [this.sourceInformation]);
|
| -
|
| - accept(ExpressionVisitor visitor) => visitor.visitInvokeStatic(this);
|
| - accept1(ExpressionVisitor1 visitor, arg) {
|
| - return visitor.visitInvokeStatic(this, arg);
|
| - }
|
| -}
|
| -
|
| -/**
|
| - * A call to a method, operator, getter, setter or index getter/setter.
|
| - *
|
| - * If [receiver] is `null`, an error is thrown before the arguments are
|
| - * evaluated. This corresponds to the JS evaluation order.
|
| - */
|
| -class InvokeMethod extends Expression implements Invoke {
|
| - Expression receiver;
|
| - final Selector selector;
|
| - final TypeMask mask;
|
| - final List<Expression> arguments;
|
| - final SourceInformation sourceInformation;
|
| -
|
| - /// If true, it is known that the receiver cannot be `null`.
|
| - bool receiverIsNotNull = false;
|
| -
|
| - InvokeMethod(this.receiver, this.selector, this.mask, this.arguments,
|
| - this.sourceInformation) {
|
| - assert(receiver != null);
|
| - }
|
| -
|
| - accept(ExpressionVisitor visitor) => visitor.visitInvokeMethod(this);
|
| - accept1(ExpressionVisitor1 visitor, arg) {
|
| - return visitor.visitInvokeMethod(this, arg);
|
| - }
|
| -}
|
| -
|
| -/// Invoke [target] on [receiver], bypassing ordinary dispatch semantics.
|
| -///
|
| -/// Since the [receiver] is not used for method lookup, it may be `null`
|
| -/// without an error being thrown.
|
| -class InvokeMethodDirectly extends Expression implements Invoke {
|
| - Expression receiver;
|
| - final Element target;
|
| - final Selector selector;
|
| - final List<Expression> arguments;
|
| - final SourceInformation sourceInformation;
|
| -
|
| - InvokeMethodDirectly(this.receiver, this.target, this.selector,
|
| - this.arguments, this.sourceInformation);
|
| -
|
| - bool get isTearOff => selector.isGetter && !target.isGetter;
|
| -
|
| - accept(ExpressionVisitor visitor) => visitor.visitInvokeMethodDirectly(this);
|
| - accept1(ExpressionVisitor1 visitor, arg) {
|
| - return visitor.visitInvokeMethodDirectly(this, arg);
|
| - }
|
| -}
|
| -
|
| -/**
|
| - * Call to a factory or generative constructor.
|
| - */
|
| -class InvokeConstructor extends Expression implements Invoke {
|
| - final DartType type;
|
| - final FunctionElement target;
|
| - final List<Expression> arguments;
|
| - final Selector selector;
|
| - final SourceInformation sourceInformation;
|
| -
|
| - /// TODO(karlklose): get rid of this field. Instead use the constant's
|
| - /// expression to find the constructor to be called in dart2dart.
|
| - final values.ConstantValue constant;
|
| -
|
| - InvokeConstructor(this.type, this.target, this.selector, this.arguments,
|
| - this.sourceInformation,
|
| - [this.constant]);
|
| -
|
| - ClassElement get targetClass => target.enclosingElement;
|
| -
|
| - accept(ExpressionVisitor visitor) {
|
| - return visitor.visitInvokeConstructor(this);
|
| - }
|
| -
|
| - accept1(ExpressionVisitor1 visitor, arg) {
|
| - return visitor.visitInvokeConstructor(this, arg);
|
| - }
|
| -}
|
| -
|
| -/// Call a method using a one-shot interceptor.
|
| -///
|
| -/// There is no explicit receiver, the first argument serves that purpose.
|
| -class OneShotInterceptor extends Expression implements Invoke {
|
| - final Selector selector;
|
| - final TypeMask mask;
|
| - final List<Expression> arguments;
|
| - final SourceInformation sourceInformation;
|
| -
|
| - OneShotInterceptor(
|
| - this.selector, this.mask, this.arguments, this.sourceInformation);
|
| -
|
| - accept(ExpressionVisitor visitor) => visitor.visitOneShotInterceptor(this);
|
| - accept1(ExpressionVisitor1 visitor, arg) {
|
| - return visitor.visitOneShotInterceptor(this, arg);
|
| - }
|
| -}
|
| -
|
| -/**
|
| - * A constant.
|
| - */
|
| -class Constant extends Expression {
|
| - final values.ConstantValue value;
|
| - final SourceInformation sourceInformation;
|
| -
|
| - Constant(this.value, {this.sourceInformation});
|
| -
|
| - Constant.bool(values.BoolConstantValue constantValue)
|
| - : value = constantValue,
|
| - sourceInformation = null;
|
| -
|
| - accept(ExpressionVisitor visitor) => visitor.visitConstant(this);
|
| - accept1(ExpressionVisitor1 visitor, arg) => visitor.visitConstant(this, arg);
|
| -
|
| - String toString() => 'Constant(value=${value.toStructuredText()})';
|
| -}
|
| -
|
| -class This extends Expression {
|
| - accept(ExpressionVisitor visitor) => visitor.visitThis(this);
|
| - accept1(ExpressionVisitor1 visitor, arg) => visitor.visitThis(this, arg);
|
| -}
|
| -
|
| -class LiteralList extends Expression {
|
| - final InterfaceType type;
|
| - final List<Expression> values;
|
| -
|
| - LiteralList(this.type, this.values);
|
| -
|
| - accept(ExpressionVisitor visitor) => visitor.visitLiteralList(this);
|
| - accept1(ExpressionVisitor1 visitor, arg) {
|
| - return visitor.visitLiteralList(this, arg);
|
| - }
|
| -}
|
| -
|
| -/// Type test or type cast.
|
| -///
|
| -/// Note that if this is a type test, then [type] cannot be `Object`, `dynamic`,
|
| -/// or the `Null` type. These cases are compiled to other node types.
|
| -class TypeOperator extends Expression {
|
| - Expression value;
|
| - final DartType type;
|
| - final List<Expression> typeArguments;
|
| - final bool isTypeTest;
|
| -
|
| - TypeOperator(this.value, this.type, this.typeArguments,
|
| - {bool this.isTypeTest});
|
| -
|
| - accept(ExpressionVisitor visitor) => visitor.visitTypeOperator(this);
|
| - accept1(ExpressionVisitor1 visitor, arg) {
|
| - return visitor.visitTypeOperator(this, arg);
|
| - }
|
| -
|
| - String get operator => isTypeTest ? 'is' : 'as';
|
| -}
|
| -
|
| -/**
|
| - * Apply a built-in operator.
|
| - *
|
| - * It must be known that the arguments have the proper types.
|
| - * Null is not a valid argument to any of the built-in operators.
|
| - */
|
| -class ApplyBuiltinOperator extends Expression {
|
| - BuiltinOperator operator;
|
| - List<Expression> arguments;
|
| - SourceInformation sourceInformation;
|
| -
|
| - ApplyBuiltinOperator(this.operator, this.arguments, this.sourceInformation);
|
| -
|
| - accept(ExpressionVisitor visitor) {
|
| - return visitor.visitApplyBuiltinOperator(this);
|
| - }
|
| -
|
| - accept1(ExpressionVisitor1 visitor, arg) {
|
| - return visitor.visitApplyBuiltinOperator(this, arg);
|
| - }
|
| -}
|
| -
|
| -class ApplyBuiltinMethod extends Expression {
|
| - BuiltinMethod method;
|
| - Expression receiver;
|
| - List<Expression> arguments;
|
| -
|
| - bool receiverIsNotNull;
|
| -
|
| - ApplyBuiltinMethod(this.method, this.receiver, this.arguments,
|
| - {this.receiverIsNotNull: false});
|
| -
|
| - accept(ExpressionVisitor visitor) {
|
| - return visitor.visitApplyBuiltinMethod(this);
|
| - }
|
| -
|
| - accept1(ExpressionVisitor1 visitor, arg) {
|
| - return visitor.visitApplyBuiltinMethod(this, arg);
|
| - }
|
| -}
|
| -
|
| -/// A conditional expression.
|
| -class Conditional extends Expression {
|
| - Expression condition;
|
| - Expression thenExpression;
|
| - Expression elseExpression;
|
| -
|
| - Conditional(this.condition, this.thenExpression, this.elseExpression);
|
| -
|
| - accept(ExpressionVisitor visitor) => visitor.visitConditional(this);
|
| - accept1(ExpressionVisitor1 visitor, arg) {
|
| - return visitor.visitConditional(this, arg);
|
| - }
|
| -
|
| - String toString() => 'Conditional(condition=$condition,thenExpression='
|
| - '$thenExpression,elseExpression=$elseExpression)';
|
| -}
|
| -
|
| -/// An && or || expression. The operator is internally represented as a boolean
|
| -/// [isAnd] to simplify rewriting of logical operators.
|
| -/// Note the result of && and || is one of the arguments, which might not be
|
| -/// boolean. 'ShortCircuitOperator' might have been a better name.
|
| -class LogicalOperator extends Expression {
|
| - Expression left;
|
| - bool isAnd;
|
| - Expression right;
|
| -
|
| - LogicalOperator(this.left, this.right, this.isAnd);
|
| - LogicalOperator.and(this.left, this.right) : isAnd = true;
|
| - LogicalOperator.or(this.left, this.right) : isAnd = false;
|
| -
|
| - String get operator => isAnd ? '&&' : '||';
|
| -
|
| - accept(ExpressionVisitor visitor) => visitor.visitLogicalOperator(this);
|
| - accept1(ExpressionVisitor1 visitor, arg) {
|
| - return visitor.visitLogicalOperator(this, arg);
|
| - }
|
| -
|
| - String toString() => 'LogicalOperator(left=$left,right=$right,isAnd=$isAnd)';
|
| -}
|
| -
|
| -/// Logical negation.
|
| -// TODO(asgerf): Replace this class with the IsFalsy builtin operator?
|
| -// Right now the tree builder compiles IsFalsy to Not.
|
| -class Not extends Expression {
|
| - Expression operand;
|
| -
|
| - Not(this.operand);
|
| -
|
| - accept(ExpressionVisitor visitor) => visitor.visitNot(this);
|
| - accept1(ExpressionVisitor1 visitor, arg) => visitor.visitNot(this, arg);
|
| -}
|
| -
|
| -/// A [LabeledStatement] or [WhileTrue] or [For].
|
| -abstract class JumpTarget extends Statement {
|
| - Label get label;
|
| - Statement get body;
|
| -}
|
| -
|
| -/**
|
| - * A labeled statement. Breaks to the label within the labeled statement
|
| - * target the successor statement.
|
| - */
|
| -class LabeledStatement extends JumpTarget {
|
| - Statement next;
|
| - final Label label;
|
| - Statement body;
|
| -
|
| - LabeledStatement(this.label, this.body, this.next) {
|
| - assert(label.binding == null);
|
| - label.binding = this;
|
| - }
|
| -
|
| - accept(StatementVisitor visitor) => visitor.visitLabeledStatement(this);
|
| - accept1(StatementVisitor1 visitor, arg) {
|
| - return visitor.visitLabeledStatement(this, arg);
|
| - }
|
| -}
|
| -
|
| -/// A [WhileTrue] or [For] loop.
|
| -abstract class Loop extends JumpTarget {}
|
| -
|
| -/**
|
| - * A labeled while(true) loop.
|
| - */
|
| -class WhileTrue extends Loop {
|
| - final Label label;
|
| - Statement body;
|
| -
|
| - WhileTrue(this.label, this.body) {
|
| - assert(label.binding == null);
|
| - label.binding = this;
|
| - }
|
| -
|
| - Statement get next => null;
|
| - void set next(Statement s) => throw 'UNREACHABLE';
|
| -
|
| - accept(StatementVisitor visitor) => visitor.visitWhileTrue(this);
|
| - accept1(StatementVisitor1 visitor, arg) => visitor.visitWhileTrue(this, arg);
|
| -}
|
| -
|
| -/**
|
| - * A loop with a condition and update expressions. If there are any update
|
| - * expressions, this generates a for loop, otherwise a while loop.
|
| - *
|
| - * When the condition is false, control resumes at the [next] statement.
|
| - *
|
| - * It is NOT valid to target this statement with a [Break].
|
| - * The only way to reach [next] is for the condition to evaluate to false.
|
| - *
|
| - * [For] statements are introduced in the [LoopRewriter] and are
|
| - * assumed not to occur before then.
|
| - */
|
| -class For extends Loop {
|
| - final Label label;
|
| - Expression condition;
|
| - List<Expression> updates;
|
| - Statement body;
|
| - Statement next;
|
| -
|
| - For(this.label, this.condition, this.updates, this.body, this.next) {
|
| - assert(label.binding == null);
|
| - label.binding = this;
|
| - }
|
| -
|
| - accept(StatementVisitor visitor) => visitor.visitFor(this);
|
| - accept1(StatementVisitor1 visitor, arg) {
|
| - return visitor.visitFor(this, arg);
|
| - }
|
| -}
|
| -
|
| -/// A [Break] or [Continue] statement.
|
| -abstract class Jump extends Statement {
|
| - Label get target;
|
| -}
|
| -
|
| -/**
|
| - * A break from an enclosing [LabeledStatement]. The break targets the
|
| - * labeled statement's successor statement.
|
| - */
|
| -class Break extends Jump {
|
| - final Label target;
|
| -
|
| - Statement get next => null;
|
| - void set next(Statement s) => throw 'UNREACHABLE';
|
| -
|
| - Break(this.target) {
|
| - ++target.useCount;
|
| - }
|
| -
|
| - accept(StatementVisitor visitor) => visitor.visitBreak(this);
|
| - accept1(StatementVisitor1 visitor, arg) => visitor.visitBreak(this, arg);
|
| -}
|
| -
|
| -/**
|
| - * A continue to an enclosing [WhileTrue] or [For] loop.
|
| - * The continue targets the loop's body.
|
| - */
|
| -class Continue extends Jump {
|
| - final Label target;
|
| -
|
| - Statement get next => null;
|
| - void set next(Statement s) => throw 'UNREACHABLE';
|
| -
|
| - Continue(this.target) {
|
| - ++target.useCount;
|
| - }
|
| -
|
| - accept(StatementVisitor visitor) => visitor.visitContinue(this);
|
| - accept1(StatementVisitor1 visitor, arg) => visitor.visitContinue(this, arg);
|
| -}
|
| -
|
| -/**
|
| - * A return exit from the function.
|
| - *
|
| - * In contrast to the CPS-based IR, the return value is an arbitrary
|
| - * expression.
|
| - */
|
| -class Return extends Statement {
|
| - /// Should not be null. Use [Constant] with [NullConstantValue] for void
|
| - /// returns.
|
| - /// Even in constructors this holds true. Take special care when translating
|
| - /// back to dart, where `return null;` in a constructor is an error.
|
| - Expression value;
|
| - SourceInformation sourceInformation;
|
| -
|
| - Statement get next => null;
|
| - void set next(Statement s) => throw 'UNREACHABLE';
|
| -
|
| - Return(this.value, {this.sourceInformation});
|
| -
|
| - accept(StatementVisitor visitor) => visitor.visitReturn(this);
|
| - accept1(StatementVisitor1 visitor, arg) => visitor.visitReturn(this, arg);
|
| -}
|
| -
|
| -/// A throw statement.
|
| -///
|
| -/// In the Tree IR, throw is a statement (like JavaScript and unlike Dart).
|
| -/// It does not have a successor statement.
|
| -class Throw extends Statement {
|
| - Expression value;
|
| -
|
| - Statement get next => null;
|
| - void set next(Statement s) => throw 'UNREACHABLE';
|
| -
|
| - Throw(this.value);
|
| -
|
| - accept(StatementVisitor visitor) => visitor.visitThrow(this);
|
| - accept1(StatementVisitor1 visitor, arg) => visitor.visitThrow(this, arg);
|
| -}
|
| -
|
| -/**
|
| - * A conditional branch based on the true value of an [Expression].
|
| - */
|
| -class If extends Statement {
|
| - Expression condition;
|
| - Statement thenStatement;
|
| - Statement elseStatement;
|
| - SourceInformation sourceInformation;
|
| -
|
| - Statement get next => null;
|
| - void set next(Statement s) => throw 'UNREACHABLE';
|
| -
|
| - If(this.condition, this.thenStatement, this.elseStatement,
|
| - this.sourceInformation);
|
| -
|
| - accept(StatementVisitor visitor) => visitor.visitIf(this);
|
| - accept1(StatementVisitor1 visitor, arg) => visitor.visitIf(this, arg);
|
| -}
|
| -
|
| -class ExpressionStatement extends Statement {
|
| - Statement next;
|
| - Expression expression;
|
| -
|
| - ExpressionStatement(this.expression, this.next);
|
| -
|
| - accept(StatementVisitor visitor) => visitor.visitExpressionStatement(this);
|
| - accept1(StatementVisitor1 visitor, arg) {
|
| - return visitor.visitExpressionStatement(this, arg);
|
| - }
|
| -}
|
| -
|
| -class Try extends Statement {
|
| - Statement tryBody;
|
| - List<Variable> catchParameters;
|
| - Statement catchBody;
|
| -
|
| - Statement get next => null;
|
| - void set next(Statement s) => throw 'UNREACHABLE';
|
| -
|
| - Try(this.tryBody, this.catchParameters, this.catchBody) {
|
| - for (Variable variable in catchParameters) {
|
| - variable.writeCount++; // Being a catch parameter counts as a write.
|
| - }
|
| - }
|
| -
|
| - accept(StatementVisitor visitor) => visitor.visitTry(this);
|
| - accept1(StatementVisitor1 visitor, arg) {
|
| - return visitor.visitTry(this, arg);
|
| - }
|
| -}
|
| -
|
| -/// A statement that is known to be unreachable.
|
| -class Unreachable extends Statement {
|
| - Statement get next => null;
|
| - void set next(Statement value) => throw 'UNREACHABLE';
|
| -
|
| - accept(StatementVisitor visitor) => visitor.visitUnreachable(this);
|
| - accept1(StatementVisitor1 visitor, arg) {
|
| - return visitor.visitUnreachable(this, arg);
|
| - }
|
| -}
|
| -
|
| -class FunctionDefinition extends Node {
|
| - final ExecutableElement element;
|
| - final List<Variable> parameters;
|
| - final SourceInformation sourceInformation;
|
| - Statement body;
|
| -
|
| - /// Creates a function definition and updates `writeCount` for [parameters].
|
| - FunctionDefinition(this.element, this.parameters, this.body,
|
| - {this.sourceInformation}) {
|
| - for (Variable param in parameters) {
|
| - param.writeCount++; // Being a parameter counts as a write.
|
| - }
|
| - }
|
| -}
|
| -
|
| -class CreateBox extends Expression {
|
| - accept(ExpressionVisitor visitor) => visitor.visitCreateBox(this);
|
| - accept1(ExpressionVisitor1 visitor, arg) => visitor.visitCreateBox(this, arg);
|
| -}
|
| -
|
| -class CreateInstance extends Expression {
|
| - ClassElement classElement;
|
| - List<Expression> arguments;
|
| - Expression typeInformation;
|
| - SourceInformation sourceInformation;
|
| -
|
| - CreateInstance(this.classElement, this.arguments, this.typeInformation,
|
| - this.sourceInformation);
|
| -
|
| - accept(ExpressionVisitor visitor) => visitor.visitCreateInstance(this);
|
| - accept1(ExpressionVisitor1 visitor, arg) {
|
| - return visitor.visitCreateInstance(this, arg);
|
| - }
|
| -}
|
| -
|
| -class GetField extends Expression {
|
| - Expression object;
|
| - Element field;
|
| - bool objectIsNotNull;
|
| - SourceInformation sourceInformation;
|
| -
|
| - GetField(this.object, this.field, this.sourceInformation,
|
| - {this.objectIsNotNull: false});
|
| -
|
| - accept(ExpressionVisitor visitor) => visitor.visitGetField(this);
|
| - accept1(ExpressionVisitor1 visitor, arg) => visitor.visitGetField(this, arg);
|
| -}
|
| -
|
| -class SetField extends Expression {
|
| - Expression object;
|
| - Element field;
|
| - Expression value;
|
| - SourceInformation sourceInformation;
|
| -
|
| - /// If non-null, this is a compound assignment to the field, using the given
|
| - /// operator. The operator must be a compoundable operator.
|
| - BuiltinOperator compound;
|
| -
|
| - SetField(this.object, this.field, this.value, this.sourceInformation,
|
| - {this.compound});
|
| -
|
| - accept(ExpressionVisitor visitor) => visitor.visitSetField(this);
|
| - accept1(ExpressionVisitor1 visitor, arg) => visitor.visitSetField(this, arg);
|
| -}
|
| -
|
| -/// Read the type test property from [object]. The value is truthy/fasly rather
|
| -/// than bool. [object] must not be `null`.
|
| -class GetTypeTestProperty extends Expression {
|
| - Expression object;
|
| - DartType dartType;
|
| -
|
| - GetTypeTestProperty(this.object, this.dartType);
|
| -
|
| - accept(ExpressionVisitor visitor) => visitor.visitGetTypeTestProperty(this);
|
| - accept1(ExpressionVisitor1 visitor, arg) =>
|
| - visitor.visitGetTypeTestProperty(this, arg);
|
| -}
|
| -
|
| -/// Read the value of a field, possibly provoking its initializer to evaluate,
|
| -/// or tear off a static method.
|
| -class GetStatic extends Expression {
|
| - Element element;
|
| - SourceInformation sourceInformation;
|
| - bool useLazyGetter = false;
|
| -
|
| - GetStatic(this.element, this.sourceInformation);
|
| -
|
| - GetStatic.lazy(this.element, this.sourceInformation) : useLazyGetter = true;
|
| -
|
| - accept(ExpressionVisitor visitor) => visitor.visitGetStatic(this);
|
| - accept1(ExpressionVisitor1 visitor, arg) => visitor.visitGetStatic(this, arg);
|
| -}
|
| -
|
| -class SetStatic extends Expression {
|
| - Element element;
|
| - Expression value;
|
| - SourceInformation sourceInformation;
|
| - BuiltinOperator compound;
|
| -
|
| - SetStatic(this.element, this.value, this.sourceInformation, {this.compound});
|
| -
|
| - accept(ExpressionVisitor visitor) => visitor.visitSetStatic(this);
|
| - accept1(ExpressionVisitor1 visitor, arg) => visitor.visitSetStatic(this, arg);
|
| -}
|
| -
|
| -class GetLength extends Expression {
|
| - Expression object;
|
| -
|
| - GetLength(this.object);
|
| -
|
| - accept(ExpressionVisitor v) => v.visitGetLength(this);
|
| - accept1(ExpressionVisitor1 v, arg) => v.visitGetLength(this, arg);
|
| -}
|
| -
|
| -class GetIndex extends Expression {
|
| - Expression object;
|
| - Expression index;
|
| -
|
| - GetIndex(this.object, this.index);
|
| -
|
| - accept(ExpressionVisitor v) => v.visitGetIndex(this);
|
| - accept1(ExpressionVisitor1 v, arg) => v.visitGetIndex(this, arg);
|
| -}
|
| -
|
| -class SetIndex extends Expression {
|
| - Expression object;
|
| - Expression index;
|
| - Expression value;
|
| - BuiltinOperator compound;
|
| -
|
| - SetIndex(this.object, this.index, this.value, {this.compound});
|
| -
|
| - accept(ExpressionVisitor v) => v.visitSetIndex(this);
|
| - accept1(ExpressionVisitor1 v, arg) => v.visitSetIndex(this, arg);
|
| -}
|
| -
|
| -class ReifyRuntimeType extends Expression {
|
| - Expression value;
|
| - SourceInformation sourceInformation;
|
| -
|
| - ReifyRuntimeType(this.value, this.sourceInformation);
|
| -
|
| - accept(ExpressionVisitor visitor) {
|
| - return visitor.visitReifyRuntimeType(this);
|
| - }
|
| -
|
| - accept1(ExpressionVisitor1 visitor, arg) {
|
| - return visitor.visitReifyRuntimeType(this, arg);
|
| - }
|
| -}
|
| -
|
| -class ReadTypeVariable extends Expression {
|
| - final TypeVariableType variable;
|
| - Expression target;
|
| - final SourceInformation sourceInformation;
|
| -
|
| - ReadTypeVariable(this.variable, this.target, this.sourceInformation);
|
| -
|
| - accept(ExpressionVisitor visitor) {
|
| - return visitor.visitReadTypeVariable(this);
|
| - }
|
| -
|
| - accept1(ExpressionVisitor1 visitor, arg) {
|
| - return visitor.visitReadTypeVariable(this, arg);
|
| - }
|
| -}
|
| -
|
| -class CreateInvocationMirror extends Expression {
|
| - final Selector selector;
|
| - final List<Expression> arguments;
|
| -
|
| - CreateInvocationMirror(this.selector, this.arguments);
|
| -
|
| - accept(ExpressionVisitor visitor) {
|
| - return visitor.visitCreateInvocationMirror(this);
|
| - }
|
| -
|
| - accept1(ExpressionVisitor1 visitor, arg) {
|
| - return visitor.visitCreateInvocationMirror(this, arg);
|
| - }
|
| -}
|
| -
|
| -class Interceptor extends Expression {
|
| - Expression input;
|
| - Set<ClassElement> interceptedClasses;
|
| - final SourceInformation sourceInformation;
|
| -
|
| - Interceptor(this.input, this.interceptedClasses, this.sourceInformation);
|
| -
|
| - accept(ExpressionVisitor visitor) {
|
| - return visitor.visitInterceptor(this);
|
| - }
|
| -
|
| - accept1(ExpressionVisitor1 visitor, arg) {
|
| - return visitor.visitInterceptor(this, arg);
|
| - }
|
| -}
|
| -
|
| -class ForeignCode extends Node {
|
| - final js.Template codeTemplate;
|
| - final types.TypeMask type;
|
| - final List<Expression> arguments;
|
| - final native.NativeBehavior nativeBehavior;
|
| - final List<bool> nullableArguments; // One 'bit' per argument.
|
| - final Element dependency;
|
| - final SourceInformation sourceInformation;
|
| -
|
| - ForeignCode(this.codeTemplate, this.type, this.arguments, this.nativeBehavior,
|
| - this.nullableArguments, this.dependency, this.sourceInformation) {
|
| - assert(arguments.length == nullableArguments.length);
|
| - }
|
| -}
|
| -
|
| -class ForeignExpression extends ForeignCode implements Expression {
|
| - ForeignExpression(
|
| - js.Template codeTemplate,
|
| - types.TypeMask type,
|
| - List<Expression> arguments,
|
| - native.NativeBehavior nativeBehavior,
|
| - List<bool> nullableArguments,
|
| - Element dependency,
|
| - SourceInformation sourceInformation)
|
| - : super(codeTemplate, type, arguments, nativeBehavior, nullableArguments,
|
| - dependency, sourceInformation);
|
| -
|
| - accept(ExpressionVisitor visitor) {
|
| - return visitor.visitForeignExpression(this);
|
| - }
|
| -
|
| - accept1(ExpressionVisitor1 visitor, arg) {
|
| - return visitor.visitForeignExpression(this, arg);
|
| - }
|
| -}
|
| -
|
| -class ForeignStatement extends ForeignCode implements Statement {
|
| - ForeignStatement(
|
| - js.Template codeTemplate,
|
| - types.TypeMask type,
|
| - List<Expression> arguments,
|
| - native.NativeBehavior nativeBehavior,
|
| - List<bool> nullableArguments,
|
| - Element dependency,
|
| - SourceInformation sourceInformation)
|
| - : super(codeTemplate, type, arguments, nativeBehavior, nullableArguments,
|
| - dependency, sourceInformation);
|
| -
|
| - accept(StatementVisitor visitor) {
|
| - return visitor.visitForeignStatement(this);
|
| - }
|
| -
|
| - accept1(StatementVisitor1 visitor, arg) {
|
| - return visitor.visitForeignStatement(this, arg);
|
| - }
|
| -
|
| - @override
|
| - Statement get next => null;
|
| -
|
| - @override
|
| - void set next(Statement s) => throw 'UNREACHABLE';
|
| -}
|
| -
|
| -/// Denotes the internal representation of [dartType], where all type variables
|
| -/// are replaced by the values in [arguments].
|
| -/// (See documentation on the TypeExpression CPS node for more details.)
|
| -class TypeExpression extends Expression {
|
| - final TypeExpressionKind kind;
|
| - final DartType dartType;
|
| - final List<Expression> arguments;
|
| -
|
| - TypeExpression(this.kind, this.dartType, this.arguments);
|
| -
|
| - accept(ExpressionVisitor visitor) {
|
| - return visitor.visitTypeExpression(this);
|
| - }
|
| -
|
| - accept1(ExpressionVisitor1 visitor, arg) {
|
| - return visitor.visitTypeExpression(this, arg);
|
| - }
|
| -}
|
| -
|
| -class Await extends Expression {
|
| - Expression input;
|
| -
|
| - Await(this.input);
|
| -
|
| - accept(ExpressionVisitor visitor) {
|
| - return visitor.visitAwait(this);
|
| - }
|
| -
|
| - accept1(ExpressionVisitor1 visitor, arg) {
|
| - return visitor.visitAwait(this, arg);
|
| - }
|
| -}
|
| -
|
| -class Yield extends Statement {
|
| - Statement next;
|
| - Expression input;
|
| - final bool hasStar;
|
| -
|
| - Yield(this.input, this.hasStar, this.next);
|
| -
|
| - accept(StatementVisitor visitor) {
|
| - return visitor.visitYield(this);
|
| - }
|
| -
|
| - accept1(StatementVisitor1 visitor, arg) {
|
| - return visitor.visitYield(this, arg);
|
| - }
|
| -}
|
| -
|
| -class ReceiverCheck extends Statement {
|
| - Expression condition;
|
| - Expression value;
|
| - Selector selector;
|
| - bool useSelector;
|
| - bool useInvoke;
|
| - Statement next;
|
| - SourceInformation sourceInformation;
|
| -
|
| - ReceiverCheck(
|
| - {this.condition,
|
| - this.value,
|
| - this.selector,
|
| - this.useSelector,
|
| - this.useInvoke,
|
| - this.next,
|
| - this.sourceInformation});
|
| -
|
| - accept(StatementVisitor visitor) {
|
| - return visitor.visitReceiverCheck(this);
|
| - }
|
| -
|
| - accept1(StatementVisitor1 visitor, arg) {
|
| - return visitor.visitReceiverCheck(this, arg);
|
| - }
|
| -}
|
| -
|
| -abstract class ExpressionVisitor<E> {
|
| - E visitExpression(Expression node) => node.accept(this);
|
| - E visitVariableUse(VariableUse node);
|
| - E visitAssign(Assign node);
|
| - E visitInvokeStatic(InvokeStatic node);
|
| - E visitInvokeMethod(InvokeMethod node);
|
| - E visitInvokeMethodDirectly(InvokeMethodDirectly node);
|
| - E visitInvokeConstructor(InvokeConstructor node);
|
| - E visitOneShotInterceptor(OneShotInterceptor node);
|
| - E visitConstant(Constant node);
|
| - E visitThis(This node);
|
| - E visitConditional(Conditional node);
|
| - E visitLogicalOperator(LogicalOperator node);
|
| - E visitNot(Not node);
|
| - E visitLiteralList(LiteralList node);
|
| - E visitTypeOperator(TypeOperator node);
|
| - E visitGetField(GetField node);
|
| - E visitSetField(SetField node);
|
| - E visitGetStatic(GetStatic node);
|
| - E visitSetStatic(SetStatic node);
|
| - E visitGetTypeTestProperty(GetTypeTestProperty node);
|
| - E visitCreateBox(CreateBox node);
|
| - E visitCreateInstance(CreateInstance node);
|
| - E visitReifyRuntimeType(ReifyRuntimeType node);
|
| - E visitReadTypeVariable(ReadTypeVariable node);
|
| - E visitTypeExpression(TypeExpression node);
|
| - E visitCreateInvocationMirror(CreateInvocationMirror node);
|
| - E visitInterceptor(Interceptor node);
|
| - E visitApplyBuiltinOperator(ApplyBuiltinOperator node);
|
| - E visitApplyBuiltinMethod(ApplyBuiltinMethod node);
|
| - E visitForeignExpression(ForeignExpression node);
|
| - E visitGetLength(GetLength node);
|
| - E visitGetIndex(GetIndex node);
|
| - E visitSetIndex(SetIndex node);
|
| - E visitAwait(Await node);
|
| -}
|
| -
|
| -abstract class ExpressionVisitor1<E, A> {
|
| - E visitExpression(Expression node, A arg) => node.accept1(this, arg);
|
| - E visitVariableUse(VariableUse node, A arg);
|
| - E visitAssign(Assign node, A arg);
|
| - E visitInvokeStatic(InvokeStatic node, A arg);
|
| - E visitInvokeMethod(InvokeMethod node, A arg);
|
| - E visitInvokeMethodDirectly(InvokeMethodDirectly node, A arg);
|
| - E visitInvokeConstructor(InvokeConstructor node, A arg);
|
| - E visitOneShotInterceptor(OneShotInterceptor node, A arg);
|
| - E visitConstant(Constant node, A arg);
|
| - E visitThis(This node, A arg);
|
| - E visitConditional(Conditional node, A arg);
|
| - E visitLogicalOperator(LogicalOperator node, A arg);
|
| - E visitNot(Not node, A arg);
|
| - E visitLiteralList(LiteralList node, A arg);
|
| - E visitTypeOperator(TypeOperator node, A arg);
|
| - E visitGetField(GetField node, A arg);
|
| - E visitSetField(SetField node, A arg);
|
| - E visitGetStatic(GetStatic node, A arg);
|
| - E visitSetStatic(SetStatic node, A arg);
|
| - E visitGetTypeTestProperty(GetTypeTestProperty node, A arg);
|
| - E visitCreateBox(CreateBox node, A arg);
|
| - E visitCreateInstance(CreateInstance node, A arg);
|
| - E visitReifyRuntimeType(ReifyRuntimeType node, A arg);
|
| - E visitReadTypeVariable(ReadTypeVariable node, A arg);
|
| - E visitTypeExpression(TypeExpression node, A arg);
|
| - E visitCreateInvocationMirror(CreateInvocationMirror node, A arg);
|
| - E visitInterceptor(Interceptor node, A arg);
|
| - E visitApplyBuiltinOperator(ApplyBuiltinOperator node, A arg);
|
| - E visitApplyBuiltinMethod(ApplyBuiltinMethod node, A arg);
|
| - E visitForeignExpression(ForeignExpression node, A arg);
|
| - E visitGetLength(GetLength node, A arg);
|
| - E visitGetIndex(GetIndex node, A arg);
|
| - E visitSetIndex(SetIndex node, A arg);
|
| - E visitAwait(Await node, A arg);
|
| -}
|
| -
|
| -abstract class StatementVisitor<S> {
|
| - S visitStatement(Statement node) => node.accept(this);
|
| - S visitLabeledStatement(LabeledStatement node);
|
| - S visitReturn(Return node);
|
| - S visitThrow(Throw node);
|
| - S visitBreak(Break node);
|
| - S visitContinue(Continue node);
|
| - S visitIf(If node);
|
| - S visitWhileTrue(WhileTrue node);
|
| - S visitFor(For node);
|
| - S visitExpressionStatement(ExpressionStatement node);
|
| - S visitTry(Try node);
|
| - S visitUnreachable(Unreachable node);
|
| - S visitForeignStatement(ForeignStatement node);
|
| - S visitYield(Yield node);
|
| - S visitReceiverCheck(ReceiverCheck node);
|
| -}
|
| -
|
| -abstract class StatementVisitor1<S, A> {
|
| - S visitStatement(Statement node, A arg) => node.accept1(this, arg);
|
| - S visitLabeledStatement(LabeledStatement node, A arg);
|
| - S visitReturn(Return node, A arg);
|
| - S visitThrow(Throw node, A arg);
|
| - S visitBreak(Break node, A arg);
|
| - S visitContinue(Continue node, A arg);
|
| - S visitIf(If node, A arg);
|
| - S visitWhileTrue(WhileTrue node, A arg);
|
| - S visitFor(For node, A arg);
|
| - S visitExpressionStatement(ExpressionStatement node, A arg);
|
| - S visitTry(Try node, A arg);
|
| - S visitUnreachable(Unreachable node, A arg);
|
| - S visitForeignStatement(ForeignStatement node, A arg);
|
| - S visitYield(Yield node, A arg);
|
| - S visitReceiverCheck(ReceiverCheck node, A arg);
|
| -}
|
| -
|
| -abstract class RecursiveVisitor implements StatementVisitor, ExpressionVisitor {
|
| - visitExpression(Expression e) => e.accept(this);
|
| - visitStatement(Statement s) => s.accept(this);
|
| -
|
| - visitVariable(Variable variable) {}
|
| -
|
| - visitVariableUse(VariableUse node) {
|
| - visitVariable(node.variable);
|
| - }
|
| -
|
| - visitAssign(Assign node) {
|
| - visitVariable(node.variable);
|
| - visitExpression(node.value);
|
| - }
|
| -
|
| - visitInvokeStatic(InvokeStatic node) {
|
| - node.arguments.forEach(visitExpression);
|
| - }
|
| -
|
| - visitInvokeMethod(InvokeMethod node) {
|
| - visitExpression(node.receiver);
|
| - node.arguments.forEach(visitExpression);
|
| - }
|
| -
|
| - visitInvokeMethodDirectly(InvokeMethodDirectly node) {
|
| - visitExpression(node.receiver);
|
| - node.arguments.forEach(visitExpression);
|
| - }
|
| -
|
| - visitInvokeConstructor(InvokeConstructor node) {
|
| - node.arguments.forEach(visitExpression);
|
| - }
|
| -
|
| - visitOneShotInterceptor(OneShotInterceptor node) {
|
| - node.arguments.forEach(visitExpression);
|
| - }
|
| -
|
| - visitConstant(Constant node) {}
|
| -
|
| - visitThis(This 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);
|
| - }
|
| -
|
| - visitTypeOperator(TypeOperator node) {
|
| - visitExpression(node.value);
|
| - node.typeArguments.forEach(visitExpression);
|
| - }
|
| -
|
| - visitLabeledStatement(LabeledStatement node) {
|
| - visitStatement(node.body);
|
| - visitStatement(node.next);
|
| - }
|
| -
|
| - visitReturn(Return node) {
|
| - visitExpression(node.value);
|
| - }
|
| -
|
| - visitThrow(Throw 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);
|
| - }
|
| -
|
| - visitFor(For node) {
|
| - visitExpression(node.condition);
|
| - node.updates.forEach(visitExpression);
|
| - visitStatement(node.body);
|
| - visitStatement(node.next);
|
| - }
|
| -
|
| - visitExpressionStatement(ExpressionStatement inputNode) {
|
| - // Iterate over chains of expression statements to avoid deep recursion.
|
| - Statement node = inputNode;
|
| - while (node is ExpressionStatement) {
|
| - ExpressionStatement stmt = node;
|
| - visitExpression(stmt.expression);
|
| - node = stmt.next;
|
| - }
|
| - visitStatement(node);
|
| - }
|
| -
|
| - visitTry(Try node) {
|
| - visitStatement(node.tryBody);
|
| - visitStatement(node.catchBody);
|
| - }
|
| -
|
| - visitGetField(GetField node) {
|
| - visitExpression(node.object);
|
| - }
|
| -
|
| - visitSetField(SetField node) {
|
| - visitExpression(node.object);
|
| - visitExpression(node.value);
|
| - }
|
| -
|
| - visitGetStatic(GetStatic node) {}
|
| -
|
| - visitSetStatic(SetStatic node) {
|
| - visitExpression(node.value);
|
| - }
|
| -
|
| - visitGetTypeTestProperty(GetTypeTestProperty node) {
|
| - visitExpression(node.object);
|
| - }
|
| -
|
| - visitCreateBox(CreateBox node) {}
|
| -
|
| - visitCreateInstance(CreateInstance node) {
|
| - node.arguments.forEach(visitExpression);
|
| - if (node.typeInformation != null) visitExpression(node.typeInformation);
|
| - }
|
| -
|
| - visitReifyRuntimeType(ReifyRuntimeType node) {
|
| - visitExpression(node.value);
|
| - }
|
| -
|
| - visitReadTypeVariable(ReadTypeVariable node) {
|
| - visitExpression(node.target);
|
| - }
|
| -
|
| - visitTypeExpression(TypeExpression node) {
|
| - node.arguments.forEach(visitExpression);
|
| - }
|
| -
|
| - visitCreateInvocationMirror(CreateInvocationMirror node) {
|
| - node.arguments.forEach(visitExpression);
|
| - }
|
| -
|
| - visitUnreachable(Unreachable node) {}
|
| -
|
| - visitApplyBuiltinOperator(ApplyBuiltinOperator node) {
|
| - node.arguments.forEach(visitExpression);
|
| - }
|
| -
|
| - visitApplyBuiltinMethod(ApplyBuiltinMethod node) {
|
| - visitExpression(node.receiver);
|
| - node.arguments.forEach(visitExpression);
|
| - }
|
| -
|
| - visitInterceptor(Interceptor node) {
|
| - visitExpression(node.input);
|
| - }
|
| -
|
| - visitForeignCode(ForeignCode node) {
|
| - node.arguments.forEach(visitExpression);
|
| - }
|
| -
|
| - visitForeignExpression(ForeignExpression node) => visitForeignCode(node);
|
| - visitForeignStatement(ForeignStatement node) => visitForeignCode(node);
|
| -
|
| - visitGetLength(GetLength node) {
|
| - visitExpression(node.object);
|
| - }
|
| -
|
| - visitGetIndex(GetIndex node) {
|
| - visitExpression(node.object);
|
| - visitExpression(node.index);
|
| - }
|
| -
|
| - visitSetIndex(SetIndex node) {
|
| - visitExpression(node.object);
|
| - visitExpression(node.index);
|
| - visitExpression(node.value);
|
| - }
|
| -
|
| - visitAwait(Await node) {
|
| - visitExpression(node.input);
|
| - }
|
| -
|
| - visitYield(Yield node) {
|
| - visitExpression(node.input);
|
| - visitStatement(node.next);
|
| - }
|
| -
|
| - visitReceiverCheck(ReceiverCheck node) {
|
| - if (node.condition != null) visitExpression(node.condition);
|
| - visitExpression(node.value);
|
| - visitStatement(node.next);
|
| - }
|
| -}
|
| -
|
| -abstract class Transformer
|
| - implements ExpressionVisitor<Expression>, StatementVisitor<Statement> {
|
| - Expression visitExpression(Expression e) => e.accept(this);
|
| - Statement visitStatement(Statement s) => s.accept(this);
|
| -}
|
| -
|
| -class RecursiveTransformer extends Transformer {
|
| - void _replaceExpressions(List<Expression> list) {
|
| - for (int i = 0; i < list.length; i++) {
|
| - list[i] = visitExpression(list[i]);
|
| - }
|
| - }
|
| -
|
| - visitVariableUse(VariableUse node) => node;
|
| -
|
| - visitAssign(Assign node) {
|
| - node.value = visitExpression(node.value);
|
| - return node;
|
| - }
|
| -
|
| - visitInvokeStatic(InvokeStatic node) {
|
| - _replaceExpressions(node.arguments);
|
| - return node;
|
| - }
|
| -
|
| - visitInvokeMethod(InvokeMethod node) {
|
| - node.receiver = visitExpression(node.receiver);
|
| - _replaceExpressions(node.arguments);
|
| - return node;
|
| - }
|
| -
|
| - visitInvokeMethodDirectly(InvokeMethodDirectly node) {
|
| - node.receiver = visitExpression(node.receiver);
|
| - _replaceExpressions(node.arguments);
|
| - return node;
|
| - }
|
| -
|
| - visitInvokeConstructor(InvokeConstructor node) {
|
| - _replaceExpressions(node.arguments);
|
| - return node;
|
| - }
|
| -
|
| - visitOneShotInterceptor(OneShotInterceptor node) {
|
| - _replaceExpressions(node.arguments);
|
| - return node;
|
| - }
|
| -
|
| - visitConstant(Constant node) => node;
|
| -
|
| - visitThis(This node) => node;
|
| -
|
| - visitConditional(Conditional node) {
|
| - node.condition = visitExpression(node.condition);
|
| - node.thenExpression = visitExpression(node.thenExpression);
|
| - node.elseExpression = visitExpression(node.elseExpression);
|
| - return node;
|
| - }
|
| -
|
| - visitLogicalOperator(LogicalOperator node) {
|
| - node.left = visitExpression(node.left);
|
| - node.right = visitExpression(node.right);
|
| - return node;
|
| - }
|
| -
|
| - visitNot(Not node) {
|
| - node.operand = visitExpression(node.operand);
|
| - return node;
|
| - }
|
| -
|
| - visitLiteralList(LiteralList node) {
|
| - _replaceExpressions(node.values);
|
| - return node;
|
| - }
|
| -
|
| - visitTypeOperator(TypeOperator node) {
|
| - node.value = visitExpression(node.value);
|
| - _replaceExpressions(node.typeArguments);
|
| - return node;
|
| - }
|
| -
|
| - visitLabeledStatement(LabeledStatement node) {
|
| - node.body = visitStatement(node.body);
|
| - node.next = visitStatement(node.next);
|
| - return node;
|
| - }
|
| -
|
| - visitReturn(Return node) {
|
| - node.value = visitExpression(node.value);
|
| - return node;
|
| - }
|
| -
|
| - visitThrow(Throw node) {
|
| - node.value = visitExpression(node.value);
|
| - return node;
|
| - }
|
| -
|
| - visitBreak(Break node) => node;
|
| -
|
| - visitContinue(Continue node) => node;
|
| -
|
| - visitIf(If node) {
|
| - node.condition = visitExpression(node.condition);
|
| - node.thenStatement = visitStatement(node.thenStatement);
|
| - node.elseStatement = visitStatement(node.elseStatement);
|
| - return node;
|
| - }
|
| -
|
| - visitWhileTrue(WhileTrue node) {
|
| - node.body = visitStatement(node.body);
|
| - return node;
|
| - }
|
| -
|
| - visitFor(For node) {
|
| - node.condition = visitExpression(node.condition);
|
| - _replaceExpressions(node.updates);
|
| - node.body = visitStatement(node.body);
|
| - node.next = visitStatement(node.next);
|
| - return node;
|
| - }
|
| -
|
| - visitExpressionStatement(ExpressionStatement node) {
|
| - // Iterate over chains of expression statements to avoid deep recursion.
|
| - Statement first = node;
|
| - while (true) {
|
| - node.expression = visitExpression(node.expression);
|
| - if (node.next is ExpressionStatement) {
|
| - node = node.next;
|
| - } else {
|
| - break;
|
| - }
|
| - }
|
| - node.next = visitStatement(node.next);
|
| - return first;
|
| - }
|
| -
|
| - visitTry(Try node) {
|
| - node.tryBody = visitStatement(node.tryBody);
|
| - node.catchBody = visitStatement(node.catchBody);
|
| - return node;
|
| - }
|
| -
|
| - visitGetField(GetField node) {
|
| - node.object = visitExpression(node.object);
|
| - return node;
|
| - }
|
| -
|
| - visitSetField(SetField node) {
|
| - node.object = visitExpression(node.object);
|
| - node.value = visitExpression(node.value);
|
| - return node;
|
| - }
|
| -
|
| - visitGetStatic(GetStatic node) => node;
|
| -
|
| - visitSetStatic(SetStatic node) {
|
| - node.value = visitExpression(node.value);
|
| - return node;
|
| - }
|
| -
|
| - visitGetTypeTestProperty(GetTypeTestProperty node) {
|
| - node.object = visitExpression(node.object);
|
| - return node;
|
| - }
|
| -
|
| - visitCreateBox(CreateBox node) => node;
|
| -
|
| - visitCreateInstance(CreateInstance node) {
|
| - _replaceExpressions(node.arguments);
|
| - if (node.typeInformation != null) {
|
| - node.typeInformation = visitExpression(node.typeInformation);
|
| - }
|
| - return node;
|
| - }
|
| -
|
| - visitReifyRuntimeType(ReifyRuntimeType node) {
|
| - node.value = visitExpression(node.value);
|
| - return node;
|
| - }
|
| -
|
| - visitReadTypeVariable(ReadTypeVariable node) {
|
| - node.target = visitExpression(node.target);
|
| - return node;
|
| - }
|
| -
|
| - visitTypeExpression(TypeExpression node) {
|
| - _replaceExpressions(node.arguments);
|
| - return node;
|
| - }
|
| -
|
| - visitCreateInvocationMirror(CreateInvocationMirror node) {
|
| - _replaceExpressions(node.arguments);
|
| - return node;
|
| - }
|
| -
|
| - visitForeignExpression(ForeignExpression node) {
|
| - _replaceExpressions(node.arguments);
|
| - return node;
|
| - }
|
| -
|
| - visitForeignStatement(ForeignStatement node) {
|
| - _replaceExpressions(node.arguments);
|
| - return node;
|
| - }
|
| -
|
| - visitUnreachable(Unreachable node) {
|
| - return node;
|
| - }
|
| -
|
| - visitApplyBuiltinOperator(ApplyBuiltinOperator node) {
|
| - _replaceExpressions(node.arguments);
|
| - return node;
|
| - }
|
| -
|
| - visitApplyBuiltinMethod(ApplyBuiltinMethod node) {
|
| - node.receiver = visitExpression(node.receiver);
|
| - _replaceExpressions(node.arguments);
|
| - return node;
|
| - }
|
| -
|
| - visitInterceptor(Interceptor node) {
|
| - node.input = visitExpression(node.input);
|
| - return node;
|
| - }
|
| -
|
| - visitGetLength(GetLength node) {
|
| - node.object = visitExpression(node.object);
|
| - return node;
|
| - }
|
| -
|
| - visitGetIndex(GetIndex node) {
|
| - node.object = visitExpression(node.object);
|
| - node.index = visitExpression(node.index);
|
| - return node;
|
| - }
|
| -
|
| - visitSetIndex(SetIndex node) {
|
| - node.object = visitExpression(node.object);
|
| - node.index = visitExpression(node.index);
|
| - node.value = visitExpression(node.value);
|
| - return node;
|
| - }
|
| -
|
| - visitAwait(Await node) {
|
| - node.input = visitExpression(node.input);
|
| - return node;
|
| - }
|
| -
|
| - visitYield(Yield node) {
|
| - node.input = visitExpression(node.input);
|
| - node.next = visitStatement(node.next);
|
| - return node;
|
| - }
|
| -
|
| - visitReceiverCheck(ReceiverCheck node) {
|
| - if (node.condition != null) {
|
| - node.condition = visitExpression(node.condition);
|
| - }
|
| - node.value = visitExpression(node.value);
|
| - node.next = visitStatement(node.next);
|
| - return node;
|
| - }
|
| -}
|
| -
|
| -class FallthroughTarget {
|
| - final Statement target;
|
| - int useCount = 0;
|
| -
|
| - FallthroughTarget(this.target);
|
| -}
|
| -
|
| -/// A stack machine for tracking fallthrough while traversing the Tree IR.
|
| -class FallthroughStack {
|
| - final List<FallthroughTarget> _stack = <FallthroughTarget>[
|
| - new FallthroughTarget(null)
|
| - ];
|
| -
|
| - /// Set a new fallthrough target.
|
| - void push(Statement newFallthrough) {
|
| - _stack.add(new FallthroughTarget(newFallthrough));
|
| - }
|
| -
|
| - /// Remove the current fallthrough target.
|
| - void pop() {
|
| - _stack.removeLast();
|
| - }
|
| -
|
| - /// The current fallthrough target, or `null` if control will fall over
|
| - /// the end of the method.
|
| - Statement get target => _stack.last.target;
|
| -
|
| - /// Number of uses of the current fallthrough target.
|
| - int get useCount => _stack.last.useCount;
|
| -
|
| - /// Indicate that a statement will fall through to the current fallthrough
|
| - /// target.
|
| - void use() {
|
| - ++_stack.last.useCount;
|
| - }
|
| -}
|
|
|