// Copyright (c) 2012, 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 'common/names.dart' show Identifiers;
import 'common/resolution.dart' show ParsingContext, Resolution;
import 'common/tasks.dart' show CompilerTask, Measurer;
import 'common.dart';
import 'compiler.dart' show Compiler;
import 'constants/expressions.dart';
import 'elements/elements.dart';
import 'elements/entities.dart';
import 'elements/entity_utils.dart' as utils;
import 'elements/modelx.dart'
    show BaseFunctionElementX, ClassElementX, ElementX;
import 'elements/resolution_types.dart';
import 'elements/types.dart';
import 'elements/visitor.dart' show ElementVisitor;
import 'js_backend/js_backend.dart' show JavaScriptBackend;
import 'js_backend/runtime_types.dart';
import 'resolution/tree_elements.dart' show TreeElements;
import 'package:front_end/src/fasta/scanner.dart' show Token;
import 'tree/tree.dart';
import 'util/util.dart';
import 'world.dart' show ClosedWorldRefiner;

// TODO(johnniwinther,efortuna): Split [ClosureConversionTask] from
// [ClosureDataLookup].
abstract class ClosureConversionTask<T> extends CompilerTask
    implements ClosureDataLookup<T> {
  ClosureConversionTask(Measurer measurer) : super(measurer);

  //void analyzeClosures();
  void convertClosures(Iterable<MemberEntity> processedEntities,
      ClosedWorldRefiner closedWorldRefiner);
}

/// Class that provides information for how closures are rewritten/represented
/// to preserve Dart semantics when compiled to JavaScript. Given a particular
/// node to look up, it returns a information about the internal representation
/// of how closure conversion is implemented. T is an ir.Node or Node.
abstract class ClosureDataLookup<T> {
  /// Look up information about the variables that have been mutated and are
  /// used inside the scope of [node].
  ScopeInfo getScopeInfo(MemberEntity member);

  /// This returns the same information as ScopeInfo, but can be called in
  /// situations when you are sure you are dealing with a closure specifically.
  // TODO(johnniwinther,efortuna): Remove the need for this. It is now only
  // used in inference.
  ClosureRepresentationInfo getClosureInfoForMember(MemberEntity member);

  ClosureRepresentationInfo getClosureInfo(T localFunction);

  /// Look up information about a loop, in case any variables it declares need
  /// to be boxed/snapshotted.
  CapturedLoopScope getCapturedLoopScope(T loopNode);

  /// Accessor to the information about scopes that closures capture. Used by
  /// the SSA builder.
  CapturedScope getCapturedScope(MemberEntity entity);
}

/// Class that represents one level of scoping information, whether this scope
/// is a closure or not. This is specifically used to store information
/// about the usage of variables in try or sync blocks, because they need to be
/// boxed.
///
/// Variables that are used in a try must be treated as boxed because the
/// control flow can be non-linear. Also parameters to a `sync*` generator must
/// be boxed, because of the way we rewrite sync* functions. See also comments
/// in [ClosureClassMap.useLocal].
class ScopeInfo {
  const ScopeInfo();

  /// Convenience reference pointer to the element representing `this`.
  /// If this scope is not in an instance member, it will be null.
  Local get thisLocal => null;

  /// Returns true if this [variable] is used inside a `try` block or a `sync*`
  /// generator (this is important to know because boxing/redirection needs to
  /// happen for those local variables).
  ///
  /// Variables that are used in a try must be treated as boxed because the
  /// control flow can be non-linear.
  ///
  /// Also parameters to a `sync*` generator must be boxed, because of the way
  /// we rewrite sync* functions. See also comments in
  /// [ClosureClassMap.useLocal].
  bool localIsUsedInTryOrSync(Local variable) => false;

  /// Loop through each variable that has been defined in this scope, modified
  /// anywhere (this scope or another scope) and used in another scope. Because
  /// it is used in another scope, these variables need to be "boxed", creating
  /// a thin wrapper around accesses to these variables so that accesses get
  /// the correct updated value. The variables in localsUsedInTryOrSync may
  /// be included in this set.
  ///
  /// In the case of loops, this is the set of iteration variables (or any
  /// variables declared in the for loop expression (`for (...here...)`) that
  /// need to be boxed to snapshot their value.
  void forEachBoxedVariable(f(Local local, FieldEntity field)) {}

  /// True if [variable] has been mutated and is also used in another scope.
  bool isBoxed(Local variable) => false;
}

/// Class representing the usage of a scope that has been captured in the
/// context of a closure.
class CapturedScope extends ScopeInfo {
  const CapturedScope();

  /// If true, this closure accesses a variable that was defined in an outside
  /// scope and this variable gets modified at some point (sometimes we say that
  /// variable has been "captured"). In this situation, access to this variable
  /// is controlled via a wrapper (box) so that updates to this variable
  /// are done in a way that is in line with Dart's closure rules.
  bool get requiresContextBox => false;

  /// Accessor to the local environment in which a particular closure node is
  /// executed. This will encapsulate the value of any variables that have been
  /// scoped into this context from outside. This is an accessor to the
  /// contextBox that [requiresContextBox] is testing is required.
  Local get context => null;
}

/// Class that describes the actual mechanics of how values of variables
/// instantiated in a loop are captured inside closures in the loop body.
/// Unlike JS, the value of a declared loop iteration variable in any closure
/// is captured/snapshotted inside at each iteration point, as if we created a
/// new local variable for that value inside the loop. For example, for the
/// following loop:
///
///     var lst = [];
///     for (int i = 0; i < 5; i++) lst.add(()=>i);
///     var result = list.map((f) => f()).toList();
///
/// `result` will be [0, 1, 2, 3, 4], whereas were this JS code
/// the result would be [5, 5, 5, 5, 5]. Because of this difference we need to
/// create a closure for these sorts of loops to capture the variable's value at
/// each iteration, by boxing the iteration variable[s].
class CapturedLoopScope extends CapturedScope {
  const CapturedLoopScope();

  /// True if this loop scope declares in the first part of the loop
  /// `for (<here>;...;...)` any variables that need to be boxed.
  bool get hasBoxedLoopVariables => false;

  /// The set of iteration variables (or variables declared in the for loop
  /// expression (`for (<here>; ... ; ...)`) that need to be boxed to snapshot
  /// their value. These variables are also included in the set of
  /// `forEachBoxedVariable` method. The distinction between these two sets is
  /// in this example:
  ///
  ///     run(f) => f();
  ///     var a;
  ///     for (int i = 0; i < 3; i++) {
  ///       var b = 3;
  ///       a = () => b = i;
  ///     }
  ///
  /// `i` would be a part of the boxedLoopVariables AND boxedVariables, but b
  /// would only be a part of boxedVariables.
  List<Local> get boxedLoopVariables => const <Local>[];
}

