// 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 file.

import 'package:kernel/ast.dart' as ir;

import '../closure.dart';
import '../common.dart';
import '../compiler.dart';
import '../constants/expressions.dart';
import '../constants/values.dart';
import '../common_elements.dart';
import '../elements/elements.dart';
import '../elements/entities.dart';
import '../elements/jumps.dart';
import '../elements/modelx.dart';
import '../elements/resolution_types.dart';
import '../elements/types.dart';
import '../js_backend/js_backend.dart';
import '../js_backend/native_data.dart';
import '../js_model/closure.dart' show KernelScopeInfo, JRecordField;
import '../kernel/element_map.dart';
import '../kernel/element_map_mixins.dart';
import '../kernel/kernel.dart';
import '../native/native.dart' as native;
import '../resolution/tree_elements.dart';
import '../ssa/type_builder.dart';
import '../tree/tree.dart' as ast;
import '../types/masks.dart';
import '../types/types.dart';
import '../universe/selector.dart';
import '../world.dart';
import 'graph_builder.dart';
import 'jump_handler.dart' show SwitchCaseJumpHandler;
import 'locals_handler.dart';
import 'types.dart';

/// A helper class that abstracts all accesses of the AST from Kernel nodes.
///
/// The goal is to remove all need for the AST from the Kernel SSA builder.
class KernelAstAdapter extends KernelToElementMapBaseMixin
    with KernelToElementMapForBuildingMixin, KernelToElementMapForImpactMixin
    implements KernelToLocalsMap {
  final Kernel kernel;
  final JavaScriptBackend _backend;
  final Map<ir.Node, ast.Node> _nodeToAst;
  final Map<ir.Node, Element> _nodeToElement;
  final Map<ir.VariableDeclaration, SyntheticLocal> _syntheticLocals =
      <ir.VariableDeclaration, SyntheticLocal>{};
  // TODO(efortuna): In an ideal world the TreeNodes should be some common
  // interface we create for both ir.Statements and ir.SwitchCase (the
  // ContinueSwitchStatement's target is a SwitchCase) rather than general
  // TreeNode. Talking to Asger about this.
  final Map<ir.TreeNode, KernelJumpTarget> _jumpTargets =
      <ir.TreeNode, KernelJumpTarget>{};
  DartTypeConverter _typeConverter;
  ResolvedAst _resolvedAst;

  /// Sometimes for resolution the resolved AST element needs to change (for
  /// example, if we're inlining, or if we're in a constructor, but then also
  /// constructing the field values). We keep track of this with a stack.
  final List<ResolvedAst> _resolvedAstStack = <ResolvedAst>[];

  final native.BehaviorBuilder nativeBehaviorBuilder;

  KernelAstAdapter(this.kernel, this._backend, this._resolvedAst,
      this._nodeToAst, this._nodeToElement)
      : nativeBehaviorBuilder = new native.ResolverBehaviorBuilder(
            _backend.compiler, _backend.frontendStrategy.nativeBasicData) {
    KernelJumpTarget.index = 0;
    // TODO(het): Maybe just use all of the kernel maps directly?
    for (FieldElement fieldElement in kernel.fields.keys) {
      _nodeToElement[kernel.fields[fieldElement]] = fieldElement;
    }
    for (FunctionElement functionElement in kernel.functions.keys) {
      _nodeToElement[kernel.functions[functionElement]] = functionElement;
    }
    for (ClassElement classElement in kernel.classes.keys) {
      _nodeToElement[kernel.classes[classElement]] = classElement;
    }
    for (LibraryElement libraryElement in kernel.libraries.keys) {
      _nodeToElement[kernel.libraries[libraryElement]] = libraryElement;
    }
    for (LocalFunctionElement localFunction in kernel.localFunctions.keys) {
      _nodeToElement[kernel.localFunctions[localFunction]] = localFunction;
    }
    for (TypeVariableElement typeVariable in kernel.typeParameters.keys) {
      _nodeToElement[kernel.typeParameters[typeVariable]] = typeVariable;
    }
    _typeConverter = new DartTypeConverter(this);
  }

  @override
  NativeBasicData get nativeBasicData =>
      _backend.frontendStrategy.nativeBasicData;

  void addProgram(ir.Program node) {
    throw new UnsupportedError('KernelAstAdapter.addProgram');
  }

  @override
  ConstantValue computeConstantValue(ConstantExpression constant,
      {bool requireConstant: true}) {
    _compiler.backend.constants.evaluate(constant);
    ConstantValue value =
        _compiler.backend.constants.getConstantValue(constant);
    if (value == null && requireConstant) {
      throw new UnsupportedError(
          'No constant value for ${constant.toStructuredText()}');
    }
    return value;
  }

  @override
  ConstantValue getFieldConstantValue(covariant FieldElement element) {
    if (element.constant != null) {
      return computeConstantValue(element.constant);
    }
    return null;
  }

  /// Called to find the corresponding Kernel element for a particular Element
  /// before traversing over it with a Kernel visitor.
  ir.Node getMemberNode(MemberElement originTarget) {
    ir.Node target;
    if (originTarget.isPatch) {
      originTarget = originTarget.origin;
    }
    if (originTarget is MethodElement) {
      if (originTarget is ConstructorBodyElement) {
        ConstructorBodyElement body = originTarget;
        originTarget = body.constructor;
      }
      target = kernel.functions[originTarget];
      // Closures require a lookup one level deeper in the closure class mapper.
      if (target == null) {
        SynthesizedCallMethodElementX originTargetFunction = originTarget;
        target = kernel.localFunctions[originTargetFunction.expression];
      }
    } else if (originTarget is FieldElement) {
      target = kernel.fields[originTarget];
    }
    assert(target != null);
    return target;
  }

  MemberDefinition getMemberDefinition(MemberElement member) {
    ir.Node node = getMemberNode(member);
    if (member is ConstructorBodyElement) {
      return new SpecialMemberDefinition(
          member, node, MemberKind.constructorBody);
    } else if (node is ir.Constructor) {
      return new SpecialMemberDefinition(member, node, MemberKind.constructor);
    } else if (node is ir.FunctionDeclaration ||
        node is ir.FunctionExpression) {
      return new SpecialMemberDefinition(member, node, MemberKind.closureCall);
    }
    return new RegularMemberDefinition(member, node);
  }

  InterfaceType getMemberThisType(MemberElement member) {
    return member.contextClass?.thisType;
  }

  ClassTypeVariableAccess getClassTypeVariableAccessForMember(
      MemberEntity member) {
    throw new UnsupportedError('KernelAstAdapter.getMemberTypeVariableAccess');
  }

  ir.Node getClassNode(ClassElement cls) {
    throw new UnsupportedError('KernelAstAdapter.getClassNode');
  }

  ClassDefinition getClassDefinition(ClassElement cls) {
    throw new UnsupportedError('KernelAstAdapter.getClassDefinition');
  }

  @override
  CommonElements get commonElements => _compiler.resolution.commonElements;

  @override
  DartTypes get types => _compiler.resolution.types;

  @override
  ElementEnvironment get elementEnvironment =>
      _compiler.resolution.elementEnvironment;

  MemberElement get currentMember => _resolvedAst.element;

  /// Push the existing resolved AST on the stack and shift the current resolved
  /// AST to the AST that this kernel node points to.
  void enterInlinedMember(MemberElement member) {
    _resolvedAstStack.add(_resolvedAst);
    _resolvedAst = member.resolvedAst;
  }

  /// Pop the resolved AST stack to reset it to the previous resolved AST node.
  void leaveInlinedMember(MemberElement member) {
    assert(_resolvedAstStack.isNotEmpty);
    assert(_resolvedAst.element == member);
    _resolvedAst = _resolvedAstStack.removeLast();
  }

  Compiler get _compiler => _backend.compiler;
  TreeElements get elements => _resolvedAst.elements;
  DiagnosticReporter get reporter => _compiler.reporter;

  // TODO(johnniwinther): Use the more precise functions below.
  Element getElement(ir.Node node) {
    Element result = _nodeToElement[node];
    assert(result != null,
        failedAt(CURRENT_ELEMENT_SPANNABLE, "No element found for $node."));
    return result;
  }

  ConstructorElement getConstructor(ir.Member node) =>
      getElement(node).declaration;

  @override
  ConstructorEntity getSuperConstructor(
      ir.Constructor constructor, ir.Member target) {
    assert(target != null);
    return getConstructor(target);
  }

  @override
  MemberEntity getSuperMember(ir.Member context, ir.Name name, ir.Member target,
      {bool setter: false}) {
    assert(target != null);
    return getMember(target);
  }

  MemberElement getMember(ir.Member node) => getElement(node).declaration;

  MethodElement getMethod(ir.Procedure node) => getElement(node).declaration;

  FieldElement getField(ir.Field node) => getElement(node).declaration;

  ClassElement getClass(ir.Class node) => getElement(node).declaration;

  LibraryElement getLibrary(ir.Library node) => getElement(node).declaration;

  LocalFunctionElement getLocalFunction(ir.TreeNode node) {
    assert(
        node is ir.FunctionDeclaration || node is ir.FunctionExpression,
        failedAt(
            CURRENT_ELEMENT_SPANNABLE, 'Invalid local function node: $node'));
    return getElement(node);
  }

  /// Returns the uri for the deferred import [node].
  String getDeferredUri(ir.LibraryDependency node) {
    PrefixElement prefixElement = getElement(node);
    return prefixElement.deferredImport.uri.toString();
  }

  ast.Node getNode(ir.Node node) {
    ast.Node result = _nodeToAst[node];
    assert(result != null,
        failedAt(CURRENT_ELEMENT_SPANNABLE, "No node found for $node"));
    return result;
  }

  ast.Node getNodeOrNull(ir.Node node) {
    return _nodeToAst[node];
  }

  void assertNodeIsSynthetic(ir.Node node) {
    assert(
        kernel.syntheticNodes.contains(node),
        failedAt(
            CURRENT_ELEMENT_SPANNABLE, "No synthetic marker found for $node"));
  }

  @override
  Local getLocalVariable(ir.VariableDeclaration variable,
      {bool isClosureCallMethod}) {
    // If this is a synthetic local, return the synthetic local
    if (variable.name == null) {
      return _syntheticLocals.putIfAbsent(
          variable, () => new SyntheticLocal("x", null, null));
    }
    return getElement(variable) as LocalElement;
  }

  @override
  ir.FunctionNode getFunctionNodeForParameter(Local parameter) {
    throw new UnsupportedError('KernelAstAdapter.getFunctionNodeForParameter');
  }

  @override
  DartType getLocalType(KernelToElementMap elementMap, Local local) {
    throw new UnsupportedError('KernelAstAdapter.getLocalType');
  }

  @override
  JumpTarget getJumpTargetForBreak(ir.BreakStatement node) {
    return getJumpTarget(node.target);
  }

  @override
  bool generateContinueForBreak(ir.BreakStatement node) => false;

  @override
  JumpTarget getJumpTargetForLabel(ir.LabeledStatement node) {
    return getJumpTarget(node);
  }

  @override
  JumpTarget getJumpTargetForSwitch(ir.SwitchStatement node) {
    return getJumpTarget(node);
  }

  @override
  JumpTarget getJumpTargetForContinueSwitch(ir.ContinueSwitchStatement node) {
    return getJumpTarget(node.target);
  }

  @override
  JumpTarget getJumpTargetForSwitchCase(ir.SwitchCase node) {
    return getJumpTarget(node, isContinueTarget: true);
  }

  @override
  JumpTarget getJumpTargetForDo(ir.DoStatement node) {
    return getJumpTarget(node);
  }

  @override
  JumpTarget getJumpTargetForFor(ir.ForStatement node) {
    return getJumpTarget(node);
  }

  @override
  JumpTarget getJumpTargetForForIn(ir.ForInStatement node) {
    return getJumpTarget(node);
  }

  @override
  JumpTarget getJumpTargetForWhile(ir.WhileStatement node) {
    return getJumpTarget(node);
  }

  KernelJumpTarget getJumpTarget(ir.TreeNode node,
      {bool isContinueTarget: false}) {
    return _jumpTargets.putIfAbsent(node, () {
      if (node is ir.LabeledStatement && _jumpTargets.containsKey(node.body)) {
        return _jumpTargets[node.body];
      }
      return new KernelJumpTarget(node, this,
          makeContinueLabel: isContinueTarget);
    });
  }

  DartType getDartType(ir.DartType type) {
    return _typeConverter.convert(type);
  }

  List<DartType> getDartTypes(List<ir.DartType> types) {
    return types.map(getDartType).toList();
  }

  /// Computes the function type corresponding the signature of [node].
  FunctionType getFunctionType(ir.FunctionNode node) {
    ResolutionDartType returnType = getDartType(node.returnType);
    List<ResolutionDartType> parameterTypes = <ResolutionDartType>[];
    List<ResolutionDartType> optionalParameterTypes = <ResolutionDartType>[];
    for (ir.VariableDeclaration variable in node.positionalParameters) {
      if (parameterTypes.length == node.requiredParameterCount) {
        optionalParameterTypes.add(getDartType(variable.type));
      } else {
        parameterTypes.add(getDartType(variable.type));
      }
    }
    List<String> namedParameters = <String>[];
    List<ResolutionDartType> namedParameterTypes = <ResolutionDartType>[];
    List<ir.VariableDeclaration> sortedNamedParameters =
        node.namedParameters.toList()..sort((a, b) => a.name.compareTo(b.name));
    for (ir.VariableDeclaration variable in sortedNamedParameters) {
      namedParameters.add(variable.name);
      namedParameterTypes.add(getDartType(variable.type));
    }
    return new ResolutionFunctionType.synthesized(returnType, parameterTypes,
        optionalParameterTypes, namedParameters, namedParameterTypes);
  }

  InterfaceType getInterfaceType(ir.InterfaceType type) => getDartType(type);

  InterfaceType getThisType(ClassElement cls) => cls.thisType;

  InterfaceType createInterfaceType(
      ir.Class cls, List<ir.DartType> typeArguments) {
    return new ResolutionInterfaceType(
        getClass(cls), getDartTypes(typeArguments));
  }

  @override
  TypedefType getTypedefType(ir.Typedef node) {
    throw new UnsupportedError('KernelAstAdapter.getTypedefType');
  }

  FunctionEntity getConstructorBody(ir.Constructor constructor) {
    AstElement element = getElement(constructor);
    MemberEntity constructorBody =
        ConstructorBodyElementX.createFromResolvedAst(element.resolvedAst);
    assert(constructorBody != null);
    return constructorBody;
  }

  @override
  Spannable getSpannable(MemberEntity member, ir.Node node) {
    return getNode(node);
  }

  @override
  CapturedLoopScope getCapturedLoopScope(
      ClosureDataLookup closureLookup, ir.TreeNode node) {
    return closureLookup.getCapturedLoopScope(getNode(node));
  }

  @override
  ClosureRepresentationInfo getClosureRepresentationInfo(
      ClosureDataLookup closureLookup, ir.TreeNode node) {
    LocalFunctionElement localFunction = getElement(node);
    return closureLookup.getClosureInfo(localFunction.node);
  }

  @override
  Map<Local, JRecordField> makeRecordContainer(
      KernelScopeInfo info, MemberEntity member, KernelToLocalsMap localsMap) {
    throw new UnsupportedError('KernelAstAdapter.makeRecordContainer');
  }
}

