// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

library simple_types_inferrer;

import '../closure.dart' show ClosureClassMap;
import '../native_handler.dart' as native;
import '../elements/elements.dart';
import '../dart2jslib.dart';
import '../tree/tree.dart';
import '../util/util.dart' show Link;
import 'types.dart' show TypesInferrer, ConcreteType, ClassBaseType;

/**
 * A work queue that ensures there are no duplicates, and adds and
 * removes in LIFO.
 */
class WorkSet<E extends Element> {
  final List<E> queue = new List<E>();
  final Set<E> elementsInQueue = new Set<E>();
  
  void add(E element) {
    element = element.implementation;
    if (elementsInQueue.contains(element)) return;
    queue.addLast(element);
    elementsInQueue.add(element);
  }

  E remove() {
    E element = queue.removeLast();
    elementsInQueue.remove(element);
    return element;
  }

  bool get isEmpty => queue.isEmpty;
}

/**
 * Placeholder for type information of final fields of classes.
 */
class ClassInfoForFinalFields {
  /**
   * Maps a final field to a map from generative constructor to the
   * inferred type of the field in that generative constructor.
   */
  final Map<Element, Map<Element, Element>> typesOfFinalFields =
      new Map<Element, Map<Element, Element>>();

  /**
   * The number of generative constructors that need to be visited
   * before we can take any decision on the type of the fields.
   * Given that all generative constructors must be analyzed before
   * re-analyzing one, we know that once [constructorsToVisitCount]
   * reaches to 0, all generative constructors have been analyzed.
   */
  int constructorsToVisitCount;

  ClassInfoForFinalFields(this.constructorsToVisitCount);

  /**
   * Records that the generative [constructor] has inferred [type]
   * for the final [field].
   */
  void recordFinalFieldType(Element constructor, Element field, Element type) {
    Map<Element, Element> typesFor = typesOfFinalFields.putIfAbsent(
        field, () => new Map<Element, Element>());
    typesFor[constructor] = type;
  }

  /**
   * Records that [constructor] has been analyzed. If not at 0,
   * decrement [constructorsToVisitCount].
   */ 
  void doneAnalyzingGenerativeConstructor(Element constructor) {
    if (constructorsToVisitCount != 0) constructorsToVisitCount--;
  }

  /**
   * Returns whether all generative constructors of the class have
   * been analyzed.
   */
  bool get isDone => constructorsToVisitCount == 0;
}

class SimpleTypesInferrer extends TypesInferrer {
  /**
   * Maps an element to its callers.
   */
  final Map<Element, Set<Element>> callersOf =
      new Map<Element, Set<Element>>();

  /**
   * Maps an element to its return type.
   */
  final Map<Element, Element> returnTypeOf =
      new Map<Element, Element>();

  /**
   * Maps an element to the number of times this type inferrer
   * analyzed it.
   */
  final Map<Element, int> analyzeCount = new Map<Element, int>();

  /**
   * Maps a class to a [ClassInfoForFinalFields] to help collect type
   * information of final fields.
   */
  final Map<ClassElement, ClassInfoForFinalFields> classInfoForFinalFields =
      new Map<ClassElement, ClassInfoForFinalFields>();

  /**
   * The work list of the inferrer.
   */
  final WorkSet<Element> workSet = new WorkSet<Element>();

  /**
   * Heuristic for avoiding too many re-analysis of an element.
   */
  final int MAX_ANALYSIS_COUNT_PER_ELEMENT = 5;

  /**
   * Sentinal used by the inferrer to notify that it gave up finding a type
   * on a specific element.
   */
  Element giveUpType;

  final Compiler compiler;

  // Times the computation of re-analysis of methods.
  final Stopwatch recomputeWatch = new Stopwatch();
  // Number of re-analysis.
  int recompiles = 0;

  SimpleTypesInferrer(this.compiler);

  /**
   * Main entry point of the inferrer. Analyzes all elements that the
   * resolver found as reachable. Returns whether it succeeded.
   */
  bool analyzeMain(Element element) {
    // We use the given element as the sentinel. This is a temporary
    // situation as long as this inferrer is using [ClassElement] for
    // expressing types.
    giveUpType = element;
    buildWorkQueue();
    int analyzed = 0;
    compiler.progress.reset();
    do {
      if (compiler.progress.elapsedMilliseconds > 500) {
        compiler.log('Inferred $analyzed methods.');
        compiler.progress.reset();
      }
      element = workSet.remove();
      if (element.isErroneous()) continue;

      bool wasAnalyzed = analyzeCount.containsKey(element);
      if (wasAnalyzed) {
        recompiles++;
        recomputeWatch.start();
      }
      bool changed = analyze(element);
      analyzed++;
      if (wasAnalyzed) {
        recomputeWatch.stop();
      }
      if (!changed) continue;
      // If something changed during the analysis of [element],
      // put back callers of it in the work list.
      Set<Element> methodCallers = callersOf[element];
      if (methodCallers != null) {
        methodCallers.forEach(enqueueAgain);
      }
    } while (!workSet.isEmpty);
    dump();
    clear();
    return true;
  }

