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

// @dart = 2.10

library entities;

import 'package:front_end/src/api_unstable/dart2js.dart' show AsyncModifier;

import '../common.dart';
import '../serialization/serialization.dart';
import '../universe/call_structure.dart' show CallStructure;
import '../util/util.dart';
import 'names.dart';
import 'types.dart';

/// Abstract interface for entities.
///
/// Implement this directly if the entity is not a Dart language entity.
/// Entities defined within the Dart language should implement [Element].
///
/// For instance, the JavaScript backend need to create synthetic variables for
/// calling intercepted classes and such variables do not correspond to an
/// entity in the Dart source code nor in the terminology of the Dart language
/// and should therefore implement [Entity] directly.
abstract class Entity implements Spannable {
  String get name;
}

/// Stripped down super interface for library like entities.
///
/// Currently only [LibraryElement] but later also kernel based Dart classes
/// and/or Dart-in-JS classes.
abstract class LibraryEntity extends Entity {
  /// Return the canonical uri that identifies this library.
  Uri get canonicalUri;

  /// Returns whether or not this library has opted into null safety.
  bool get isNonNullableByDefault;
}

/// Stripped down super interface for import entities.
///
/// The [name] property corresponds to the prefix name, if any.
class ImportEntity {
  final String name;

  /// The canonical URI of the library where this import occurs
  /// (where the import is declared).
  final Uri enclosingLibraryUri;

  /// Whether the import is a deferred import.
  final bool isDeferred;

  /// The target import URI.
  final Uri uri;

  ImportEntity(this.isDeferred, this.name, this.uri, this.enclosingLibraryUri);

  @override
  String toString() => 'import($name:${isDeferred ? ' deferred' : ''})';
}

/// Stripped down super interface for class like entities.
///
/// Currently only [ClassElement] but later also kernel based Dart classes
/// and/or Dart-in-JS classes.
abstract class ClassEntity extends Entity {
  /// If this is a normal class, the enclosing library for this class. If this
  /// is a closure class, the enclosing class of the closure for which it was
  /// created.
  LibraryEntity get library;

  /// Whether this is a synthesized class for a closurized method or local
  /// function.
  bool get isClosure;

  /// Whether this is an abstract class.
  bool get isAbstract;
}

abstract class TypeVariableEntity extends Entity {
  /// The class or generic method that declared this type variable.
  Entity get typeDeclaration;

  /// The index of this type variable in the type variables of its
  /// [typeDeclaration].
  int get index;
}

/// Stripped down super interface for member like entities, that is,
/// constructors, methods, fields etc.
///
/// Currently only [MemberElement] but later also kernel based Dart members
/// and/or Dart-in-JS properties.
abstract class MemberEntity extends Entity {
  /// The [Name] of member which takes privacy and getter/setter naming into
  /// account.
  Name get memberName;

  /// Whether this is a member of a library.
  bool get isTopLevel;

  /// Whether this is a static member of a class.
  bool get isStatic;

  /// Whether this is an instance member of a class.
  bool get isInstanceMember;

  /// Whether this is a constructor.
  bool get isConstructor;

  /// Whether this is a field.
  bool get isField;

  /// Whether this is a normal method (neither constructor, getter or setter)
  /// or operator method.
  bool get isFunction;

  /// Whether this is a getter.
  bool get isGetter;

  /// Whether this is a setter.
  bool get isSetter;

  /// Whether this member is assignable, i.e. a non-final, non-const field.
  bool get isAssignable;

  /// Whether this member is constant, i.e. a constant field or constructor.
  bool get isConst;

  /// Whether this member is abstract, i.e. an abstract method, getter or
  /// setter.
  bool get isAbstract;

  /// The enclosing class if this is a constructor, instance member or
  /// static member of a class.
  ClassEntity get enclosingClass;

  /// The enclosing library if this is a library member, otherwise the
  /// enclosing library of the [enclosingClass].
  LibraryEntity get library;
}

/// Stripped down super interface for field like entities.
///
/// Currently only [FieldElement] but later also kernel based Dart fields
/// and/or Dart-in-JS field-like properties.
abstract class FieldEntity extends MemberEntity {}

/// Stripped down super interface for function like entities.
///
/// Currently only [MethodElement] but later also kernel based Dart constructors
/// and methods and/or Dart-in-JS function-like properties.
abstract class FunctionEntity extends MemberEntity {
  /// Whether this function is external, i.e. the body is not defined in terms
  /// of Dart code.
  bool get isExternal;

  /// The structure of the function parameters.
  ParameterStructure get parameterStructure;

  /// The synchronous/asynchronous marker on this function.
  AsyncMarker get asyncMarker;
}

/// Enum for the synchronous/asynchronous function body modifiers.
class AsyncMarker {
  /// The default function body marker.
  static const AsyncMarker SYNC = AsyncMarker._(AsyncModifier.Sync);

