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

import '../closure.dart' as closure;
import '../common.dart';
import '../common/names.dart' show
    Identifiers,
    Names,
    Selectors;
import '../common/tasks.dart' show
    CompilerTask;
import '../compiler.dart' show
    Compiler;
import '../constants/expressions.dart';
import '../dart_types.dart';
import '../elements/elements.dart';
import '../elements/modelx.dart' show
    SynthesizedConstructorElementX,
    ConstructorBodyElementX,
    FunctionSignatureX;
import '../io/source_information.dart';
import '../js_backend/backend_helpers.dart' show
    BackendHelpers;
import '../js_backend/js_backend.dart' show
    JavaScriptBackend,
    SyntheticConstantKind;
import '../resolution/tree_elements.dart' show
    TreeElements;
import '../resolution/semantic_visitor.dart';
import '../resolution/operators.dart' as op;
import '../tree/tree.dart' as ast;
import '../types/types.dart' show
    TypeMask;
import '../universe/call_structure.dart' show
    CallStructure;
import '../universe/selector.dart' show
    Selector;
import '../constants/values.dart' show
    ConstantValue;
import 'cps_ir_nodes.dart' as ir;
import 'cps_ir_builder.dart';
import '../native/native.dart' show
    NativeBehavior,
    HasCapturedPlaceholders;

// TODO(karlklose): remove.
import '../js/js.dart' as js show js, Template, Expression, Name;
import '../ssa/ssa.dart' show TypeMaskFactory;
import '../util/util.dart';

import 'package:js_runtime/shared/embedded_names.dart'
    show JsBuiltin, JsGetName;
import '../constants/values.dart';
import 'type_mask_system.dart' show
    TypeMaskSystem;

typedef void IrBuilderCallback(Element element, ir.FunctionDefinition irNode);

/// This task provides the interface to build IR nodes from [ast.Node]s, which
/// is used from the [CpsFunctionCompiler] to generate code.
///
/// This class is mainly there to correctly measure how long building the IR
/// takes.
class IrBuilderTask extends CompilerTask {
  final SourceInformationStrategy sourceInformationStrategy;

  String bailoutMessage = null;

  /// If not null, this function will be called with for each
  /// [ir.FunctionDefinition] node that has been built.
  IrBuilderCallback builderCallback;

  IrBuilderTask(Compiler compiler, this.sourceInformationStrategy,
      [this.builderCallback])
      : super(compiler);

  String get name => 'CPS builder';

  ir.FunctionDefinition buildNode(AstElement element,
                                  TypeMaskSystem typeMaskSystem) {
    return measure(() {
      bailoutMessage = null;

      TreeElements elementsMapping = element.resolvedAst.elements;
      element = element.implementation;
      return reporter.withCurrentElement(element, () {
        SourceInformationBuilder sourceInformationBuilder =
            sourceInformationStrategy.createBuilderForContext(element);

        IrBuilderVisitor builder =
            new IrBuilderVisitor(
                elementsMapping, compiler, sourceInformationBuilder,
                typeMaskSystem);
        ir.FunctionDefinition irNode = builder.buildExecutable(element);
        if (irNode == null) {
          bailoutMessage = builder.bailoutMessage;
        } else if (builderCallback != null) {
          builderCallback(element, irNode);
        }
        return irNode;
      });
    });
  }
}