  /**
   * Query method after the analysis to know the type of [element].
   */
  getConcreteTypeOfElement(element) {
    return getTypeIfValuable(returnTypeOf[element]);
  }

  getTypeIfValuable(returnType) {
    if (returnType == null
        || returnType == compiler.dynamicClass
        || returnType == giveUpType) {
      return null;
    }
    return new ConcreteType.singleton(
        compiler.maxConcreteTypeSize, new ClassBaseType(returnType));
  }

  /**
   * Query method after the analysis to know the type of [node],
   * defined in the context of [owner].
   */
  getConcreteTypeOfNode(Element owner, Node node) {
    var elements = compiler.enqueuer.resolution.resolvedElements[owner];
    // TODO(ngeoffray): Not sure why the resolver would put a null
    // mapping.
    if (elements == null) return null;
    Selector selector = elements.getSelector(node);
    // TODO(ngeoffray): Should the builder call this method with a
    // SendSet?
    if (selector == null || selector.isSetter() || selector.isIndexSet()) {
      return null;
    }
    return getTypeIfValuable(returnTypeOfSelector(selector));
  }

  /**
   * Enqueues [e] in the work queue if it is valuable.
   */
  void enqueueAgain(Element e) {
    Element returnType = returnTypeOf[e];
    // If we have found a type for [e], no need to re-analyze it.
    if (returnType != compiler.dynamicClass) return;
    if (analyzeCount[e] > MAX_ANALYSIS_COUNT_PER_ELEMENT) return;
    workSet.add(e);
  }

  /**
   * Builds the initial work queue by adding all resolved elements in
   * the work queue, ordered by the number of selectors they use. This
   * order is benficial for the analysis of return types, but we may
   * have to refine it once we analyze parameter types too.
   */
  void buildWorkQueue() {
    int max = 0;
    Map<int, Set<Element>> methodSizes = new Map<int, Set<Element>>();
    compiler.enqueuer.resolution.resolvedElements.forEach(
      (Element element, TreeElementMapping mapping) {
        // TODO(ngeoffray): Not sure why the resolver would put a null
        // mapping.
        if (mapping == null) return;
        if (element.isAbstract(compiler)) return;
        int length = mapping.selectors.length;
        max = length > max ? length : max;
        Set<Element> set = methodSizes.putIfAbsent(
            length, () => new Set<Element>());
        set.add(element);
    });
    
    // This iteration assumes the [WorkSet] is LIFO.
    for (int i = max; i >= 0; i--) {
      Set<Element> set = methodSizes[i];
      if (set != null) {
        set.forEach((e) { workSet.add(e); });
      }
    }

    // Build the [classInfoForFinalFields] map by iterating over all
    // seen classes and counting the number of their generative
    // constructors.
    // We iterate over the seen classes and not the instantiated ones,
    // because we also need to analyze the final fields of super
    // classes that are not instantiated.
    compiler.enqueuer.resolution.seenClasses.forEach((ClassElement cls) {
      int constructorCount = 0;
      cls.forEachMember((_, member) {
        if (member.isGenerativeConstructor()) constructorCount++;
      });
      classInfoForFinalFields[cls.implementation] =
          new ClassInfoForFinalFields(constructorCount);
    });
  }

  dump() {
    int interestingTypes = 0;
    int giveUpTypes = 0;
    returnTypeOf.forEach((Element method, Element type) {
      if (type == giveUpType) {
        giveUpTypes++;
      } else if (type != compiler.nullClass && type != compiler.dynamicClass) {
        interestingTypes++;
      }
    });
    compiler.log('Type inferrer re-analyzed methods $recompiles times '
                 'in ${recomputeWatch.elapsedMilliseconds} ms.');
    compiler.log('Type inferrer found $interestingTypes interesting '
                 'return types and gave up on $giveUpTypes methods.');
  }

  /**
   * Clear data structures that are not used after the analysis.
   */
  void clear() {
    callersOf.clear();
    analyzeCount.clear();
    classInfoForFinalFields.clear();
  }

