// 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_builder;

import '../closure.dart' as closure;
import '../common.dart';
import '../common/names.dart' show
    Names,
    Selectors;
import '../compile_time_constants.dart' show
    BackendConstantEnvironment;
import '../constants/constant_system.dart';
import '../constants/values.dart' show
    ConstantValue,
    PrimitiveConstantValue;
import '../dart_types.dart';
import '../elements/elements.dart';
import '../io/source_information.dart';
import '../js/js.dart' as js show
    js,
    LiteralStatement,
    Template;
import '../native/native.dart' show
    NativeBehavior;
import '../tree/tree.dart' as ast;
import '../types/types.dart' show
    TypeMask;
import '../universe/call_structure.dart' show
    CallStructure;
import '../universe/selector.dart' show
    Selector,
    SelectorKind;

import 'cps_ir_builder_task.dart' show
    GlobalProgramInformation;
import 'cps_ir_nodes.dart' as ir;


/// A mapping from variable elements to their compile-time values.
///
/// Map elements denoted by parameters and local variables to the
/// [ir.Primitive] that is their value.  Parameters and locals are
/// assigned indexes which can be used to refer to them.
class Environment {
  /// A map from locals to their environment index.
  final Map<Local, int> variable2index;

  /// A reverse map from environment indexes to the variable.
  final List<Local> index2variable;

  /// A map from environment indexes to their value.
  final List<ir.Primitive> index2value;

  Environment.empty()
      : variable2index = <Local, int>{},
        index2variable = <Local>[],
        index2value = <ir.Primitive>[];

  /// Construct an environment that is a copy of another one.
  ///
  /// The mapping from elements to indexes is shared, not copied.
  Environment.from(Environment other)
      : variable2index = other.variable2index,
        index2variable = new List<Local>.from(other.index2variable),
        index2value = new List<ir.Primitive>.from(other.index2value);

  /// Construct an environment that is shaped like another one but with a
  /// fresh parameter for each variable.
  ///
  /// The mapping from elements to indexes is shared, not copied.
  Environment.fresh(Environment other)
      : variable2index = other.variable2index,
        index2variable = new List<Local>.from(other.index2variable),
        index2value = other.index2variable.map((Local local) {
          return new ir.Parameter(local);
        }).toList();

  get length => index2variable.length;

  ir.Primitive operator [](int index) => index2value[index];

  void extend(Local element, ir.Primitive value) {
    // Assert that the name is not already in the environment.  `null` is used
    // as the name of anonymous variables.
    assert(!variable2index.containsKey(element));
    if (element != null) variable2index[element] = index2variable.length;
    index2variable.add(element);
    index2value.add(value);
  }

  /// Drop [count] values from the environment.
  ///
  /// Return the previous last value in the environment for convenience.
  ir.Primitive discard(int count) {
    assert(count > 0);
    assert(count <= index2variable.length);
    ir.Primitive value = index2value.last;
    // The map from variables to their index are shared, so we cannot remove
    // the mapping in `variable2index`.
    index2variable.length -= count;
    index2value.length -= count;
    return value;
  }

  ir.Primitive lookup(Local element) {
    assert(invariant(element, variable2index.containsKey(element),
                     message: "Unknown variable: $element."));
    return index2value[variable2index[element]];
  }

  void update(Local element, ir.Primitive value) {
    index2value[variable2index[element]] = value;
  }

  /// Verify that the variable2index and index2variable maps agree up to the
  /// index [length] exclusive.
  bool sameDomain(int length, Environment other) {
    assert(this.length >= length);
    assert(other.length >= length);
    for (int i = 0; i < length; ++i) {
      // An index maps to the same variable in both environments.
      Local variable = index2variable[i];
      if (variable != other.index2variable[i]) return false;

      // A named variable maps to the same index in both environments.
      if (variable != null) {
        int index = variable2index[variable];
        if (index == null || index != other.variable2index[variable]) {
          return false;
        }
      }
    }
    return true;
  }

  bool contains(Local local) => variable2index.containsKey(local);
}

/// The abstract base class of objects that emit jumps to a continuation and
/// give a handle to the continuation and its environment.
abstract class JumpCollector {
  final JumpTarget target;

  ir.Continuation _continuation = null;
  final Environment _continuationEnvironment;

  final List<Iterable<LocalVariableElement>> _boxedTryVariables =
      <Iterable<LocalVariableElement>>[];

  /// Construct a collector for a given environment and optionally a target.
  ///
  /// The environment is the one in effect at the point where the jump's
  /// continuation will be bound.  Continuations can take an extra argument
  /// (see [addJump]).
  JumpCollector(this._continuationEnvironment, this.target,
      bool hasExtraArgument) {
    if (hasExtraArgument) _continuationEnvironment.extend(null, null);
  }

  /// Construct a collector for collecting only return jumps.
  ///
  /// There is no jump target, it is implicitly the exit from the function.
  /// There is no environment at the destination.
  JumpCollector.retrn(this._continuation)
      : _continuationEnvironment = null, target = null;

  /// True if the collector has not recorded any jumps to its continuation.
  bool get isEmpty;

  /// The continuation encapsulated by this collector.
  ir.Continuation get continuation;

  /// The compile-time environment to be used for translating code in the body
  /// of the continuation.
  Environment get environment;

  /// Emit a jump to the continuation for a given [IrBuilder].
  ///
  /// Jumps can take a single extra argument.  This is used to pass return
  /// values to finally blocks for returns inside try/finally and to pass
  /// values of expressions that have internal control flow to their join-point
  /// continuations.
  void addJump(IrBuilder builder,
      [ir.Primitive value, SourceInformation sourceInformation]);

  /// Add a set of variables that were boxed on entry to a try block.
  ///
  /// All jumps from a try block to targets outside have to unbox the
  /// variables that were boxed on entry before invoking the target
  /// continuation.  Call this function before translating a try block and
  /// call [leaveTry] after translating it.
  void enterTry(Iterable<LocalVariableElement> boxedOnEntry) {
    // The boxed variables are maintained as a stack to make leaving easy.
    _boxedTryVariables.add(boxedOnEntry);
  }

  /// Remove the most recently added set of variables boxed on entry to a try
  /// block.
  ///
  /// Call [enterTry] before translating a try block and call this function
  /// after translating it.
  void leaveTry() {
    _boxedTryVariables.removeLast();
  }

  void _buildTryExit(IrBuilder builder) {
    for (Iterable<LocalVariableElement> boxedOnEntry in _boxedTryVariables) {
      for (LocalVariableElement variable in boxedOnEntry) {
        assert(builder.isInMutableVariable(variable));
        ir.Primitive value = builder.buildLocalGet(variable);
        builder.environment.update(variable, value);
      }
    }
  }

  /// True if a jump inserted now will escape from a try block.
  ///
  /// Concretely, this is true when [enterTry] has been called without
  /// its corresponding [leaveTry] call.
  bool get isEscapingTry => _boxedTryVariables.isNotEmpty;
}

/// A class to collect 'forward' jumps.
///
/// A forward jump to a continuation in the sense of the CPS translation is
/// a jump where the jump is emitted before any code in the body of the
/// continuation is translated.  They have the property that continuation
/// parameters and the environment for the translation of the body can be
/// determined based on the invocations, before translating the body.  A
/// [ForwardJumpCollector] can encapsulate a continuation where all the
/// jumps are forward ones.
///
/// Examples of forward jumps in the translation are join points of
/// if-then-else and breaks from loops.
///
/// The implementation strategy is that the collector collects invocation
/// sites and the environments at those sites.  Then it constructs a
/// continuation 'on demand' after all the jumps are seen.  It determines
/// continuation parameters, the environment for the translation of code in
/// the continuation body, and the arguments at the invocation site only
/// after all the jumps to the continuation are seen.
class ForwardJumpCollector extends JumpCollector {
  final List<ir.InvokeContinuation> _invocations = <ir.InvokeContinuation>[];
  final List<Environment> _invocationEnvironments = <Environment>[];

  /// Construct a collector with a given base environment.
  ///
  /// The base environment is the one in scope at the site that the
  /// continuation represented by this collector will be bound.  The
  /// environment is copied by the collector.  Subsequent mutation of the
  /// original environment will not affect the collector.
  ForwardJumpCollector(Environment environment,
      {JumpTarget target, bool hasExtraArgument: false})
      : super(new Environment.from(environment), target, hasExtraArgument);

  bool get isEmpty => _invocations.isEmpty;

  ir.Continuation get continuation {
    if (_continuation == null) _setContinuation();
    return _continuation;
  }

  Environment get environment {
    if (_continuation == null) _setContinuation();
    return _continuationEnvironment;
  }

  void addJump(IrBuilder builder,
      [ir.Primitive value, SourceInformation sourceInformation]) {
    assert(_continuation == null);
    _buildTryExit(builder);
    ir.InvokeContinuation invoke = new ir.InvokeContinuation.uninitialized(
        isEscapingTry: isEscapingTry);
    builder.add(invoke);
    _invocations.add(invoke);
    // Truncate the environment at the invocation site so it only includes
    // values that will be continuation arguments.  If an extra value is passed
    // it will already be included in the continuation environment, but it is
    // not present in the invocation environment.
    int delta = builder.environment.length - _continuationEnvironment.length;
    if (value != null) ++delta;
    if (delta > 0) builder.environment.discard(delta);
    if (value != null) builder.environment.extend(null, value);
    _invocationEnvironments.add(builder.environment);
    builder._current = null;
    // TODO(kmillikin): Can we set builder.environment to null to make it
    // less likely to mutate it?
  }

  void _setContinuation() {
    assert(_continuation == null);
    // We have seen all invocations of this continuation, and recorded the
    // environment in effect at each invocation site.

    // Compute the union of the assigned variables reaching the continuation.
    //
    // There is a continuation parameter for each environment variable
    // that has a different value (from the environment in scope at the
    // continuation binding) on some path.  `_environment` is initially a copy
    // of the environment in scope at the continuation binding.  Compute the
    // continuation parameters and add them to `_environment` so it will become
    // the one in scope for the continuation body.
    List<ir.Parameter> parameters = <ir.Parameter>[];
    if (_invocationEnvironments.isNotEmpty) {
      int length = _continuationEnvironment.length;
      for (int varIndex = 0; varIndex < length; ++varIndex) {
        for (Environment invocationEnvironment in _invocationEnvironments) {
          assert(invocationEnvironment.sameDomain(length,
                                                  _continuationEnvironment));
          if (invocationEnvironment[varIndex] !=
              _continuationEnvironment[varIndex]) {
            ir.Parameter parameter = new ir.Parameter(
                _continuationEnvironment.index2variable[varIndex]);
            _continuationEnvironment.index2value[varIndex] = parameter;
            parameters.add(parameter);
            break;
          }
        }
      }
    }
    _continuation = new ir.Continuation(parameters);

    // Compute the intersection of the parameters with the environments at
    // each continuation invocation.  Initialize the invocations.
    for (int jumpIndex = 0; jumpIndex < _invocations.length; ++jumpIndex) {
      Environment invocationEnvironment = _invocationEnvironments[jumpIndex];
      List<ir.Reference> arguments = <ir.Reference>[];
      int varIndex = 0;
      for (ir.Parameter parameter in parameters) {
        varIndex =
            _continuationEnvironment.index2value.indexOf(parameter, varIndex);
        arguments.add(new ir.Reference(invocationEnvironment[varIndex]));
      }
      ir.InvokeContinuation invocation = _invocations[jumpIndex];
      invocation.continuation = new ir.Reference(_continuation);
      invocation.arguments = arguments;
    }
  }
}

/// A class to collect 'backward' jumps.
///
/// A backward jump to a continuation in the sense of the CPS translation is
/// a jump where some code in the body of the continuation is translated
/// before the jump is emitted.  They have the property that the
/// continuation parameters and the environment for the translation of the
/// body must be determined before emitting all the invocations.  A
/// [BackwardJumpCollector] can ecapsulate a continuation where some jumps
/// are backward ones.
///
/// Examples of backward jumps in the translation are the recursive
/// invocations of loop continuations.
///
/// The implementation strategy is that the collector inserts a continuation
/// parameter for each variable in scope at the entry to the continuation,
/// before emitting any jump to the continuation.  When a jump is added, it
/// is given an argument for each continuation parameter.
class BackwardJumpCollector extends JumpCollector {
  /// Construct a collector with a given base environment.
  ///
  /// The base environment is the one in scope at the site that the
  /// continuation represented by this collector will be bound.  The
  /// translation of the continuation body will use an environment with the
  /// same shape, but with fresh continuation parameters for each variable.
  BackwardJumpCollector(Environment environment,
      {JumpTarget target, bool hasExtraArgument: false})
      : super(new Environment.fresh(environment), target, hasExtraArgument) {
    List<ir.Parameter> parameters =
        new List<ir.Parameter>.from(_continuationEnvironment.index2value);
    _continuation = new ir.Continuation(parameters, isRecursive: true);
  }

  bool isEmpty = true;

  ir.Continuation get continuation => _continuation;
  Environment get environment => _continuationEnvironment;