/// Visitor that converts kernel dart types into [ResolutionDartType].
class DartTypeConverter extends ir.DartTypeVisitor<ResolutionDartType> {
  final KernelAstAdapter astAdapter;
  bool topLevel = true;

  DartTypeConverter(this.astAdapter);

  ResolutionDartType convert(ir.DartType type) {
    topLevel = true;
    return type.accept(this);
  }

  /// Visit a inner type.
  ResolutionDartType visitType(ir.DartType type) {
    topLevel = false;
    return type.accept(this);
  }

  List<ResolutionDartType> visitTypes(List<ir.DartType> types) {
    topLevel = false;
    return new List.generate(
        types.length, (int index) => types[index].accept(this));
  }

  @override
  ResolutionDartType visitTypeParameterType(ir.TypeParameterType node) {
    if (node.parameter.parent is ir.Class) {
      ir.Class cls = node.parameter.parent;
      int index = cls.typeParameters.indexOf(node.parameter);
      ClassElement classElement = astAdapter.getElement(cls);
      return classElement.typeVariables[index];
    } else if (node.parameter.parent is ir.FunctionNode) {
      ir.FunctionNode func = node.parameter.parent;
      int index = func.typeParameters.indexOf(node.parameter);
      Element element = astAdapter.getElement(func);
      if (element.isConstructor) {
        ClassElement classElement = element.enclosingClass;
        return classElement.typeVariables[index];
      } else {
        GenericElement genericElement = element;
        return genericElement.typeVariables[index];
      }
    }
    throw new UnsupportedError('Unsupported type parameter type node $node.');
  }