/// Class that describes the actual mechanics of how the converted, rewritten
/// closure is implemented. For example, for the following closure (named foo
/// for convenience):
///
///   var foo = (x) => y + x;
///
/// We would produce the following class to control access to these variables in
/// the following way (modulo naming of variables, assuming that y is modified
/// elsewhere in its scope):
///
///    class FooClosure {
///       int y;
///       FooClosure(this.y);
///       call(x) => this.y + x;
///    }
///
///  and then to execute this closure, for example:
///
///     var foo = new FooClosure(1);
///     foo.call(2);
///
/// if `y` is modified elsewhere within its scope, accesses to y anywhere in the
/// code will be controlled via a box object.
///
/// Because in these examples `y` was declared in some other, outer scope, but
/// used in the inner scope of this closure, we say `y` is a "captured"
/// variable.
/// TODO(efortuna): Make interface simpler in subsequent refactorings.
class ClosureRepresentationInfo extends ScopeInfo {
  const ClosureRepresentationInfo();

  /// The original local function before any translation.
  ///
  /// Will be null for methods.
  Local get closureEntity => null;

  /// The entity for the class used to represent the rewritten closure in the
  /// emitted JavaScript.
  ///
  /// Closures are rewritten in the form of classes that have fields to control
  /// the redirection and editing of captured variables.
  ClassEntity get closureClassEntity => null;

  /// The function that implements the [local] function as a `call` method on
  /// the closure class.
  FunctionEntity get callMethod => null;

  /// As shown in the example in the comments at the top of this class, we
  /// create fields in the closure class for each captured variable. This is an
  /// accessor to that set of fields.
  List<Local> get createdFieldEntities => const <Local>[];

  /// Convenience pointer to the field entity representation in the closure
  /// class of the element representing `this`.
  FieldEntity get thisFieldEntity => null;

  /// Loop through every variable that has been captured in this closure. This
  /// consists of all the free variables (variables captured *just* in this
  /// closure) and all variables captured in nested scopes that we may be
  /// capturing as well. These nested scopes hold "boxes" to hold the executable
  /// context for that scope.
  void forEachCapturedVariable(f(Local from, FieldEntity to)) {}

  /// Loop through each variable that has been boxed in this closure class. Only
  /// captured variables that are mutated need to be "boxed" (which basically
  /// puts a thin layer between updates and reads to this variable to ensure
  /// that every place that accesses it gets the correct updated value). This
  /// includes looping over variables that were boxed from other scopes, not
  /// strictly variables defined in this closure, unlike the behavior in
  /// the superclass ScopeInfo.
  @override
  void forEachBoxedVariable(f(Local local, FieldEntity field)) {}

  /// Loop through each free variable in this closure. Free variables are the
  /// variables that have been captured *just* in this closure, not in nested
  /// scopes.
  void forEachFreeVariable(f(Local variable, FieldEntity field)) {}

  /// Return true if [variable] has been captured and mutated (all other
  /// variables do not require boxing).
  bool isVariableBoxed(Local variable) => false;

  // TODO(efortuna): Remove this method. The old system was using
  // ClosureClassMaps for situations other than closure class maps, and that's
  // just confusing.
  bool get isClosure => false;
}

class ClosureTask extends ClosureConversionTask<Node> {
  Map<Node, CapturedScopeImpl> _closureInfoMap = <Node, CapturedScopeImpl>{};
  Map<MemberElement, ClosureClassMap> _closureMemberMappingCache =
      <MemberElement, ClosureClassMap>{};
  Map<FunctionExpression, ClosureClassMap> _closureNodeMappingCache =
      <FunctionExpression, ClosureClassMap>{};
  Compiler compiler;
  ClosureTask(Compiler compiler)
      : compiler = compiler,
        super(compiler.measurer);

  String get name => "Closure Simplifier";

  DiagnosticReporter get reporter => compiler.reporter;

  void convertClosures(Iterable<MemberEntity> processedEntities,
      ClosedWorldRefiner closedWorldRefiner) {
    createClosureClasses(closedWorldRefiner);
  }

  CapturedScope _getCapturedScope(Node node) {
    var value = _closureInfoMap[node];
    return value == null ? const CapturedScope() : value;
  }

  CapturedScope getCapturedScope(covariant MemberElement member) {
    ResolvedAst resolvedAst = member.resolvedAst;
    if (resolvedAst.kind != ResolvedAstKind.PARSED)
      return const CapturedScope();
    return _getCapturedScope(resolvedAst.node);
  }

  ScopeInfo getScopeInfo(MemberEntity member) {
    return _getMemberMapping(member);
  }

  ClosureRepresentationInfo getClosureInfoForMember(MemberEntity member) {
    return _getMemberMapping(member);
  }

  ClosureRepresentationInfo getClosureInfo(covariant FunctionExpression node) {
    return _getClosureMapping(node);
  }

  CapturedLoopScope getCapturedLoopScope(Node loopNode) {
    var value = _closureInfoMap[loopNode];
    return value == null ? const CapturedLoopScope() : value;
  }

  /// Returns the [ClosureClassMap] computed for [element].
  ClosureClassMap _getMemberMapping(MemberElement element) {
    return measure(() {
      if (element.isGenerativeConstructorBody) {
        ConstructorBodyElement constructorBody = element;
        element = constructorBody.constructor;
      }
      ClosureClassMap closureClassMap = _closureMemberMappingCache[element];
      assert(closureClassMap != null,
          failedAt(element, "No ClosureClassMap computed for ${element}."));
      return closureClassMap;
    });
  }

  /// Returns the [ClosureClassMap] computed for [node].
  ClosureClassMap _getClosureMapping(FunctionExpression node) {
    return measure(() {
      ClosureClassMap closureClassMap = _closureNodeMappingCache[node];
      assert(closureClassMap != null,
          failedAt(node, "No ClosureClassMap computed for ${node}."));
      return closureClassMap;
    });
  }

  /// Create [ClosureClassMap]s for all live members.
  void createClosureClasses(ClosedWorldRefiner closedWorldRefiner) {
    compiler.enqueuer.resolution.processedEntities
        .forEach((MemberEntity _element) {
      MemberElement element = _element;
      ResolvedAst resolvedAst = element.resolvedAst;
      if (element.isAbstract) return;
      if (element.isField &&
          !element.isInstanceMember &&
          resolvedAst.body == null) {
        // Skip top-level/static fields without an initializer.
        return;
      }
      computeClosureToClassMapping(element, closedWorldRefiner);
    });
  }