  void addJump(IrBuilder builder,
      [ir.Primitive value, SourceInformation sourceInformation]) {
    assert(_continuation.parameters.length <= builder.environment.length);
    isEmpty = false;
    _buildTryExit(builder);
    // Truncate the environment at the invocation site so it only includes
    // values that will be continuation arguments.  If an extra value is passed
    // it will already be included in the continuation environment, but it is
    // not present in the invocation environment.
    int delta = builder.environment.length - _continuationEnvironment.length;
    if (value != null) ++delta;
    if (delta > 0) builder.environment.discard(delta);
    if (value != null) builder.environment.extend(null, value);
    builder.add(new ir.InvokeContinuation(_continuation,
        builder.environment.index2value,
        isRecursive: true,
        isEscapingTry: isEscapingTry));
    builder._current = null;
  }
}

/// Collect 'return' jumps.
///
/// A return jump is one that targets the return continuation of a function.
/// Thus, returns from inside try/finally are not return jumps because they are
/// intercepted by a block that contains the finally handler code.
class ReturnJumpCollector extends JumpCollector {
  bool isEmpty = true;
  ir.Continuation get continuation => _continuation;
  Environment environment = null;

  /// Construct a return jump collector for a given return continuation.
  ReturnJumpCollector(ir.Continuation continuation) : super.retrn(continuation);

  void addJump(IrBuilder builder,
      [ir.Primitive value, SourceInformation sourceInformation]) {
    isEmpty = false;
    builder.add(new ir.InvokeContinuation(continuation, <ir.Primitive>[value],
        isEscapingTry: isEscapingTry,
        sourceInformation: sourceInformation));
    builder._current = null;
  }
}

/// Function for building a node in the context of the current builder.
typedef ir.Node BuildFunction(node);

/// Function for building nodes in the context of the provided [builder].
typedef ir.Node SubbuildFunction(IrBuilder builder);

/// Mixin that provides encapsulated access to nested builders.
abstract class IrBuilderMixin<N> {
  IrBuilder _irBuilder;

  /// Execute [f] with [builder] as the current builder.
  withBuilder(IrBuilder builder, f()) {
    assert(builder != null);
    IrBuilder prev = _irBuilder;
    _irBuilder = builder;
    var result = f();
    _irBuilder = prev;
    return result;
  }

  /// The current builder.
  IrBuilder get irBuilder {
    assert(_irBuilder != null);
    return _irBuilder;
  }

  /// Visits the [node].
  ir.Primitive visit(N node);

  /// Builds and returns the [ir.Node] for [node] or returns `null` if
  /// [node] is `null`.
  ir.Node build(N node) => node != null ? visit(node) : null;

  /// Returns a closure that takes an [IrBuilder] and builds [node] in its
  /// context using [build].
  SubbuildFunction subbuild(N node) {
    return (IrBuilder builder) => withBuilder(builder, () => build(node));
  }

  /// Returns a closure that takes an [IrBuilder] and runs [f] in its context.
  SubbuildFunction nested(f()) {
    return (IrBuilder builder) => withBuilder(builder, f);
  }

  /// Returns a closure that takes an [IrBuilder] and builds the sequence of
  /// [nodes] in its context using [build].
  // TODO(johnniwinther): Type [nodes] as `Iterable<N>` when `NodeList` uses
  // `List` instead of `Link`.
  SubbuildFunction subbuildSequence(/*Iterable<N>*/ nodes) {
    return (IrBuilder builder) {
      return withBuilder(builder, () => builder.buildSequence(nodes, build));
    };
  }
}

/// Shared state between delimited IrBuilders within the same function.
class IrBuilderSharedState {
  final GlobalProgramInformation program;

  final BackendConstantEnvironment constants;

  ConstantSystem get constantSystem => constants.constantSystem;

  /// A stack of collectors for breaks.
  List<JumpCollector> breakCollectors = <JumpCollector>[];

  /// A stack of collectors for continues.
  List<JumpCollector> continueCollectors = <JumpCollector>[];

  final ExecutableElement currentElement;

  final ir.Continuation returnContinuation = new ir.Continuation.retrn();

  /// The target of a return from the function.
  ///
  /// A null value indicates that the target is the function's return
  /// continuation.  Otherwise, when inside the try block of try/finally
  /// a return is intercepted to give a place to generate the finally code.
  JumpCollector returnCollector;

  /// Parameter holding the internal value of 'this' passed to the function.
  ///
  /// For nested functions, this is *not* captured receiver, but the function
  /// object itself.
  ir.Parameter thisParameter;

  /// If non-null, this refers to the receiver (`this`) in the enclosing method.
  ir.Primitive enclosingThis;

  final List<ir.Parameter> functionParameters = <ir.Parameter>[];

  /// Maps boxed locals to their location. These locals are not part of
  /// the environment.
  final Map<Local, ClosureLocation> boxedVariables = {};

  IrBuilderSharedState(this.program, this.constants, this.currentElement) {
    returnCollector = new ReturnJumpCollector(returnContinuation);
  }
}

class ThisParameterLocal implements Local {
  final ExecutableElement executableContext;
  ThisParameterLocal(this.executableContext);
  String get name => 'this';
  toString() => 'ThisParameterLocal($executableContext)';
}

/// The IR builder maintains an environment and an IR fragment.
///
/// The IR fragment is an expression with a hole in it. The hole represents
/// the focus where new expressions can be added. The fragment is implemented
/// by [_root] which is the root of the expression and [_current] which is the
/// expression that immediately contains the hole. Not all expressions have a
/// hole (e.g., invocations, which always occur in tail position, do not have a
/// hole). Expressions with a hole have a plug method.
///
/// The environment maintains the reaching definition of each local variable,
/// including some synthetic locals such as [TypeVariableLocal].
///
/// Internally, IR builders also maintains a [JumpCollector] stack and tracks
/// which variables are currently boxed or held in a mutable local variable.
class IrBuilder {
  final List<ir.Parameter> _parameters = <ir.Parameter>[];

  final IrBuilderSharedState state;

  /// A map from variable indexes to their values.
  ///
  /// [BoxLocal]s map to their box. [LocalElement]s that are boxed are not
  /// in the map; look up their [BoxLocal] instead.
  Environment environment;

  /// A map from mutable local variables to their [ir.MutableVariable]s.
  ///
  /// Mutable variables are treated as boxed.  Writes to them are observable
  /// side effects.
  Map<Local, ir.MutableVariable> mutableVariables;

  ir.Expression _root = null;
  ir.Expression _current = null;

  GlobalProgramInformation get program => state.program;

  IrBuilder(GlobalProgramInformation program,
            BackendConstantEnvironment constants,
            ExecutableElement currentElement)
    : state = new IrBuilderSharedState(program, constants, currentElement),
      environment = new Environment.empty(),
      mutableVariables = <Local, ir.MutableVariable>{};

  IrBuilder._internal(this.state, this.environment, this.mutableVariables);

  /// Construct a delimited visitor for visiting a subtree.
  ///
  /// Build a subterm that is not (yet) connected to the CPS term.  The
  /// delimited visitor has its own has its own context for building an IR
  /// expression, so the built expression is not plugged into the parent's
  /// context.  It has its own compile-time environment mapping local
  /// variables to their values.  If an optional environment argument is
  /// supplied, it is used as the builder's initial environment.  Otherwise
  /// the environment is initially a copy of the parent builder's environment.
  IrBuilder makeDelimitedBuilder([Environment env = null]) {
    return new IrBuilder._internal(
        state,
        env != null ? env : new Environment.from(environment),
        mutableVariables);
  }

  /// True if [local] should currently be accessed from a [ir.MutableVariable].
  bool isInMutableVariable(Local local) {
    return mutableVariables.containsKey(local);
  }

  /// Creates a [ir.MutableVariable] for the given local.
  void makeMutableVariable(Local local) {
    mutableVariables[local] =
        new ir.MutableVariable(local);
  }

  /// Remove an [ir.MutableVariable] for a local.
  ///
  /// Subsequent access to the local will be direct rather than through the
  /// mutable variable.
  void removeMutableVariable(Local local) {
    mutableVariables.remove(local);
  }

  /// Gets the [MutableVariable] containing the value of [local].
  ir.MutableVariable getMutableVariable(Local local) {
    return mutableVariables[local];
  }

  bool get isOpen => _root == null || _current != null;

  List<ir.Primitive> buildFunctionHeader(Iterable<Local> parameters,
                                        {ClosureScope closureScope,
                                         ClosureEnvironment env}) {
    _createThisParameter();
    _enterClosureEnvironment(env);
    _enterScope(closureScope);
    parameters.forEach(_createFunctionParameter);
    return _parameters;
  }

  /// Creates a parameter for [local] and adds it to the current environment.
  ir.Parameter _createLocalParameter(Local local) {
    ir.Parameter parameter = new ir.Parameter(local);
    _parameters.add(parameter);
    environment.extend(local, parameter);
    return parameter;
  }

  /// Plug an expression into the 'hole' in the context being accumulated.  The
  /// empty context (just a hole) is represented by root (and current) being
  /// null.  Since the hole in the current context is filled by this function,
  /// the new hole must be in the newly added expression---which becomes the
  /// new value of current.
  void add(ir.Expression expr) {
    assert(isOpen);
    if (_root == null) {
      _root = _current = expr;
    } else {
      _current = _current.plug(expr);
    }
  }

  /// Create and add a new [LetPrim] for [primitive].
  ir.Primitive addPrimitive(ir.Primitive primitive) {
    add(new ir.LetPrim(primitive));
    return primitive;
  }

  ir.Primitive buildInvokeStatic(Element element,
                                 Selector selector,
                                 List<ir.Primitive> arguments,
                                 SourceInformation sourceInformation) {
    assert(!element.isLocal);
    assert(!element.isInstanceMember);
    assert(isOpen);
    return addPrimitive(
        new ir.InvokeStatic(element, selector, arguments, sourceInformation));
  }

  ir.Primitive _buildInvokeSuper(Element target,
                                 Selector selector,
                                 List<ir.Primitive> arguments,
                                 SourceInformation sourceInformation) {
    assert(target.isInstanceMember);
    assert(isOpen);
    return addPrimitive(new ir.InvokeMethodDirectly(
        buildThis(), target, selector, arguments, sourceInformation));
  }

  ir.Primitive _buildInvokeDynamic(ir.Primitive receiver,
                                   Selector selector,
                                   TypeMask mask,
                                   List<ir.Primitive> arguments,
                                   SourceInformation sourceInformation) {
    assert(isOpen);
    return addPrimitive(new ir.InvokeMethod(
        receiver, selector, mask, arguments,
        sourceInformation: sourceInformation));
  }

  ir.Primitive _buildInvokeCall(ir.Primitive target,
                                CallStructure callStructure,
                                TypeMask mask,
                                List<ir.Definition> arguments,
                                {SourceInformation sourceInformation}) {
    Selector selector = callStructure.callSelector;
    return _buildInvokeDynamic(
        target, selector, mask, arguments, sourceInformation);
  }

  ir.Primitive buildStaticNoSuchMethod(Selector selector,
                                       List<ir.Primitive> arguments) {
    ir.Primitive receiver = buildStringConstant('');
    ir.Primitive name = buildStringConstant(selector.name);
    ir.Primitive argumentList = buildListLiteral(null, arguments);
    ir.Primitive expectedArgumentNames = buildNullConstant();
    return buildStaticFunctionInvocation(
        program.throwNoSuchMethod,
        <ir.Primitive>[receiver, name, argumentList, expectedArgumentNames]);
  }

  /// Create a [ir.Constant] from [value] and add it to the CPS term.
  ir.Constant buildConstant(ConstantValue value,
                            {SourceInformation sourceInformation}) {
    assert(isOpen);
    return addPrimitive(
        new ir.Constant(value, sourceInformation: sourceInformation));
  }

  /// Create an integer constant and add it to the CPS term.
  ir.Constant buildIntegerConstant(int value) {
    return buildConstant(state.constantSystem.createInt(value));
  }

  /// Create a double constant and add it to the CPS term.
  ir.Constant buildDoubleConstant(double value) {
    return buildConstant(state.constantSystem.createDouble(value));
  }

  /// Create a Boolean constant and add it to the CPS term.
  ir.Constant buildBooleanConstant(bool value) {
    return buildConstant(state.constantSystem.createBool(value));
  }

  /// Create a null constant and add it to the CPS term.
  ir.Constant buildNullConstant() {
    return buildConstant(state.constantSystem.createNull());
  }

  /// Create a string constant and add it to the CPS term.
  ir.Constant buildStringConstant(String value) {
    return buildConstant(
        state.constantSystem.createString(new ast.DartString.literal(value)));
  }

  /// Create a string constant and add it to the CPS term.
  ir.Constant buildDartStringConstant(ast.DartString value) {
    return buildConstant(state.constantSystem.createString(value));
  }

  /// Creates a non-constant list literal of the provided [type] and with the
  /// provided [values].
  ir.Primitive buildListLiteral(InterfaceType type,
                                Iterable<ir.Primitive> values,
                                {TypeMask allocationSiteType}) {
    assert(isOpen);
    return addPrimitive(new ir.LiteralList(type, values.toList(),
        allocationSiteType: allocationSiteType));
  }