  @override
  ResolutionDartType visitFunctionType(ir.FunctionType node) {
    return new ResolutionFunctionType.synthesized(
        visitType(node.returnType),
        visitTypes(node.positionalParameters
            .take(node.requiredParameterCount)
            .toList()),
        visitTypes(node.positionalParameters
            .skip(node.requiredParameterCount)
            .toList()),
        node.namedParameters.map((n) => n.name).toList(),
        node.namedParameters.map((n) => visitType(n.type)).toList());
  }

  @override
  ResolutionDartType visitInterfaceType(ir.InterfaceType node) {
    ClassElement cls = astAdapter.getClass(node.classNode);
    return new ResolutionInterfaceType(cls, visitTypes(node.typeArguments));
  }

  @override
  ResolutionDartType visitVoidType(ir.VoidType node) {
    return const ResolutionVoidType();
  }

  @override
  ResolutionDartType visitDynamicType(ir.DynamicType node) {
    return const ResolutionDynamicType();
  }

  @override
  ResolutionDartType visitInvalidType(ir.InvalidType node) {
    // Root uses such a `o is Unresolved` and `o as Unresolved` must be special
    // cased in the builder, nested invalid types are treated as `dynamic`.
    return const ResolutionDynamicType();
  }
}

class KernelJumpTarget implements JumpTargetX {
  static int index = 0;