/// Translates the frontend AST of a method to its CPS IR.
///
/// The visitor has an [IrBuilder] which contains an IR fragment to build upon
/// and the current reaching definition of local variables.
///
/// Visiting a statement or expression extends the IR builder's fragment.
/// For expressions, the primitive holding the resulting value is returned.
/// For statements, `null` is returned.
// TODO(johnniwinther): Implement [SemanticDeclVisitor].
class IrBuilderVisitor extends ast.Visitor<ir.Primitive>
    with IrBuilderMixin<ast.Node>,
         SemanticSendResolvedMixin<ir.Primitive, dynamic>,
         ErrorBulkMixin<ir.Primitive, dynamic>,
         BaseImplementationOfStaticsMixin<ir.Primitive, dynamic>,
         BaseImplementationOfLocalsMixin<ir.Primitive, dynamic>,
         BaseImplementationOfDynamicsMixin<ir.Primitive, dynamic>,
         BaseImplementationOfConstantsMixin<ir.Primitive, dynamic>,
         BaseImplementationOfNewMixin<ir.Primitive, dynamic>,
         BaseImplementationOfCompoundsMixin<ir.Primitive, dynamic>,
         BaseImplementationOfSetIfNullsMixin<ir.Primitive, dynamic>,
         BaseImplementationOfIndexCompoundsMixin<ir.Primitive, dynamic>
    implements SemanticSendVisitor<ir.Primitive, dynamic> {
  final TreeElements elements;
  final Compiler compiler;
  final SourceInformationBuilder sourceInformationBuilder;
  final TypeMaskSystem typeMaskSystem;

  /// A map from try statements in the source to analysis information about
  /// them.
  ///
  /// The analysis information includes the set of variables that must be
  /// copied into [ir.MutableVariable]s on entry to the try and copied out on
  /// exit.
  Map<ast.Node, TryStatementInfo> tryStatements = null;

  // In SSA terms, join-point continuation parameters are the phis and the
  // continuation invocation arguments are the corresponding phi inputs.  To
  // support name introduction and renaming for source level variables, we use
  // nested (delimited) visitors for constructing subparts of the IR that will
  // need renaming.  Each source variable is assigned an index.
  //
  // Each nested visitor maintains a list of free variable uses in the body.
  // These are implemented as a list of parameters, each with their own use
  // list of references.  When the delimited subexpression is plugged into the
  // surrounding context, the free occurrences can be captured or become free
  // occurrences in the next outer delimited subexpression.
  //
  // Each nested visitor maintains a list that maps indexes of variables
  // assigned in the delimited subexpression to their reaching definition ---
  // that is, the definition in effect at the hole in 'current'.  These are
  // used to determine if a join-point continuation needs to be passed
  // arguments, and what the arguments are.

  /// Construct a top-level visitor.
  IrBuilderVisitor(this.elements,
                   this.compiler,
                   this.sourceInformationBuilder,
                   this.typeMaskSystem);

  JavaScriptBackend get backend => compiler.backend;
  BackendHelpers get helpers => backend.helpers;
  DiagnosticReporter get reporter => compiler.reporter;

  String bailoutMessage = null;

  ir.Primitive visit(ast.Node node) => node.accept(this);

  @override
  ir.Primitive apply(ast.Node node, _) => node.accept(this);

  SemanticSendVisitor get sendVisitor => this;

  /// Result of closure conversion for the current body of code.
  ///
  /// Will be initialized upon entering the body of a function.
  /// It is computed by the [ClosureTranslator].
  closure.ClosureClassMap closureClassMap;

  /// If [node] has declarations for variables that should be boxed,
  /// returns a [ClosureScope] naming a box to create, and enumerating the
  /// variables that should be stored in the box.
  ///
  /// Also see [ClosureScope].
  ClosureScope getClosureScopeForNode(ast.Node node) {
    // We translate a ClosureScope from closure.dart into IR builder's variant
    // because the IR builder should not depend on the synthetic elements
    // created in closure.dart.
    return new ClosureScope(closureClassMap.capturingScopes[node]);
  }

  /// Returns the [ClosureScope] for any function, possibly different from the
  /// one currently being built.
  ClosureScope getClosureScopeForFunction(FunctionElement function) {
    closure.ClosureClassMap map =
        compiler.closureToClassMapper.computeClosureToClassMapping(
            function,
            function.node,
            elements);
    return new ClosureScope(map.capturingScopes[function.node]);
  }

  /// If the current function is a nested function with free variables (or a
  /// captured reference to `this`), returns a [ClosureEnvironment]
  /// indicating how to access these.
  ClosureEnvironment getClosureEnvironment() {
    return new ClosureEnvironment(closureClassMap);
  }

  IrBuilder getBuilderFor(Element element) {
    return new IrBuilder(
        new GlobalProgramInformation(compiler),
        backend.constants,
        element);
  }

  /// Builds the [ir.FunctionDefinition] for an executable element. In case the
  /// function uses features that cannot be expressed in the IR, this element
  /// returns `null`.
  ir.FunctionDefinition buildExecutable(ExecutableElement element) {
    return nullIfGiveup(() {
      ir.FunctionDefinition root;
      switch (element.kind) {
        case ElementKind.GENERATIVE_CONSTRUCTOR:
          root = buildConstructor(element);
          break;

        case ElementKind.GENERATIVE_CONSTRUCTOR_BODY:
          root = buildConstructorBody(element);
          break;

        case ElementKind.FACTORY_CONSTRUCTOR:
        case ElementKind.FUNCTION:
        case ElementKind.GETTER:
        case ElementKind.SETTER:
          root = buildFunction(element);
          break;

        case ElementKind.FIELD:
          if (Elements.isStaticOrTopLevel(element)) {
            root = buildStaticFieldInitializer(element);
          } else {
            // Instance field initializers are inlined in the constructor,
            // so we shouldn't need to build anything here.
            // TODO(asgerf): But what should we return?
            return null;
          }
          break;

        default:
          reporter.internalError(element, "Unexpected element type $element");
      }
      return root;
    });
  }

  /// Loads the type variables for all super classes of [superClass] into the
  /// IR builder's environment with their corresponding values.
  ///
  /// The type variables for [currentClass] must already be in the IR builder's
  /// environment.
  ///
  /// Type variables are stored as [TypeVariableLocal] in the environment.
  ///
  /// This ensures that access to type variables mentioned inside the
  /// constructors and initializers will happen through the local environment
  /// instead of using 'this'.
  void loadTypeVariablesForSuperClasses(ClassElement currentClass) {
    if (currentClass.isObject) return;
    loadTypeVariablesForType(currentClass.supertype);
    if (currentClass is MixinApplicationElement) {
      loadTypeVariablesForType(currentClass.mixinType);
    }
  }

  /// Loads all type variables for [type] and all of its super classes into
  /// the environment. All type variables mentioned in [type] must already
  /// be in the environment.
  void loadTypeVariablesForType(InterfaceType type) {
    ClassElement clazz = type.element;
    assert(clazz.typeVariables.length == type.typeArguments.length);
    for (int i = 0; i < clazz.typeVariables.length; ++i) {
      irBuilder.declareTypeVariable(clazz.typeVariables[i],
          type.typeArguments[i]);
    }
    loadTypeVariablesForSuperClasses(clazz);
  }

  /// Returns the constructor body associated with the given constructor or
  /// creates a new constructor body, if none can be found.
  ///
  /// Returns `null` if the constructor does not have a body.
  ConstructorBodyElement getConstructorBody(FunctionElement constructor) {
    // TODO(asgerf): This is largely inherited from the SSA builder.
    // The ConstructorBodyElement has an invalid function signature, but we
    // cannot add a BoxLocal as parameter, because BoxLocal is not an element.
    // Instead of forging ParameterElements to forge a FunctionSignature, we
    // need a way to create backend methods without creating more fake elements.
    assert(constructor.isGenerativeConstructor);
    assert(constructor.isImplementation);
    if (constructor.isSynthesized) return null;
    ast.FunctionExpression node = constructor.node;
    // If we know the body doesn't have any code, we don't generate it.
    if (!node.hasBody()) return null;
    if (node.hasEmptyBody()) return null;
    ClassElement classElement = constructor.enclosingClass;
    ConstructorBodyElement bodyElement;
    classElement.forEachBackendMember((Element backendMember) {
      if (backendMember.isGenerativeConstructorBody) {
        ConstructorBodyElement body = backendMember;
        if (body.constructor == constructor) {
          bodyElement = backendMember;
        }
      }
    });
    if (bodyElement == null) {
      bodyElement = new ConstructorBodyElementX(constructor);
      classElement.addBackendMember(bodyElement);

      if (constructor.isPatch) {
        // Create origin body element for patched constructors.
        ConstructorBodyElementX patch = bodyElement;
        ConstructorBodyElementX origin =
        new ConstructorBodyElementX(constructor.origin);
        origin.applyPatch(patch);
        classElement.origin.addBackendMember(bodyElement.origin);
      }
    }
    assert(bodyElement.isGenerativeConstructorBody);
    return bodyElement;
  }

  /// The list of parameters to send from the generative constructor
  /// to the generative constructor body.
  ///
  /// Boxed parameters are not in the list, instead, a [BoxLocal] is passed
  /// containing the boxed parameters.
  ///
  /// For example, given the following constructor,
  ///
  ///     Foo(x, y) : field = (() => ++x) { print(x + y) }
  ///
  /// the argument `x` would be replaced by a [BoxLocal]:
  ///
  ///     Foo_body(box0, y) { print(box0.x + y) }
  ///
  List<Local> getConstructorBodyParameters(ConstructorBodyElement body) {
    List<Local> parameters = <Local>[];
    ClosureScope scope = getClosureScopeForFunction(body.constructor);
    if (scope != null) {
      parameters.add(scope.box);
    }
    body.functionSignature.orderedForEachParameter((ParameterElement param) {
      if (scope != null && scope.capturedVariables.containsKey(param)) {
        // Do not pass this parameter; the box will carry its value.
      } else {
        parameters.add(param);
      }
    });
    return parameters;
  }

  /// Builds the IR for a given constructor.
  ///
  /// 1. Computes the type held in all own or "inherited" type variables.
  /// 2. Evaluates all own or inherited field initializers.
  /// 3. Creates the object and assigns its fields and runtime type.
  /// 4. Calls constructor body and super constructor bodies.
  /// 5. Returns the created object.
  ir.FunctionDefinition buildConstructor(ConstructorElement constructor) {
    // TODO(asgerf): Optimization: If constructor is redirecting, then just
    //               evaluate arguments and call the target constructor.
    constructor = constructor.implementation;
    ClassElement classElement = constructor.enclosingClass.implementation;

    IrBuilder builder = getBuilderFor(constructor);

    final bool requiresTypeInformation =
        builder.program.requiresRuntimeTypesFor(classElement);

    return withBuilder(builder, () {
      // Setup parameters and create a box if anything is captured.
      List<Local> parameters = <Local>[];
      constructor.functionSignature.orderedForEachParameter(
          (ParameterElement p) => parameters.add(p));

      int firstTypeArgumentParameterIndex;

      // If instances of the class may need runtime type information, we add a
      // synthetic parameter for each type parameter.
      if (requiresTypeInformation) {
        firstTypeArgumentParameterIndex = parameters.length;
        classElement.typeVariables.forEach((TypeVariableType variable) {
          parameters.add(new closure.TypeVariableLocal(variable, constructor));
        });
      } else {
        classElement.typeVariables.forEach((TypeVariableType variable) {
          irBuilder.declareTypeVariable(variable, const DynamicType());
        });
      }

      // Create IR parameters and setup the environment.
      List<ir.Parameter> irParameters = builder.buildFunctionHeader(parameters,
          closureScope: getClosureScopeForFunction(constructor));

      // Create a list of the values of all type argument parameters, if any.
      ir.Primitive typeInformation;
      if (requiresTypeInformation) {
        typeInformation = new ir.TypeExpression(
            ir.TypeExpressionKind.INSTANCE,
            classElement.thisType,
            irParameters.sublist(firstTypeArgumentParameterIndex));
        irBuilder.add(new ir.LetPrim(typeInformation));
      } else {
        typeInformation = null;
      }

      // -- Load values for type variables declared on super classes --
      // Field initializers for super classes can reference these, so they
      // must be available before evaluating field initializers.
      // This could be interleaved with field initialization, but we choose do
      // get it out of the way here to avoid complications with mixins.
      loadTypeVariablesForSuperClasses(classElement);

      /// Maps each field from this class or a superclass to its initial value.
      Map<FieldElement, ir.Primitive> fieldValues =
          <FieldElement, ir.Primitive>{};

      // -- Evaluate field initializers ---
      // Evaluate field initializers in constructor and super constructors.
      List<ConstructorElement> constructorList = <ConstructorElement>[];
      evaluateConstructorFieldInitializers(
          constructor, constructorList, fieldValues);

      // All parameters in all constructors are now bound in the environment.
      // BoxLocals for captured parameters are also in the environment.
      // The initial value of all fields are now bound in [fieldValues].

      // --- Create the object ---
      // Get the initial field values in the canonical order.
      List<ir.Primitive> instanceArguments = <ir.Primitive>[];
      classElement.forEachInstanceField((ClassElement c, FieldElement field) {
        ir.Primitive value = fieldValues[field];
        if (value != null) {
          instanceArguments.add(value);
        } else {
          assert(backend.isNativeOrExtendsNative(c));
          // Native fields are initialized elsewhere.
        }
      }, includeSuperAndInjectedMembers: true);

      ir.Primitive instance = new ir.CreateInstance(
          classElement,
          instanceArguments,
          typeInformation,
          constructor.hasNode
              ? sourceInformationBuilder.buildCreate(constructor.node)
          // TODO(johnniwinther): Provide source information for creation
          // through synthetic constructors.
              : null);
      irBuilder.add(new ir.LetPrim(instance));

      // --- Call constructor bodies ---
      for (ConstructorElement target in constructorList) {
        ConstructorBodyElement bodyElement = getConstructorBody(target);
        if (bodyElement == null) continue; // Skip if constructor has no body.
        List<ir.Primitive> bodyArguments = <ir.Primitive>[];
        for (Local param in getConstructorBodyParameters(bodyElement)) {
          bodyArguments.add(irBuilder.environment.lookup(param));
        }
        Selector selector = new Selector.call(target.memberName,
            new CallStructure(bodyArguments.length));
        irBuilder.addPrimitive(new ir.InvokeMethodDirectly(
            instance, bodyElement, selector, bodyArguments, null));
      }

      // --- step 4: return the created object ----
      irBuilder.buildReturn(
          value: instance,
          sourceInformation:
          sourceInformationBuilder.buildImplicitReturn(constructor));

      return irBuilder.makeFunctionDefinition();
    });
  }

  /// Make a visitor suitable for translating ASTs taken from [context].
  ///
  /// Every visitor can only be applied to nodes in one context, because
  /// the [elements] field is specific to that context.
  IrBuilderVisitor makeVisitorForContext(AstElement context) {
    return new IrBuilderVisitor(
        context.resolvedAst.elements,
        compiler,
        sourceInformationBuilder.forContext(context),
        typeMaskSystem);
  }

  /// Builds the IR for an [expression] taken from a different [context].
  ///
  /// Such expressions need to be compiled with a different [sourceFile] and
  /// [elements] mapping.
  ir.Primitive inlineExpression(AstElement context, ast.Expression expression) {
    IrBuilderVisitor visitor = makeVisitorForContext(context);
    return visitor.withBuilder(irBuilder, () => visitor.visit(expression));
  }

  /// Evaluate the implicit super call in the given mixin constructor.
  void forwardSynthesizedMixinConstructor(
      ConstructorElement constructor,
      List<ConstructorElement> supers,
      Map<FieldElement, ir.Primitive> fieldValues) {
    assert(constructor.enclosingClass.implementation.isMixinApplication);
    assert(constructor.isSynthesized);
    ConstructorElement target =
        constructor.definingConstructor.implementation;
    // The resolver gives us the exact same FunctionSignature for the two
    // constructors. The parameters for the synthesized constructor
    // are already in the environment, so the target constructor's parameters
    // are also in the environment since their elements are the same.
    assert(constructor.functionSignature == target.functionSignature);
    IrBuilderVisitor visitor = makeVisitorForContext(target);
    visitor.withBuilder(irBuilder, () {
      visitor.evaluateConstructorFieldInitializers(target, supers, fieldValues);
    });
  }

  /// In preparation of inlining (part of) [target], the [arguments] are moved
  /// into the environment bindings for the corresponding parameters.
  ///
  /// Defaults for optional arguments are evaluated in order to ensure
  /// all parameters are available in the environment.
  void loadArguments(ConstructorElement target,
      CallStructure call,
      List<ir.Primitive> arguments) {
    assert(target.isImplementation);
    assert(target == elements.analyzedElement);
    FunctionSignature signature = target.functionSignature;

    // Establish a scope in case parameters are captured.
    ClosureScope scope = getClosureScopeForFunction(target);
    irBuilder.enterScope(scope);

    // Load required parameters
    int index = 0;
    signature.forEachRequiredParameter((ParameterElement param) {
      irBuilder.declareLocalVariable(param, initialValue: arguments[index]);
      index++;
    });

    // Load optional parameters, evaluating default values for omitted ones.
    signature.forEachOptionalParameter((ParameterElement param) {
      ir.Primitive value;
      // Load argument if provided.
      if (signature.optionalParametersAreNamed) {
        int nameIndex = call.namedArguments.indexOf(param.name);
        if (nameIndex != -1) {
          int translatedIndex = call.positionalArgumentCount + nameIndex;
          value = arguments[translatedIndex];
        }
      } else if (index < arguments.length) {
        value = arguments[index];
      }
      // Load default if argument was not provided.
      if (value == null) {
        if (param.initializer != null) {
          value = visit(param.initializer);
        } else {
          value = irBuilder.buildNullConstant();
        }
      }
      irBuilder.declareLocalVariable(param, initialValue: value);
      index++;
    });
  }

  /// Evaluates a call to the given constructor from an initializer list.
  ///
  /// Calls [loadArguments] and [evaluateConstructorFieldInitializers] in a
  /// visitor that has the proper [TreeElements] mapping.
  void evaluateConstructorCallFromInitializer(
      ConstructorElement target,
      CallStructure call,
      List<ir.Primitive> arguments,
      List<ConstructorElement> supers,
      Map<FieldElement, ir.Primitive> fieldValues) {
    IrBuilderVisitor visitor = makeVisitorForContext(target);
    visitor.withBuilder(irBuilder, () {
      visitor.loadArguments(target, call, arguments);
      visitor.evaluateConstructorFieldInitializers(target, supers, fieldValues);
    });
  }

  /// Evaluates all field initializers on [constructor] and all constructors
  /// invoked through `this()` or `super()` ("superconstructors").
  ///
  /// The resulting field values will be available in [fieldValues]. The values
  /// are not stored in any fields.
  ///
  /// This procedure assumes that the parameters to [constructor] are available
  /// in the IR builder's environment.
  ///
  /// The parameters to superconstructors are, however, assumed *not* to be in
  /// the environment, but will be put there by this procedure.
  ///
  /// All constructors will be added to [supers], with superconstructors first.
  void evaluateConstructorFieldInitializers(
      ConstructorElement constructor,
      List<ConstructorElement> supers,
      Map<FieldElement, ir.Primitive> fieldValues) {
    assert(constructor.isImplementation);
    assert(constructor == elements.analyzedElement);
    ClassElement enclosingClass = constructor.enclosingClass.implementation;
    // Evaluate declaration-site field initializers, unless this constructor
    // redirects to another using a `this()` initializer. In that case, these
    // will be initialized by the effective target constructor.
    if (!constructor.isRedirectingGenerative) {
      enclosingClass.forEachInstanceField((ClassElement c, FieldElement field) {
        if (field.initializer != null) {
          fieldValues[field] = inlineExpression(field, field.initializer);
        } else {
          if (backend.isNativeOrExtendsNative(c)) {
            // Native field is initialized elsewhere.
          } else {
            // Fields without an initializer default to null.
            // This value will be overwritten below if an initializer is found.
            fieldValues[field] = irBuilder.buildNullConstant();
          }
        }
      });
    }
    // If this is a mixin constructor, it does not have its own parameter list
    // or initializer list. Directly forward to the super constructor.
    // Note that the declaration-site initializers originating from the
    // mixed-in class were handled above.
    if (enclosingClass.isMixinApplication) {
      forwardSynthesizedMixinConstructor(constructor, supers, fieldValues);
      return;
    }
    // Evaluate initializing parameters, e.g. `Foo(this.x)`.
    constructor.functionSignature.orderedForEachParameter(
        (ParameterElement parameter) {
      if (parameter.isInitializingFormal) {
        InitializingFormalElement fieldParameter = parameter;
        fieldValues[fieldParameter.fieldElement] =
            irBuilder.buildLocalGet(parameter);
      }
    });
    // Evaluate constructor initializers, e.g. `Foo() : x = 50`.
    ast.FunctionExpression node = constructor.node;
    bool hasConstructorCall = false; // Has this() or super() initializer?
    if (node != null && node.initializers != null) {
      for(ast.Node initializer in node.initializers) {
        if (initializer is ast.SendSet) {
          // Field initializer.
          FieldElement field = elements[initializer];
          fieldValues[field] = visit(initializer.arguments.head);
        } else if (initializer is ast.Send) {
          // Super or this initializer.
          ConstructorElement target = elements[initializer].implementation;
          Selector selector = elements.getSelector(initializer);
          List<ir.Primitive> arguments = initializer.arguments.mapToList(visit);
          evaluateConstructorCallFromInitializer(
              target,
              selector.callStructure,
              arguments,
              supers,
              fieldValues);
          hasConstructorCall = true;
        } else {
          reporter.internalError(initializer,
              "Unexpected initializer type $initializer");
        }
      }
    }
    // If no super() or this() was found, also call default superconstructor.
    if (!hasConstructorCall && !enclosingClass.isObject) {
      ClassElement superClass = enclosingClass.superclass;
      FunctionElement target = superClass.lookupDefaultConstructor();
      if (target == null) {
        reporter.internalError(superClass, "No default constructor available.");
      }
      target = target.implementation;
      evaluateConstructorCallFromInitializer(
          target,
          CallStructure.NO_ARGS,
          const [],
          supers,
          fieldValues);
    }
    // Add this constructor after the superconstructors.
    supers.add(constructor);
  }

  TryBoxedVariables _analyzeTryBoxedVariables(ast.Node node) {
    TryBoxedVariables variables = new TryBoxedVariables(elements);
    try {
      variables.analyze(node);
    } catch (e) {
      bailoutMessage = variables.bailoutMessage;
      rethrow;
    }
    return variables;
  }

  /// Builds the IR for the body of a constructor.
  ///
  /// This function is invoked from one or more "factory" constructors built by
  /// [buildConstructor].
  ir.FunctionDefinition buildConstructorBody(ConstructorBodyElement body) {
    ConstructorElement constructor = body.constructor;
    ast.FunctionExpression node = constructor.node;
    closureClassMap =
        compiler.closureToClassMapper.computeClosureToClassMapping(
            constructor,
            node,
            elements);

    // We compute variables boxed in mutable variables on entry to each try
    // block, not including variables captured by a closure (which are boxed
    // in the heap).  This duplicates some of the work of closure conversion
    // without directly using the results.  This duplication is wasteful and
    // error-prone.
    // TODO(kmillikin): We should combine closure conversion and try/catch
    // variable analysis in some way.
    TryBoxedVariables variables = _analyzeTryBoxedVariables(node);
    tryStatements = variables.tryStatements;
    IrBuilder builder = getBuilderFor(body);

    return withBuilder(builder, () {
      irBuilder.buildConstructorBodyHeader(getConstructorBodyParameters(body),
          getClosureScopeForNode(node));
      visit(node.body);
      return irBuilder.makeFunctionDefinition();
    });
  }

  ir.FunctionDefinition buildFunction(FunctionElement element) {
    assert(invariant(element, element.isImplementation));
    ast.FunctionExpression node = element.node;

    assert(!element.isSynthesized);
    assert(node != null);
    assert(elements[node] != null);

    closureClassMap =
        compiler.closureToClassMapper.computeClosureToClassMapping(
            element,
            node,
            elements);
    TryBoxedVariables variables = _analyzeTryBoxedVariables(node);
    tryStatements = variables.tryStatements;
    IrBuilder builder = getBuilderFor(element);
    return withBuilder(builder,
        () => _makeFunctionBody(builder, element, node));
  }

  ir.FunctionDefinition buildStaticFieldInitializer(FieldElement element) {
    if (!backend.constants.lazyStatics.contains(element)) {
      return null; // Nothing to do.
    }
    closureClassMap =
        compiler.closureToClassMapper.computeClosureToClassMapping(
            element,
            element.node,
            elements);
    IrBuilder builder = getBuilderFor(element);
    return withBuilder(builder, () {
      irBuilder.buildFunctionHeader(<Local>[]);
      ir.Primitive initialValue = visit(element.initializer);
      ast.VariableDefinitions node = element.node;
      ast.SendSet sendSet = node.definitions.nodes.head;
      irBuilder.buildReturn(
          value: initialValue,
          sourceInformation:
          sourceInformationBuilder.buildReturn(sendSet.assignmentOperator));
      return irBuilder.makeFunctionDefinition();
    });
  }

  /// Builds the IR for a constant taken from a different [context].
  ///
  /// Such constants need to be compiled with a different [sourceFile] and
  /// [elements] mapping.
  ir.Primitive inlineConstant(AstElement context, ast.Expression exp) {
    IrBuilderVisitor visitor = makeVisitorForContext(context);
    return visitor.withBuilder(irBuilder, () => visitor.translateConstant(exp));
  }

  /// Creates a primitive for the default value of [parameter].
  ir.Primitive translateDefaultValue(ParameterElement parameter) {
    if (parameter.initializer == null ||
        // TODO(sigmund): JS doesn't support default values, so this should be
        // reported as an error earlier (Issue #25759).
        backend.isJsInterop(parameter.functionDeclaration)) {
      return irBuilder.buildNullConstant();
    } else {
      return inlineConstant(parameter.executableContext, parameter.initializer);
    }
  }

  /// Normalizes the argument list of a static invocation.
  ///
  /// A static invocation is one where the target is known.  The argument list
  /// [arguments] is normalized by adding default values for optional arguments
  /// that are not passed, and by sorting it in place so that named arguments
  /// appear in a canonical order.  A [CallStructure] reflecting this order
  /// is returned.
  CallStructure normalizeStaticArguments(CallStructure callStructure,
      FunctionElement target,
      List<ir.Primitive> arguments) {
    target = target.implementation;
    FunctionSignature signature = target.functionSignature;
    if (!signature.optionalParametersAreNamed &&
        signature.parameterCount == arguments.length) {
      return callStructure;
    }

    if (!signature.optionalParametersAreNamed) {
      int i = signature.requiredParameterCount;
      signature.forEachOptionalParameter((ParameterElement element) {
        if (i < callStructure.positionalArgumentCount) {
          ++i;
        } else {
          arguments.add(translateDefaultValue(element));
        }
      });
      return new CallStructure(signature.parameterCount);
    }

    int offset = signature.requiredParameterCount;
    List<ir.Primitive> namedArguments = arguments.sublist(offset);
    arguments.length = offset;
    List<String> normalizedNames = <String>[];
    // Iterate over the optional parameters of the signature, and try to
    // find them in the callStructure's named arguments. If found, we use the
    // value in the temporary list, otherwise the default value.
    signature.orderedOptionalParameters.forEach((ParameterElement element) {
      int nameIndex = callStructure.namedArguments.indexOf(element.name);
      arguments.add(nameIndex == -1 ? translateDefaultValue(element)
          : namedArguments[nameIndex]);
      normalizedNames.add(element.name);
    });
    return new CallStructure(signature.parameterCount, normalizedNames);
  }

  /// Normalizes the argument list of a dynamic invocation.
  ///
  /// A dynamic invocation is one where the target is not known.  The argument
  /// list [arguments] is normalized by sorting it in place so that the named
  /// arguments appear in a canonical order.  A [CallStructure] reflecting this
  /// order is returned.
  CallStructure normalizeDynamicArguments(CallStructure callStructure,
      List<ir.Primitive> arguments) {
    assert(arguments.length == callStructure.argumentCount);
    if (callStructure.namedArguments.isEmpty) return callStructure;
    int destinationIndex = callStructure.positionalArgumentCount;
    List<ir.Primitive> namedArguments = arguments.sublist(destinationIndex);
    for (String argName in callStructure.getOrderedNamedArguments()) {
      int sourceIndex = callStructure.namedArguments.indexOf(argName);
      arguments[destinationIndex++] = namedArguments[sourceIndex];
    }
    return new CallStructure(callStructure.argumentCount,
        callStructure.getOrderedNamedArguments());
  }

  /// Read the value of [field].
  ir.Primitive buildStaticFieldGet(FieldElement field, SourceInformation src) {
    ConstantValue constant = getConstantForVariable(field);
    if (constant != null && !field.isAssignable) {
      typeMaskSystem.associateConstantValueWithElement(constant, field);
      return irBuilder.buildConstant(constant, sourceInformation: src);
    } else if (backend.constants.lazyStatics.contains(field)) {
      return irBuilder.addPrimitive(new ir.GetLazyStatic(field, src));
    } else {
      return irBuilder.addPrimitive(new ir.GetStatic(field, src));
    }
  }

  ir.FunctionDefinition _makeFunctionBody(
      IrBuilder builder,
      FunctionElement element,
      ast.FunctionExpression node) {
    FunctionSignature signature = element.functionSignature;
    List<Local> parameters = <Local>[];
    signature.orderedForEachParameter(
        (LocalParameterElement e) => parameters.add(e));

    bool requiresRuntimeTypes = false;
    if (element.isFactoryConstructor) {
      requiresRuntimeTypes =
          builder.program.requiresRuntimeTypesFor(element.enclosingElement);
      if (requiresRuntimeTypes) {
        // Type arguments are passed in as extra parameters.
        for (DartType typeVariable in element.enclosingClass.typeVariables) {
          parameters.add(new closure.TypeVariableLocal(typeVariable, element));
        }
      }
    }

    irBuilder.buildFunctionHeader(parameters,
                                  closureScope: getClosureScopeForNode(node),
                                  env: getClosureEnvironment());

    if (element == helpers.jsArrayTypedConstructor) {
      // Generate a body for JSArray<E>.typed(allocation):
      //
      //    t1 = setRuntimeTypeInfo(allocation, TypeExpression($E));
      //    return Refinement(t1, <JSArray>);
      //
      assert(parameters.length == 1 || parameters.length == 2);
      ir.Primitive allocation = irBuilder.buildLocalGet(parameters[0]);
      ClassElement classElement = element.enclosingElement;

      // Only call setRuntimeTypeInfo if JSArray requires the type parameter.
      if (requiresRuntimeTypes) {
        assert(parameters.length == 2);
        closure.TypeVariableLocal typeParameter = parameters[1];
        ir.Primitive typeArgument =
            irBuilder.buildTypeVariableAccess(typeParameter.typeVariable);

        ir.Primitive typeInformation = irBuilder.addPrimitive(
            new ir.TypeExpression(ir.TypeExpressionKind.INSTANCE,
                                  element.enclosingClass.thisType,
                                  <ir.Primitive>[typeArgument]));

        MethodElement helper = helpers.setRuntimeTypeInfo;
        CallStructure callStructure = CallStructure.TWO_ARGS;
        Selector selector = new Selector.call(helper.memberName, callStructure);
        allocation = irBuilder.buildInvokeStatic(
            helper, selector, <ir.Primitive>[allocation, typeInformation],
            sourceInformationBuilder.buildGeneric(node));
      }

      ir.Primitive refinement = irBuilder.addPrimitive(
          new ir.Refinement(allocation, typeMaskSystem.arrayType));

      irBuilder.buildReturn(value: refinement,
          sourceInformation:
              sourceInformationBuilder.buildImplicitReturn(element));
    } else {
      visit(node.body);
    }
    return irBuilder.makeFunctionDefinition();
  }

  /// Builds the IR for creating an instance of the closure class corresponding
  /// to the given nested function.
  closure.ClosureClassElement makeSubFunction(ast.FunctionExpression node) {
    closure.ClosureClassMap innerMap =
        compiler.closureToClassMapper.getMappingForNestedFunction(node);
    closure.ClosureClassElement closureClass = innerMap.closureClassElement;
    return closureClass;
  }

  ir.Primitive visitFunctionExpression(ast.FunctionExpression node) {
    return irBuilder.buildFunctionExpression(makeSubFunction(node),
        sourceInformationBuilder.buildCreate(node));
  }

  visitFunctionDeclaration(ast.FunctionDeclaration node) {
    LocalFunctionElement element = elements[node.function];
    Object inner = makeSubFunction(node.function);
    irBuilder.declareLocalFunction(element, inner,
        sourceInformationBuilder.buildCreate(node.function));
  }

  // ## Statements ##
  visitBlock(ast.Block node) {
    irBuilder.buildBlock(node.statements.nodes, build);
  }

  ir.Primitive visitBreakStatement(ast.BreakStatement node) {
    if (!irBuilder.buildBreak(elements.getTargetOf(node))) {
      reporter.internalError(node, "'break' target not found");
    }
    return null;
  }

  ir.Primitive visitContinueStatement(ast.ContinueStatement node) {
    if (!irBuilder.buildContinue(elements.getTargetOf(node))) {
      reporter.internalError(node, "'continue' target not found");
    }
    return null;
  }

  // Build(EmptyStatement, C) = C
  ir.Primitive visitEmptyStatement(ast.EmptyStatement node) {
    assert(irBuilder.isOpen);
    return null;
  }

  // Build(ExpressionStatement(e), C) = C'
  //   where (C', _) = Build(e, C)
  ir.Primitive visitExpressionStatement(ast.ExpressionStatement node) {
    assert(irBuilder.isOpen);
    if (node.expression is ast.Throw) {
      // Throw expressions that occur as statements are translated differently
      // from ones that occur as subexpressions.  This is achieved by peeking
      // at statement-level expressions here.
      irBuilder.buildThrow(visit(node.expression));
    } else {
      visit(node.expression);
    }
    return null;
  }

  ir.Primitive visitRethrow(ast.Rethrow node) {
    assert(irBuilder.isOpen);
    irBuilder.buildRethrow();
    return null;
  }

  /// Construct a method that executes the forwarding call to the target
  /// constructor.  This is only required, if the forwarding factory
  /// constructor can potentially be the target of a reflective call, because
  /// the builder shortcuts calls to redirecting factories at the call site
  /// (see [handleConstructorInvoke]).
  visitRedirectingFactoryBody(ast.RedirectingFactoryBody node) {
    ConstructorElement targetConstructor =
        elements.getRedirectingTargetConstructor(node).implementation;
    ConstructorElement redirectingConstructor =
        irBuilder.state.currentElement.implementation;
    List<ir.Primitive> arguments = <ir.Primitive>[];
    FunctionSignature redirectingSignature =
        redirectingConstructor.functionSignature;
    List<String> namedParameters = <String>[];
    redirectingSignature.forEachParameter((ParameterElement parameter) {
      arguments.add(irBuilder.environment.lookup(parameter));
      if (parameter.isNamed) {
        namedParameters.add(parameter.name);
      }
    });
    ClassElement cls = redirectingConstructor.enclosingClass;
    InterfaceType targetType =
          redirectingConstructor.computeEffectiveTargetType(cls.thisType);
    CallStructure callStructure = new CallStructure(
        redirectingSignature.parameterCount,
        namedParameters);
    callStructure =
        normalizeStaticArguments(callStructure, targetConstructor, arguments);
    ir.Primitive instance = irBuilder.buildConstructorInvocation(
        targetConstructor,
        callStructure,
        targetType,
        arguments,
        sourceInformationBuilder.buildNew(node));
    irBuilder.buildReturn(
        value: instance,
        sourceInformation: sourceInformationBuilder.buildReturn(node));
  }

  visitFor(ast.For node) {
    List<LocalElement> loopVariables = <LocalElement>[];
    if (node.initializer is ast.VariableDefinitions) {
      ast.VariableDefinitions definitions = node.initializer;
      for (ast.Node node in definitions.definitions.nodes) {
        LocalElement loopVariable = elements[node];
        loopVariables.add(loopVariable);
      }
    }

    JumpTarget target = elements.getTargetDefinition(node);
    irBuilder.buildFor(
        buildInitializer: subbuild(node.initializer),
        buildCondition: subbuild(node.condition),
        buildBody: subbuild(node.body),
        buildUpdate: subbuildSequence(node.update),
        closureScope: getClosureScopeForNode(node),
        loopVariables: loopVariables,
        target: target);
  }

  visitIf(ast.If node) {
    irBuilder.buildIf(
        build(node.condition),
        subbuild(node.thenPart),
        subbuild(node.elsePart));
  }

  visitLabeledStatement(ast.LabeledStatement node) {
    ast.Statement body = node.statement;
    if (body is ast.Loop) {
      visit(body);
    } else {
      JumpTarget target = elements.getTargetDefinition(body);
      irBuilder.buildLabeledStatement(
          buildBody: subbuild(body),
          target: target);
    }
  }

  visitDoWhile(ast.DoWhile node) {
    irBuilder.buildDoWhile(
        buildBody: subbuild(node.body),
        buildCondition: subbuild(node.condition),
        target: elements.getTargetDefinition(node),
        closureScope: getClosureScopeForNode(node));
  }

  visitWhile(ast.While node) {
    irBuilder.buildWhile(
        buildCondition: subbuild(node.condition),
        buildBody: subbuild(node.body),
        target: elements.getTargetDefinition(node),
        closureScope: getClosureScopeForNode(node));
  }

  visitAsyncForIn(ast.AsyncForIn node) {
    // Translate await for into a loop over a StreamIterator.  The source
    // statement:
    //
    // await for (<decl> in <stream>) <body>
    //
    // is translated as if it were:
    //
    // var iterator = new StreamIterator(<stream>);
    // try {
    //   while (await iterator.hasNext()) {
    //     <decl> = await iterator.current;
    //     <body>
    //   }
    // } finally {
    //   await iterator.cancel();
    // }
    ir.Primitive stream = visit(node.expression);
    ir.Primitive dummyTypeArgument = irBuilder.buildNullConstant();
    ConstructorElement constructor = helpers.streamIteratorConstructor;
    ir.Primitive iterator = irBuilder.addPrimitive(new ir.InvokeConstructor(
        constructor.enclosingClass.thisType,
        constructor,
        new Selector.callConstructor(constructor.memberName, 1),
        <ir.Primitive>[stream, dummyTypeArgument],
        sourceInformationBuilder.buildGeneric(node)));

    ir.Node buildTryBody(IrBuilder builder) {
      ir.Node buildLoopCondition(IrBuilder builder) {
        ir.Primitive moveNext = builder.buildDynamicInvocation(
            iterator,
            Selectors.moveNext,
            elements.getMoveNextTypeMask(node),
            <ir.Primitive>[]);
        return builder.addPrimitive(new ir.Await(moveNext));
      }

      ir.Node buildLoopBody(IrBuilder builder) {
        return withBuilder(builder, () {
          ir.Primitive current = irBuilder.buildDynamicInvocation(
              iterator,
              Selectors.current,
              elements.getCurrentTypeMask(node),
              <ir.Primitive>[]);
          Element variable = elements.getForInVariable(node);
          if (Elements.isLocal(variable)) {
            if (node.declaredIdentifier.asVariableDefinitions() != null) {
              irBuilder.declareLocalVariable(variable);
            }
            irBuilder.buildLocalVariableSet(variable, current);
          } else if (Elements.isError(variable) ||
                     Elements.isMalformed(variable)) {
            Selector selector =
                new Selector.setter(new Name(variable.name, variable.library));
            List<ir.Primitive> args = <ir.Primitive>[current];
            // Note the comparison below.  It can be the case that an element
            // isError and isMalformed.
            if (Elements.isError(variable)) {
              irBuilder.buildStaticNoSuchMethod(selector, args);
            } else {
              irBuilder.buildErroneousInvocation(variable, selector, args);
            }
          } else if (Elements.isStaticOrTopLevel(variable)) {
            if (variable.isField) {
              irBuilder.addPrimitive(new ir.SetStatic(variable, current));
            } else {
              irBuilder.buildStaticSetterSet(variable, current);
            }
          } else {
            ir.Primitive receiver = irBuilder.buildThis();
            ast.Node identifier = node.declaredIdentifier;
            irBuilder.buildDynamicSet(
                receiver,
                elements.getSelector(identifier),
                elements.getTypeMask(identifier),
                current);
          }
          visit(node.body);
        });
      }

      builder.buildWhile(
          buildCondition: buildLoopCondition,
          buildBody: buildLoopBody,
          target: elements.getTargetDefinition(node),
          closureScope: getClosureScopeForNode(node));
    }

    ir.Node buildFinallyBody(IrBuilder builder) {
      ir.Primitive cancellation = builder.buildDynamicInvocation(
          iterator,
          Selectors.cancel,
          backend.dynamicType,
          <ir.Primitive>[],
          sourceInformation: sourceInformationBuilder.buildGeneric(node));
      return builder.addPrimitive(new ir.Await(cancellation));
    }

    irBuilder.buildTryFinally(new TryStatementInfo(), buildTryBody,
        buildFinallyBody);
  }

  visitAwait(ast.Await node) {
    assert(irBuilder.isOpen);
    ir.Primitive value = visit(node.expression);
    return irBuilder.addPrimitive(new ir.Await(value));
  }

  visitYield(ast.Yield node) {
    assert(irBuilder.isOpen);
    ir.Primitive value = visit(node.expression);
    return irBuilder.addPrimitive(new ir.Yield(value, node.hasStar));
  }

  visitSyncForIn(ast.SyncForIn node) {
    // [node.declaredIdentifier] can be either an [ast.VariableDefinitions]
    // (defining a new local variable) or a send designating some existing
    // variable.
    ast.Node identifier = node.declaredIdentifier;
    ast.VariableDefinitions variableDeclaration =
        identifier.asVariableDefinitions();
    Element variableElement = elements.getForInVariable(node);
    Selector selector = elements.getSelector(identifier);

    irBuilder.buildForIn(
        buildExpression: subbuild(node.expression),
        buildVariableDeclaration: subbuild(variableDeclaration),
        variableElement: variableElement,
        variableSelector: selector,
        variableMask: elements.getTypeMask(identifier),
        currentMask: elements.getCurrentTypeMask(node),
        moveNextMask: elements.getMoveNextTypeMask(node),
        iteratorMask: elements.getIteratorTypeMask(node),
        buildBody: subbuild(node.body),
        target: elements.getTargetDefinition(node),
        closureScope: getClosureScopeForNode(node));
  }

  /// If compiling with trusted type annotations, assumes that [value] is
  /// now known to be `null` or an instance of [type].
  ///
  /// This is also where we should add type checks in checked mode, but this
  /// is not supported yet.
  ir.Primitive checkType(ir.Primitive value, DartType dartType) {
    if (!compiler.trustTypeAnnotations) return value;
    TypeMask type = typeMaskSystem.subtypesOf(dartType).nullable();
    return irBuilder.addPrimitive(new ir.Refinement(value, type));
  }

  ir.Primitive checkTypeVsElement(ir.Primitive value, TypedElement element) {
    return checkType(value, element.type);
  }

  ir.Primitive visitVariableDefinitions(ast.VariableDefinitions node) {
    assert(irBuilder.isOpen);
    for (ast.Node definition in node.definitions.nodes) {
      Element element = elements[definition];
      ir.Primitive initialValue;
      // Definitions are either SendSets if there is an initializer, or
      // Identifiers if there is no initializer.
      if (definition is ast.SendSet) {
        assert(!definition.arguments.isEmpty);
        assert(definition.arguments.tail.isEmpty);
        initialValue = visit(definition.arguments.head);
        initialValue = checkTypeVsElement(initialValue, element);
      } else {
        assert(definition is ast.Identifier);
      }
      irBuilder.declareLocalVariable(element, initialValue: initialValue);
    }
    return null;
  }

  static final RegExp nativeRedirectionRegExp =
      new RegExp(r'^[a-zA-Z][a-zA-Z_$0-9]*$');

  // 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.
  visitReturn(ast.Return node) {
    assert(irBuilder.isOpen);
    SourceInformation source = sourceInformationBuilder.buildReturn(node);
    if (node.beginToken.value == 'native') {
      FunctionElement function = irBuilder.state.currentElement;
      assert(backend.isNative(function));
      ast.Node nativeBody = node.expression;
      if (nativeBody != null) {
        ast.LiteralString jsCode = nativeBody.asLiteralString();
        String javaScriptCode = jsCode.dartString.slowToString();
        assert(invariant(nativeBody,
            !nativeRedirectionRegExp.hasMatch(javaScriptCode),
          message: "Deprecated syntax, use @JSName('name') instead."));
        assert(invariant(nativeBody,
            function.functionSignature.parameterCount == 0,
            message: 'native "..." syntax is restricted to '
              'functions with zero parameters.'));
        irBuilder.buildNativeFunctionBody(function, javaScriptCode);
      } else {
        String name = backend.getFixedBackendName(function);
        irBuilder.buildRedirectingNativeFunctionBody(function, name, source);
      }
    } else {
      irBuilder.buildReturn(
          value: build(node.expression),
          sourceInformation: source);
    }
  }

  visitSwitchStatement(ast.SwitchStatement node) {
    // Dart switch cases can be labeled and be the target of continue from
    // within the switch.  Such cases are 'recursive'.  If there are any
    // recursive cases, we implement the switch using a pair of switches with
    // the second one switching over a state variable in a loop.  The first
    // switch contains the non-recursive cases, and the second switch contains
    // the recursive ones.
    //
    // For example, for the Dart switch:
    //
    // switch (E) {
    //   case 0:
    //     BODY0;
    //     break;
    //   LABEL0: case 1:
    //     BODY1;
    //     break;
    //   case 2:
    //     BODY2;
    //     continue LABEL1;
    //   LABEL1: case 3:
    //     BODY3;
    //     continue LABEL0;
    //   default:
    //     BODY4;
    // }
    //
    // We translate it as if it were the JavaScript:
    //
    // var state = -1;
    // switch (E) {
    //   case 0:
    //     BODY0;
    //     break;
    //   case 1:
    //     state = 0;  // Recursive, label ID = 0.
    //     break;
    //   case 2:
    //     BODY2;
    //     state = 1;  // Continue to label ID = 1.
    //     break;
    //   case 3:
    //     state = 1;  // Recursive, label ID = 1.
    //     break;
    //   default:
    //     BODY4;
    // }
    // L: while (state != -1) {
    //   case 0:
    //     BODY1;
    //     break L;  // Break from switch becomes break from loop.
    //   case 1:
    //     BODY2;
    //     state = 0;  // Continue to label ID = 0.
    //     break;
    // }
    assert(irBuilder.isOpen);
    // Preprocess: compute a list of cases that are the target of continue.
    // These are the so-called 'recursive' cases.
    List<JumpTarget> continueTargets = <JumpTarget>[];
    List<ast.Node> switchCases = node.cases.nodes.toList();
    for (ast.SwitchCase switchCase in switchCases) {
      for (ast.Node labelOrCase in switchCase.labelsAndCases) {
        if (labelOrCase is ast.Label) {
          LabelDefinition definition = elements.getLabelDefinition(labelOrCase);
          if (definition != null && definition.isContinueTarget) {
            continueTargets.add(definition.target);
          }
        }
      }
    }

    // If any cases are continue targets, use an anonymous local value to
    // implement a state machine.  The initial value is -1.
    ir.Primitive initial;
    int stateIndex;
    if (continueTargets.isNotEmpty) {
      initial = irBuilder.buildIntegerConstant(-1);
      stateIndex = irBuilder.environment.length;
      irBuilder.environment.extend(null, initial);
    }

    // Use a simple switch for the non-recursive cases.  A break will go to the
    // join-point after the switch.  A continue to a labeled case will assign
    // to the state variable and go to the join-point.
    ir.Primitive value = visit(node.expression);
    JumpCollector join = new ForwardJumpCollector(irBuilder.environment,
        target: elements.getTargetDefinition(node));
    irBuilder.state.breakCollectors.add(join);
    for (int i = 0; i < continueTargets.length; ++i) {
      // The state value is i, the case's position in the list of recursive
      // cases.
      irBuilder.state.continueCollectors.add(new GotoJumpCollector(
          continueTargets[i], stateIndex, i, join));
    }

    // For each non-default case use a pair of functions, one to translate the
    // condition and one to translate the body.  For the default case use a
    // function to translate the body.  Use continueTargetIterator as a pointer
    // to the next recursive case.
    Iterator<JumpTarget> continueTargetIterator = continueTargets.iterator;
    continueTargetIterator.moveNext();
    List<SwitchCaseInfo> cases = <SwitchCaseInfo>[];
    SubbuildFunction buildDefaultBody;
    for (ast.SwitchCase switchCase in switchCases) {
      JumpTarget nextContinueTarget = continueTargetIterator.current;
      if (switchCase.isDefaultCase) {
        if (nextContinueTarget != null &&
            switchCase == nextContinueTarget.statement) {
          // In this simple switch, recursive cases are as if they immediately
          // continued to themselves.
          buildDefaultBody = nested(() {
            irBuilder.buildContinue(nextContinueTarget);
          });
          continueTargetIterator.moveNext();
        } else {
          // Non-recursive cases consist of the translation of the body.
          // For the default case, there is implicitly a break if control
          // flow reaches the end.
          buildDefaultBody = nested(() {
            irBuilder.buildSequence(switchCase.statements, visit);
            if (irBuilder.isOpen) irBuilder.jumpTo(join);
          });
        }
        continue;
      }

      ir.Primitive buildCondition(IrBuilder builder) {
        // There can be multiple cases sharing the same body, because empty
        // cases are allowed to fall through to the next one.  Each case is
        // a comparison, build a short-circuited disjunction of all of them.
        return withBuilder(builder, () {
          ir.Primitive condition;
          for (ast.Node labelOrCase in switchCase.labelsAndCases) {
            if (labelOrCase is ast.CaseMatch) {
              ir.Primitive buildComparison() {
                ir.Primitive constant =
                    translateConstant(labelOrCase.expression);
                return irBuilder.buildIdentical(value, constant);
              }

              if (condition == null) {
                condition = buildComparison();
              } else {
                condition = irBuilder.buildLogicalOperator(condition,
                    nested(buildComparison), isLazyOr: true);
              }
            }
          }
          return condition;
        });
      }

      SubbuildFunction buildBody;
      if (nextContinueTarget != null &&
          switchCase == nextContinueTarget.statement) {
        // Recursive cases are as if they immediately continued to themselves.
        buildBody = nested(() {
          irBuilder.buildContinue(nextContinueTarget);
        });
        continueTargetIterator.moveNext();
      } else {
        // Non-recursive cases consist of the translation of the body.  It is a
        // runtime error if control-flow reaches the end of the body of any but
        // the last case.
        buildBody = (IrBuilder builder) {
          withBuilder(builder, () {
            irBuilder.buildSequence(switchCase.statements, visit);
            if (irBuilder.isOpen) {
              if (switchCase == switchCases.last) {
                irBuilder.jumpTo(join);
              } else {
                Element error = helpers.fallThroughError;
                ir.Primitive exception = irBuilder.buildInvokeStatic(
                    error,
                    new Selector.fromElement(error),
                    <ir.Primitive>[],
                    sourceInformationBuilder.buildGeneric(node));
                irBuilder.buildThrow(exception);
              }
            }
          });
          return null;
        };
      }

      cases.add(new SwitchCaseInfo(buildCondition, buildBody));
    }

    irBuilder.buildSimpleSwitch(join, cases, buildDefaultBody);
    irBuilder.state.breakCollectors.removeLast();
    irBuilder.state.continueCollectors.length -= continueTargets.length;
    if (continueTargets.isEmpty) return;

    // If there were recursive cases build a while loop whose body is a
    // switch containing (only) the recursive cases.  The condition is
    // 'state != initialValue' so the loop is not taken when the state variable
    // has not been assigned.
    //
    // 'loop' is the join-point of the exits from the inner switch which will
    // perform another iteration of the loop.  'exit' is the join-point of the
    // breaks from the switch, outside the loop.
    JumpCollector loop = new ForwardJumpCollector(irBuilder.environment);
    JumpCollector exit = new ForwardJumpCollector(irBuilder.environment,
        target: elements.getTargetDefinition(node));
    irBuilder.state.breakCollectors.add(exit);
    for (int i = 0; i < continueTargets.length; ++i) {
      irBuilder.state.continueCollectors.add(new GotoJumpCollector(
          continueTargets[i], stateIndex, i, loop));
    }
    cases.clear();
    for (int i = 0; i < continueTargets.length; ++i) {
      // The conditions compare to the recursive case index.
      ir.Primitive buildCondition(IrBuilder builder) {
        ir.Primitive constant = builder.buildIntegerConstant(i);
        return builder.buildIdentical(
            builder.environment.index2value[stateIndex], constant);
      }

      ir.Primitive buildBody(IrBuilder builder) {
        withBuilder(builder, () {
          ast.SwitchCase switchCase = continueTargets[i].statement;
          irBuilder.buildSequence(switchCase.statements, visit);
          if (irBuilder.isOpen) {
            if (switchCase == switchCases.last) {
              irBuilder.jumpTo(exit);
            } else {
              Element error = helpers.fallThroughError;
              ir.Primitive exception = irBuilder.buildInvokeStatic(
                  error,
                  new Selector.fromElement(error),
                  <ir.Primitive>[],
                  sourceInformationBuilder.buildGeneric(node));
              irBuilder.buildThrow(exception);
            }
          }
        });
        return null;
      }

      cases.add(new SwitchCaseInfo(buildCondition, buildBody));
    }

    // A loop with a simple switch in the body.
    IrBuilder whileBuilder = irBuilder.makeDelimitedBuilder();
    whileBuilder.buildWhile(
        buildCondition: (IrBuilder builder) {
          ir.Primitive condition = builder.buildIdentical(
              builder.environment.index2value[stateIndex], initial);
          return builder.buildNegation(condition);
        },
        buildBody: (IrBuilder builder) {
          builder.buildSimpleSwitch(loop, cases, null);
        });
    // Jump to the exit continuation.  This jump is the body of the loop exit
    // continuation, so the loop exit continuation can be eta-reduced.  The
    // jump is here for simplicity because `buildWhile` does not expose the
    // loop's exit continuation directly and has already emitted all jumps
    // to it anyway.
    whileBuilder.jumpTo(exit);
    irBuilder.add(new ir.LetCont(exit.continuation, whileBuilder.root));
    irBuilder.environment = exit.environment;
    irBuilder.environment.discard(1);  // Discard the state variable.
    irBuilder.state.breakCollectors.removeLast();
    irBuilder.state.continueCollectors.length -= continueTargets.length;
  }

  visitTryStatement(ast.TryStatement node) {
    List<CatchClauseInfo> catchClauseInfos = <CatchClauseInfo>[];
    for (ast.CatchBlock catchClause in node.catchBlocks.nodes) {
      LocalVariableElement exceptionVariable;
      if (catchClause.exception != null) {
        exceptionVariable = elements[catchClause.exception];
      }
      LocalVariableElement stackTraceVariable;
      if (catchClause.trace != null) {
        stackTraceVariable = elements[catchClause.trace];
      }
      DartType type;
      if (catchClause.onKeyword != null) {
        type = elements.getType(catchClause.type);
      }
      catchClauseInfos.add(new CatchClauseInfo(
          type: type,
          exceptionVariable: exceptionVariable,
          stackTraceVariable: stackTraceVariable,
          buildCatchBlock: subbuild(catchClause.block)));
    }

    assert(!node.catchBlocks.isEmpty || node.finallyBlock != null);
    if (!node.catchBlocks.isEmpty && node.finallyBlock != null) {
      // Try/catch/finally is encoded in terms of try/catch and try/finally:
      //
      // try tryBlock catch (ex, st) catchBlock finally finallyBlock
      // ==>
      // try { try tryBlock catch (ex, st) catchBlock } finally finallyBlock
      irBuilder.buildTryFinally(tryStatements[node.finallyBlock],
          (IrBuilder inner) {
            inner.buildTryCatch(tryStatements[node.catchBlocks],
                subbuild(node.tryBlock),
                catchClauseInfos);
          },
          subbuild(node.finallyBlock));
    } else if (!node.catchBlocks.isEmpty) {
      irBuilder.buildTryCatch(tryStatements[node.catchBlocks],
          subbuild(node.tryBlock),
          catchClauseInfos);
    } else {
      irBuilder.buildTryFinally(tryStatements[node.finallyBlock],
          subbuild(node.tryBlock),
          subbuild(node.finallyBlock));
    }
  }

  // ## Expressions ##
  ir.Primitive visitConditional(ast.Conditional node) {
    return irBuilder.buildConditional(
        build(node.condition),
        subbuild(node.thenExpression),
        subbuild(node.elseExpression));
  }

  // For all simple literals:
  // Build(Literal(c), C) = C[let val x = Constant(c) in [], x]
  ir.Primitive visitLiteralBool(ast.LiteralBool node) {
    assert(irBuilder.isOpen);
    return irBuilder.buildBooleanConstant(node.value);
  }

  ir.Primitive visitLiteralDouble(ast.LiteralDouble node) {
    assert(irBuilder.isOpen);
    return irBuilder.buildDoubleConstant(node.value);
  }

  ir.Primitive visitLiteralInt(ast.LiteralInt node) {
    assert(irBuilder.isOpen);
    return irBuilder.buildIntegerConstant(node.value);
  }

  ir.Primitive visitLiteralNull(ast.LiteralNull node) {
    assert(irBuilder.isOpen);
    return irBuilder.buildNullConstant();
  }

  ir.Primitive visitLiteralString(ast.LiteralString node) {
    assert(irBuilder.isOpen);
    return irBuilder.buildDartStringConstant(node.dartString);
  }

  ConstantValue getConstantForNode(ast.Node node) {
    return irBuilder.state.constants.getConstantValueForNode(node, elements);
  }

  ConstantValue getConstantForVariable(VariableElement element) {
    return irBuilder.state.constants.getConstantValueForVariable(element);
  }

  ir.Primitive buildConstantExpression(ConstantExpression expression,
                                       SourceInformation sourceInformation) {
    return irBuilder.buildConstant(
        irBuilder.state.constants.getConstantValue(expression),
        sourceInformation: sourceInformation);
  }

  /// Returns the allocation site-specific type for a given allocation.
  ///
  /// Currently, it is an error to call this with anything that is not the
  /// allocation site for a List object (a literal list or a call to one
  /// of the List constructors).
  TypeMask getAllocationSiteType(ast.Node node) {
    return compiler.typesTask.getGuaranteedTypeOfNode(
        elements.analyzedElement, node);
  }

  ir.Primitive visitLiteralList(ast.LiteralList node) {
    if (node.isConst) {
      return translateConstant(node);
    }
    List<ir.Primitive> values = node.elements.nodes.mapToList(visit);
    InterfaceType type = elements.getType(node);
    TypeMask allocationSiteType = getAllocationSiteType(node);
    // TODO(sra): In checked mode, the elements must be checked as though
    // operator[]= is called.
    ir.Primitive list = irBuilder.buildListLiteral(type, values,
          allocationSiteType: allocationSiteType);
    if (type.treatAsRaw) return list;
    // Call JSArray<E>.typed(allocation) to install the reified type.
    ConstructorElement constructor = helpers.jsArrayTypedConstructor;
    ir.Primitive tagged = irBuilder.buildConstructorInvocation(
        constructor.effectiveTarget,
        CallStructure.ONE_ARG,
        constructor.computeEffectiveTargetType(type),
        <ir.Primitive>[list],
        sourceInformationBuilder.buildNew(node));

    if (allocationSiteType == null) return tagged;

    return irBuilder.addPrimitive(
        new ir.Refinement(tagged, allocationSiteType));
  }

  ir.Primitive visitLiteralMap(ast.LiteralMap node) {
    assert(irBuilder.isOpen);
    if (node.isConst) {
      return translateConstant(node);
    }

    InterfaceType type = elements.getType(node);

    if (node.entries.nodes.isEmpty) {
      if (type.treatAsRaw) {
        return irBuilder.buildStaticFunctionInvocation(
            helpers.mapLiteralUntypedEmptyMaker,
            <ir.Primitive>[],
            sourceInformation: sourceInformationBuilder.buildNew(node));
      } else {
        ConstructorElement constructor = helpers.mapLiteralConstructorEmpty;
        return irBuilder.buildConstructorInvocation(
            constructor.effectiveTarget,
            CallStructure.NO_ARGS,
            constructor.computeEffectiveTargetType(type),
            <ir.Primitive>[],
            sourceInformationBuilder.buildNew(node));
      }
    }

    List<ir.Primitive> keysAndValues = <ir.Primitive>[];
    for (ast.LiteralMapEntry entry in node.entries.nodes.toList()) {
      keysAndValues.add(visit(entry.key));
      keysAndValues.add(visit(entry.value));
    }
    ir.Primitive keysAndValuesList =
        irBuilder.buildListLiteral(null, keysAndValues);

    if (type.treatAsRaw) {
      return irBuilder.buildStaticFunctionInvocation(
          helpers.mapLiteralUntypedMaker,
          <ir.Primitive>[keysAndValuesList],
          sourceInformation: sourceInformationBuilder.buildNew(node));
    } else {
      ConstructorElement constructor = helpers.mapLiteralConstructor;
      return irBuilder.buildConstructorInvocation(
          constructor.effectiveTarget,
          CallStructure.ONE_ARG,
          constructor.computeEffectiveTargetType(type),
          <ir.Primitive>[keysAndValuesList],
          sourceInformationBuilder.buildNew(node));
    }
  }

  ir.Primitive visitLiteralSymbol(ast.LiteralSymbol node) {
    assert(irBuilder.isOpen);
    return translateConstant(node);
  }

  ir.Primitive visitParenthesizedExpression(
      ast.ParenthesizedExpression node) {
    assert(irBuilder.isOpen);
    return visit(node.expression);
  }

  // Stores the result of visiting a CascadeReceiver, so we can return it from
  // its enclosing Cascade.
  ir.Primitive _currentCascadeReceiver;

  ir.Primitive visitCascadeReceiver(ast.CascadeReceiver node) {
    assert(irBuilder.isOpen);
    return _currentCascadeReceiver = visit(node.expression);
  }

  ir.Primitive visitCascade(ast.Cascade node) {
    assert(irBuilder.isOpen);
    var oldCascadeReceiver = _currentCascadeReceiver;
    // Throw away the result of visiting the expression.
    // Instead we return the result of visiting the CascadeReceiver.
    visit(node.expression);
    ir.Primitive receiver = _currentCascadeReceiver;
    _currentCascadeReceiver = oldCascadeReceiver;
    return receiver;
  }

  @override
  ir.Primitive visitAssert(ast.Assert node) {
    assert(irBuilder.isOpen);
    if (compiler.enableUserAssertions) {
      return giveup(node, 'assert in checked mode not implemented');
    } else {
      // The call to assert and its argument expression must be ignored
      // in production mode.
      // Assertions can only occur in expression statements, so no value needs
      // to be returned.
      return null;
    }
  }

  // ## Sends ##
  @override
  void previsitDeferredAccess(ast.Send node, PrefixElement prefix, _) {
    if (prefix != null) buildCheckDeferredIsLoaded(prefix, node);
  }

  /// Create a call to check that a deferred import has already been loaded.
  ir.Primitive buildCheckDeferredIsLoaded(PrefixElement prefix, ast.Send node) {
    SourceInformation sourceInformation =
        sourceInformationBuilder.buildCall(node, node.selector);
    ir.Primitive name = irBuilder.buildStringConstant(
        compiler.deferredLoadTask.getImportDeferName(node, prefix));
    ir.Primitive uri =
        irBuilder.buildStringConstant('${prefix.deferredImport.uri}');
    return irBuilder.buildStaticFunctionInvocation(
        helpers.checkDeferredIsLoaded,
        <ir.Primitive>[name, uri],
        sourceInformation: sourceInformation);
  }

  ir.Primitive visitNamedArgument(ast.NamedArgument node) {
    assert(irBuilder.isOpen);
    return visit(node.expression);
  }

  @override
  ir.Primitive visitExpressionInvoke(ast.Send node,
                                     ast.Node expression,
                                     ast.NodeList argumentsNode,
                                     CallStructure callStructure, _) {
    ir.Primitive receiver = visit(expression);
    List<ir.Primitive> arguments = argumentsNode.nodes.mapToList(visit);
    callStructure = normalizeDynamicArguments(callStructure, arguments);
    return irBuilder.buildCallInvocation(receiver, callStructure, arguments,
        sourceInformation:
            sourceInformationBuilder.buildCall(node, argumentsNode));
  }

  /// Returns `true` if [node] is a super call.
  // TODO(johnniwinther): Remove the need for this.
  bool isSuperCall(ast.Send node) {
    return node != null && node.receiver != null && node.receiver.isSuper();
  }

  @override
  ir.Primitive handleConstantGet(
      ast.Node node,
      ConstantExpression constant, _) {
    return buildConstantExpression(constant,
        sourceInformationBuilder.buildGet(node));
  }

  /// If [node] is null, returns this.
  /// Otherwise visits [node] and returns the result.
  ir.Primitive translateReceiver(ast.Expression node) {
    return node != null ? visit(node) : irBuilder.buildThis();
  }

  @override
  ir.Primitive handleDynamicGet(
      ast.Send node,
      ast.Node receiver,
      Name name,
      _) {
    return irBuilder.buildDynamicGet(
        translateReceiver(receiver),
        new Selector.getter(name),
        elements.getTypeMask(node),
        sourceInformationBuilder.buildGet(node));
  }

  @override
  ir.Primitive visitIfNotNullDynamicPropertyGet(
      ast.Send node,
      ast.Node receiver,
      Name name,
      _) {
    ir.Primitive target = visit(receiver);
    return irBuilder.buildIfNotNullSend(
        target,
        nested(() => irBuilder.buildDynamicGet(
            target,
            new Selector.getter(name),
            elements.getTypeMask(node),
            sourceInformationBuilder.buildGet(node))));
  }

  @override
  ir.Primitive visitDynamicTypeLiteralGet(
      ast.Send node,
      ConstantExpression constant,
      _) {
    return buildConstantExpression(constant,
        sourceInformationBuilder.buildGet(node));
  }

  @override
  ir.Primitive visitLocalVariableGet(
      ast.Send node,
      LocalVariableElement element,
      _) {
    return element.isConst
        ? irBuilder.buildConstant(getConstantForVariable(element),
            sourceInformation: sourceInformationBuilder.buildGet(node))
        : irBuilder.buildLocalGet(element);
  }

  ir.Primitive handleLocalGet(
      ast.Send node,
      LocalElement element,
      _) {
    return irBuilder.buildLocalGet(element);
  }

  @override
  ir.Primitive handleStaticFunctionGet(
      ast.Send node,
      MethodElement function,
      _) {
    return irBuilder.addPrimitive(new ir.GetStatic(function));
  }

  @override
  ir.Primitive handleStaticGetterGet(
      ast.Send node,
      FunctionElement getter,
      _) {
    return buildStaticGetterGet(getter, node);
  }

  /// Create a getter invocation of the static getter [getter]. This also
  /// handles the special case where [getter] is the `loadLibrary`
  /// pseudo-function on library prefixes of deferred imports.
  ir.Primitive buildStaticGetterGet(MethodElement getter, ast.Send node) {
    SourceInformation sourceInformation =
        sourceInformationBuilder.buildGet(node);
    if (getter.isDeferredLoaderGetter) {
      PrefixElement prefix = getter.enclosingElement;
      ir.Primitive loadId = irBuilder.buildStringConstant(
          compiler.deferredLoadTask.getImportDeferName(node, prefix));
      return irBuilder.buildStaticFunctionInvocation(
          compiler.loadLibraryFunction,
          <ir.Primitive>[loadId],
          sourceInformation: sourceInformation);
    } else {
      return irBuilder.buildStaticGetterGet(getter, sourceInformation);
    }
  }

  @override
  ir.Primitive visitSuperFieldGet(
      ast.Send node,
      FieldElement field,
      _) {
    return irBuilder.buildSuperFieldGet(field);
  }

  @override
  ir.Primitive visitSuperGetterGet(
      ast.Send node,
      FunctionElement getter,
      _) {
    return irBuilder.buildSuperGetterGet(
        getter, sourceInformationBuilder.buildGet(node));
  }

  @override
  ir.Primitive visitSuperMethodGet(
      ast.Send node,
      MethodElement method,
      _) {
    return irBuilder.buildSuperMethodGet(method);
  }

  @override
  ir.Primitive visitUnresolvedSuperGet(
      ast.Send node,
      Element element, _) {
    return buildSuperNoSuchMethod(
        elements.getSelector(node), elements.getTypeMask(node), []);
  }

  @override
  ir.Primitive visitUnresolvedSuperSet(
      ast.Send node,
      Element element,
      ast.Node rhs, _) {
    return buildSuperNoSuchMethod(
        elements.getSelector(node), elements.getTypeMask(node), [visit(rhs)]);
  }

  @override
  ir.Primitive visitThisGet(ast.Identifier node, _) {
    if (irBuilder.state.thisParameter == null) {
      // TODO(asgerf,johnniwinther): Should be in a visitInvalidThis method.
      // 'this' in static context. Just translate to null.
      assert(compiler.compilationFailed);
      return irBuilder.buildNullConstant();
    }
    return irBuilder.buildThis();
  }

  ir.Primitive translateTypeVariableTypeLiteral(
      TypeVariableElement element,
      SourceInformation sourceInformation) {
    return irBuilder.buildReifyTypeVariable(element.type, sourceInformation);
  }

  @override
  ir.Primitive visitTypeVariableTypeLiteralGet(ast.Send node,
                                               TypeVariableElement element, _) {
    return translateTypeVariableTypeLiteral(element,
        sourceInformationBuilder.buildGet(node));
  }

  ir.Primitive translateLogicalOperator(ast.Expression left,
                                        ast.Expression right,
                                        {bool isLazyOr}) {
    ir.Primitive leftValue = visit(left);

    ir.Primitive buildRightValue(IrBuilder rightBuilder) {
      return withBuilder(rightBuilder, () => visit(right));
    }

    return irBuilder.buildLogicalOperator(
        leftValue, buildRightValue, isLazyOr: isLazyOr);
  }

  @override
  ir.Primitive visitIfNull(
      ast.Send node, ast.Node left, ast.Node right, _) {
    return irBuilder.buildIfNull(build(left), subbuild(right));
  }

  @override
  ir.Primitive visitLogicalAnd(
      ast.Send node, ast.Node left, ast.Node right, _) {
    return translateLogicalOperator(left, right, isLazyOr: false);
  }

  @override
  ir.Primitive visitLogicalOr(
      ast.Send node, ast.Node left, ast.Node right, _) {
    return translateLogicalOperator(left, right, isLazyOr: true);
  }

  @override
  ir.Primitive visitAs(
      ast.Send node,
      ast.Node expression,
      DartType type,
      _) {
    ir.Primitive receiver = visit(expression);
    return irBuilder.buildTypeOperator(receiver, type, isTypeTest: false);
  }

  @override
  ir.Primitive visitIs(
      ast.Send node,
      ast.Node expression,
      DartType type,
      _) {
    ir.Primitive value = visit(expression);
    return irBuilder.buildTypeOperator(value, type, isTypeTest: true);
  }

  @override
  ir.Primitive visitIsNot(ast.Send node,
                          ast.Node expression, DartType type, _) {
    ir.Primitive value = visit(expression);
    ir.Primitive check = irBuilder.buildTypeOperator(
        value, type, isTypeTest: true);
    return irBuilder.buildNegation(check);
  }

  ir.Primitive translateBinary(ast.Send node,
                               ast.Node left,
                               op.BinaryOperator operator,
                               ast.Node right) {
    ir.Primitive receiver = visit(left);
    Selector selector = new Selector.binaryOperator(operator.selectorName);
    List<ir.Primitive> arguments = <ir.Primitive>[visit(right)];
    CallStructure callStructure =
        normalizeDynamicArguments(selector.callStructure, arguments);
    return irBuilder.buildDynamicInvocation(
        receiver,
        new Selector(selector.kind, selector.memberName, callStructure),
        elements.getTypeMask(node),
        arguments,
        sourceInformation:
            sourceInformationBuilder.buildCall(node, node.selector));
  }

  @override
  ir.Primitive visitBinary(ast.Send node,
                           ast.Node left,
                           op.BinaryOperator operator,
                           ast.Node right, _) {
    return translateBinary(node, left, operator, right);
  }

  @override
  ir.Primitive visitIndex(ast.Send node,
                          ast.Node receiver,
                          ast.Node index, _) {
    ir.Primitive target = visit(receiver);
    Selector selector = new Selector.index();
    List<ir.Primitive> arguments = <ir.Primitive>[visit(index)];
    CallStructure callStructure =
        normalizeDynamicArguments(selector.callStructure, arguments);
    return irBuilder.buildDynamicInvocation(
        target,
        new Selector(selector.kind, selector.memberName, callStructure),
        elements.getTypeMask(node),
        arguments,
        sourceInformation:
            sourceInformationBuilder.buildCall(receiver, node.selector));
  }

  ir.Primitive translateSuperBinary(FunctionElement function,
                                    op.BinaryOperator operator,
                                    ast.Node argument) {
    List<ir.Primitive> arguments = <ir.Primitive>[visit(argument)];
    return irBuilder.buildSuperMethodInvocation(function,
        CallStructure.ONE_ARG, arguments);
  }

  @override
  ir.Primitive visitSuperBinary(
      ast.Send node,
      FunctionElement function,
      op.BinaryOperator operator,
      ast.Node argument,
      _) {
    return translateSuperBinary(function, operator, argument);
  }

  @override
  ir.Primitive visitSuperIndex(
      ast.Send node,
      FunctionElement function,
      ast.Node index,
      _) {
    return irBuilder.buildSuperIndex(function, visit(index));
  }

  @override
  ir.Primitive visitEquals(
      ast.Send node,
      ast.Node left,
      ast.Node right,
      _) {
    return translateBinary(node, left, op.BinaryOperator.EQ, right);
  }

  @override
  ir.Primitive visitSuperEquals(
      ast.Send node,
      FunctionElement function,
      ast.Node argument,
      _) {
    return translateSuperBinary(function, op.BinaryOperator.EQ, argument);
  }

  @override
  ir.Primitive visitNot(
      ast.Send node,
      ast.Node expression,
      _) {
    return irBuilder.buildNegation(visit(expression));
  }

  @override
  ir.Primitive visitNotEquals(
      ast.Send node,
      ast.Node left,
      ast.Node right,
      _) {
    return irBuilder.buildNegation(
        translateBinary(node, left, op.BinaryOperator.NOT_EQ, right));
  }

  @override
  ir.Primitive visitSuperNotEquals(
      ast.Send node,
      FunctionElement function,
      ast.Node argument,
      _) {
    return irBuilder.buildNegation(
        translateSuperBinary(function, op.BinaryOperator.NOT_EQ, argument));
  }

  @override
  ir.Primitive visitUnary(ast.Send node,
                          op.UnaryOperator operator, ast.Node expression, _) {
    // TODO(johnniwinther): Clean up the creation of selectors.
    Selector selector = operator.selector;
    ir.Primitive receiver = translateReceiver(expression);
    return irBuilder.buildDynamicInvocation(
        receiver, selector, elements.getTypeMask(node), const [],
        sourceInformation: sourceInformationBuilder.buildCall(
            expression, node));
  }

  @override
  ir.Primitive visitSuperUnary(
      ast.Send node,
      op.UnaryOperator operator,
      FunctionElement function,
      _) {
    return irBuilder.buildSuperMethodInvocation(
        function, CallStructure.NO_ARGS, const []);
  }

  // TODO(johnniwinther): Handle this in the [IrBuilder] to ensure the correct
  // semantic correlation between arguments and invocation.
  CallStructure translateDynamicArguments(ast.NodeList nodeList,
                                          CallStructure callStructure,
                                          List<ir.Primitive> arguments) {
    assert(arguments.isEmpty);
    for (ast.Node node in nodeList) arguments.add(visit(node));
    return normalizeDynamicArguments(callStructure, arguments);
  }

  // TODO(johnniwinther): Handle this in the [IrBuilder] to ensure the correct
  // semantic correlation between arguments and invocation.
  CallStructure translateStaticArguments(ast.NodeList nodeList,
                                         Element element,
                                         CallStructure callStructure,
                                         List<ir.Primitive> arguments) {
    assert(arguments.isEmpty);
    for (ast.Node node in nodeList) arguments.add(visit(node));
    return normalizeStaticArguments(callStructure, element, arguments);
  }

  ir.Primitive translateCallInvoke(ir.Primitive target,
                                   ast.NodeList argumentsNode,
                                   CallStructure callStructure,
                                   SourceInformation sourceInformation) {
    List<ir.Primitive> arguments = <ir.Primitive>[];
    callStructure =
        translateDynamicArguments(argumentsNode, callStructure, arguments);
    return irBuilder.buildCallInvocation(target, callStructure, arguments,
        sourceInformation: sourceInformation);
  }

  @override
  ir.Primitive handleConstantInvoke(
      ast.Send node,
      ConstantExpression constant,
      ast.NodeList arguments,
      CallStructure callStructure,
      _) {
    ir.Primitive target = buildConstantExpression(constant,
        sourceInformationBuilder.buildGet(node));
    return translateCallInvoke(target, arguments, callStructure,
        sourceInformationBuilder.buildCall(node, arguments));
  }

  @override
  ir.Primitive handleConstructorInvoke(
      ast.NewExpression node,
      ConstructorElement constructor,
      DartType type,
      ast.NodeList argumentsNode,
      CallStructure callStructure,
      _) {

    // TODO(sigmund): move these checks down after visiting arguments
    // (see issue #25355)
    ast.Send send = node.send;
    // If an allocation refers to a type using a deferred import prefix (e.g.
    // `new lib.A()`), we must ensure that the deferred import has already been
    // loaded.
    var prefix = compiler.deferredLoadTask.deferredPrefixElement(
        send, elements);
    if (prefix != null) buildCheckDeferredIsLoaded(prefix, send);

    // We also emit deferred import checks when using redirecting factories that
    // refer to deferred prefixes.
    if (constructor.isRedirectingFactory && !constructor.isCyclicRedirection) {
      ConstructorElement current = constructor;
      while (current.isRedirectingFactory) {
        var prefix = current.redirectionDeferredPrefix;
        if (prefix != null) buildCheckDeferredIsLoaded(prefix, send);
        current = current.immediateRedirectionTarget;
      }
    }

    List<ir.Primitive> arguments = argumentsNode.nodes.mapToList(visit);
    // Use default values from the effective target, not the immediate target.
    ConstructorElement target;
    if (constructor == compiler.symbolConstructor) {
      // The Symbol constructor should perform validation of its argument
      // which is not expressible as a Dart const constructor.  Instead, the
      // libraries contain a dummy const constructor implementation that
      // doesn't perform validation and the compiler compiles a call to
      // (non-const) Symbol.validated when it sees new Symbol(...).
      target = compiler.symbolValidatedConstructor;
    } else {
      target = constructor.implementation;
    }
    while (target.isRedirectingFactory && !target.isCyclicRedirection) {
      target = target.effectiveTarget.implementation;
    }

    callStructure = normalizeStaticArguments(callStructure, target, arguments);
    TypeMask allocationSiteType;

    if (Elements.isFixedListConstructorCall(constructor, send, compiler) ||
        Elements.isGrowableListConstructorCall(constructor, send, compiler) ||
        Elements.isFilledListConstructorCall(constructor, send, compiler) ||
        Elements.isConstructorOfTypedArraySubclass(constructor, compiler)) {
      allocationSiteType = getAllocationSiteType(send);
    }
    ConstructorElement constructorImplementation = constructor.implementation;
    return irBuilder.buildConstructorInvocation(
        target,
        callStructure,
        constructorImplementation.computeEffectiveTargetType(type),
        arguments,
        sourceInformationBuilder.buildNew(node),
        allocationSiteType: allocationSiteType);
  }

  @override
  ir.Primitive handleDynamicInvoke(
      ast.Send node,
      ast.Node receiver,
      ast.NodeList argumentsNode,
      Selector selector,
      _) {
    ir.Primitive target = translateReceiver(receiver);
    List<ir.Primitive> arguments = <ir.Primitive>[];
    CallStructure callStructure = translateDynamicArguments(
        argumentsNode, selector.callStructure, arguments);
    return irBuilder.buildDynamicInvocation(
        target,
        new Selector(selector.kind, selector.memberName, callStructure),
        elements.getTypeMask(node),
        arguments,
        sourceInformation:
            sourceInformationBuilder.buildCall(node, node.selector));
  }

  @override
  ir.Primitive visitIfNotNullDynamicPropertyInvoke(
      ast.Send node,
      ast.Node receiver,
      ast.NodeList argumentsNode,
      Selector selector,
      _) {
    ir.Primitive target = visit(receiver);
    return irBuilder.buildIfNotNullSend(
        target,
        nested(() {
          List<ir.Primitive> arguments = <ir.Primitive>[];
          CallStructure callStructure = translateDynamicArguments(
              argumentsNode, selector.callStructure, arguments);
          return irBuilder.buildDynamicInvocation(
              target,
              new Selector(selector.kind, selector.memberName, callStructure),
              elements.getTypeMask(node),
              arguments);
        }));
  }

  ir.Primitive handleLocalInvoke(
      ast.Send node,
      LocalElement element,
      ast.NodeList argumentsNode,
      CallStructure callStructure,
      _) {
    ir.Primitive function = irBuilder.buildLocalGet(element);
    List<ir.Primitive> arguments = <ir.Primitive>[];
    callStructure =
        translateDynamicArguments(argumentsNode, callStructure, arguments);
    return irBuilder.buildCallInvocation(function, callStructure, arguments,
        sourceInformation:
            sourceInformationBuilder.buildCall(node, argumentsNode));
  }

  @override
  ir.Primitive handleStaticFieldGet(ast.Send node, FieldElement field, _) {
    return buildStaticFieldGet(field, sourceInformationBuilder.buildGet(node));
  }

  @override
  ir.Primitive handleStaticFieldInvoke(
      ast.Send node,
      FieldElement field,
      ast.NodeList argumentsNode,
      CallStructure callStructure,
      _) {
    SourceInformation src = sourceInformationBuilder.buildGet(node);
    ir.Primitive target = buildStaticFieldGet(field, src);
    List<ir.Primitive> arguments = <ir.Primitive>[];
    callStructure =
        translateDynamicArguments(argumentsNode, callStructure, arguments);
    return irBuilder.buildCallInvocation(
        target,
        callStructure,
        arguments,
        sourceInformation:
            sourceInformationBuilder.buildCall(node, argumentsNode));
  }

  @override
  ir.Primitive handleStaticFunctionInvoke(ast.Send node,
      MethodElement function,
      ast.NodeList argumentsNode,
      CallStructure callStructure,
      _) {
    if (compiler.backend.isForeign(function)) {
      return handleForeignCode(node, function, argumentsNode, callStructure);
    } else {
      List<ir.Primitive> arguments = <ir.Primitive>[];
      callStructure = translateStaticArguments(argumentsNode, function,
          callStructure, arguments);
      Selector selector = new Selector.call(function.memberName, callStructure);
      return irBuilder.buildInvokeStatic(function, selector, arguments,
          sourceInformationBuilder.buildCall(node, node.selector));
    }
  }

  @override
  ir.Primitive handleStaticFunctionIncompatibleInvoke(
      ast.Send node,
      MethodElement function,
      ast.NodeList arguments,
      CallStructure callStructure, _) {
    return irBuilder.buildStaticNoSuchMethod(
        elements.getSelector(node),
        arguments.nodes.mapToList(visit));
  }

  @override
  ir.Primitive handleStaticGetterInvoke(
      ast.Send node,
      FunctionElement getter,
      ast.NodeList argumentsNode,
      CallStructure callStructure,
      _) {
    ir.Primitive target = buildStaticGetterGet(getter, node);
    List<ir.Primitive> arguments = <ir.Primitive>[];
    callStructure =
        translateDynamicArguments(argumentsNode, callStructure, arguments);
    return irBuilder.buildCallInvocation(
        target,
        callStructure,
        arguments,
        sourceInformation:
            sourceInformationBuilder.buildCall(node, argumentsNode));
  }

  @override
  ir.Primitive visitSuperFieldInvoke(
      ast.Send node,
      FieldElement field,
      ast.NodeList argumentsNode,
      CallStructure callStructure,
      _) {
    ir.Primitive target = irBuilder.buildSuperFieldGet(field);
    List<ir.Primitive> arguments = <ir.Primitive>[];
    callStructure =
        translateDynamicArguments(argumentsNode, callStructure, arguments);
    return irBuilder.buildCallInvocation(
        target,
        callStructure,
        arguments,
        sourceInformation:
            sourceInformationBuilder.buildCall(node, argumentsNode));
  }

  @override
  ir.Primitive visitSuperGetterInvoke(
      ast.Send node,
      FunctionElement getter,
      ast.NodeList argumentsNode,
      CallStructure callStructure,
      _) {
    ir.Primitive target = irBuilder.buildSuperGetterGet(getter,
        sourceInformationBuilder.buildGet(node));
    List<ir.Primitive> arguments = <ir.Primitive>[];
    callStructure =
        translateDynamicArguments(argumentsNode, callStructure, arguments);
    return irBuilder.buildCallInvocation(
        target,
        callStructure,
        arguments,
        sourceInformation:
            sourceInformationBuilder.buildCall(node, argumentsNode));
  }

  @override
  ir.Primitive visitSuperMethodInvoke(
      ast.Send node,
      MethodElement method,
      ast.NodeList argumentsNode,
      CallStructure callStructure,
      _) {
    List<ir.Primitive> arguments = <ir.Primitive>[];
    callStructure = translateStaticArguments(argumentsNode, method,
        callStructure, arguments);
    return irBuilder.buildSuperMethodInvocation(
        method,
        callStructure,
        arguments,
        sourceInformation:
            sourceInformationBuilder.buildCall(node, node.selector));
  }

  @override
  ir.Primitive visitSuperMethodIncompatibleInvoke(
      ast.Send node,
      MethodElement method,
      ast.NodeList arguments,
      CallStructure callStructure, _) {
    List<ir.Primitive> normalizedArguments = <ir.Primitive>[];
    CallStructure normalizedCallStructure =
      translateDynamicArguments(arguments, callStructure, normalizedArguments);
    return buildSuperNoSuchMethod(
        new Selector.call(method.memberName, normalizedCallStructure),
        elements.getTypeMask(node),
        normalizedArguments);
  }

  @override
  ir.Primitive visitUnresolvedSuperInvoke(
      ast.Send node,
      Element element,
      ast.NodeList argumentsNode,
      Selector selector, _) {
    List<ir.Primitive> arguments = <ir.Primitive>[];
    CallStructure callStructure = translateDynamicArguments(
        argumentsNode, selector.callStructure, arguments);
    // TODO(johnniwinther): Supply a member name to the visit function instead
    // of looking it up in elements.
    return buildSuperNoSuchMethod(
        new Selector.call(elements.getSelector(node).memberName, callStructure),
        elements.getTypeMask(node),
        arguments);
  }

  @override
  ir.Primitive visitThisInvoke(
      ast.Send node,
      ast.NodeList arguments,
      CallStructure callStructure,
      _) {
    return translateCallInvoke(
        irBuilder.buildThis(),
        arguments,
        callStructure,
        sourceInformationBuilder.buildCall(node, arguments));
  }

  @override
  ir.Primitive visitTypeVariableTypeLiteralInvoke(
      ast.Send node,
      TypeVariableElement element,
      ast.NodeList arguments,
      CallStructure callStructure,
      _) {
    return translateCallInvoke(
        translateTypeVariableTypeLiteral(
            element, sourceInformationBuilder.buildGet(node)),
        arguments,
        callStructure,
        sourceInformationBuilder.buildCall(node, arguments));
  }

  @override
  ir.Primitive visitIndexSet(
       ast.SendSet node,
       ast.Node receiver,
       ast.Node index,
       ast.Node rhs,
       _) {
    return irBuilder.buildDynamicIndexSet(
        visit(receiver), elements.getTypeMask(node), visit(index), visit(rhs));
  }

  @override
  ir.Primitive visitSuperIndexSet(
      ast.SendSet node,
      FunctionElement function,
      ast.Node index,
      ast.Node rhs,
      _) {
    return irBuilder.buildSuperIndexSet(function, visit(index), visit(rhs));
  }

  ir.Primitive translateCompounds(
      ast.SendSet node,
      ir.Primitive getValue(),
      CompoundRhs rhs,
      void setValue(ir.Primitive value)) {
    ir.Primitive value = getValue();
    op.BinaryOperator operator = rhs.operator;
    if (operator.kind == op.BinaryOperatorKind.IF_NULL) {
      // Unlike other compound operators if-null conditionally will not do the
      // assignment operation.
      return irBuilder.buildIfNull(value, nested(() {
        ir.Primitive newValue = build(rhs.rhs);
        setValue(newValue);
        return newValue;
      }));
    }

    Selector operatorSelector =
        new Selector.binaryOperator(operator.selectorName);
    ir.Primitive rhsValue;
    if (rhs.kind == CompoundKind.ASSIGNMENT) {
      rhsValue = visit(rhs.rhs);
    } else {
      rhsValue = irBuilder.buildIntegerConstant(1);
    }
    List<ir.Primitive> arguments = <ir.Primitive>[rhsValue];
    CallStructure callStructure =
        normalizeDynamicArguments(operatorSelector.callStructure, arguments);
    TypeMask operatorTypeMask =
        elements.getOperatorTypeMaskInComplexSendSet(node);
    SourceInformation operatorSourceInformation =
        sourceInformationBuilder.buildCall(node, node.assignmentOperator);
    ir.Primitive result = irBuilder.buildDynamicInvocation(
        value,
        new Selector(operatorSelector.kind, operatorSelector.memberName,
            callStructure),
        operatorTypeMask,
        arguments,
        sourceInformation: operatorSourceInformation);
    setValue(result);
    return rhs.kind == CompoundKind.POSTFIX ? value : result;
  }

  ir.Primitive translateSetIfNull(
      ast.SendSet node,
      ir.Primitive getValue(),
      ast.Node rhs,
      void setValue(ir.Primitive value)) {
    ir.Primitive value = getValue();
    // Unlike other compound operators if-null conditionally will not do the
    // assignment operation.
    return irBuilder.buildIfNull(value, nested(() {
      ir.Primitive newValue = build(rhs);
      setValue(newValue);
      return newValue;
    }));
  }

  @override
  ir.Primitive handleDynamicSet(
      ast.SendSet node,
      ast.Node receiver,
      Name name,
      ast.Node rhs,
      _) {
    return irBuilder.buildDynamicSet(
        translateReceiver(receiver),
        new Selector.setter(name),
        elements.getTypeMask(node),
        visit(rhs));
  }

  @override
  ir.Primitive visitIfNotNullDynamicPropertySet(
      ast.SendSet node,
      ast.Node receiver,
      Name name,
      ast.Node rhs,
      _) {
    ir.Primitive target = visit(receiver);
    return irBuilder.buildIfNotNullSend(
        target,
        nested(() => irBuilder.buildDynamicSet(
            target,
            new Selector.setter(name),
            elements.getTypeMask(node),
            visit(rhs))));
  }

  @override
  ir.Primitive handleLocalSet(
      ast.SendSet node,
      LocalElement element,
      ast.Node rhs,
      _) {
    ir.Primitive value = visit(rhs);
    value = checkTypeVsElement(value, element);
    return irBuilder.buildLocalVariableSet(element, value);
  }

  @override
  ir.Primitive handleStaticFieldSet(
      ast.SendSet node,
      FieldElement field,
      ast.Node rhs,
      _) {
    ir.Primitive value = visit(rhs);
    irBuilder.addPrimitive(new ir.SetStatic(field, value));
    return value;
  }

  @override
  ir.Primitive visitSuperFieldSet(
      ast.SendSet node,
      FieldElement field,
      ast.Node rhs,
      _) {
    return irBuilder.buildSuperFieldSet(field, visit(rhs));
  }

  @override
  ir.Primitive visitSuperSetterSet(
      ast.SendSet node,
      FunctionElement setter,
      ast.Node rhs,
      _) {
    return irBuilder.buildSuperSetterSet(setter, visit(rhs));
  }

  @override
  ir.Primitive visitUnresolvedSuperIndexSet(
      ast.Send node,
      Element element,
      ast.Node index,
      ast.Node rhs,
      arg) {
    return giveup(node, 'visitUnresolvedSuperIndexSet');
  }

  @override
  ir.Primitive handleStaticSetterSet(
      ast.SendSet node,
      FunctionElement setter,
      ast.Node rhs,
      _) {
    return irBuilder.buildStaticSetterSet(setter, visit(rhs));
  }

  @override
  ir.Primitive handleTypeLiteralConstantCompounds(
      ast.SendSet node,
      ConstantExpression constant,
      CompoundRhs rhs,
      arg) {
    SourceInformation src = sourceInformationBuilder.buildGet(node);
    return translateCompounds(node, () {
      return buildConstantExpression(constant, src);
    }, rhs, (ir.Primitive value) {
      // The binary operator will throw before this.
    });
  }

  @override
  ir.Primitive handleTypeLiteralConstantSetIfNulls(
      ast.SendSet node,
      ConstantExpression constant,
      ast.Node rhs,
      _) {
    // The type literal is never `null`.
    return buildConstantExpression(constant,
        sourceInformationBuilder.buildGet(node));
  }

  @override
  ir.Primitive handleDynamicCompounds(
      ast.SendSet node,
      ast.Node receiver,
      Name name,
      CompoundRhs rhs,
      arg) {
    ir.Primitive target = translateReceiver(receiver);
    ir.Primitive helper() {
      return translateCompounds(node, () {
        return irBuilder.buildDynamicGet(
            target,
            new Selector.getter(name),
            elements.getGetterTypeMaskInComplexSendSet(node),
            sourceInformationBuilder.buildGet(node));
      }, rhs, (ir.Primitive result) {
        irBuilder.buildDynamicSet(
            target,
            new Selector.setter(name),
            elements.getTypeMask(node),
            result);
      });
    }
    return node.isConditional
        ? irBuilder.buildIfNotNullSend(target, nested(helper))
        : helper();
  }

  @override
  ir.Primitive handleDynamicSetIfNulls(
      ast.Send node,
      ast.Node receiver,
      Name name,
      ast.Node rhs,
      _) {
    ir.Primitive target = translateReceiver(receiver);
    ir.Primitive helper() {
      return translateSetIfNull(node, () {
        return irBuilder.buildDynamicGet(
            target,
            new Selector.getter(name),
            elements.getGetterTypeMaskInComplexSendSet(node),
            sourceInformationBuilder.buildGet(node));
      }, rhs, (ir.Primitive result) {
        irBuilder.buildDynamicSet(
            target,
            new Selector.setter(name),
            elements.getTypeMask(node),
            result);
      });
    }
    return node.isConditional
        ? irBuilder.buildIfNotNullSend(target, nested(helper))
        : helper();
  }

  ir.Primitive buildLocalNoSuchSetter(LocalElement local, ir.Primitive value) {
    Selector selector = new Selector.setter(
        new Name(local.name, local.library, isSetter: true));
    return irBuilder.buildStaticNoSuchMethod(selector, [value]);
  }

  @override
  ir.Primitive handleLocalCompounds(
      ast.SendSet node,
      LocalElement local,
      CompoundRhs rhs,
      arg,
      {bool isSetterValid}) {
    return translateCompounds(node, () {
      return irBuilder.buildLocalGet(local);
    }, rhs, (ir.Primitive result) {
      if (isSetterValid) {
        irBuilder.buildLocalVariableSet(local, result);
      } else {
        Selector selector = new Selector.setter(
            new Name(local.name, local.library, isSetter: true));
        irBuilder.buildStaticNoSuchMethod(selector, <ir.Primitive>[result]);
      }
    });
  }

  @override
  ir.Primitive handleLocalSetIfNulls(
      ast.SendSet node,
      LocalElement local,
      ast.Node rhs,
      _,
      {bool isSetterValid}) {
    return translateSetIfNull(node, () {
      return irBuilder.buildLocalGet(local);
    }, rhs, (ir.Primitive result) {
      if (isSetterValid) {
        irBuilder.buildLocalVariableSet(local, result);
      } else {
        Selector selector = new Selector.setter(
            new Name(local.name, local.library, isSetter: true));
        irBuilder.buildStaticNoSuchMethod(selector, <ir.Primitive>[result]);
      }
    });
  }

  @override
  ir.Primitive handleStaticCompounds(
      ast.SendSet node,
      Element getter,
      CompoundGetter getterKind,
      Element setter,
      CompoundSetter setterKind,
      CompoundRhs rhs,
      arg) {
    return translateCompounds(node, () {
      switch (getterKind) {
        case CompoundGetter.FIELD:
          SourceInformation src = sourceInformationBuilder.buildGet(node);
          return buildStaticFieldGet(getter, src);
        case CompoundGetter.GETTER:
          return buildStaticGetterGet(getter, node);
        case CompoundGetter.METHOD:
          return irBuilder.addPrimitive(new ir.GetStatic(getter));
        case CompoundGetter.UNRESOLVED:
          return irBuilder.buildStaticNoSuchMethod(
              new Selector.getter(new Name(getter.name, getter.library)),
              <ir.Primitive>[]);
      }
    }, rhs, (ir.Primitive result) {
      switch (setterKind) {
        case CompoundSetter.FIELD:
          irBuilder.addPrimitive(new ir.SetStatic(setter, result));
          return;
        case CompoundSetter.SETTER:
          irBuilder.buildStaticSetterSet(setter, result);
          return;
        case CompoundSetter.INVALID:
          irBuilder.buildStaticNoSuchMethod(
              new Selector.setter(new Name(setter.name, setter.library)),
              <ir.Primitive>[result]);
          return;
      }
    });
  }

  @override
  ir.Primitive handleStaticSetIfNulls(
      ast.SendSet node,
      Element getter,
      CompoundGetter getterKind,
      Element setter,
      CompoundSetter setterKind,
      ast.Node rhs,
      _) {
    return translateSetIfNull(node, () {
      switch (getterKind) {
        case CompoundGetter.FIELD:
          SourceInformation src = sourceInformationBuilder.buildGet(node);
          return buildStaticFieldGet(getter, src);
        case CompoundGetter.GETTER:
          return buildStaticGetterGet(getter, node);
        case CompoundGetter.METHOD:
          return irBuilder.addPrimitive(new ir.GetStatic(getter));
        case CompoundGetter.UNRESOLVED:
          return irBuilder.buildStaticNoSuchMethod(
              new Selector.getter(new Name(getter.name, getter.library)),
              <ir.Primitive>[]);
      }
    }, rhs, (ir.Primitive result) {
      switch (setterKind) {
        case CompoundSetter.FIELD:
          irBuilder.addPrimitive(new ir.SetStatic(setter, result));
          return;
        case CompoundSetter.SETTER:
          irBuilder.buildStaticSetterSet(setter, result);
          return;
        case CompoundSetter.INVALID:
          irBuilder.buildStaticNoSuchMethod(
              new Selector.setter(new Name(setter.name, setter.library)),
              <ir.Primitive>[result]);
          return;
      }
    });
  }

  ir.Primitive buildSuperNoSuchGetter(Element element, TypeMask mask) {
    return buildSuperNoSuchMethod(
        new Selector.getter(new Name(element.name, element.library)),
        mask,
        const <ir.Primitive>[]);
  }

  ir.Primitive buildSuperNoSuchSetter(Element element,
                                      TypeMask mask,
                                      ir.Primitive value) {
    return buildSuperNoSuchMethod(
        new Selector.setter(new Name(element.name, element.library)),
        mask,
        <ir.Primitive>[value]);
  }

  @override
  ir.Primitive handleSuperCompounds(
      ast.SendSet node,
      Element getter,
      CompoundGetter getterKind,
      Element setter,
      CompoundSetter setterKind,
      CompoundRhs rhs,
      arg) {
    return translateCompounds(node, () {
      switch (getterKind) {
        case CompoundGetter.FIELD:
          return irBuilder.buildSuperFieldGet(getter);
        case CompoundGetter.GETTER:
          return irBuilder.buildSuperGetterGet(
              getter, sourceInformationBuilder.buildGet(node));
        case CompoundGetter.METHOD:
          return irBuilder.buildSuperMethodGet(getter);
        case CompoundGetter.UNRESOLVED:
          return buildSuperNoSuchGetter(
              getter, elements.getGetterTypeMaskInComplexSendSet(node));
      }
    }, rhs, (ir.Primitive result) {
      switch (setterKind) {
        case CompoundSetter.FIELD:
          irBuilder.buildSuperFieldSet(setter, result);
          return;
        case CompoundSetter.SETTER:
          irBuilder.buildSuperSetterSet(setter, result);
          return;
        case CompoundSetter.INVALID:
          buildSuperNoSuchSetter(
              setter, elements.getTypeMask(node), result);
          return;
      }
    });
  }

  @override
  ir.Primitive handleSuperSetIfNulls(
      ast.SendSet node,
      Element getter,
      CompoundGetter getterKind,
      Element setter,
      CompoundSetter setterKind,
      ast.Node rhs,
      _) {
    return translateSetIfNull(node, () {
      switch (getterKind) {
        case CompoundGetter.FIELD:
          return irBuilder.buildSuperFieldGet(getter);
        case CompoundGetter.GETTER:
          return irBuilder.buildSuperGetterGet(
              getter, sourceInformationBuilder.buildGet(node));
        case CompoundGetter.METHOD:
          return irBuilder.buildSuperMethodGet(getter);
        case CompoundGetter.UNRESOLVED:
          return buildSuperNoSuchGetter(
              getter,
              elements.getGetterTypeMaskInComplexSendSet(node));
      }
    }, rhs, (ir.Primitive result) {
      switch (setterKind) {
        case CompoundSetter.FIELD:
          irBuilder.buildSuperFieldSet(setter, result);
          return;
        case CompoundSetter.SETTER:
          irBuilder.buildSuperSetterSet(setter, result);
          return;
        case CompoundSetter.INVALID:
          buildSuperNoSuchSetter(
              setter, elements.getTypeMask(node), result);
          return;
      }
    });
  }

  @override
  ir.Primitive handleTypeVariableTypeLiteralCompounds(
      ast.SendSet node,
      TypeVariableElement typeVariable,
      CompoundRhs rhs,
      arg) {
    return translateCompounds(node, () {
      return irBuilder.buildReifyTypeVariable(
          typeVariable.type,
          sourceInformationBuilder.buildGet(node));
    }, rhs, (ir.Primitive value) {
      // The binary operator will throw before this.
    });
  }

  @override
  ir.Primitive visitTypeVariableTypeLiteralSetIfNull(
      ast.Send node,
      TypeVariableElement element,
      ast.Node rhs,
      _) {
    // The type variable is never `null`.
    return translateTypeVariableTypeLiteral(element,
        sourceInformationBuilder.buildGet(node));
  }

  @override
  ir.Primitive handleIndexCompounds(
      ast.SendSet node,
      ast.Node receiver,
      ast.Node index,
      CompoundRhs rhs,
      arg) {
    ir.Primitive target = visit(receiver);
    ir.Primitive indexValue = visit(index);
    return translateCompounds(node, () {
      Selector selector = new Selector.index();
      List<ir.Primitive> arguments = <ir.Primitive>[indexValue];
      CallStructure callStructure =
          normalizeDynamicArguments(selector.callStructure, arguments);
      return irBuilder.buildDynamicInvocation(
          target,
          new Selector(selector.kind, selector.memberName, callStructure),
          elements.getGetterTypeMaskInComplexSendSet(node),
          arguments,
          sourceInformation:
          sourceInformationBuilder.buildCall(receiver, node));
    }, rhs, (ir.Primitive result) {
      irBuilder.buildDynamicIndexSet(
          target,
          elements.getTypeMask(node),
          indexValue,
          result);
    });
  }

  @override
  ir.Primitive handleSuperIndexCompounds(
      ast.SendSet node,
      Element indexFunction,
      Element indexSetFunction,
      ast.Node index,
      CompoundRhs rhs,
      arg,
      {bool isGetterValid,
       bool isSetterValid}) {
    ir.Primitive indexValue = visit(index);
    return translateCompounds(node, () {
      return isGetterValid
          ? irBuilder.buildSuperIndex(indexFunction, indexValue)
          : buildSuperNoSuchMethod(
              new Selector.index(),
              elements.getGetterTypeMaskInComplexSendSet(node),
              <ir.Primitive>[indexValue]);
    }, rhs, (ir.Primitive result) {
      if (isSetterValid) {
        irBuilder.buildSuperIndexSet(indexSetFunction, indexValue, result);
      } else {
        buildSuperNoSuchMethod(
            new Selector.indexSet(),
            elements.getTypeMask(node),
            <ir.Primitive>[indexValue, result]);
      }
    });
  }

  /// Build code to handle foreign code, that is, native JavaScript code, or
  /// builtin values and operations of the backend.
  ir.Primitive handleForeignCode(ast.Send node,
      MethodElement function,
      ast.NodeList argumentList,
      CallStructure callStructure) {

    void validateArgumentCount({int minimum, int exactly}) {
      assert((minimum == null) != (exactly == null));
      int count = 0;
      int maximum;
      if (exactly != null) {
        minimum = exactly;
        maximum = exactly;
      }
      for (ast.Node argument in argumentList) {
        count++;
        if (maximum != null && count > maximum) {
          internalError(argument, 'Additional argument.');
        }
      }
      if (count < minimum) {
        internalError(node, 'Expected at least $minimum arguments.');
      }
    }

    /// Call a helper method from the isolate library. The isolate library uses
    /// its own isolate structure, that encapsulates dart2js's isolate.
    ir.Primitive buildIsolateHelperInvocation(MethodElement element,
        CallStructure callStructure) {
      if (element == null) {
        reporter.internalError(node,
            'Isolate library and compiler mismatch.');
      }
      List<ir.Primitive> arguments = <ir.Primitive>[];
      callStructure = translateStaticArguments(argumentList, element,
          callStructure, arguments);
      Selector selector = new Selector.call(element.memberName, callStructure);
      return irBuilder.buildInvokeStatic(element, selector, arguments,
          sourceInformationBuilder.buildCall(node, node.selector));
    }

    /// Lookup the value of the enum described by [node].
    getEnumValue(ast.Node node, EnumClassElement enumClass, List values) {
      Element element = elements[node];
      if (element is! FieldElement || element.enclosingClass != enumClass) {
        internalError(node, 'expected a JsBuiltin enum value');
      }

      int index = enumClass.enumValues.indexOf(element);
      return values[index];
    }

    /// Returns the String the node evaluates to, or throws an error if the
    /// result is not a string constant.
    String expectStringConstant(ast.Node node) {
      ir.Primitive nameValue = visit(node);
      if (nameValue is ir.Constant && nameValue.value.isString) {
        StringConstantValue constantValue = nameValue.value;
        return constantValue.primitiveValue.slowToString();
      } else {
        return internalError(node, 'expected a literal string');
      }
    }

    Link<ast.Node> argumentNodes  = argumentList.nodes;
    NativeBehavior behavior =
    compiler.enqueuer.resolution.nativeEnqueuer.getNativeBehaviorOf(node);
    switch (function.name) {
      case 'JS':
        validateArgumentCount(minimum: 2);
        // The first two arguments are the type and the foreign code template,
        // which already have been analyzed by the resolver and can be retrieved
        // using [NativeBehavior]. We can ignore these arguments in the backend.
        List<ir.Primitive> arguments =
        argumentNodes.skip(2).mapToList(visit, growable: false);
        if (behavior.codeTemplate.positionalArgumentCount != arguments.length) {
          reporter.reportErrorMessage(
              node, MessageKind.GENERIC,
              {'text':
              'Mismatch between number of placeholders'
                  ' and number of arguments.'});
          return irBuilder.buildNullConstant();
        }

        if (HasCapturedPlaceholders.check(behavior.codeTemplate.ast)) {
          reporter.reportErrorMessage(node, MessageKind.JS_PLACEHOLDER_CAPTURE);
          return irBuilder.buildNullConstant();
        }

        return irBuilder.buildForeignCode(behavior.codeTemplate, arguments,
            behavior);

      case 'DART_CLOSURE_TO_JS':
      // TODO(ahe): This should probably take care to wrap the closure in
      // another closure that saves the current isolate.
      case 'RAW_DART_FUNCTION_REF':
        validateArgumentCount(exactly: 1);

        ast.Node argument = node.arguments.single;
        FunctionElement closure = elements[argument].implementation;
        if (!Elements.isStaticOrTopLevelFunction(closure)) {
          internalError(argument,
              'only static or toplevel function supported');
        }
        if (closure.functionSignature.hasOptionalParameters) {
          internalError(argument,
              'closures with optional parameters not supported');
        }
        return irBuilder.buildForeignCode(
            js.js.expressionTemplateYielding(
                backend.emitter.staticFunctionAccess(closure)),
            <ir.Primitive>[],
            NativeBehavior.PURE,
            dependency: closure);

      case 'JS_BUILTIN':
      // The first argument is a description of the type and effect of the
      // builtin, which has already been analyzed in the frontend.  The second
      // argument must be a [JsBuiltin] value.  All other arguments are
      // values used by the JavaScript template that is associated with the
      // builtin.
        validateArgumentCount(minimum: 2);

        ast.Node builtin = argumentNodes.tail.head;
        JsBuiltin value = getEnumValue(builtin, helpers.jsBuiltinEnum,
            JsBuiltin.values);
        js.Template template = backend.emitter.builtinTemplateFor(value);
        List<ir.Primitive> arguments =
        argumentNodes.skip(2).mapToList(visit, growable: false);
        return irBuilder.buildForeignCode(template, arguments, behavior);

      case 'JS_EMBEDDED_GLOBAL':
        validateArgumentCount(exactly: 2);

        String name = expectStringConstant(argumentNodes.tail.head);
        js.Expression access =
        backend.emitter.generateEmbeddedGlobalAccess(name);
        js.Template template = js.js.expressionTemplateYielding(access);
        return irBuilder.buildForeignCode(template, <ir.Primitive>[], behavior);

      case 'JS_INTERCEPTOR_CONSTANT':
        validateArgumentCount(exactly: 1);

        ast.Node argument = argumentNodes.head;
        ir.Primitive argumentValue = visit(argument);
        if (argumentValue is ir.Constant && argumentValue.value.isType) {
          TypeConstantValue constant = argumentValue.value;
          ConstantValue interceptorValue =
          new InterceptorConstantValue(constant.representedType);
          return irBuilder.buildConstant(interceptorValue);
        }
        return internalError(argument, 'expected Type as argument');

      case 'JS_EFFECT':
        return irBuilder.buildNullConstant();

      case 'JS_GET_NAME':
        validateArgumentCount(exactly: 1);

        ast.Node argument = argumentNodes.head;
        JsGetName id = getEnumValue(argument, helpers.jsGetNameEnum,
            JsGetName.values);
        js.Name name = backend.namer.getNameForJsGetName(argument, id);
        ConstantValue nameConstant =
        new SyntheticConstantValue(SyntheticConstantKind.NAME,
            js.js.quoteName(name));

        return irBuilder.buildConstant(nameConstant);

      case 'JS_GET_FLAG':
        validateArgumentCount(exactly: 1);

        String name = expectStringConstant(argumentNodes.first);
        bool value = false;
        switch (name) {
          case 'MUST_RETAIN_METADATA':
            value = backend.mustRetainMetadata;
            break;
          case 'USE_CONTENT_SECURITY_POLICY':
            value = compiler.useContentSecurityPolicy;
            break;
          default:
            internalError(node, 'Unknown internal flag "$name".');
        }
        return irBuilder.buildBooleanConstant(value);

      case 'JS_STRING_CONCAT':
        validateArgumentCount(exactly: 2);
        List<ir.Primitive> arguments = argumentNodes.mapToList(visit);
        return irBuilder.buildStringConcatenation(arguments);

      case 'JS_CURRENT_ISOLATE_CONTEXT':
        validateArgumentCount(exactly: 0);

        if (!compiler.hasIsolateSupport) {
          // If the isolate library is not used, we just generate code
          // to fetch the current isolate.
          continue getStaticState;
        }
        return buildIsolateHelperInvocation(helpers.currentIsolate,
            CallStructure.NO_ARGS);

      getStaticState: case 'JS_GET_STATIC_STATE':
        validateArgumentCount(exactly: 0);

        return irBuilder.buildForeignCode(
            js.js.parseForeignJS(backend.namer.staticStateHolder),
            const <ir.Primitive>[],
            NativeBehavior.DEPENDS_OTHER);

      case 'JS_SET_STATIC_STATE':
        validateArgumentCount(exactly: 1);

        ir.Primitive value = visit(argumentNodes.single);
        String isolateName = backend.namer.staticStateHolder;
        return irBuilder.buildForeignCode(
            js.js.parseForeignJS("$isolateName = #"),
            <ir.Primitive>[value],
            NativeBehavior.CHANGES_OTHER);

      case 'JS_CALL_IN_ISOLATE':
        validateArgumentCount(exactly: 2);

        if (!compiler.hasIsolateSupport) {
          ir.Primitive closure = visit(argumentNodes.tail.head);
          return irBuilder.buildCallInvocation(closure, CallStructure.NO_ARGS,
              const <ir.Primitive>[]);
        }
        return buildIsolateHelperInvocation(helpers.callInIsolate,
            CallStructure.TWO_ARGS);

      default:
        return giveup(node, 'unplemented native construct: ${function.name}');
    }
  }

  /// Evaluates a string interpolation and appends each part to [accumulator]
  /// (after stringify conversion).
  void buildStringParts(ast.Node node, List<ir.Primitive> accumulator) {
    if (node is ast.StringJuxtaposition) {
      buildStringParts(node.first, accumulator);
      buildStringParts(node.second, accumulator);
    } else if (node is ast.StringInterpolation) {
      buildStringParts(node.string, accumulator);
      for (ast.StringInterpolationPart part in node.parts) {
        buildStringParts(part.expression, accumulator);
        buildStringParts(part.string, accumulator);
      }
    } else if (node is ast.LiteralString) {
      // Empty strings often occur at the end of a string interpolation,
      // do not bother to include them.
      if (!node.dartString.isEmpty) {
        accumulator.add(irBuilder.buildDartStringConstant(node.dartString));
      }
    } else if (node is ast.ParenthesizedExpression) {
      buildStringParts(node.expression, accumulator);
    } else {
      ir.Primitive value = visit(node);
      accumulator.add(irBuilder.buildStaticFunctionInvocation(
          helpers.stringInterpolationHelper,
          <ir.Primitive>[value]));
    }
  }

  ir.Primitive visitStringJuxtaposition(ast.StringJuxtaposition node) {
    assert(irBuilder.isOpen);
    List<ir.Primitive> parts = <ir.Primitive>[];
    buildStringParts(node, parts);
    return irBuilder.buildStringConcatenation(parts);
  }

  ir.Primitive visitStringInterpolation(ast.StringInterpolation node) {
    assert(irBuilder.isOpen);
    List<ir.Primitive> parts = <ir.Primitive>[];
    buildStringParts(node, parts);
    return irBuilder.buildStringConcatenation(parts);
  }

  ir.Primitive translateConstant(ast.Node node) {
    assert(irBuilder.isOpen);
    return irBuilder.buildConstant(
        getConstantForNode(node),
        sourceInformation: sourceInformationBuilder.buildGet(node));
  }

  ir.Primitive visitThrow(ast.Throw node) {
    assert(irBuilder.isOpen);
    // This function is not called for throw expressions occurring as
    // statements.
    return irBuilder.buildNonTailThrow(visit(node.expression));
  }

  ir.Primitive buildSuperNoSuchMethod(Selector selector,
      TypeMask mask,
      List<ir.Primitive> arguments) {
    ClassElement cls = elements.analyzedElement.enclosingClass;
    MethodElement element = cls.lookupSuperMember(Identifiers.noSuchMethod_);
    if (!Selectors.noSuchMethod_.signatureApplies(element)) {
      element = compiler.coreClasses.objectClass.lookupMember(
          Identifiers.noSuchMethod_);
    }
    return irBuilder.buildSuperMethodInvocation(
        element,
        Selectors.noSuchMethod_.callStructure,
        [irBuilder.buildInvocationMirror(selector, arguments)]);
  }

  @override
  ir.Primitive visitUnresolvedCompound(
      ast.Send node,
      Element element,
      op.AssignmentOperator operator,
      ast.Node rhs, _) {
    // TODO(asgerf): What is unresolved? The getter and/or the setter?
    //               If it was the setter, we must evaluate the right-hand side.
    return irBuilder.buildStaticNoSuchMethod(elements.getSelector(node), []);
  }

  @override
  ir.Primitive visitUnresolvedClassConstructorInvoke(
      ast.NewExpression node,
      Element element,
      DartType type,
      ast.NodeList arguments,
      Selector selector, _) {
    // If the class is missing it's a runtime error.
    ir.Primitive message =
        irBuilder.buildStringConstant("Unresolved class: '${element.name}'");
    return irBuilder.buildStaticFunctionInvocation(
        helpers.throwRuntimeError,
        <ir.Primitive>[message]);
  }

  @override
  ir.Primitive visitUnresolvedConstructorInvoke(
      ast.NewExpression node,
      Element constructor,
      DartType type,
      ast.NodeList argumentsNode,
      Selector selector, _) {
    // If the class is there but the constructor is missing, it's an NSM error.
    List<ir.Primitive> arguments = <ir.Primitive>[];
    CallStructure callStructure = translateDynamicArguments(
        argumentsNode, selector.callStructure, arguments);
    return irBuilder.buildStaticNoSuchMethod(
        new Selector(selector.kind, selector.memberName, callStructure),
        arguments);
  }

  @override
  ir.Primitive visitConstructorIncompatibleInvoke(
      ast.NewExpression node,
      ConstructorElement constructor,
      DartType type,
      ast.NodeList argumentsNode,
      CallStructure callStructure, _) {
    List<ir.Primitive> arguments = <ir.Primitive>[];
    callStructure =
        translateDynamicArguments(argumentsNode, callStructure, arguments);
    return irBuilder.buildStaticNoSuchMethod(
        new Selector.call(constructor.memberName, callStructure), arguments);
  }

  @override
  ir.Primitive visitUnresolvedGet(
      ast.Send node,
      Element element, _) {
    return irBuilder.buildStaticNoSuchMethod(elements.getSelector(node), []);
  }

  @override
  ir.Primitive visitUnresolvedInvoke(
      ast.Send node,
      Element element,
      ast.NodeList arguments,
      Selector selector, _) {
    return irBuilder.buildStaticNoSuchMethod(elements.getSelector(node),
        arguments.nodes.mapToList(visit));
  }

  @override
  ir.Primitive visitUnresolvedRedirectingFactoryConstructorInvoke(
       ast.NewExpression node,
       ConstructorElement constructor,
       InterfaceType type,
       ast.NodeList argumentsNode,
       CallStructure callStructure, _) {
    String nameString = Elements.reconstructConstructorName(constructor);
    Name name = new Name(nameString, constructor.library);
    List<ir.Primitive> arguments = <ir.Primitive>[];
    callStructure =
        translateDynamicArguments(argumentsNode, callStructure, arguments);
    return irBuilder.buildStaticNoSuchMethod(
        new Selector.call(name, callStructure),
        arguments);
  }

  @override
  ir.Primitive visitUnresolvedSet(
      ast.Send node,
      Element element,
      ast.Node rhs, _) {
    return irBuilder.buildStaticNoSuchMethod(elements.getSelector(node),
        [visit(rhs)]);
  }

  @override
  ir.Primitive visitUnresolvedSuperIndex(
      ast.Send node,
      Element function,
      ast.Node index, _) {
    // Assume the index getter is missing.
    return buildSuperNoSuchMethod(
        new Selector.index(), elements.getTypeMask(node), [visit(index)]);
  }

  @override
  ir.Primitive visitUnresolvedSuperBinary(
      ast.Send node,
      Element element,
      op.BinaryOperator operator,
      ast.Node argument, _) {
    return buildSuperNoSuchMethod(
        elements.getSelector(node),
        elements.getTypeMask(node),
        [visit(argument)]);
  }

  @override
  ir.Primitive visitUnresolvedSuperUnary(
      ast.Send node,
      op.UnaryOperator operator,
      Element element, _) {
    return buildSuperNoSuchMethod(
        elements.getSelector(node), elements.getTypeMask(node), []);
  }

  @override
  ir.Primitive bulkHandleNode(ast.Node node, String message, _) {
    return giveup(node, "Unhandled node: ${message.replaceAll('#', '$node')}");
  }

  @override
  ir.Primitive bulkHandleError(ast.Node node, ErroneousElement error, _) {
    return irBuilder.buildNullConstant();
  }

  @override
  ir.Primitive visitClassTypeLiteralSet(
      ast.SendSet node,
      TypeConstantExpression constant,
      ast.Node rhs, _) {
    InterfaceType type = constant.type;
    ClassElement element = type.element;
    return irBuilder.buildStaticNoSuchMethod(
        new Selector.setter(element.memberName),
        [visit(rhs)]);
  }

  @override
  ir.Primitive visitTypedefTypeLiteralSet(
      ast.SendSet node,
      TypeConstantExpression constant,
      ast.Node rhs, _) {
    TypedefType type = constant.type;
    TypedefElement element = type.element;
    return irBuilder.buildStaticNoSuchMethod(
        new Selector.setter(element.memberName),
        [visit(rhs)]);
  }

  @override
  ir.Primitive visitTypeVariableTypeLiteralSet(
      ast.SendSet node,
      TypeVariableElement element,
      ast.Node rhs, _) {
    return irBuilder.buildStaticNoSuchMethod(
        new Selector.setter(element.memberName), [visit(rhs)]);
  }

  @override
  ir.Primitive visitDynamicTypeLiteralSet(
      ast.SendSet node,
      ConstantExpression constant,
      ast.Node rhs, _) {
    return irBuilder.buildStaticNoSuchMethod(
        new Selector.setter(Names.dynamic_), [visit(rhs)]);
  }

  @override
  ir.Primitive visitAbstractClassConstructorInvoke(
      ast.NewExpression node,
      ConstructorElement element,
      InterfaceType type,
      ast.NodeList arguments,
      CallStructure callStructure, _) {
    for (ast.Node argument in arguments) visit(argument);
    ir.Primitive name =
        irBuilder.buildStringConstant(element.enclosingClass.name);
    return irBuilder.buildStaticFunctionInvocation(
        helpers.throwAbstractClassInstantiationError,
        <ir.Primitive>[name]);
  }

  @override
  ir.Primitive handleFinalStaticFieldSet(
      ast.SendSet node,
      FieldElement field,
      ast.Node rhs, _) {
    // TODO(asgerf): Include class name somehow for static class members?
    return irBuilder.buildStaticNoSuchMethod(
        new Selector.setter(field.memberName),
        [visit(rhs)]);
  }

  @override
  ir.Primitive visitFinalSuperFieldSet(
      ast.SendSet node,
      FieldElement field,
      ast.Node rhs, _) {
    return buildSuperNoSuchMethod(
        new Selector.setter(field.memberName),
        elements.getTypeMask(node),
        [visit(rhs)]);
  }

  @override
  ir.Primitive handleImmutableLocalSet(
      ast.SendSet node,
      LocalElement local,
      ast.Node rhs, _) {
    return irBuilder.buildStaticNoSuchMethod(
        new Selector.setter(new Name(local.name, local.library)),
        [visit(rhs)]);
  }

  @override
  ir.Primitive handleStaticFunctionSet(
      ast.Send node,
      MethodElement function,
      ast.Node rhs,
      _) {
    return irBuilder.buildStaticNoSuchMethod(
        new Selector.setter(function.memberName),
        [visit(rhs)]);
  }

  @override
  ir.Primitive handleStaticGetterSet(
      ast.SendSet node,
      GetterElement getter,
      ast.Node rhs,
      _) {
    return irBuilder.buildStaticNoSuchMethod(
        new Selector.setter(getter.memberName),
        [visit(rhs)]);
  }

  @override
  ir.Primitive handleStaticSetterGet(
      ast.Send node,
      SetterElement setter,
      _) {
    return irBuilder.buildStaticNoSuchMethod(
        new Selector.getter(setter.memberName),
        []);
  }

  @override
  ir.Primitive handleStaticSetterInvoke(
      ast.Send node,
      SetterElement setter,
      ast.NodeList argumentsNode,
      CallStructure callStructure, _) {
    // Translate as a method call.
    List<ir.Primitive> arguments = argumentsNode.nodes.mapToList(visit);
    return irBuilder.buildStaticNoSuchMethod(
        new Selector.call(setter.memberName, callStructure),
        arguments);
  }

  @override
  ir.Primitive visitSuperGetterSet(
      ast.SendSet node,
      GetterElement getter,
      ast.Node rhs,
      _) {
    return buildSuperNoSuchMethod(
        new Selector.setter(getter.memberName),
        elements.getTypeMask(node),
        [visit(rhs)]);
  }

  @override
  ir.Primitive visitSuperMethodSet(
      ast.Send node,
      MethodElement method,
      ast.Node rhs,
      _) {
    return buildSuperNoSuchMethod(
        new Selector.setter(method.memberName),
        elements.getTypeMask(node),
        [visit(rhs)]);
  }

  @override
  ir.Primitive visitSuperSetterGet(
      ast.Send node,
      SetterElement setter, _) {
    return buildSuperNoSuchMethod(
        new Selector.setter(setter.memberName),
        elements.getTypeMask(node),
        []);
  }

  @override
  ir.Primitive visitSuperSetterInvoke(
      ast.Send node,
      SetterElement setter,
      ast.NodeList argumentsNode,
      CallStructure callStructure, _) {
    List<ir.Primitive> arguments = <ir.Primitive>[];
    callStructure =
        translateDynamicArguments(argumentsNode, callStructure, arguments);
    return buildSuperNoSuchMethod(
        new Selector.call(setter.memberName, callStructure),
        elements.getTypeMask(node),
        arguments);
  }

  ir.FunctionDefinition nullIfGiveup(ir.FunctionDefinition action()) {
    try {
      return action();
    } catch(e) {
      if (e == ABORT_IRNODE_BUILDER) {
        return null;
      }
      rethrow;
    }
  }

  internalError(ast.Node node, String message) {
    reporter.internalError(node, message);
  }

  @override
  visitNode(ast.Node node) {
    giveup(node, "Unhandled node");
  }

  dynamic giveup(ast.Node node, [String reason]) {
    bailoutMessage = '($node): $reason';
    throw ABORT_IRNODE_BUILDER;
  }
}