  ClosureClassMap computeClosureToClassMapping(
      MemberElement element, ClosedWorldRefiner closedWorldRefiner) {
    return measure(() {
      ClosureClassMap cached = _closureMemberMappingCache[element];
      if (cached != null) return cached;
      if (element.resolvedAst.kind != ResolvedAstKind.PARSED) {
        return _closureMemberMappingCache[element] =
            new ClosureClassMap(null, null, null, new ThisLocal(element));
      }
      return reporter.withCurrentElement(element.implementation, () {
        Node node = element.resolvedAst.node;
        TreeElements elements = element.resolvedAst.elements;

        ClosureTranslator translator = new ClosureTranslator(
            compiler,
            closedWorldRefiner,
            elements,
            _closureMemberMappingCache,
            _closureNodeMappingCache,
            _closureInfoMap);

        // The translator will store the computed closure-mappings inside the
        // cache. One for given node and one for each nested closure.
        if (node is FunctionExpression) {
          translator.translateFunction(element, node);
        } else if (element.isSynthesized) {
          reporter.internalError(
              element, "Unexpected synthesized element: $element");
          _closureMemberMappingCache[element] =
              new ClosureClassMap(null, null, null, new ThisLocal(element));
        } else {
          assert(element.isField,
              failedAt(element, "Expected $element to be a field."));
          Node initializer = element.resolvedAst.body;
          if (initializer != null) {
            // The lazy initializer of a static.
            translator.translateLazyInitializer(element, node, initializer);
          } else {
            assert(
                element.isInstanceMember,
                failedAt(
                    element,
                    "Expected $element (${element.runtimeType}) "
                    "to be an instance field."));
            _closureMemberMappingCache[element] =
                new ClosureClassMap(null, null, null, new ThisLocal(element));
          }
        }
        assert(_closureMemberMappingCache[element] != null,
            failedAt(element, "No ClosureClassMap computed for ${element}."));
        return _closureMemberMappingCache[element];
      });
    });
  }
}

// TODO(ahe): These classes continuously cause problems.  We need to
// find a more general solution.
class ClosureFieldElement extends ElementX
    implements FieldElement, PrivatelyNamedJSEntity {
  /// The [BoxLocal] or [LocalElement] being accessed through the field.
  final Local local;

  ClosureFieldElement(String name, this.local, ClosureClassElement enclosing)
      : super(name, ElementKind.FIELD, enclosing);

  /// Use [closureClass] instead.
  @deprecated
  get enclosingElement => super.enclosingElement;

  ClosureClassElement get closureClass => super.enclosingElement;

  MemberElement get memberContext => closureClass.methodElement.memberContext;

  @override
  Local get declaredEntity => local;

  @override
  Entity get rootOfScope => closureClass;

  bool get hasNode => false;

  VariableDefinitions get node {
    throw failedAt(local, 'Should not access node of ClosureFieldElement.');
  }

  bool get hasResolvedAst => hasTreeElements;

  ResolvedAst get resolvedAst {
    return new ParsedResolvedAst(this, null, null, treeElements,
        memberContext.compilationUnit.script.resourceUri);
  }

  Expression get initializer {
    throw failedAt(
        local, 'Should not access initializer of ClosureFieldElement.');
  }

  bool get isInstanceMember => true;
  bool get isAssignable => false;

  ResolutionDartType computeType(Resolution resolution) => type;

  ResolutionDartType get type {
    if (local is LocalElement) {
      LocalElement element = local;
      return element.type;
    }
    return const ResolutionDynamicType();
  }

  String toString() => "ClosureFieldElement($name)";

  accept(ElementVisitor visitor, arg) {
    return visitor.visitClosureFieldElement(this, arg);
  }

  AnalyzableElement get analyzableElement =>
      closureClass.methodElement.analyzableElement;

  @override
  List<MethodElement> get nestedClosures => const <MethodElement>[];

  @override
  bool get hasConstant => false;

  @override
  ConstantExpression get constant => null;
}

// TODO(ahe): These classes continuously cause problems.  We need to find
// a more general solution.
class ClosureClassElement extends ClassElementX {
  ResolutionInterfaceType rawType;
  ResolutionInterfaceType thisType;
  ResolutionFunctionType callType;

  /// Node that corresponds to this closure, used for source position.
  final FunctionExpression node;

  /**
   * The element for the declaration of the function expression.
   */
  final LocalFunctionElement methodElement;

  final List<ClosureFieldElement> _closureFields = <ClosureFieldElement>[];

  ClosureClassElement(
      this.node, String name, Compiler compiler, LocalFunctionElement closure)
      : this.methodElement = closure,
        super(
            name,
            closure.compilationUnit,
            // By assigning a fresh class-id we make sure that the hashcode
            // is unique, but also emit closure classes after all other
            // classes (since the emitter sorts classes by their id).
            compiler.idGenerator.getNextFreeId(),
            STATE_DONE) {
    ClassElement superclass = compiler.resolution.commonElements.closureClass;
    superclass.ensureResolved(compiler.resolution);
    supertype = superclass.thisType;
    interfaces = const Link<ResolutionDartType>();
    thisType = rawType = new ResolutionInterfaceType(this);
    allSupertypesAndSelf =
        superclass.allSupertypesAndSelf.extendClass(thisType);
    callType = methodElement.type;
  }

  Iterable<ClosureFieldElement> get closureFields => _closureFields;

  void addField(ClosureFieldElement field, DiagnosticReporter listener) {
    _closureFields.add(field);
    addMember(field, listener);
  }

  bool get hasNode => true;

  bool get isClosure => true;

  Token get position => node.getBeginToken();

  Node parseNode(ParsingContext parsing) => node;

  // A [ClosureClassElement] is nested inside a function or initializer in terms
  // of [enclosingElement], but still has to be treated as a top-level
  // element.
  bool get isTopLevel => true;

  get enclosingElement => methodElement;

  accept(ElementVisitor visitor, arg) {
    return visitor.visitClosureClassElement(this, arg);
  }
}

/// A local variable that contains the box object holding the [BoxFieldElement]
/// fields.
class BoxLocal extends Local {
  final String name;
  final MemberEntity memberContext;

  final int hashCode = _nextHashCode = (_nextHashCode + 10007).toUnsigned(30);
  static int _nextHashCode = 0;

  BoxLocal(this.name, this.memberContext);

  Entity get executableContext => memberContext;

  String toString() => 'BoxLocal($name)';
}

