// 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,
    objectLiteral,
    Expression,
    LiteralStatement,
    Template,
    InterpolatedExpression,
    isIdentityTemplate;
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;

  /// Construct a collector for collecting goto jumps.
  ///
  /// There is no continuation or environment at the destination.
  JumpCollector.goto(this.target) : _continuationEnvironment = 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.continuationRef = new ir.Reference(_continuation);
      invocation.argumentRefs = 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;
  }
}

/// Collect 'goto' jumps, continue to a labeled case from within a switch.
///
/// These jumps are unrestricted within the switch.  They can be forward or
/// backward.  They are implemented by assigning to a state variable.
class GotoJumpCollector extends JumpCollector {
  bool isEmpty = true;
  final ir.Continuation continuation = null;
  final Environment environment = null;

  int _stateVariableIndex;
  int _stateValue;
  JumpCollector _breakJoin;

  GotoJumpCollector(JumpTarget target, this._stateVariableIndex,
      this._stateValue, this._breakJoin) : super.goto(target);

  void addJump(IrBuilder builder,
      [ir.Primitive value, SourceInformation sourceInformation]) {
    isEmpty = false;
    ir.Primitive constant = builder.buildIntegerConstant(_stateValue);
    builder.environment.index2value[_stateVariableIndex] = constant;
    builder.jumpTo(_breakJoin);
  }
}

/// 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);
    if (program.isJsInterop(element)) {
      return buildInvokeJsInteropMember(element, arguments);
    }
    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(
      SourceInformation sourceInformation) {
    _ensureReturn();
    return new ir.FunctionDefinition(
        state.currentElement,
        state.thisParameter,
        state.functionParameters,
        state.returnContinuation,
        root,
        sourceInformation: sourceInformation);
  }

  /// 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 comparison 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(JumpCollector join,
                         List<SwitchCaseInfo> cases,
                         SubbuildFunction buildDefaultBody) {
    IrBuilder casesBuilder = makeDelimitedBuilder();
    for (SwitchCaseInfo caseInfo in cases) {
      ir.Primitive condition = caseInfo.buildCondition(casesBuilder);
      IrBuilder thenBuilder = makeDelimitedBuilder();
      caseInfo.buildBody(thenBuilder);
      ir.Continuation thenContinuation = new ir.Continuation([]);
      thenContinuation.body = thenBuilder.root;
      ir.Continuation elseContinuation = new ir.Continuation([]);
      // A LetCont.two 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 (buildDefaultBody == null) {
      casesBuilder.jumpTo(join);
    } else {
      buildDefaultBody(casesBuilder);
    }

    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,
        type: program.getTypeMaskForNativeFunction(function));
    buildReturn(value: value, sourceInformation: source);
  }

  static _isNotNull(ir.Primitive value) =>
      !(value is ir.Constant && value.value.isNull);

  /// Builds a call to a resolved js-interop element.
  ir.Primitive buildInvokeJsInteropMember(FunctionElement element,
      List<ir.Primitive> arguments) {
    program.addNativeMethod(element);
    String target = program.getJsInteropTargetPath(element);
    // Strip off trailing arguments that were not specified.
    // TODO(jacobr,sigmund): assert that the trailing arguments are all null.
    // TODO(jacobr): rewrite named arguments to an object literal matching
    // the factory constructor case.
    var inputs = arguments.where(_isNotNull).toList();

    var behavior = new NativeBehavior()..sideEffects.setAllSideEffects();
    DartType type = element.isConstructor ?
        element.enclosingClass.thisType : element.type.returnType;
    // Native behavior effects here are similar to native/behavior.dart.
    // The return type is dynamic if we don't trust js-interop type
    // declarations.
    behavior.typesReturned.add(
        program.trustJSInteropTypeAnnotations ? type : const DynamicType());

    // The allocation effects include the declared type if it is native (which
    // includes js interop types).
    if (type.element != null && program.isNative(type.element)) {
      behavior.typesInstantiated.add(type);
    }

    // It also includes any other JS interop type if we don't trust the
    // annotation or if is declared too broad.
    if (!program.trustJSInteropTypeAnnotations || type.isObject ||
        type.isDynamic) {
      behavior.typesInstantiated.add(program.jsJavascriptObjectType);
    }

    String code;
    if (element.isGetter) {
      code = target;
    } else if (element.isSetter) {
      code = "$target = #";
    } else {
      var args = new List.filled(inputs.length, '#').join(',');
      code = element.isConstructor ? "new $target($args)" : "$target($args)";
    }
    return buildForeignCode(js.js.parseForeignJS(code), inputs, behavior);
    // TODO(sigmund): should we record the source-information here?
  }

  /// Builds an object literal that results from invoking a factory constructor
  /// of a js-interop anonymous type.
  ir.Primitive buildJsInteropObjectLiteral(ConstructorElement constructor,
      List<ir.Primitive> arguments, {SourceInformation source}) {
    assert(program.isJsInteropAnonymous(constructor));
    program.addNativeMethod(constructor);
    FunctionSignature params = constructor.functionSignature;
    int i = 0;
    var filteredArguments = <ir.Primitive>[];
    var entries = new Map<String, js.Expression>();
    params.orderedForEachParameter((ParameterElement parameter) {
      // TODO(jacobr): throw if parameter names do not match names of property
      // names in the class.
      assert (parameter.isNamed);
      ir.Primitive argument = arguments[i++];
      if (_isNotNull(argument)) {
        filteredArguments.add(argument);
        entries[parameter.name] =
            new js.InterpolatedExpression(filteredArguments.length - 1);
      }
    });
    var code = new js.Template(null, js.objectLiteral(entries));
    var behavior = new NativeBehavior();
    if (program.trustJSInteropTypeAnnotations) {
      behavior.typesReturned.add(constructor.enclosingClass.thisType);
    }

    // TODO(sigmund): should we record the source-information here?
    return buildForeignCode(code, filteredArguments, behavior);
  }

  /// 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, null, 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,
        isFinal: program.fieldNeverChanges(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.isJsInterop(element)) {
      if (program.isJsInteropAnonymous(element)) {
        return buildJsInteropObjectLiteral(element, arguments,
            source: sourceInformation);
      }
      return buildInvokeJsInteropMember(element, arguments);
    }
    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(ir.TypeExpressionKind.COMPLETE,
                                                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,
                                 TypeMask type}) {
    assert(behavior != null);
    if (type == null) {
      type = program.getTypeMaskForForeign(behavior);
    }
    if (js.isIdentityTemplate(codeTemplate) && !program.isArrayType(type)) {
      // JS expression is just a refinement.
      // Do not do this for arrays - those are special because array types can
      // change after creation.  The input and output must therefore be modeled
      // as distinct values.
      return addPrimitive(new ir.Refinement(arguments.single, type));
    }
    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 SubbuildFunction buildCondition;
  final SubbuildFunction buildBody;

  SwitchCaseInfo(this.buildCondition, this.buildBody);
}