final String ABORT_IRNODE_BUILDER = "IrNode builder aborted";

/// Determines which local variables should be boxed in a mutable variable
/// inside a given try block.
class TryBoxedVariables extends ast.Visitor {
  final TreeElements elements;
  TryBoxedVariables(this.elements);

  FunctionElement currentFunction;
  bool insideInitializer = false;
  Set<Local> capturedVariables = new Set<Local>();

  /// A map containing variables boxed inside try blocks.
  ///
  /// The map is keyed by the [NodeList] of catch clauses for try/catch and
  /// by the finally block for try/finally.  try/catch/finally is treated
  /// as a try/catch nested in the try block of a try/finally.
  Map<ast.Node, TryStatementInfo> tryStatements =
      <ast.Node, TryStatementInfo>{};

  List<TryStatementInfo> tryNestingStack = <TryStatementInfo>[];
  bool get inTryStatement => tryNestingStack.isNotEmpty;

  String bailoutMessage = null;

  giveup(ast.Node node, [String reason]) {
    bailoutMessage = '($node): $reason';
    throw ABORT_IRNODE_BUILDER;
  }

  void markAsCaptured(Local local) {
    capturedVariables.add(local);
  }

  analyze(ast.Node node) {
    visit(node);
    // Variables that are captured by a closure are boxed for their entire
    // lifetime, so they never need to be boxed on entry to a try block.
    // They are not filtered out before this because we cannot identify all
    // of them in the same pass (they may be captured by a closure after the
    // try statement).
    for (TryStatementInfo info in tryStatements.values) {
      info.boxedOnEntry.removeAll(capturedVariables);
    }
  }

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