  /// Creates a conditional expression with the provided [condition] where the
  /// then and else expression are created through the [buildThenExpression]
  /// and [buildElseExpression] functions, respectively.
  ir.Primitive buildConditional(
      ir.Primitive condition,
      ir.Primitive buildThenExpression(IrBuilder builder),
      ir.Primitive buildElseExpression(IrBuilder builder)) {
    assert(isOpen);

    // The then and else expressions are delimited.
    IrBuilder thenBuilder = makeDelimitedBuilder();
    IrBuilder elseBuilder = makeDelimitedBuilder();
    ir.Primitive thenValue = buildThenExpression(thenBuilder);
    ir.Primitive elseValue = buildElseExpression(elseBuilder);

    // Treat the values of the subexpressions as named values in the
    // environment, so they will be treated as arguments to the join-point
    // continuation.  We know the environments are the right size because
    // expressions cannot introduce variable bindings.
    assert(environment.length == thenBuilder.environment.length);
    assert(environment.length == elseBuilder.environment.length);
    JumpCollector join =
        new ForwardJumpCollector(environment, hasExtraArgument: true);
    thenBuilder.jumpTo(join, thenValue);
    elseBuilder.jumpTo(join, elseValue);

    // Build the term
    //   let cont join(x, ..., result) = [] in
    //   let cont then() = [[thenPart]]; join(v, ...)
    //        and else() = [[elsePart]]; join(v, ...)
    //   in
    //     if condition (then, else)
    ir.Continuation thenContinuation = new ir.Continuation([]);
    ir.Continuation elseContinuation = new ir.Continuation([]);
    thenContinuation.body = thenBuilder._root;
    elseContinuation.body = elseBuilder._root;
    add(new ir.LetCont(join.continuation,
            new ir.LetCont.two(thenContinuation, elseContinuation,
                new ir.Branch.strict(condition,
                                     thenContinuation,
                                     elseContinuation))));
    environment = join.environment;
    return environment.discard(1);
  }

  /**
   * Add an explicit `return null` for functions that don't have a return
   * statement on each branch. This includes functions with an empty body,
   * such as `foo(){ }`.
   */
  void _ensureReturn() {
    if (!isOpen) return;
    ir.Constant constant = buildNullConstant();
    add(new ir.InvokeContinuation(state.returnContinuation, [constant]));
    _current = null;
  }

  /// Create a [ir.FunctionDefinition] using [_root] as the body.
  ///
  /// The protocol for building a function is:
  /// 1. Call [buildFunctionHeader].
  /// 2. Call `buildXXX` methods to build the body.
  /// 3. Call [makeFunctionDefinition] to finish.
  ir.FunctionDefinition makeFunctionDefinition() {
    _ensureReturn();
    return new ir.FunctionDefinition(
        state.currentElement,
        state.thisParameter,
        state.functionParameters,
        state.returnContinuation,
        _root);
  }

  /// Create a invocation of the [method] on the super class where the call
  /// structure is defined [callStructure] and the argument values are defined
  /// by [arguments].
  ir.Primitive buildSuperMethodInvocation(
      MethodElement method,
      CallStructure callStructure,
      List<ir.Primitive> arguments,
      {SourceInformation sourceInformation}) {
    // TODO(johnniwinther): This shouldn't be necessary.
    SelectorKind kind = Elements.isOperatorName(method.name)
        ? SelectorKind.OPERATOR : SelectorKind.CALL;
    Selector selector =
        new Selector(kind, method.memberName, callStructure);
    return _buildInvokeSuper(method, selector, arguments, sourceInformation);
  }

  /// Create a read access of the [method] on the super class, i.e. a
  /// closurization of [method].
  ir.Primitive buildSuperMethodGet(MethodElement method,
                                   {SourceInformation sourceInformation}) {
    // TODO(johnniwinther): This should have its own ir node.
    return _buildInvokeSuper(
        method,
        new Selector.getter(method.memberName),
        const <ir.Primitive>[],
        sourceInformation);
  }

  /// Create a getter invocation of the [getter] on the super class.
  ir.Primitive buildSuperGetterGet(MethodElement getter,
                                   SourceInformation sourceInformation) {
    // TODO(johnniwinther): This should have its own ir node.
    return _buildInvokeSuper(
        getter,
        new Selector.getter(getter.memberName),
        const <ir.Primitive>[],
        sourceInformation);
  }

  /// Create an setter invocation of the [setter] on the super class with
  /// [value].
  ir.Primitive buildSuperSetterSet(MethodElement setter,
                                   ir.Primitive value,
                                   {SourceInformation sourceInformation}) {
    // TODO(johnniwinther): This should have its own ir node.
    _buildInvokeSuper(
        setter,
        new Selector.setter(setter.memberName),
        <ir.Primitive>[value],
        sourceInformation);
    return value;
  }

  /// Create an invocation of the index [method] on the super class with
  /// the provided [index].
  ir.Primitive buildSuperIndex(MethodElement method,
                               ir.Primitive index,
                               {SourceInformation sourceInformation}) {
    return _buildInvokeSuper(
        method, new Selector.index(), <ir.Primitive>[index],
        sourceInformation);
  }

  /// Create an invocation of the index set [method] on the super class with
  /// the provided [index] and [value].
  ir.Primitive buildSuperIndexSet(MethodElement method,
                                  ir.Primitive index,
                                  ir.Primitive value,
                                  {SourceInformation sourceInformation}) {
    _buildInvokeSuper(method, new Selector.indexSet(),
        <ir.Primitive>[index, value], sourceInformation);
    return value;
  }

  /// Create a dynamic invocation on [receiver] where the method name and
  /// argument structure are defined by [selector] and the argument values are
  /// defined by [arguments].
  ir.Primitive buildDynamicInvocation(ir.Primitive receiver,
                                      Selector selector,
                                      TypeMask mask,
                                      List<ir.Primitive> arguments,
                                      {SourceInformation sourceInformation}) {
    return _buildInvokeDynamic(
        receiver, selector, mask, arguments, sourceInformation);
  }

  /// Create a dynamic getter invocation on [receiver] where the getter name is
  /// defined by [selector].
  ir.Primitive buildDynamicGet(ir.Primitive receiver,
                               Selector selector,
                               TypeMask mask,
                               SourceInformation sourceInformation) {
    assert(selector.isGetter);
    FieldElement field = program.locateSingleField(selector, mask);
    if (field != null) {
      // If the world says this resolves to a unique field, then it MUST be
      // treated as a field access, since the getter might not be emitted.
      return buildFieldGet(receiver, field);
    } else {
      return _buildInvokeDynamic(
          receiver, selector, mask, const <ir.Primitive>[], sourceInformation);
    }
  }

  /// Create a dynamic setter invocation on [receiver] where the setter name and
  /// argument are defined by [selector] and [value], respectively.
  ir.Primitive buildDynamicSet(ir.Primitive receiver,
                               Selector selector,
                               TypeMask mask,
                               ir.Primitive value,
                               {SourceInformation sourceInformation}) {
    assert(selector.isSetter);
    FieldElement field = program.locateSingleField(selector, mask);
    if (field != null) {
      // If the world says this resolves to a unique field, then it MUST be
      // treated as a field access, since the setter might not be emitted.
      buildFieldSet(receiver, field, value);
    } else {
      _buildInvokeDynamic(receiver, selector, mask, <ir.Primitive>[value],
                          sourceInformation);
    }
    return value;
  }

  /// Create a dynamic index set invocation on [receiver] with the provided
  /// [index] and [value].
  ir.Primitive buildDynamicIndexSet(ir.Primitive receiver,
                                    TypeMask mask,
                                    ir.Primitive index,
                                    ir.Primitive value,
                                    {SourceInformation sourceInformation}) {
    _buildInvokeDynamic(
        receiver, new Selector.indexSet(), mask, <ir.Primitive>[index, value],
        sourceInformation);
    return value;
  }

  /// Create an invocation of the local [function] where argument structure is
  /// defined by [callStructure] and the argument values are defined by
  /// [arguments].
  ir.Primitive buildLocalFunctionInvocation(
      LocalFunctionElement function,
      CallStructure callStructure,
      List<ir.Primitive> arguments,
      SourceInformation sourceInformation) {
    // TODO(johnniwinther): Maybe this should have its own ir node.
    return buildCallInvocation(
        buildLocalGet(function), callStructure, arguments,
        sourceInformation: sourceInformation);
  }

  /// Create a static invocation of [function].
  ///
  /// The arguments are not named and their values are defined by [arguments].
  ir.Primitive buildStaticFunctionInvocation(
      MethodElement function,
      List<ir.Primitive> arguments,
      {SourceInformation sourceInformation}) {
    Selector selector = new Selector.call(
        function.memberName, new CallStructure(arguments.length));
    return buildInvokeStatic(function, selector, arguments, sourceInformation);
  }

  /// Create a getter invocation of the static [getter].
  ir.Primitive buildStaticGetterGet(MethodElement getter,
                                    SourceInformation sourceInformation) {
    Selector selector = new Selector.getter(getter.memberName);
    return buildInvokeStatic(
        getter, selector, const <ir.Primitive>[], sourceInformation);
  }

  /// Create a write access to the static [field] with the [value].
  ir.Primitive buildStaticFieldSet(FieldElement field,
                                   ir.Primitive value,
                                   [SourceInformation sourceInformation]) {
    addPrimitive(new ir.SetStatic(field, value, sourceInformation));
    return value;
  }

  /// Create a setter invocation of the static [setter] with the [value].
  ir.Primitive buildStaticSetterSet(MethodElement setter,
                                    ir.Primitive value,
                                    {SourceInformation sourceInformation}) {
    Selector selector = new Selector.setter(setter.memberName);
    buildInvokeStatic(
        setter, selector, <ir.Primitive>[value], sourceInformation);
    return value;
  }

  /// Create an erroneous invocation where argument structure is defined by
  /// [selector] and the argument values are defined by [arguments].
  // TODO(johnniwinther): Make this more fine-grained.
  ir.Primitive buildErroneousInvocation(
      Element element,
      Selector selector,
      List<ir.Primitive> arguments) {
    // TODO(johnniwinther): This should have its own ir node.
    return buildInvokeStatic(element, selector, arguments, null);
  }

  /// Concatenate string values.  The arguments must be strings.
  ir.Primitive buildStringConcatenation(List<ir.Primitive> arguments,
                                        {SourceInformation sourceInformation}) {
    assert(isOpen);
    return addPrimitive(new ir.ApplyBuiltinOperator(
        ir.BuiltinOperator.StringConcatenate,
        arguments,
        sourceInformation));
  }

  /// Create an invocation of the `call` method of [functionExpression], where
  /// the structure of arguments are given by [callStructure].
  // TODO(johnniwinther): This should take a [TypeMask].
  ir.Primitive buildCallInvocation(
      ir.Primitive functionExpression,
      CallStructure callStructure,
      List<ir.Definition> arguments,
      {SourceInformation sourceInformation}) {
    return _buildInvokeCall(functionExpression, callStructure, null, arguments,
        sourceInformation: sourceInformation);
  }

  /// Creates an if-then-else statement with the provided [condition] where the
  /// then and else branches are created through the [buildThenPart] and
  /// [buildElsePart] functions, respectively.
  ///
  /// An if-then statement is created if [buildElsePart] is a no-op.
  // TODO(johnniwinther): Unify implementation with [buildConditional] and
  // [_buildLogicalOperator].
  void buildIf(ir.Primitive condition,
               void buildThenPart(IrBuilder builder),
               void buildElsePart(IrBuilder builder)) {
    assert(isOpen);

    // The then and else parts are delimited.
    IrBuilder thenBuilder = makeDelimitedBuilder();
    IrBuilder elseBuilder = makeDelimitedBuilder();
    buildThenPart(thenBuilder);
    buildElsePart(elseBuilder);

    // Build the term
    // (Result =) let cont then() = [[thenPart]]
    //                 and else() = [[elsePart]]
    //            in
    //              if condition (then, else)
    ir.Continuation thenContinuation = new ir.Continuation([]);
    ir.Continuation elseContinuation = new ir.Continuation([]);
    // If exactly one of the then and else continuation bodies is open (i.e.,
    // the other one has an exit on all paths), then Continuation.plug expects
    // that continuation to be listed first.  Arbitrarily use [then, else]
    // order otherwise.
    List<ir.Continuation> arms = !thenBuilder.isOpen && elseBuilder.isOpen
        ? <ir.Continuation>[elseContinuation, thenContinuation]
        : <ir.Continuation>[thenContinuation, elseContinuation];

    ir.Expression result =
        new ir.LetCont.many(arms,
            new ir.Branch.strict(condition,
                                 thenContinuation,
                                 elseContinuation));

    JumpCollector join;  // Null if there is no join.
    if (thenBuilder.isOpen && elseBuilder.isOpen) {
      // There is a join-point continuation.  Build the term
      // 'let cont join(x, ...) = [] in Result' and plug invocations of the
      // join-point continuation into the then and else continuations.
      join = new ForwardJumpCollector(environment);
      thenBuilder.jumpTo(join);
      elseBuilder.jumpTo(join);
      result = new ir.LetCont(join.continuation, result);
    }

    // The then or else term root could be null, but not both.  If there is
    // a join then an InvokeContinuation was just added to both of them.  If
    // there is no join, then at least one of them is closed and thus has a
    // non-null root by the definition of the predicate isClosed.  In the
    // case that one of them is null, it must be the only one that is open
    // and thus contains the new hole in the context.  This case is handled
    // after the branch is plugged into the current hole.
    thenContinuation.body = thenBuilder._root;
    elseContinuation.body = elseBuilder._root;

    add(result);
    if (join == null) {
      // At least one subexpression is closed.
      if (thenBuilder.isOpen) {
        if (thenBuilder._root != null) _current = thenBuilder._current;
        environment = thenBuilder.environment;
      } else if (elseBuilder.isOpen) {
        if (elseBuilder._root != null) _current = elseBuilder._current;
        environment = elseBuilder.environment;
      } else {
        _current = null;
      }
    } else {
      environment = join.environment;
    }
  }

