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

library dart2js.js_model.type_recipe;

import '../elements/entities.dart' show ClassEntity;
import '../elements/types.dart';
import '../diagnostics/invariant.dart';
import '../diagnostics/spannable.dart' show CURRENT_ELEMENT_SPANNABLE;
import '../serialization/serialization.dart';
import '../util/util.dart' show Hashing;

abstract class TypeRecipeDomain {
  /// Detect if a recipe evaluates to its input environment.
  ///
  /// Returns `true` if [recipe] evaluates in an environment with [structure] to
  /// the environment. This is typically a recipe that selects the entire input.
  bool isIdentity(TypeRecipe recipe, TypeEnvironmentStructure structure);

  /// Detect if a recipe evaluates to its input environment.
  ///
  /// Returns `true` if [recipe] evaluates in an environment with
  /// [environmentStructure] to the environment, where the environment is known
  /// to be an instance type of exactly the class [classEntity].
  ///
  /// This is a special case of [isIdentity] where we have additional
  /// information about the input environment that is not encoded in the
  /// environment structure.
  // TODO(sra): Consider extending TypeEnvironmentStructure to encode when the
  // classType is an exact type. Then the [classEntity] parameter would not be
  // needed.
  bool isReconstruction(ClassEntity classEntity,
      TypeEnvironmentStructure environmentStructure, TypeRecipe recipe);

  /// Tries to evaluate [recipe] against a fixed environment [environmentRecipe]
  /// having structure [environmentStructure].
  ///
  /// May return `null` if the evaluation is too complex.
  TypeRecipe? foldLoadEval(TypeRecipe environmentRecipe,
      TypeEnvironmentStructure environmentStructure, TypeRecipe recipe);

  /// Partial constant folding of a type expression when the environment is
  /// created by binding a ground term.
  ///
  /// An 'original' environment is extended with [bindArgument] to produce an
  /// intermediate environment with structure [environmentStructure]. [recipe]
  /// is evaluated against this intermediate environment to produce a result.
  ///
  /// Returns the structure of the 'original' environment and a recipe that
  /// evaluates against that structure to produce the same result.
  ///
  /// [bindArgument] must be a ground term, i.e. have no type variables.
  TypeRecipeAndEnvironmentStructure? foldBindLoadEval(
    TypeRecipe bindArgument,
    TypeEnvironmentStructure environmentStructure,
    TypeRecipe recipe,
  );

  /// Combines [recipe1] and [recipe2] into a single recipe that can be
  /// evaluated against [environmentStructure1]. ([recipe1] produces an
  /// intermediate type or environment value that conforms to the layout
  /// described by [environmentStructure2].)
  TypeRecipeAndEnvironmentStructure? foldEvalEval(
    TypeEnvironmentStructure environmentStructure1,
    TypeRecipe recipe1,
    TypeEnvironmentStructure environmentStructure2,
    TypeRecipe recipe2,
  );
}

/// A type recipe and the structure of the type environment against which it is
/// evaluated.
class TypeRecipeAndEnvironmentStructure {
  final TypeRecipe recipe;
  final TypeEnvironmentStructure environmentStructure;

  TypeRecipeAndEnvironmentStructure(this.recipe, this.environmentStructure);
}

/// A TypeEnvironmentStructure describes the shape or layout of a reified type
/// environment.
///
/// A type environment maps type parameter variables to type values. The type
/// variables are mostly elided in the runtime representation, replaced by
/// indexes into the reified environment.
abstract class TypeEnvironmentStructure {
  /// Structural equality on [TypeEnvironmentStructure].
  static bool same(TypeEnvironmentStructure a, TypeEnvironmentStructure b) {
    if (a is SingletonTypeEnvironmentStructure) {
      if (b is SingletonTypeEnvironmentStructure) {
        return a.variable == b.variable;
      }
      return false;
    }
    return _sameFullStructure(
        a as FullTypeEnvironmentStructure, b as FullTypeEnvironmentStructure);
  }