  visitNode(ast.Node node) {
    node.visitChildren(this);
  }

  void handleSend(ast.Send node) {
    Element element = elements[node];
    if (Elements.isLocal(element) &&
        !element.isConst &&
        element.enclosingElement != currentFunction) {
      LocalElement local = element;
      markAsCaptured(local);
    }
  }

  visitSend(ast.Send node) {
    handleSend(node);
    node.visitChildren(this);
  }

  visitSendSet(ast.SendSet node) {
    handleSend(node);
    Element element = elements[node];
    if (Elements.isLocal(element)) {
      LocalElement local = element;
      if (insideInitializer &&
          local.isParameter &&
          local.enclosingElement == currentFunction) {
        assert(local.enclosingElement.isConstructor);
        // Initializers in an initializer-list can communicate via parameters.
        // If a parameter is stored in an initializer list we box it.
        // TODO(sigurdm): Fix this.
        // Though these variables do not outlive the activation of the
        // function, they still need to be boxed.  As a simplification, we
        // treat them as if they are captured by a closure (i.e., they do
        // outlive the activation of the function).
        markAsCaptured(local);
      } else if (inTryStatement) {
        assert(local.isParameter || local.isVariable);
        // Search for the position of the try block containing the variable
        // declaration, or -1 if it is declared outside the outermost try.
        int i = tryNestingStack.length - 1;
        while (i >= 0 && !tryNestingStack[i].declared.contains(local)) {
          --i;
        }
        // If there is a next inner try, then the variable should be boxed on
        // entry to it.
        if (i + 1 < tryNestingStack.length) {
          tryNestingStack[i + 1].boxedOnEntry.add(local);
        }
      }
    }
    node.visitChildren(this);
  }

