// 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.
library dart2js.ir_nodes;

import 'dart:collection';
import 'cps_fragment.dart' show CpsFragment;
import 'cps_ir_nodes_sexpr.dart';
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 '../universe/side_effects.dart';

import 'builtin_operator.dart';
export 'builtin_operator.dart';

import 'effects.dart';

// 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, isNullGuardOnFirstArgument;
import '../native/native.dart' as native show NativeBehavior;

abstract class Node {
  /// A pointer to the parent node. Is null until set by optimization passes.
  Node parent;

  /// Workaround for a slow Object.hashCode in the VM.
  static int _usedHashCodes = 0;
  final int hashCode = ++_usedHashCodes;

  Node() {
    setParentPointers();
  }

  accept(Visitor visitor);

  /// Updates the [parent] of the immediate children to refer to this node.
  ///
  /// All constructors call this method to initialize parent pointers.
  void setParentPointers();

  /// Returns the SExpression for the subtree rooted at this node.
  ///
  /// [annotations] maps strings to nodes and/or nodes to values that will be
  /// converted to strings. Each binding causes the annotation to appear on the
  /// given node.
  ///
  /// For example, the following could be used to diagnose a problem with nodes
  /// not appearing in an environment map:
  ///
  ///     if (environment[node] == null)
  ///       root.debugPrint({
  ///         'currentNode': node,
  ///         'caller': someContinuation
  ///       });
  ///       throw 'Node was not in environment';
  ///     }
  ///
  /// If two strings map to the same node, it will be given both annotations.
  ///
  /// Avoid using nodes as keys if there is a chance that two keys are the
  /// same node.
  String debugString([Map annotations]) {
    return new SExpressionStringifier()
        .withAnnotations(annotations)
        .visit(this);
  }

  /// Prints the result of [debugString].
  void debugPrint([Map annotations]) {
    print(debugString(annotations));
  }
}

/// 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].
///
/// All subclasses implement exactly one of [CallExpression],
/// [InteriorExpression], or [TailExpression].
abstract class Expression extends Node {
  InteriorNode get parent; // Only InteriorNodes may contain expressions.

  Expression plug(Expression expr) => throw 'impossible';

  /// The next expression in the basic block.
  ///
  /// For [InteriorExpression]s this is the body, for [CallExpressions] it is
  /// the body of the continuation, and for [TailExpressions] it is `null`.
  Expression get next;

  accept(BlockVisitor visitor);
}

/// Represents a node with a child node, which can be accessed through the
/// `body` member. A typical usage is when removing a node from the CPS graph:
///
///     Node child          = node.body;
///     InteriorNode parent = node.parent;
///
///     child.parent = parent;
///     parent.body  = child;
abstract class InteriorNode extends Node {
  Expression get body;
  void set body(Expression body);

  accept(BlockVisitor visitor);
}

/// The base class of things that variables can refer to: primitives,
/// continuations, function and continuation parameters, etc.
abstract class Definition<T extends Definition<T>> extends Node {
  // The head of a linked-list of occurrences, in no particular order.
  Reference<T> firstRef;

  bool get hasAtMostOneUse => firstRef == null || firstRef.next == null;
  bool get hasExactlyOneUse => firstRef != null && firstRef.next == null;
  bool get hasNoUses => firstRef == null;
  bool get hasAtLeastOneUse => firstRef != null;
  bool get hasMultipleUses => !hasAtMostOneUse;

  void replaceUsesWith(Definition<T> newDefinition) {
    if (newDefinition == this) return;
    if (hasNoUses) return;
    Reference<T> previous, current = firstRef;
    do {
      current.definition = newDefinition;
      previous = current;
      current = current.next;
    } while (current != null);
    previous.next = newDefinition.firstRef;
    if (newDefinition.firstRef != null) {
      newDefinition.firstRef.previous = previous;
    }
    newDefinition.firstRef = firstRef;
    firstRef = null;
  }
}

/// Operands to invocations and primitives are always variables.  They point to
/// their definition and are doubly-linked into a list of occurrences.
class Reference<T extends Definition<T>> {
  T definition;
  Reference<T> previous;
  Reference<T> next;

  /// A pointer to the parent node. Is null until set by optimization passes.
  Node parent;

  Reference(this.definition) {
    next = definition.firstRef;
    if (next != null) next.previous = this;
    definition.firstRef = this;
  }

  /// Unlinks this reference from the list of occurrences.
  void unlink() {
    if (previous == null) {
      assert(definition.firstRef == this);
      definition.firstRef = next;
    } else {
      previous.next = next;
    }
    if (next != null) next.previous = previous;
  }

  /// Changes the definition referenced by this object and updates
  /// the reference chains accordingly.
  void changeTo(Definition<T> newDefinition) {
    unlink();
    previous = null;
    definition = newDefinition;
    next = definition.firstRef;
    if (next != null) next.previous = this;
    definition.firstRef = this;
  }
}

class EffectiveUseIterator extends Iterator<Reference<Primitive>> {
  Reference<Primitive> current;
  Reference<Primitive> next;
  final List<Refinement> stack = <Refinement>[];

  EffectiveUseIterator(Primitive prim) : next = prim.firstRef;

  bool moveNext() {
    Reference<Primitive> ref = next;
    while (true) {
      if (ref == null) {
        if (stack.isNotEmpty) {
          ref = stack.removeLast().firstRef;
        } else {
          current = null;
          return false;
        }
      } else if (ref.parent is Refinement) {
        stack.add(ref.parent);
        ref = ref.next;
      } else {
        current = ref;
        next = current.next;
        return true;
      }
    }
  }
}

class RefinedUseIterable extends IterableBase<Reference<Primitive>> {
  Primitive primitive;
  RefinedUseIterable(this.primitive);
  EffectiveUseIterator get iterator => new EffectiveUseIterator(primitive);
}

/// A named value.
///
/// The identity of the [Primitive] object is the name of the value.
/// The subclass describes how to compute the value.
///
/// All primitives except [Parameter] must be bound by a [LetPrim].
abstract class Primitive extends Variable<Primitive> {
  Primitive() : super(null);

  /// Returns a bitmask with the non-local side effects and dependencies of
  /// this primitive, as defined by [Effects].
  int get effects => Effects.none;

  /// True if this primitive has a value that can be used by other expressions.
  bool get hasValue;

  /// True if the primitive can be removed, assuming it has no uses
  /// (this getter does not check if there are any uses).
  ///
  /// False must be returned for primitives that may throw, diverge, or have
  /// observable side-effects.
  bool get isSafeForElimination;

  /// True if time-of-evaluation is irrelevant for the given primitive,
  /// assuming its inputs are the same values.
  bool get isSafeForReordering;

  /// The source information associated with this primitive.
  // TODO(johnniwinther): Require source information for all primitives.
  SourceInformation get sourceInformation => null;

  /// If this is a [Refinement], [BoundsCheck] or [ReceiverCheck] node, returns
  /// the value being refined, the indexable object being checked, or the value
  /// that was checked to be non-null, respectively.
  ///
  /// Those instructions all return the corresponding operand directly, and
  /// this getter can be used to get (closer to) where the value came from.
  //
  // TODO(asgerf): Also do this for [TypeCast]?
  Primitive get effectiveDefinition => this;

  /// Like [effectiveDefinition] but only unfolds [Refinement] nodes.
  Primitive get unrefined => this;

  /// True if the two primitives are (refinements of) the same value.
  bool sameValue(Primitive other) {
    return effectiveDefinition == other.effectiveDefinition;
  }

  /// Iterates all non-refinement uses of the primitive and all uses of
  /// a [Refinement] of this primitive (transitively).
  ///
  /// Notes regarding concurrent modification:
  /// - The current reference may safely be unlinked.
  /// - Yet unvisited references may not be unlinked.
  /// - References to this primitive created during iteration will not be seen.
  /// - References to a refinement of this primitive may not be created during
  ///   iteration.
  RefinedUseIterable get refinedUses => new RefinedUseIterable(this);

  bool get hasMultipleRefinedUses {
    Iterator it = refinedUses.iterator;
    return it.moveNext() && it.moveNext();
  }

  bool get hasNoRefinedUses {
    return refinedUses.isEmpty;
  }

  /// Unlinks all references contained in this node.
  void destroy() {
    assert(hasNoUses);
    RemovalVisitor.remove(this);
  }

  /// Replaces this definition, both at the binding site and at all uses sites.
  ///
  /// This can be thought of as changing the definition of a `let` while
  /// preserving the variable name:
  ///
  ///     let x = OLD in BODY
  ///       ==>
  ///     let x = NEW in BODY
  ///
  void replaceWith(Primitive newDefinition) {
    assert(this is! Parameter);
    assert(newDefinition is! Parameter);
    assert(newDefinition.parent == null);
    replaceUsesWith(newDefinition);
    destroy();
    LetPrim let = parent;
    let.primitive = newDefinition;
    newDefinition.parent = let;
    newDefinition.useElementAsHint(hint);
  }

  /// Replaces this definition with a CPS fragment (a term with a hole in it),
  /// given the value to replace the uses of the definition with.
  ///
  /// This can be thought of as substituting:
  ///
  ///     let x = OLD in BODY
  ///       ==>
  ///     FRAGMENT[BODY{newPrimitive/x}]
  void replaceWithFragment(CpsFragment fragment, Primitive newPrimitive) {
    assert(this is! Parameter);
    replaceUsesWith(newPrimitive);
    destroy();
    LetPrim let = parent;
    fragment.insertBelow(let);
    let.remove();
  }
}

/// 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'.
class Continuation extends Definition<Continuation> implements InteriorNode {
  final List<Parameter> parameters;
  Expression body = null;

  // A continuation is recursive if it has any recursive invocations.
  bool isRecursive;

  /// True if this is the return continuation.  The return continuation is bound
  /// by [FunctionDefinition].
  bool get isReturnContinuation => body == null;

  /// True if this is a branch continuation.  Branch continuations are bound
  /// by [LetCont] and can only have one use.
  bool get isBranchContinuation => firstRef?.parent is Branch;

  /// True if this is the exception handler bound by a [LetHandler].
  bool get isHandlerContinuation => parent is LetHandler;

  /// True if this is a non-return continuation that can be targeted by
  /// [InvokeContinuation].
  bool get isJoinContinuation {
    return body != null &&
        parent is! LetHandler &&
        (firstRef == null || firstRef.parent is InvokeContinuation);
  }

  Continuation(this.parameters, {this.isRecursive: false});

  Continuation.retrn()
      : parameters = <Parameter>[new Parameter(null)],
        isRecursive = false;

  accept(BlockVisitor visitor) => visitor.visitContinuation(this);

  void setParentPointers() {
    _setParentsOnNodes(parameters, this);
    if (body != null) body.parent = this;
  }
}

/// Common interface for [Primitive] and [MutableVariable].
abstract class Variable<T extends Variable<T>> extends Definition<T> {
  /// Type of value held in the variable.
  ///
  /// Is `null` until initialized by type propagation.
  TypeMask type;

  /// The [VariableElement] or [ParameterElement] from which the variable
  /// binding originated.
  Entity hint;

  Variable(this.hint);

  /// Use the given element as a hint for naming this primitive.
  ///
  /// Has no effect if this primitive already has a non-null [element].
  void useElementAsHint(Entity hint) {
    this.hint ??= hint;
  }
}

/// Identifies a mutable variable.
class MutableVariable extends Variable<MutableVariable> {
  MutableVariable(Entity hint) : super(hint);

  accept(Visitor v) => v.visitMutableVariable(this);

  void setParentPointers() {}
}