// TODO(ngeoffray, ahe): These classes continuously cause problems.  We need to
// find a more general solution.
class BoxFieldElement extends ElementX
    implements TypedElement, FieldElement, PrivatelyNamedJSEntity {
  final LocalVariableElement variableElement;
  final BoxLocal box;

  BoxFieldElement(String name, this.variableElement, BoxLocal box)
      : this.box = box,
        super(name, ElementKind.FIELD, box.executableContext);

  ResolutionDartType computeType(Resolution resolution) => type;

  ResolutionDartType get type => variableElement.type;

  @override
  Local get declaredEntity => variableElement;

  @override
  Entity get rootOfScope => box;

  accept(ElementVisitor visitor, arg) {
    return visitor.visitBoxFieldElement(this, arg);
  }

  @override
  bool get hasNode => false;

  @override
  bool get hasResolvedAst => false;

  @override
  Expression get initializer {
    throw new UnsupportedError("BoxFieldElement.initializer");
  }

  @override
  MemberElement get memberContext => box.memberContext;

  @override
  List<MethodElement> get nestedClosures => const <MethodElement>[];

  @override
  VariableDefinitions get node {
    throw new UnsupportedError("BoxFieldElement.node");
  }

  @override
  ResolvedAst get resolvedAst {
    throw new UnsupportedError("BoxFieldElement.resolvedAst");
  }

  @override
  bool get hasConstant => false;

  @override
  ConstantExpression get constant => null;
}

/// A local variable used encode the direct (uncaptured) references to [this].
class ThisLocal extends Local {
  final MemberEntity memberContext;

  ThisLocal(this.memberContext);

  Entity get executableContext => memberContext;

  String get name => 'this';

  ClassEntity get enclosingClass => memberContext.enclosingClass;

  bool operator ==(other) {
    return other is ThisLocal &&
        other.name == name &&
        other.memberContext == memberContext &&
        other.enclosingClass == enclosingClass;
  }

  int get hashCode => memberContext.hashCode + enclosingClass.hashCode;
}

/// Call method of a closure class.
// ignore: STRONG_MODE_INVALID_METHOD_OVERRIDE_FROM_BASE
class SynthesizedCallMethodElementX extends BaseFunctionElementX
    implements MethodElement {
  final LocalFunctionElement expression;
  final FunctionExpression node;
  final TreeElements treeElements;

  SynthesizedCallMethodElementX(String name, LocalFunctionElement other,
      ClosureClassElement enclosing, this.node, this.treeElements)
      : expression = other,
        super(name, other.kind, Modifiers.EMPTY, enclosing) {
    asyncMarker = other.asyncMarker;
    functionSignature = other.functionSignature;
    expression.callMethod = this;
  }

  /// Use [closureClass] instead.
  @deprecated
  get enclosingElement => super.enclosingElement;

  ClosureClassElement get closureClass => super.enclosingElement;

  MemberElement get memberContext {
    return closureClass.methodElement.memberContext;
  }

  bool get hasNode => node != null;

  FunctionExpression parseNode(ParsingContext parsing) => node;

  AnalyzableElement get analyzableElement =>
      closureClass.methodElement.analyzableElement;

  bool get hasResolvedAst => true;

  ResolvedAst get resolvedAst {
    return new ParsedResolvedAst(this, node, node.body, treeElements,
        expression.compilationUnit.script.resourceUri);
  }

  accept(ElementVisitor visitor, arg) {
    return visitor.visitMethodElement(this, arg);
  }
}

// The box-element for a scope, and the captured variables that need to be
// stored in the box.
class CapturedScopeImpl implements CapturedScope, CapturedLoopScope {
  final BoxLocal boxElement;
  final Map<Local, BoxFieldElement> capturedVariables;

  // If the scope is attached to a [For] contains the variables that are
  // declared in the initializer of the [For] and that need to be boxed.
  // Otherwise contains the empty List.
  List<Local> boxedLoopVariables = const <Local>[];

  CapturedScopeImpl(this.boxElement, this.capturedVariables);

  Local get context => boxElement;

  bool get requiresContextBox => capturedVariables.keys.isNotEmpty;

  void forEachBoxedVariable(f(Local local, FieldEntity field)) {
    capturedVariables.forEach(f);
  }

  bool get hasBoxedLoopVariables => boxedLoopVariables.isNotEmpty;

  bool isBoxed(Local variable) {
    return capturedVariables.containsKey(variable);
  }

  void forEachCapturedVariable(
      f(LocalVariableElement variable, BoxFieldElement boxField)) {
    capturedVariables.forEach(f);
  }

  // Should not be called. Added to make the new interface happy.
  bool localIsUsedInTryOrSync(Local variable) =>
      throw new UnsupportedError("CapturedScopeImpl.localIsUsedInTryOrSync");

  // Should not be called. Added to make the new interface happy.
  Local get thisLocal =>
      throw new UnsupportedError("CapturedScopeImpl.thisLocal");

  String toString() {
    String separator = '';
    StringBuffer sb = new StringBuffer();
    sb.write('CapturedScopeImpl(');
    if (boxElement != null) {
      sb.write('box=$boxElement');
      separator = ',';
    }
    if (boxedLoopVariables.isNotEmpty) {
      sb.write(separator);
      sb.write('boxedLoopVariables=${boxedLoopVariables}');
      separator = ',';
    }
    if (capturedVariables.isNotEmpty) {
      sb.write(separator);
      sb.write('capturedVariables=$capturedVariables');
    }
    sb.write(')');
    return sb.toString();
  }
}

class ClosureClassMap implements ClosureRepresentationInfo {
  /// The local function element before any translation.
  ///
  /// Will be null for methods.
  final LocalFunctionElement closureEntity;

  /// The synthesized closure class for [closureEntity].
  ///
  /// The closureClassEntity will be null for methods that are not local
  /// closures.
  final ClosureClassElement closureClassEntity;

  /// The synthesized `call` method of the [closureClassEntity].
  ///
  /// The callMethod will be null for methods that are not local closures.
  final MethodElement callMethod;

  /// The [thisLocal] makes handling 'this' easier by treating it like any
  /// other argument. It is only set for instance-members.
  final ThisLocal thisLocal;

  /// Maps free locals, arguments, function elements, and box locals to
  /// their locations.
  final Map<Local, FieldEntity> freeVariableMap = new Map<Local, FieldEntity>();

  /// Maps [Loop] and [FunctionExpression] nodes to their [CapturedScopeImpl] which
  /// contains their box and the captured variables that are stored in the box.
  /// This map will be empty if the method/closure of this [ClosureData] does
  /// not contain any nested closure.
  final Map<Node, CapturedScopeImpl> capturingScopes =
      new Map<Node, CapturedScopeImpl>();

  /// Set of [variable]s referenced in this scope that are used inside a
  /// `try` block or a `sync*` generator (this is important to know because
  /// boxing/redirection needs to happen for those local variables).
  ///
  /// Variables that are used in a try must be treated as boxed because the
  /// control flow can be non-linear.
  ///
  /// Also parameters to a `sync*` generator must be boxed, because of the way
  /// we rewrite sync* functions. See also comments in [useLocal].
  // TODO(johnniwinther): Add variables to this only if the variable is mutated.
  final Set<Local> localsUsedInTryOrSync = new Set<Local>();