  /// Pointer to the actual executable statements that a jump target refers to.
  /// If this jump target was not initially constructed with a LabeledStatement,
  /// this value is identical to originalStatement. This Node is actually of
  /// type either ir.Statement or ir.SwitchCase.
  ir.Node targetStatement;

  /// The original statement used to construct this jump target.
  /// If this jump target was not initially constructed with a LabeledStatement,
  /// this value is identical to targetStatement. This Node is actually of
  /// type either ir.Statement or ir.SwitchCase.
  ir.Node originalStatement;

  /// Used to provide unique numbers to labels that would otherwise be duplicate
  /// if one JumpTarget is inside another.
  int nestingLevel;

  @override
  bool isBreakTarget = false;

  @override
  bool isContinueTarget = false;

  KernelJumpTarget(this.targetStatement, KernelAstAdapter adapter,
      {bool makeContinueLabel = false}) {
    originalStatement = targetStatement;
    this.labels = <LabelDefinition<ast.Node>>[];
    if (targetStatement is ir.WhileStatement ||
        targetStatement is ir.DoStatement ||
        targetStatement is ir.ForStatement ||
        targetStatement is ir.ForInStatement) {
      // Currently these labels are set at resolution on the element itself.
      // Once that gets updated, this logic can change downstream.
      JumpTarget<ast.Node> target = adapter.elements
          .getTargetDefinition(adapter.getNode(targetStatement));
      if (target != null) {
        labels.addAll(target.labels);
        isBreakTarget = target.isBreakTarget;
        isContinueTarget = target.isContinueTarget;
      }
    } else if (targetStatement is ir.LabeledStatement) {
      targetStatement = (targetStatement as ir.LabeledStatement).body;
      labels.add(
          new LabelDefinitionX(null, 'L${index++}', this)..setBreakTarget());
      isBreakTarget = true;
    }
    var originalNode = adapter.getNode(originalStatement);
    var originalTarget = adapter.elements.getTargetDefinition(originalNode);
    if (originalTarget != null) {
      nestingLevel = originalTarget.nestingLevel;
    } else {
      nestingLevel = 0;
    }

    if (makeContinueLabel) {
      labels.add(
          new LabelDefinitionX(null, 'L${index++}', this)..setContinueTarget());
      isContinueTarget = true;
    }
  }