/// 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;
  final List<Parameter> parameters;
  final Continuation returnContinuation;
  Expression body;

  FunctionDefinition(this.element, this.thisParameter, this.parameters,
      this.returnContinuation, this.body);

  accept(BlockVisitor visitor) => visitor.visitFunctionDefinition(this);

  void setParentPointers() {
    if (thisParameter != null) thisParameter.parent = this;
    _setParentsOnNodes(parameters, this);
    returnContinuation.parent = this;
    if (body != null) body.parent = this;
  }
}

// ----------------------------------------------------------------------------
//                            PRIMITIVES
// ----------------------------------------------------------------------------

class Parameter extends Primitive {
  Parameter(Entity hint) {
    super.hint = hint;
  }

  accept(Visitor visitor) => visitor.visitParameter(this);

  String toString() => 'Parameter(${hint == null ? null : hint.name})';

  bool get hasValue => true;
  bool get isSafeForElimination => true;
  bool get isSafeForReordering => true;

  void setParentPointers() {}
}

/// A primitive that is generally not safe for elimination, but may be marked
/// as safe by type propagation
abstract class UnsafePrimitive extends Primitive {
  int effects = Effects.all;
  bool isSafeForElimination = false;
  bool isSafeForReordering = false;
}

enum CallingConvention {
  /// JS receiver is the Dart receiver, there are no extra arguments.
  ///
  /// This includes cases (e.g., static functions, constructors) where there
  /// is no receiver.
  ///
  /// For example: `foo.bar$1(x)`
  Normal,

  /// JS receiver is an interceptor, the first argument is the Dart receiver.
  ///
  /// For example: `getInterceptor(foo).bar$1(foo, x)`
  Intercepted,

  /// JS receiver is the Dart receiver, the first argument is a dummy value.
  ///
  /// For example: `foo.bar$1(0, x)`
  DummyIntercepted,

  /// JS receiver is the Dart receiver, there are no extra arguments.
  ///
  /// Compiles to a one-shot interceptor, e.g: `J.bar$1(foo, x)`
  OneShotIntercepted,
}

/// Base class of function invocations.
///
/// This class defines the common interface of function invocations.
abstract class InvocationPrimitive extends UnsafePrimitive {
  Reference<Primitive> get receiverRef => null;
  Primitive get receiver => receiverRef?.definition;

  List<Reference<Primitive>> get argumentRefs;
  Primitive argument(int n) => argumentRefs[n].definition;
  Iterable<Primitive> get arguments => _dereferenceList(argumentRefs);

  Reference<Primitive> get dartReceiverRef => null;
  Primitive get dartReceiver => dartReceiverRef?.definition;

  CallingConvention get callingConvention => CallingConvention.Normal;

  Reference<Primitive> dartArgumentReference(int n) {
    switch (callingConvention) {
      case CallingConvention.Normal:
      case CallingConvention.OneShotIntercepted:
        return argumentRefs[n];

      case CallingConvention.Intercepted:
      case CallingConvention.DummyIntercepted:
        return argumentRefs[n + 1];
    }
  }

  Primitive dartArgument(int n) => dartArgumentReference(n).definition;

  int get dartArgumentsLength =>
      argumentRefs.length -
      (callingConvention == CallingConvention.Intercepted ||
          callingConvention == CallingConvention.DummyIntercepted ? 1 : 0);

  SourceInformation get sourceInformation;
}

/// 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 InvocationPrimitive {
  final FunctionElement target;
  final Selector selector;
  final List<Reference<Primitive>> argumentRefs;
  final SourceInformation sourceInformation;

  InvokeStatic(this.target, this.selector, List<Primitive> args,
      [this.sourceInformation])
      : argumentRefs = _referenceList(args);

  InvokeStatic.byReference(this.target, this.selector, this.argumentRefs,
      [this.sourceInformation]);

  accept(Visitor visitor) => visitor.visitInvokeStatic(this);

  bool get hasValue => true;

  void setParentPointers() {
    _setParentsOnList(argumentRefs, this);
  }
}

/// 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.
class InvokeMethod extends InvocationPrimitive {
  Reference<Primitive> receiverRef;
  Selector selector;
  TypeMask mask;
  final List<Reference<Primitive>> argumentRefs;
  final SourceInformation sourceInformation;

  CallingConvention callingConvention = CallingConvention.Normal;

  Reference<Primitive> get dartReceiverRef {
    return callingConvention == CallingConvention.Intercepted
        ? argumentRefs[0]
        : receiverRef;
  }

  InvokeMethod(
      Primitive receiver, this.selector, this.mask, List<Primitive> arguments,
      {this.sourceInformation,
      this.callingConvention: CallingConvention.Normal})
      : this.receiverRef = new Reference<Primitive>(receiver),
        this.argumentRefs = _referenceList(arguments);

  accept(Visitor visitor) => visitor.visitInvokeMethod(this);

  bool get hasValue => true;

  void setParentPointers() {
    receiverRef.parent = this;
    _setParentsOnList(argumentRefs, this);
  }
}

/// Invoke [target] on [receiver], bypassing dispatch and override semantics.
///
/// That is, if [receiver] is an instance of a class that overrides [target]
/// with a different implementation, the overriding implementation is bypassed
/// and [target]'s implementation is invoked.
///
/// As with [InvokeMethod], this can be used to invoke a method, operator,
/// getter, setter, or index getter/setter.
///
/// If it is known that [target] does not use its receiver argument, then
/// [receiver] may refer to a null constant primitive. This happens for direct
/// invocations to intercepted methods, where the effective receiver is instead
/// passed as a formal parameter.
///
/// TODO(sra): Review. A direct call to a method that is mixed into a native
/// class will still require an explicit argument.
///
/// All optional arguments declared by [target] are passed in explicitly, and
/// occur at the end of [arguments] list, in normalized order.
class InvokeMethodDirectly extends InvocationPrimitive {
  Reference<Primitive> receiverRef;
  final FunctionElement target;
  final Selector selector;
  final List<Reference<Primitive>> argumentRefs;
  final SourceInformation sourceInformation;

  CallingConvention callingConvention;

  Reference<Primitive> get dartReceiverRef {
    return callingConvention == CallingConvention.Intercepted
        ? argumentRefs[0]
        : receiverRef;
  }

  InvokeMethodDirectly(Primitive receiver, this.target, this.selector,
      List<Primitive> arguments, this.sourceInformation,
      {this.callingConvention: CallingConvention.Normal})
      : this.receiverRef = new Reference<Primitive>(receiver),
        this.argumentRefs = _referenceList(arguments);

  accept(Visitor visitor) => visitor.visitInvokeMethodDirectly(this);

  bool get hasValue => true;

  void setParentPointers() {
    receiverRef.parent = this;
    _setParentsOnList(argumentRefs, this);
  }

  bool get isConstructorBodyCall => target is ConstructorBodyElement;
  bool get isTearOff => selector.isGetter && !target.isGetter;
}

/// 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 InvocationPrimitive {
  final DartType dartType;
  final ConstructorElement target;
  final List<Reference<Primitive>> argumentRefs;
  final Selector selector;
  final SourceInformation sourceInformation;

  /// If non-null, this is an allocation site-specific type that is potentially
  /// better than the inferred return type of [target].
  ///
  /// In particular, container type masks depend on the allocation site and
  /// can therefore not be inferred solely based on the call target.
  TypeMask allocationSiteType;

  InvokeConstructor(this.dartType, this.target, this.selector,
      List<Primitive> args, this.sourceInformation,
      {this.allocationSiteType})
      : argumentRefs = _referenceList(args);

  accept(Visitor visitor) => visitor.visitInvokeConstructor(this);

  bool get hasValue => true;

  void setParentPointers() {
    _setParentsOnList(argumentRefs, this);
  }
}

/// An alias for [value] in a context where the value is known to satisfy
/// [type].
///
/// Refinement nodes are inserted before the type propagator pass and removed
/// afterwards, so as not to complicate passes that don't reason about types,
/// but need to reason about value references being identical (i.e. referring
/// to the same primitive).
class Refinement extends Primitive {
  Reference<Primitive> value;
  final TypeMask refineType;

  Refinement(Primitive value, this.refineType)
      : value = new Reference<Primitive>(value);

  bool get hasValue => true;
  bool get isSafeForElimination => false;
  bool get isSafeForReordering => false;

  accept(Visitor visitor) => visitor.visitRefinement(this);

  Primitive get effectiveDefinition => value.definition.effectiveDefinition;

  Primitive get unrefined => value.definition.unrefined;

  void setParentPointers() {
    value.parent = this;
  }
}

/// Checks that [index] is a valid index on a given indexable [object].
///
/// In the simplest form, compiles to the following:
///
///     if (index < 0 || index >= object.length)
///         ThrowIndexOutOfRangeException(object, index);
///
/// In the general form, any of the following conditions can be checked:
///
///  Lower bound: `index >= 0`
///  Upper bound: `index < object.length`
///  Emptiness:   `object.length !== 0`
///  Integerness: `index >>> 0 === index`
///
/// [index] must be an integer unless integerness is checked, and [object] must
/// refer to null or an indexable object, and [length] must be the length of
/// [object] at the time of the check.
///
/// Returns [object] so the bounds check can be used to restrict code motion.
/// It is possible to have a bounds check node that performs no checks but
/// is retained to restrict code motion.
///
/// The [index] reference may be null if there are no checks to perform,
/// and the [length] reference may be null if there is no upper bound or
/// emptiness check.
///
/// If a separate code motion guard for the index is required, e.g. because it
/// must be known to be non-negative in an operator that does not involve
/// [object], a [Refinement] can be created for it with the non-negative integer
/// type.
class BoundsCheck extends Primitive {
  final Reference<Primitive> objectRef;
  Reference<Primitive> indexRef;
  Reference<Primitive> lengthRef;
  int checks;
  final SourceInformation sourceInformation;

  Primitive get object => objectRef.definition;
  Primitive get index => indexRef?.definition;
  Primitive get length => lengthRef?.definition;

  /// If true, check that `index >= 0`.
  bool get hasLowerBoundCheck => checks & LOWER_BOUND != 0;

  /// If true, check that `index < object.length`.
  bool get hasUpperBoundCheck => checks & UPPER_BOUND != 0;

  /// If true, check that `object.length !== 0`.
  ///
  /// Equivalent to a lower bound check with `object.length - 1` as the index,
  /// but this check is faster.
  ///
  /// Although [index] is not used in the condition, it is used to generate
  /// the thrown error.  Currently it is always `-1` for emptiness checks,
  /// because that corresponds to `object.length - 1` in the error case.
  bool get hasEmptinessCheck => checks & EMPTINESS != 0;

  /// If true, check that `index` is an integer.
  bool get hasIntegerCheck => checks & INTEGER != 0;

  /// True if the [length] is needed to perform the check.
  bool get lengthUsedInCheck => checks & (UPPER_BOUND | EMPTINESS) != 0;

  bool get hasNoChecks => checks == NONE;

  static const int UPPER_BOUND = 1 << 0;
  static const int LOWER_BOUND = 1 << 1;
  static const int EMPTINESS = 1 << 2; // See [hasEmptinessCheck].
  static const int INTEGER = 1 << 3; // Check if index is an int.
  static const int BOTH_BOUNDS = UPPER_BOUND | LOWER_BOUND;
  static const int NONE = 0;

  BoundsCheck(Primitive object, Primitive index, Primitive length,
      [this.checks = BOTH_BOUNDS, this.sourceInformation])
      : this.objectRef = new Reference<Primitive>(object),
        this.indexRef = new Reference<Primitive>(index),
        this.lengthRef = _optionalReference(length);

  BoundsCheck.noCheck(Primitive object, [this.sourceInformation])
      : this.objectRef = new Reference<Primitive>(object),
        this.checks = NONE;

  accept(Visitor visitor) => visitor.visitBoundsCheck(this);

  void setParentPointers() {
    objectRef.parent = this;
    if (indexRef != null) {
      indexRef.parent = this;
    }
    if (lengthRef != null) {
      lengthRef.parent = this;
    }
  }