  bool analyze(Element element) {
    SimpleTypeInferrerVisitor visitor =
        new SimpleTypeInferrerVisitor(element, compiler, this);
    Element returnType = visitor.run();
    if (analyzeCount.containsKey(element)) {
      analyzeCount[element]++;
    } else {
      analyzeCount[element] = 1;
    }
    if (element.isGenerativeConstructor()) {
      // We always know the return type of a generative constructor.
      return false;
    } else if (element.isField()) {
      if (element.modifiers.isFinal() || element.modifiers.isConst()) {
        if (element.parseNode(compiler).asSendSet() != null) {
          // If [element] is final and has an initializer, we record
          // the inferred type.
          return recordReturnType(element, returnType);
        }
      }
      // We don't record anything for non-final fields.
      return false;
    } else {
      return recordReturnType(element, returnType);
    }
  }

  /**
   * Records [returnType] as the return type of [analyzedElement].
   * Returns whether the new type is worth recompiling the callers of
   * [analyzedElement].
   */
  bool recordReturnType(analyzedElement, returnType) {
    assert(returnType != null);
    Element existing = returnTypeOf[analyzedElement];
    Element newType = existing == compiler.dynamicClass
        ? returnType // Previous analysis did not find any type.
        : computeLUB(existing, returnType);
    returnTypeOf[analyzedElement] = newType;
    // If the return type is useful, say it has changed.
    return existing != newType
        && newType != compiler.dynamicClass
        && newType != compiler.nullClass;
  }

  /**
   * Returns the return type of [element]. Returns [:Dynamic:] if
   * [element] has not been analyzed yet.
   */
  ClassElement returnTypeOfElement(Element element) {
    element = element.implementation;
    if (element.isGenerativeConstructor()) return element.getEnclosingClass();
    Element returnType = returnTypeOf[element];
    if (returnType == null || returnType == giveUpType) {
      return compiler.dynamicClass;
    }
    assert(returnType != null);
    return returnType;
  }

  /**
   * Returns the union of the return types of all elements that match
   * the called [selector].
   */
  ClassElement returnTypeOfSelector(Selector selector) {
    ClassElement result;
    iterateOverElements(selector, (Element element) {
      assert(element.isImplementation);
      Element cls;
      if (element.isFunction() && selector.isGetter()) {
        cls = compiler.functionClass;
      } else {
        cls = returnTypeOf[element];
      }
      if (cls == null
          || cls == compiler.dynamicClass
          || cls == giveUpType
          || (cls != result && result != null)) {
        result = compiler.dynamicClass;
        return false;
      } else {
        result = cls;
        return true;
      }
    });
    if (result == null) {
      result = compiler.dynamicClass;
    }
    return result;
  }

  bool isNotClosure(Element element) {
    // If the outermost enclosing element of [element] is [element]
    // itself, we know it cannot be a closure.
    Element outermost = element.getOutermostEnclosingMemberOrTopLevel();
    return outermost.declaration == element.declaration;
  }

  /**
   * Registers that [caller] calls [callee] with the given
   * [arguments].
   */
  void registerCalledElement(Element caller,
                             Element callee,
                             ArgumentsTypes arguments) {
    assert(isNotClosure(caller));
    if (analyzeCount.containsKey(caller)) return;
    callee = callee.implementation;
    Set<Element> callers = callersOf.putIfAbsent(
        callee, () => new Set<Element>());
    callers.add(caller);
  }

  /**
   * Registers that [caller] accesses [callee] through a property
   * access.
   */
  void registerGetterOnElement(Element caller,
                               Element callee) {
    assert(isNotClosure(caller));
    if (analyzeCount.containsKey(caller)) return;
    callee = callee.implementation;
    Set<Element> callers = callersOf.putIfAbsent(
        callee, () => new Set<Element>());
    callers.add(caller);
  }

  /**
   * Registers that [caller] calls an element matching [selector]
   * with the given [arguments].
   */
  void registerCalledSelector(Element caller,
                              Selector selector,
                              ArgumentsTypes arguments) {
    assert(isNotClosure(caller));
    if (analyzeCount.containsKey(caller)) return;
    iterateOverElements(selector, (Element element) {
      assert(element.isImplementation);
      Set<Element> callers = callersOf.putIfAbsent(
          element, () => new Set<Element>());
      callers.add(caller);
      return true;
    });
  }

  /**
   * Registers that [caller] accesses an element matching [selector]
   * through a property access.
   */
  void registerGetterOnSelector(Element caller, Selector selector) {
    assert(isNotClosure(caller));
    if (analyzeCount.containsKey(caller)) return;
    iterateOverElements(selector, (Element element) {
      assert(element.isImplementation);
      Set<Element> callers = callersOf.putIfAbsent(
          element, () => new Set<Element>());
      callers.add(caller);
      return true;
    });
  }