  /// The `sync*` function body marker.
  static const AsyncMarker SYNC_STAR =
      AsyncMarker._(AsyncModifier.SyncStar, isYielding: true);

  /// The `async` function body marker.
  static const AsyncMarker ASYNC =
      AsyncMarker._(AsyncModifier.Async, isAsync: true);

  /// The `async*` function body marker.
  static const AsyncMarker ASYNC_STAR =
      AsyncMarker._(AsyncModifier.AsyncStar, isAsync: true, isYielding: true);

  /// Is `true` if this marker defines the function body to have an
  /// asynchronous result, that is, either a [Future] or a [Stream].
  final bool isAsync;

  /// Is `true` if this marker defines the function body to have a plural
  /// result, that is, either an [Iterable] or a [Stream].
  final bool isYielding;

  final AsyncModifier asyncParserState;

  const AsyncMarker._(this.asyncParserState,
      {this.isAsync = false, this.isYielding = false});

  @override
  String toString() {
    return '${isAsync ? 'async' : 'sync'}${isYielding ? '*' : ''}';
  }

  /// Canonical list of marker values.
  ///
  /// Added to make [AsyncMarker] enum-like.
  static const List<AsyncMarker> values = <AsyncMarker>[
    SYNC,
    SYNC_STAR,
    ASYNC,
    ASYNC_STAR
  ];

  /// Index to this marker within [values].
  ///
  /// Added to make [AsyncMarker] enum-like.
  int get index => values.indexOf(this);
}

/// Values for variance annotations.
/// This needs to be kept in sync with values of `Variance` in `dart:_rti`.
enum Variance { legacyCovariant, covariant, contravariant, invariant }

/// Stripped down super interface for constructor like entities.
///
/// Currently only [ConstructorElement] but later also kernel based Dart
/// constructors and/or Dart-in-JS constructor-like properties.
// TODO(johnniwinther): Remove factory constructors from the set of
// constructors.
abstract class ConstructorEntity extends FunctionEntity {
  /// Whether this is a generative constructor, possibly redirecting.
  bool get isGenerativeConstructor;

  /// Whether this is a factory constructor, possibly redirecting.
  bool get isFactoryConstructor;

  /// Whether this is a `fromEnvironment` const constructor in `int`, `bool` or
  /// `String`.
  bool get isFromEnvironmentConstructor;
}

/// The constructor body for a [ConstructorEntity].
///
/// This is used only in the backend to split encoding of a Dart constructor
/// into two JavaScript functions; the constructor and the constructor body.
// TODO(johnniwinther): Remove this when modelx is removed. Constructor bodies
// should then be created directly with the J-model.
abstract class ConstructorBodyEntity extends FunctionEntity {
  /// The constructor for which this constructor body was created.
  ConstructorEntity get constructor;
}

/// An entity that defines a local entity (memory slot) in generated code.
///
/// Parameters, local variables and local functions (can) define local entity
/// and thus implement [Local] through [LocalElement]. For non-element locals,
/// like `this` and boxes, specialized [Local] classes are created.
///
/// Type variables can introduce locals in factories and constructors
/// but since one type variable can introduce different locals in different
/// factories and constructors it is not itself a [Local] but instead
/// a non-element [Local] is created through a specialized class.
abstract class Local extends Entity {}

/// The structure of function parameters.
class ParameterStructure {
  /// Tag used for identifying serialized [ParameterStructure] objects in a
  /// debugging data stream.
  static const String tag = 'parameter-structure';

  /// The number of required positional parameters.
  final int requiredPositionalParameters;

  /// The number of positional parameters.
  final int positionalParameters;

  /// All named parameters sorted alphabetically.
  final List<String> namedParameters;

  /// The required named parameters.
  final Set<String> requiredNamedParameters;

  /// The number of type parameters.
  final int typeParameters;

  static const ParameterStructure getter =
      ParameterStructure._(0, 0, [], {}, 0);

  static const ParameterStructure setter =
      ParameterStructure._(1, 1, [], {}, 0);

  static const ParameterStructure zeroArguments =
      ParameterStructure._(0, 0, [], {}, 0);

  static const ParameterStructure oneArgument =
      ParameterStructure._(1, 1, [], {}, 0);

  static const ParameterStructure twoArguments =
      ParameterStructure._(2, 2, [], {}, 0);

  static const List<ParameterStructure> _simple = [
    ParameterStructure._(0, 0, [], {}, 0),
    ParameterStructure._(1, 1, [], {}, 0),
    ParameterStructure._(2, 2, [], {}, 0),
    ParameterStructure._(3, 3, [], {}, 0),
    ParameterStructure._(4, 4, [], {}, 0),
    ParameterStructure._(5, 5, [], {}, 0),
  ];

  const ParameterStructure._(
      this.requiredPositionalParameters,
      this.positionalParameters,
      this.namedParameters,
      this.requiredNamedParameters,
      this.typeParameters);