  String get checkString {
    if (hasNoChecks) return 'no-check';
    return [
      hasUpperBoundCheck ? 'upper' : null,
      hasLowerBoundCheck ? 'lower' : null,
      hasEmptinessCheck ? 'emptiness' : null,
      hasIntegerCheck ? 'integer' : null,
      'check'
    ].where((x) => x != null).join('-');
  }

  bool get isSafeForElimination => checks == NONE;
  bool get isSafeForReordering => false;
  bool get hasValue => true; // Can be referenced to restrict code motion.

  Primitive get effectiveDefinition => object.effectiveDefinition;
}

/// Throw a [NoSuchMethodError] if [value] cannot respond to [selector].
///
/// Returns [value] so this can be used to restrict code motion.
///
/// The check can take one of three forms:
///
///     value.toString;
///     value.selectorName;
///     value.selectorName();    (should only be used if check always fails)
///
/// The first two forms are used when it is known that only null fails the
/// check.  Additionally, the check may be guarded by a [condition], allowing
/// for three more forms:
///
///     if (condition) value.toString;          (this form is valid but unused)
///     if (condition) value.selectorName;
///     if (condition) value.selectorName();
///
/// The condition must be true if and only if the check should fail. It should
/// ideally be of a form understood by JS engines, e.g. a `typeof` test.
///
/// If [useSelector] is false, the first form instead becomes `value.toString;`.
/// This form is faster when the value is non-null and the accessed property has
/// been removed by tree shaking.
///
/// [selector] may not be one of the selectors implemented by the null object.
class ReceiverCheck extends Primitive {
  final Reference<Primitive> valueRef;
  final Selector selector;
  final SourceInformation sourceInformation;
  final Reference<Primitive> conditionRef;
  final int _flags;

  Primitive get value => valueRef.definition;
  Primitive get condition => conditionRef?.definition;

  static const int _USE_SELECTOR = 1 << 0;
  static const int _NULL_CHECK = 1 << 1;

  /// True if the selector name should be used in the check; otherwise
  /// `toString` will be used.
  bool get useSelector => _flags & _USE_SELECTOR != 0;

  /// True if null is the only possible input that cannot respond to [selector].
  bool get isNullCheck => _flags & _NULL_CHECK != 0;

  /// Constructor for creating checks in arbitrary configurations.
  ///
  /// Consider using one of the named constructors instead.
  ///
  /// [useSelector] and [isNullCheck] are mandatory named arguments.
  ReceiverCheck(Primitive value, this.selector, this.sourceInformation,
      {Primitive condition, bool useSelector, bool isNullCheck})
      : valueRef = new Reference<Primitive>(value),
        conditionRef = _optionalReference(condition),
        _flags =
            (useSelector ? _USE_SELECTOR : 0) | (isNullCheck ? _NULL_CHECK : 0);

  /// Simplified constructor for building null checks.
  ///
  /// Null must be the only possible input value that does not respond to
  /// [selector].
  ReceiverCheck.nullCheck(
      Primitive value, Selector selector, SourceInformation sourceInformation,
      {Primitive condition})
      : this(value, selector, sourceInformation,
            condition: condition,
            useSelector: condition != null,
            isNullCheck: true);

  /// Simplified constructor for building the general check of form:
  ///
  ///     if (condition) value.selectorName();
  ///
  ReceiverCheck.generalCheck(Primitive value, Selector selector,
      SourceInformation sourceInformation, Primitive condition)
      : this(value, selector, sourceInformation,
            condition: condition, useSelector: true, isNullCheck: false);

  bool get isSafeForElimination => false;
  bool get isSafeForReordering => false;
  bool get hasValue => true;

  accept(Visitor visitor) => visitor.visitReceiverCheck(this);

  void setParentPointers() {
    valueRef.parent = this;
    if (conditionRef != null) {
      conditionRef.parent = this;
    }
  }

  Primitive get effectiveDefinition => value.effectiveDefinition;

  String get nullCheckString => isNullCheck ? 'null-check' : 'general-check';
  String get useSelectorString => useSelector ? 'use-selector' : 'no-selector';
  String get flagString => '$nullCheckString $useSelectorString';
}

/// An "is" type test.
///
/// Returns `true` if [value] is an instance of [dartType].
///
/// [type] must not be the [Object], `dynamic` or [Null] types (though it might
/// be a type variable containing one of these types). This design is chosen
/// to simplify code generation for type tests.
class TypeTest extends Primitive {
  Reference<Primitive> valueRef;
  final DartType dartType;

  /// If [dartType] is an [InterfaceType], this holds the internal
  /// representation of the type arguments to [dartType]. Since these may
  /// reference type variables from the enclosing class, they are not constant.
  ///
  /// If [dartType] is a [TypeVariableType], this is a singleton list with the
  /// internal representation of the type held in that type variable.
  ///
  /// If [dartType] is a [FunctionType], this is a singleton list with the
  /// internal representation of that type,
  ///
  /// Otherwise the list is empty.
  final List<Reference<Primitive>> typeArgumentRefs;

  Primitive get value => valueRef.definition;
  Primitive typeArgument(int n) => typeArgumentRefs[n].definition;
  Iterable<Primitive> get typeArguments => _dereferenceList(typeArgumentRefs);

  TypeTest(Primitive value, this.dartType, List<Primitive> typeArguments)
      : this.valueRef = new Reference<Primitive>(value),
        this.typeArgumentRefs = _referenceList(typeArguments);

  accept(Visitor visitor) => visitor.visitTypeTest(this);

  bool get hasValue => true;
  bool get isSafeForElimination => true;
  bool get isSafeForReordering => true;

  void setParentPointers() {
    valueRef.parent = this;
    _setParentsOnList(typeArgumentRefs, this);
  }
}

/// An "is" type test for a raw type, performed by testing a flag property.
///
/// Returns `true` if [interceptor] is for [dartType].
class TypeTestViaFlag extends Primitive {
  Reference<Primitive> interceptorRef;
  final DartType dartType;

  Primitive get interceptor => interceptorRef.definition;

  TypeTestViaFlag(Primitive interceptor, this.dartType)
      : this.interceptorRef = new Reference<Primitive>(interceptor);

  accept(Visitor visitor) => visitor.visitTypeTestViaFlag(this);

  bool get hasValue => true;
  bool get isSafeForElimination => true;
  bool get isSafeForReordering => true;

  void setParentPointers() {
    interceptorRef.parent = this;
  }
}

/// An "as" type cast.
///
/// If [value] is `null` or is an instance of [type], [continuation] is invoked
/// with [value] as argument. Otherwise, a [CastError] is thrown.
///
/// Discussion:
/// The parameter to [continuation] is redundant since it will always equal
/// [value], which is typically in scope in the continuation. However, it might
/// simplify type propagation, since a better type can be computed for the
/// continuation parameter without needing flow-sensitive analysis.
class TypeCast extends UnsafePrimitive {
  Reference<Primitive> valueRef;
  final DartType dartType;

  /// See the corresponding field on [TypeTest].
  final List<Reference<Primitive>> typeArgumentRefs;

  Primitive get value => valueRef.definition;
  Primitive typeArgument(int n) => typeArgumentRefs[n].definition;
  Iterable<Primitive> get typeArguments => _dereferenceList(typeArgumentRefs);

  TypeCast(Primitive value, this.dartType, List<Primitive> typeArguments)
      : this.valueRef = new Reference<Primitive>(value),
        this.typeArgumentRefs = _referenceList(typeArguments);

  accept(Visitor visitor) => visitor.visitTypeCast(this);

  bool get hasValue => true;

  void setParentPointers() {
    valueRef.parent = this;
    _setParentsOnList(typeArgumentRefs, this);
  }
}

/// Apply a built-in operator.
///
/// It must be known that the arguments have the proper types.
class ApplyBuiltinOperator extends Primitive {
  BuiltinOperator operator;
  List<Reference<Primitive>> argumentRefs;
  final SourceInformation sourceInformation;

  Primitive argument(int n) => argumentRefs[n].definition;
  Iterable<Primitive> get arguments => _dereferenceList(argumentRefs);

  ApplyBuiltinOperator(
      this.operator, List<Primitive> arguments, this.sourceInformation)
      : this.argumentRefs = _referenceList(arguments);

  accept(Visitor visitor) => visitor.visitApplyBuiltinOperator(this);

  bool get hasValue => true;
  bool get isSafeForElimination => true;
  bool get isSafeForReordering => true;

  void setParentPointers() {
    _setParentsOnList(argumentRefs, this);
  }
}

/// Apply a built-in method.
///
/// It must be known that the arguments have the proper types.
class ApplyBuiltinMethod extends Primitive {
  BuiltinMethod method;
  Reference<Primitive> receiverRef;
  List<Reference<Primitive>> argumentRefs;
  final SourceInformation sourceInformation;

  Primitive get receiver => receiverRef.definition;
  Primitive argument(int n) => argumentRefs[n].definition;
  Iterable<Primitive> get arguments => _dereferenceList(argumentRefs);

  ApplyBuiltinMethod(this.method, Primitive receiver, List<Primitive> arguments,
      this.sourceInformation)
      : this.receiverRef = new Reference<Primitive>(receiver),
        this.argumentRefs = _referenceList(arguments);

  accept(Visitor visitor) => visitor.visitApplyBuiltinMethod(this);

  bool get hasValue => true;
  bool get isSafeForElimination => false;
  bool get isSafeForReordering => false;

  void setParentPointers() {
    receiverRef.parent = this;
    _setParentsOnList(argumentRefs, this);
  }

  int get effects => getEffectsOfBuiltinMethod(method);
}

/// Gets the value from a [MutableVariable].
///
/// [MutableVariable]s can be seen as ref cells that are not first-class
/// values.  A [LetPrim] with a [GetMutable] can then be seen as:
///
///   let prim p = ![variable] in [body]
///
class GetMutable extends Primitive {
  final Reference<MutableVariable> variableRef;

  MutableVariable get variable => variableRef.definition;

  GetMutable(MutableVariable variable)
      : this.variableRef = new Reference<MutableVariable>(variable);

  accept(Visitor visitor) => visitor.visitGetMutable(this);

  bool get hasValue => true;
  bool get isSafeForElimination => true;
  bool get isSafeForReordering => false;

  void setParentPointers() {
    variableRef.parent = this;
  }
}

/// Assign a [MutableVariable].
///
/// [MutableVariable]s can be seen as ref cells that are not first-class
/// values.  This can be seen as a dereferencing assignment:
///
///   { [variable] := [value]; [body] }
class SetMutable extends Primitive {
  final Reference<MutableVariable> variableRef;
  final Reference<Primitive> valueRef;

  MutableVariable get variable => variableRef.definition;
  Primitive get value => valueRef.definition;

  SetMutable(MutableVariable variable, Primitive value)
      : this.variableRef = new Reference<MutableVariable>(variable),
        this.valueRef = new Reference<Primitive>(value);

  accept(Visitor visitor) => visitor.visitSetMutable(this);

  bool get hasValue => false;
  bool get isSafeForElimination => false;
  bool get isSafeForReordering => false;

  void setParentPointers() {
    variableRef.parent = this;
    valueRef.parent = this;
  }
}

/// Directly reads from a field on a given object.
///
/// The [object] must either be `null` or an object that has [field].
class GetField extends Primitive {
  final Reference<Primitive> objectRef;
  FieldElement field;

  /// True if the field never changes value.
  final bool isFinal;

  /// True if the object is known not to be null.
  // TODO(asgerf): This is a placeholder until we agree on how to track
  //               side effects.
  bool objectIsNotNull = false;

  Primitive get object => objectRef.definition;

  GetField(Primitive object, this.field, {this.isFinal: false})
      : this.objectRef = new Reference<Primitive>(object);