  ClosureClassMap(this.closureEntity, this.closureClassEntity, this.callMethod,
      this.thisLocal);

  List<Local> get createdFieldEntities {
    List<Local> fields = <Local>[];
    if (closureClassEntity == null) return const <Local>[];
    closureClassEntity.closureFields.forEach((field) {
      fields.add(field.local);
    });
    return fields;
  }

  void addFreeVariable(Local element) {
    assert(freeVariableMap[element] == null);
    freeVariableMap[element] = null;
  }

  Iterable<Local> get freeVariables => freeVariableMap.keys;

  bool isFreeVariable(Local element) {
    return freeVariableMap.containsKey(element);
  }

  void forEachFreeVariable(f(Local variable, FieldEntity field)) {
    freeVariableMap.forEach(f);
  }

  FieldEntity get thisFieldEntity => freeVariableMap[thisLocal];

  bool localIsUsedInTryOrSync(Local variable) =>
      localsUsedInTryOrSync.contains(variable);

  Local getLocalVariableForClosureField(ClosureFieldElement field) {
    return field.local;
  }

  bool get isClosure => closureEntity != null;

  bool capturingScopesBox(Local variable) {
    return capturingScopes.values.any((scope) {
      return scope.boxedLoopVariables.contains(variable);
    });
  }

  bool isVariableBoxed(Local variable) {
    FieldEntity copy = freeVariableMap[variable];
    if (copy is BoxFieldElement) {
      return true;
    }
    return capturingScopesBox(variable);
  }

  void forEachCapturedVariable(void f(Local variable, FieldEntity field)) {
    freeVariableMap.forEach((variable, copy) {
      if (variable is BoxLocal) return;
      f(variable, copy);
    });
    capturingScopes.values.forEach((CapturedScopeImpl scope) {
      scope.forEachCapturedVariable(f);
    });
  }

  void forEachBoxedVariable(
      void f(LocalVariableElement local, BoxFieldElement field)) {
    freeVariableMap.forEach((variable, copy) {
      if (!isVariableBoxed(variable)) return;
      f(variable, copy);
    });
    capturingScopes.values.forEach((CapturedScopeImpl scope) {
      scope.forEachCapturedVariable(f);
    });
  }

  bool isBoxed(Local local) {
    bool variableIsBoxed = false;
    forEachBoxedVariable((LocalVariableElement element, BoxFieldElement field) {
      if (element == local) variableIsBoxed = true;
    });
    return variableIsBoxed;
  }
}

class ClosureTranslator extends Visitor {
  final Compiler compiler;
  final ClosedWorldRefiner closedWorldRefiner;
  final TreeElements elements;
  int closureFieldCounter = 0;
  int boxedFieldCounter = 0;
  bool inTryStatement = false;

  final Map<MemberElement, ClosureClassMap> memberMappingCache;
  final Map<FunctionExpression, ClosureClassMap> nodeMappingCache;
  final Map<Node, CapturedScopeImpl> closureInfo;

  // Map of captured variables. Initially they will map to `null`. If
  // a variable needs to be boxed then the scope declaring the variable
  // will update this to mapping to the capturing [BoxFieldElement].
  Map<Local, BoxFieldElement> _capturedVariableMapping =
      new Map<Local, BoxFieldElement>();

  // List of encountered closures.
  List<FunctionExpression> closures = <FunctionExpression>[];

  // The local variables that have been declared in the current scope.
  List<LocalVariableElement> scopeVariables;

  // Keep track of the mutated local variables so that we don't need to box
  // non-mutated variables.
  Set<LocalVariableElement> mutatedVariables = new Set<LocalVariableElement>();

  MemberElement outermostElement;
  ExecutableElement executableContext;

  // The closureData of the currentFunctionElement.
  ClosureClassMap closureData;

  bool insideClosure = false;

  ClosureTranslator(this.compiler, this.closedWorldRefiner, this.elements,
      this.memberMappingCache, this.nodeMappingCache, this.closureInfo);

  DiagnosticReporter get reporter => compiler.reporter;

  RuntimeTypesNeed get rtiNeed => closedWorldRefiner.closedWorld.rtiNeed;

  /// Generate a unique name for the [id]th closure field, with proposed name
  /// [name].
  ///
  /// The result is used as the name of [ClosureFieldElement]s, and must
  /// therefore be unique to avoid breaking an invariant in the element model
  /// (classes cannot declare multiple fields with the same name).
  ///
  /// Also, the names should be distinct from real field names to prevent
  /// clashes with selectors for those fields.
  ///
  /// These names are not used in generated code, just as element name.
  String getClosureVariableName(String name, int id) {
    return "_captured_${name}_$id";
  }

  /// Generate a unique name for the [id]th box field, with proposed name
  /// [name].
  ///
  /// The result is used as the name of [BoxFieldElement]s, and must
  /// therefore be unique to avoid breaking an invariant in the element model
  /// (classes cannot declare multiple fields with the same name).
  ///
  /// Also, the names should be distinct from real field names to prevent
  /// clashes with selectors for those fields.
  ///
  /// These names are not used in generated code, just as element name.
  String getBoxFieldName(int id) {
    return "_box_$id";
  }

  bool isCapturedVariable(Local element) {
    return _capturedVariableMapping.containsKey(element);
  }

  void addCapturedVariable(Node node, Local variable) {
    if (_capturedVariableMapping[variable] != null) {
      reporter.internalError(node, 'In closure analyzer.');
    }
    _capturedVariableMapping[variable] = null;
  }

  void setCapturedVariableBoxField(Local variable, BoxFieldElement boxField) {
    assert(isCapturedVariable(variable));
    _capturedVariableMapping[variable] = boxField;
  }

  BoxFieldElement getCapturedVariableBoxField(Local variable) {
    return _capturedVariableMapping[variable];
  }

  void translateFunction(Element element, FunctionExpression node) {
    // For constructors the [element] and the [:elements[node]:] may differ.
    // The [:elements[node]:] always points to the generative-constructor
    // element, whereas the [element] might be the constructor-body element.
    visit(node); // [visitFunctionExpression] will call [visitInvokable].
    // When variables need to be boxed their [_capturedVariableMapping] is
    // updated, but we delay updating the similar freeVariableMapping in the
    // closure datas that capture these variables.
    // The closures don't have their fields (in the closure class) set, either.
    updateClosures();
  }

  void translateLazyInitializer(
      FieldElement element, VariableDefinitions node, Expression initializer) {
    visitInvokable(element, node, () {
      visit(initializer);
    });
    updateClosures();
  }