  static bool _sameFullStructure(
      FullTypeEnvironmentStructure a, FullTypeEnvironmentStructure b) {
    if (a.classType != b.classType) return false;
    List<TypeVariableType> aBindings = a.bindings;
    List<TypeVariableType> bBindings = b.bindings;
    if (aBindings.length != bBindings.length) return false;
    for (int i = 0; i < aBindings.length; i++) {
      if (aBindings[i] != bBindings[i]) return false;
    }
    return true;
  }
}

/// A singleton type environment maps a binds a single value.
class SingletonTypeEnvironmentStructure extends TypeEnvironmentStructure {
  final TypeVariableType variable;

  SingletonTypeEnvironmentStructure(this.variable);

  @override
  String toString() => 'SingletonTypeEnvironmentStructure($variable)';
}

/// A type environment containing an interface type and/or a tuple of function
/// type parameters.
class FullTypeEnvironmentStructure extends TypeEnvironmentStructure {
  final InterfaceType? classType;
  final List<TypeVariableType> bindings;

  FullTypeEnvironmentStructure({this.classType, this.bindings = const []});

  @override
  String toString() => 'FullTypeEnvironmentStructure($classType, $bindings)';
}

/// A TypeRecipe is evaluated against a type environment to produce either a
/// type, or another type environment.
abstract class TypeRecipe {
  /// Tag used for identifying serialized [TypeRecipe] objects in a debugging
  /// data stream.
  static const String tag = 'type-recipe';

  TypeRecipe();

  @override
  late final hashCode = _computeHashCode();

  int _computeHashCode();

  factory TypeRecipe.readFromDataSource(DataSourceReader source) {
    TypeRecipe recipe;
    source.begin(tag);
    _TypeRecipeKind kind = source.readEnum(_TypeRecipeKind.values);
    switch (kind) {
      case _TypeRecipeKind.expression:
        recipe = TypeExpressionRecipe._readFromDataSource(source);
        break;
      case _TypeRecipeKind.singletonEnvironment:
        recipe = SingletonTypeEnvironmentRecipe._readFromDataSource(source);
        break;
      case _TypeRecipeKind.fullEnvironment:
        recipe = FullTypeEnvironmentRecipe._readFromDataSource(source);
        break;
    }
    source.end(tag);
    return recipe;
  }

  void writeToDataSink(DataSinkWriter sink) {
    sink.begin(tag);
    sink.writeEnum(_kind);
    _writeToDataSink(sink);
    sink.end(tag);
  }

  _TypeRecipeKind get _kind;
  void _writeToDataSink(DataSinkWriter sink);

  /// Returns `true` is [recipeB] evaluated in an environment described by
  /// [structureB] gives the same type as [recipeA] evaluated in environment
  /// described by [structureA].
  static bool yieldsSameType(
      TypeRecipe recipeA,
      TypeEnvironmentStructure structureA,
      TypeRecipe recipeB,
      TypeEnvironmentStructure structureB) {
    if (recipeA == recipeB &&
        TypeEnvironmentStructure.same(structureA, structureB)) {
      return true;
    }

    // TODO(sra): Type recipes that are different but equal modulo naming also
    // yield the same type, e.g. `List<X> @X` and `List<Y> @Y`.
    return false;
  }
}

enum _TypeRecipeKind { expression, singletonEnvironment, fullEnvironment }

/// A recipe that yields a reified type.
class TypeExpressionRecipe extends TypeRecipe {
  final DartType type;

  TypeExpressionRecipe(this.type);

  static TypeExpressionRecipe _readFromDataSource(DataSourceReader source) {
    return TypeExpressionRecipe(source.readDartType());
  }

  @override
  _TypeRecipeKind get _kind => _TypeRecipeKind.expression;

  @override
  void _writeToDataSink(DataSinkWriter sink) {
    sink.writeDartType(type);
  }

  @override
  int _computeHashCode() => type.hashCode * 7;

  @override
  bool operator ==(other) {
    return other is TypeExpressionRecipe && type == other.type;
  }

  @override
  String toString() => 'TypeExpressionRecipe($type)';
}

/// A recipe that yields a reified type environment.
abstract class TypeEnvironmentRecipe extends TypeRecipe {}