  accept(Visitor visitor) => visitor.visitGetField(this);

  bool get hasValue => true;
  bool get isSafeForElimination => objectIsNotNull;
  bool get isSafeForReordering => false;

  toString() => 'GetField($field)';

  void setParentPointers() {
    objectRef.parent = this;
  }

  int get effects => isFinal ? 0 : Effects.dependsOnInstanceField;
}

/// Directly assigns to a field on a given object.
class SetField extends Primitive {
  final Reference<Primitive> objectRef;
  FieldElement field;
  final Reference<Primitive> valueRef;

  Primitive get object => objectRef.definition;
  Primitive get value => valueRef.definition;

  SetField(Primitive object, this.field, Primitive value)
      : this.objectRef = new Reference<Primitive>(object),
        this.valueRef = new Reference<Primitive>(value);

  accept(Visitor visitor) => visitor.visitSetField(this);

  bool get hasValue => false;
  bool get isSafeForElimination => false;
  bool get isSafeForReordering => false;

  void setParentPointers() {
    objectRef.parent = this;
    valueRef.parent = this;
  }

  int get effects => Effects.changesInstanceField;
}

/// Get the length of a string or native list.
class GetLength extends Primitive {
  final Reference<Primitive> objectRef;

  /// True if the length of the given object can never change.
  bool isFinal;

  /// True if the object is known not to be null.
  bool objectIsNotNull = false;

  Primitive get object => objectRef.definition;

  GetLength(Primitive object, {this.isFinal: false})
      : this.objectRef = new Reference<Primitive>(object);

  bool get hasValue => true;
  bool get isSafeForElimination => objectIsNotNull;
  bool get isSafeForReordering => false;

  accept(Visitor v) => v.visitGetLength(this);

  void setParentPointers() {
    objectRef.parent = this;
  }

  int get effects => isFinal ? 0 : Effects.dependsOnIndexableLength;
}

/// Read an entry from an indexable object.
///
/// [object] must be null or an indexable object, and [index] must be
/// an integer where `0 <= index < object.length`.
class GetIndex extends Primitive {
  final Reference<Primitive> objectRef;
  final Reference<Primitive> indexRef;

  /// True if the object is known not to be null.
  bool objectIsNotNull = false;

  Primitive get object => objectRef.definition;
  Primitive get index => indexRef.definition;

  GetIndex(Primitive object, Primitive index)
      : this.objectRef = new Reference<Primitive>(object),
        this.indexRef = new Reference<Primitive>(index);

  bool get hasValue => true;
  bool get isSafeForElimination => objectIsNotNull;
  bool get isSafeForReordering => false;

  accept(Visitor v) => v.visitGetIndex(this);

  void setParentPointers() {
    objectRef.parent = this;
    indexRef.parent = this;
  }

  int get effects => Effects.dependsOnIndexableContent;
}

/// Set an entry on a native list.
///
/// [object] must be null or a native list, and [index] must be an integer
/// within the bounds of the indexable object.
///
/// [SetIndex] may not be used to alter the length of a JS array.
///
/// The primitive itself has no value and may not be referenced.
class SetIndex extends Primitive {
  final Reference<Primitive> objectRef;
  final Reference<Primitive> indexRef;
  final Reference<Primitive> valueRef;

  Primitive get object => objectRef.definition;
  Primitive get index => indexRef.definition;
  Primitive get value => valueRef.definition;

  SetIndex(Primitive object, Primitive index, Primitive value)
      : this.objectRef = new Reference<Primitive>(object),
        this.indexRef = new Reference<Primitive>(index),
        this.valueRef = new Reference<Primitive>(value);

  bool get hasValue => false;
  bool get isSafeForElimination => false;
  bool get isSafeForReordering => false;

  accept(Visitor v) => v.visitSetIndex(this);

  void setParentPointers() {
    objectRef.parent = this;
    indexRef.parent = this;
    valueRef.parent = this;
  }

  int get effects => Effects.changesIndexableContent;
}

/// Reads the value of a static field or tears off a static method.
///
/// If [GetStatic] is used to load a lazily initialized static field, it must
/// have been initialized beforehand, and a [witness] must be set to restrict
/// code motion.
class GetStatic extends Primitive {
  /// Can be [FieldElement] or [FunctionElement].
  final Element element;
  final SourceInformation sourceInformation;

  /// True if the field never changes value.
  final bool isFinal;

  /// If reading a lazily initialized field, [witness] must refer to a node
  /// that initializes the field or always occurs after the field initializer.
  ///
  /// The value of the witness is not used.
  Reference<Primitive> witnessRef;

  Primitive get witness => witnessRef.definition;

  GetStatic(this.element, {this.isFinal: false, this.sourceInformation});

  /// Read a lazily initialized static field that is known to have been
  /// initialized by [witness] or earlier.
  GetStatic.witnessed(this.element, Primitive witness, {this.sourceInformation})
      : witnessRef = _optionalReference(witness),
        isFinal = false;

  accept(Visitor visitor) => visitor.visitGetStatic(this);

  bool get hasValue => true;
  bool get isSafeForElimination => true;
  bool get isSafeForReordering => isFinal;

  void setParentPointers() {
    if (witnessRef != null) {
      witnessRef.parent = this;
    }
  }

  int get effects => isFinal ? 0 : Effects.dependsOnStaticField;
}

/// Sets the value of a static field.
class SetStatic extends Primitive {
  final FieldElement element;
  final Reference<Primitive> valueRef;
  final SourceInformation sourceInformation;

  Primitive get value => valueRef.definition;

  SetStatic(this.element, Primitive value, [this.sourceInformation])
      : this.valueRef = new Reference<Primitive>(value);

  accept(Visitor visitor) => visitor.visitSetStatic(this);

  bool get hasValue => false;
  bool get isSafeForElimination => false;
  bool get isSafeForReordering => false;

  void setParentPointers() {
    valueRef.parent = this;
  }

  int get effects => Effects.changesStaticField;
}

/// Reads the value of a lazily initialized static field.
///
/// If the field has not yet been initialized, its initializer is evaluated
/// and assigned to the field.
class GetLazyStatic extends UnsafePrimitive {
  final FieldElement element;
  final SourceInformation sourceInformation;

  /// True if the field never changes value.
  final bool isFinal;

  GetLazyStatic(this.element, {this.isFinal: false, this.sourceInformation});

  accept(Visitor visitor) => visitor.visitGetLazyStatic(this);

  bool get hasValue => true;

  void setParentPointers() {}

  // TODO(asgerf): Track side effects of lazy field initializers.
  int get effects => Effects.all;
}

/// Creates an object for holding boxed variables captured by a closure.
class CreateBox extends Primitive {
  accept(Visitor visitor) => visitor.visitCreateBox(this);

  bool get hasValue => true;
  bool get isSafeForElimination => true;
  bool get isSafeForReordering => true;

  void setParentPointers() {}
}

/// Creates an instance of a class and initializes its fields and runtime type
/// information.
class CreateInstance extends Primitive {
  final ClassElement classElement;

  /// Initial values for the fields on the class.
  /// The order corresponds to the order of fields on the class.
  final List<Reference<Primitive>> argumentRefs;

  /// The runtime type information structure which contains the type arguments.
  ///
  /// May be `null` to indicate that no type information is needed because the
  /// compiler determined that the type information for instances of this class
  /// is not needed at runtime.
  final Reference<Primitive> typeInformationRef;

  final SourceInformation sourceInformation;

  Primitive argument(int n) => argumentRefs[n].definition;
  Iterable<Primitive> get arguments => _dereferenceList(argumentRefs);
  Primitive get typeInformation => typeInformationRef?.definition;

  CreateInstance(this.classElement, List<Primitive> arguments,
      Primitive typeInformation, this.sourceInformation)
      : this.argumentRefs = _referenceList(arguments),
        this.typeInformationRef = _optionalReference(typeInformation);

  accept(Visitor visitor) => visitor.visitCreateInstance(this);

  bool get hasValue => true;
  bool get isSafeForElimination => true;
  bool get isSafeForReordering => true;

  toString() => 'CreateInstance($classElement)';

  void setParentPointers() {
    _setParentsOnList(argumentRefs, this);
    if (typeInformationRef != null) typeInformationRef.parent = this;
  }
}

/// Obtains the interceptor for the given value.  This is a method table
/// corresponding to the Dart class of the value.
///
/// All values are either intercepted or self-intercepted.  The interceptor for
/// an "intercepted value" is one of the subclasses of Interceptor.
/// The interceptor for a "self-intercepted value" is the value itself.
///
/// If the input is an intercepted value, and any of its superclasses is in
/// [interceptedClasses], the method table for the input is returned.
/// Otherwise, the input itself is returned.
///
/// There are thus three significant cases:
/// - the input is a self-interceptor
/// - the input is an intercepted value and is caught by [interceptedClasses]
/// - the input is an intercepted value but is bypassed by [interceptedClasses]
///
/// The [flags] field indicates which of the above cases may happen, with
/// additional special cases for null (which can either by intercepted or
/// bypassed).
class Interceptor extends Primitive {
  final Reference<Primitive> inputRef;
  final Set<ClassElement> interceptedClasses = new Set<ClassElement>();
  final SourceInformation sourceInformation;

  Primitive get input => inputRef.definition;

  Interceptor(Primitive input, this.sourceInformation)
      : this.inputRef = new Reference<Primitive>(input);

  accept(Visitor visitor) => visitor.visitInterceptor(this);

  bool get hasValue => true;
  bool get isSafeForElimination => true;
  bool get isSafeForReordering => true;

  void setParentPointers() {
    inputRef.parent = this;
  }
}

/// Create an instance of [Invocation] for use in a call to `noSuchMethod`.
class CreateInvocationMirror extends Primitive {
  final Selector selector;
  final List<Reference<Primitive>> argumentRefs;

  Primitive argument(int n) => argumentRefs[n].definition;
  Iterable<Primitive> get arguments => _dereferenceList(argumentRefs);

  CreateInvocationMirror(this.selector, List<Primitive> arguments)
      : this.argumentRefs = _referenceList(arguments);

  accept(Visitor visitor) => visitor.visitCreateInvocationMirror(this);

  bool get hasValue => true;
  bool get isSafeForElimination => true;
  bool get isSafeForReordering => true;

  void setParentPointers() {
    _setParentsOnList(argumentRefs, this);
  }
}

class ForeignCode extends UnsafePrimitive {
  final js.Template codeTemplate;
  final TypeMask storedType;
  final List<Reference<Primitive>> argumentRefs;
  final native.NativeBehavior nativeBehavior;
  final FunctionElement dependency;

  Primitive argument(int n) => argumentRefs[n].definition;
  Iterable<Primitive> get arguments => _dereferenceList(argumentRefs);

  ForeignCode(this.codeTemplate, this.storedType, List<Primitive> arguments,
      this.nativeBehavior,
      {this.dependency})
      : this.argumentRefs = _referenceList(arguments) {
    effects = Effects.from(nativeBehavior.sideEffects);
  }

  accept(Visitor visitor) => visitor.visitForeignCode(this);

  bool get hasValue => true;

  void setParentPointers() {
    _setParentsOnList(argumentRefs, this);
  }

  bool isNullGuardOnNullFirstArgument() {
    if (argumentRefs.length < 1) return false;
    // TODO(sra): Fix NativeThrowBehavior to distinguish MAY from
    // throws-nsm-on-null-followed-by-MAY and remove
    // [isNullGuardForFirstArgument].
    if (nativeBehavior.throwBehavior.isNullNSMGuard) return true;
    return js.isNullGuardOnFirstArgument(codeTemplate);
  }
}

class Constant extends Primitive {
  final values.ConstantValue value;
  final SourceInformation sourceInformation;

  Constant(this.value, {this.sourceInformation}) {
    assert(value != null);
  }