  /**
   * Registers that [caller] closurizes [function].
   */
  void registerGetFunction(Element caller, Element function) {
    assert(isNotClosure(caller));
    assert(caller.isImplementation);
    if (analyzeCount.containsKey(caller)) return;
    // We don't register that [caller] calls [function] because we
    // don't know if the code is going to call it, and if it is, then
    // the inferrer has lost track of its identity anyway.
  }

  /**
   * Applies [f] to all elements in the universe that match
   * [selector]. If [f] returns false, aborts the iteration.
   */
  void iterateOverElements(Selector selector, bool f(Element element)) {
    Iterable<Element> elements = compiler.world.allFunctions.filter(selector);
    for (Element e in elements) {
      if (!f(e.implementation)) return;
    }
  }

  /**
   * Records in [classInfoForFinalFields] that [constructor] has
   * inferred [type] for the final [field].
   */
  void recordFinalFieldType(Element constructor, Element field, Element type) {
    // If the field is being set at its declaration site, it is not
    // being tracked in the [classInfoForFinalFields] map.
    if (constructor == field) return;
    assert(field.modifiers.isFinal() || field.modifiers.isConst());
    ClassElement cls = constructor.getEnclosingClass();
    ClassInfoForFinalFields info = classInfoForFinalFields[cls.implementation];
    info.recordFinalFieldType(constructor, field, type);
  }

  /**
   * Records that we are done analyzing [constructor]. If all
   * generative constructors of its enclosing class have already been
   * analyzed, this method updates the types of final fields.
   */
  void doneAnalyzingGenerativeConstructor(Element constructor) {
    ClassElement cls = constructor.getEnclosingClass();
    ClassInfoForFinalFields info = classInfoForFinalFields[cls.implementation];
    info.doneAnalyzingGenerativeConstructor(constructor);
    if (info.isDone) {
      updateFieldTypes(info);
    }
  }

  /**
   * Updates types of final fields listed in [info].
   */
  void updateFieldTypes(ClassInfoForFinalFields info) {
    assert(info.isDone);
    info.typesOfFinalFields.forEach((Element field,
                                     Map<Element, Element> types) {
      assert(field.modifiers.isFinal());
      Element fieldType;
      types.forEach((_, type) {
        fieldType = computeLUB(fieldType, type);
      });
      returnTypeOf[field] = fieldType;
    });
  }

  /**
   * Returns the least upper bound between [firstType] and
   * [secondType].
   */
  Element computeLUB(Element firstType, Element secondType) {
    bool isNumber(type) {
      return type == compiler.numClass
          || type == compiler.doubleClass
          || type == compiler.intClass;
    }
    assert(secondType != null);
    if (firstType == null) {
      return secondType;
    } else if (firstType == giveUpType) {
      return firstType;
    } else if (secondType == compiler.dynamicClass) {
      return secondType;
    } else if (firstType == compiler.dynamicClass) {
      return firstType;
    } else if (firstType != secondType) {
      if (isNumber(firstType) && isNumber(secondType)) {
        // The JavaScript backend knows how to deal with numbers.
        return compiler.numClass;
      }
      // TODO(ngeoffray): Actually compute the least upper bound.
      return giveUpType;
    } else {
      assert(firstType == secondType);
      return firstType;
    }
  }
}

/**
 * Placeholder for inferred arguments types on sends.
 */
class ArgumentsTypes {
  final List<Element> positional;
  final Map<Identifier, Element> named;
  ArgumentsTypes(this.positional, this.named);
  int get length => positional.length + named.length;
  toString() => "{ positional = $positional, named = $named }";
}

/**
 * Placeholder for inferred types of local variables.
 */
class LocalsHandler {
  final SimpleTypesInferrer inferrer;
  final Map<Element, Element> locals;
  final Set<Element> captured;
  final bool inTryBlock;

  LocalsHandler(this.inferrer)
      : locals = new Map<Element, Element>(),
        captured = new Set<Element>(),
        inTryBlock = false;
  LocalsHandler.from(LocalsHandler other, {bool inTryBlock: false})
      : locals = new Map<Element, Element>.from(other.locals),
        captured = new Set<Element>.from(other.captured),
        inTryBlock = other.inTryBlock || inTryBlock,
        inferrer = other.inferrer;

  Element use(Element local) {
    return locals[local];
  }

  void update(Element local, Element type) {
    assert(type != null);
    if (captured.contains(local) || inTryBlock) {
      // If a local is captured or is set in a try block, we compute the
      // LUB of its assignments. We don't know if an assignment in a try block
      // will be executed, so all assigments in a try block are
      // potential types after we have left the try block.
      type = inferrer.computeLUB(locals[local], type);
      if (type == inferrer.giveUpType) type = inferrer.compiler.dynamicClass;
    }
    locals[local] = type;
  }