  @override
  LabelDefinition<ast.Node> addLabel(ast.Label label, String labelName,
      {bool isBreakTarget: false, bool isContinueTarget: false}) {
    LabelDefinitionX result = new LabelDefinitionX(label, labelName, this);
    labels.add(result);
    if (isBreakTarget) {
      result.setBreakTarget();
    }
    if (isContinueTarget) {
      result.setContinueTarget();
    }
    return result;
  }

  @override
  ExecutableElement get executableContext => null;

  @override
  MemberElement get memberContext => null;

  @override
  bool get isSwitch => targetStatement is ir.SwitchStatement;

  bool get isSwitchCase => targetStatement is ir.SwitchCase;

  @override
  bool get isTarget => isBreakTarget || isContinueTarget;

  @override
  List<LabelDefinition<ast.Node>> labels;

  @override
  String get name => 'target';

  @override
  ast.Label get statement => null;

  String toString() => 'Target:$targetStatement';
}

/// Special [JumpHandler] implementation used to handle continue statements
/// targeting switch cases.
class KernelSwitchCaseJumpHandler extends SwitchCaseJumpHandler {
  KernelSwitchCaseJumpHandler(GraphBuilder builder, JumpTarget target,
      ir.SwitchStatement switchStatement, KernelToLocalsMap localsMap)
      : super(builder, target) {
    // The switch case indices must match those computed in
    // [KernelSsaBuilder.buildSwitchCaseConstants].
    // Switch indices are 1-based so we can bypass the synthetic loop when no
    // cases match simply by branching on the index (which defaults to null).
    // TODO
    int switchIndex = 1;
    for (ir.SwitchCase switchCase in switchStatement.cases) {
      JumpTarget continueTarget =
          localsMap.getJumpTargetForSwitchCase(switchCase);
      if (continueTarget != null) {
        targetIndexMap[continueTarget] = switchIndex;
        assert(builder.jumpTargets[continueTarget] == null);
        builder.jumpTargets[continueTarget] = this;
      }
      switchIndex++;
    }
  }
}