  accept(Visitor visitor) => visitor.visitConstant(this);

  bool get hasValue => true;
  bool get isSafeForElimination => true;
  bool get isSafeForReordering => true;

  void setParentPointers() {}
}

class LiteralList extends Primitive {
  /// The List type being created; this is not the type argument.
  final InterfaceType dartType;
  final List<Reference<Primitive>> valueRefs;

  /// If non-null, this is an allocation site-specific type for the list
  /// created here.
  TypeMask allocationSiteType;

  Primitive value(int n) => valueRefs[n].definition;
  Iterable<Primitive> get values => _dereferenceList(valueRefs);

  LiteralList(this.dartType, List<Primitive> values, {this.allocationSiteType})
      : this.valueRefs = _referenceList(values);

  accept(Visitor visitor) => visitor.visitLiteralList(this);

  bool get hasValue => true;
  bool get isSafeForElimination => true;
  bool get isSafeForReordering => true;

  void setParentPointers() {
    _setParentsOnList(valueRefs, this);
  }
}

/// Converts the internal representation of a type to a Dart object of type
/// [Type].
class ReifyRuntimeType extends Primitive {
  /// Reference to the internal representation of a type (as produced, for
  /// example, by [ReadTypeVariable]).
  final Reference<Primitive> valueRef;

  final SourceInformation sourceInformation;

  Primitive get value => valueRef.definition;

  ReifyRuntimeType(Primitive value, this.sourceInformation)
      : this.valueRef = new Reference<Primitive>(value);

  @override
  accept(Visitor visitor) => visitor.visitReifyRuntimeType(this);

  bool get hasValue => true;
  bool get isSafeForElimination => true;
  bool get isSafeForReordering => true;

  void setParentPointers() {
    valueRef.parent = this;
  }
}

/// Read the value the type variable [variable] from the target object.
///
/// 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 {
  final TypeVariableType variable;
  final Reference<Primitive> targetRef;
  final SourceInformation sourceInformation;

  Primitive get target => targetRef.definition;

  ReadTypeVariable(this.variable, Primitive target, this.sourceInformation)
      : this.targetRef = new Reference<Primitive>(target);

  @override
  accept(Visitor visitor) => visitor.visitReadTypeVariable(this);

  bool get hasValue => true;
  bool get isSafeForElimination => true;
  bool get isSafeForReordering => true;

  void setParentPointers() {
    targetRef.parent = this;
  }
}

enum TypeExpressionKind { COMPLETE, INSTANCE }

/// Constructs a representation of a closed or ground-term type (that is, a type
/// without type variables).
///
/// There are two forms:
///
/// - COMPLETE: A complete form that is self contained, used for the values of
///   type parameters and non-raw is-checks.
///
/// - INSTANCE: A headless flat form for representing the sequence of values of
///   the type parameters of an instance of a generic type.
///
/// The COMPLETE form value is constructed from [dartType] by replacing the type
/// variables with consecutive values from [arguments], in the order generated
/// by [DartType.forEachTypeVariable].  The type variables in [dartType] are
/// 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.
///
/// The INSTANCE form is constructed as a list of [arguments]. This is the same
/// as the COMPLETE form for the 'thisType', except the root term's type is
/// missing; this is implicit as the raw type of instance.  The [dartType] of
/// the INSTANCE form must be the thisType of some class.
///
/// While we would like to remove the constrains on the INSTANCE form, we can
/// get by with a tree of TypeExpressions.  Consider:
///
///     class Foo<T> {
///       ... new Set<List<T>>()
///     }
///     class Set<E1> {
///       factory Set() => new _LinkedHashSet<E1>();
///     }
///     class List<E2> { ... }
///     class _LinkedHashSet<E3> { ... }
///
/// After inlining the factory constructor for `Set<E1>`, the CreateInstance
/// should have type `_LinkedHashSet<List<T>>` and the TypeExpression should be
/// a tree:
///
///    CreateInstance(dartType: _LinkedHashSet<List<T>>,
///        [], // No arguments
///        TypeExpression(INSTANCE,
///            dartType: _LinkedHashSet<E3>, // _LinkedHashSet's thisType
///            TypeExpression(COMPLETE,  // E3 = List<T>
///                dartType: List<E2>,
///                ReadTypeVariable(this, T)))) // E2 = T
//
// TODO(sra): The INSTANCE form requires the actual instance for full
// interpretation. I want to move to a representation where the INSTANCE form is
// also a complete form (possibly the same).
class TypeExpression extends Primitive {
  final TypeExpressionKind kind;
  final DartType dartType;
  final List<Reference<Primitive>> argumentRefs;

  Primitive argument(int n) => argumentRefs[n].definition;
  Iterable<Primitive> get arguments => _dereferenceList(argumentRefs);

  TypeExpression(this.kind, this.dartType, List<Primitive> arguments)
      : this.argumentRefs = _referenceList(arguments) {
    assert(kind == TypeExpressionKind.INSTANCE
        ? dartType == (dartType.element as ClassElement).thisType
        : true);
  }

  @override
  accept(Visitor visitor) {
    return visitor.visitTypeExpression(this);
  }

  bool get hasValue => true;
  bool get isSafeForElimination => true;
  bool get isSafeForReordering => true;

  void setParentPointers() {
    _setParentsOnList(argumentRefs, this);
  }

  String get kindAsString {
    switch (kind) {
      case TypeExpressionKind.COMPLETE:
        return 'COMPLETE';
      case TypeExpressionKind.INSTANCE:
        return 'INSTANCE';
    }
  }
}

class Await extends UnsafePrimitive {
  final Reference<Primitive> inputRef;

  Primitive get input => inputRef.definition;

  Await(Primitive input) : this.inputRef = new Reference<Primitive>(input);

  @override
  accept(Visitor visitor) {
    return visitor.visitAwait(this);
  }

  bool get hasValue => true;

  void setParentPointers() {
    inputRef.parent = this;
  }
}

class Yield extends UnsafePrimitive {
  final Reference<Primitive> inputRef;
  final bool hasStar;

  Primitive get input => inputRef.definition;

  Yield(Primitive input, this.hasStar)
      : this.inputRef = new Reference<Primitive>(input);

  @override
  accept(Visitor visitor) {
    return visitor.visitYield(this);
  }

  bool get hasValue => true;

  void setParentPointers() {
    inputRef.parent = this;
  }
}

// ---------------------------------------------------------------------------
//                            EXPRESSIONS
// ---------------------------------------------------------------------------

/// An expression that creates new bindings and continues evaluation in
/// a subexpression.
///
/// The interior expressions are [LetPrim], [LetCont], [LetHandler], and
/// [LetMutable].
abstract class InteriorExpression extends Expression implements InteriorNode {
  Expression get next => body;

  /// Removes this expression from its current position in the IR.
  ///
  /// The node can be re-inserted elsewhere or remain orphaned.
  ///
  /// If orphaned, the caller is responsible for unlinking all references in
  /// the orphaned node. Use [Reference.unlink] or [Primitive.destroy] for this.
  void remove() {
    assert(parent != null);
    assert(parent.body == this);
    assert(body.parent == this);
    parent.body = body;
    body.parent = parent;
    parent = null;
    body = null;
  }

  /// Inserts this above [node].
  ///
  /// This node must be orphaned first.
  void insertAbove(Expression node) {
    insertBelow(node.parent);
  }

  /// Inserts this below [node].
  ///
  /// This node must be orphaned first.
  void insertBelow(InteriorNode newParent) {
    assert(parent == null);
    assert(body == null);
    Expression child = newParent.body;
    newParent.body = this;
    this.body = child;
    child.parent = this;
    this.parent = newParent;
  }
}

/// An expression without a continuation or a subexpression body.
///
/// These break straight-line control flow and can be thought of as ending a
/// basic block.
abstract class TailExpression extends Expression {
  Expression get next => null;
}

/// 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 InteriorExpression {
  Primitive primitive;
  Expression body;

  LetPrim(this.primitive, [this.body = null]);

  Expression plug(Expression expr) {
    assert(body == null);
    return body = expr;
  }

  accept(BlockVisitor visitor) => visitor.visitLetPrim(this);

  void setParentPointers() {
    primitive.parent = this;
    if (body != null) body.parent = this;
  }
}

/// Binding continuations.
///
/// let cont k0(v0 ...) = E0
///          k1(v1 ...) = E1
///          ...
///   in E
///
/// 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`.
class LetCont extends InteriorExpression {
  List<Continuation> continuations;
  Expression body;

  LetCont(Continuation continuation, this.body)
      : continuations = <Continuation>[continuation];

  LetCont.two(Continuation first, Continuation second, this.body)
      : continuations = <Continuation>[first, second];

  LetCont.many(this.continuations, this.body);

  Expression plug(Expression expr) {
    assert(continuations != null &&
        continuations.isNotEmpty &&
        continuations.first.body == null);
    return continuations.first.body = expr;
  }

  accept(BlockVisitor visitor) => visitor.visitLetCont(this);

  void setParentPointers() {
    _setParentsOnNodes(continuations, this);
    if (body != null) body.parent = this;
  }
}

// Binding an exception handler.
//
// let handler h(v0, v1) = E0 in E1
//
// The handler is a two-argument (exception, stack trace) continuation which
// is implicitly the error continuation of all the code in its body E1.
// [LetHandler] differs from a [LetCont] binding in that it (1) has the
// runtime semantics of pushing/popping a handler from the dynamic exception
// handler stack and (2) it does not have any explicit invocations.
class LetHandler extends InteriorExpression {
  Continuation handler;
  Expression body;

  LetHandler(this.handler, this.body);

  accept(BlockVisitor visitor) => visitor.visitLetHandler(this);

  void setParentPointers() {
    handler.parent = this;
    if (body != null) body.parent = this;
  }
}

/// Binding mutable variables.
///
/// let mutable v = P in E
///
/// [MutableVariable]s can be seen as ref cells that are not first-class
/// values.  They are therefore not [Primitive]s and not bound by [LetPrim]
/// to prevent unrestricted use of references to them.  During one-pass
/// construction, a [LetMutable] with an empty body is use to represent the
/// one-hole context 'let mutable v = P in []'.
class LetMutable extends InteriorExpression {
  final MutableVariable variable;
  final Reference<Primitive> valueRef;
  Expression body;

  Primitive get value => valueRef.definition;

  LetMutable(this.variable, Primitive value)
      : this.valueRef = new Reference<Primitive>(value);

  Expression plug(Expression expr) {
    return body = expr;
  }

  accept(BlockVisitor visitor) => visitor.visitLetMutable(this);

  void setParentPointers() {
    variable.parent = this;
    valueRef.parent = this;
    if (body != null) body.parent = this;
  }
}

/// Throw a value.
///
/// Throw is an expression, i.e., it always occurs in tail position with
/// respect to a body or expression.
class Throw extends TailExpression {
  Reference<Primitive> valueRef;

  Primitive get value => valueRef.definition;

  Throw(Primitive value) : valueRef = new Reference<Primitive>(value);

  accept(BlockVisitor visitor) => visitor.visitThrow(this);

  void setParentPointers() {
    valueRef.parent = this;
  }
}

/// Rethrow
///
/// Rethrow can only occur inside a continuation bound by [LetHandler].  It
/// implicitly throws the exception parameter of the enclosing handler with
/// the same stack trace as the enclosing handler.
class Rethrow extends TailExpression {
  accept(BlockVisitor visitor) => visitor.visitRethrow(this);
  void setParentPointers() {}
}

/// An expression that is known to be unreachable.
///
/// This can be placed as the body of a call continuation, when the caller is
/// known never to invoke it, e.g. because the calling expression always throws.
class Unreachable extends TailExpression {
  accept(BlockVisitor visitor) => visitor.visitUnreachable(this);
  void setParentPointers() {}
}