  void jumpTo(JumpCollector collector,
      [ir.Primitive value, SourceInformation sourceInformation]) {
    collector.addJump(this, value, sourceInformation);
  }

  void addRecursiveContinuation(BackwardJumpCollector collector) {
    assert(environment.length == collector.environment.length);
    add(new ir.LetCont(collector.continuation,
            new ir.InvokeContinuation(collector.continuation,
                                      environment.index2value)));
    environment = collector.environment;
  }

  /// Creates a for loop in which the initializer, condition, body, update are
  /// created by [buildInitializer], [buildCondition], [buildBody] and
  /// [buildUpdate], respectively.
  ///
  /// The jump [target] is used to identify which `break` and `continue`
  /// statements that have this `for` statement as their target.
  ///
  /// The [closureScope] identifies variables that should be boxed in this loop.
  /// This includes variables declared inside the body of the loop as well as
  /// in the for-loop initializer.
  ///
  /// [loopVariables] is the list of variables declared in the for-loop
  /// initializer.
  void buildFor({SubbuildFunction buildInitializer,
                 SubbuildFunction buildCondition,
                 SubbuildFunction buildBody,
                 SubbuildFunction buildUpdate,
                 JumpTarget target,
                 ClosureScope closureScope,
                 List<LocalElement> loopVariables}) {
    assert(isOpen);

    // For loops use four named continuations: the entry to the condition,
    // the entry to the body, the loop exit, and the loop successor (break).
    // The CPS translation of
    // [[for (initializer; condition; update) body; successor]] is:
    //
    // _enterForLoopInitializer();
    // [[initializer]];
    // let cont loop(x, ...) =
    //     let prim cond = [[condition]] in
    //     let cont break(x, ...) = [[successor]] in
    //     let cont exit() = break(v, ...) in
    //     let cont body() =
    //         _enterForLoopBody();
    //         let cont continue(x, ...) =
    //             _enterForLoopUpdate();
    //             [[update]];
    //             loop(v, ...) in
    //         [[body]];
    //         continue(v, ...) in
    //     branch cond (body, exit) in
    // loop(v, ...)
    //
    // If there are no breaks in the body, the break continuation is inlined
    // in the exit continuation (i.e., the translation of the successor
    // statement occurs in the exit continuation).  If there is only one
    // invocation of the continue continuation (i.e., no continues in the
    // body), the continue continuation is inlined in the body.
    _enterForLoopInitializer(closureScope, loopVariables);
    buildInitializer(this);

    JumpCollector loop = new BackwardJumpCollector(environment);
    addRecursiveContinuation(loop);

    ir.Primitive condition = buildCondition(this);
    if (condition == null) {
      // If the condition is empty then the body is entered unconditionally.
      condition = buildBooleanConstant(true);
    }
    JumpCollector breakCollector =
        new ForwardJumpCollector(environment, target: target);

    // Use a pair of builders for the body, one for the entry code if any
    // and one for the body itself.  We only decide whether to insert a
    // continue continuation until after translating the body and there is no
    // way to insert such a continuation between the entry code and the body
    // if they are translated together.
    IrBuilder outerBodyBuilder = makeDelimitedBuilder();
    outerBodyBuilder._enterForLoopBody(closureScope, loopVariables);
    JumpCollector continueCollector =
        new ForwardJumpCollector(outerBodyBuilder.environment, target: target);

    IrBuilder innerBodyBuilder = outerBodyBuilder.makeDelimitedBuilder();
    state.breakCollectors.add(breakCollector);
    state.continueCollectors.add(continueCollector);
    buildBody(innerBodyBuilder);
    assert(state.breakCollectors.last == breakCollector);
    assert(state.continueCollectors.last == continueCollector);
    state.breakCollectors.removeLast();
    state.continueCollectors.removeLast();

    // The binding of the continue continuation should occur as late as
    // possible, that is, at the nearest common ancestor of all the continue
    // sites in the body.  However, that is difficult to compute here, so it
    // is instead placed just outside the translation of the loop body.  In
    // the case where there are no continues in the body, the updates are
    // translated immediately after the body.
    bool hasContinues = !continueCollector.isEmpty;
    IrBuilder updateBuilder;
    if (hasContinues) {
      if (innerBodyBuilder.isOpen) innerBodyBuilder.jumpTo(continueCollector);
      updateBuilder = makeDelimitedBuilder(continueCollector.environment);
    } else {
      updateBuilder = innerBodyBuilder;
    }
    updateBuilder._enterForLoopUpdate(closureScope, loopVariables);
    buildUpdate(updateBuilder);
    if (updateBuilder.isOpen) updateBuilder.jumpTo(loop);
    // Connect the inner and outer body builders.  This is done only after
    // it is guaranteed that the updateBuilder has a non-empty term.
    if (hasContinues) {
      outerBodyBuilder.add(new ir.LetCont(continueCollector.continuation,
          innerBodyBuilder._root));
      continueCollector.continuation.body = updateBuilder._root;
    } else {
      outerBodyBuilder.add(innerBodyBuilder._root);
    }

    // Create loop exit and body entry continuations and a branch to them.
    ir.Continuation exitContinuation = new ir.Continuation([]);
    ir.Continuation bodyContinuation = new ir.Continuation([]);
    bodyContinuation.body = outerBodyBuilder._root;
    // Note the order of continuations: the first one is the one that will
    // be filled by LetCont.plug.
    ir.LetCont branch =
        new ir.LetCont.two(exitContinuation, bodyContinuation,
            new ir.Branch.strict(condition,
                                 bodyContinuation,
                                 exitContinuation));
    // If there are breaks in the body, then there must be a join-point
    // continuation for the normal exit and the breaks.  Otherwise, the
    // successor is translated in the hole in the exit continuation.
    bool hasBreaks = !breakCollector.isEmpty;
    ir.LetCont letBreak;
    if (hasBreaks) {
      IrBuilder exitBuilder = makeDelimitedBuilder();
      exitBuilder.jumpTo(breakCollector);
      exitContinuation.body = exitBuilder._root;
      letBreak = new ir.LetCont(breakCollector.continuation, branch);
      add(letBreak);
      environment = breakCollector.environment;
    } else {
      add(branch);
    }
  }

  /// Creates a for-in loop, `for (v in e) b`.
  ///
  /// [buildExpression] creates the expression, `e`. The variable, `v`, can
  /// take one of three forms:
  ///     1) `v` can be declared within the for-in statement, like in
  ///        `for (var v in e)`, in which case, [buildVariableDeclaration]
  ///        creates its declaration and [variableElement] is the element for
  ///        the declared variable,
  ///     2) `v` is predeclared statically known variable, that is top-level,
  ///        static, or local variable, in which case [variableElement] is the
  ///        variable element, and [variableSelector] defines its write access,
  ///     3) `v` is an instance variable in which case [variableSelector]
  ///        defines its write access.
  /// [buildBody] creates the body, `b`, of the loop. The jump [target] is used
  /// to identify which `break` and `continue` statements that have this for-in
  /// statement as their target.
  void buildForIn({SubbuildFunction buildExpression,
                   SubbuildFunction buildVariableDeclaration,
                   Element variableElement,
                   Selector variableSelector,
                   TypeMask variableMask,
                   TypeMask currentMask,
                   TypeMask iteratorMask,
                   TypeMask moveNextMask,
                   SubbuildFunction buildBody,
                   JumpTarget target,
                   ClosureScope closureScope}) {
    // The for-in loop
    //
    // for (a in e) s;
    //
    // Is compiled analogously to:
    //
    // it = e.iterator;
    // while (it.moveNext()) {
    //   var a = it.current;
    //   s;
    // }

    // Fill the current hole with:
    // let prim expressionReceiver = [[e]] in
    // let cont iteratorInvoked(iterator) =
    //     [ ]
    // in expressionReceiver.iterator () iteratorInvoked
    ir.Primitive expressionReceiver = buildExpression(this);
    List<ir.Primitive> emptyArguments = <ir.Primitive>[];
    ir.Primitive iterator = addPrimitive(
        new ir.InvokeMethod(expressionReceiver,
            Selectors.iterator,
            iteratorMask,
            emptyArguments));

    // Fill with:
    // let cont loop(x, ...) =
    //     let cont moveNextInvoked(condition) =
    //         [ ]
    //     in iterator.moveNext () moveNextInvoked
    // in loop(v, ...)
    JumpCollector loop = new BackwardJumpCollector(environment, target: target);
    addRecursiveContinuation(loop);
    ir.Primitive condition = addPrimitive(
        new ir.InvokeMethod(iterator,
            Selectors.moveNext,
            moveNextMask,
            emptyArguments));

    // As a delimited term, build:
    // <<BODY>> =
    //   _enterScope();
    //   [[variableDeclaration]]
    //   let cont currentInvoked(currentValue) =
    //       [[a = currentValue]];
    //       [ ]
    //   in iterator.current () currentInvoked
    IrBuilder bodyBuilder = makeDelimitedBuilder();
    bodyBuilder._enterScope(closureScope);
    if (buildVariableDeclaration != null) {
      buildVariableDeclaration(bodyBuilder);
    }
    ir.Primitive currentValue = bodyBuilder.addPrimitive(
        new ir.InvokeMethod(
            iterator,
            Selectors.current,
            currentMask,
            emptyArguments));
    // TODO(johnniwinther): Extract this as a provided strategy.
    if (Elements.isLocal(variableElement)) {
      bodyBuilder.buildLocalVariableSet(variableElement, currentValue);
    } else if (Elements.isError(variableElement) ||
               Elements.isMalformed(variableElement)) {
      Selector selector = new Selector.setter(
          new Name(variableElement.name, variableElement.library));
      List<ir.Primitive> value = <ir.Primitive>[currentValue];
      // Note the order of the comparisons below.  It can be the case that an
      // element isError and isMalformed.
      if (Elements.isError(variableElement)) {
        bodyBuilder.buildStaticNoSuchMethod(selector, value);
      } else {
        bodyBuilder.buildErroneousInvocation(variableElement, selector, value);
      }
    } else if (Elements.isStaticOrTopLevel(variableElement)) {
      if (variableElement.isField) {
        bodyBuilder.addPrimitive(
            new ir.SetStatic(variableElement, currentValue));
      } else {
        bodyBuilder.buildStaticSetterSet(variableElement, currentValue);
      }
    } else {
      ir.Primitive receiver = bodyBuilder.buildThis();
      assert(receiver != null);
      bodyBuilder.buildDynamicSet(
          receiver, variableSelector, variableMask, currentValue);
    }

    // Translate the body in the hole in the delimited term above, and add
    // a jump to the loop if control flow is live after the body.
    JumpCollector breakCollector =
        new ForwardJumpCollector(environment, target: target);
    state.breakCollectors.add(breakCollector);
    state.continueCollectors.add(loop);
    buildBody(bodyBuilder);
    assert(state.breakCollectors.last == breakCollector);
    assert(state.continueCollectors.last == loop);
    state.breakCollectors.removeLast();
    state.continueCollectors.removeLast();
    if (bodyBuilder.isOpen) bodyBuilder.jumpTo(loop);

    // Create body entry and loop exit continuations and a branch to them.
    //
    // let cont exit() = [ ]
    //      and body() = <<BODY>>
    // in branch condition (body, exit)
    ir.Continuation exitContinuation = new ir.Continuation([]);
    ir.Continuation bodyContinuation = new ir.Continuation([]);
    bodyContinuation.body = bodyBuilder._root;
    // Note the order of continuations: the first one is the one that will
    // be filled by LetCont.plug.
    ir.LetCont branch =
        new ir.LetCont.two(exitContinuation, bodyContinuation,
            new ir.Branch.strict(condition,
                                 bodyContinuation,
                                 exitContinuation));
    // If there are breaks in the body, then there must be a join-point
    // continuation for the normal exit and the breaks.  Otherwise, the
    // successor is translated in the hole in the exit continuation.
    bool hasBreaks = !breakCollector.isEmpty;
    ir.LetCont letBreak;
    if (hasBreaks) {
      IrBuilder exitBuilder = makeDelimitedBuilder();
      exitBuilder.jumpTo(breakCollector);
      exitContinuation.body = exitBuilder._root;
      letBreak = new ir.LetCont(breakCollector.continuation, branch);
      add(letBreak);
      environment = breakCollector.environment;
    } else {
      add(branch);
    }
  }

