// 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 '../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 '../diagnostics/invariant.dart' show
    invariant;
import '../elements/elements.dart';
import '../io/source_information.dart';
import '../tree/tree.dart' as ast;
import '../types/types.dart' show
    TypeMask;
import '../closure.dart' hide ClosureScope;
import '../universe/call_structure.dart' show
    CallStructure;
import '../universe/selector.dart' show
    Selector,
    SelectorKind;
import 'cps_ir_nodes.dart' as ir;
import 'cps_ir_builder_task.dart' show
    DartCapturedVariables,
    GlobalProgramInformation;

import '../common.dart' as types show
    TypeMask;
import '../js/js.dart' as js show Template, js, LiteralStatement;
import '../native/native.dart' show
    NativeBehavior;

/// 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);
  }

  /// 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]);

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

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

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

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

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

  bool isEmpty = true;

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

  void addJump(IrBuilder builder, [ir.Primitive value]) {
    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;
  }
}

/// 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 = null;

  /// 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);
}

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 _continueWithExpression(ir.Expression build(ir.Continuation k)) {
    ir.Parameter v = new ir.Parameter(null);
    ir.Continuation k = new ir.Continuation([v]);
    ir.Expression expression = build(k);
    add(new ir.LetCont(k, expression));
    return v;
  }

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

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

  ir.Primitive _buildInvokeDynamic(ir.Primitive receiver,
                                   Selector selector,
                                   TypeMask mask,
                                   List<ir.Primitive> arguments,
                                   SourceInformation sourceInformation) {
    assert(isOpen);
    return _continueWithExpression(
        (k) => new ir.InvokeMethod(receiver, selector, mask, arguments, k,
                                   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);
  }


  /// 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) {
    assert(isOpen);
    return addPrimitive(new ir.LiteralList(type, values.toList()));
  }

  /// Creates a non-constant map literal of the provided [type] and with the
  /// entries build from the [keys] and [values] using [build].
  ir.Primitive buildMapLiteral(InterfaceType type,
                               Iterable keys,
                               Iterable values,
                               BuildFunction build) {
    assert(isOpen);
    List<ir.LiteralMapEntry> entries = <ir.LiteralMapEntry>[];
    Iterator key = keys.iterator;
    Iterator value = values.iterator;
    while (key.moveNext() && value.moveNext()) {
      entries.add(new ir.LiteralMapEntry(
          build(key.current), build(value.current)));
    }
    assert(!key.moveNext() && !value.moveNext());
    return addPrimitive(new ir.LiteralMap(type, entries));
  }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  /// Create a read access of the [local] variable or parameter.
  ir.Primitive buildLocalVariableGet(LocalElement local) {
    // TODO(johnniwinther): Separate function access from variable access.
    return _buildLocalGet(local);
  }

  /// Create a read access of the local [function], i.e. closurization of
  /// [function].
  ir.Primitive buildLocalFunctionGet(LocalFunctionElement function) {
    // TODO(johnniwinther): Separate function access from variable access.
    return _buildLocalGet(function);
  }

  /// Create an invocation of the the [local] variable or parameter where
  /// argument structure is defined by [callStructure] and the argument values
  /// are defined by [arguments].
  ir.Primitive buildLocalVariableInvocation(
      LocalVariableElement local,
      CallStructure callStructure,
      List<ir.Primitive> arguments,
      {SourceInformation callSourceInformation}) {
    return buildCallInvocation(
        buildLocalVariableGet(local), callStructure, arguments,
        sourceInformation: callSourceInformation);
  }

  /// 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(
        buildLocalFunctionGet(function), callStructure, arguments,
        sourceInformation: sourceInformation);
  }

  /// Create a static invocation of [function] where argument structure is
  /// defined by [callStructure] and the argument values are defined by
  /// [arguments].
  ir.Primitive buildStaticFunctionInvocation(
      MethodElement function,
      CallStructure callStructure,
      List<ir.Primitive> arguments,
      {SourceInformation sourceInformation}) {
    Selector selector =
        new Selector(SelectorKind.CALL, function.memberName, callStructure);
    return _buildInvokeStatic(
        function, selector, arguments, sourceInformation);
  }

  /// Create a read access of the static [field].
  ir.Primitive buildStaticFieldGet(FieldElement field,
                                   SourceInformation sourceInformation) {
    return addPrimitive(new ir.GetStatic(field, sourceInformation));
  }

  /// Create a read access of a static [field] that might not have been
  /// initialized yet.
  ir.Primitive buildStaticFieldLazyGet(FieldElement field,
                                       SourceInformation sourceInformation) {
    return _continueWithExpression(
        (k) => new ir.GetLazyStatic(field, k, 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 read access of the static [function], i.e. a closurization of
  /// [function].
  ir.Primitive buildStaticFunctionGet(MethodElement function,
                                      {SourceInformation sourceInformation}) {
    return addPrimitive(new ir.GetStatic(function, 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; usually a call to [buildStringify] is
  /// needed to ensure the proper conversion takes places.
  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]) {
    collector.addJump(this, value);
  }

  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.Parameter iterator = new ir.Parameter(null);
    ir.Continuation iteratorInvoked = new ir.Continuation([iterator]);
    add(new ir.LetCont(iteratorInvoked,
        new ir.InvokeMethod(expressionReceiver,
            Selectors.iterator,
            iteratorMask,
            emptyArguments,
            iteratorInvoked)));

    // 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.Parameter condition = new ir.Parameter(null);
    ir.Continuation moveNextInvoked = new ir.Continuation([condition]);
    add(new ir.LetCont(moveNextInvoked,
        new ir.InvokeMethod(iterator,
            Selectors.moveNext,
            moveNextMask,
            emptyArguments,
            moveNextInvoked)));

    // 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.Parameter currentValue = new ir.Parameter(null);
    ir.Continuation currentInvoked = new ir.Continuation([currentValue]);
    bodyBuilder.add(new ir.LetCont(currentInvoked,
        new ir.InvokeMethod(
            iterator,
            Selectors.current,
            currentMask,
            emptyArguments, currentInvoked)));
    // TODO(sra): Does this cover all cases? The general setter case include
    // super.
    // TODO(johnniwinther): Extract this as a provided strategy.
    if (Elements.isLocal(variableElement)) {
      bodyBuilder.buildLocalVariableSet(variableElement, currentValue);
    } else if (Elements.isErroneous(variableElement)) {
      bodyBuilder.buildErroneousInvocation(variableElement,
          new Selector.setter(
              new Name(variableElement.name, variableElement.library)),
          <ir.Primitive>[currentValue]);
    } else if (Elements.isStaticOrTopLevel(variableElement)) {
      if (variableElement.isField) {
        bodyBuilder.buildStaticFieldSet(variableElement, currentValue);
      } else {
        bodyBuilder.buildStaticSetterSet(variableElement, currentValue);
      }
    } else {
      ir.Primitive receiver = bodyBuilder.buildThis();
      assert(receiver != null);
      bodyBuilder.buildDynamicSet(
          receiver, variableSelector, variableMask, currentValue);
    }

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

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

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

    ir.Primitive condition = buildCondition(this);

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

    casesBuilder.state.breakCollectors.removeLast();

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

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

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

    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);
    }

    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();
    }
    if (state.returnCollector == null) {
      add(new ir.InvokeContinuation(state.returnContinuation, [value],
              sourceInformation: sourceInformation));
      _current = null;
    } else {
      // Inside the try block of try/finally, all returns go to a join-point
      // continuation that contains the finally code.  The return value is
      // passed as an extra argument.
      jumpTo(state.returnCollector, value);
    }
  }

  /// Build a call to the closure conversion helper for the [Function] typed
  /// value in [value].
  ir.Primitive _convertDartClosure(ir.Primitive value, FunctionType type) {
    ir.Constant arity = buildIntegerConstant(type.computeArity());
    return buildStaticFunctionInvocation(
        program.closureConverter,
        CallStructure.TWO_ARGS,
        <ir.Primitive>[value, arity]);
  }

  /// 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,
                                          SourceInformation source) {
    String name = function.fixedBackendName;
    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).
        input = _convertDartClosure(input, type);
      }
      arguments.add(input);
      argumentTemplates.add('#');
    });
    // Construct the application of parameters for functions and setters.
    if (function.kind == ElementKind.FUNCTION) {
      code = "$code(${argumentTemplates.join(', ')})";
    } else if (function.kind == ElementKind.SETTER) {
      code = "$code = ${argumentTemplates.single}";
    } else {
      assert(argumentTemplates.isEmpty);
      assert(function.kind == ElementKind.GETTER);
    }
    // Generate the [ForeignCode] expression and a return statement to return
    // its value.
    ir.Primitive value = buildForeignCode(
        js.js.uncachedExpressionTemplate(code),
        arguments,
        behavior);
    buildReturn(value: value, sourceInformation: source);
  }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  ir.Primitive buildFunctionExpression(ClosureClassElement classElement,
                                       SourceInformation sourceInformation) {
    List<ir.Primitive> arguments = <ir.Primitive>[];
    for (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 ThisLocal) {
        value = buildThis();
      } else if (field.local is TypeVariableLocal) {
        TypeVariableLocal variable = field.local;
        value = buildTypeVariableAccess(variable.typeVariable);
      } else {
        value = environment.lookup(field.local);
      }
      arguments.add(value);
    }
    return addPrimitive(new ir.CreateInstance(
        classElement, arguments, const <ir.Primitive>[], sourceInformation));
  }

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

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

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

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

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

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

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

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

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

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

  ir.Primitive buildInvokeDirectly(MethodElement target,
                                   ir.Primitive receiver,
                                   List<ir.Primitive> arguments,
                                   {SourceInformation sourceInformation}) {
    assert(isOpen);
    Selector selector =
        new Selector.call(target.memberName, new CallStructure(arguments.length));
    return _continueWithExpression(
        (k) => new ir.InvokeMethodDirectly(
            receiver, target, selector, arguments, k, sourceInformation));
  }

  /// 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) {
    assert(isOpen);
    Selector selector =
        new Selector(SelectorKind.CALL, element.memberName, callStructure);
    ClassElement cls = element.enclosingClass;
    if (program.requiresRuntimeTypesFor(cls)) {
      InterfaceType interface = type;
      Iterable<ir.Primitive> typeArguments =
          interface.typeArguments.map((DartType argument) {
        return type.treatAsRaw
            ? buildNullConstant()
            : buildTypeExpression(argument);
      });
      arguments = new List<ir.Primitive>.from(arguments)
          ..addAll(typeArguments);
    }
    return _continueWithExpression(
        (k) => new ir.InvokeConstructor(
            type, element, selector, arguments, k, sourceInformation));
  }

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

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

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

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

  ir.Primitive buildForeignCode(js.Template codeTemplate,
                                List<ir.Primitive> arguments,
                                NativeBehavior behavior,
                                {Element dependency}) {
    assert(behavior != null);
    types.TypeMask type = program.getTypeMaskForForeign(behavior);
    ir.Primitive result = _continueWithExpression((k) => new ir.ForeignCode(
        codeTemplate,
        type,
        arguments,
        behavior,
        k,
        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) {
      FunctionElement helper = program.throwTypeErrorHelper;
      ErroneousElement element = type.element;
      ir.Primitive message = buildStringConstant(element.message);
      return buildStaticFunctionInvocation(
          helper,
          CallStructure.ONE_ARG,
          <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 _continueWithExpression(
              (k) => new ir.TypeCast(value, type, typeArguments, k));
    }
  }

  /// 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);
  }

  /// Convert the given value to a string.
  ir.Primitive buildStringify(ir.Primitive value) {
    return buildStaticFunctionInvocation(
        program.stringifyFunction,
        new CallStructure.unnamed(1),
        <ir.Primitive>[value]);
  }

  ir.Node buildAwait(ir.Primitive value) {
    return _continueWithExpression((k) => new ir.Await(value, k));
  }

  void buildYield(ir.Primitive value, bool hasStar) {
    _continueWithExpression((k) {
      return new ir.Yield(value, hasStar, k);
    });
  }
}

/// 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 BoxLocal box;

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

  bool get isBox => box != null;

  ClosureLocation(this.box, this.field);
}

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

  ClosureScope(this.box, this.capturedVariables, this.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 ThisLocal thisLocal;

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

  ClosureEnvironment(this.selfReference, this.thisLocal, this.freeVariables);
}

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

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

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

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

  SwitchCaseInfo(this.buildBody);

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