  // This function runs through all of the existing closures and updates their
  // free variables to the boxed value. It also adds the field-elements to the
  // class representing the closure.
  void updateClosures() {
    for (FunctionExpression closure in closures) {
      // The captured variables that need to be stored in a field of the closure
      // class.
      Set<Local> fieldCaptures = new Set<Local>();
      Set<BoxLocal> boxes = new Set<BoxLocal>();
      ClosureClassMap data = nodeMappingCache[closure];
      // We get a copy of the keys and iterate over it, to avoid modifications
      // to the map while iterating over it.
      Iterable<Local> freeVariables = data.freeVariables.toList();
      freeVariables.forEach((Local fromElement) {
        assert(data.isFreeVariable(fromElement));
        assert(data.freeVariableMap[fromElement] == null);
        assert(isCapturedVariable(fromElement));
        BoxFieldElement boxFieldElement =
            getCapturedVariableBoxField(fromElement);
        if (boxFieldElement == null) {
          assert(fromElement is! BoxLocal);
          // The variable has not been boxed.
          fieldCaptures.add(fromElement);
        } else {
          // A boxed element.
          data.freeVariableMap[fromElement] = boxFieldElement;
          boxes.add(boxFieldElement.box);
        }
      });
      ClosureClassElement closureClass = data.closureClassEntity;
      assert(closureClass != null || (fieldCaptures.isEmpty && boxes.isEmpty));

      void addClosureField(Local local, String name) {
        ClosureFieldElement closureField =
            new ClosureFieldElement(name, local, closureClass);
        closureClass.addField(closureField, reporter);
        data.freeVariableMap[local] = closureField;
      }

      // Add the box elements first so we get the same ordering.
      // TODO(sra): What is the canonical order of multiple boxes?
      for (BoxLocal capturedElement in boxes) {
        addClosureField(capturedElement, capturedElement.name);
      }

      /// Comparator for locals. Position boxes before elements.
      int compareLocals(a, b) {
        if (a is Element && b is Element) {
          return Elements.compareByPosition(a, b);
        } else if (a is Element) {
          return 1;
        } else if (b is Element) {
          return -1;
        } else {
          return a.name.compareTo(b.name);
        }
      }

      for (Local capturedLocal in fieldCaptures.toList()..sort(compareLocals)) {
        int id = closureFieldCounter++;
        String name = getClosureVariableName(capturedLocal.name, id);
        addClosureField(capturedLocal, name);
      }
    }
  }

  void useLocal(Local variable) {
    // If the element is not declared in the current function and the element
    // is not the closure itself we need to mark the element as free variable.
    // Note that the check on [insideClosure] is not just an
    // optimization: factories have type parameters as function
    // parameters, and type parameters are declared in the class, not
    // the factory.
    bool inCurrentContext(Local variable) {
      return variable == executableContext ||
          variable.executableContext == executableContext;
    }

    if (insideClosure && !inCurrentContext(variable)) {
      closureData.addFreeVariable(variable);
    } else if (inTryStatement) {
      // Don't mark the this-element or a self-reference. This would complicate
      // things in the builder.
      // Note that nested (named) functions are immutable.
      if (variable != closureData.thisLocal &&
          variable != closureData.closureEntity &&
          variable is! TypeVariableLocal) {
        closureData.localsUsedInTryOrSync.add(variable);
      }
    } else if (variable is LocalParameterElement &&
        variable.functionDeclaration.asyncMarker == AsyncMarker.SYNC_STAR) {
      // Parameters in a sync* function are shared between each Iterator created
      // by the Iterable returned by the function, therefore they must be boxed.
      closureData.localsUsedInTryOrSync.add(variable);
    }
  }

  void useTypeVariableAsLocal(ResolutionTypeVariableType typeVariable) {
    useLocal(new TypeVariableLocal(
        typeVariable, outermostElement, outermostElement.memberContext));
  }

  void declareLocal(LocalVariableElement element) {
    scopeVariables.add(element);
  }

  void registerNeedsThis() {
    if (closureData.thisLocal != null) {
      useLocal(closureData.thisLocal);
    }
  }

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

  visitNode(Node node) => node.visitChildren(this);

  visitVariableDefinitions(VariableDefinitions node) {
    if (node.type != null) {
      visit(node.type);
    }
    for (Link<Node> link = node.definitions.nodes;
        !link.isEmpty;
        link = link.tail) {
      Node definition = link.head;
      LocalElement element = elements[definition];
      assert(element != null);
      if (!element.isInitializingFormal) {
        declareLocal(element);
      }
      // We still need to visit the right-hand sides of the init-assignments.
      // For SendSets don't visit the left again. Otherwise it would be marked
      // as mutated.
      if (definition is Send) {
        Send assignment = definition;
        Node arguments = assignment.argumentsNode;
        if (arguments != null) {
          visit(arguments);
        }
      } else {
        visit(definition);
      }
    }
  }

  visitTypeAnnotation(TypeAnnotation node) {
    MemberElement member = executableContext.memberContext;
    ResolutionDartType type = elements.getType(node);
    // TODO(karlklose,johnniwinther): if the type is null, the annotation is
    // from a parameter which has been analyzed before the method has been
    // resolved and the result has been thrown away.
    if (compiler.options.enableTypeAssertions &&
        type != null &&
        type.containsTypeVariables) {
      if (insideClosure && member.isFactoryConstructor) {
        // This is a closure in a factory constructor.  Since there is no
        // [:this:], we have to mark the type arguments as free variables to
        // capture them in the closure.
        type.forEachTypeVariable((ResolutionTypeVariableType variable) {
          useTypeVariableAsLocal(variable);
        });
      }
      if (member.isInstanceMember && !member.isField) {
        // In checked mode, using a type variable in a type annotation may lead
        // to a runtime type check that needs to access the type argument and
        // therefore the closure needs a this-element, if it is not in a field
        // initializer; field initializers are evaluated in a context where
        // the type arguments are available in locals.
        registerNeedsThis();
      }
    }
  }

  visitIdentifier(Identifier node) {
    if (node.isThis()) {
      registerNeedsThis();
    } else {
      Element element = elements[node];
      if (element != null && element.isTypeVariable) {
        if (outermostElement.isConstructor || outermostElement.isField) {
          TypeVariableElement typeVariable = element;
          useTypeVariableAsLocal(typeVariable.type);
        } else {
          registerNeedsThis();
        }
      }
    }
    node.visitChildren(this);
  }