  factory ParameterStructure(
      int requiredPositionalParameters,
      int positionalParameters,
      List<String> namedParameters,
      Set<String> requiredNamedParameters,
      int typeParameters) {
    // This simple canonicalization reduces the number of ParameterStructure
    // objects by over 90%.
    if (requiredPositionalParameters == positionalParameters &&
        namedParameters.isEmpty &&
        requiredNamedParameters.isEmpty &&
        typeParameters == 0 &&
        positionalParameters < _simple.length) {
      return _simple[positionalParameters];
    }

    // Force sharing of empty collections.
    if (namedParameters.isEmpty) namedParameters = const [];
    if (requiredNamedParameters.isEmpty) requiredNamedParameters = const {};

    return ParameterStructure._(
      requiredPositionalParameters,
      positionalParameters,
      namedParameters,
      requiredNamedParameters,
      typeParameters,
    );
  }

  factory ParameterStructure.fromType(FunctionType type) {
    return ParameterStructure(
        type.parameterTypes.length,
        type.parameterTypes.length + type.optionalParameterTypes.length,
        type.namedParameters,
        type.requiredNamedParameters,
        type.typeVariables.length);
  }

  /// Deserializes a [ParameterStructure] object from [source].
  factory ParameterStructure.readFromDataSource(DataSourceReader source) {
    source.begin(tag);
    int requiredPositionalParameters = source.readInt();
    int positionalParameters = source.readInt();
    List<String> namedParameters = source.readStrings();
    Set<String> requiredNamedParameters =
        source.readStrings(emptyAsNull: true)?.toSet() ?? const <String>{};
    int typeParameters = source.readInt();
    source.end(tag);
    return ParameterStructure(
        requiredPositionalParameters,
        positionalParameters,
        namedParameters,
        requiredNamedParameters,
        typeParameters);
  }

  /// Serializes this [ParameterStructure] to [sink].
  void writeToDataSink(DataSinkWriter sink) {
    sink.begin(tag);
    sink.writeInt(requiredPositionalParameters);
    sink.writeInt(positionalParameters);
    sink.writeStrings(namedParameters);
    sink.writeStrings(requiredNamedParameters);
    sink.writeInt(typeParameters);
    sink.end(tag);
  }

  /// The number of optional parameters (positional or named).
  int get optionalParameters =>
      (positionalParameters - requiredPositionalParameters) +
      (namedParameters.length - requiredNamedParameters.length);

  /// The total number of parameters (required or optional).
  int get totalParameters => positionalParameters + namedParameters.length;

  /// Returns the [CallStructure] corresponding to a call site passing all
  /// parameters both required and optional.
  CallStructure get callStructure {
    return CallStructure(totalParameters, namedParameters, typeParameters);
  }

  @override
  int get hashCode => Hashing.listHash(
      namedParameters,
      Hashing.setHash(
          requiredNamedParameters,
          Hashing.objectHash(
              positionalParameters,
              Hashing.objectHash(requiredPositionalParameters,
                  Hashing.objectHash(typeParameters)))));

  @override
  bool operator ==(other) {
    if (identical(this, other)) return true;
    if (other is! ParameterStructure) return false;
    if (requiredPositionalParameters != other.requiredPositionalParameters ||
        positionalParameters != other.positionalParameters ||
        typeParameters != other.typeParameters ||
        namedParameters.length != other.namedParameters.length ||
        requiredNamedParameters.length !=
            other.requiredNamedParameters.length) {
      return false;
    }
    for (int i = 0; i < namedParameters.length; i++) {
      if (namedParameters[i] != other.namedParameters[i]) {
        return false;
      }
    }
    for (String name in requiredNamedParameters) {
      if (!other.requiredNamedParameters.contains(name)) return false;
    }
    return true;
  }

  /// Short textual representation use for testing.
  String get shortText {
    StringBuffer sb = StringBuffer();
    if (typeParameters != 0) {
      sb.write('<');
      sb.write(typeParameters);
      sb.write('>');
    }
    sb.write('(');
    sb.write(positionalParameters);
    for (var name in namedParameters) {
      sb.write(',');
      if (requiredNamedParameters.contains(name)) sb.write('req ');
      sb.write(name);
    }
    sb.write(')');
    return sb.toString();
  }

  @override
  String toString() {
    StringBuffer sb = StringBuffer();
    sb.write('ParameterStructure(');
    sb.write('requiredPositionalParameters=$requiredPositionalParameters,');
    sb.write('positionalParameters=$positionalParameters,');
    sb.write('namedParameters={${namedParameters.join(',')}},');
    sb.write('requiredNamedParameters={${requiredNamedParameters.join(',')}},');
    sb.write('typeParameters=$typeParameters)');
    return sb.toString();
  }

  int get size => totalParameters + typeParameters;
}