  /// Creates a while loop in which the condition and body are created by
  /// [buildCondition] and [buildBody], respectively.
  ///
  /// The jump [target] is used to identify which `break` and `continue`
  /// statements that have this `while` statement as their target.
  void buildWhile({SubbuildFunction buildCondition,
                   SubbuildFunction buildBody,
                   JumpTarget target,
                   ClosureScope closureScope}) {
    assert(isOpen);
    // While loops use four named continuations: the entry to the body, the
    // loop exit, the loop back edge (continue), and the loop exit (break).
    // The CPS translation of [[while (condition) body; successor]] is:
    //
    // let cont continue(x, ...) =
    //     let prim cond = [[condition]] in
    //     let cont break(x, ...) = [[successor]] in
    //     let cont exit() = break(v, ...)
    //          and body() =
    //                _enterScope();
    //                [[body]];
    //                continue(v, ...)
    //     in branch cond (body, exit)
    // in continue(v, ...)
    //
    // If there are no breaks in the body, the break continuation is inlined
    // in the exit continuation (i.e., the translation of the successor
    // statement occurs in the exit continuation).
    JumpCollector loop = new BackwardJumpCollector(environment, target: target);
    addRecursiveContinuation(loop);

    ir.Primitive condition = buildCondition(this);

    JumpCollector breakCollector =
        new ForwardJumpCollector(environment, target: target);

    IrBuilder bodyBuilder = makeDelimitedBuilder();
    bodyBuilder._enterScope(closureScope);
    state.breakCollectors.add(breakCollector);
    state.continueCollectors.add(loop);
    buildBody(bodyBuilder);
    assert(state.breakCollectors.last == breakCollector);
    assert(state.continueCollectors.last == loop);
    state.breakCollectors.removeLast();
    state.continueCollectors.removeLast();
    if (bodyBuilder.isOpen) bodyBuilder.jumpTo(loop);

    // Create body entry and loop exit continuations and a branch to them.
    ir.Continuation exitContinuation = new ir.Continuation([]);
    ir.Continuation bodyContinuation = new ir.Continuation([]);
    bodyContinuation.body = bodyBuilder._root;
    // Note the order of continuations: the first one is the one that will
    // be filled by LetCont.plug.
    ir.LetCont branch =
        new ir.LetCont.two(exitContinuation, bodyContinuation,
            new ir.Branch.strict(condition,
                                 bodyContinuation,
                                 exitContinuation));
    // If there are breaks in the body, then there must be a join-point
    // continuation for the normal exit and the breaks.  Otherwise, the
    // successor is translated in the hole in the exit continuation.
    bool hasBreaks = !breakCollector.isEmpty;
    ir.LetCont letBreak;
    if (hasBreaks) {
      IrBuilder exitBuilder = makeDelimitedBuilder();
      exitBuilder.jumpTo(breakCollector);
      exitContinuation.body = exitBuilder._root;
      letBreak = new ir.LetCont(breakCollector.continuation, branch);
      add(letBreak);
      environment = breakCollector.environment;
    } else {
      add(branch);
    }
  }


  /// Creates a do-while loop.
  ///
  /// The body and condition are created by [buildBody] and [buildCondition].
  /// The jump target [target] is the target of `break` and `continue`
  /// statements in the body that have the loop as their target.
  /// [closureScope] contains all the variables declared in the loop (but not
  /// declared in some inner closure scope).
  void buildDoWhile({SubbuildFunction buildBody,
                     SubbuildFunction buildCondition,
                     JumpTarget target,
                     ClosureScope closureScope}) {
    assert(isOpen);
    // The CPS translation of [[do body; while (condition); successor]] is:
    //
    // let cont break(x, ...) = [[successor]] in
    // let cont rec loop(x, ...) =
    //   let cont continue(x, ...) =
    //     let prim cond = [[condition]] in
    //       let cont exit() = break(v, ...)
    //            and repeat() = loop(v, ...)
    //       in branch cond (repeat, exit)
    //   in [[body]]; continue(v, ...)
    // in loop(v, ...)
    IrBuilder loopBuilder = makeDelimitedBuilder();
    JumpCollector loop =
        new BackwardJumpCollector(loopBuilder.environment, target: target);
    loopBuilder.addRecursiveContinuation(loop);

    // Translate the body.
    JumpCollector breakCollector =
        new ForwardJumpCollector(environment, target: target);
    JumpCollector continueCollector =
        new ForwardJumpCollector(loopBuilder.environment, target: target);
    IrBuilder bodyBuilder = loopBuilder.makeDelimitedBuilder();
    bodyBuilder._enterScope(closureScope);
    state.breakCollectors.add(breakCollector);
    state.continueCollectors.add(continueCollector);
    buildBody(bodyBuilder);
    assert(state.breakCollectors.last == breakCollector);
    assert(state.continueCollectors.last == continueCollector);
    state.breakCollectors.removeLast();
    state.continueCollectors.removeLast();
    if (bodyBuilder.isOpen) bodyBuilder.jumpTo(continueCollector);

    // Construct the body of the continue continuation (i.e., the condition).
    // <Continue> =
    // let prim cond = [[condition]] in
    //   let cont exit() = break(v, ...)
    //        and repeat() = loop(v, ...)
    //   in branch cond (repeat, exit)
    IrBuilder continueBuilder = loopBuilder.makeDelimitedBuilder();
    continueBuilder.environment = continueCollector.environment;
    ir.Primitive condition = buildCondition(continueBuilder);

    ir.Continuation exitContinuation = new ir.Continuation([]);
    IrBuilder exitBuilder = continueBuilder.makeDelimitedBuilder();
    exitBuilder.jumpTo(breakCollector);
    exitContinuation.body = exitBuilder._root;
    ir.Continuation repeatContinuation = new ir.Continuation([]);
    IrBuilder repeatBuilder = continueBuilder.makeDelimitedBuilder();
    repeatBuilder.jumpTo(loop);
    repeatContinuation.body = repeatBuilder._root;

    continueBuilder.add(
        new ir.LetCont.two(exitContinuation, repeatContinuation,
            new ir.Branch.strict(condition,
                                 repeatContinuation,
                                 exitContinuation)));
    continueCollector.continuation.body = continueBuilder._root;

    // Construct the loop continuation (i.e., the body and condition).
    // <Loop> =
    // let cont continue(x, ...) =
    //   <Continue>
    // in [[body]]; continue(v, ...)
    loopBuilder.add(
        new ir.LetCont(continueCollector.continuation,
            bodyBuilder._root));

    // And tie it all together.
    add(new ir.LetCont(breakCollector.continuation, loopBuilder._root));
    environment = breakCollector.environment;
  }

  void buildSimpleSwitch(JumpTarget target,
                         ir.Primitive value,
                         List<SwitchCaseInfo> cases,
                         SwitchCaseInfo defaultCase,
                         Element error,
                         SourceInformation sourceInformation) {
    assert(isOpen);
    JumpCollector join = new ForwardJumpCollector(environment, target: target);

    IrBuilder casesBuilder = makeDelimitedBuilder();
    casesBuilder.state.breakCollectors.add(join);
    for (SwitchCaseInfo caseInfo in cases) {
      buildConditionsFrom(int index) => (IrBuilder builder) {
        ir.Primitive comparison = builder.buildIdentical(
            value, caseInfo.constants[index]);
        return (index == caseInfo.constants.length - 1)
            ? comparison
            : builder.buildLogicalOperator(
                comparison, buildConditionsFrom(index + 1), isLazyOr: true);
      };

      ir.Primitive condition = buildConditionsFrom(0)(casesBuilder);
      IrBuilder thenBuilder = makeDelimitedBuilder();
      caseInfo.buildBody(thenBuilder);
      if (thenBuilder.isOpen) {
        // It is a runtime error to reach the end of a switch case, unless
        // it is the last case.
        if (caseInfo == cases.last && defaultCase == null) {
          thenBuilder.jumpTo(join);
        } else {
          ir.Primitive exception = thenBuilder.buildInvokeStatic(
              error,
              new Selector.fromElement(error),
              <ir.Primitive>[],
              sourceInformation);
          thenBuilder.buildThrow(exception);
        }
      }

      ir.Continuation thenContinuation = new ir.Continuation([]);
      thenContinuation.body = thenBuilder._root;
      ir.Continuation elseContinuation = new ir.Continuation([]);
      // A LetCont.many term has a hole as the body of the first listed
      // continuation, to be plugged by the translation.  Therefore put the
      // else continuation first.
      casesBuilder.add(
          new ir.LetCont.two(elseContinuation, thenContinuation,
              new ir.Branch.strict(condition,
                                   thenContinuation,
                                   elseContinuation)));
    }

    if (defaultCase != null) {
      defaultCase.buildBody(casesBuilder);
    }
    if (casesBuilder.isOpen) casesBuilder.jumpTo(join);

    casesBuilder.state.breakCollectors.removeLast();

    if (!join.isEmpty) {
      add(new ir.LetCont(join.continuation, casesBuilder._root));
      environment = join.environment;
    } else if (casesBuilder._root != null) {
      add(casesBuilder._root);
      _current = casesBuilder._current;
      environment = casesBuilder.environment;
    } else {
      // The translation of the cases did not emit any code.
    }
  }

  /// Utility function to translate try/catch into the IR.
  ///
  /// The translation treats try/finally and try/catch/finally as if they
  /// were macro-expanded into try/catch.  This utility function generates
  /// that try/catch.  The function is parameterized over a list of variables
  /// that should be boxed on entry to the try, and over functions to emit
  /// code for entering the try, building the try body, leaving the try body,
  /// building the catch body, and leaving the entire try/catch.
  ///
  /// Please see the function's implementation for where these functions are
  /// called.
  void _helpBuildTryCatch(TryStatementInfo variables,
      void enterTry(IrBuilder builder),
      SubbuildFunction buildTryBlock,
      void leaveTry(IrBuilder builder),
      List<ir.Parameter> buildCatch(IrBuilder builder, JumpCollector join),
      void leaveTryCatch(IrBuilder builder, JumpCollector join,
          ir.Expression body)) {
    JumpCollector join = new ForwardJumpCollector(environment);
    IrBuilder tryCatchBuilder = makeDelimitedBuilder();

    // Variables treated as mutable in a try are not mutable outside of it.
    // Work with a copy of the outer builder's mutable variables.
    tryCatchBuilder.mutableVariables =
        new Map<Local, ir.MutableVariable>.from(mutableVariables);
    for (LocalVariableElement variable in variables.boxedOnEntry) {
      assert(!tryCatchBuilder.isInMutableVariable(variable));
      ir.Primitive value = tryCatchBuilder.buildLocalGet(variable);
      tryCatchBuilder.makeMutableVariable(variable);
      tryCatchBuilder.declareLocalVariable(variable, initialValue: value);
    }

    IrBuilder tryBuilder = tryCatchBuilder.makeDelimitedBuilder();
    enterTry(tryBuilder);
    buildTryBlock(tryBuilder);
    if (tryBuilder.isOpen) {
      join.enterTry(variables.boxedOnEntry);
      tryBuilder.jumpTo(join);
      join.leaveTry();
    }
    leaveTry(tryBuilder);

    IrBuilder catchBuilder = tryCatchBuilder.makeDelimitedBuilder();
    for (LocalVariableElement variable in variables.boxedOnEntry) {
      assert(catchBuilder.isInMutableVariable(variable));
      ir.Primitive value = catchBuilder.buildLocalGet(variable);
      // After this point, the variables that were boxed on entry to the try
      // are no longer treated as mutable.
      catchBuilder.removeMutableVariable(variable);
      catchBuilder.environment.update(variable, value);
    }

    List<ir.Parameter> catchParameters = buildCatch(catchBuilder, join);
    ir.Continuation catchContinuation = new ir.Continuation(catchParameters);
    catchContinuation.body = catchBuilder._root;
    tryCatchBuilder.add(
        new ir.LetHandler(catchContinuation, tryBuilder._root));

    leaveTryCatch(this, join, tryCatchBuilder._root);
  }