/// A recipe that yields a reified type environment that binds a single generic
/// function type parameter.
class SingletonTypeEnvironmentRecipe extends TypeEnvironmentRecipe {
  final DartType type;

  SingletonTypeEnvironmentRecipe(this.type);

  static SingletonTypeEnvironmentRecipe _readFromDataSource(
      DataSourceReader source) {
    return SingletonTypeEnvironmentRecipe(source.readDartType());
  }

  @override
  _TypeRecipeKind get _kind => _TypeRecipeKind.singletonEnvironment;

  @override
  void _writeToDataSink(DataSinkWriter sink) {
    sink.writeDartType(type);
  }

  @override
  int _computeHashCode() => type.hashCode * 11;

  @override
  bool operator ==(other) {
    return other is SingletonTypeEnvironmentRecipe && type == other.type;
  }

  @override
  String toString() => 'SingletonTypeEnvironmentRecipe($type)';
}

/// A recipe that yields a reified type environment that binds a class instance
/// type and/or a tuple of types, usually generic function type arguments.
///
/// With no class is also used as a tuple of types.
class FullTypeEnvironmentRecipe extends TypeEnvironmentRecipe {
  /// Type expression for the interface type of a class scope.  `null` for
  /// environments outside a class scope or a class scope where no supertype is
  /// generic, or where optimization has determined that no use of the
  /// environment requires any of the class type variables.
  final InterfaceType? classType;

  // Type expressions for the tuple of function type arguments.
  final List<DartType> types;

  FullTypeEnvironmentRecipe({this.classType, this.types = const []});

  static FullTypeEnvironmentRecipe _readFromDataSource(
      DataSourceReader source) {
    final classType = source.readDartTypeOrNull() as InterfaceType?;
    List<DartType> types = source.readDartTypes();
    return FullTypeEnvironmentRecipe(classType: classType, types: types);
  }

  @override
  _TypeRecipeKind get _kind => _TypeRecipeKind.fullEnvironment;

  @override
  void _writeToDataSink(DataSinkWriter sink) {
    sink.writeDartTypeOrNull(classType);
    sink.writeDartTypes(types);
  }

  @override
  int _computeHashCode() {
    return Hashing.listHash(types, Hashing.objectHash(classType, 0));
  }

  @override
  bool operator ==(other) {
    return other is FullTypeEnvironmentRecipe && _equal(this, other);
  }

  static bool _equal(FullTypeEnvironmentRecipe a, FullTypeEnvironmentRecipe b) {
    if (a.classType != b.classType) return false;
    List<DartType> aTypes = a.types;
    List<DartType> bTypes = b.types;
    if (aTypes.length != bTypes.length) return false;
    for (int i = 0; i < aTypes.length; i++) {
      if (aTypes[i] != bTypes[i]) return false;
    }
    return true;
  }

  @override
  String toString() => 'FullTypeEnvironmentRecipe($classType, $types)';
}

class TypeRecipeDomainImpl implements TypeRecipeDomain {
  final DartTypes _dartTypes;

  const TypeRecipeDomainImpl(this._dartTypes);

  @override
  bool isIdentity(TypeRecipe recipe, TypeEnvironmentStructure structure) {
    if (structure is SingletonTypeEnvironmentStructure &&
        recipe is TypeExpressionRecipe) {
      if (structure.variable == recipe.type) return true;
    }
    return false;
  }

  @override
  bool isReconstruction(ClassEntity classEntity,
      TypeEnvironmentStructure environmentStructure, TypeRecipe recipe) {
    if (environmentStructure is FullTypeEnvironmentStructure &&
        environmentStructure.bindings.isEmpty) {
      InterfaceType classType = environmentStructure.classType!;
      if (classType.element == classEntity) {
        if (recipe is TypeExpressionRecipe && recipe.type == classType) {
          return true;
        }
      }
    }
    return false;
  }