class KernelAstTypeInferenceMap implements KernelToTypeInferenceMap {
  final KernelAstAdapter _astAdapter;

  KernelAstTypeInferenceMap(this._astAdapter);

  MemberElement get _target => _astAdapter._resolvedAst.element;

  GlobalTypeInferenceResults get _globalInferenceResults =>
      _astAdapter._compiler.globalInference.results;

  GlobalTypeInferenceElementResult _resultOf(MemberElement e) =>
      _globalInferenceResults
          .resultOfMember(e is ConstructorBodyElementX ? e.constructor : e);

  TypeMask getReturnTypeOf(FunctionEntity function) {
    return TypeMaskFactory.inferredReturnTypeForElement(
        function, _globalInferenceResults);
  }

  TypeMask typeOfInvocation(ir.MethodInvocation send, ClosedWorld closedWorld) {
    ast.Node operatorNode = _astAdapter.kernel.nodeToAstOperator[send];
    if (operatorNode != null) {
      return _resultOf(_target).typeOfOperator(operatorNode);
    }
    if (send.name.name == '[]=') {
      return closedWorld.commonMasks.dynamicType;
    }
    ast.Node node = _astAdapter.getNodeOrNull(send);
    if (node == null) {
      assert(send.name.name == '==');
      return closedWorld.commonMasks.dynamicType;
    }
    return _resultOf(_target).typeOfSend(node);
  }