  void setCaptured(Element local) {
    captured.add(local);
  }

  /**
   * Merge handlers [first] and [second] into [:this:] and returns
   * whether the merge changed one of the variables types in [first].
   */
  bool merge(LocalsHandler other) {
    bool changed = false;
    List<Element> toRemove = <Element>[];
    // Iterating over a map and just updating its entries is OK.
    locals.forEach((local, oldType) {
      Element otherType = other.locals[local];
      if (otherType == null) {
        // If [local] is not in the other map, we know it is not a
        // local we want to keep. For example, in an if/else, we don't
        // want to keep variables declared in the if or in the else
        // branch at the merge point.
        toRemove.add(local);
        return;
      }
      var type = inferrer.computeLUB(oldType, otherType);
      if (type == inferrer.giveUpType) type = inferrer.compiler.dynamicClass;
      if (type != oldType) changed = true;
      locals[local] = type;
    });

    // Remove locals that will not be used anymore.
    toRemove.forEach((Element element) {
      locals.remove(element);
    });

    // Update the locals that are captured.
    other.captured.forEach((Element element) {
      if (locals.containsKey(element)) {
        captured.add(element);
      }
    });
    return changed;
  }
}

class SimpleTypeInferrerVisitor extends ResolvedVisitor {
  final Element analyzedElement;
  final Element outermostElement;
  final SimpleTypesInferrer inferrer;
  final Compiler compiler;
  LocalsHandler locals;
  Element returnType;

  SimpleTypeInferrerVisitor.internal(TreeElements mapping,
                                     this.analyzedElement,
                                     this.outermostElement,
                                     this.inferrer,
                                     this.compiler,
                                     this.locals)
    : super(mapping);

  factory SimpleTypeInferrerVisitor(Element element,
                                    Compiler compiler,
                                    SimpleTypesInferrer inferrer,
                                    [LocalsHandler handler]) {
    Element outermostElement =
        element.getOutermostEnclosingMemberOrTopLevel().implementation;
    TreeElements elements = compiler.enqueuer.resolution.resolvedElements[
        outermostElement.declaration];
    assert(elements != null);
    assert(outermostElement != null);
    handler = handler != null ? handler : new LocalsHandler(inferrer);
    return new SimpleTypeInferrerVisitor.internal(
        elements, element, outermostElement, inferrer, compiler, handler);
  }

  Element run() {
    var node = analyzedElement.implementation.parseNode(compiler);
    if (analyzedElement.isField()) {
      returnType = visit(node);
    } else if (analyzedElement.isGenerativeConstructor()) {
      FunctionElement function = analyzedElement;
      FunctionSignature signature = function.computeSignature(compiler);
      signature.forEachParameter((element) {
        // We don't track argument types yet, so just set the fields
        // and parameters as dynamic.
        if (element.kind == ElementKind.FIELD_PARAMETER
            && element.modifiers.isFinal()) {
          inferrer.recordFinalFieldType(
              analyzedElement, element.fieldElement, compiler.dynamicClass);
        } else {
          locals.update(element, compiler.dynamicClass);
        }
      });
      visit(node.initializers);
      visit(node.body);
      inferrer.doneAnalyzingGenerativeConstructor(analyzedElement);
      returnType = analyzedElement.getEnclosingClass();
    } else if (analyzedElement.isNative()) {
      // Native methods do not have a body, and we currently just say
      // they return dynamic.
      returnType = compiler.dynamicClass;
    } else {
      FunctionElement function = analyzedElement;
      FunctionSignature signature = function.computeSignature(compiler);
      signature.forEachParameter((element) {
        // We don't track argument types yet, so just set the
        // parameters as dynamic.
        locals.update(element, compiler.dynamicClass);
      });
      visit(node.body);
      if (returnType == null) {
        // No return in the body.
        returnType = compiler.nullClass;
      }
    }
    return returnType;
  }

  recordReturnType(ClassElement cls) {
    returnType = inferrer.computeLUB(returnType, cls);
  }

  visitNode(Node node) {
    node.visitChildren(this);
    return compiler.dynamicClass;
  }

  visitNewExpression(NewExpression node) {
    return node.send.accept(this);
  }

  visit(Node node) {
    return node == null ? compiler.dynamicClass : node.accept(this);
  }

