// Copyright (c) 2016, 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.md file.

import 'package:kernel/ast.dart' as ir;
import 'package:kernel/frontend/accessors.dart'
    show
        Accessor,
        IndexAccessor,
        NullAwarePropertyAccessor,
        PropertyAccessor,
        ReadOnlyAccessor,
        StaticAccessor,
        SuperIndexAccessor,
        SuperPropertyAccessor,
        ThisPropertyAccessor,
        VariableAccessor,
        buildIsNull,
        makeBinary,
        makeLet,
        makeOrReuseVariable;
import 'package:kernel/transformations/flags.dart';

import '../common.dart';
import '../constants/expressions.dart'
    show
        BoolFromEnvironmentConstantExpression,
        ConstantExpression,
        ConstructedConstantExpression,
        IntFromEnvironmentConstantExpression,
        StringFromEnvironmentConstantExpression,
        TypeConstantExpression;
import '../dart_types.dart' show DartType, InterfaceType;
import '../diagnostics/spannable.dart' show Spannable;
import '../elements/elements.dart'
    show
        AstElement,
        AsyncMarker,
        ClassElement,
        ConstructorElement,
        Element,
        FieldElement,
        FunctionElement,
        FunctionSignature,
        GetterElement,
        InitializingFormalElement,
        JumpTarget,
        LocalElement,
        LocalFunctionElement,
        LocalVariableElement,
        MethodElement,
        Name,
        ParameterElement,
        PrefixElement,
        TypeVariableElement;
import '../resolution/operators.dart'
    show AssignmentOperator, BinaryOperator, IncDecOperator, UnaryOperator;
import '../resolution/semantic_visitor.dart'
    show
        BaseImplementationOfCompoundsMixin,
        BaseImplementationOfLocalsMixin,
        BaseImplementationOfSetIfNullsMixin,
        BaseImplementationOfStaticsMixin,
        CompoundGetter,
        CompoundKind,
        CompoundRhs,
        CompoundSetter,
        SemanticDeclarationResolvedMixin,
        SemanticDeclarationVisitor,
        SemanticSendResolvedMixin,
        SemanticSendVisitor,
        SemanticVisitor;
import '../resolution/send_resolver.dart' show DeclarationResolverMixin;
import '../resolution/send_structure.dart'
    show
        InitializerStructure,
        InitializersStructure,
        ParameterStructure,
        VariableStructure;
import '../resolution/tree_elements.dart' show TreeElements;
import '../tree/tree.dart'
    show
        Assert,
        AsyncForIn,
        Await,
        Block,
        BreakStatement,
        Cascade,
        CascadeReceiver,
        CaseMatch,
        CatchBlock,
        Conditional,
        ConditionalUri,
        ContinueStatement,
        DoWhile,
        DottedName,
        EmptyStatement,
        Enum,
        Expression,
        ExpressionStatement,
        For,
        ForIn,
        FunctionDeclaration,
        FunctionExpression,
        Identifier,
        If,
        Label,
        LabeledStatement,
        LiteralBool,
        LiteralDouble,
        LiteralInt,
        LiteralList,
        LiteralMap,
        LiteralMapEntry,
        LiteralNull,
        LiteralString,
        LiteralSymbol,
        Metadata,
        NamedArgument,
        NewExpression,
        Node,
        NodeList,
        Operator,
        ParenthesizedExpression,
        RedirectingFactoryBody,
        Rethrow,
        Return,
        Send,
        SendSet,
        Statement,
        StringInterpolation,
        StringInterpolationPart,
        StringJuxtaposition,
        SwitchCase,
        SwitchStatement,
        SyncForIn,
        Throw,
        TryStatement,
        TypeAnnotation,
        TypeVariable,
        VariableDefinitions,
        While,
        Yield;
import '../universe/call_structure.dart' show CallStructure;
import '../universe/selector.dart' show Selector;
import '../util/util.dart' show Link;
import 'error.dart' show KernelError;
import 'fall_through_visitor.dart' show fallsThrough;
import 'kernel.dart' show ConstructorTarget, Kernel;
import 'unavailable.dart' show UnavailableVisitor;
import 'unresolved.dart' show UnresolvedVisitor;