  /// Translates a try/catch.
  ///
  /// [variables] provides information on local variables declared and boxed
  /// within the try body.
  /// [buildTryBlock] builds the try block.
  /// [catchClauseInfos] provides access to the catch type, exception variable,
  /// and stack trace variable, and a function for building the catch block.
  void buildTryCatch(TryStatementInfo variables,
                     SubbuildFunction buildTryBlock,
                     List<CatchClauseInfo> catchClauseInfos) {
    assert(isOpen);
    // Catch handlers are in scope for their body.  The CPS translation of
    // [[try tryBlock catch (ex, st) catchBlock; successor]] is:
    //
    // let cont join(v0, v1, ...) = [[successor]] in
    //   let mutable m0 = x0 in
    //     let mutable m1 = x1 in
    //       ...
    //       let handler catch_(ex, st) =
    //         let prim p0 = GetMutable(m0) in
    //           let prim p1 = GetMutable(m1) in
    //             ...
    //             [[catchBlock]]
    //             join(p0, p1, ...)
    //       in
    //         [[tryBlock]]
    //         let prim p0' = GetMutable(m0) in
    //           let prim p1' = GetMutable(m1) in
    //             ...
    //             join(p0', p1', ...)
    //
    // In other words, both the try and catch block are in the scope of the
    // join-point continuation, and they are both in the scope of a sequence
    // of mutable bindings for the variables assigned in the try.  The join-
    // point continuation is not in the scope of these mutable bindings.
    // The tryBlock is in the scope of a binding for the catch handler.  Each
    // instruction (specifically, each call) in the tryBlock is in the dynamic
    // scope of the handler.  The mutable bindings are dereferenced at the end
    // of the try block and at the beginning of the catch block, so the
    // variables are unboxed in the catch block and at the join point.

    void enterTry(IrBuilder builder) {
      // On entry to try of try/catch, update the builder's state to reflect the
      // variables that have been boxed.
      void interceptJump(JumpCollector collector) {
        collector.enterTry(variables.boxedOnEntry);
      }
      builder.state.breakCollectors.forEach(interceptJump);
      builder.state.continueCollectors.forEach(interceptJump);
      interceptJump(builder.state.returnCollector);
    }

    void leaveTry(IrBuilder builder) {
      // On exit from try of try/catch, update the builder's state to reflect
      // the variables that are no longer boxed.
      void restoreJump(JumpCollector collector) {
        collector.leaveTry();
      }
      builder.state.breakCollectors.forEach(restoreJump);
      builder.state.continueCollectors.forEach(restoreJump);
      restoreJump(builder.state.returnCollector);
    }

    List<ir.Parameter> buildCatch(IrBuilder builder,
                                  JumpCollector join) {
      // Translate the catch clauses.  Multiple clauses are translated as if
      // they were explicitly cascaded if/else type tests.

      // Handlers are always translated as having both exception and stack trace
      // parameters.  Multiple clauses do not have to use the same names for
      // them.  Choose the first of each as the name hint for the respective
      // handler parameter.
      ir.Parameter exceptionParameter =
          new ir.Parameter(catchClauseInfos.first.exceptionVariable);
      LocalVariableElement traceVariable;
      CatchClauseInfo catchAll;
      for (int i = 0; i < catchClauseInfos.length; ++i) {
        CatchClauseInfo info = catchClauseInfos[i];
        if (info.type == null) {
          catchAll = info;
          catchClauseInfos.length = i;
          break;
        }
        if (traceVariable == null) {
          traceVariable = info.stackTraceVariable;
        }
      }
      ir.Parameter traceParameter = new ir.Parameter(traceVariable);

      ir.Expression buildCatchClause(CatchClauseInfo clause) {
        IrBuilder clauseBuilder = builder.makeDelimitedBuilder();
        if (clause.exceptionVariable != null) {
          clauseBuilder.declareLocalVariable(clause.exceptionVariable,
              initialValue: exceptionParameter);
        }
        if (clause.stackTraceVariable != null) {
          clauseBuilder.declareLocalVariable(clause.stackTraceVariable,
              initialValue: traceParameter);
        }
        clause.buildCatchBlock(clauseBuilder);
        if (clauseBuilder.isOpen) clauseBuilder.jumpTo(join);
        return clauseBuilder._root;
      }

      // Expand multiple catch clauses into an explicit if/then/else.  Iterate
      // them in reverse so the current block becomes the next else block.
      ir.Expression catchBody = (catchAll == null)
          ? new ir.Rethrow()
          : buildCatchClause(catchAll);
      for (CatchClauseInfo clause in catchClauseInfos.reversed) {
        ir.Continuation thenContinuation = new ir.Continuation([]);
        ir.Continuation elseContinuation = new ir.Continuation([]);
        thenContinuation.body = buildCatchClause(clause);
        elseContinuation.body = catchBody;

        // Build the type test guarding this clause. We can share the
        // environment with the nested builder because this part cannot mutate
        // it.
        IrBuilder checkBuilder = builder.makeDelimitedBuilder(environment);
        ir.Primitive typeMatches =
            checkBuilder.buildTypeOperator(exceptionParameter,
                clause.type,
                isTypeTest: true);
        checkBuilder.add(new ir.LetCont.two(thenContinuation, elseContinuation,
            new ir.Branch.strict(typeMatches,
                                 thenContinuation,
                                 elseContinuation)));
        catchBody = checkBuilder._root;
      }
      builder.add(catchBody);

      return <ir.Parameter>[exceptionParameter, traceParameter];
    }

    void leaveTryCatch(IrBuilder builder, JumpCollector join,
                       ir.Expression body) {
      // Add the binding for the join-point continuation and continue the
      // translation in its body.
      builder.add(new ir.LetCont(join.continuation, body));
      builder.environment = join.environment;
    }

    _helpBuildTryCatch(variables, enterTry, buildTryBlock, leaveTry,
        buildCatch, leaveTryCatch);
  }

  /// Translates a try/finally.
  ///
  /// [variables] provides information on local variables declared and boxed
  /// within the try body.
  /// [buildTryBlock] builds the try block.
  /// [buildFinallyBlock] builds the finally block.
  void buildTryFinally(TryStatementInfo variables,
                       SubbuildFunction buildTryBlock,
                       SubbuildFunction buildFinallyBlock) {
    assert(isOpen);
    // Try/finally is implemented in terms of try/catch and by duplicating the
    // code for finally at all exits.  The encoding is:
    //
    // try tryBlock finally finallyBlock
    // ==>
    // try tryBlock catch (ex, st) { finallyBlock; rethrow } finallyBlock
    //
    // Where in tryBlock, all of the break, continue, and return exits are
    // translated as jumps to continuations (bound outside the catch handler)
    // that include the finally code followed by a break, continue, or
    // return respectively.

    List<JumpCollector> savedBreaks, newBreaks, savedContinues, newContinues;
    JumpCollector savedReturn, newReturn;
    void enterTry(IrBuilder builder) {
      // On entry to the try of try/finally, update the builder's state to
      // relfect the variables that have been boxed.  Then intercept all break,
      // continue, and return jumps out of the try so that they can go to
      // continuations that include the finally code.
      JumpCollector interceptJump(JumpCollector collector) {
        JumpCollector result =
            new ForwardJumpCollector(environment, target: collector.target);
        result.enterTry(variables.boxedOnEntry);
        return result;
      }
      savedBreaks = builder.state.breakCollectors;
      savedContinues = builder.state.continueCollectors;
      savedReturn = builder.state.returnCollector;

      builder.state.breakCollectors = newBreaks =
          savedBreaks.map(interceptJump).toList();
      builder.state.continueCollectors = newContinues =
          savedContinues.map(interceptJump).toList();
      builder.state.returnCollector = newReturn =
          new ForwardJumpCollector(environment, hasExtraArgument: true)
              ..enterTry(variables.boxedOnEntry);
    }

    void leaveTry(IrBuilder builder) {
      // On exit from the try of try/finally, update the builder's state to
      // reflect the variables that are no longer boxed and restore the
      // original, unintercepted break, continue, and return targets.
      void restoreJump(JumpCollector collector) {
        collector.leaveTry();
      }
      newBreaks.forEach(restoreJump);
      newContinues.forEach(restoreJump);
      newReturn.leaveTry();
      builder.state.breakCollectors = savedBreaks;
      builder.state.continueCollectors = savedContinues;
      builder.state.returnCollector = savedReturn;
    }

    List<ir.Parameter> buildCatch(IrBuilder builder,
                                  JumpCollector join) {
      // The catch block of the try/catch used for try/finally is the finally
      // code followed by a rethrow.
      buildFinallyBlock(builder);
      if (builder.isOpen) {
        builder.add(new ir.Rethrow());
        builder._current = null;
      }
      return <ir.Parameter>[new ir.Parameter(null), new ir.Parameter(null)];
    }

    void leaveTryCatch(IrBuilder builder, JumpCollector join,
                       ir.Expression body) {
      // Build a list of continuations for jumps from the try block and
      // duplicate the finally code before jumping to the actual target.
      List<ir.Continuation> exits = <ir.Continuation>[join.continuation];
      void addJump(JumpCollector newCollector,
                   JumpCollector originalCollector) {
        if (newCollector.isEmpty) return;
        IrBuilder builder = makeDelimitedBuilder(newCollector.environment);
        buildFinallyBlock(builder);
        if (builder.isOpen) builder.jumpTo(originalCollector);
        newCollector.continuation.body = builder._root;
        exits.add(newCollector.continuation);
      }
      for (int i = 0; i < newBreaks.length; ++i) {
        addJump(newBreaks[i], savedBreaks[i]);
      }
      for (int i = 0; i < newContinues.length; ++i) {
        addJump(newContinues[i], savedContinues[i]);
      }
      if (!newReturn.isEmpty) {
        IrBuilder builder = makeDelimitedBuilder(newReturn.environment);
        ir.Primitive value = builder.environment.discard(1);
        buildFinallyBlock(builder);
        if (builder.isOpen) builder.buildReturn(value: value);
        newReturn.continuation.body = builder._root;
        exits.add(newReturn.continuation);
      }
      builder.add(new ir.LetCont.many(exits, body));
      builder.environment = join.environment;
      buildFinallyBlock(builder);
    }

    _helpBuildTryCatch(variables, enterTry, buildTryBlock, leaveTry,
        buildCatch, leaveTryCatch);
  }

  /// Create a return statement `return value;` or `return;` if [value] is
  /// null.
  void buildReturn({ir.Primitive value, SourceInformation sourceInformation}) {
    // Build(Return(e), C) = C'[InvokeContinuation(return, x)]
    //   where (C', x) = Build(e, C)
    //
    // Return without a subexpression is translated as if it were return null.
    assert(isOpen);
    if (value == null) {
      value = buildNullConstant();
    }
    jumpTo(state.returnCollector, value, sourceInformation);
  }

  /// Generate the body for a native function [function] that is annotated with
  /// an implementation in JavaScript (provided as string in [javaScriptCode]).
  void buildNativeFunctionBody(FunctionElement function,
                               String javaScriptCode) {
    NativeBehavior behavior = new NativeBehavior();
    behavior.sideEffects.setAllSideEffects();
    // Generate a [ForeignCode] statement from the given native code.
    buildForeignCode(
        js.js.statementTemplateYielding(
            new js.LiteralStatement(javaScriptCode)),
        <ir.Primitive>[],
        behavior);
  }

  /// Generate the body for a native function that redirects to a native
  /// JavaScript function, getter, or setter.
  ///
  /// Generates a call to the real target, which is given by [functions]'s
  /// `fixedBackendName`, passing all parameters as arguments.  The target can
  /// be the JavaScript implementation of a function, getter, or setter.
  void buildRedirectingNativeFunctionBody(FunctionElement function,
                                          String name,
                                          SourceInformation source) {
    List<ir.Primitive> arguments = <ir.Primitive>[];
    NativeBehavior behavior = new NativeBehavior();
    behavior.sideEffects.setAllSideEffects();
    program.addNativeMethod(function);
    // Construct the access of the target element.
    String code = function.isInstanceMember ? '#.$name' : name;
    if (function.isInstanceMember) {
      arguments.add(state.thisParameter);
    }
    // Collect all parameters of the function and templates for them to be
    // inserted into the JavaScript code.
    List<String> argumentTemplates = <String>[];
    function.functionSignature.forEachParameter((ParameterElement parameter) {
      ir.Primitive input = environment.lookup(parameter);
      DartType type = program.unaliasType(parameter.type);
      if (type is FunctionType) {
        // The parameter type is a function type either directly or through
        // typedef(s).
        ir.Constant arity = buildIntegerConstant(type.computeArity());
        input = buildStaticFunctionInvocation(
            program.closureConverter, <ir.Primitive>[input, arity]);
      }
      arguments.add(input);
      argumentTemplates.add('#');
    });
    // Construct the application of parameters for functions and setters.
    if (function.kind == ElementKind.FUNCTION) {
      code = "$code(${argumentTemplates.join(', ')})";
    } else if (function.kind == ElementKind.SETTER) {
      code = "$code = ${argumentTemplates.single}";
    } else {
      assert(argumentTemplates.isEmpty);
      assert(function.kind == ElementKind.GETTER);
    }
    // Generate the [ForeignCode] expression and a return statement to return
    // its value.
    ir.Primitive value = buildForeignCode(
        js.js.uncachedExpressionTemplate(code),
        arguments,
        behavior);
    buildReturn(value: value, sourceInformation: source);
  }

  /// Create a blocks of [statements] by applying [build] to all reachable
  /// statements. The first statement is assumed to be reachable.
  // TODO(johnniwinther): Type [statements] as `Iterable` when `NodeList` uses
  // `List` instead of `Link`.
  void buildBlock(var statements, BuildFunction build) {
    // Build(Block(stamements), C) = C'
    //   where C' = statements.fold(Build, C)
    assert(isOpen);
    return buildSequence(statements, build);
  }

  /// Creates a sequence of [nodes] by applying [build] to all reachable nodes.
  ///
  /// The first node in the sequence does not need to be reachable.
  // TODO(johnniwinther): Type [nodes] as `Iterable` when `NodeList` uses
  // `List` instead of `Link`.
  void buildSequence(var nodes, BuildFunction build) {
    for (var node in nodes) {
      if (!isOpen) return;
      build(node);
    }
  }

  /// Creates a labeled statement
  void buildLabeledStatement({SubbuildFunction buildBody,
                              JumpTarget target}) {
    JumpCollector join = new ForwardJumpCollector(environment, target: target);
    IrBuilder innerBuilder = makeDelimitedBuilder();
    innerBuilder.state.breakCollectors.add(join);
    buildBody(innerBuilder);
    innerBuilder.state.breakCollectors.removeLast();
    bool hasBreaks = !join.isEmpty;
    if (hasBreaks) {
      if (innerBuilder.isOpen) innerBuilder.jumpTo(join);
      add(new ir.LetCont(join.continuation, innerBuilder._root));
      environment = join.environment;
    } else if (innerBuilder._root != null) {
      add(innerBuilder._root);
      _current = innerBuilder._current;
      environment = innerBuilder.environment;
    } else {
      // The translation of the body did not emit any CPS term.
    }
  }

  // Build(BreakStatement L, C) = C[InvokeContinuation(...)]
  //
  // The continuation and arguments are filled in later after translating
  // the body containing the break.
  bool buildBreak(JumpTarget target) {
    return buildJumpInternal(target, state.breakCollectors);
  }

  // Build(ContinueStatement L, C) = C[InvokeContinuation(...)]
  //
  // The continuation and arguments are filled in later after translating
  // the body containing the continue.
  bool buildContinue(JumpTarget target) {
    return buildJumpInternal(target, state.continueCollectors);
  }

