| 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 175abfcfb33d6c9e39756594cb2f081a3456a59a..d052121e9ce2ce1aec11e740784e965075c61085 100644
|
| --- a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
|
| +++ b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
|
| @@ -1,18 +1,11 @@
|
| // Copyright (c) 2013, 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.
|
| -
|
| -// IrNodes are kept in a separate library to have precise control over their
|
| -// dependencies on other parts of the system.
|
| library dart2js.ir_nodes;
|
|
|
| import '../constants/expressions.dart';
|
| import '../constants/values.dart' as values show ConstantValue;
|
| -import '../dart_types.dart' show DartType, GenericType, TypeVariableType;
|
| -import '../dart2jslib.dart' as dart2js show
|
| - CURRENT_ELEMENT_SPANNABLE,
|
| - InternalErrorFunction,
|
| - invariant;
|
| +import '../dart_types.dart' show DartType, InterfaceType, TypeVariableType;
|
| import '../elements/elements.dart';
|
| import '../io/source_information.dart' show SourceInformation;
|
| import '../universe/universe.dart' show Selector, SelectorKind;
|
| @@ -24,6 +17,16 @@ abstract class Node {
|
| accept(Visitor visitor);
|
| }
|
|
|
| +/// Expressions can be evaluated, and may diverge, throw, and/or have
|
| +/// side-effects.
|
| +///
|
| +/// Evaluation continues by stepping into a sub-expression, invoking a
|
| +/// continuation, or throwing an exception.
|
| +///
|
| +/// Expressions do not a return value. Expressions that produce values should
|
| +/// invoke a [Continuation] with the result as argument. Alternatively, values
|
| +/// that can be obtained without side-effects, divergence, or throwing
|
| +/// exceptions can be built using a [LetPrim].
|
| abstract class Expression extends Node {
|
| Expression plug(Expression expr) => throw 'impossible';
|
| }
|
| @@ -59,9 +62,11 @@ abstract class Definition<T extends Definition<T>> extends Node {
|
| /// An expression that cannot throw or diverge and has no side-effects.
|
| /// All primitives are named using the identity of the [Primitive] object.
|
| ///
|
| -/// Primitives may allocate objects, this is not considered side-effect here.
|
| +/// Primitives may allocate objects; this is not considered side-effect here.
|
| ///
|
| /// Although primitives may not mutate state, they may depend on state.
|
| +///
|
| +/// All primitives except [Parameter] must be bound by a [LetPrim].
|
| abstract class Primitive extends Definition<Primitive> {
|
| /// The [VariableElement] or [ParameterElement] from which the primitive
|
| /// binding originated.
|
| @@ -105,10 +110,12 @@ 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 the one-hole context 'let val x = V in []'.
|
| +/// Evaluates a primitive and binds it to variable: `let val x = V in E`.
|
| +///
|
| +/// The bound value is in scope in the body.
|
| +///
|
| +/// During one-pass construction a LetPrim with an empty body is used to
|
| +/// represent the one-hole context `let val x = V in []`.
|
| class LetPrim extends Expression implements InteriorNode {
|
| final Primitive primitive;
|
| Expression body;
|
| @@ -133,9 +140,10 @@ 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-hole context
|
| -/// 'let cont ... k(v) = [] ... in E'.
|
| +/// `let cont ... k(v) = [] ... in E`.
|
| class LetCont extends Expression implements InteriorNode {
|
| List<Continuation> continuations;
|
| Expression body;
|
| @@ -215,18 +223,17 @@ abstract class InteriorNode extends Node {
|
| void set body(Expression body);
|
| }
|
|
|
| -/// Invoke a static function or static getter/setter.
|
| +/// Invoke a static function.
|
| +///
|
| +/// All optional arguments declared by [target] are passed in explicitly, and
|
| +/// occur at the end of [arguments] list, in normalized order.
|
| +///
|
| +/// Discussion:
|
| +/// All information in the [selector] is technically redundant; it will likely
|
| +/// be removed.
|
| class InvokeStatic extends Expression implements Invoke {
|
| - /// [FunctionElement] or [FieldElement].
|
| - final Entity target;
|
| -
|
| - /**
|
| - * The selector encodes how the function is invoked: number of positional
|
| - * arguments, names used in named arguments. This information is required
|
| - * to build the [StaticCallSiteTypeInformation] for the inference graph.
|
| - */
|
| + final FunctionElement target;
|
| final Selector selector;
|
| -
|
| final List<Reference<Primitive>> arguments;
|
| final Reference<Continuation> continuation;
|
| final SourceInformation sourceInformation;
|
| @@ -237,81 +244,39 @@ class InvokeStatic extends Expression implements Invoke {
|
| Continuation cont,
|
| this.sourceInformation)
|
| : arguments = _referenceList(args),
|
| - continuation = new Reference<Continuation>(cont) {
|
| - assert(target is ErroneousElement || selector.name == target.name);
|
| - }
|
| + continuation = new Reference<Continuation>(cont);
|
|
|
| accept(Visitor visitor) => visitor.visitInvokeStatic(this);
|
| }
|
|
|
| -/// A [CallingConvention] codifies how arguments are matched to parameters when
|
| -/// emitting code for a function call.
|
| -class CallingConvention {
|
| - final String name;
|
| - const CallingConvention(this.name);
|
| - /// The normal way of calling a Dart function: Positional arguments are
|
| - /// matched with (mandatory and optional) positionals parameters from left to
|
| - /// right and named arguments are matched by name.
|
| - static const CallingConvention DART = const CallingConvention("Dart call");
|
| - /// Intercepted calls have an additional first argument that is the actual
|
| - /// receiver of the call. See the documentation of [Interceptor] for more
|
| - /// information.
|
| - static const CallingConvention JS_INTERCEPTED =
|
| - const CallingConvention("intercepted JavaScript call");
|
| -}
|
| -
|
| -/// Invoke a method, operator, getter, setter, or index getter/setter.
|
| -/// Converting a method to a function object is treated as a getter invocation.
|
| +/// Invoke a method on an object.
|
| +///
|
| +/// This includes getters, setters, operators, and index getter/setters.
|
| +///
|
| +/// Tearing off a method is treated like a getter invocation (getters and
|
| +/// tear-offs cannot be distinguished at compile-time).
|
| +///
|
| +/// The [selector] records the names of named arguments. The value of named
|
| +/// arguments occur at the end of the [arguments] list, in normalized order.
|
| +///
|
| +/// Discussion:
|
| +/// If the [selector] is a [TypedSelector], the type information contained
|
| +/// there is used by optimization passes. This is likely to change.
|
| class InvokeMethod extends Expression implements Invoke {
|
| Reference<Primitive> receiver;
|
| Selector selector;
|
| - CallingConvention callingConvention;
|
| final List<Reference<Primitive>> arguments;
|
| final Reference<Continuation> continuation;
|
| final SourceInformation sourceInformation;
|
|
|
| InvokeMethod(Primitive receiver,
|
| - Selector selector,
|
| + this.selector,
|
| List<Primitive> arguments,
|
| Continuation continuation,
|
| - {SourceInformation sourceInformation})
|
| - : this.internal(new Reference<Primitive>(receiver),
|
| - selector,
|
| - _referenceList(arguments),
|
| - new Reference<Continuation>(continuation),
|
| - sourceInformation);
|
| -
|
| - InvokeMethod.internal(this.receiver,
|
| - this.selector,
|
| - this.arguments,
|
| - this.continuation,
|
| - this.sourceInformation,
|
| - [this.callingConvention = CallingConvention.DART]) {
|
| - assert(isValid);
|
| - }
|
| -
|
| - /// Returns whether the arguments match the selector under the given calling
|
| - /// convention.
|
| - ///
|
| - /// This check is designed to be used in an assert, as it also checks that the
|
| - /// selector, arguments, and calling convention have meaningful values.
|
| - bool get isValid {
|
| - if (selector == null || callingConvention == null) return false;
|
| - if (callingConvention != CallingConvention.DART &&
|
| - callingConvention != CallingConvention.JS_INTERCEPTED) {
|
| - return false;
|
| - }
|
| - int numberOfArguments =
|
| - callingConvention == CallingConvention.JS_INTERCEPTED
|
| - ? arguments.length - 1
|
| - : arguments.length;
|
| - return selector.kind == SelectorKind.CALL ||
|
| - selector.kind == SelectorKind.OPERATOR ||
|
| - (selector.kind == SelectorKind.GETTER && numberOfArguments == 0) ||
|
| - (selector.kind == SelectorKind.SETTER && numberOfArguments == 1) ||
|
| - (selector.kind == SelectorKind.INDEX && numberOfArguments == 1) ||
|
| - (selector.kind == SelectorKind.INDEX && numberOfArguments == 2);
|
| - }
|
| + {this.sourceInformation})
|
| + : this.receiver = new Reference<Primitive>(receiver),
|
| + this.arguments = _referenceList(arguments),
|
| + this.continuation = new Reference<Continuation>(continuation);
|
|
|
| accept(Visitor visitor) => visitor.visitInvokeMethod(this);
|
| }
|
| @@ -333,12 +298,11 @@ class InvokeMethod extends Expression implements Invoke {
|
| /// TODO(sra): Review. A direct call to a method that is mixed into a native
|
| /// class will still require an explicit argument.
|
| ///
|
| -/// When targeting Dart, this instruction is used to represent super calls.
|
| -/// Here, [receiver] must always be a reference to `this`, and [target] must be
|
| -/// a method that is available in the super class.
|
| +/// All optional arguments declared by [target] are passed in explicitly, and
|
| +/// occur at the end of [arguments] list, in normalized order.
|
| class InvokeMethodDirectly extends Expression implements Invoke {
|
| Reference<Primitive> receiver;
|
| - final Element target;
|
| + final FunctionElement target;
|
| final Selector selector;
|
| final List<Reference<Primitive>> arguments;
|
| final Reference<Continuation> continuation;
|
| @@ -346,66 +310,56 @@ class InvokeMethodDirectly extends Expression implements Invoke {
|
| InvokeMethodDirectly(Primitive receiver,
|
| this.target,
|
| this.selector,
|
| - List<Primitive> args,
|
| - Continuation cont)
|
| + List<Primitive> arguments,
|
| + Continuation continuation)
|
| : this.receiver = new Reference<Primitive>(receiver),
|
| - arguments = _referenceList(args),
|
| - continuation = new Reference<Continuation>(cont) {
|
| - assert(selector != null);
|
| - assert(selector.kind == SelectorKind.CALL ||
|
| - selector.kind == SelectorKind.OPERATOR ||
|
| - (selector.kind == SelectorKind.GETTER && arguments.isEmpty) ||
|
| - (selector.kind == SelectorKind.SETTER && arguments.length == 1) ||
|
| - (selector.kind == SelectorKind.INDEX && arguments.length == 1) ||
|
| - (selector.kind == SelectorKind.INDEX && arguments.length == 2));
|
| - }
|
| + this.arguments = _referenceList(arguments),
|
| + this.continuation = new Reference<Continuation>(continuation);
|
|
|
| accept(Visitor visitor) => visitor.visitInvokeMethodDirectly(this);
|
| }
|
|
|
| -/// Non-const call to a constructor. The [target] may be a generative
|
| -/// constructor, factory, or redirecting factory.
|
| +/// Non-const call to a constructor.
|
| +///
|
| +/// The [target] may be a generative constructor (forwarding or normal)
|
| +/// or a non-redirecting factory.
|
| +///
|
| +/// All optional arguments declared by [target] are passed in explicitly, and
|
| +/// occur in the [arguments] list, in normalized order.
|
| +///
|
| +/// Last in the [arguments] list, after the mandatory and optional arguments,
|
| +/// the internal representation of each type argument occurs, unless it could
|
| +/// be determined at build-time that the constructed class has no need for its
|
| +/// runtime type information.
|
| +///
|
| +/// Note that [InvokeConstructor] does it itself allocate an object.
|
| +/// The invoked constructor will do that using [CreateInstance].
|
| class InvokeConstructor extends Expression implements Invoke {
|
| final DartType type;
|
| - final FunctionElement target;
|
| + final ConstructorElement target;
|
| final List<Reference<Primitive>> arguments;
|
| final Reference<Continuation> continuation;
|
| final Selector selector;
|
|
|
| - /// The class being instantiated. This is the same as `target.enclosingClass`
|
| - /// and `type.element`.
|
| - ClassElement get targetClass => target.enclosingElement;
|
| -
|
| - /// True if this is an invocation of a factory constructor.
|
| - bool get isFactory => target.isFactoryConstructor;
|
| -
|
| InvokeConstructor(this.type,
|
| this.target,
|
| this.selector,
|
| List<Primitive> args,
|
| Continuation cont)
|
| : arguments = _referenceList(args),
|
| - continuation = new Reference<Continuation>(cont) {
|
| - assert(dart2js.invariant(target,
|
| - target.isErroneous ||
|
| - type.isDynamic ||
|
| - type.element == target.enclosingClass.declaration,
|
| - message: "Constructor invocation target is not a constructor: "
|
| - "$target."));
|
| - }
|
| + continuation = new Reference<Continuation>(cont);
|
|
|
| accept(Visitor visitor) => visitor.visitInvokeConstructor(this);
|
| }
|
|
|
| -/// "as" casts and "is" checks.
|
| -// We might want to turn "is"-checks into a [Primitive] as it can never diverge.
|
| -// But then we need to special-case for is-checks with an erroneous .type as
|
| -// these will throw.
|
| +// TODO(asgerf): Make a Primitive for "is" and an Expression for "as".
|
| +
|
| +/// An "as" cast or an "is" check.
|
| class TypeOperator extends Expression {
|
| Reference<Primitive> value;
|
| final DartType type;
|
|
|
| - /// If [type] is a [GenericType], this holds the internal representation of
|
| + /// If [type] is an [InterfaceType], this holds the internal representation of
|
| /// the type arguments to [type]. Since these may reference type variables
|
| /// from the enclosing class, they are not constant.
|
| ///
|
| @@ -415,7 +369,6 @@ class TypeOperator extends Expression {
|
| /// Otherwise the list is empty.
|
| final List<Reference<Primitive>> typeArguments;
|
| final Reference<Continuation> continuation;
|
| - // TODO(johnniwinther): Use `Operator` class to encapsule the operator type.
|
| final bool isTypeTest;
|
|
|
| TypeOperator(Primitive value,
|
| @@ -520,30 +473,6 @@ class SetMutableVariable extends Expression implements InteriorNode {
|
| }
|
| }
|
|
|
| -/// 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, DartSpecificNode {
|
| - final MutableVariable variable;
|
| - final FunctionDefinition definition;
|
| - Expression body;
|
| -
|
| - DeclareFunction(this.variable, this.definition);
|
| -
|
| - Expression plug(Expression expr) {
|
| - assert(body == null);
|
| - return body = expr;
|
| - }
|
| -
|
| - accept(Visitor visitor) => visitor.visitDeclareFunction(this);
|
| -}
|
| -
|
| /// Invoke a continuation in tail position.
|
| class InvokeContinuation extends Expression {
|
| Reference<Continuation> continuation;
|
| @@ -586,6 +515,8 @@ class IsTrue extends Condition {
|
| }
|
|
|
| /// Choose between a pair of continuations based on a condition value.
|
| +///
|
| +/// The two continuations must not declare any parameters.
|
| class Branch extends Expression {
|
| final Condition condition;
|
| final Reference<Continuation> trueContinuation;
|
| @@ -598,19 +529,10 @@ class Branch extends Expression {
|
| accept(Visitor visitor) => visitor.visitBranch(this);
|
| }
|
|
|
| -/// Marker interface for nodes that are only handled in the JavaScript backend.
|
| -///
|
| -/// These nodes are generated by the unsugar step or the [JsIrBuilder] and need
|
| -/// special translation to the Tree IR, which is implemented in JsTreeBuilder.
|
| -abstract class JsSpecificNode implements Node {}
|
| -
|
| -/// Marker interface for nodes that are only handled inthe Dart backend.
|
| -abstract class DartSpecificNode implements Node {}
|
| -
|
| /// Directly assigns to a field on a given object.
|
| -class SetField extends Expression implements InteriorNode, JsSpecificNode {
|
| +class SetField extends Expression implements InteriorNode {
|
| final Reference<Primitive> object;
|
| - Element field;
|
| + FieldElement field;
|
| final Reference<Primitive> value;
|
| Expression body;
|
|
|
| @@ -627,9 +549,9 @@ class SetField extends Expression implements InteriorNode, JsSpecificNode {
|
| }
|
|
|
| /// Directly reads from a field on a given object.
|
| -class GetField extends Primitive implements JsSpecificNode {
|
| +class GetField extends Primitive {
|
| final Reference<Primitive> object;
|
| - Element field;
|
| + FieldElement field;
|
|
|
| GetField(Primitive object, this.field)
|
| : this.object = new Reference<Primitive>(object);
|
| @@ -639,6 +561,7 @@ class GetField extends Primitive implements JsSpecificNode {
|
|
|
| /// Reads the value of a static field or tears off a static method.
|
| class GetStatic extends Primitive {
|
| + /// Can be [FieldElement] or [FunctionElement].
|
| final Element element;
|
| final SourceInformation sourceInformation;
|
|
|
| @@ -649,7 +572,7 @@ class GetStatic extends Primitive {
|
|
|
| /// Sets the value of a static field.
|
| class SetStatic extends Expression implements InteriorNode {
|
| - final Element element;
|
| + final FieldElement element;
|
| final Reference<Primitive> value;
|
| Expression body;
|
| final SourceInformation sourceInformation;
|
| @@ -677,21 +600,21 @@ class GetLazyStatic extends Expression {
|
| final SourceInformation sourceInformation;
|
|
|
| GetLazyStatic(this.element,
|
| - Continuation cont,
|
| + Continuation continuation,
|
| this.sourceInformation)
|
| - : continuation = new Reference<Continuation>(cont);
|
| + : continuation = new Reference<Continuation>(continuation);
|
|
|
| accept(Visitor visitor) => visitor.visitGetLazyStatic(this);
|
| }
|
|
|
| /// Creates an object for holding boxed variables captured by a closure.
|
| -class CreateBox extends Primitive implements JsSpecificNode {
|
| +class CreateBox extends Primitive {
|
| accept(Visitor visitor) => visitor.visitCreateBox(this);
|
| }
|
|
|
| /// Creates an instance of a class and initializes its fields and runtime type
|
| /// information.
|
| -class CreateInstance extends Primitive implements JsSpecificNode {
|
| +class CreateInstance extends Primitive {
|
| final ClassElement classElement;
|
|
|
| /// Initial values for the fields on the class.
|
| @@ -713,7 +636,11 @@ class CreateInstance extends Primitive implements JsSpecificNode {
|
| accept(Visitor visitor) => visitor.visitCreateInstance(this);
|
| }
|
|
|
| -class Identical extends Primitive implements JsSpecificNode {
|
| +/// Compare objects for identity.
|
| +///
|
| +/// It is an error pass in a value that does not correspond to a Dart value,
|
| +/// such as an interceptor or a box.
|
| +class Identical extends Primitive {
|
| final Reference<Primitive> left;
|
| final Reference<Primitive> right;
|
| Identical(Primitive left, Primitive right)
|
| @@ -722,7 +649,7 @@ class Identical extends Primitive implements JsSpecificNode {
|
| accept(Visitor visitor) => visitor.visitIdentical(this);
|
| }
|
|
|
| -class Interceptor extends Primitive implements JsSpecificNode {
|
| +class Interceptor extends Primitive {
|
| final Reference<Primitive> input;
|
| final Set<ClassElement> interceptedClasses;
|
| Interceptor(Primitive input, this.interceptedClasses)
|
| @@ -731,7 +658,7 @@ class Interceptor extends Primitive implements JsSpecificNode {
|
| }
|
|
|
| /// Create an instance of [Invocation] for use in a call to `noSuchMethod`.
|
| -class CreateInvocationMirror extends Primitive implements JsSpecificNode {
|
| +class CreateInvocationMirror extends Primitive {
|
| final Selector selector;
|
| final List<Reference<Primitive>> arguments;
|
|
|
| @@ -751,21 +678,9 @@ class Constant extends Primitive {
|
| accept(Visitor visitor) => visitor.visitConstant(this);
|
| }
|
|
|
| -/// Reify the given type variable as a [Type].
|
| -/// This depends on the current binding of 'this'.
|
| -class ReifyTypeVar extends Primitive implements DartSpecificNode {
|
| - final TypeVariableElement typeVariable;
|
| -
|
| - ReifyTypeVar(this.typeVariable);
|
| -
|
| - values.ConstantValue get constant => null;
|
| -
|
| - accept(Visitor visitor) => visitor.visitReifyTypeVar(this);
|
| -}
|
| -
|
| class LiteralList extends Primitive {
|
| /// The List type being created; this is not the type argument.
|
| - final GenericType type;
|
| + final InterfaceType type;
|
| final List<Reference<Primitive>> values;
|
|
|
| LiteralList(this.type, List<Primitive> values)
|
| @@ -784,7 +699,7 @@ class LiteralMapEntry {
|
| }
|
|
|
| class LiteralMap extends Primitive {
|
| - final GenericType type;
|
| + final InterfaceType type;
|
| final List<LiteralMapEntry> entries;
|
|
|
| LiteralMap(this.type, this.entries);
|
| @@ -792,8 +707,17 @@ class LiteralMap extends Primitive {
|
| accept(Visitor visitor) => visitor.visitLiteralMap(this);
|
| }
|
|
|
| -/// Create a non-recursive function.
|
| -class CreateFunction extends Primitive implements DartSpecificNode {
|
| +/// Currently unused.
|
| +///
|
| +/// Nested functions (from Dart code) are translated to classes by closure
|
| +/// conversion, hence they are instantiated with [CreateInstance].
|
| +///
|
| +/// We keep this around for now because it might come in handy when we
|
| +/// handle async/await in the CPS IR.
|
| +///
|
| +/// Instantiates a nested function. [MutableVariable]s are in scope in the
|
| +/// inner function, but primitives are not shared across function boundaries.
|
| +class CreateFunction extends Primitive {
|
| final FunctionDefinition definition;
|
|
|
| CreateFunction(this.definition);
|
| @@ -819,7 +743,7 @@ class Parameter extends Primitive {
|
|
|
| /// Continuations are normally bound by 'let cont'. A continuation with one
|
| /// parameter and no body is used to represent a function's return continuation.
|
| -/// The return continuation is bound by the Function, not by 'let cont'.
|
| +/// The return continuation is bound by the function, not by 'let cont'.
|
| class Continuation extends Definition<Continuation> implements InteriorNode {
|
| final List<Parameter> parameters;
|
| Expression body = null;
|
| @@ -841,39 +765,6 @@ class Continuation extends Definition<Continuation> implements InteriorNode {
|
| accept(Visitor visitor) => visitor.visitContinuation(this);
|
| }
|
|
|
| -abstract class RootNode extends Node {
|
| - Element get element;
|
| -
|
| - /// True if there is no body for this root node.
|
| - ///
|
| - /// In some parts of the compiler, empty root nodes are used as placeholders
|
| - /// for abstract methods, external constructors, fields without initializers,
|
| - /// etc.
|
| - bool get isEmpty;
|
| -
|
| - /// List of parameters, or an empty list if this is a field.
|
| - /// For fields, this list is immutable.
|
| - List<Definition> get parameters;
|
| -}
|
| -
|
| -// This is basically a function definition with an empty parameter list and a
|
| -// field element instead of a function element and no const declarations, and
|
| -// never a getter or setter, though that's less important.
|
| -class FieldDefinition extends RootNode implements DartSpecificNode {
|
| - final FieldElement element;
|
| - List<Definition> get parameters => const <Definition>[];
|
| - final Body body;
|
| -
|
| - FieldDefinition(this.element, this.body);
|
| -
|
| - FieldDefinition.withoutInitializer(this.element)
|
| - : this.body = null;
|
| -
|
| - accept(Visitor visitor) => visitor.visitFieldDefinition(this);
|
| -
|
| - bool get isEmpty => body == null;
|
| -}
|
| -
|
| /// Identifies a mutable variable.
|
| class MutableVariable extends Definition {
|
| Entity hint;
|
| @@ -883,102 +774,29 @@ class MutableVariable extends Definition {
|
| accept(Visitor v) => v.visitMutableVariable(this);
|
| }
|
|
|
| -class Body extends InteriorNode {
|
| - Expression body;
|
| - final Continuation returnContinuation;
|
| - Body(this.body, this.returnContinuation);
|
| - accept(Visitor visitor) => visitor.visitBody(this);
|
| -}
|
| -
|
| -/// A function definition, consisting of parameters and a body. The parameters
|
| -/// include a distinguished continuation parameter (held by the body).
|
| -class FunctionDefinition extends RootNode {
|
| +/// A function definition, consisting of parameters and a body.
|
| +///
|
| +/// There is an explicit parameter for the `this` argument, and a return
|
| +/// continuation to invoke when returning from the function.
|
| +class FunctionDefinition extends InteriorNode {
|
| final ExecutableElement element;
|
| final Parameter thisParameter;
|
| - /// Mixed list of [Parameter]s and [MutableVariable]s.
|
| - final List<Definition> parameters;
|
| - final Body body;
|
| - final List<ConstDeclaration> localConstants;
|
| -
|
| - /// Values for optional parameters.
|
| - final List<ConstantExpression> defaultParameterValues;
|
| + final List<Parameter> parameters;
|
| + final Continuation returnContinuation;
|
| + Expression body;
|
|
|
| FunctionDefinition(this.element,
|
| this.thisParameter,
|
| this.parameters,
|
| - this.body,
|
| - this.localConstants,
|
| - this.defaultParameterValues);
|
| -
|
| - FunctionDefinition.abstract(this.element,
|
| - this.parameters,
|
| - this.defaultParameterValues)
|
| - : body = null,
|
| - thisParameter = null,
|
| - localConstants = const <ConstDeclaration>[];
|
| + this.returnContinuation,
|
| + this.body);
|
|
|
| accept(Visitor visitor) => visitor.visitFunctionDefinition(this);
|
| -
|
| - bool get isEmpty => body == null;
|
| -}
|
| -
|
| -abstract class Initializer extends Node implements DartSpecificNode {}
|
| -
|
| -class FieldInitializer extends Initializer {
|
| - final FieldElement element;
|
| - final Body body;
|
| -
|
| - FieldInitializer(this.element, this.body);
|
| - accept(Visitor visitor) => visitor.visitFieldInitializer(this);
|
| -}
|
| -
|
| -class SuperInitializer extends Initializer {
|
| - final ConstructorElement target;
|
| - final List<Body> arguments;
|
| - final Selector selector;
|
| - SuperInitializer(this.target, this.arguments, this.selector);
|
| - accept(Visitor visitor) => visitor.visitSuperInitializer(this);
|
| -}
|
| -
|
| -class ConstructorDefinition extends RootNode implements DartSpecificNode {
|
| - final ConstructorElement element;
|
| - final Parameter thisParameter;
|
| - /// Mixed list of [Parameter]s and [MutableVariable]s.
|
| - final List<Definition> parameters;
|
| - final Body body;
|
| - final List<ConstDeclaration> localConstants;
|
| - final List<Initializer> initializers;
|
| -
|
| - /// Values for optional parameters.
|
| - final List<ConstantExpression> defaultParameterValues;
|
| -
|
| - ConstructorDefinition(this.element,
|
| - this.thisParameter,
|
| - this.parameters,
|
| - this.body,
|
| - this.initializers,
|
| - this.localConstants,
|
| - this.defaultParameterValues);
|
| -
|
| - // 'Abstract' here means "has no body" and is used to represent external
|
| - // constructors.
|
| - ConstructorDefinition.abstract(
|
| - this.element,
|
| - this.parameters,
|
| - this.defaultParameterValues)
|
| - : body = null,
|
| - initializers = null,
|
| - thisParameter = null,
|
| - localConstants = const <ConstDeclaration>[];
|
| -
|
| - accept(Visitor visitor) => visitor.visitConstructorDefinition(this);
|
| -
|
| - bool get isEmpty => body == null;
|
| }
|
|
|
| /// Converts the internal representation of a type to a Dart object of type
|
| /// [Type].
|
| -class ReifyRuntimeType extends Primitive implements JsSpecificNode {
|
| +class ReifyRuntimeType extends Primitive {
|
| /// Reference to the internal representation of a type (as produced, for
|
| /// example, by [ReadTypeVariable]).
|
| final Reference<Primitive> value;
|
| @@ -994,7 +812,7 @@ class ReifyRuntimeType extends Primitive implements JsSpecificNode {
|
| /// The resulting value is an internal representation (and not neccessarily a
|
| /// Dart object), and must be reified by [ReifyRuntimeType], if it should be
|
| /// used as a Dart value.
|
| -class ReadTypeVariable extends Primitive implements JsSpecificNode {
|
| +class ReadTypeVariable extends Primitive {
|
| final TypeVariableType variable;
|
| final Reference<Primitive> target;
|
|
|
| @@ -1013,7 +831,7 @@ class ReadTypeVariable extends Primitive implements JsSpecificNode {
|
| /// treated as 'holes' in the term, which means that it must be ensured at
|
| /// construction, that duplicate occurences of a type variable in [dartType]
|
| /// are assigned the same value.
|
| -class TypeExpression extends Primitive implements JsSpecificNode {
|
| +class TypeExpression extends Primitive {
|
| final DartType dartType;
|
| final List<Reference<Primitive>> arguments;
|
|
|
| @@ -1037,14 +855,7 @@ abstract class Visitor<T> {
|
| T visit(Node node);
|
|
|
| // Concrete classes.
|
| - T visitFieldDefinition(FieldDefinition node);
|
| T visitFunctionDefinition(FunctionDefinition node);
|
| - T visitConstructorDefinition(ConstructorDefinition node);
|
| - T visitBody(Body node);
|
| -
|
| - // Initializers
|
| - T visitFieldInitializer(FieldInitializer node);
|
| - T visitSuperInitializer(SuperInitializer node);
|
|
|
| // Expressions.
|
| T visitLetPrim(LetPrim node);
|
| @@ -1062,15 +873,14 @@ abstract class Visitor<T> {
|
| T visitBranch(Branch node);
|
| T visitTypeOperator(TypeOperator node);
|
| T visitSetMutableVariable(SetMutableVariable node);
|
| - T visitDeclareFunction(DeclareFunction node);
|
| T visitSetStatic(SetStatic node);
|
| T visitGetLazyStatic(GetLazyStatic node);
|
| + T visitSetField(SetField node);
|
|
|
| // Definitions.
|
| T visitLiteralList(LiteralList node);
|
| T visitLiteralMap(LiteralMap node);
|
| T visitConstant(Constant node);
|
| - T visitReifyTypeVar(ReifyTypeVar node);
|
| T visitCreateFunction(CreateFunction node);
|
| T visitGetMutableVariable(GetMutableVariable node);
|
| T visitParameter(Parameter node);
|
| @@ -1078,16 +888,6 @@ abstract class Visitor<T> {
|
| T visitMutableVariable(MutableVariable node);
|
| T visitNonTailThrow(NonTailThrow node);
|
| T visitGetStatic(GetStatic node);
|
| -
|
| - // JavaScript specific nodes.
|
| -
|
| - // Conditions.
|
| - T visitIsTrue(IsTrue node);
|
| -
|
| - // Expressions.
|
| - T visitSetField(SetField node);
|
| -
|
| - // Definitions.
|
| T visitIdentical(Identical node);
|
| T visitInterceptor(Interceptor node);
|
| T visitCreateInstance(CreateInstance node);
|
| @@ -1097,6 +897,9 @@ abstract class Visitor<T> {
|
| T visitReadTypeVariable(ReadTypeVariable node);
|
| T visitTypeExpression(TypeExpression node);
|
| T visitCreateInvocationMirror(CreateInvocationMirror node);
|
| +
|
| + // Conditions.
|
| + T visitIsTrue(IsTrue node);
|
| }
|
|
|
| /// Recursively visits the entire CPS term, and calls abstract `process*`
|
| @@ -1108,56 +911,15 @@ class RecursiveVisitor implements Visitor {
|
|
|
| processReference(Reference ref) {}
|
|
|
| - processBody(Body node) {}
|
| - visitBody(Body node) {
|
| - processBody(node);
|
| - visit(node.returnContinuation);
|
| - visit(node.body);
|
| - }
|
| -
|
| - processFieldDefinition(FieldDefinition node) {}
|
| - visitFieldDefinition(FieldDefinition node) {
|
| - processFieldDefinition(node);
|
| - if (node.body != null) {
|
| - visit(node.body);
|
| - }
|
| - }
|
| -
|
| processFunctionDefinition(FunctionDefinition node) {}
|
| visitFunctionDefinition(FunctionDefinition node) {
|
| processFunctionDefinition(node);
|
| if (node.thisParameter != null) visit(node.thisParameter);
|
| node.parameters.forEach(visit);
|
| - if (node.body != null) {
|
| - visit(node.body);
|
| - }
|
| - }
|
| -
|
| - processConstructorDefinition(ConstructorDefinition node) {}
|
| - visitConstructorDefinition(ConstructorDefinition node) {
|
| - processConstructorDefinition(node);
|
| - if (node.thisParameter != null) visit(node.thisParameter);
|
| - node.parameters.forEach(visit);
|
| - if (node.initializers != null) {
|
| - node.initializers.forEach(visit);
|
| - }
|
| - if (node.body != null) {
|
| - visit(node.body);
|
| - }
|
| - }
|
| -
|
| - processFieldInitializer(FieldInitializer node) {}
|
| - visitFieldInitializer(FieldInitializer node) {
|
| - processFieldInitializer(node);
|
| + visit(node.returnContinuation);
|
| visit(node.body);
|
| }
|
|
|
| - processSuperInitializer(SuperInitializer node) {}
|
| - visitSuperInitializer(SuperInitializer node) {
|
| - processSuperInitializer(node);
|
| - node.arguments.forEach(visit);
|
| - }
|
| -
|
| // Expressions.
|
|
|
| processLetPrim(LetPrim node) {}
|
| @@ -1268,22 +1030,12 @@ class RecursiveVisitor implements Visitor {
|
| visit(node.body);
|
| }
|
|
|
| - processDeclareFunction(DeclareFunction node) {}
|
| - visitDeclareFunction(DeclareFunction node) {
|
| - processDeclareFunction(node);
|
| - visit(node.variable);
|
| - visit(node.definition);
|
| - visit(node.body);
|
| - }
|
| -
|
| processGetLazyStatic(GetLazyStatic node) {}
|
| visitGetLazyStatic(GetLazyStatic node) {
|
| processGetLazyStatic(node);
|
| processReference(node.continuation);
|
| }
|
|
|
| - // Definitions.
|
| -
|
| processLiteralList(LiteralList node) {}
|
| visitLiteralList(LiteralList node) {
|
| processLiteralList(node);
|
| @@ -1304,11 +1056,6 @@ class RecursiveVisitor implements Visitor {
|
| processConstant(node);
|
| }
|
|
|
| - processReifyTypeVar(ReifyTypeVar node) {}
|
| - visitReifyTypeVar(ReifyTypeVar node) {
|
| - processReifyTypeVar(node);
|
| - }
|
| -
|
| processCreateFunction(CreateFunction node) {}
|
| visitCreateFunction(CreateFunction node) {
|
| processCreateFunction(node);
|
| @@ -1338,15 +1085,12 @@ class RecursiveVisitor implements Visitor {
|
| if (node.body != null) visit(node.body);
|
| }
|
|
|
| - // Conditions.
|
| -
|
| processIsTrue(IsTrue node) {}
|
| visitIsTrue(IsTrue node) {
|
| processIsTrue(node);
|
| processReference(node.value);
|
| }
|
|
|
| - // JavaScript specific nodes.
|
| processIdentical(Identical node) {}
|
| visitIdentical(Identical node) {
|
| processIdentical(node);
|
|
|