/// Invoke a continuation in tail position.
class InvokeContinuation extends TailExpression {
  Reference<Continuation> continuationRef;
  List<Reference<Primitive>> argumentRefs;
  SourceInformation sourceInformation;

  Continuation get continuation => continuationRef.definition;
  Primitive argument(int n) => argumentRefs[n].definition;
  Iterable<Primitive> get arguments => _dereferenceList(argumentRefs);

  // An invocation of a continuation is recursive if it occurs in the body of
  // the continuation itself.
  bool isRecursive;

  /// True if this invocation escapes from the body of a [LetHandler]
  /// (i.e. a try block). Notably, such an invocation cannot be inlined.
  bool isEscapingTry;

  InvokeContinuation(Continuation cont, List<Primitive> args,
      {this.isRecursive: false,
      this.isEscapingTry: false,
      this.sourceInformation})
      : continuationRef = new Reference<Continuation>(cont),
        argumentRefs = _referenceList(args) {
    assert(cont.parameters == null || cont.parameters.length == args.length);
    if (isRecursive) cont.isRecursive = true;
  }

  /// A continuation invocation whose target and arguments will be filled
  /// in later.
  ///
  /// Used as a placeholder for a jump whose target is not yet created
  /// (e.g., in the translation of break and continue).
  InvokeContinuation.uninitialized(
      {this.isRecursive: false, this.isEscapingTry: false})
      : continuationRef = null,
        argumentRefs = null,
        sourceInformation = null;

  accept(BlockVisitor visitor) => visitor.visitInvokeContinuation(this);

  void setParentPointers() {
    if (continuationRef != null) continuationRef.parent = this;
    if (argumentRefs != null) _setParentsOnList(argumentRefs, this);
  }
}

/// Choose between a pair of continuations based on a condition value.
///
/// The two continuations must not declare any parameters.
class Branch extends TailExpression {
  final Reference<Primitive> conditionRef;
  final Reference<Continuation> trueContinuationRef;
  final Reference<Continuation> falseContinuationRef;

  Primitive get condition => conditionRef.definition;
  Continuation get trueContinuation => trueContinuationRef.definition;
  Continuation get falseContinuation => falseContinuationRef.definition;

  /// If true, only the value `true` satisfies the condition. Otherwise, any
  /// truthy value satisfies the check.
  ///
  /// Non-strict checks are preferable when the condition is known to be a
  /// boolean.
  bool isStrictCheck;

  Branch(Primitive condition, Continuation trueCont, Continuation falseCont,
      {bool strict})
      : this.conditionRef = new Reference<Primitive>(condition),
        trueContinuationRef = new Reference<Continuation>(trueCont),
        falseContinuationRef = new Reference<Continuation>(falseCont),
        isStrictCheck = strict {
    assert(strict != null);
  }

  Branch.strict(
      Primitive condition, Continuation trueCont, Continuation falseCont)
      : this(condition, trueCont, falseCont, strict: true);

  Branch.loose(
      Primitive condition, Continuation trueCont, Continuation falseCont)
      : this(condition, trueCont, falseCont, strict: false);

  accept(BlockVisitor visitor) => visitor.visitBranch(this);

  void setParentPointers() {
    conditionRef.parent = this;
    trueContinuationRef.parent = this;
    falseContinuationRef.parent = this;
  }
}

// ----------------------------------------------------------------------------
//                            UTILITY STUFF
// ----------------------------------------------------------------------------

Reference<Primitive> _reference(Primitive definition) {
  return new Reference<Primitive>(definition);
}

Reference<Primitive> _optionalReference(Primitive definition) {
  return definition == null ? null : new Reference<Primitive>(definition);
}

List<Reference<Primitive>> _referenceList(Iterable<Primitive> definitions) {
  return definitions.map((e) => new Reference<Primitive>(e)).toList();
}

Iterable<Primitive> _dereferenceList(List<Reference<Primitive>> references) {
  return references.map((ref) => ref.definition);
}

void _setParentsOnNodes(List<Node> nodes, Node parent) {
  for (Node node in nodes) {
    node.parent = parent;
  }
}

void _setParentsOnList(List<Reference> nodes, Node parent) {
  for (Reference node in nodes) {
    node.parent = parent;
  }
}

// ----------------------------------------------------------------------------
//                                 VISITORS
// ----------------------------------------------------------------------------

/// Visitor for block-level traversals that do not need to dispatch on
/// primitives.
abstract class BlockVisitor<T> {
  const BlockVisitor();

  T visit(Node node) => node.accept(this);

  // Block headers.
  T visitFunctionDefinition(FunctionDefinition node) => null;
  T visitContinuation(Continuation node) => null;

  // Interior expressions.
  T visitLetPrim(LetPrim node) => null;
  T visitLetCont(LetCont node) => null;
  T visitLetHandler(LetHandler node) => null;
  T visitLetMutable(LetMutable node) => null;

  // Tail expressions.
  T visitInvokeContinuation(InvokeContinuation node) => null;
  T visitThrow(Throw node) => null;
  T visitRethrow(Rethrow node) => null;
  T visitBranch(Branch node) => null;
  T visitUnreachable(Unreachable node) => null;

  /// Visits block-level nodes in lexical post-order (not post-dominator order).
  ///
  /// Continuations and function definitions are considered "block headers".
  /// The block itself is the sequence of interior expressions in the body,
  /// terminated by a tail expression.
  ///
  /// Each block is visited starting with its tail expression, then every
  /// interior expression from bottom to top, and finally the block header
  /// is visited.
  ///
  /// Blocks are visited in post-order, so the body of a continuation is always
  /// processed before its non-recursive invocation sites.
  ///
  /// The IR may be transformed during the traversal, but only the original
  /// nodes will be visited.
  static void traverseInPostOrder(FunctionDefinition root, BlockVisitor v) {
    List<Continuation> stack = <Continuation>[];
    List<Node> nodes = <Node>[];
    void walkBlock(InteriorNode block) {
      nodes.add(block);
      Expression node = block.body;
      nodes.add(node);
      while (node.next != null) {
        if (node is LetCont) {
          stack.addAll(node.continuations);
        } else if (node is LetHandler) {
          stack.add(node.handler);
        }
        node = node.next;
        nodes.add(node);
      }
    }
    walkBlock(root);
    while (stack.isNotEmpty) {
      walkBlock(stack.removeLast());
    }
    nodes.reversed.forEach(v.visit);
  }

  /// Visits block-level nodes in lexical pre-order.
  ///
  /// Traversal continues at the original success for the current node, so:
  /// - The current node can safely be removed.
  /// - Nodes inserted immediately below the current node will not be seen.
  /// - The body of the current node should not be moved/removed, as traversal
  ///   would otherwise continue into an orphaned or relocated node.
  static void traverseInPreOrder(FunctionDefinition root, BlockVisitor v) {
    List<Continuation> stack = <Continuation>[];
    void walkBlock(InteriorNode block) {
      v.visit(block);
      Expression node = block.body;
      while (node != null) {
        if (node is LetCont) {
          stack.addAll(node.continuations);
        } else if (node is LetHandler) {
          stack.add(node.handler);
        }
        Expression next = node.next;
        v.visit(node);
        node = next;
      }
    }
    walkBlock(root);
    while (stack.isNotEmpty) {
      walkBlock(stack.removeLast());
    }
  }
}

abstract class Visitor<T> implements BlockVisitor<T> {
  const Visitor();

  T visit(Node node);

  // Definitions.
  T visitInvokeStatic(InvokeStatic node);
  T visitInvokeMethod(InvokeMethod node);
  T visitInvokeMethodDirectly(InvokeMethodDirectly node);
  T visitInvokeConstructor(InvokeConstructor node);
  T visitTypeCast(TypeCast node);
  T visitSetMutable(SetMutable node);
  T visitSetStatic(SetStatic node);
  T visitSetField(SetField node);
  T visitGetLazyStatic(GetLazyStatic node);
  T visitAwait(Await node);
  T visitYield(Yield node);
  T visitLiteralList(LiteralList node);
  T visitConstant(Constant node);
  T visitGetMutable(GetMutable node);
  T visitParameter(Parameter node);
  T visitMutableVariable(MutableVariable node);
  T visitGetStatic(GetStatic node);
  T visitInterceptor(Interceptor node);
  T visitCreateInstance(CreateInstance node);
  T visitGetField(GetField node);
  T visitCreateBox(CreateBox node);
  T visitReifyRuntimeType(ReifyRuntimeType node);
  T visitReadTypeVariable(ReadTypeVariable node);
  T visitTypeExpression(TypeExpression node);
  T visitCreateInvocationMirror(CreateInvocationMirror node);
  T visitTypeTest(TypeTest node);
  T visitTypeTestViaFlag(TypeTestViaFlag node);
  T visitApplyBuiltinOperator(ApplyBuiltinOperator node);
  T visitApplyBuiltinMethod(ApplyBuiltinMethod node);
  T visitGetLength(GetLength node);
  T visitGetIndex(GetIndex node);
  T visitSetIndex(SetIndex node);
  T visitRefinement(Refinement node);
  T visitBoundsCheck(BoundsCheck node);
  T visitReceiverCheck(ReceiverCheck node);
  T visitForeignCode(ForeignCode node);
}

/// Recursively visits all children of a CPS term.
///
/// The user of the class is responsible for avoiding stack overflows from
/// deep recursion, e.g. by overriding methods to cut off recursion at certain
/// points.
///
/// All recursive invocations occur through the [visit] method, which the
/// subclass may override as a generic way to control the visitor without
/// overriding all visitor methods.
///
/// The `process*` methods are called in pre-order for every node visited.
/// These can be overridden without disrupting the visitor traversal.
class DeepRecursiveVisitor implements Visitor {
  const DeepRecursiveVisitor();

  visit(Node node) => node.accept(this);

  processReference(Reference ref) {}

  processFunctionDefinition(FunctionDefinition node) {}
  visitFunctionDefinition(FunctionDefinition node) {
    processFunctionDefinition(node);
    if (node.thisParameter != null) visit(node.thisParameter);
    node.parameters.forEach(visit);
    visit(node.body);
  }

  processContinuation(Continuation node) {}
  visitContinuation(Continuation node) {
    processContinuation(node);
    node.parameters.forEach(visit);
    if (node.body != null) visit(node.body);
  }

  // Expressions.
  processLetPrim(LetPrim node) {}
  visitLetPrim(LetPrim node) {
    processLetPrim(node);
    visit(node.primitive);
    visit(node.body);
  }

  processLetCont(LetCont node) {}
  visitLetCont(LetCont node) {
    processLetCont(node);
    node.continuations.forEach(visit);
    visit(node.body);
  }

  processLetHandler(LetHandler node) {}
  visitLetHandler(LetHandler node) {
    processLetHandler(node);
    visit(node.handler);
    visit(node.body);
  }

  processLetMutable(LetMutable node) {}
  visitLetMutable(LetMutable node) {
    processLetMutable(node);
    visit(node.variable);
    processReference(node.valueRef);
    visit(node.body);
  }

  processInvokeStatic(InvokeStatic node) {}
  visitInvokeStatic(InvokeStatic node) {
    processInvokeStatic(node);
    node.argumentRefs.forEach(processReference);
  }

  processInvokeContinuation(InvokeContinuation node) {}
  visitInvokeContinuation(InvokeContinuation node) {
    processInvokeContinuation(node);
    processReference(node.continuationRef);
    node.argumentRefs.forEach(processReference);
  }

  processInvokeMethod(InvokeMethod node) {}
  visitInvokeMethod(InvokeMethod node) {
    processInvokeMethod(node);
    processReference(node.receiverRef);
    node.argumentRefs.forEach(processReference);
  }