  bool buildJumpInternal(JumpTarget target,
                         Iterable<JumpCollector> collectors) {
    assert(isOpen);
    for (JumpCollector collector in collectors) {
      if (target == collector.target) {
        jumpTo(collector);
        return true;
      }
    }
    return false;
  }

  void buildThrow(ir.Primitive value) {
    assert(isOpen);
    add(new ir.Throw(value));
    _current = null;
  }

  ir.Primitive buildNonTailThrow(ir.Primitive value) {
    assert(isOpen);
    ir.Parameter param = new ir.Parameter(null);
    ir.Continuation cont = new ir.Continuation(<ir.Parameter>[param]);
    add(new ir.LetCont(cont, new ir.Throw(value)));
    return param;
  }

  void buildRethrow() {
    assert(isOpen);
    add(new ir.Rethrow());
    _current = null;
  }

  /// Create a negation of [condition].
  ir.Primitive buildNegation(ir.Primitive condition) {
    // ! e is translated as e ? false : true

    // Add a continuation parameter for the result of the expression.
    ir.Parameter resultParameter = new ir.Parameter(null);

    ir.Continuation joinContinuation = new ir.Continuation([resultParameter]);
    ir.Continuation thenContinuation = new ir.Continuation([]);
    ir.Continuation elseContinuation = new ir.Continuation([]);

    ir.Constant makeBoolConstant(bool value) {
      return new ir.Constant(state.constantSystem.createBool(value));
    }

    ir.Constant trueConstant = makeBoolConstant(true);
    ir.Constant falseConstant = makeBoolConstant(false);

    thenContinuation.body = new ir.LetPrim(falseConstant)
        ..plug(new ir.InvokeContinuation(joinContinuation, [falseConstant]));
    elseContinuation.body = new ir.LetPrim(trueConstant)
        ..plug(new ir.InvokeContinuation(joinContinuation, [trueConstant]));

    add(new ir.LetCont(joinContinuation,
          new ir.LetCont.two(thenContinuation, elseContinuation,
              new ir.Branch.strict(condition,
                                   thenContinuation,
                                   elseContinuation))));
    return resultParameter;
  }

  /// Create a lazy and/or expression. [leftValue] is the value of the left
  /// operand and [buildRightValue] is called to process the value of the right
  /// operand in the context of its own [IrBuilder].
  ir.Primitive buildLogicalOperator(
      ir.Primitive leftValue,
      ir.Primitive buildRightValue(IrBuilder builder),
      {bool isLazyOr: false}) {
    // e0 && e1 is translated as if e0 ? (e1 == true) : false.
    // e0 || e1 is translated as if e0 ? true : (e1 == true).
    // The translation must convert both e0 and e1 to booleans and handle
    // local variable assignments in e1.
    IrBuilder rightBuilder = makeDelimitedBuilder();
    ir.Primitive rightValue = buildRightValue(rightBuilder);
    // A dummy empty target for the branch on the left subexpression branch.
    // This enables using the same infrastructure for join-point continuations
    // as in visitIf and visitConditional.  It will hold a definition of the
    // appropriate constant and an invocation of the join-point continuation.
    IrBuilder emptyBuilder = makeDelimitedBuilder();
    // Dummy empty targets for right true and right false.  They hold
    // definitions of the appropriate constant and an invocation of the
    // join-point continuation.
    IrBuilder rightTrueBuilder = rightBuilder.makeDelimitedBuilder();
    IrBuilder rightFalseBuilder = rightBuilder.makeDelimitedBuilder();

    // If we don't evaluate the right subexpression, the value of the whole
    // expression is this constant.
    ir.Constant leftBool = emptyBuilder.buildBooleanConstant(isLazyOr);
    // If we do evaluate the right subexpression, the value of the expression
    // is a true or false constant.
    ir.Constant rightTrue = rightTrueBuilder.buildBooleanConstant(true);
    ir.Constant rightFalse = rightFalseBuilder.buildBooleanConstant(false);

    // Result values are passed as continuation arguments, which are
    // constructed based on environments.  These assertions are a sanity check.
    assert(environment.length == emptyBuilder.environment.length);
    assert(environment.length == rightTrueBuilder.environment.length);
    assert(environment.length == rightFalseBuilder.environment.length);

    // Wire up two continuations for the left subexpression, two continuations
    // for the right subexpression, and a three-way join continuation.
    JumpCollector join =
        new ForwardJumpCollector(environment, hasExtraArgument: true);
    emptyBuilder.jumpTo(join, leftBool);
    rightTrueBuilder.jumpTo(join, rightTrue);
    rightFalseBuilder.jumpTo(join, rightFalse);
    ir.Continuation leftTrueContinuation = new ir.Continuation([]);
    ir.Continuation leftFalseContinuation = new ir.Continuation([]);
    ir.Continuation rightTrueContinuation = new ir.Continuation([]);
    ir.Continuation rightFalseContinuation = new ir.Continuation([]);
    rightTrueContinuation.body = rightTrueBuilder._root;
    rightFalseContinuation.body = rightFalseBuilder._root;
    // The right subexpression has two continuations.
    rightBuilder.add(
        new ir.LetCont.two(rightTrueContinuation, rightFalseContinuation,
            new ir.Branch.strict(rightValue,
                                 rightTrueContinuation,
                                 rightFalseContinuation)));
    // Depending on the operator, the left subexpression's continuations are
    // either the right subexpression or an invocation of the join-point
    // continuation.
    if (isLazyOr) {
      leftTrueContinuation.body = emptyBuilder._root;
      leftFalseContinuation.body = rightBuilder._root;
    } else {
      leftTrueContinuation.body = rightBuilder._root;
      leftFalseContinuation.body = emptyBuilder._root;
    }

    add(new ir.LetCont(join.continuation,
            new ir.LetCont.two(leftTrueContinuation, leftFalseContinuation,
                new ir.Branch.strict(leftValue,
                                     leftTrueContinuation,
                                     leftFalseContinuation))));
    environment = join.environment;
    return environment.discard(1);
  }

  ir.Primitive buildIdentical(ir.Primitive x, ir.Primitive y,
                              {SourceInformation sourceInformation}) {
    return addPrimitive(new ir.ApplyBuiltinOperator(
        ir.BuiltinOperator.Identical, <ir.Primitive>[x, y],
        sourceInformation));
  }

  /// Called when entering a nested function with free variables.
  ///
  /// The free variables must subsequently be accessible using [buildLocalGet]
  /// and [buildLocalSet].
  void _enterClosureEnvironment(ClosureEnvironment env) {
    if (env == null) return;

    // Obtain a reference to the function object (this).
    ir.Parameter thisPrim = state.thisParameter;

    // Obtain access to the free variables.
    env.freeVariables.forEach((Local local, ClosureLocation location) {
      if (location.isBox) {
        // Boxed variables are loaded from their box on-demand.
        state.boxedVariables[local] = location;
      } else {
        // Unboxed variables are loaded from the function object immediately.
        // This includes BoxLocals which are themselves unboxed variables.
        environment.extend(local,
            addPrimitive(new ir.GetField(thisPrim, location.field)));
      }
    });

    // If the function captures a reference to the receiver from the
    // enclosing method, remember which primitive refers to the receiver object.
    if (env.thisLocal != null && env.freeVariables.containsKey(env.thisLocal)) {
      state.enclosingThis = environment.lookup(env.thisLocal);
    }

    // If the function has a self-reference, use the value of `this`.
    if (env.selfReference != null) {
      environment.extend(env.selfReference, thisPrim);
    }
  }

  /// Creates a box for [scope.box] and binds the captured variables to
  /// that box.
  ///
  /// The captured variables can subsequently be manipulated with
  /// [declareLocalVariable], [buildLocalGet], and [buildLocalSet].
  void enterScope(ClosureScope scope) => _enterScope(scope);

  /// Called when entering a function body or loop body.
  ///
  /// This is not called for for-loops, which instead use the methods
  /// [_enterForLoopInitializer], [_enterForLoopBody], and [_enterForLoopUpdate]
  /// due to their special scoping rules.
  ///
  /// The boxed variables declared in this scope must subsequently be available
  /// using [buildLocalGet], [buildLocalSet], etc.
  void _enterScope(ClosureScope scope) {
    if (scope == null) return;
    ir.CreateBox boxPrim = addPrimitive(new ir.CreateBox());
    environment.extend(scope.box, boxPrim);
    boxPrim.useElementAsHint(scope.box);
    scope.capturedVariables.forEach((Local local, ClosureLocation location) {
      assert(!state.boxedVariables.containsKey(local));
      if (location.isBox) {
        state.boxedVariables[local] = location;
      }
    });
  }

  /// Add the given function parameter to the IR, and bind it in the environment
  /// or put it in its box, if necessary.
  void _createFunctionParameter(Local parameterElement) {
    ir.Parameter parameter = new ir.Parameter(parameterElement);
    _parameters.add(parameter);
    state.functionParameters.add(parameter);
    ClosureLocation location = state.boxedVariables[parameterElement];
    if (location != null) {
      addPrimitive(new ir.SetField(
          environment.lookup(location.box),
          location.field,
          parameter));
    } else {
      environment.extend(parameterElement, parameter);
    }
  }

  void _createThisParameter() {
    assert(state.thisParameter == null);
    if (Elements.isStaticOrTopLevel(state.currentElement)) return;
    if (state.currentElement.isLocal) return;
    state.thisParameter =
        new ir.Parameter(new ThisParameterLocal(state.currentElement));
  }

  void declareLocalVariable(LocalElement variableElement,
                            {ir.Primitive initialValue}) {
    assert(isOpen);
    if (initialValue == null) {
      initialValue = buildNullConstant();
    }
    ClosureLocation location = state.boxedVariables[variableElement];
    if (location != null) {
      addPrimitive(new ir.SetField(
          environment.lookup(location.box),
          location.field,
          initialValue));
    } else if (isInMutableVariable(variableElement)) {
      add(new ir.LetMutable(
          getMutableVariable(variableElement),
          initialValue));
    } else {
      initialValue.useElementAsHint(variableElement);
      environment.extend(variableElement, initialValue);
    }
  }

  /// Add [functionElement] to the environment with provided [definition].
  void declareLocalFunction(LocalFunctionElement functionElement,
                            closure.ClosureClassElement classElement,
                            SourceInformation sourceInformation) {
    ir.Primitive closure =
         buildFunctionExpression(classElement, sourceInformation);
    declareLocalVariable(functionElement, initialValue: closure);
  }

  ir.Primitive buildFunctionExpression(closure.ClosureClassElement classElement,
                                       SourceInformation sourceInformation) {
    List<ir.Primitive> arguments = <ir.Primitive>[];
    for (closure.ClosureFieldElement field in classElement.closureFields) {
      // Captured 'this' and type variables are not always available as locals
      // in the environment, so treat those specially.
      ir.Primitive value;
      if (field.local is closure.ThisLocal) {
        value = buildThis();
      } else if (field.local is closure.TypeVariableLocal) {
        closure.TypeVariableLocal variable = field.local;
        value = buildTypeVariableAccess(variable.typeVariable);
      } else {
        value = environment.lookup(field.local);
      }
      arguments.add(value);
    }
    return addPrimitive(new ir.CreateInstance(
        classElement, arguments, const <ir.Primitive>[], sourceInformation));
  }

  /// Create a read access of [local] function, variable, or parameter.
  ir.Primitive buildLocalGet(LocalElement local) {
    assert(isOpen);
    ClosureLocation location = state.boxedVariables[local];
    if (location != null) {
      ir.Primitive result = new ir.GetField(environment.lookup(location.box),
                                            location.field);
      result.useElementAsHint(local);
      return addPrimitive(result);
    } else if (isInMutableVariable(local)) {
      return addPrimitive(new ir.GetMutable(getMutableVariable(local)));
    } else {
      return environment.lookup(local);
    }
  }

  /// Create a write access to [local] variable or parameter with the provided
  /// [value].
  ir.Primitive buildLocalVariableSet(LocalElement local, ir.Primitive value) {
    assert(isOpen);
    ClosureLocation location = state.boxedVariables[local];
    if (location != null) {
      addPrimitive(new ir.SetField(
          environment.lookup(location.box),
          location.field,
          value));
    } else if (isInMutableVariable(local)) {
      addPrimitive(new ir.SetMutable(
          getMutableVariable(local), value));
    } else {
      value.useElementAsHint(local);
      environment.update(local, value);
    }
    return value;
  }

  /// Called before building the initializer of a for-loop.
  ///
  /// The loop variables will subsequently be declared using
  /// [declareLocalVariable].
  void _enterForLoopInitializer(ClosureScope scope,
                                List<LocalElement> loopVariables) {
    if (scope == null) return;
    // If there are no boxed loop variables, don't create the box here, let
    // it be created inside the body instead.
    if (scope.boxedLoopVariables.isEmpty) return;
    _enterScope(scope);
  }

  /// Called before building the body of a for-loop.
  void _enterForLoopBody(ClosureScope scope,
                         List<LocalElement> loopVariables) {
    if (scope == null) return;
    // If there are boxed loop variables, the box has already been created
    // at the initializer.
    if (!scope.boxedLoopVariables.isEmpty) return;
    _enterScope(scope);
  }