  visitFunctionExpression(ast.FunctionExpression node) {
    FunctionElement savedFunction = currentFunction;
    currentFunction = elements[node];

    if (currentFunction.asyncMarker != AsyncMarker.SYNC &&
        currentFunction.asyncMarker != AsyncMarker.SYNC_STAR &&
        currentFunction.asyncMarker != AsyncMarker.ASYNC) {
      giveup(node, "cannot handle async* functions");
    }

    if (node.initializers != null) {
      visit(node.initializers);
    }
    visit(node.body);
    currentFunction = savedFunction;
  }

  visitTryStatement(ast.TryStatement node) {
    // Try/catch/finally is treated as two simpler constructs: try/catch and
    // try/finally.  The encoding is:
    //
    // try S0 catch (ex, st) S1 finally S2
    // ==>
    // try { try S0 catch (ex, st) S1 } finally S2
    //
    // The analysis associates variables assigned in S0 with the catch clauses
    // and variables assigned in S0 and S1 with the finally block.
    TryStatementInfo enterTryFor(ast.Node node) {
      TryStatementInfo info = new TryStatementInfo();
      tryStatements[node] = info;
      tryNestingStack.add(info);
      return info;
    }
    void leaveTryFor(TryStatementInfo info) {
      assert(tryNestingStack.last == info);
      tryNestingStack.removeLast();
    }
    bool hasCatch = !node.catchBlocks.isEmpty;
    bool hasFinally = node.finallyBlock != null;
    TryStatementInfo catchInfo, finallyInfo;
    // There is a nesting stack of try blocks, so the outer try/finally block
    // is added first.
    if (hasFinally) finallyInfo = enterTryFor(node.finallyBlock);
    if (hasCatch) catchInfo = enterTryFor(node.catchBlocks);
    visit(node.tryBlock);

    if (hasCatch) {
      leaveTryFor(catchInfo);
      visit(node.catchBlocks);
    }
    if (hasFinally) {
      leaveTryFor(finallyInfo);
      visit(node.finallyBlock);
    }
  }