  TypeMask typeOfGet(ir.PropertyGet getter) {
    return _resultOf(_target).typeOfSend(_astAdapter.getNode(getter));
  }

  TypeMask typeOfSet(ir.PropertySet setter, ClosedWorld closedWorld) {
    return closedWorld.commonMasks.dynamicType;
  }

  TypeMask typeOfListLiteral(MemberElement owner, ir.ListLiteral listLiteral,
      ClosedWorld closedWorld) {
    ast.Node node = _astAdapter.getNodeOrNull(listLiteral);
    if (node == null) {
      _astAdapter.assertNodeIsSynthetic(listLiteral);
      return closedWorld.commonMasks.growableListType;
    }
    return _resultOf(owner)
            .typeOfListLiteral(_astAdapter.getNode(listLiteral)) ??
        closedWorld.commonMasks.dynamicType;
  }

  TypeMask typeOfIterator(ir.ForInStatement forInStatement) {
    return _resultOf(_target)
        .typeOfIterator(_astAdapter.getNode(forInStatement));
  }

  TypeMask typeOfIteratorCurrent(ir.ForInStatement forInStatement) {
    return _resultOf(_target)
        .typeOfIteratorCurrent(_astAdapter.getNode(forInStatement));
  }

  TypeMask typeOfIteratorMoveNext(ir.ForInStatement forInStatement) {
    return _resultOf(_target)
        .typeOfIteratorMoveNext(_astAdapter.getNode(forInStatement));
  }

  bool isJsIndexableIterator(
      ir.ForInStatement forInStatement, ClosedWorld closedWorld) {
    TypeMask mask = typeOfIterator(forInStatement);
    return mask != null &&
        mask.satisfies(
            closedWorld.commonElements.jsIndexableClass, closedWorld) &&
        // String is indexable but not iterable.
        !mask.satisfies(closedWorld.commonElements.jsStringClass, closedWorld);
  }

  bool isFixedLength(TypeMask mask, ClosedWorld closedWorld) {
    if (mask.isContainer && (mask as ContainerTypeMask).length != null) {
      // A container on which we have inferred the length.
      return true;
    }
    // TODO(sra): Recognize any combination of fixed length indexables.
    if (mask.containsOnly(closedWorld.commonElements.jsFixedArrayClass) ||
        mask.containsOnly(
            closedWorld.commonElements.jsUnmodifiableArrayClass) ||
        mask.containsOnlyString(closedWorld) ||
        closedWorld.commonMasks.isTypedArray(mask)) {
      return true;
    }
    return false;
  }

  TypeMask inferredIndexType(ir.ForInStatement forInStatement) {
    return TypeMaskFactory.inferredTypeForSelector(new Selector.index(),
        typeOfIterator(forInStatement), _globalInferenceResults);
  }

  TypeMask getInferredTypeOf(MemberEntity member) {
    return TypeMaskFactory.inferredTypeForMember(
        member, _globalInferenceResults);
  }

  TypeMask getInferredTypeOfParameter(Local parameter) {
    return TypeMaskFactory.inferredTypeForParameter(
        parameter, _globalInferenceResults);
  }

  TypeMask selectorTypeOf(Selector selector, TypeMask mask) {
    return TypeMaskFactory.inferredTypeForSelector(
        selector, mask, _globalInferenceResults);
  }

  TypeMask typeFromNativeBehavior(
      native.NativeBehavior nativeBehavior, ClosedWorld closedWorld) {
    return TypeMaskFactory.fromNativeBehavior(nativeBehavior, closedWorld);
  }
}