  visitSend(Send node) {
    Element element = elements[node];
    if (Elements.isLocal(element)) {
      LocalElement localElement = element;
      useLocal(localElement);
    } else if (element != null && element.isTypeVariable) {
      TypeVariableElement variable = element;
      analyzeType(variable.type);
    } else if (node.receiver == null &&
        Elements.isInstanceSend(node, elements)) {
      registerNeedsThis();
    } else if (node.isSuperCall) {
      registerNeedsThis();
    } else if (node.isTypeTest || node.isTypeCast) {
      TypeAnnotation annotation = node.typeAnnotationFromIsCheckOrCast;
      ResolutionDartType type = elements.getType(annotation);
      analyzeType(type);
    } else if (node.isTypeTest) {
      ResolutionDartType type =
          elements.getType(node.typeAnnotationFromIsCheckOrCast);
      analyzeType(type);
    } else if (node.isTypeCast) {
      ResolutionDartType type = elements.getType(node.arguments.head);
      analyzeType(type);
    }
    node.visitChildren(this);
  }

  visitSendSet(SendSet node) {
    Element element = elements[node];
    if (Elements.isLocal(element)) {
      mutatedVariables.add(element);
      if (compiler.options.enableTypeAssertions) {
        TypedElement typedElement = element;
        analyzeTypeVariables(typedElement.type);
      }
    }
    super.visitSendSet(node);
  }

  visitNewExpression(NewExpression node) {
    ResolutionDartType type = elements.getType(node);
    analyzeType(type);
    node.visitChildren(this);
  }

  visitLiteralList(LiteralList node) {
    ResolutionDartType type = elements.getType(node);
    analyzeType(type);
    node.visitChildren(this);
  }

  visitLiteralMap(LiteralMap node) {
    ResolutionDartType type = elements.getType(node);
    analyzeType(type);
    node.visitChildren(this);
  }

  void analyzeTypeVariables(ResolutionDartType type) {
    type.forEachTypeVariable((ResolutionTypeVariableType typeVariable) {
      // Field initializers are inlined and access the type variable as
      // normal parameters.
      if (!outermostElement.isField && !outermostElement.isConstructor) {
        registerNeedsThis();
      } else {
        useTypeVariableAsLocal(typeVariable);
      }
    });
  }

  void analyzeType(ResolutionDartType type) {
    // TODO(johnniwinther): Find out why this can be null.
    if (type == null) return;
    if (outermostElement.isClassMember &&
        rtiNeed.classNeedsRti(outermostElement.enclosingClass)) {
      if (outermostElement.isConstructor || outermostElement.isField) {
        analyzeTypeVariables(type);
      } else if (outermostElement.isInstanceMember) {
        if (type.containsTypeVariables) {
          registerNeedsThis();
        }
      }
    }
  }

  // If variables that are declared in the [node] scope are captured and need
  // to be boxed create a box-element and update the [capturingScopes] in the
  // current [closureData].
  // The boxed variables are updated in the [capturedVariableMapping].
  void attachCapturedScopeVariables(Node node) {
    BoxLocal box = null;
    Map<LocalVariableElement, BoxFieldElement> scopeMapping =
        new Map<LocalVariableElement, BoxFieldElement>();

    void boxCapturedVariable(LocalVariableElement variable) {
      if (isCapturedVariable(variable)) {
        if (box == null) {
          // TODO(floitsch): construct better box names.
          String boxName = getBoxFieldName(closureFieldCounter++);
          box = new BoxLocal(boxName, executableContext.memberContext);
        }
        String elementName = variable.name;
        String boxedName =
            getClosureVariableName(elementName, boxedFieldCounter++);
        // TODO(kasperl): Should this be a FieldElement instead?
        BoxFieldElement boxed = new BoxFieldElement(boxedName, variable, box);
        scopeMapping[variable] = boxed;
        setCapturedVariableBoxField(variable, boxed);
      }
    }

    for (LocalVariableElement variable in scopeVariables) {
      // No need to box non-assignable elements.
      if (!variable.isAssignable) continue;
      if (!mutatedVariables.contains(variable)) continue;
      boxCapturedVariable(variable);
    }
    if (!scopeMapping.isEmpty) {
      CapturedScopeImpl scope = new CapturedScopeImpl(box, scopeMapping);
      closureData.capturingScopes[node] = scope;
      assert(closureInfo[node] == null);
      closureInfo[node] = scope;
    }
  }

  void inNewScope(Node node, Function action) {
    List<LocalVariableElement> oldScopeVariables = scopeVariables;
    scopeVariables = <LocalVariableElement>[];
    action();
    attachCapturedScopeVariables(node);
    mutatedVariables.removeAll(scopeVariables);
    scopeVariables = oldScopeVariables;
  }

  visitLoop(Loop node) {
    inNewScope(node, () {
      node.visitChildren(this);
    });
  }

  visitFor(For node) {
    List<LocalVariableElement> boxedLoopVariables = <LocalVariableElement>[];
    inNewScope(node, () {
      // First visit initializer and update so we can easily check if a loop
      // variable was captured in one of these subexpressions.
      if (node.initializer != null) visit(node.initializer);
      if (node.update != null) visit(node.update);

      // Loop variables that have not been captured yet can safely be flagged as
      // non-mutated, because no nested function can observe the mutation.
      if (node.initializer is VariableDefinitions) {
        VariableDefinitions definitions = node.initializer;
        definitions.definitions.nodes.forEach((Node node) {
          LocalVariableElement local = elements[node];
          if (!isCapturedVariable(local)) {
            mutatedVariables.remove(local);
          }
        });
      }

      // Visit condition and body.
      // This must happen after the above, so any loop variables mutated in the
      // condition or body are indeed flagged as mutated.
      if (node.conditionStatement != null) visit(node.conditionStatement);
      if (node.body != null) visit(node.body);

      // See if we have declared loop variables that need to be boxed.
      if (node.initializer == null) return;
      VariableDefinitions definitions =
          node.initializer.asVariableDefinitions();
      if (definitions == null) return;
      for (Link<Node> link = definitions.definitions.nodes;
          !link.isEmpty;
          link = link.tail) {
        Node definition = link.head;
        LocalVariableElement element = elements[definition];
        // Non-mutated variables should not be boxed.  The mutatedVariables set
        // gets cleared when 'inNewScope' returns, so check it here.
        if (isCapturedVariable(element) && mutatedVariables.contains(element)) {
          boxedLoopVariables.add(element);
        }
      }
    });
    CapturedScopeImpl scopeData = closureData.capturingScopes[node];
    if (scopeData == null) return;
    scopeData.boxedLoopVariables = boxedLoopVariables;
  }