  visitVariableDefinitions(ast.VariableDefinitions node) {
    if (inTryStatement) {
      for (ast.Node definition in node.definitions.nodes) {
        LocalVariableElement local = elements[definition];
        assert(local != null);
        // In the closure conversion pass we check for isInitializingFormal,
        // but I'm not sure it can arise.
        assert(!local.isInitializingFormal);
        tryNestingStack.last.declared.add(local);
      }
    }
    node.visitChildren(this);
  }
}

/// The [IrBuilder]s view on the information about the program that has been
/// computed in resolution and and type interence.
class GlobalProgramInformation {
  final Compiler _compiler;
  JavaScriptBackend get _backend => _compiler.backend;

  GlobalProgramInformation(this._compiler);

  /// Returns [true], if the analysis could not determine that the type
  /// arguments for the class [cls] are never used in the program.
  bool requiresRuntimeTypesFor(ClassElement cls) {
    return cls.typeVariables.isNotEmpty && _backend.classNeedsRti(cls);
  }

  FunctionElement get throwTypeErrorHelper => _backend.helpers.throwTypeError;
  Element get throwNoSuchMethod => _backend.helpers.throwNoSuchMethod;

  ClassElement get nullClass => _compiler.coreClasses.nullClass;

  DartType unaliasType(DartType type) => type.unaliased;