  visitFunctionExpression(FunctionExpression node) {
    // Fetch the closure data of [node] and mark all locals that are
    // captured by [node] to be captured in the locals handler.
    compiler.closureToClassMapper.computeClosureToClassMapping(
        outermostElement, outermostElement.parseNode(compiler), elements);
    ClosureClassMap nestedClosureData =
        compiler.closureToClassMapper.getMappingForNestedFunction(node);

    nestedClosureData.forEachCapturedVariable((variable) {
      locals.setCaptured(variable);
    });
    // We don't put the closure in the work queue of the
    // inferrer, because it will share information with its enclosing
    // method, like for example the types of local variables.
    LocalsHandler closureLocals = new LocalsHandler.from(locals);
    SimpleTypeInferrerVisitor visitor = new SimpleTypeInferrerVisitor(
        elements[node], compiler, inferrer, closureLocals);
    visitor.run();
    // Do not register the runtime type, because the analysis may be
    // invalidated due to updates on locals.
    // TODO(ngeoffray): Track return types of closures.
    // The closure may have updated the type of locals.
    locals.merge(closureLocals);
    return compiler.functionClass;
  }

  visitFunctionDeclaration(FunctionDeclaration node) {
    locals.update(elements[node], compiler.functionClass);
    return visit(node.function);
  }


  visitLiteralString(LiteralString node) {
    return compiler.stringClass;
  }

  visitStringInterpolation(StringInterpolation node) {
    return compiler.stringClass;
  }

  visitStringJuxtaposition(StringJuxtaposition node) {
    return compiler.stringClass;
  }

  visitLiteralBool(LiteralBool node) {
    return compiler.boolClass;
  }

  visitLiteralDouble(LiteralDouble node) {
    return compiler.doubleClass;
  }

  visitLiteralInt(LiteralInt node) {
    return compiler.intClass;
  }

  visitLiteralList(LiteralList node) {
    return compiler.listClass;
  }

  visitLiteralMap(LiteralMap node) {
    return compiler.mapClass;
  }

  visitLiteralNull(LiteralNull node) {
    return compiler.nullClass;
  }

  visitTypeReferenceSend(Send node) {
    return compiler.typeClass;
  }

  visitSendSet(SendSet node) {
    Element element = elements[node];
    if (!Elements.isUnresolved(element) && element.impliesType()) {
      node.visitChildren(this);
      return compiler.dynamicClass;
    }

    Operator op = node.assignmentOperator;
    if (node.isSuperCall) {
      // [: super.foo = 42 :] or [: super.foo++ :] or [: super.foo += 1 :].
      node.visitChildren(this);
      return compiler.dynamicClass;
    } else if (node.isIndex) {
      if (const SourceString("=") == op.source) {
        // [: foo[0] = 42 :]
        visit(node.receiver);
        Element returnType;
        for (Node argument in node.arguments) {
          returnType = argument.accept(this);
        }
        return returnType;
      } else {
        // [: foo[0] += 42 :] or [: foo[0]++ :].
        node.visitChildren(this);
        return compiler.dynamicClass;
      }
    } else if (const SourceString("=") == op.source) {
      // [: foo = 42 :] or [: foo.bar = 42 :].
      if (element == null) {
        visit(node.receiver);
      }
      Link<Node> link = node.arguments;
      assert(!link.isEmpty && link.tail.isEmpty);
      Element type = link.head.accept(this);

      if (!Elements.isUnresolved(element)) {
        if (element.isField() && element.modifiers.isFinal()) {
          inferrer.recordFinalFieldType(outermostElement, element, type);
        } else if (element.isVariable()) {
          locals.update(element, type);
        }
      }
      return type;
    } else {
      // [: foo++ :] or [: foo += 1 :].
      assert(const SourceString("++") == op.source ||
             const SourceString("--") == op.source ||
             node.assignmentOperator.source.stringValue.endsWith("="));
      node.visitChildren(this);
      return compiler.dynamicClass;
    }
  }

  visitIdentifier(Identifier node) {
    if (node.isThis() || node.isSuper()) {
      // TODO(ngeoffray): Represent subclasses.
      return compiler.dynamicClass;
    }
    return compiler.dynamicClass;
  }

  visitSuperSend(Send node) {
    Element element = elements[node];
    if (Elements.isUnresolved(element)) {
      return compiler.dynamicClass;
    }
    Selector selector = elements.getSelector(node);
    if (node.isPropertyAccess) {
      inferrer.registerGetterOnElement(outermostElement, element);
      return inferrer.returnTypeOfElement(element);
    } else if (element.isFunction()) {
      ArgumentsTypes arguments = analyzeArguments(node.arguments);
      inferrer.registerCalledElement(outermostElement, element, arguments);
      return inferrer.returnTypeOfElement(element);
    } else {
      // Closure call on a getter. We don't have function types yet,
      // so we just return [:Dynamic:].
      return compiler.dynamicClass;
    }
  }