  /// Called before building the update of a for-loop.
  void _enterForLoopUpdate(ClosureScope scope,
                           List<LocalElement> loopVariables) {
    if (scope == null) return;
    // If there are no boxed loop variables, then the box is created inside the
    // body, so there is no need to explicitly renew it.
    if (scope.boxedLoopVariables.isEmpty) return;
    ir.Primitive box = environment.lookup(scope.box);
    ir.Primitive newBox = addPrimitive(new ir.CreateBox());
    newBox.useElementAsHint(scope.box);
    for (VariableElement loopVar in scope.boxedLoopVariables) {
      ClosureLocation location = scope.capturedVariables[loopVar];
      ir.Primitive value = addPrimitive(new ir.GetField(box, location.field));
      addPrimitive(new ir.SetField(newBox, location.field, value));
    }
    environment.update(scope.box, newBox);
  }

  /// Creates an access to the receiver from the current (or enclosing) method.
  ///
  /// If inside a closure class, [buildThis] will redirect access through
  /// closure fields in order to access the receiver from the enclosing method.
  ir.Primitive buildThis() {
    if (state.enclosingThis != null) return state.enclosingThis;
    assert(state.thisParameter != null);
    return state.thisParameter;
  }

  ir.Primitive buildFieldGet(ir.Primitive receiver, FieldElement target) {
    return addPrimitive(new ir.GetField(receiver, target));
  }

  void buildFieldSet(ir.Primitive receiver,
                     FieldElement target,
                     ir.Primitive value) {
    addPrimitive(new ir.SetField(receiver, target, value));
  }

  ir.Primitive buildSuperFieldGet(FieldElement target) {
    return addPrimitive(new ir.GetField(buildThis(), target));
  }

  ir.Primitive buildSuperFieldSet(FieldElement target, ir.Primitive value) {
    addPrimitive(new ir.SetField(buildThis(), target, value));
    return value;
  }

  /// Loads parameters to a constructor body into the environment.
  ///
  /// The header for a constructor body differs from other functions in that
  /// some parameters are already boxed, and the box is passed as an argument
  /// instead of being created in the header.
  void buildConstructorBodyHeader(Iterable<Local> parameters,
                                  ClosureScope closureScope) {
    _createThisParameter();
    for (Local param in parameters) {
      ir.Parameter parameter = _createLocalParameter(param);
      state.functionParameters.add(parameter);
    }
    if (closureScope != null) {
      state.boxedVariables.addAll(closureScope.capturedVariables);
    }
  }

  /// Create a constructor invocation of [element] on [type] where the
  /// constructor name and argument structure are defined by [callStructure] and
  /// the argument values are defined by [arguments].
  ir.Primitive buildConstructorInvocation(
      ConstructorElement element,
      CallStructure callStructure,
      DartType type,
      List<ir.Primitive> arguments,
      SourceInformation sourceInformation,
      {TypeMask allocationSiteType}) {
    assert(isOpen);
    Selector selector =
        new Selector(SelectorKind.CALL, element.memberName, callStructure);
    ClassElement cls = element.enclosingClass;
    if (program.requiresRuntimeTypesFor(cls)) {
      InterfaceType interface = type;
      Iterable<ir.Primitive> typeArguments =
          interface.typeArguments.map((DartType argument) {
        return type.treatAsRaw
            ? buildNullConstant()
            : buildTypeExpression(argument);
      });
      arguments = new List<ir.Primitive>.from(arguments)
          ..addAll(typeArguments);
    }
    return addPrimitive(new ir.InvokeConstructor(
        type, element, selector, arguments, sourceInformation,
        allocationSiteType: allocationSiteType));
  }

  ir.Primitive buildTypeExpression(DartType type) {
    type = program.unaliasType(type);
    if (type is TypeVariableType) {
      return buildTypeVariableAccess(type);
    } else if (type is InterfaceType || type is FunctionType) {
      List<ir.Primitive> arguments = <ir.Primitive>[];
      type.forEachTypeVariable((TypeVariableType variable) {
        ir.Primitive value = buildTypeVariableAccess(variable);
        arguments.add(value);
      });
      return addPrimitive(new ir.TypeExpression(type, arguments));
    } else if (type.treatAsDynamic) {
      return buildNullConstant();
    } else {
      // TypedefType can reach here, and possibly other things.
      throw 'unimplemented translation of type expression $type (${type.kind})';
    }
  }

  /// Obtains the internal type representation of the type held in [variable].
  ///
  /// The value of [variable] is taken from the current receiver object, or
  /// if we are currently building a constructor field initializer, from the
  /// corresponding type argument (field initializers are evaluated before the
  /// receiver object is created).
  ir.Primitive buildTypeVariableAccess(TypeVariableType variable,
                                       {SourceInformation sourceInformation}) {
    // If the local exists in the environment, use that.
    // This is put here when we are inside a constructor or field initializer,
    // (or possibly a closure inside one of these).
    Local local = new closure.TypeVariableLocal(variable, state.currentElement);
    if (environment.contains(local)) {
      return environment.lookup(local);
    }

    // If the type variable is not in a local, read its value from the
    // receiver object.
    ir.Primitive target = buildThis();
    return addPrimitive(
        new ir.ReadTypeVariable(variable, target, sourceInformation));
  }

  /// Make the given type variable accessible through the local environment
  /// with the value of [binding].
  void declareTypeVariable(TypeVariableType variable, DartType binding) {
    environment.extend(
        new closure.TypeVariableLocal(variable, state.currentElement),
        buildTypeExpression(binding));
  }

  /// Reifies the value of [variable] on the current receiver object.
  ir.Primitive buildReifyTypeVariable(TypeVariableType variable,
                                      SourceInformation sourceInformation) {
    ir.Primitive typeArgument =
        buildTypeVariableAccess(variable, sourceInformation: sourceInformation);
    return addPrimitive(
        new ir.ReifyRuntimeType(typeArgument, sourceInformation));
  }

  ir.Primitive buildInvocationMirror(Selector selector,
                                     List<ir.Primitive> arguments) {
    return addPrimitive(new ir.CreateInvocationMirror(selector, arguments));
  }

  ir.Primitive buildForeignCode(js.Template codeTemplate,
                                List<ir.Primitive> arguments,
                                NativeBehavior behavior,
                                {Element dependency}) {
    assert(behavior != null);
    TypeMask type = program.getTypeMaskForForeign(behavior);
    ir.Primitive result = addPrimitive(new ir.ForeignCode(
        codeTemplate,
        type,
        arguments,
        behavior,
        dependency: dependency));
    if (!codeTemplate.isExpression) {
      // Close the term if this is a "throw" expression or native body.
      add(new ir.Unreachable());
      _current = null;
    }
    return result;
  }

  /// Creates a type test or type cast of [value] against [type].
  ir.Primitive buildTypeOperator(ir.Primitive value,
                                 DartType type,
                                 {bool isTypeTest}) {
    assert(isOpen);
    assert(isTypeTest != null);

    type = program.unaliasType(type);

    if (type.isMalformed) {
      ErroneousElement element = type.element;
      ir.Primitive message = buildStringConstant(element.message);
      return buildStaticFunctionInvocation(
          program.throwTypeErrorHelper,
          <ir.Primitive>[message]);
    }

    List<ir.Primitive> typeArguments = const <ir.Primitive>[];
    if (type is GenericType && type.typeArguments.isNotEmpty) {
      typeArguments = type.typeArguments.map(buildTypeExpression).toList();
    } else if (type is TypeVariableType) {
      typeArguments = <ir.Primitive>[buildTypeVariableAccess(type)];
    } else if (type is FunctionType) {
      typeArguments = <ir.Primitive>[buildTypeExpression(type)];
    }

    if (isTypeTest) {
      // For type tests, we must treat specially the rare cases where `null`
      // satisfies the test (which otherwise never satisfies a type test).
      // This is not an optimization: the TypeOperator assumes that `null`
      // cannot satisfy the type test unless the type is a type variable.
      if (type.isObject || type.isDynamic) {
        // `x is Object` and `x is dynamic` are always true, even if x is null.
        return buildBooleanConstant(true);
      }
      if (type is InterfaceType && type.element == program.nullClass) {
        // `x is Null` is true if and only if x is null.
        return _buildCheckNull(value);
      }
      return addPrimitive(new ir.TypeTest(value, type, typeArguments));
    } else {
      if (type.isObject || type.isDynamic) {
        // `x as Object` and `x as dynamic` are the same as `x`.
        return value;
      }
      return addPrimitive(new ir.TypeCast(value, type, typeArguments));
    }
  }

  /// Create an if-null expression. This is equivalent to a conditional
  /// expression whose result is either [value] if [value] is not null, or
  /// `right` if [value] is null. Only when [value] is null, [buildRight] is
  /// evaluated to produce the `right` value.
  ir.Primitive buildIfNull(ir.Primitive value,
                           ir.Primitive buildRight(IrBuilder builder),
                           {SourceInformation sourceInformation}) {
    ir.Primitive condition =
        _buildCheckNull(value, sourceInformation: sourceInformation);
    return buildConditional(condition, buildRight, (_) => value);
  }

  /// Create a conditional send. This is equivalent to a conditional expression
  /// that checks if [receiver] is null, if so, it returns null, otherwise it
  /// evaluates the [buildSend] expression.
  ir.Primitive buildIfNotNullSend(ir.Primitive receiver,
                                  ir.Primitive buildSend(IrBuilder builder),
                                  {SourceInformation sourceInformation}) {
    ir.Primitive condition =
        _buildCheckNull(receiver, sourceInformation: sourceInformation);
    return buildConditional(condition, (_) => receiver, buildSend);
  }

  /// Creates a type test checking whether [value] is null.
  ir.Primitive _buildCheckNull(ir.Primitive value,
                               {SourceInformation sourceInformation}) {
    assert(isOpen);
    return buildIdentical(value, buildNullConstant(),
        sourceInformation: sourceInformation);
  }
}

/// Location of a variable relative to a given closure.
class ClosureLocation {
  /// If not `null`, this location is [box].[field].
  /// The location of [box] can be obtained separately from an
  /// enclosing [ClosureEnvironment] or [ClosureScope].
  /// If `null`, then the location is [field] on the enclosing function object.
  final closure.BoxLocal box;

  /// The field in which the variable is stored.
  final Entity field;

  bool get isBox => box != null;

  ClosureLocation(this.box, this.field);

  /// Converts a map containing closure.dart's [CapturedVariable]s into one
  /// containing [ClosureLocation]s.
  ///
  /// There is a 1:1 corresponce between these; we do this because the
  /// IR builder should not depend on synthetic elements.
  static Map<Local, ClosureLocation> mapFrom(
      Map<Local, closure.CapturedVariable> map) {
    Map result = {};
    map.forEach((Local k, closure.CapturedVariable v) {
      closure.BoxLocal box = v is closure.BoxFieldElement ? v.box : null;
      result[k] = new ClosureLocation(box, v);
    });
    return result;
  }
}

/// Introduces a new box and binds local variables to this box.
///
/// A [ClosureScope] may exist for each function and for each loop.
/// Generally, one may pass `null` to the [IrBuilder] instead of a
/// [ClosureScope] when a given scope has no boxed variables.
class ClosureScope {
  /// This box is now in scope and [capturedVariables] may use it.
  final closure.BoxLocal box;

  /// Maps [LocalElement]s to their location.
  final Map<Local, ClosureLocation> capturedVariables;

  /// If this is the scope of a for-loop, [boxedLoopVariables] is the list
  /// of boxed variables that are declared in the initializer.
  final List<VariableElement> boxedLoopVariables;

  factory ClosureScope(closure.ClosureScope scope) {
    return scope == null ? null : new ClosureScope._internal(scope);
  }

  ClosureScope._internal(closure.ClosureScope scope)
      : box = scope.boxElement,
        capturedVariables = ClosureLocation.mapFrom(scope.capturedVariables),
        boxedLoopVariables = scope.boxedLoopVariables;
}

/// Environment passed when building a nested function, describing how
/// to access variables from the enclosing scope.
class ClosureEnvironment {
  /// References to this local should be treated as recursive self-reference.
  /// (This is *not* in [freeVariables]).
  final LocalFunctionElement selfReference;

  /// If non-null, [thisLocal] has an entry in [freeVariables] describing where
  /// to find the captured value of `this`.
  final closure.ThisLocal thisLocal;

  /// Maps [LocalElement]s, [BoxLocal]s and [ThisLocal] to their location.
  final Map<Local, ClosureLocation> freeVariables;

  factory ClosureEnvironment(closure.ClosureClassMap closureClassMap) {
    if (closureClassMap.closureElement == null) return null;
    return new ClosureEnvironment._internal(closureClassMap);
  }

  ClosureEnvironment._internal(closure.ClosureClassMap closureClassMap)
      : selfReference = closureClassMap.closureElement,
        thisLocal = closureClassMap.thisLocal,
        freeVariables =
            ClosureLocation.mapFrom(closureClassMap.freeVariableMap);
}

class TryStatementInfo {
  final Set<LocalVariableElement> declared = new Set<LocalVariableElement>();
  final Set<LocalVariableElement> boxedOnEntry =
      new Set<LocalVariableElement>();
}

class CatchClauseInfo {
  final DartType type;
  final LocalVariableElement exceptionVariable;
  final LocalVariableElement stackTraceVariable;
  final SubbuildFunction buildCatchBlock;

  CatchClauseInfo({this.type,
                   this.exceptionVariable,
                   this.stackTraceVariable,
                   this.buildCatchBlock});
}

class SwitchCaseInfo {
  final List<ir.Primitive> constants = <ir.Primitive>[];
  final SubbuildFunction buildBody;

  SwitchCaseInfo(this.buildBody);

  void addConstant(ir.Primitive constant) => constants.add(constant);
}