  @override
  TypeRecipe? foldLoadEval(TypeRecipe environmentRecipe,
      TypeEnvironmentStructure environmentStructure, TypeRecipe recipe) {
    if (environmentStructure is SingletonTypeEnvironmentStructure) {
      if (environmentRecipe is TypeExpressionRecipe) {
        List<TypeVariableType> variables = [environmentStructure.variable];
        List<DartType> replacements = [environmentRecipe.type];
        return _Substitution(_dartTypes, null, null, variables, replacements)
            .substituteRecipe(recipe);
      }
      failedAt(CURRENT_ELEMENT_SPANNABLE,
          'Expected a TypeExpressionRecipe: $environmentRecipe');
    }

    if (environmentStructure is FullTypeEnvironmentStructure) {
      if (environmentStructure.classType != null) {
        if (environmentRecipe is TypeExpressionRecipe) {
          assert(environmentStructure.bindings.isEmpty);
          return _Substitution(_dartTypes, environmentStructure.classType,
                  environmentRecipe.type as InterfaceType, null, null)
              .substituteRecipe(recipe);
        }
        return null;
      }
      if (environmentRecipe is TypeExpressionRecipe) {
        // Is this possible?
        return null;
      }
      if (environmentRecipe is FullTypeEnvironmentRecipe) {
        return _Substitution(
                _dartTypes,
                environmentStructure.classType,
                environmentRecipe.classType,
                environmentStructure.bindings,
                environmentRecipe.types)
            .substituteRecipe(recipe);
      }
      return null;
    }

    failedAt(CURRENT_ELEMENT_SPANNABLE,
        'Unknown environmentStructure: $environmentStructure');
  }

  @override
  TypeRecipeAndEnvironmentStructure? foldBindLoadEval(TypeRecipe bindArgument,
      TypeEnvironmentStructure environmentStructure, TypeRecipe recipe) {
    // 'Bind' adds variables to the environment. We fold 'bind' of a ground type
    // by removing the added variables and replacing them in the recipe with the
    // constant type values.

    if (environmentStructure is FullTypeEnvironmentStructure) {
      late final List<DartType> replacements;
      if (bindArgument is TypeExpressionRecipe) {
        // Bind call adds a single binding.
        replacements = [bindArgument.type];
      } else if (bindArgument is FullTypeEnvironmentRecipe) {
        replacements = bindArgument.types;
      } else {
        failedAt(CURRENT_ELEMENT_SPANNABLE,
            'Unexpected bindArgument: $bindArgument');
      }
      List<TypeVariableType> bindings = environmentStructure.bindings;
      int index = bindings.length - replacements.length;
      List<TypeVariableType> replacedVariables = bindings.sublist(index);
      List<TypeVariableType> remainingVariables = bindings.sublist(0, index);
      TypeRecipe? newRecipe =
          _Substitution(_dartTypes, null, null, replacedVariables, replacements)
              .substituteRecipe(recipe);
      if (newRecipe == null) return null;
      TypeEnvironmentStructure newEnvironmentStructure =
          FullTypeEnvironmentStructure(
              classType: environmentStructure.classType,
              bindings: remainingVariables);
      return TypeRecipeAndEnvironmentStructure(
          newRecipe, newEnvironmentStructure);
    }

    failedAt(CURRENT_ELEMENT_SPANNABLE,
        'unexpected bind on environment with structure $environmentStructure');
  }

  @override
  TypeRecipeAndEnvironmentStructure? foldEvalEval(
      TypeEnvironmentStructure environmentStructure1,
      TypeRecipe recipe1,
      TypeEnvironmentStructure environmentStructure2,
      TypeRecipe recipe2) {
    if (environmentStructure2 is SingletonTypeEnvironmentStructure &&
        recipe1 is TypeExpressionRecipe) {
      TypeRecipe? newRecipe = _Substitution(
          _dartTypes,
          null,
          null,
          [environmentStructure2.variable],
          [recipe1.type]).substituteRecipe(recipe2);
      if (newRecipe == null) return null;
      return TypeRecipeAndEnvironmentStructure(
          newRecipe, environmentStructure1);
    }

    if (environmentStructure2 is FullTypeEnvironmentStructure &&
        recipe1 is TypeExpressionRecipe) {
      assert(environmentStructure2.bindings.isEmpty);
      TypeRecipe? newRecipe = _Substitution(
              _dartTypes,
              environmentStructure2.classType,
              recipe1.type as InterfaceType,
              null,
              null)
          .substituteRecipe(recipe2);
      if (newRecipe == null) return null;
      return TypeRecipeAndEnvironmentStructure(
          newRecipe, environmentStructure1);
    }

    if (environmentStructure2 is FullTypeEnvironmentStructure &&
        recipe1 is FullTypeEnvironmentRecipe) {
      TypeRecipe? newRecipe = _Substitution(
              _dartTypes,
              environmentStructure2.classType,
              recipe1.classType,
              environmentStructure2.bindings,
              recipe1.types)
          .substituteRecipe(recipe2);
      if (newRecipe == null) return null;
      return TypeRecipeAndEnvironmentStructure(
          newRecipe, environmentStructure1);
    }

    return null;
  }
}