/// Translates dart2js AST nodes [Node] into Kernel IR [ir.TreeNode].
///
/// Most methods in this class have a prefix that follows these conventions:
///
///   * `visit` for overridden visitor methods.
///   * `handle` for methods that implement common behavior for several `visit`
///     methods. These methods are called by `visit` methods implemented by
///     various mixins below.
///   * `build` helper method that builds a new Kernel IR tree.
///   * `get` helper method that use a cache to build exactly one Kernel IR
///     tree for a given element.
///
/// We reserve the prefixes `visit` and `handle` for superclasses of this
/// class. So those methods should always have an @override annotation. Use
/// `build` instead of `handle` when adding a new helper method to this class.
class KernelVisitor extends Object
    with
        SemanticSendResolvedMixin,
        BaseImplementationOfStaticsMixin,
        BaseImplementationOfLocalsMixin,
        BaseImplementationOfCompoundsMixin,
        BaseImplementationOfSetIfNullsMixin,
        SemanticDeclarationResolvedMixin,
        DeclarationResolverMixin,
        UnavailableVisitor,
        UnresolvedVisitor,
        KernelError
    implements
        SemanticVisitor,
        SemanticSendVisitor,
        SemanticDeclarationVisitor {
  TreeElements elements;
  AstElement currentElement;
  final Kernel kernel;
  int transformerFlags = 0;

  final Map<JumpTarget, ir.LabeledStatement> continueTargets =
      <JumpTarget, ir.LabeledStatement>{};

  final Map<JumpTarget, ir.SwitchCase> continueSwitchTargets =
      <JumpTarget, ir.SwitchCase>{};

  final Map<JumpTarget, ir.LabeledStatement> breakTargets =
      <JumpTarget, ir.LabeledStatement>{};

  final Map<LocalElement, ir.VariableDeclaration> locals =
      <LocalElement, ir.VariableDeclaration>{};

  final Map<CascadeReceiver, ir.VariableGet> cascadeReceivers =
      <CascadeReceiver, ir.VariableGet>{};

  ir.Node associateElement(ir.Node node, Element element) {
    kernel.nodeToElement[node] = element;
    return node;
  }

  ir.Node associateNode(ir.Node node, Node ast) {
    kernel.nodeToAst[node] = ast;
    return node;
  }

  bool isVoidContext = false;

  KernelVisitor(this.currentElement, this.elements, this.kernel);

  KernelVisitor get sendVisitor => this;

  KernelVisitor get declVisitor => this;

  ir.TreeNode visitForValue(Expression node) {
    bool wasVoidContext = isVoidContext;
    isVoidContext = false;
    try {
      return node?.accept(this);
    } finally {
      isVoidContext = wasVoidContext;
    }
  }

  ir.TreeNode visitForEffect(Expression node) {
    bool wasVoidContext = isVoidContext;
    isVoidContext = true;
    try {
      return node?.accept(this);
    } finally {
      isVoidContext = wasVoidContext;
    }
  }

  ir.TreeNode visitWithCurrentContext(Expression node) => node?.accept(this);

  withCurrentElement(AstElement element, f()) {
    assert(element.library == kernel.compiler.currentElement.library);
    Element previousElement = currentElement;
    currentElement = element;
    try {
      return f();
    } finally {
      currentElement = previousElement;
    }
  }

  ir.DartType computeType(TypeAnnotation node) {
    if (node == null) return const ir.DynamicType();
    return kernel.typeToIr(elements.getType(node));
  }

  // This works around a bug in dart2js.
  // TODO(ahe): Fix the bug in dart2js and remove this function.
  ir.DartType typeToIrHack(DartType type) {
    if (currentElement.isSynthesized &&
        currentElement.enclosingClass.isMixinApplication &&
        !kernel.hasHierarchyProblem(currentElement.enclosingClass)) {
      // Dart2js doesn't compute the correct functionSignature for synthetic
      // constructors in mixin applications. So we compute the correct type:
      // First, find the first superclass that isn't a mixin.
      ClassElement superclass = currentElement.enclosingClass.superclass;
      while (superclass.isMixinApplication) {
        superclass = superclass.superclass;
      }
      // Then translate the "this type" of the mixin application to its
      // supertype with the correct type arguments.
      //
      // Consider this example:
      //
      //     class Super<S> {}
      //     class Sub<T> extends Object with Super<T> {}
      //
      // Here the problem is that dart2js has created a constructor that refers
      // to S (not T) in Sub (for example, the return type of the constructor
      // is Super<S> and it should be Sub<T>, but we settle for Super<T> for
      // now). So we need to translate Sub<T> to an instance of Super, which is
      // Super<T> (not Super<S>).
      InterfaceType supertype =
          currentElement.enclosingClass.asInstanceOf(superclass);
      // Once we have [supertype], we know how to substitute S with T: the type
      // arguments of [supertype] corresponds to T, and the type variables of
      // its element correspond to S.
      type =
          type.subst(supertype.typeArguments, supertype.element.typeVariables);
    }
    return kernel.typeToIr(type);
  }

  // TODO(ahe): Hack. Fix dart2js instead.
  ir.Name nameToIrName(Name name) {
    assert(!name.isPrivate ||
        name.library.implementation == currentElement.library.implementation);
    return kernel.irName(name.text, currentElement);
  }

  List<ir.DartType> computeTypesFromTypes(NodeList nodes, {int expected}) {
    if (expected == null) {
      throw "[expected] is null";
    }
    List<ir.DartType> types = new List<ir.DartType>(expected);
    Iterator<Node> iterator = nodes?.iterator;
    for (int i = 0; i < expected; i++) {
      TypeAnnotation type = null;
      if (iterator != null && iterator.moveNext()) {
        type = iterator.current;
      }
      types[i] = computeType(type);
    }
    if (iterator != null && iterator.moveNext()) {
      // Should already have been reported by resolution.
      // TODO(ahe): Delete this debug message.
      kernel.debugMessage(iterator.current, "Extra type arguments.");
    }
    return types;
  }

  ir.DartType computeTypeFromTypes(NodeList node) {
    return computeTypesFromTypes(node, expected: 1).single;
  }

  ir.MethodInvocation buildInvokeSelector(
      ir.Expression receiver, Selector selector, ir.Arguments arguments) {
    return new ir.MethodInvocation(
        receiver, nameToIrName(selector.memberName), arguments);
  }

  ir.MethodInvocation buildCall(
      ir.Expression receiver, CallStructure callStructure, NodeList arguments) {
    return buildInvokeSelector(
        receiver, callStructure.callSelector, buildArguments(arguments));
  }

  @override
  ir.Expression visitIdentifier(Identifier node) {
    // TODO(ahe): Shouldn't have to override this method, but
    // [SemanticSendResolvedMixin.visitIdentifier] may return `null` on errors.
    if (node.isThis()) {
      return sendVisitor.visitThisGet(node, null);
    } else {
      return new ir.InvalidExpression();
    }
  }

  @override
  ir.InvalidExpression handleUnresolved(Node node) {
    return new ir.InvalidExpression();
  }

  @override
  ir.Expression handleError(Node node) => new ir.InvalidExpression();

  @override
  void apply(Node node, _) {
    throw new UnsupportedError("apply");
  }

  @override
  void previsitDeferredAccess(Send node, PrefixElement prefix, _) {}

  @override
  internalError(Spannable spannable, String message) {
    kernel.internalError(spannable, message);
  }

  @override
  applyParameters(NodeList parameters, _) {
    throw new UnsupportedError("applyParameters");
  }

  @override
  applyInitializers(FunctionExpression constructor, _) {
    throw new UnsupportedError("applyInitializers");
  }

  @override
  ir.AssertStatement visitAssert(Assert node) {
    return new ir.AssertStatement(
        visitForValue(node.condition), visitForValue(node.message));
  }

  ir.LabeledStatement getBreakTarget(JumpTarget target) {
    return breakTargets.putIfAbsent(
        target, () => new ir.LabeledStatement(null));
  }

  ir.LabeledStatement getContinueTarget(JumpTarget target) {
    return continueTargets.putIfAbsent(
        target, () => new ir.LabeledStatement(null));
  }

  ir.SwitchCase getContinueSwitchTarget(JumpTarget target) {
    return continueSwitchTargets[target];
  }

  ir.Statement buildBreakTarget(
      ir.Statement statement, Node node, JumpTarget jumpTarget) {
    assert(node.isValidBreakTarget());
    assert(jumpTarget == elements.getTargetDefinition(node));
    if (jumpTarget != null && jumpTarget.isBreakTarget) {
      ir.LabeledStatement breakTarget = getBreakTarget(jumpTarget);
      breakTarget.body = statement;
      statement.parent = breakTarget;
      return breakTarget;
    } else {
      return statement;
    }
  }

  ir.Statement buildContinueTarget(
      ir.Statement statement, Node node, JumpTarget jumpTarget) {
    assert(node.isValidContinueTarget());
    assert(jumpTarget == elements.getTargetDefinition(node));
    if (jumpTarget != null && jumpTarget.isContinueTarget) {
      ir.LabeledStatement continueTarget = getContinueTarget(jumpTarget);
      continueTarget.body = statement;
      statement.parent = continueTarget;
      return continueTarget;
    } else {
      return statement;
    }
  }

  ir.Statement buildForInCommon(
      ForIn node, ir.VariableDeclaration variable, ir.Statement body,
      {bool isAsync}) {
    ir.Expression iterable = visitForValue(node.expression);
    JumpTarget jumpTarget = elements.getTargetDefinition(node);
    body = buildContinueTarget(body, node, jumpTarget);
    return buildBreakTarget(
        new ir.ForInStatement(variable, iterable, body, isAsync: isAsync),
        node,
        jumpTarget);
  }

  /// Builds a for-in statement for this case:
  ///
  ///     for (constOrVarOrType loopVariable in expression) body
  ir.Statement buildForInWithDeclaration(
      ForIn node, VariableDefinitions declaration,
      {bool isAsync}) {
    if (declaration.definitions.slowLength() != 1) {
      // It's not legal to declare more than one variable in a for-in loop.
      return new ir.InvalidStatement();
    }
    ir.VariableDeclaration variable = declaration.accept(this);
    return buildForInCommon(node, variable, buildStatementInBlock(node.body),
        isAsync: isAsync);
  }

  Accessor buildStaticAccessor(Element getter, [Element setter]) {
    if (setter == null &&
        getter != null &&
        getter.isField &&
        !getter.isFinal &&
        !getter.isConst) {
      setter = getter;
    }
    return new StaticAccessor(
        (getter == null) ? null : kernel.elementToIr(getter),
        (setter == null) ? null : kernel.elementToIr(setter));
  }

  Accessor computeAccessor(ForIn node, Element element) {
    if (element == null) {
      Send send = node.declaredIdentifier.asSend();
      if (send == null) {
        return buildStaticAccessor(null);
      }
      // This should be the situation where `node.declaredIdentifier` is
      // unresolved, but in an instance method context. If it is some different
      // situation, the assignment to [ir.PropertyGet] should act as an
      // assertion.
      ir.PropertyGet expression = visitForValue(send);
      return PropertyAccessor.make(
          expression.receiver, expression.name, null, null);
    } else if (kernel.isSyntheticError(element)) {
      return buildStaticAccessor(null);
    } else if (element.isGetter) {
      if (element.isInstanceMember) {
        return new ThisPropertyAccessor(
            kernel.irName(element.name, element), null, null);
      } else {
        GetterElement getter = element;
        Element setter = getter.setter;
        return buildStaticAccessor(getter, setter);
      }
    } else if (element.isLocal) {
      return new VariableAccessor(getLocal(element));
    } else if (element.isField) {
      return buildStaticAccessor(element);
    } else {
      return buildStaticAccessor(null);
    }
  }

  /// Builds a for-in statement for this case:
  ///
  ///     for (element in expression) body
  ///
  /// This is normalized to:
  ///
  ///     for (final #t in expression) {
  ///       element = #t;
  ///       body;
  ///     }
  ir.Statement buildForInWithoutDeclaration(ForIn node, Element element,
      {bool isAsync}) {
    Accessor accessor = computeAccessor(node, elements.getForInVariable(node));
    // Since we've created [variable], we know it's only assigned to in the
    // loop header and can be final.
    ir.VariableDeclaration variable =
        new ir.VariableDeclaration.forValue(null, isFinal: true);
    ir.Statement assigment = new ir.ExpressionStatement(accessor
        .buildAssignment(new ir.VariableGet(variable), voidContext: true));
    ir.Block body = buildStatementInBlock(node.body, forceBlock: true);
    List<ir.Statement> statements = <ir.Statement>[assigment]
      ..addAll(body.statements);
    return buildForInCommon(node, variable, new ir.Block(statements),
        isAsync: isAsync);
  }

  ir.Statement buildForIn(ForIn node, {bool isAsync}) {
    VariableDefinitions declaration =
        node.declaredIdentifier.asVariableDefinitions();
    if (declaration != null) {
      return buildForInWithDeclaration(node, declaration, isAsync: isAsync);
    } else {
      Element element = elements.getForInVariable(node);
      return buildForInWithoutDeclaration(node, element, isAsync: isAsync);
    }
  }

  @override
  ir.Statement visitAsyncForIn(AsyncForIn node) {
    return buildForIn(node, isAsync: true);
  }

  @override
  ir.AwaitExpression visitAwait(Await node) {
    return new ir.AwaitExpression(visitForValue(node.expression));
  }

  @override
  ir.Statement visitBlock(Block node) {
    return buildBreakTarget(
        buildStatementInBlock(node), node, elements.getTargetDefinition(node));
  }

  bool buildStatement(Statement statement, List<ir.Statement> statements) {
    ir.Node irNode = statement.accept(this);
    bool hasVariableDeclaration = false;
    if (irNode is VariableDeclarations) {
      statements.addAll(irNode.variables);
      hasVariableDeclaration = true;
    } else {
      statements.add(irNode);
      if (irNode is ir.VariableDeclaration) {
        hasVariableDeclaration = true;
      }
    }
    return hasVariableDeclaration;
  }

  ir.Statement buildStatementInBlock(Statement node, {bool forceBlock: false}) {
    if (node == null) return null;
    List<ir.Statement> statements = <ir.Statement>[];
    if (node is Block) {
      for (Node statement in node.statements.nodes) {
        buildStatement(statement, statements);
      }
    } else {
      if (buildStatement(node, statements)) forceBlock = true;
      if (!forceBlock && statements.length == 1) {
        return statements.single;
      }
      // One VariableDefinitions statement node (dart2js AST) may generate
      // multiple statements in Kernel IR so we sometimes fall through here.
    }
    return new ir.Block(statements);
  }

  @override
  ir.Statement visitBreakStatement(BreakStatement node) {
    JumpTarget target = elements.getTargetOf(node);
    if (target == null || !target.statement.isValidBreakTarget()) {
      // This is a break in an invalid position.
      return new ir.InvalidStatement();
    }
    // A break can break to itself in the degenerate case `label: break
    // label'`.
    return buildBreakTarget(new ir.BreakStatement(getBreakTarget(target)), node,
        elements.getTargetDefinition(node));
  }

  CascadeReceiver computeCascadeReceiver(Cascade cascade) {
    CascadeReceiver receiver;
    Expression send = cascade.expression.asSend();
    while (send != null && (receiver = send.asCascadeReceiver()) == null) {
      Expression possibleReceiver = send.asSend()?.receiver;
      if (possibleReceiver != null) {
        send = possibleReceiver;
      } else {
        // Can happen in this case: `a..add(foo)('WHAT')`.
        send = send.asSend()?.selector;
      }
    }
    if (receiver == null) {
      internalError(cascade, "Can't find cascade receiver");
    }
    return receiver;
  }

  @override
  ir.Let visitCascade(Cascade node) {
    // Given this cascade expression `receiver..cascade1()..cascade2()`, the
    // parser has produced a tree like this:
    //     Cascade(Send(
    //         CascadeReceiver(Cascade(Send(
    //             CascadeRecevier(receiver), 'cascade1', []))),
    //         'cascade2', []))
    // If viewed as a tree, `CascadeReceiver(receiver)` is the left-most leaf
    // node.  Below, we create this:
    //     cascades = [
    //         Cascade(Send(CascadeReceiver(...), 'cascade2', [])),
    //         Cascade(Send(CascadeReceiver(...), 'cascade1', []))]
    // Notice that the cascades are in reverse order, which we use to build a
    // `let` expression bottom up.
    // First iteration of the loop produces:
    //     let dummy = rcv.cascade2() in
    //         rcv
    // Second iteration:
    //     let dummy = rcv.cascade1() in
    //         let dummy = rcv.cascade2() in
    //             rcv
    // Finally we return:
    //     let rcv = receiver in
    //         let dummy = rcv.cascade1() in
    //             let dummy = rcv.cascade2() in
    //                 rcv
    int startLength;
    assert((startLength = cascadeReceivers.length) >= 0);

    Cascade cascade = node;
    List<Cascade> cascades = <Cascade>[];
    CascadeReceiver receiver;
    ir.VariableDeclaration receiverVariable = makeOrReuseVariable(null);

    do {
      cascades.add(cascade);
      receiver = computeCascadeReceiver(cascade);
      cascadeReceivers[receiver] = new ir.VariableGet(receiverVariable);
      cascade = receiver.expression.asCascade();
    } while (cascade != null);
    // At this point, all nested [Cascades] targeting the same receiver have
    // been collected in [cascades] in reverse order. [receiver] is the
    // left-most receiver. [receiverVariable] will hold the value of evaluating
    // [receiver]. Each [CascadeReceiver] has a getter for [receiverVariable]
    // in [cascadeReceivers].

    receiverVariable.initializer = visitForValue(receiver.expression);
    receiverVariable.initializer.parent = receiverVariable;

    ir.Expression result = new ir.VariableGet(receiverVariable); // rcv.
    for (Cascade cascade in cascades) {
      // When evaluating `cascade.expression`, we stop the recursion at
      // [visitCascadeReceiver] and instead returns an [ir.VariableGet].
      // TODO(ahe): Use visitForEffect here?
      ir.Expression value = visitForValue(cascade.expression);
      result = new ir.Let(makeOrReuseVariable(value), result);
    }

    assert(startLength == cascadeReceivers.length);
    return new ir.Let(receiverVariable, result);
  }

  @override
  ir.VariableGet visitCascadeReceiver(CascadeReceiver node) {
    return cascadeReceivers.remove(node);
  }

  @override
  visitCaseMatch(CaseMatch node) {
    // Shouldn't be called. Handled by [visitSwitchCase].
    return internalError(node, "CaseMatch");
  }

  @override
  ir.Catch visitCatchBlock(CatchBlock node) {
    ir.VariableDeclaration exception =
        (node.exception == null) ? null : getLocal(elements[node.exception]);
    ir.VariableDeclaration trace =
        (node.trace == null) ? null : getLocal(elements[node.trace]);
    ir.DartType guard = computeType(node.type);
    return new ir.Catch(exception, buildStatementInBlock(node.block),
        guard: guard, stackTrace: trace);
  }

  @override
  ir.ConditionalExpression visitConditional(Conditional node) {
    return new ir.ConditionalExpression(
        visitForValue(node.condition),
        visitWithCurrentContext(node.thenExpression),
        visitWithCurrentContext(node.elseExpression));
  }

  @override
  ir.Statement visitContinueStatement(ContinueStatement node) {
    JumpTarget target = elements.getTargetOf(node);
    if (target == null || !target.statement.isValidContinueTarget()) {
      // This is a continue in an invalid position.
      return new ir.InvalidStatement();
    }
    ir.SwitchCase switchCase = getContinueSwitchTarget(target);
    return (switchCase == null)
        ? new ir.BreakStatement(getContinueTarget(target))
        : new ir.ContinueSwitchStatement(switchCase);
  }

  @override
  ir.Statement visitDoWhile(DoWhile node) {
    JumpTarget jumpTarget = elements.getTargetDefinition(node);
    ir.Statement body =
        buildContinueTarget(buildStatementInBlock(node.body), node, jumpTarget);
    ir.Expression condition = visitForValue(node.condition);
    return buildBreakTarget(
        new ir.DoStatement(body, condition), node, jumpTarget);
  }

  @override
  ir.EmptyStatement visitEmptyStatement(EmptyStatement node) {
    return new ir.EmptyStatement();
  }

  @override
  visitEnum(Enum node) {
    // Not called normally. In dart2js, enums are represented as class
    // elements, so `classToIr` handles enums.  All the synthetic members of an
    // enum class have already been installed by dart2js and we don't have to
    // do anything special.
    return internalError(node, "Enum");
  }

  @override
  ir.ExpressionStatement visitExpressionStatement(ExpressionStatement node) {
    return new ir.ExpressionStatement(visitForEffect(node.expression));
  }

  @override
  ir.Statement visitFor(For node) {
    VariableDefinitions initializers =
        node.initializer?.asVariableDefinitions();
    ir.Expression initializer;
    List<ir.VariableDeclaration> variables;
    if (initializers != null) {
      ir.Block block = buildStatementInBlock(initializers, forceBlock: true);
      variables = new List<ir.VariableDeclaration>.from(block.statements);
    } else {
      if (node.initializer != null) {
        initializer = visitForValue(node.initializer);
      }
      variables = const <ir.VariableDeclaration>[];
    }
    ir.Expression condition = visitForValue(node.condition);
    List<ir.Expression> updates = <ir.Expression>[];
    for (Expression update in node.update) {
      updates.add(visitForEffect(update));
    }

    JumpTarget jumpTarget = elements.getTargetDefinition(node);
    ir.Statement body =
        buildContinueTarget(buildStatementInBlock(node.body), node, jumpTarget);
    ir.ForStatement forStatement = associateNode(
        new ir.ForStatement(variables, condition, updates, body), node);
    ir.Statement result = buildBreakTarget(forStatement, node, jumpTarget);
    if (initializer != null) {
      result = new ir.Block(
          <ir.Statement>[new ir.ExpressionStatement(initializer), result]);
    }
    return result;
  }

  @override
  ir.FunctionDeclaration visitFunctionDeclaration(FunctionDeclaration node) {
    return node.function.accept(this);
  }

  @override
  ir.Statement visitIf(If node) {
    return buildBreakTarget(
        new ir.IfStatement(
            visitForValue(node.condition),
            buildStatementInBlock(node.thenPart),
            buildStatementInBlock(node.elsePart)),
        node,
        elements.getTargetDefinition(node));
  }

  @override
  visitLabel(Label node) {
    // Shouldn't be called. Handled by visitLabeledStatement and
    // visitSwitchCase.
    return internalError(node, "Label");
  }

  @override
  ir.Statement visitLabeledStatement(LabeledStatement node) {
    Statement statement = node.statement;
    ir.Statement result = (statement is Block)
        // If [statement] is a Block, we need to ensure that we don't bypass
        // its visit method (so it can build break targets correctly).
        ? statement.accept(this)
        : buildStatementInBlock(statement);

    // A [LabeledStatement] isn't the actual jump target, instead, [statement]
    // is the target. This allows uniform handling of break and continue in
    // loops. The following code simply assert that [result] has been generated
    // correctly with respect to jump targets.
    JumpTarget jumpTarget = elements.getTargetDefinition(node.statement);
    if (jumpTarget != null) {
      if (jumpTarget.isBreakTarget) {
        ir.LabeledStatement target = breakTargets[jumpTarget];
        if (target != null && target != result && target.parent == null) {
          internalError(node, "no parent");
        }
      }
      if (jumpTarget.isContinueTarget) {
        ir.LabeledStatement target = continueTargets[jumpTarget];
        if (target != null && target != result && target.parent == null) {
          internalError(node, "no parent");
        }
      }
    }

    return result;
  }

  @override
  ir.BoolLiteral visitLiteralBool(LiteralBool node) {
    return new ir.BoolLiteral(node.value);
  }

  @override
  ir.DoubleLiteral visitLiteralDouble(LiteralDouble node) {
    return new ir.DoubleLiteral(node.value);
  }

  @override
  ir.IntLiteral visitLiteralInt(LiteralInt node) {
    return new ir.IntLiteral(node.value);
  }

  @override
  ir.ListLiteral visitLiteralList(LiteralList node) {
    // TODO(ahe): Type arguments.
    List<ir.Expression> elements = <ir.Expression>[];
    for (Expression element in node.elements.nodes) {
      elements.add(visitForValue(element));
    }
    return associateNode(
        new ir.ListLiteral(elements,
            typeArgument: computeTypeFromTypes(node.typeArguments),
            // TODO(ahe): Should constness be validated?
            isConst: node.isConst),
        node);
  }

  @override
  ir.MapLiteral visitLiteralMap(LiteralMap node) {
    // TODO(ahe): Type arguments.
    List<ir.MapEntry> entries = <ir.MapEntry>[];
    for (LiteralMapEntry entry in node.entries.nodes) {
      entries.add(new ir.MapEntry(
          visitForValue(entry.key), visitForValue(entry.value)));
    }
    List<ir.DartType> typeArguments =
        computeTypesFromTypes(node.typeArguments, expected: 2);
    return associateNode(
        new ir.MapLiteral(entries,
            keyType: typeArguments.first,
            valueType: typeArguments.last,
            // TODO(ahe): Should Constness be validated?
            isConst: node.isConst),
        node);
  }

  @override
  visitLiteralMapEntry(LiteralMapEntry node) {
    // Shouldn't be called. Handled by [visitLiteralMap].
    return internalError(node, "LiteralMapEntry");
  }

  @override
  ir.NullLiteral visitLiteralNull(LiteralNull node) {
    return new ir.NullLiteral();
  }

  @override
  ir.Expression visitLiteralString(LiteralString node) {
    if (node.dartString == null) return new ir.InvalidExpression();
    return new ir.StringLiteral(node.dartString.slowToString());
  }

  @override
  ir.SymbolLiteral visitLiteralSymbol(LiteralSymbol node) {
    var result = new ir.SymbolLiteral(node.slowNameString);
    return associateNode(result, node);
  }

  @override
  visitMetadata(Metadata node) {
    // Shouldn't be called. Metadata should already have been analyzed and
    // converted to a constant expression in the resolver.
    return internalError(node, "Metadata not handled as constant.");
  }

  @override
  ir.NamedExpression visitNamedArgument(NamedArgument node) {
    return new ir.NamedExpression(
        node.name.source, visitForValue(node.expression));
  }

  @override
  visitOperator(Operator node) {
    // This is a special subclass of [Identifier], and we should never see that
    // in the semantic visitor.
    return internalError(node, "Operator");
  }

  @override
  ir.Expression visitParenthesizedExpression(ParenthesizedExpression node) {
    return visitWithCurrentContext(node.expression);
  }

  @override
  ir.InvalidStatement visitRedirectingFactoryBody(RedirectingFactoryBody node) {
    // Not implemented yet, only serves to recover from parser errors as
    // dart2js is lenient in parsing something that looks like a redirecting
    // factory method.
    return new ir.InvalidStatement();
  }

  @override
  ir.ExpressionStatement visitRethrow(Rethrow node) {
    return new ir.ExpressionStatement(new ir.Rethrow());
  }

  @override
  ir.ReturnStatement visitReturn(Return node) {
    return new ir.ReturnStatement(visitForValue(node.expression));
  }

  @override
  ir.StringConcatenation visitStringInterpolation(StringInterpolation node) {
    List<ir.Expression> expressions = <ir.Expression>[];
    expressions.add(visitForValue(node.string));
    for (StringInterpolationPart part in node.parts) {
      expressions.add(visitForValue(part.expression));
      expressions.add(visitForValue(part.string));
    }
    return new ir.StringConcatenation(expressions);
  }

  @override
  ir.StringConcatenation visitStringJuxtaposition(StringJuxtaposition node) {
    return new ir.StringConcatenation(
        <ir.Expression>[visitForValue(node.first), visitForValue(node.second)]);
  }

  @override
  ir.SwitchCase visitSwitchCase(SwitchCase node) {
    List<ir.Expression> expressions = <ir.Expression>[];
    for (var labelOrCase in node.labelsAndCases.nodes) {
      CaseMatch match = labelOrCase.asCaseMatch();
      if (match != null) {
        expressions.add(visitForValue(match.expression));
      } else {
        // Assert that labelOrCase is one of two known types: [CaseMatch] or
        // [Label]. We ignore cases, as any users have been resolved to use the
        // case directly.
        assert(labelOrCase.asLabel() != null);
      }
    }
    // We ignore the node's statements here, they're generated below in
    // [visitSwitchStatement] once we've set up all the jump targets.
    return new ir.SwitchCase(expressions, null, isDefault: node.isDefaultCase);
  }

  @override
  ir.Statement visitSwitchStatement(SwitchStatement node) {
    ir.Expression expression = visitForValue(node.expression);
    List<ir.SwitchCase> cases = <ir.SwitchCase>[];
    for (SwitchCase caseNode in node.cases.nodes) {
      cases.add(caseNode.accept(this));
      JumpTarget jumpTarget = elements.getTargetDefinition(caseNode);
      if (jumpTarget != null) {
        assert(jumpTarget.isContinueTarget);
        assert(!continueSwitchTargets.containsKey(jumpTarget));
        continueSwitchTargets[jumpTarget] = cases.last;
      }
    }

    Iterator<ir.SwitchCase> casesIterator = cases.iterator;
    for (Link<Node> link = node.cases.nodes;
        link.isNotEmpty;
        link = link.tail) {
      SwitchCase caseNode = link.head;
      bool isLastCase = link.tail.isEmpty;
      if (!casesIterator.moveNext()) {
        internalError(caseNode, "case node mismatch");
      }
      ir.SwitchCase irCase = casesIterator.current;
      List<ir.Statement> statements = <ir.Statement>[];
      bool hasVariableDeclaration = false;
      for (Statement statement in caseNode.statements.nodes) {
        if (buildStatement(statement, statements)) {
          hasVariableDeclaration = true;
        }
      }
      if (!isLastCase &&
          (statements.isEmpty || fallsThrough(statements.last))) {
        statements.add(new ir.ExpressionStatement(new ir.Throw(
            new ir.StaticInvocation(kernel.getFallThroughErrorBuilder(),
                new ir.Arguments.empty()))));
      }
      ir.Statement body;
      if (!hasVariableDeclaration && statements.length == 1) {
        body = statements.single;
      } else {
        body = new ir.Block(statements);
      }
      irCase.body = body;
      body.parent = irCase;
    }
    assert(!casesIterator.moveNext());

    return buildBreakTarget(new ir.SwitchStatement(expression, cases), node,
        elements.getTargetDefinition(node));
  }

  @override
  ir.Statement visitSyncForIn(SyncForIn node) {
    return buildForIn(node, isAsync: false);
  }

  @override
  ir.Throw visitThrow(Throw node) {
    return new ir.Throw(visitForValue(node?.expression));
  }

  @override
  ir.Statement visitTryStatement(TryStatement node) {
    ir.Statement result = buildStatementInBlock(node.tryBlock);
    if (node.catchBlocks != null && !node.catchBlocks.isEmpty) {
      List<ir.Catch> catchBlocks = <ir.Catch>[];
      for (CatchBlock block in node.catchBlocks.nodes) {
        catchBlocks.add(block.accept(this));
      }
      result = new ir.TryCatch(result, catchBlocks);
    }
    if (node.finallyBlock != null) {
      result =
          new ir.TryFinally(result, buildStatementInBlock(node.finallyBlock));
    }
    return buildBreakTarget(result, node, elements.getTargetDefinition(node));
  }

  @override
  visitTypeAnnotation(TypeAnnotation node) {
    // Shouldn't be called, as the resolver have already resolved types and
    // created [DartType] objects.
    return internalError(node, "TypeAnnotation");
  }

  @override
  visitTypeVariable(TypeVariable node) {
    // Shouldn't be called, as the resolver have already resolved types and
    // created [DartType] objects.
    return internalError(node, "TypeVariable");
  }

  @override
  ir.Statement visitWhile(While node) {
    ir.Expression condition = visitForValue(node.condition);
    JumpTarget jumpTarget = elements.getTargetDefinition(node);
    ir.Statement body =
        buildContinueTarget(buildStatementInBlock(node.body), node, jumpTarget);
    return buildBreakTarget(
        associateNode(new ir.WhileStatement(condition, body), node),
        node,
        jumpTarget);
  }

  @override
  ir.YieldStatement visitYield(Yield node) {
    return new ir.YieldStatement(visitForValue(node.expression),
        isYieldStar: node.hasStar);
  }

  @override
  ir.InvalidExpression visitAbstractClassConstructorInvoke(
      NewExpression node,
      ConstructorElement element,
      InterfaceType type,
      NodeList arguments,
      CallStructure callStructure,
      _) {
    return new ir.InvalidExpression();
  }

  IrFunction buildIrFunction(
      ir.ProcedureKind kind, FunctionElement function, Node body) {
    return new IrFunction.procedure(kind, buildFunctionNode(function, body));
  }

  @override
  IrFunction visitAbstractGetterDeclaration(
      FunctionExpression node, MethodElement getter, _) {
    return buildIrFunction(ir.ProcedureKind.Getter, getter, null);
  }

  @override
  IrFunction visitAbstractSetterDeclaration(
      FunctionExpression node, MethodElement setter, NodeList parameters, _) {
    return buildIrFunction(ir.ProcedureKind.Setter, setter, null);
  }

  @override
  ir.AsExpression visitAs(Send node, Node expression, DartType type, _) {
    return new ir.AsExpression(
        visitForValue(expression), kernel.typeToIr(type));
  }

  @override
  ir.MethodInvocation visitBinary(
      Send node, Node left, BinaryOperator operator, Node right, _) {
    return associateNode(
        buildBinaryOperator(left, operator.selectorName, right), node);
  }

  ir.Expression buildConstructorInvoke(NewExpression node, {bool isConst}) {
    ConstructorElement constructor = elements[node.send];
    ConstructorTarget target;
    if (isConst) {
      target =
          kernel.computeEffectiveTarget(constructor, elements.getType(node));
    } else {
      target = new ConstructorTarget(constructor, elements.getType(node));
    }
    NodeList arguments = node.send.argumentsNode;
    if (kernel.isSyntheticError(target.element)) {
      return new ir.MethodInvocation(new ir.InvalidExpression(),
          kernel.irName("call", currentElement), buildArguments(arguments));
    }
    ir.InvocationExpression invoke = target.element.isGenerativeConstructor
        ? buildGenerativeConstructorInvoke(target.element, arguments,
            isConst: isConst)
        : buildStaticInvoke(target.element, arguments, isConst: isConst);
    if (target.type.isInterfaceType) {
      InterfaceType type = target.type;
      if (type.isGeneric) {
        invoke.arguments.types.addAll(kernel.typesToIr(type.typeArguments));
      }
    }
    return invoke;
  }

  @override
  ir.InvocationExpression visitBoolFromEnvironmentConstructorInvoke(
      NewExpression node, BoolFromEnvironmentConstantExpression constant, _) {
    return buildConstructorInvoke(node, isConst: true);
  }

  ir.TypeLiteral buildTypeLiteral(TypeConstantExpression constant) {
    return new ir.TypeLiteral(kernel.typeLiteralToIr(constant));
  }

  @override
  ir.TypeLiteral visitClassTypeLiteralGet(
      Send node, ConstantExpression constant, _) {
    return buildTypeLiteral(constant);
  }

  @override
  ir.MethodInvocation visitClassTypeLiteralInvoke(
      Send node,
      ConstantExpression constant,
      NodeList arguments,
      CallStructure callStructure,
      _) {
    return buildCall(buildTypeLiteral(constant), callStructure, arguments);
  }

  ir.Expression buildTypeLiteralSet(TypeConstantExpression constant, Node rhs) {
    return new ReadOnlyAccessor(buildTypeLiteral(constant))
        .buildAssignment(visitForValue(rhs), voidContext: isVoidContext);
  }

  @override
  ir.Expression visitClassTypeLiteralSet(
      SendSet node, ConstantExpression constant, Node rhs, _) {
    return buildTypeLiteralSet(constant, rhs);
  }

  @override
  ir.FunctionExpression visitClosureDeclaration(FunctionExpression node,
      LocalFunctionElement closure, NodeList parameters, Node body, _) {
    return withCurrentElement(closure, () {
      ir.FunctionExpression function =
          new ir.FunctionExpression(buildFunctionNode(closure, body));
      kernel.localFunctions[closure] = function;
      return function;
    });
  }

  @override
  ir.Expression visitCompoundIndexSet(SendSet node, Node receiver, Node index,
      AssignmentOperator operator, Node rhs, _) {
    return buildIndexAccessor(receiver, index).buildCompoundAssignment(
        kernel.irName(operator.selectorName, currentElement),
        visitForValue(rhs),
        voidContext: isVoidContext);
  }

  @override
  ir.InvocationExpression visitConstConstructorInvoke(
      NewExpression node, ConstructedConstantExpression constant, _) {
    return buildConstructorInvoke(node, isConst: true);
  }

  @override
  visitConstantGet(Send node, ConstantExpression constant, _) {
    // TODO(ahe): This method is never called. Is it a bug in semantic visitor?
    return internalError(node, "ConstantGet");
  }

  @override
  visitConstantInvoke(Send node, ConstantExpression constant,
      NodeList arguments, CallStructure callStructure, _) {
    // TODO(ahe): This method is never called. Is it a bug in semantic visitor?
    return internalError(node, "ConstantInvoke");
  }

  @override
  ir.InvalidExpression visitConstructorIncompatibleInvoke(
      NewExpression node,
      ConstructorElement constructor,
      InterfaceType type,
      NodeList arguments,
      CallStructure callStructure,
      _) {
    return new ir.InvalidExpression();
  }

  @override
  ir.PropertyGet visitDynamicPropertyGet(
      Send node, Node receiver, Name name, _) {
    return associateNode(
        new ir.PropertyGet(visitForValue(receiver), nameToIrName(name)), node);
  }

  @override
  ir.MethodInvocation visitDynamicPropertyInvoke(
      Send node, Node receiver, NodeList arguments, Selector selector, _) {
    return associateNode(
        buildInvokeSelector(
            visitForValue(receiver), selector, buildArguments(arguments)),
        node);
  }

  @override
  ir.Expression handleDynamicCompounds(
      Send node, Node receiver, Name name, CompoundRhs rhs, _) {
    ir.Expression receiverNode =
        receiver == null ? new ir.ThisExpression() : visitForValue(receiver);
    ir.Expression compound = buildCompound(
        PropertyAccessor.make(receiverNode, nameToIrName(name), null, null),
        rhs);
    if (compound is ir.VariableSet) {
      associateNode(compound.value, node);
    } else {
      associateNode(compound, node);
    }
    return compound;
  }

  @override
  ir.PropertySet visitDynamicPropertySet(
      SendSet node, Node receiver, Name name, Node rhs, _) {
    ir.Expression value = visitForValue(rhs);
    return new ir.PropertySet(
        visitForValue(receiver), nameToIrName(name), value);
  }

  @override
  ir.Expression handleDynamicSetIfNulls(
      Send node, Node receiver, Name name, Node rhs, _) {
    ir.Name irName = nameToIrName(name);
    Accessor accessor = (receiver == null)
        ? new ThisPropertyAccessor(irName, null, null)
        : PropertyAccessor.make(visitForValue(receiver), irName, null, null);
    return accessor.buildNullAwareAssignment(visitForValue(rhs),
        voidContext: isVoidContext);
  }

  @override
  ir.TypeLiteral visitDynamicTypeLiteralGet(
      Send node, ConstantExpression constant, _) {
    return buildTypeLiteral(constant);
  }

  @override
  ir.MethodInvocation visitDynamicTypeLiteralInvoke(
      Send node,
      ConstantExpression constant,
      NodeList arguments,
      CallStructure callStructure,
      _) {
    return buildCall(buildTypeLiteral(constant), callStructure, arguments);
  }

  @override
  ir.Expression visitDynamicTypeLiteralSet(
      SendSet node, ConstantExpression constant, Node rhs, _) {
    return buildTypeLiteralSet(constant, rhs);
  }

  ir.MethodInvocation buildBinaryOperator(
      Node left, String operator, Node right) {
    ir.Name name = kernel.irName(operator, currentElement);
    return makeBinary(visitForValue(left), name, null, visitForValue(right));
  }

  @override
  ir.MethodInvocation visitEquals(Send node, Node left, Node right, _) {
    return associateNode(buildBinaryOperator(left, '==', right), node);
  }

  @override
  ir.MethodInvocation visitExpressionInvoke(Send node, Node expression,
      NodeList arguments, CallStructure callStructure, _) {
    return associateNode(
        buildCall(visitForValue(expression), callStructure, arguments), node);
  }

  @override
  IrFunction visitFactoryConstructorDeclaration(FunctionExpression node,
      ConstructorElement constructor, NodeList parameters, Node body, _) {
    return buildIrFunction(ir.ProcedureKind.Factory, constructor, body);
  }

  @override
  ir.InvocationExpression visitFactoryConstructorInvoke(
      NewExpression node,
      ConstructorElement constructor,
      InterfaceType type,
      NodeList arguments,
      CallStructure callStructure,
      _) {
    return buildConstructorInvoke(node, isConst: false);
  }

  @override
  ir.Initializer visitFieldInitializer(
      SendSet node, FieldElement field, Node expression, _) {
    if (kernel.isSyntheticError(field)) {
      return new ir.InvalidInitializer();
    } else {
      return new ir.FieldInitializer(
          kernel.fieldToIr(field), visitForValue(expression));
    }
  }

  ir.Expression buildStaticFieldSet(FieldElement field, Node rhs) {
    return buildStaticAccessor(field)
        .buildAssignment(visitForValue(rhs), voidContext: isVoidContext);
  }

  @override
  ir.Expression handleFinalStaticFieldSet(
      SendSet node, FieldElement field, Node rhs, _) {
    return buildStaticFieldSet(field, rhs);
  }

  @override
  ir.Expression visitFinalSuperFieldSet(
      SendSet node, FieldElement field, Node rhs, _) {
    return buildSuperPropertyAccessor(field)
        .buildAssignment(visitForValue(rhs), voidContext: isVoidContext);
  }

  IrFunction buildGenerativeConstructor(
      ConstructorElement constructor, NodeList parameters, Node body) {
    List<ir.Initializer> constructorInitializers = <ir.Initializer>[];
    if (kernel.hasHierarchyProblem(constructor.enclosingClass)) {
      constructorInitializers.add(new ir.InvalidInitializer());
    } else if (constructor.isSynthesized) {
      List<ir.Expression> arguments = const <ir.Expression>[];
      List<ir.NamedExpression> named = const <ir.NamedExpression>[];
      FunctionSignature signature = constructor.functionSignature;
      if (signature.parameterCount != 0) {
        // Mixin application implicit super call.
        arguments = <ir.Expression>[];
        named = <ir.NamedExpression>[];
        signature.orderedForEachParameter((ParameterElement parameter) {
          ir.VariableGet argument = buildLocalGet(parameter);
          if (parameter.isNamed) {
            named.add(new ir.NamedExpression(parameter.name, argument));
          } else {
            arguments.add(argument);
          }
        });
      }
      if (kernel.isSyntheticError(constructor.definingConstructor)) {
        constructorInitializers.add(new ir.InvalidInitializer());
      } else {
        constructorInitializers.add(new ir.SuperInitializer(
            kernel.functionToIr(constructor.definingConstructor),
            new ir.Arguments(arguments, named: named, types: null)));
      }
    } else {
      if (parameters != null) {
        // TODO(ahe): the following is a (modified) copy of
        // [SemanticDeclarationResolvedMixin.visitParameters].
        List<ParameterStructure> structures =
            computeParameterStructures(parameters);
        for (ParameterStructure structure in structures) {
          if (structure.parameter.isInitializingFormal) {
            constructorInitializers.add(structure.dispatch(declVisitor, null));
          }
        }
      }
      // TODO(ahe): the following is a (modified) copy of
      // [SemanticDeclarationResolvedMixin.visitInitializers].
      InitializersStructure initializers =
          computeInitializersStructure(constructor.node);
      for (InitializerStructure structure in initializers.initializers) {
        constructorInitializers.add(structure.dispatch(declVisitor, null));
      }
    }
    return new IrFunction.constructor(
        buildFunctionNode(constructor, body), constructorInitializers);
  }

  @override
  IrFunction visitGenerativeConstructorDeclaration(
      FunctionExpression node,
      ConstructorElement constructor,
      NodeList parameters,
      NodeList initializers,
      Node body,
      _) {
    return buildGenerativeConstructor(constructor, parameters, body);
  }

  ir.ConstructorInvocation buildGenerativeConstructorInvoke(
      ConstructorElement constructor, NodeList arguments,
      {bool isConst}) {
    if (const bool.fromEnvironment("require_kernel_arguments")) {
      // Check that all constructors from kernel/ast.dart (that are invoked
      // from this package) provide all arguments (including optional
      // arguments).
      // TODO(ahe): Remove this when the implementation has matured.
      if (("package:kernel/ast.dart" ==
              "${constructor.library.canonicalUri}") &&
          "${currentElement.library.canonicalUri}"
              .startsWith("package:rasta/")) {
        if (constructor.functionSignature.parameterCount !=
            arguments.slowLength()) {
          kernel.debugMessage(arguments, "Missing arguments");
          kernel.debugMessage(constructor, "When calling the constructor");
        }
      }
    }
    ir.Arguments argumentsNode = buildArguments(arguments);
    ir.Constructor target = kernel.functionToIr(constructor);
    return new ir.ConstructorInvocation(target, argumentsNode,
        isConst: isConst);
  }

  @override
  ir.InvocationExpression visitGenerativeConstructorInvoke(
      NewExpression node,
      ConstructorElement constructor,
      InterfaceType type,
      NodeList arguments,
      CallStructure callStructure,
      _) {
    return buildConstructorInvoke(node, isConst: false);
  }

  Accessor buildNullAwarePropertyAccessor(Node receiver, Name name) {
    return new NullAwarePropertyAccessor(
        visitForValue(receiver), nameToIrName(name), null, null);
  }

  @override
  ir.Expression visitIfNotNullDynamicPropertyGet(
      Send node, Node receiver, Name name, _) {
    return buildNullAwarePropertyAccessor(receiver, name).buildSimpleRead();
  }

  @override
  ir.Let visitIfNotNullDynamicPropertyInvoke(
      Send node, Node receiverNode, NodeList arguments, Selector selector, _) {
    ir.VariableDeclaration receiver =
        makeOrReuseVariable(visitForValue(receiverNode));
    return makeLet(
        receiver,
        new ir.ConditionalExpression(
            buildIsNull(new ir.VariableGet(receiver)),
            new ir.NullLiteral(),
            buildInvokeSelector(new ir.VariableGet(receiver), selector,
                buildArguments(arguments))));
  }

  @override
  ir.Expression visitIfNotNullDynamicPropertySet(
      SendSet node, Node receiver, Name name, Node rhs, _) {
    return buildNullAwarePropertyAccessor(receiver, name)
        .buildAssignment(visitForValue(rhs), voidContext: isVoidContext);
  }

  @override
  ir.Expression visitIfNotNullDynamicPropertySetIfNull(
      Send node, Node receiver, Name name, Node rhs, _) {
    return buildNullAwarePropertyAccessor(receiver, name)
        .buildNullAwareAssignment(visitForValue(rhs),
            voidContext: isVoidContext);
  }

  ir.LogicalExpression buildLogicalExpression(
      Node left, Operator operator, Node right) {
    return new ir.LogicalExpression(
        visitForValue(left), operator.source, visitForValue(right));
  }

  @override
  ir.LogicalExpression visitIfNull(Send node, Node left, Node right, _) {
    return buildLogicalExpression(left, node.selector, right);
  }

  @override
  ir.Initializer visitImplicitSuperConstructorInvoke(FunctionExpression node,
      ConstructorElement superConstructor, InterfaceType type, _) {
    if (superConstructor == null) {
      // TODO(ahe): Semantic visitor shouldn't call this.
      return new ir.InvalidInitializer();
    }
    return new ir.SuperInitializer(
        kernel.functionToIr(superConstructor), new ir.Arguments.empty());
  }

  Accessor buildIndexAccessor(Node receiver, Node index) {
    return IndexAccessor.make(
        visitForValue(receiver), visitForValue(index), null, null);
  }

  @override
  ir.Expression visitIndex(Send node, Node receiver, Node index, _) {
    return associateNode(
        buildIndexAccessor(receiver, index).buildSimpleRead(), node);
  }

  ir.Expression buildIndexPostfix(Accessor accessor, IncDecOperator operator) {
    ir.Name name = kernel.irName(operator.selectorName, currentElement);
    return accessor.buildPostfixIncrement(name, voidContext: isVoidContext);
  }

  @override
  ir.Expression visitIndexPostfix(
      Send node, Node receiver, Node index, IncDecOperator operator, _) {
    return buildIndexPostfix(buildIndexAccessor(receiver, index), operator);
  }

  ir.Expression buildIndexPrefix(Accessor accessor, IncDecOperator operator) {
    ir.Name name = kernel.irName(operator.selectorName, currentElement);
    return accessor.buildPrefixIncrement(name, voidContext: isVoidContext);
  }

  @override
  ir.Expression visitIndexPrefix(
      Send node, Node receiver, Node index, IncDecOperator operator, _) {
    return buildIndexPrefix(buildIndexAccessor(receiver, index), operator);
  }

  @override
  ir.Expression visitIndexSet(
      SendSet node, Node receiver, Node index, Node rhs, _) {
    return associateNode(
        buildIndexAccessor(receiver, index)
            .buildAssignment(visitForValue(rhs), voidContext: isVoidContext),
        node);
  }

  ir.Initializer buildInitializingFormal(InitializingFormalElement parameter) {
    FieldElement field = parameter.fieldElement;
    if (kernel.isSyntheticError(field)) {
      return new ir.InvalidInitializer();
    } else {
      return new ir.FieldInitializer(
          kernel.fieldToIr(field), buildLocalGet(parameter));
    }
  }

  @override
  ir.Initializer visitInitializingFormalDeclaration(VariableDefinitions node,
      Node definition, InitializingFormalElement parameter, int index, _) {
    return buildInitializingFormal(parameter);
  }

  @override
  visitInstanceFieldDeclaration(VariableDefinitions node, Node definition,
      FieldElement field, Node initializer, _) {
    // Shouldn't be called, handled by fieldToIr.
    return internalError(node, "InstanceFieldDeclaration");
  }

  @override
  IrFunction visitInstanceGetterDeclaration(
      FunctionExpression node, MethodElement getter, Node body, _) {
    return buildIrFunction(ir.ProcedureKind.Getter, getter, body);
  }

  @override
  IrFunction visitInstanceSetterDeclaration(FunctionExpression node,
      MethodElement setter, NodeList parameters, Node body, _) {
    return buildIrFunction(ir.ProcedureKind.Setter, setter, body);
  }

  @override
  ir.InvocationExpression visitIntFromEnvironmentConstructorInvoke(
      NewExpression node, IntFromEnvironmentConstantExpression constant, _) {
    return buildConstructorInvoke(node, isConst: true);
  }

  ir.IsExpression buildIs(Node expression, DartType type) {
    return new ir.IsExpression(
        visitForValue(expression), kernel.typeToIr(type));
  }

  @override
  ir.IsExpression visitIs(Send node, Node expression, DartType type, _) {
    return buildIs(expression, type);
  }

  @override
  ir.Not visitIsNot(Send node, Node expression, DartType type, _) {
    return new ir.Not(buildIs(expression, type));
  }

  ir.VariableDeclaration buildLocalVariableDeclaration(
      LocalVariableElement variable, Node initializer) {
    ir.Expression initializerNode = visitForValue(initializer);
    ir.VariableDeclaration local = getLocal(variable);
    if (initializer != null) {
      local.initializer = initializerNode;
      initializerNode.parent = local;
    }
    return local;
  }

  @override
  ir.VariableDeclaration visitLocalConstantDeclaration(
      VariableDefinitions node,
      Node definition,
      LocalVariableElement variable,
      ConstantExpression constant,
      _) {
    // TODO(ahe): Use [constant]?
    return buildLocalVariableDeclaration(variable, variable.initializer)
      ..isConst = true;
  }

  @override
  ir.FunctionDeclaration visitLocalFunctionDeclaration(FunctionExpression node,
      LocalFunctionElement localFunction, NodeList parameters, Node body, _) {
    return withCurrentElement(localFunction, () {
      ir.VariableDeclaration local = getLocal(localFunction)..isFinal = true;
      ir.FunctionDeclaration function = new ir.FunctionDeclaration(
          local, buildFunctionNode(localFunction, body));
      // Closures can escape their context and we must therefore store them
      // globally to include them in the world computation.
      kernel.localFunctions[localFunction] = function;
      return function;
    });
  }

  @override
  ir.VariableDeclaration visitLocalVariableDeclaration(VariableDefinitions node,
      Node definition, LocalVariableElement variable, Node initializer, _) {
    return buildLocalVariableDeclaration(variable, initializer);
  }

  ir.VariableGet buildLocalGet(LocalElement local) {
    return new ir.VariableGet(getLocal(local));
  }

  @override
  ir.VariableGet handleLocalGet(Send node, LocalElement element, _) {
    return buildLocalGet(element);
  }

  ir.Expression buildCompound(Accessor accessor, CompoundRhs rhs) {
    ir.Name name = kernel.irName(rhs.operator.selectorName, currentElement);
    switch (rhs.kind) {
      case CompoundKind.POSTFIX:
        return accessor.buildPostfixIncrement(name, voidContext: isVoidContext);

      case CompoundKind.PREFIX:
        return accessor.buildPrefixIncrement(name, voidContext: isVoidContext);

      case CompoundKind.ASSIGNMENT:
        return accessor.buildCompoundAssignment(name, visitForValue(rhs.rhs),
            voidContext: isVoidContext);
    }
  }

  @override
  ir.Expression handleLocalCompounds(
      SendSet node, LocalElement local, CompoundRhs rhs, _,
      {bool isSetterValid}) {
    ir.Expression compound =
        buildCompound(new VariableAccessor(getLocal(local)), rhs);
    if (compound is ir.VariableSet) {
      associateNode(compound.value, node);
    } else {
      associateNode(compound, node);
    }
    return compound;
  }

  @override
  ir.VariableSet handleLocalSet(
      SendSet node, LocalElement element, Node rhs, _) {
    return new ir.VariableSet(getLocal(element), visitForValue(rhs));
  }

  @override
  ir.VariableSet handleImmutableLocalSet(
      SendSet node, LocalElement element, Node rhs, _) {
    // TODO(ahe): Build invalid?
    return handleLocalSet(node, element, rhs, _);
  }

  @override
  ir.LogicalExpression visitLogicalAnd(Send node, Node left, Node right, _) {
    return buildLogicalExpression(left, node.selector, right);
  }

  @override
  ir.LogicalExpression visitLogicalOr(Send node, Node left, Node right, _) {
    return buildLogicalExpression(left, node.selector, right);
  }

  @override
  ir.Initializer visitNamedInitializingFormalDeclaration(
      VariableDefinitions node,
      Node definition,
      InitializingFormalElement parameter,
      ConstantExpression defaultValue,
      _) {
    return buildInitializingFormal(parameter);
  }

  @override
  visitNamedParameterDeclaration(VariableDefinitions node, Node definition,
      ParameterElement parameter, ConstantExpression defaultValue, _) {
    // Shouldn't be called, we handle parameters via [FunctionSignture].
    return internalError(node, "NamedParameterDeclaration");
  }

  @override
  ir.Not visitNot(Send node, Node expression, _) {
    return new ir.Not(visitForValue(expression));
  }

  @override
  ir.Not visitNotEquals(Send node, Node left, Node right, _) {
    return associateNode(
        new ir.Not(associateNode(buildBinaryOperator(left, '==', right), node)),
        node);
  }

  @override
  ir.Initializer visitOptionalInitializingFormalDeclaration(
      VariableDefinitions node,
      Node definition,
      InitializingFormalElement parameter,
      ConstantExpression defaultValue,
      int index,
      _) {
    return buildInitializingFormal(parameter);
  }

  @override
  visitOptionalParameterDeclaration(
      VariableDefinitions node,
      Node definition,
      ParameterElement parameter,
      ConstantExpression defaultValue,
      int index,
      _) {
    // Shouldn't be called, we handle parameters via [FunctionSignture].
    return internalError(node, "OptionalParameterDeclaration");
  }

  @override
  visitParameterDeclaration(VariableDefinitions node, Node definition,
      ParameterElement parameter, int index, _) {
    // Shouldn't be called, we handle parameters via [FunctionSignture].
    return internalError(node, "ParameterDeclaration");
  }

  @override
  ir.MethodInvocation handleLocalInvoke(Send node, LocalElement element,
      NodeList arguments, CallStructure callStructure, _) {
    return associateNode(
        buildCall(buildLocalGet(element), callStructure, arguments), node);
  }

  @override
  ir.Expression handleLocalSetIfNulls(
      SendSet node, LocalElement local, Node rhs, _,
      {bool isSetterValid}) {
    return new VariableAccessor(getLocal(local)).buildNullAwareAssignment(
        visitForValue(rhs),
        voidContext: isVoidContext);
  }

  @override
  IrFunction visitRedirectingFactoryConstructorDeclaration(
      FunctionExpression node,
      ConstructorElement constructor,
      NodeList parameters,
      DartType redirectionType, // TODO(ahe): Should be InterfaceType.
      ConstructorElement redirectionTarget,
      _) {
    if (!constructor.isFactoryConstructor) {
      // TODO(ahe): This seems like a bug in semantic visitor and how it
      // recovers from a bad constructor.
      return new IrFunction.constructor(buildFunctionNode(constructor, null),
          <ir.Initializer>[new ir.InvalidInitializer()]);
    }
    ir.Statement body = null;
    if (kernel.isSyntheticError(redirectionTarget)) {
      body = new ir.InvalidStatement();
    } else {
      // TODO(ahe): This should be implemented, but doesn't matter much unless
      // we support reflection. At the call-site, we bypass this factory and
      // call its effective target directly. So this factory is only necessary
      // for reflection.
      body = new ir.InvalidStatement();
    }
    IrFunction function =
        buildIrFunction(ir.ProcedureKind.Factory, constructor, null);
    function.node.body = body..parent = function.node;
    return function;
  }

  @override
  ir.InvocationExpression visitRedirectingFactoryConstructorInvoke(
      NewExpression node,
      ConstructorElement constructor,
      InterfaceType type,
      ConstructorElement effectiveTarget,
      InterfaceType effectiveTargetType,
      NodeList arguments,
      CallStructure callStructure,
      _) {
    return buildConstructorInvoke(node, isConst: false);
  }

  @override
  IrFunction visitRedirectingGenerativeConstructorDeclaration(
      FunctionExpression node,
      ConstructorElement constructor,
      NodeList parameters,
      NodeList initializers,
      _) {
    return buildGenerativeConstructor(constructor, parameters, null);
  }

  @override
  ir.InvocationExpression visitRedirectingGenerativeConstructorInvoke(
      NewExpression node,
      ConstructorElement constructor,
      InterfaceType type,
      NodeList arguments,
      CallStructure callStructure,
      _) {
    return buildConstructorInvoke(node, isConst: false);
  }

  @override
  visitStaticConstantDeclaration(VariableDefinitions node, Node definition,
      FieldElement field, ConstantExpression constant, _) {
    // Shouldn't be called, handled by fieldToIr.
    return internalError(node, "StaticConstantDeclaration");
  }

  @override
  visitStaticFieldDeclaration(VariableDefinitions node, Node definition,
      FieldElement field, Node initializer, _) {
    // Shouldn't be called, handled by fieldToIr.
    return internalError(node, "StaticFieldDeclaration");
  }

  ir.Expression buildStaticGet(Element element) {
    return buildStaticAccessor(element).buildSimpleRead();
  }

  @override
  ir.Expression handleStaticFieldGet(Send node, FieldElement field, _) {
    return buildStaticGet(field);
  }

  @override
  ir.MethodInvocation handleStaticFieldInvoke(Send node, FieldElement field,
      NodeList arguments, CallStructure callStructure, _) {
    return associateNode(
        buildCall(buildStaticGet(field), callStructure, arguments), node);
  }

  @override
  ir.Expression handleStaticFieldSet(
      SendSet node, FieldElement field, Node rhs, _) {
    return buildStaticFieldSet(field, rhs);
  }

  @override
  ir.Expression handleStaticSetIfNulls(
      SendSet node,
      Element getter,
      CompoundGetter getterKind,
      Element setter,
      CompoundSetter setterKind,
      Node rhs,
      _) {
    if (setterKind == CompoundSetter.INVALID) {
      setter = null;
    }
    return buildStaticAccessor(getter, setter).buildNullAwareAssignment(
        visitForValue(rhs),
        voidContext: isVoidContext);
  }

  ir.VariableDeclaration getLocal(LocalElement local) {
    return locals.putIfAbsent(local, () {
      // Currently, initializing formals are not final.
      bool isFinal = local.isFinal && !local.isInitializingFormal;
      return associateElement(
          new ir.VariableDeclaration(local.name,
              initializer: null,
              type: typeToIrHack(local.type),
              isFinal: isFinal,
              isConst: local.isConst),
          local);
    });
  }

  ir.FunctionNode buildFunctionNode(FunctionElement function, Node bodyNode) {
    List<ir.TypeParameter> typeParameters =
        kernel.typeParametersNotImplemented();
    List<ir.VariableDeclaration> positionalParameters =
        <ir.VariableDeclaration>[];
    List<ir.VariableDeclaration> namedParameters = <ir.VariableDeclaration>[];
    int requiredParameterCount = 0;
    ir.DartType returnType = const ir.DynamicType();
    if (function.hasFunctionSignature) {
      FunctionSignature signature = function.functionSignature;
      requiredParameterCount = signature.requiredParameterCount;
      signature.forEachParameter((ParameterElement parameter) {
        ir.VariableDeclaration variable = getLocal(parameter);
        if (parameter.isNamed) {
          namedParameters.add(variable);
        } else {
          positionalParameters.add(variable);
        }
      });
      signature.forEachParameter((ParameterElement parameter) {
        if (!parameter.isOptional) return;
        ir.Expression initializer = visitForValue(parameter.initializer);
        ir.VariableDeclaration variable = getLocal(parameter);
        if (initializer != null) {
          variable.initializer = initializer;
          initializer.parent = variable;
        }
      });
      if (function.isGenerativeConstructor) {
        returnType = const ir.VoidType();
      } else {
        returnType = typeToIrHack(signature.type.returnType);
      }
      if (function.isFactoryConstructor) {
        InterfaceType type = function.enclosingClass.thisType;
        if (type.isGeneric) {
          typeParameters = new List<ir.TypeParameter>();
          for (DartType parameter in type.typeArguments) {
            typeParameters.add(kernel.typeVariableToIr(parameter.element));
          }
        }
      }
    }
    ir.AsyncMarker asyncMarker = ir.AsyncMarker.Sync;
    if (!kernel.isSyntheticError(function)) {
      switch (function.asyncMarker) {
        case AsyncMarker.SYNC:
          asyncMarker = ir.AsyncMarker.Sync;
          break;

        case AsyncMarker.SYNC_STAR:
          asyncMarker = ir.AsyncMarker.SyncStar;
          break;

        case AsyncMarker.ASYNC:
          asyncMarker = ir.AsyncMarker.Async;
          break;

        case AsyncMarker.ASYNC_STAR:
          asyncMarker = ir.AsyncMarker.AsyncStar;
          break;

        default:
          internalError(
              function, "Unknown async maker: ${function.asyncMarker}");
          break;
      }
    }
    ir.Statement body;
    if (function.isExternal) {
      // [body] must be `null`.
    } else if (function.isConstructor) {
      // TODO(johnniwinther): Clean this up pending kernel issue #28.
      ConstructorElement constructor = function;
      if (constructor.isDefaultConstructor) {
        body = new ir.EmptyStatement();
      } else if (bodyNode != null && bodyNode.asEmptyStatement() == null) {
        body = buildStatementInBlock(bodyNode);
      }
    } else if (bodyNode != null) {
      body = buildStatementInBlock(bodyNode);
    }
    return associateElement(
        new ir.FunctionNode(body,
            asyncMarker: asyncMarker,
            returnType: returnType,
            typeParameters: typeParameters,
            positionalParameters: positionalParameters,
            namedParameters: namedParameters,
            requiredParameterCount: requiredParameterCount),
        function);
  }

  @override
  IrFunction visitStaticFunctionDeclaration(FunctionExpression node,
      MethodElement function, NodeList parameters, Node body, _) {
    return buildIrFunction(ir.ProcedureKind.Method, function, body);
  }

  ir.ProcedureKind computeInstanceMethodKind(MethodElement method) {
    assert(method.isFunction);
    return method.isOperator
        ? ir.ProcedureKind.Operator
        : ir.ProcedureKind.Method;
  }

  @override
  IrFunction visitInstanceMethodDeclaration(FunctionExpression node,
      MethodElement method, NodeList parameters, Node body, _) {
    return buildIrFunction(
        computeInstanceMethodKind(currentElement), currentElement, body);
  }

  @override
  IrFunction visitAbstractMethodDeclaration(
      FunctionExpression node, MethodElement method, NodeList parameters, _) {
    return buildIrFunction(
        computeInstanceMethodKind(currentElement), currentElement, null);
  }

  @override
  ir.Expression handleStaticFunctionGet(Send node, MethodElement function, _) {
    return buildStaticGet(function);
  }

  @override
  ir.StaticInvocation handleStaticFunctionIncompatibleInvoke(
      Send node,
      MethodElement function,
      NodeList arguments,
      CallStructure callStructure,
      _) {
    return buildStaticInvoke(function, arguments, isConst: false);
  }

  ir.StaticInvocation buildStaticInvoke(
      FunctionElement function, NodeList arguments,
      {bool isConst}) {
    ir.Arguments argumentsNode = buildArguments(arguments);
    return new ir.StaticInvocation(kernel.functionToIr(function), argumentsNode,
        isConst: isConst);
  }

  @override
  ir.StaticInvocation handleStaticFunctionInvoke(
      Send node,
      MethodElement function,
      NodeList arguments,
      CallStructure callStructure,
      _) {
    return buildStaticInvoke(function, arguments, isConst: false);
  }

  @override
  ir.Expression handleStaticFunctionSet(
      Send node, MethodElement function, Node rhs, _) {
    return buildStaticAccessor(function)
        .buildAssignment(visitForValue(rhs), voidContext: isVoidContext);
  }

  @override
  IrFunction visitStaticGetterDeclaration(
      FunctionExpression node, MethodElement getter, Node body, _) {
    return buildIrFunction(ir.ProcedureKind.Getter, getter, body);
  }

  @override
  ir.Expression handleStaticGetterGet(Send node, FunctionElement getter, _) {
    if (getter.isDeferredLoaderGetter) {
      // TODO(ahe): Support deferred load.
      return new ir.InvalidExpression();
    }
    return buildStaticGet(getter);
  }

  @override
  ir.Expression handleStaticGetterInvoke(Send node, FunctionElement getter,
      NodeList arguments, CallStructure callStructure, _) {
    if (getter.isDeferredLoaderGetter) {
      // TODO(ahe): Support deferred load.
      return new ir.InvalidExpression();
    }
    return buildCall(buildStaticGet(getter), callStructure, arguments);
  }

  @override
  ir.Expression handleStaticGetterSet(
      SendSet node, FunctionElement getter, Node rhs, _) {
    return buildStaticAccessor(getter)
        .buildAssignment(visitForValue(rhs), voidContext: isVoidContext);
  }

  @override
  IrFunction visitStaticSetterDeclaration(FunctionExpression node,
      MethodElement setter, NodeList parameters, Node body, _) {
    return buildIrFunction(ir.ProcedureKind.Setter, setter, body);
  }

  @override
  ir.Expression handleStaticSetterGet(Send node, FunctionElement setter, _) {
    return buildStaticAccessor(null, setter).buildSimpleRead();
  }

  @override
  ir.MethodInvocation handleStaticSetterInvoke(
      Send node,
      FunctionElement setter,
      NodeList arguments,
      CallStructure callStructure,
      _) {
    return buildCall(buildStaticAccessor(null, setter).buildSimpleRead(),
        callStructure, arguments);
  }

  @override
  ir.Expression handleStaticSetterSet(
      SendSet node, FunctionElement setter, Node rhs, _) {
    return buildStaticAccessor(null, setter)
        .buildAssignment(visitForValue(rhs), voidContext: isVoidContext);
  }

  @override
  ir.InvocationExpression visitStringFromEnvironmentConstructorInvoke(
      NewExpression node, StringFromEnvironmentConstantExpression constant, _) {
    return buildConstructorInvoke(node, isConst: true);
  }

  @override
  ir.SuperMethodInvocation visitSuperBinary(Send node, FunctionElement function,
      BinaryOperator operator, Node argument, _) {
    transformerFlags |= TransformerFlag.superCalls;
    return new ir.SuperMethodInvocation(
        kernel.irName(operator.selectorName, currentElement),
        new ir.Arguments(<ir.Expression>[visitForValue(argument)]),
        kernel.functionToIr(function));
  }

  @override
  ir.Expression visitSuperCompoundIndexSet(
      SendSet node,
      MethodElement getter,
      MethodElement setter,
      Node index,
      AssignmentOperator operator,
      Node rhs,
      _) {
    return buildSuperIndexAccessor(index, getter, setter)
        .buildCompoundAssignment(
            kernel.irName(operator.selectorName, currentElement),
            visitForValue(rhs),
            voidContext: isVoidContext);
  }

  @override
  ir.Initializer visitSuperConstructorInvoke(
      Send node,
      ConstructorElement superConstructor,
      InterfaceType type,
      NodeList arguments,
      CallStructure callStructure,
      _) {
    if (kernel.isSyntheticError(superConstructor)) {
      // TODO(ahe): Semantic visitor shouldn't call in this case.
      return new ir.InvalidInitializer();
    }
    return new ir.SuperInitializer(
        kernel.functionToIr(superConstructor), buildArguments(arguments));
  }

  ir.SuperMethodInvocation buildSuperEquals(
      FunctionElement function, Node argument) {
    transformerFlags |= TransformerFlag.superCalls;
    return new ir.SuperMethodInvocation(
        kernel.irName(function.name, function),
        new ir.Arguments(<ir.Expression>[visitForValue(argument)],
            types: null, named: null),
        kernel.functionToIr(function));
  }

  @override
  ir.SuperMethodInvocation visitSuperEquals(
      Send node, FunctionElement function, Node argument, _) {
    return buildSuperEquals(function, argument);
  }

  @override
  ir.Expression handleSuperCompounds(
      SendSet node,
      Element getter,
      CompoundGetter getterKind,
      Element setter,
      CompoundSetter setterKind,
      CompoundRhs rhs,
      _) {
    if (setterKind == CompoundSetter.INVALID) {
      setter = null;
    }
    return buildCompound(buildSuperPropertyAccessor(getter, setter), rhs);
  }

  @override
  ir.Expression handleStaticCompounds(
      SendSet node,
      Element getter,
      CompoundGetter getterKind,
      Element setter,
      CompoundSetter setterKind,
      CompoundRhs rhs,
      _) {
    if (setterKind == CompoundSetter.INVALID) {
      setter = null;
    }
    return buildCompound(buildStaticAccessor(getter, setter), rhs);
  }

  @override
  ir.Expression handleTypeLiteralConstantCompounds(
      SendSet node, ConstantExpression constant, CompoundRhs rhs, _) {
    return buildCompound(new ReadOnlyAccessor(buildTypeLiteral(constant)), rhs);
  }

  ir.TypeLiteral buildTypeVariable(TypeVariableElement element) {
    return new ir.TypeLiteral(kernel.typeToIr(element.type));
  }

  @override
  ir.Expression handleTypeVariableTypeLiteralCompounds(
      SendSet node, TypeVariableElement element, CompoundRhs rhs, _) {
    return buildCompound(new ReadOnlyAccessor(buildTypeVariable(element)), rhs);
  }

  @override
  ir.SuperPropertyGet visitSuperFieldGet(Send node, FieldElement field, _) {
    return buildSuperPropertyAccessor(field).buildSimpleRead();
  }

  @override
  ir.MethodInvocation visitSuperFieldInvoke(Send node, FieldElement field,
      NodeList arguments, CallStructure callStructure, _) {
    return buildCall(buildSuperPropertyAccessor(field).buildSimpleRead(),
        callStructure, arguments);
  }

  @override
  ir.Expression visitSuperFieldSet(
      SendSet node, FieldElement field, Node rhs, _) {
    return buildSuperPropertyAccessor(field)
        .buildAssignment(visitForValue(rhs), voidContext: isVoidContext);
  }

  Accessor buildSuperPropertyAccessor(Element getter, [Element setter]) {
    transformerFlags |= TransformerFlag.superCalls;
    if (setter == null &&
        getter.isField &&
        !getter.isFinal &&
        !getter.isConst) {
      setter = getter;
    }
    Element element = getter ?? setter;
    return new SuperPropertyAccessor(
        kernel.irName(element.name, element),
        (getter == null) ? null : kernel.elementToIr(getter),
        (setter == null) ? null : kernel.elementToIr(setter));
  }

  Accessor buildSuperIndexAccessor(Expression index, Element getter,
      [Element setter]) {
    if (setter == null &&
        getter.isField &&
        !getter.isFinal &&
        !getter.isConst) {
      setter = getter;
    }
    return new SuperIndexAccessor(
        visitForValue(index),
        (getter == null) ? null : kernel.elementToIr(getter),
        (setter == null) ? null : kernel.elementToIr(setter));
  }

  @override
  ir.SuperPropertyGet visitSuperGetterGet(
      Send node, FunctionElement getter, _) {
    return buildSuperPropertyAccessor(getter).buildSimpleRead();
  }

  @override
  ir.MethodInvocation visitSuperGetterInvoke(Send node, FunctionElement getter,
      NodeList arguments, CallStructure callStructure, _) {
    return buildCall(buildSuperPropertyAccessor(getter).buildSimpleRead(),
        callStructure, arguments);
  }

  @override
  ir.Expression visitSuperGetterSet(
      SendSet node, FunctionElement getter, Node rhs, _) {
    return buildSuperPropertyAccessor(getter)
        .buildAssignment(visitForValue(rhs), voidContext: isVoidContext);
  }

  @override
  ir.Expression handleSuperSetIfNulls(
      SendSet node,
      Element getter,
      CompoundGetter getterKind,
      Element setter,
      CompoundSetter setterKind,
      Node rhs,
      _) {
    if (setterKind == CompoundSetter.INVALID) {
      setter = null;
    }
    return buildSuperPropertyAccessor(getter, setter).buildNullAwareAssignment(
        visitForValue(rhs),
        voidContext: isVoidContext);
  }

  @override
  ir.SuperMethodInvocation visitSuperIndex(
      Send node, FunctionElement function, Node index, _) {
    return buildSuperIndexAccessor(index, function).buildSimpleRead();
  }

  @override
  ir.Expression visitSuperIndexPostfix(Send node, MethodElement indexFunction,
      MethodElement indexSetFunction, Node index, IncDecOperator operator, _) {
    Accessor accessor =
        buildSuperIndexAccessor(index, indexFunction, indexSetFunction);
    return buildIndexPostfix(accessor, operator);
  }

  @override
  ir.Expression visitSuperIndexPrefix(Send node, MethodElement indexFunction,
      MethodElement indexSetFunction, Node index, IncDecOperator operator, _) {
    Accessor accessor =
        buildSuperIndexAccessor(index, indexFunction, indexSetFunction);
    return buildIndexPrefix(accessor, operator);
  }

  @override
  ir.Expression visitSuperIndexSet(
      SendSet node, FunctionElement function, Node index, Node rhs, _) {
    return buildSuperIndexAccessor(index, null, function)
        .buildAssignment(visitForValue(rhs), voidContext: isVoidContext);
  }

  @override
  ir.Expression visitSuperMethodGet(Send node, MethodElement method, _) {
    return buildSuperPropertyAccessor(method).buildSimpleRead();
  }

  ir.SuperMethodInvocation buildSuperMethodInvoke(
      MethodElement method, NodeList arguments) {
    transformerFlags |= TransformerFlag.superCalls;
    return new ir.SuperMethodInvocation(kernel.irName(method.name, method),
        buildArguments(arguments), kernel.functionToIr(method));
  }

  @override
  ir.SuperMethodInvocation visitSuperMethodIncompatibleInvoke(
      Send node,
      MethodElement method,
      NodeList arguments,
      CallStructure callStructure,
      _) {
    return buildSuperMethodInvoke(method, arguments);
  }

  @override
  ir.SuperMethodInvocation visitSuperMethodInvoke(
      Send node,
      MethodElement method,
      NodeList arguments,
      CallStructure callStructure,
      _) {
    return associateNode(buildSuperMethodInvoke(method, arguments), node);
  }

  @override
  ir.Expression visitSuperMethodSet(
      Send node, MethodElement method, Node rhs, _) {
    return buildSuperPropertyAccessor(method)
        .buildAssignment(visitForValue(rhs), voidContext: isVoidContext);
  }

  @override
  ir.Not visitSuperNotEquals(
      Send node, FunctionElement function, Node argument, _) {
    return new ir.Not(buildSuperEquals(function, argument));
  }

  @override
  ir.Expression visitSuperSetterGet(Send node, FunctionElement setter, _) {
    return buildSuperPropertyAccessor(null, setter).buildSimpleRead();
  }

  @override
  ir.MethodInvocation visitSuperSetterInvoke(Send node, FunctionElement setter,
      NodeList arguments, CallStructure callStructure, _) {
    return buildCall(buildSuperPropertyAccessor(null, setter).buildSimpleRead(),
        callStructure, arguments);
  }

  @override
  ir.Expression visitSuperSetterSet(
      SendSet node, FunctionElement setter, Node rhs, _) {
    return buildSuperPropertyAccessor(null, setter)
        .buildAssignment(visitForValue(rhs), voidContext: isVoidContext);
  }

  @override
  ir.SuperMethodInvocation visitSuperUnary(
      Send node, UnaryOperator operator, FunctionElement function, _) {
    transformerFlags |= TransformerFlag.superCalls;
    return new ir.SuperMethodInvocation(kernel.irName(function.name, function),
        new ir.Arguments.empty(), kernel.functionToIr(function));
  }

  @override
  ir.Initializer visitThisConstructorInvoke(
      Send node,
      ConstructorElement thisConstructor,
      NodeList arguments,
      CallStructure callStructure,
      _) {
    if (kernel.isSyntheticError(thisConstructor)) {
      return new ir.InvalidInitializer();
    } else {
      return new ir.RedirectingInitializer(
          kernel.functionToIr(thisConstructor), buildArguments(arguments));
    }
  }

  @override
  ir.ThisExpression visitThisGet(Identifier node, _) {
    return new ir.ThisExpression();
  }

  @override
  ir.MethodInvocation visitThisInvoke(
      Send node, NodeList arguments, CallStructure callStructure, _) {
    return buildCall(new ir.ThisExpression(), callStructure, arguments);
  }

  Accessor buildThisPropertyAccessor(Name name) {
    return new ThisPropertyAccessor(nameToIrName(name), null, null);
  }

  @override
  ir.Expression visitThisPropertyGet(Send node, Name name, _) {
    return associateNode(
        buildThisPropertyAccessor(name).buildSimpleRead(), node);
  }

  @override
  ir.MethodInvocation visitThisPropertyInvoke(
      Send node, NodeList arguments, Selector selector, _) {
    return associateNode(
        buildInvokeSelector(
            new ir.ThisExpression(), selector, buildArguments(arguments)),
        node);
  }

  @override
  ir.Expression visitThisPropertySet(SendSet node, Name name, Node rhs, _) {
    return buildThisPropertyAccessor(name)
        .buildAssignment(visitForValue(rhs), voidContext: isVoidContext);
  }

  @override
  ir.Expression visitTopLevelConstantDeclaration(VariableDefinitions node,
      Node definition, FieldElement field, ConstantExpression constant, _) {
    // Shouldn't be called, handled by fieldToIr.
    return internalError(node, "TopLevelFieldDeclaration");
  }

  @override
  ir.Expression visitTopLevelFieldDeclaration(VariableDefinitions node,
      Node definition, FieldElement field, Node initializer, _) {
    // Shouldn't be called, handled by fieldToIr.
    return internalError(node, "TopLevelFieldDeclaration");
  }

  @override
  IrFunction visitTopLevelFunctionDeclaration(FunctionExpression node,
      MethodElement function, NodeList parameters, Node body, _) {
    return buildIrFunction(ir.ProcedureKind.Method, function, body);
  }

  ir.Arguments buildArguments(NodeList arguments) {
    List<ir.Expression> positional = <ir.Expression>[];
    List<ir.NamedExpression> named = <ir.NamedExpression>[];
    for (Expression expression in arguments.nodes) {
      ir.TreeNode argument = visitForValue(expression);
      if (argument is ir.NamedExpression) {
        named.add(argument);
      } else {
        positional.add(argument);
      }
    }
    return new ir.Arguments(positional, named: named, types: null);
  }

  @override
  IrFunction visitTopLevelGetterDeclaration(
      FunctionExpression node, MethodElement getter, Node body, _) {
    return buildIrFunction(ir.ProcedureKind.Getter, getter, body);
  }

  @override
  IrFunction visitTopLevelSetterDeclaration(FunctionExpression node,
      MethodElement setter, NodeList parameters, Node body, _) {
    return buildIrFunction(ir.ProcedureKind.Setter, setter, body);
  }

  @override
  ir.TypeLiteral visitTypeVariableTypeLiteralGet(
      Send node, TypeVariableElement element, _) {
    return buildTypeVariable(element);
  }

  @override
  ir.MethodInvocation visitTypeVariableTypeLiteralInvoke(
      Send node,
      TypeVariableElement element,
      NodeList arguments,
      CallStructure callStructure,
      _) {
    return buildCall(buildTypeVariable(element), callStructure, arguments);
  }

  @override
  ir.Expression visitTypeVariableTypeLiteralSet(
      SendSet node, TypeVariableElement element, Node rhs, _) {
    return new ReadOnlyAccessor(buildTypeVariable(element))
        .buildAssignment(visitForValue(rhs), voidContext: isVoidContext);
  }

  @override
  ir.Expression visitTypeVariableTypeLiteralSetIfNull(
      Send node, TypeVariableElement element, Node rhs, _) {
    return new ReadOnlyAccessor(buildTypeVariable(element))
        .buildNullAwareAssignment(visitForValue(rhs),
            voidContext: isVoidContext);
  }

  @override
  ir.TypeLiteral visitTypedefTypeLiteralGet(
      Send node, ConstantExpression constant, _) {
    return buildTypeLiteral(constant);
  }

  @override
  ir.MethodInvocation visitTypedefTypeLiteralInvoke(
      Send node,
      ConstantExpression constant,
      NodeList arguments,
      CallStructure callStructure,
      _) {
    return buildCall(buildTypeLiteral(constant), callStructure, arguments);
  }

  @override
  ir.Expression visitTypedefTypeLiteralSet(
      SendSet node, ConstantExpression constant, Node rhs, _) {
    return buildTypeLiteralSet(constant, rhs);
  }

  @override
  ir.Expression handleTypeLiteralConstantSetIfNulls(
      SendSet node, ConstantExpression constant, Node rhs, _) {
    // Degenerate case: ignores [rhs] as a type literal is never null.
    return buildTypeLiteral(constant);
  }

  @override
  ir.MethodInvocation visitUnary(
      Send node, UnaryOperator operator, Node expression, _) {
    return associateNode(
        new ir.MethodInvocation(
            visitForValue(expression),
            kernel.irName(operator.selectorName, currentElement),
            new ir.Arguments.empty()),
        node);
  }

  @override
  visitConditionalUri(ConditionalUri node) {
    // Shouldn't be called, handled by library loader.
    return internalError(node, "ConditionalUri");
  }

  @override
  visitDottedName(DottedName node) {
    // Shouldn't be called, handled by library loader.
    return internalError(node, "DottedName");
  }

  @override
  visitForIn(ForIn node) {
    // Shouldn't be called, handled by [visitAsyncForIn] or [visitSyncForIn].
    return internalError(node, "ForIn");
  }

  @override
  ir.Expression visitIndexSetIfNull(
      SendSet node, Node receiver, Node index, Node rhs, _) {
    return buildIndexAccessor(receiver, index).buildNullAwareAssignment(
        visitForValue(rhs),
        voidContext: isVoidContext);
  }

  @override
  ir.Expression visitSuperIndexSetIfNull(SendSet node, MethodElement getter,
      MethodElement setter, Node index, Node rhs, _) {
    return buildSuperIndexAccessor(index, getter, setter)
        .buildNullAwareAssignment(visitForValue(rhs),
            voidContext: isVoidContext);
  }

  @override
  ir.Node visitVariableDefinitions(VariableDefinitions definitions) {
    // TODO(ahe): This method is copied from [SemanticDeclarationResolvedMixin]
    // and modified. Perhaps we can find a way to avoid code duplication.
    List<ir.VariableDeclaration> variables = <ir.VariableDeclaration>[];
    computeVariableStructures(definitions,
        (Node node, VariableStructure structure) {
      if (structure == null) {
        return internalError(node, 'No structure for $node');
      } else {
        ir.VariableDeclaration variable =
            structure.dispatch(declVisitor, node, null);
        variables.add(variable);
        return variable;
      }
    });
    if (variables.length == 1) return variables.single;
    return new VariableDeclarations(variables);
  }

  IrFunction buildFunction() {
    return kernel.compiler.reporter.withCurrentElement(currentElement, () {
      if (kernel.isSyntheticError(currentElement)) {
        kernel.internalError(currentElement,
            "Can't build synthetic function element: $currentElement");
      } else if (currentElement.isMalformed) {
        ir.FunctionNode node = buildFunctionNode(currentElement, null);
        if (currentElement.isGenerativeConstructor) {
          return new IrFunction.constructor(
              node, <ir.Initializer>[new ir.InvalidInitializer()]);
        } else {
          node.body = new ir.InvalidStatement()..parent = node;
          return new IrFunction.procedure(ir.ProcedureKind.Method, node);
        }
      } else if (currentElement.isSynthesized) {
        if (currentElement.isGenerativeConstructor) {
          return buildGenerativeConstructor(currentElement, null, null);
        } else {
          return internalError(currentElement, "Unhandled synthetic function.");
        }
      } else {
        Node node = currentElement.node;
        if (node.isErroneous) {
          return internalError(currentElement, "Unexpected syntax error.");
        } else {
          return node.accept(this);
        }
      }
    });
  }

  ir.Expression buildInitializer() {
    return kernel.compiler.reporter.withCurrentElement(currentElement, () {
      FieldElement field = currentElement;
      return field.isMalformed
          ? new ir.InvalidExpression()
          : visitForValue(field.initializer);
    });
  }
}

class VariableDeclarations implements ir.Node {
  final List<ir.VariableDeclaration> variables;

  VariableDeclarations(this.variables);

  accept(ir.Visitor v) => throw "unsupported";

  visitChildren(ir.Visitor v) => throw "unsupported";

  String toString() => "VariableDeclarations($variables)";
}

class IrFunction implements ir.Node {
  final ir.ProcedureKind kind;
  final bool isConstructor;
  final ir.FunctionNode node;
  final List<ir.Initializer> initializers;

  IrFunction(this.kind, this.isConstructor, this.node, this.initializers);

  IrFunction.procedure(ir.ProcedureKind kind, ir.FunctionNode node)
      : this(kind, false, node, null);

  IrFunction.constructor(
      ir.FunctionNode node, List<ir.Initializer> initializers)
      : this(null, true, node, initializers);

  accept(ir.Visitor v) => throw "unsupported";

  visitChildren(ir.Visitor v) => throw "unsupported";

  String toString() {
    return "IrFunction($kind, $isConstructor, $node, $initializers)";
  }
}