  visitStaticSend(Send node) {
    Element element = elements[node];
    if (Elements.isUnresolved(element)) {
      return compiler.dynamicClass;
    }
    if (element.isForeign(compiler)) {
      return handleForeignSend(node);
    }
    ArgumentsTypes arguments = analyzeArguments(node.arguments);
    inferrer.registerCalledElement(outermostElement, element, arguments);
    return inferrer.returnTypeOfElement(element);
  }

  handleForeignSend(Send node) {
    node.visitChildren(this);
    Selector selector = elements.getSelector(node);
    SourceString name = selector.name;
    if (name == const SourceString('JS')) {
      native.NativeBehavior nativeBehavior =
          compiler.enqueuer.resolution.nativeEnqueuer.getNativeBehaviorOf(node);
      if (nativeBehavior == null) return compiler.dynamicClass;
      List typesReturned = nativeBehavior.typesReturned;
      if (typesReturned.isEmpty) return compiler.dynamicClass;
      ClassElement returnType;
      for (var type in typesReturned) {
        ClassElement mappedType;
        if (type == native.SpecialType.JsObject) {
          mappedType = compiler.objectClass;
        } else if (type == native.SpecialType.JsArray) {
          mappedType = compiler.listClass;
        } else {
          mappedType = type.element;
          // For primitive types, we know how to handle them here and
          // in the backend.
          if (mappedType != compiler.stringClass
              && mappedType != compiler.intClass
              && mappedType != compiler.doubleClass
              && mappedType != compiler.boolClass
              && mappedType != compiler.numClass) {
            Set<ClassElement> subtypes = compiler.world.subtypes[mappedType];
            // TODO(ngeoffray): Handle subtypes and subclasses.
            if (subtypes != null && !subtypes.isEmpty) {
              return compiler.dynamicClass;
            }
          }
        }
        if (returnType == null) {
          returnType = mappedType;
        } else {
          return compiler.dynamicClass;
        }
      }
      return returnType;
    } else if (name == const SourceString('JS_OPERATOR_IS_PREFIX')) {
      return compiler.stringClass;
    } else {
      return compiler.dynamicClass;
    }
  }

  analyzeArguments(Link<Node> arguments) {
    List<ClassElement> positional = [];
    Map<Identifier, ClassElement> named = new Map<Identifier, ClassElement>();
    for (Node argument in arguments) {
      NamedArgument namedArgument = argument.asNamedArgument();
      if (namedArgument != null) {
        named[namedArgument.name] = namedArgument.expression.accept(this);
      } else {
        positional.add(argument.accept(this));
      }
    }
    return new ArgumentsTypes(positional, named);
  }

  visitOperatorSend(Send node) {
    Operator op = node.selector;
    if (const SourceString("[]") == op.source) {
      return visitDynamicSend(node);
    } else if (const SourceString("&&") == op.source ||
               const SourceString("||") == op.source) {
      visit(node.receiver);
      LocalsHandler saved = new LocalsHandler.from(locals);
      visit(node.arguments.head);
      saved.merge(locals);
      locals = saved;
      return compiler.boolClass;
    } else if (const SourceString("!") == op.source) {
      node.visitChildren(this);
      return compiler.boolClass;
    } else if (const SourceString("is") == op.source) {
      node.visitChildren(this);
      return compiler.boolClass;
    } else if (const SourceString("as") == op.source) {
      node.visitChildren(this);
      return compiler.dynamicClass;
    } else if (node.isParameterCheck) {
      node.visitChildren(this);
      return compiler.boolClass;
    } else if (node.argumentsNode is Prefix) {
      // Unary operator.
      return visitDynamicSend(node);
    } else if (const SourceString('===') == op.source
               || const SourceString('!==') == op.source) {
      node.visitChildren(this);
      return compiler.boolClass;
    } else {
      // Binary operator.
      return visitDynamicSend(node);
    }
  }

  // Because some nodes just visit their children, we may end up
  // visiting a type annotation, that may contain a send in case of a
  // prefixed type. Therefore we explicitly visit the type annotation
  // to avoid confusing the [ResolvedVisitor].
  visitTypeAnnotation(TypeAnnotation node) {}

  visitGetterSend(Send node) {
    Element element = elements[node];
    if (Elements.isStaticOrTopLevelField(element)) {
      inferrer.registerGetterOnElement(outermostElement, element);
      return inferrer.returnTypeOfElement(element);
    } else if (Elements.isInstanceSend(node, elements)) {
      ClassElement receiverType;
      if (node.receiver == null) {
        receiverType = outermostElement.getEnclosingClass();
      } else {
        receiverType = node.receiver.accept(this);
      }
      Selector selector = elements.getSelector(node);
      inferrer.registerGetterOnSelector(outermostElement, selector);
      return inferrer.returnTypeOfSelector(selector);
    } else if (Elements.isStaticOrTopLevelFunction(element)) {
      inferrer.registerGetFunction(outermostElement, element);
      return compiler.functionClass;
    } else if (Elements.isErroneousElement(element)) {
      return compiler.dynamicClass;
    } else if (Elements.isLocal(element)) {
      assert(locals.use(element) != null);
      return locals.use(element);
    } else {
      node.visitChildren(this);
      return compiler.dynamicClass;
    }
  }