/// Substitution algorithm for transforming a TypeRecipe by substitution of
/// bindings of a type environment.
///
/// Since the general case of a type environment has class type variables (bound
/// by a class instance type) and method type variable bindings, both are
/// provided. The class type variables can be implicit (e.g. CodeUnits defines
/// ListMixin.E), whereas the method type variables are always bound explicitly.
///
/// A [_Substitution] contains the bindings and the state required to perform
/// a single substitution.
class _Substitution extends DartTypeSubstitutionVisitor<Null> {
  @override
  final DartTypes dartTypes;
  final Map<DartType, DartType?> _lookupCache = {};
  final Map<DartType, int> _counts = {};
  bool _failed = false;

  final InterfaceType? _classEnvironment;
  final InterfaceType? _classValue;
  final List<TypeVariableType>? _variables;
  final List<DartType>? _replacements;

  _Substitution(this.dartTypes, this._classEnvironment, this._classValue,
      this._variables, this._replacements)
      : assert(_variables?.length == _replacements?.length);

  // Returns `null` if declined.
  TypeRecipe? substituteRecipe(TypeRecipe recipe) {
    if (recipe is TypeExpressionRecipe) {
      DartType result = _substituteType(recipe.type);
      if (_failed) return null;
      return TypeExpressionRecipe(result);
    }
    if (recipe is FullTypeEnvironmentRecipe) {
      final newClass =
          _substitutePossiblyNullType(recipe.classType) as InterfaceType?;
      List<DartType> newTypes = recipe.types.map(_substituteType).toList();
      if (_failed) return null;
      return FullTypeEnvironmentRecipe(classType: newClass, types: newTypes);
    }

    failedAt(CURRENT_ELEMENT_SPANNABLE, 'Unexpected recipe: $recipe');
  }

  DartType _substituteType(DartType type) => visit(type, null);

  DartType? _substitutePossiblyNullType(DartType? type) =>
      type == null ? null : visit(type, null);

  // Returns `null` if not bound.
  DartType? _lookupTypeVariableType(TypeVariableType type) {
    if (_variables != null) {
      int index = _variables!.indexOf(type);
      if (index >= 0) return _replacements![index];
    }
    if (_classEnvironment == null) return null;

    if (_classEnvironment!.element == _classValue?.element) {
      int index = _classEnvironment!.typeArguments.indexOf(type);
      if (index >= 0) return _classValue!.typeArguments[index];
      return null;
    }
    // TODO(sra): Lookup type variable of supertype (e.g. ListMixin.E of
    // CodeUnits).
    _failed = true;
    return null;
  }

  @override
  DartType substituteTypeVariableType(
      TypeVariableType variable, Null argument, bool freshReference) {
    DartType? replacement =
        _lookupCache[variable] ??= _lookupTypeVariableType(variable);
    if (replacement == null) return variable; // not substituted.
    if (!freshReference) return replacement;
    int count = _counts[variable] = (_counts[variable] ?? 0) + 1;
    if (count > 1) {
      // If the replacement is 'big', duplicating it can grow the term, perhaps
      // exponentially given a sufficently pathological input.
      // TODO(sra): Fix exponential terms by encoding a DAG in recipes to avoid
      // linearization.
      if (replacement is FunctionType ||
          replacement is InterfaceType &&
              replacement.typeArguments.isNotEmpty ||
          replacement is FutureOrType) {
        _failed = true;
      }
    }
    return replacement;
  }
}