  processInvokeMethodDirectly(InvokeMethodDirectly node) {}
  visitInvokeMethodDirectly(InvokeMethodDirectly node) {
    processInvokeMethodDirectly(node);
    processReference(node.receiverRef);
    node.argumentRefs.forEach(processReference);
  }

  processInvokeConstructor(InvokeConstructor node) {}
  visitInvokeConstructor(InvokeConstructor node) {
    processInvokeConstructor(node);
    node.argumentRefs.forEach(processReference);
  }

  processThrow(Throw node) {}
  visitThrow(Throw node) {
    processThrow(node);
    processReference(node.valueRef);
  }

  processRethrow(Rethrow node) {}
  visitRethrow(Rethrow node) {
    processRethrow(node);
  }

  processBranch(Branch node) {}
  visitBranch(Branch node) {
    processBranch(node);
    processReference(node.trueContinuationRef);
    processReference(node.falseContinuationRef);
    processReference(node.conditionRef);
  }

  processTypeCast(TypeCast node) {}
  visitTypeCast(TypeCast node) {
    processTypeCast(node);
    processReference(node.valueRef);
    node.typeArgumentRefs.forEach(processReference);
  }

  processTypeTest(TypeTest node) {}
  visitTypeTest(TypeTest node) {
    processTypeTest(node);
    processReference(node.valueRef);
    node.typeArgumentRefs.forEach(processReference);
  }

  processTypeTestViaFlag(TypeTestViaFlag node) {}
  visitTypeTestViaFlag(TypeTestViaFlag node) {
    processTypeTestViaFlag(node);
    processReference(node.interceptorRef);
  }

  processSetMutable(SetMutable node) {}
  visitSetMutable(SetMutable node) {
    processSetMutable(node);
    processReference(node.variableRef);
    processReference(node.valueRef);
  }

  processGetLazyStatic(GetLazyStatic node) {}
  visitGetLazyStatic(GetLazyStatic node) {
    processGetLazyStatic(node);
  }

  processLiteralList(LiteralList node) {}
  visitLiteralList(LiteralList node) {
    processLiteralList(node);
    node.valueRefs.forEach(processReference);
  }

  processConstant(Constant node) {}
  visitConstant(Constant node) {
    processConstant(node);
  }

  processMutableVariable(node) {}
  visitMutableVariable(MutableVariable node) {
    processMutableVariable(node);
  }

  processGetMutable(GetMutable node) {}
  visitGetMutable(GetMutable node) {
    processGetMutable(node);
    processReference(node.variableRef);
  }

  processParameter(Parameter node) {}
  visitParameter(Parameter node) {
    processParameter(node);
  }

  processInterceptor(Interceptor node) {}
  visitInterceptor(Interceptor node) {
    processInterceptor(node);
    processReference(node.inputRef);
  }

  processCreateInstance(CreateInstance node) {}
  visitCreateInstance(CreateInstance node) {
    processCreateInstance(node);
    node.argumentRefs.forEach(processReference);
    if (node.typeInformationRef != null) {
      processReference(node.typeInformationRef);
    }
  }

  processSetField(SetField node) {}
  visitSetField(SetField node) {
    processSetField(node);
    processReference(node.objectRef);
    processReference(node.valueRef);
  }

  processGetField(GetField node) {}
  visitGetField(GetField node) {
    processGetField(node);
    processReference(node.objectRef);
  }

  processGetStatic(GetStatic node) {}
  visitGetStatic(GetStatic node) {
    processGetStatic(node);
    if (node.witnessRef != null) {
      processReference(node.witnessRef);
    }
  }

  processSetStatic(SetStatic node) {}
  visitSetStatic(SetStatic node) {
    processSetStatic(node);
    processReference(node.valueRef);
  }

  processCreateBox(CreateBox node) {}
  visitCreateBox(CreateBox node) {
    processCreateBox(node);
  }

  processReifyRuntimeType(ReifyRuntimeType node) {}
  visitReifyRuntimeType(ReifyRuntimeType node) {
    processReifyRuntimeType(node);
    processReference(node.valueRef);
  }

  processReadTypeVariable(ReadTypeVariable node) {}
  visitReadTypeVariable(ReadTypeVariable node) {
    processReadTypeVariable(node);
    processReference(node.targetRef);
  }

  processTypeExpression(TypeExpression node) {}
  visitTypeExpression(TypeExpression node) {
    processTypeExpression(node);
    node.argumentRefs.forEach(processReference);
  }

  processCreateInvocationMirror(CreateInvocationMirror node) {}
  visitCreateInvocationMirror(CreateInvocationMirror node) {
    processCreateInvocationMirror(node);
    node.argumentRefs.forEach(processReference);
  }

  processApplyBuiltinOperator(ApplyBuiltinOperator node) {}
  visitApplyBuiltinOperator(ApplyBuiltinOperator node) {
    processApplyBuiltinOperator(node);
    node.argumentRefs.forEach(processReference);
  }

  processApplyBuiltinMethod(ApplyBuiltinMethod node) {}
  visitApplyBuiltinMethod(ApplyBuiltinMethod node) {
    processApplyBuiltinMethod(node);
    processReference(node.receiverRef);
    node.argumentRefs.forEach(processReference);
  }

  processForeignCode(ForeignCode node) {}
  visitForeignCode(ForeignCode node) {
    processForeignCode(node);
    node.argumentRefs.forEach(processReference);
  }

  processUnreachable(Unreachable node) {}
  visitUnreachable(Unreachable node) {
    processUnreachable(node);
  }

  processAwait(Await node) {}
  visitAwait(Await node) {
    processAwait(node);
    processReference(node.inputRef);
  }

  processYield(Yield node) {}
  visitYield(Yield node) {
    processYield(node);
    processReference(node.inputRef);
  }

  processGetLength(GetLength node) {}
  visitGetLength(GetLength node) {
    processGetLength(node);
    processReference(node.objectRef);
  }

  processGetIndex(GetIndex node) {}
  visitGetIndex(GetIndex node) {
    processGetIndex(node);
    processReference(node.objectRef);
    processReference(node.indexRef);
  }

  processSetIndex(SetIndex node) {}
  visitSetIndex(SetIndex node) {
    processSetIndex(node);
    processReference(node.objectRef);
    processReference(node.indexRef);
    processReference(node.valueRef);
  }

  processRefinement(Refinement node) {}
  visitRefinement(Refinement node) {
    processRefinement(node);
    processReference(node.value);
  }

  processBoundsCheck(BoundsCheck node) {}
  visitBoundsCheck(BoundsCheck node) {
    processBoundsCheck(node);
    processReference(node.objectRef);
    if (node.indexRef != null) {
      processReference(node.indexRef);
    }
    if (node.lengthRef != null) {
      processReference(node.lengthRef);
    }
  }

  processNullCheck(ReceiverCheck node) {}
  visitReceiverCheck(ReceiverCheck node) {
    processNullCheck(node);
    processReference(node.valueRef);
    if (node.conditionRef != null) {
      processReference(node.conditionRef);
    }
  }
}

typedef void StackAction();

/// Calls `process*` for all nodes in a tree.
/// For simple usage, only override the `process*` methods.
///
/// To avoid deep recursion, this class uses an "action stack" containing
/// callbacks to be invoked after the processing of some term has finished.
///
/// To avoid excessive overhead from the action stack, basic blocks of
/// interior nodes are iterated in a loop without using the action stack.
///
/// The iteration order can be controlled by overriding the `traverse*`
/// methods for [LetCont], [LetPrim], [LetMutable], [LetHandler] and
/// [Continuation].
///
/// The `traverse*` methods return the expression to visit next, and may
/// push other subterms onto the stack using [push] or [pushAction] to visit
/// them later. Actions pushed onto the stack will be executed after the body
/// has been processed (and the stack actions it pushed have been executed).
///
/// By default, the `traverse` methods visit all non-recursive subterms,
/// push all bound continuations on the stack, and return the body of the term.
///
/// Subclasses should not override the `visit` methods for the nodes that have
/// a `traverse` method.
class TrampolineRecursiveVisitor extends DeepRecursiveVisitor {
  List<StackAction> _stack = <StackAction>[];

  void pushAction(StackAction callback) {
    _stack.add(callback);
  }

  void push(Continuation cont) {
    _stack.add(() {
      if (cont.isReturnContinuation) {
        traverseContinuation(cont);
      } else {
        _processBlock(traverseContinuation(cont));
      }
    });
  }

  visitFunctionDefinition(FunctionDefinition node) {
    processFunctionDefinition(node);
    if (node.thisParameter != null) visit(node.thisParameter);
    node.parameters.forEach(visit);
    visit(node.body);
  }

  visitContinuation(Continuation cont) {
    if (cont.isReturnContinuation) {
      traverseContinuation(cont);
    } else {
      int initialHeight = _stack.length;
      Expression body = traverseContinuation(cont);
      _trampoline(body, initialHeight: initialHeight);
    }
  }

  visitLetPrim(LetPrim node) => _trampoline(node);
  visitLetCont(LetCont node) => _trampoline(node);
  visitLetHandler(LetHandler node) => _trampoline(node);
  visitLetMutable(LetMutable node) => _trampoline(node);

  Expression traverseContinuation(Continuation cont) {
    processContinuation(cont);
    cont.parameters.forEach(visitParameter);
    return cont.body;
  }

  Expression traverseLetCont(LetCont node) {
    processLetCont(node);
    node.continuations.forEach(push);
    return node.body;
  }

  Expression traverseLetHandler(LetHandler node) {
    processLetHandler(node);
    push(node.handler);
    return node.body;
  }

  Expression traverseLetPrim(LetPrim node) {
    processLetPrim(node);
    visit(node.primitive);
    return node.body;
  }

  Expression traverseLetMutable(LetMutable node) {
    processLetMutable(node);
    visit(node.variable);
    processReference(node.valueRef);
    return node.body;
  }

  void _trampoline(Expression node, {int initialHeight}) {
    initialHeight = initialHeight ?? _stack.length;
    _processBlock(node);
    while (_stack.length > initialHeight) {
      StackAction callback = _stack.removeLast();
      callback();
    }
  }

  _processBlock(Expression node) {
    while (node is InteriorExpression) {
      if (node is LetCont) {
        node = traverseLetCont(node);
      } else if (node is LetHandler) {
        node = traverseLetHandler(node);
      } else if (node is LetPrim) {
        node = traverseLetPrim(node);
      } else {
        node = traverseLetMutable(node);
      }
    }
    visit(node);
  }
}

/// Visit a just-deleted subterm and unlink all [Reference]s in it.
class RemovalVisitor extends TrampolineRecursiveVisitor {
  processReference(Reference reference) {
    reference.unlink();
  }

  static void remove(Node node) {
    (new RemovalVisitor()).visit(node);
  }
}

/// A visitor to copy instances of [Definition] or its subclasses, except for
/// instances of [Continuation].
///
/// The visitor maintains a map from original definitions to their copies.
/// When the [copy] method is called for a non-Continuation definition,
/// a copy is created, added to the map and returned as the result. Copying a
/// definition assumes that the definitions of all references have already
/// been copied by the same visitor.
class DefinitionCopyingVisitor extends Visitor<Definition> {
  Map<Definition, Definition> _copies = <Definition, Definition>{};

  /// Put a copy into the map.
  ///
  /// This method should be used instead of directly adding copies to the map.
  Definition putCopy(Definition original, Definition copy) {
    if (copy is Variable) {
      Variable originalVariable = original;
      copy.type = originalVariable.type;
      copy.hint = originalVariable.hint;
    }
    return _copies[original] = copy;
  }

  /// Get the copy of a [Reference]'s definition from the map.
  Definition getCopy(Reference reference) => _copies[reference.definition];

  /// Get the copy of a [Reference]'s definition from the map.
  Definition getCopyOrNull(Reference reference) =>
      reference == null ? null : getCopy(reference);