  visitClosureSend(Send node) {
    node.visitChildren(this);
    return compiler.dynamicClass;
  }

  visitDynamicSend(Send node) {
    ClassElement receiverType;
    if (node.receiver == null) {
      receiverType = outermostElement.getEnclosingClass();
    } else {
      receiverType = node.receiver.accept(this);
    }
    ArgumentsTypes arguments = analyzeArguments(node.arguments);
    Selector selector = elements.getSelector(node);
    inferrer.registerCalledSelector(outermostElement, selector, arguments);
    return inferrer.returnTypeOfSelector(selector);
  }

  visitReturn(Return node) {
    Node expression = node.expression;
    recordReturnType(expression == null
        ? compiler.nullClass
        : expression.accept(this));
  }

  visitConditional(Conditional node) {
    node.condition.accept(this);
    LocalsHandler saved = new LocalsHandler.from(locals);
    Element firstType = node.thenExpression.accept(this);
    LocalsHandler thenLocals = locals;
    locals = saved;
    Element secondType = node.elseExpression.accept(this);
    locals.merge(thenLocals);
    Element type = inferrer.computeLUB(firstType, secondType);
    if (type == inferrer.giveUpType) type = compiler.dynamicClass;
    return type;
  }

  visitVariableDefinitions(VariableDefinitions node) {
    for (Link<Node> link = node.definitions.nodes;
         !link.isEmpty;
         link = link.tail) {
      Node definition = link.head;
      if (definition is Identifier) {
        locals.update(elements[definition], compiler.nullClass);
      } else {
        assert(definition.asSendSet() != null);
        visit(definition);
      }
    }
  }

  visitIf(If node) {
    visit(node.condition);
    LocalsHandler saved = new LocalsHandler.from(locals);
    visit(node.thenPart);
    LocalsHandler thenLocals = locals;
    locals = saved;
    visit(node.elsePart);
    locals.merge(thenLocals);
    return compiler.dynamicClass;
  }

  visitWhile(While node) {
    bool changed = false;
    do {
      LocalsHandler saved = new LocalsHandler.from(locals);
      visit(node.condition);
      visit(node.body);
      changed = saved.merge(locals);
      locals = saved;
    } while (changed);

    return compiler.dynamicClass;
  }

  visitDoWhile(DoWhile node) {
    bool changed = false;
    do {
      LocalsHandler saved = new LocalsHandler.from(locals);
      visit(node.body);
      visit(node.condition);
      changed = saved.merge(locals);
      locals = saved;
    } while (changed);

    return compiler.dynamicClass;
  }

  visitFor(For node) {
    bool changed = false;
    visit(node.initializer);
    do {
      LocalsHandler saved = new LocalsHandler.from(locals);
      visit(node.condition);
      visit(node.body);
      visit(node.update);
      changed = saved.merge(locals);
      locals = saved;
    } while (changed);

    return compiler.dynamicClass;
  }

  visitForIn(ForIn node) {
    bool changed = false;
    visit(node.expression);
    Element variable;
    if (node.declaredIdentifier.asSend() != null) {
      variable = elements[node.declaredIdentifier];
    } else {
      assert(node.declaredIdentifier.asVariableDefinitions() != null);
      VariableDefinitions variableDefinitions = node.declaredIdentifier;
      variable = elements[variableDefinitions.definitions.nodes.head];
    }
    locals.update(variable, compiler.dynamicClass);
    do {
      LocalsHandler saved = new LocalsHandler.from(locals);
      visit(node.body);
      changed = saved.merge(locals);
      locals = saved;
    } while (changed);

    return compiler.dynamicClass;
  }

  visitTryStatement(TryStatement node) {
    LocalsHandler saved = locals;
    locals = new LocalsHandler.from(locals, inTryBlock: true);
    visit(node.tryBlock);
    saved.merge(locals);
    locals = saved;
    for (Node catchBlock in node.catchBlocks) {
      saved = new LocalsHandler.from(locals);
      visit(catchBlock);
      saved.merge(locals);
      locals = saved;
    }
    visit(node.finallyBlock);
  }

  internalError(String reason, {Node node}) {
    compiler.internalError(reason, node: node);
  }
}
