// 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 'package:kernel/ast.dart' as ir;
import 'common.dart';
import 'elements/entities.dart';
import 'js_model/closure.dart';
import 'js_model/element_map.dart';
import 'serialization/serialization.dart';

/// 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 ClosureData {
  /// Deserializes a [ClosureData] object from [source].
  factory ClosureData.readFromDataSource(
          JsToElementMap elementMap, DataSourceReader source) =
      ClosureDataImpl.readFromDataSource;

  /// Serializes this [ClosureData] to [sink].
  void writeToDataSink(DataSinkWriter sink);

  /// Look up information about the variables that have been mutated and are
  /// used inside the scope of [node]. Assumes member is not abstract and
  /// therefore scope info exists.
  ScopeInfo getScopeInfo(MemberEntity member);

  ClosureRepresentationInfo getClosureInfo(ir.LocalFunction localFunction);

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

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

  /// If [entity] is a closure call method or closure signature method, the
  /// original enclosing member is returned. Otherwise [entity] is returned.
  ///
  /// A member and its nested closure share the underlying AST, we need to
  /// ensure that locals are shared between them. We therefore store the
  /// locals in the global locals map using the enclosing member as key.
  MemberEntity getEnclosingMember(MemberEntity entity);
}

/// Enum used for identifying [ScopeInfo] subclasses in serialization.
enum ScopeInfoKind {
  scopeInfo,
  capturedScope,
  capturedLoopScope,
  closureRepresentationInfo,
}

/// 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();

  /// Deserializes a [ScopeInfo] object from [source].
  factory ScopeInfo.readFromDataSource(DataSourceReader source) {
    ScopeInfoKind kind = source.readEnum(ScopeInfoKind.values);
    switch (kind) {
      case ScopeInfoKind.scopeInfo:
        return JsScopeInfo.readFromDataSource(source);
      case ScopeInfoKind.capturedScope:
        return JsCapturedScope.readFromDataSource(source);
      case ScopeInfoKind.capturedLoopScope:
        return JsCapturedLoopScope.readFromDataSource(source);
      case ScopeInfoKind.closureRepresentationInfo:
        return JsClosureClassInfo.readFromDataSource(source);
    }
  }

  /// Serializes this [ScopeInfo] to [sink].
  void writeToDataSink(DataSinkWriter sink) {
    throw UnsupportedError('${runtimeType}.writeToDataSink');
  }

  /// 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(KernelToLocalsMap localsMap, 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(
      KernelToLocalsMap localsMap, f(Local local, FieldEntity field)) {}

  /// True if [variable] has been mutated and is also used in another scope.
  bool isBoxedVariable(KernelToLocalsMap localsMap, 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();

  /// Deserializes a [CapturedScope] object from [source].
  factory CapturedScope.readFromDataSource(DataSourceReader source) {
    ScopeInfoKind kind = source.readEnum(ScopeInfoKind.values);
    switch (kind) {
      case ScopeInfoKind.scopeInfo:
      case ScopeInfoKind.closureRepresentationInfo:
        throw UnsupportedError('Unexpected CapturedScope kind $kind');
      case ScopeInfoKind.capturedScope:
        return JsCapturedScope.readFromDataSource(source);
      case ScopeInfoKind.capturedLoopScope:
        return JsCapturedLoopScope.readFromDataSource(source);
    }
  }

  /// 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 contextBox => 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();

  /// Deserializes a [CapturedLoopScope] object from [source].
  factory CapturedLoopScope.readFromDataSource(DataSourceReader source) {
    ScopeInfoKind kind = source.readEnum(ScopeInfoKind.values);
    switch (kind) {
      case ScopeInfoKind.scopeInfo:
      case ScopeInfoKind.closureRepresentationInfo:
      case ScopeInfoKind.capturedScope:
        throw UnsupportedError('Unexpected CapturedLoopScope kind $kind');
      case ScopeInfoKind.capturedLoopScope:
        return JsCapturedLoopScope.readFromDataSource(source);
    }
  }

  /// 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> getBoxedLoopVariables(KernelToLocalsMap localsMap) =>
      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 = 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();

  /// Deserializes a [ClosureRepresentationInfo] object from [source].
  factory ClosureRepresentationInfo.readFromDataSource(
      DataSourceReader source) {
    ScopeInfoKind kind = source.readEnum(ScopeInfoKind.values);
    switch (kind) {
      case ScopeInfoKind.scopeInfo:
      case ScopeInfoKind.capturedScope:
      case ScopeInfoKind.capturedLoopScope:
        throw UnsupportedError(
            'Unexpected ClosureRepresentationInfo kind $kind');
      case ScopeInfoKind.closureRepresentationInfo:
        return JsClosureClassInfo.readFromDataSource(source);
    }
  }

  /// The original local function before any translation.
  ///
  /// Will be null for methods.
  Local? getClosureEntity(KernelToLocalsMap localsMap) => 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;

  /// The signature method for [callMethod] if needed.
  FunctionEntity? get signatureMethod => null;

  /// List of locals that this closure class has created corresponding field
  /// entities for.
  @deprecated
  List<Local> getCreatedFieldEntities(KernelToLocalsMap localsMap) =>
      const <Local>[];

  /// 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 the [local] for which [field] was created.
  /// Returns the [local] for which [field] was created.
  Local getLocalForField(KernelToLocalsMap localsMap, FieldEntity field) {
    failedAt(field, "No local for $field.");
  }

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

  /// 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(
      KernelToLocalsMap localsMap, 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(
      KernelToLocalsMap localsMap, f(Local variable, FieldEntity field)) {}

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

/// A type variable as a local variable.
class TypeVariableLocal implements Local {
  final TypeVariableEntity typeVariable;

  TypeVariableLocal(this.typeVariable);

  @override
  String? get name => typeVariable.name;

  @override
  int get hashCode => typeVariable.hashCode;

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

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

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

  ThisLocal(this.enclosingClass);

  @override
  String get name => 'this';

  @override
  bool operator ==(other) {
    return other is ThisLocal && other.enclosingClass == enclosingClass;
  }

  @override
  int get hashCode => enclosingClass.hashCode;
}

/// A local variable that contains the box object holding the [BoxFieldElement]
/// fields.
class BoxLocal extends Local {
  final ClassEntity container;

  BoxLocal(this.container);

  @override
  String get name => container.name;

  @override
  bool operator ==(other) {
    return other is BoxLocal && other.container == container;
  }

  @override
  int get hashCode => container.hashCode;

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

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

abstract class PrivatelyNamedJSEntity implements JSEntity {
  Entity get rootOfScope;
}