  /** Returns a non-unique name for the given closure element. */
  String computeClosureName(Element element) {
    Link<String> parts = const Link<String>();
    String ownName = element.name;
    if (ownName == null || ownName == "") {
      parts = parts.prepend("closure");
    } else {
      parts = parts.prepend(ownName);
    }
    for (Element enclosingElement = element.enclosingElement;
        enclosingElement != null &&
            (enclosingElement.kind == ElementKind.GENERATIVE_CONSTRUCTOR_BODY ||
                enclosingElement.kind == ElementKind.GENERATIVE_CONSTRUCTOR ||
                enclosingElement.kind == ElementKind.CLASS ||
                enclosingElement.kind == ElementKind.FUNCTION ||
                enclosingElement.kind == ElementKind.GETTER ||
                enclosingElement.kind == ElementKind.SETTER);
        enclosingElement = enclosingElement.enclosingElement) {
      // TODO(johnniwinther): Simplify computed names.
      if (enclosingElement.isGenerativeConstructor ||
          enclosingElement.isGenerativeConstructorBody ||
          enclosingElement.isFactoryConstructor) {
        ConstructorElement constructor = enclosingElement;
        parts = parts.prepend(utils.reconstructConstructorName(constructor));
      } else {
        String surroundingName =
            Elements.operatorNameToIdentifier(enclosingElement.name);
        parts = parts.prepend(surroundingName);
      }
      // A generative constructors's parent is the class; the class name is
      // already part of the generative constructor's name.
      if (enclosingElement.kind == ElementKind.GENERATIVE_CONSTRUCTOR) break;
    }
    StringBuffer sb = new StringBuffer();
    parts.printOn(sb, '_');
    return sb.toString();
  }

  JavaScriptBackend get backend => compiler.backend;

  ClosureClassMap globalizeClosure(
      FunctionExpression node, LocalFunctionElement element) {
    String closureName = computeClosureName(element);
    ClosureClassElement globalizedElement =
        new ClosureClassElement(node, closureName, compiler, element);
    // Extend [globalizedElement] as an instantiated class in the closed world.
    closedWorldRefiner.registerClosureClass(globalizedElement);
    MethodElement callElement = new SynthesizedCallMethodElementX(
        Identifiers.call, element, globalizedElement, node, elements);
    backend.mirrorsDataBuilder.maybeMarkClosureAsNeededForReflection(
        globalizedElement, callElement, element);
    MemberElement enclosing = element.memberContext;
    enclosing.nestedClosures.add(callElement);
    globalizedElement.addMember(callElement, reporter);
    globalizedElement.computeAllClassMembers(compiler.resolution);
    // The nested function's 'this' is the same as the one for the outer
    // function. It could be [null] if we are inside a static method.
    ThisLocal thisElement = closureData.thisLocal;

    return new ClosureClassMap(
        element, globalizedElement, callElement, thisElement);
  }

  void visitInvokable(
      ExecutableElement element, Node node, void visitChildren()) {
    bool oldInsideClosure = insideClosure;
    Element oldFunctionElement = executableContext;
    ClosureClassMap oldClosureData = closureData;

    insideClosure = outermostElement != null;
    LocalFunctionElement closure;
    executableContext = element;
    bool needsRti = false;
    if (insideClosure) {
      closure = element;
      closures.add(node);
      nodeMappingCache[node] = closureData = globalizeClosure(node, closure);
      needsRti = compiler.options.enableTypeAssertions ||
          rtiNeed.localFunctionNeedsRti(closure);
    } else {
      outermostElement = element;
      ThisLocal thisElement = null;
      if (element.isInstanceMember || element.isGenerativeConstructor) {
        MemberElement member = element;
        thisElement = new ThisLocal(member);
      }
      closureData = new ClosureClassMap(null, null, null, thisElement);
      memberMappingCache[element] = closureData;
      memberMappingCache[element.declaration] = closureData;
      if (element is MethodElement) {
        needsRti = compiler.options.enableTypeAssertions ||
            rtiNeed.methodNeedsRti(element);
      }
    }
    if (closureData.callMethod != null) {
      memberMappingCache[closureData.callMethod] = closureData;
    }

    inNewScope(node, () {
      // If the method needs RTI, or checked mode is set, we need to
      // escape the potential type variables used in that closure.
      if (needsRti) {
        analyzeTypeVariables(element.type);
      }

      visitChildren();
    });

    ClosureClassMap savedClosureData = closureData;
    bool savedInsideClosure = insideClosure;

    // Restore old values.
    insideClosure = oldInsideClosure;
    closureData = oldClosureData;
    executableContext = oldFunctionElement;

    // Mark all free variables as captured and use them in the outer function.
    Iterable<Local> freeVariables = savedClosureData.freeVariables;
    assert(freeVariables.isEmpty || savedInsideClosure);
    for (Local freeVariable in freeVariables) {
      addCapturedVariable(node, freeVariable);
      useLocal(freeVariable);
    }
  }

  visitFunctionExpression(FunctionExpression node) {
    Element element = elements[node];

    if (element.isRegularParameter) {
      // TODO(ahe): This is a hack. This method should *not* call
      // visitChildren.
      return node.name.accept(this);
    }

    visitInvokable(element, node, () {
      // TODO(ahe): This is problematic. The backend should not repeat
      // the work of the resolver. It is the resolver's job to create
      // parameters, etc. Other phases should only visit statements.
      if (node.parameters != null) node.parameters.accept(this);
      if (node.initializers != null) node.initializers.accept(this);
      if (node.body != null) node.body.accept(this);
    });
  }

  visitTryStatement(TryStatement node) {
    // TODO(ngeoffray): implement finer grain state.
    bool oldInTryStatement = inTryStatement;
    inTryStatement = true;
    node.visitChildren(this);
    inTryStatement = oldInTryStatement;
  }

  visitCatchBlock(CatchBlock node) {
    if (node.type != null) {
      // The "on T" clause may contain type variables.
      analyzeType(elements.getType(node.type));
    }
    if (node.formals != null) {
      node.formals.visitChildren(this);
    }
    node.block.accept(this);
  }

  visitAsyncForIn(AsyncForIn node) {
    // An `await for` loop is enclosed in an implicit try-finally.
    bool oldInTryStatement = inTryStatement;
    inTryStatement = true;
    visitLoop(node);
    inTryStatement = oldInTryStatement;
  }
}

/// A type variable as a local variable.
class TypeVariableLocal implements Local {
  final TypeVariableType typeVariable;
  final Entity executableContext;
  final MemberEntity memberContext;

  TypeVariableLocal(
      this.typeVariable, this.executableContext, this.memberContext);

  String get name => typeVariable.element.name;

  int get hashCode => typeVariable.hashCode;

  bool operator ==(other) {
    if (other is! TypeVariableLocal) return false;
    return typeVariable == other.typeVariable;
  }

  String toString() {
    StringBuffer sb = new StringBuffer();
    sb.write('type_variable_local(');
    sb.write(typeVariable);
    sb.write(')');
    return sb.toString();
  }
}

///
/// Move the below classes to a JS model eventually.
///
abstract class JSEntity implements MemberEntity {
  Local get declaredEntity;
}

abstract class PrivatelyNamedJSEntity implements JSEntity {
  Entity get rootOfScope;
}