  TypeMask getTypeMaskForForeign(NativeBehavior behavior) {
    if (behavior == null) {
      return _backend.dynamicType;
    }
    return TypeMaskFactory.fromNativeBehavior(behavior, _compiler);
  }

  bool isArrayType(TypeMask type) {
    return type.satisfies(_backend.helpers.jsArrayClass, _compiler.world);
  }

  TypeMask getTypeMaskForNativeFunction(FunctionElement function) {
    return  _compiler.typesTask.getGuaranteedReturnTypeOfElement(function);
  }

  FieldElement locateSingleField(Selector selector, TypeMask type) {
    return _compiler.world.locateSingleField(selector, type);
  }

  Element get closureConverter {
    return _backend.helpers.closureConverter;
  }

  void addNativeMethod(FunctionElement function) {
    _backend.emitter.nativeEmitter.nativeMethods.add(function);
  }

  bool get trustJSInteropTypeAnnotations =>
      _compiler.trustJSInteropTypeAnnotations;

  bool isNative(ClassElement element) => _backend.isNative(element);

  bool isJsInterop(FunctionElement element) => _backend.isJsInterop(element);

  bool isJsInteropAnonymous(FunctionElement element) =>
    _backend.jsInteropAnalysis.hasAnonymousAnnotation(element.contextClass);

  String getJsInteropTargetPath(FunctionElement element) {
    return '${_backend.namer.fixedBackendPath(element)}.'
      '${_backend.getFixedBackendName(element)}';
  }

  DartType get jsJavascriptObjectType =>
    _backend.helpers.jsJavaScriptObjectClass.thisType;
}