  /// Map a list of [Reference]s to the list of their definition's copies.
  List<Definition> getList(List<Reference> list) => list.map(getCopy).toList();

  /// Copy a non-[Continuation] [Definition].
  Definition copy(Definition node) {
    assert(node is! Continuation);
    return putCopy(node, visit(node));
  }

  Definition visit(Node node) => node.accept(this);

  visitFunctionDefinition(FunctionDefinition node) {}
  visitLetPrim(LetPrim node) {}
  visitLetCont(LetCont node) {}
  visitLetHandler(LetHandler node) {}
  visitLetMutable(LetMutable node) {}
  visitInvokeContinuation(InvokeContinuation node) {}
  visitThrow(Throw node) {}
  visitRethrow(Rethrow node) {}
  visitBranch(Branch node) {}
  visitUnreachable(Unreachable node) {}
  visitContinuation(Continuation node) {}

  Definition visitInvokeStatic(InvokeStatic node) {
    return new InvokeStatic(node.target, node.selector,
        getList(node.argumentRefs), node.sourceInformation);
  }

  Definition visitInvokeMethod(InvokeMethod node) {
    return new InvokeMethod(getCopy(node.receiverRef), node.selector, node.mask,
        getList(node.argumentRefs),
        sourceInformation: node.sourceInformation,
        callingConvention: node.callingConvention);
  }

  Definition visitInvokeMethodDirectly(InvokeMethodDirectly node) {
    return new InvokeMethodDirectly(getCopy(node.receiverRef), node.target,
        node.selector, getList(node.argumentRefs), node.sourceInformation,
        callingConvention: node.callingConvention);
  }

  Definition visitInvokeConstructor(InvokeConstructor node) {
    return new InvokeConstructor(
        node.dartType,
        node.target,
        node.selector,
        getList(node.argumentRefs),
        node.sourceInformation)..allocationSiteType = node.allocationSiteType;
  }

  Definition visitTypeCast(TypeCast node) {
    return new TypeCast(
        getCopy(node.valueRef), node.dartType, getList(node.typeArgumentRefs));
  }

  Definition visitSetMutable(SetMutable node) {
    return new SetMutable(getCopy(node.variableRef), getCopy(node.valueRef));
  }

  Definition visitSetStatic(SetStatic node) {
    return new SetStatic(
        node.element, getCopy(node.valueRef), node.sourceInformation);
  }

  Definition visitSetField(SetField node) {
    return new SetField(
        getCopy(node.objectRef), node.field, getCopy(node.valueRef));
  }

  Definition visitGetLazyStatic(GetLazyStatic node) {
    return new GetLazyStatic(node.element,
        isFinal: node.isFinal, sourceInformation: node.sourceInformation);
  }

  Definition visitAwait(Await node) {
    return new Await(getCopy(node.inputRef));
  }

  Definition visitYield(Yield node) {
    return new Yield(getCopy(node.inputRef), node.hasStar);
  }

  Definition visitLiteralList(LiteralList node) {
    return new LiteralList(node.dartType, getList(node.valueRefs))
      ..allocationSiteType = node.allocationSiteType;
  }

  Definition visitConstant(Constant node) {
    return new Constant(node.value, sourceInformation: node.sourceInformation);
  }

  Definition visitGetMutable(GetMutable node) {
    return new GetMutable(getCopy(node.variableRef));
  }

  Definition visitParameter(Parameter node) {
    return new Parameter(node.hint);
  }

  Definition visitMutableVariable(MutableVariable node) {
    return new MutableVariable(node.hint);
  }

  Definition visitGetStatic(GetStatic node) {
    if (node.witnessRef != null) {
      return new GetStatic.witnessed(node.element, getCopy(node.witnessRef),
          sourceInformation: node.sourceInformation);
    } else {
      return new GetStatic(node.element,
          isFinal: node.isFinal, sourceInformation: node.sourceInformation);
    }
  }

  Definition visitInterceptor(Interceptor node) {
    return new Interceptor(getCopy(node.inputRef), node.sourceInformation)
      ..interceptedClasses.addAll(node.interceptedClasses);
  }

  Definition visitCreateInstance(CreateInstance node) {
    return new CreateInstance(node.classElement, getList(node.argumentRefs),
        getCopyOrNull(node.typeInformationRef), node.sourceInformation);
  }

  Definition visitGetField(GetField node) {
    return new GetField(getCopy(node.objectRef), node.field,
        isFinal: node.isFinal);
  }

  Definition visitCreateBox(CreateBox node) {
    return new CreateBox();
  }

  Definition visitReifyRuntimeType(ReifyRuntimeType node) {
    return new ReifyRuntimeType(getCopy(node.valueRef), node.sourceInformation);
  }

  Definition visitReadTypeVariable(ReadTypeVariable node) {
    return new ReadTypeVariable(
        node.variable, getCopy(node.targetRef), node.sourceInformation);
  }

  Definition visitTypeExpression(TypeExpression node) {
    return new TypeExpression(
        node.kind, node.dartType, getList(node.argumentRefs));
  }

  Definition visitCreateInvocationMirror(CreateInvocationMirror node) {
    return new CreateInvocationMirror(
        node.selector, getList(node.argumentRefs));
  }

  Definition visitTypeTest(TypeTest node) {
    return new TypeTest(
        getCopy(node.valueRef), node.dartType, getList(node.typeArgumentRefs));
  }

  Definition visitTypeTestViaFlag(TypeTestViaFlag node) {
    return new TypeTestViaFlag(getCopy(node.interceptorRef), node.dartType);
  }

  Definition visitApplyBuiltinOperator(ApplyBuiltinOperator node) {
    return new ApplyBuiltinOperator(
        node.operator, getList(node.argumentRefs), node.sourceInformation);
  }

  Definition visitApplyBuiltinMethod(ApplyBuiltinMethod node) {
    return new ApplyBuiltinMethod(node.method, getCopy(node.receiverRef),
        getList(node.argumentRefs), node.sourceInformation);
  }

  Definition visitGetLength(GetLength node) {
    return new GetLength(getCopy(node.objectRef), isFinal: node.isFinal);
  }

  Definition visitGetIndex(GetIndex node) {
    return new GetIndex(getCopy(node.objectRef), getCopy(node.indexRef));
  }

  Definition visitSetIndex(SetIndex node) {
    return new SetIndex(getCopy(node.objectRef), getCopy(node.indexRef),
        getCopy(node.valueRef));
  }

  Definition visitRefinement(Refinement node) {
    return new Refinement(getCopy(node.value), node.refineType);
  }

  Definition visitBoundsCheck(BoundsCheck node) {
    if (node.hasNoChecks) {
      return new BoundsCheck.noCheck(
          getCopy(node.objectRef), node.sourceInformation);
    } else {
      return new BoundsCheck(getCopy(node.objectRef), getCopy(node.indexRef),
          getCopyOrNull(node.lengthRef), node.checks, node.sourceInformation);
    }
  }

  Definition visitReceiverCheck(ReceiverCheck node) {
    return new ReceiverCheck(
        getCopy(node.valueRef), node.selector, node.sourceInformation,
        condition: getCopyOrNull(node.conditionRef),
        useSelector: node.useSelector,
        isNullCheck: node.isNullCheck);
  }

  Definition visitForeignCode(ForeignCode node) {
    return new ForeignCode(node.codeTemplate, node.storedType,
        getList(node.argumentRefs), node.nativeBehavior,
        dependency: node.dependency);
  }
}

/// A trampolining visitor to copy [FunctionDefinition]s.
class CopyingVisitor extends TrampolineRecursiveVisitor {
  // The visitor maintains a map from original continuations to their copies.
  Map<Continuation, Continuation> _copies = <Continuation, Continuation>{};

  // The visitor uses an auxiliary visitor to copy definitions.
  DefinitionCopyingVisitor _definitions = new DefinitionCopyingVisitor();

  // While copying a block, the state of the visitor is a 'linked list' of
  // the expressions in the block's body, with a pointer to the last element
  // of the list.
  Expression _first = null;
  Expression _current = null;

  void plug(Expression body) {
    if (_first == null) {
      _first = body;
    } else {
      assert(_current != null);
      InteriorExpression interior = _current;
      interior.body = body;
      body.parent = interior;
    }
    _current = body;
  }

  // Continuations are added to the visitor's stack to be visited after copying
  // the current block is finished.  The stack action saves the current block,
  // copies the continuation's body, sets the body on the copy of the
  // continuation, and restores the current block.
  //
  // Note that continuations are added to the copy map before the stack action
  // to visit them is performed.
  void push(Continuation cont) {
    assert(!cont.isReturnContinuation);
    _stack.add(() {
      Expression savedFirst = _first;
      _first = _current = null;
      _processBlock(cont.body);
      Continuation contCopy = _copies[cont];
      contCopy.body = _first;
      _first.parent = contCopy;
      _first = savedFirst;
      _current = null;
    });
  }

  FunctionDefinition copy(FunctionDefinition node) {
    assert(_first == null && _current == null);
    _first = _current = null;
    // Definitions are copied where they are bound, before processing
    // expressions in the scope of their binding.
    Parameter thisParameter = node.thisParameter == null
        ? null
        : _definitions.copy(node.thisParameter);
    List<Parameter> parameters =
        node.parameters.map(_definitions.copy).toList();
    // Though the return continuation's parameter does not have any uses,
    // we still make a proper copy to ensure that hints, type, etc. are
    // copied.
    Parameter returnParameter =
        _definitions.copy(node.returnContinuation.parameters.first);
    Continuation returnContinuation =
        _copies[node.returnContinuation] = new Continuation([returnParameter]);

    visit(node.body);
    FunctionDefinition copy = new FunctionDefinition(
        node.element, thisParameter, parameters, returnContinuation, _first);
    _first = _current = null;
    return copy;
  }

  Node visit(Node node) => node.accept(this);

  Expression traverseLetCont(LetCont node) {
    // Continuations are copied where they are bound, before processing
    // expressions in the scope of their binding.
    List<Continuation> continuations = node.continuations.map((Continuation c) {
      push(c);
      return _copies[c] =
          new Continuation(c.parameters.map(_definitions.copy).toList());
    }).toList();
    plug(new LetCont.many(continuations, null));
    return node.body;
  }

  Expression traverseLetHandler(LetHandler node) {
    // Continuations are copied where they are bound, before processing
    // expressions in the scope of their binding.
    push(node.handler);
    Continuation handler = _copies[node.handler] = new Continuation(
        node.handler.parameters.map(_definitions.copy).toList());
    plug(new LetHandler(handler, null));
    return node.body;
  }

  Expression traverseLetPrim(LetPrim node) {
    plug(new LetPrim(_definitions.copy(node.primitive)));
    return node.body;
  }

  Expression traverseLetMutable(LetMutable node) {
    plug(new LetMutable(
        _definitions.copy(node.variable), _definitions.getCopy(node.valueRef)));
    return node.body;
  }

  // Tail expressions do not have references, so we do not need to map them
  // to their copies.
  visitInvokeContinuation(InvokeContinuation node) {
    plug(new InvokeContinuation(
        _copies[node.continuation], _definitions.getList(node.argumentRefs),
        isRecursive: node.isRecursive,
        isEscapingTry: node.isEscapingTry,
        sourceInformation: node.sourceInformation));
  }

  visitThrow(Throw node) {
    plug(new Throw(_definitions.getCopy(node.valueRef)));
  }

  visitRethrow(Rethrow node) {
    plug(new Rethrow());
  }

  visitBranch(Branch node) {
    plug(new Branch.loose(
        _definitions.getCopy(node.conditionRef),
        _copies[node.trueContinuation],
        _copies[node.falseContinuation])..isStrictCheck = node.isStrictCheck);
  }

  visitUnreachable(Unreachable node) {
    plug(new Unreachable());
  }
}
