// Copyright (c) 2013, 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

part of masks;

/// An implementation of a [UniverseSelectorConstraints] that is consists if an
/// only increasing set of [TypeMask]s, that is, once a mask is added it cannot
/// be removed.
class IncreasingTypeMaskSet extends UniverseSelectorConstraints {
  bool isAll = false;
  Set<TypeMask> _masks;

  @override
  bool canHit(MemberEntity element, Name name, JClosedWorld world) {
    if (isAll) return true;
    if (_masks == null) return false;
    for (TypeMask mask in _masks) {
      if (mask.canHit(element, name, world)) return true;
    }
    return false;
  }

  @override
  bool needsNoSuchMethodHandling(Selector selector, JClosedWorld world) {
    if (isAll) {
      TypeMask mask =
          TypeMask.subclass(world.commonElements.objectClass, world);
      return mask.needsNoSuchMethodHandling(selector, world);
    }
    for (TypeMask mask in _masks) {
      if (mask.needsNoSuchMethodHandling(selector, world)) {
        return true;
      }
    }
    return false;
  }

  @override
  bool addReceiverConstraint(TypeMask mask) {
    if (isAll) return false;
    if (mask == null) {
      isAll = true;
      _masks = null;
      return true;
    }
    _masks ??= {};
    return _masks.add(mask);
  }

  @override
  String toString() {
    if (isAll) {
      return '<all>';
    } else if (_masks != null) {
      return '$_masks';
    } else {
      return '<none>';
    }
  }
}

class TypeMaskStrategy implements AbstractValueStrategy {
  const TypeMaskStrategy();

  @override
  AbstractValueDomain createDomain(JClosedWorld closedWorld) {
    return CommonMasks(closedWorld);
  }

  @override
  SelectorConstraintsStrategy createSelectorStrategy() {
    return TypeMaskSelectorStrategy();
  }
}

class TypeMaskSelectorStrategy implements SelectorConstraintsStrategy {
  const TypeMaskSelectorStrategy();

  @override
  UniverseSelectorConstraints createSelectorConstraints(
      Selector selector, Object initialConstraint) {
    return IncreasingTypeMaskSet()..addReceiverConstraint(initialConstraint);
  }

  @override
  bool appliedUnnamed(DynamicUse dynamicUse, MemberEntity member,
      covariant JClosedWorld world) {
    Selector selector = dynamicUse.selector;
    TypeMask mask = dynamicUse.receiverConstraint;
    return selector.appliesUnnamed(member) &&
        (mask == null || mask.canHit(member, selector.memberName, world));
  }
}

/// Enum used for identifying [TypeMask] subclasses in serialization.
enum TypeMaskKind {
  flat,
  union,
  container,
  set,
  map,
  dictionary,
  value,
}

/// A type mask represents a set of contained classes, but the
/// operations on it are not guaranteed to be precise and they may
/// yield conservative answers that contain too many classes.
abstract class TypeMask implements AbstractValue {
  const TypeMask();

  factory TypeMask.empty({bool hasLateSentinel = false}) =>
      FlatTypeMask.empty(hasLateSentinel: hasLateSentinel);

  factory TypeMask.exact(ClassEntity base, JClosedWorld closedWorld,
      {bool hasLateSentinel = false}) {
    assert(
        closedWorld.classHierarchy.isInstantiated(base),
        failedAt(
            base ?? CURRENT_ELEMENT_SPANNABLE,
            "Cannot create exact type mask for uninstantiated "
            "class $base.\n${closedWorld.classHierarchy.dump(base)}"));
    return FlatTypeMask.exact(base, closedWorld,
        hasLateSentinel: hasLateSentinel);
  }

  factory TypeMask.exactOrEmpty(ClassEntity base, JClosedWorld closedWorld,
      {bool hasLateSentinel = false}) {
    if (closedWorld.classHierarchy.isInstantiated(base)) {
      return FlatTypeMask.exact(base, closedWorld,
          hasLateSentinel: hasLateSentinel);
    }
    return TypeMask.empty(hasLateSentinel: hasLateSentinel);
  }

  factory TypeMask.subclass(ClassEntity base, JClosedWorld closedWorld,
      {bool hasLateSentinel = false}) {
    assert(
        closedWorld.classHierarchy.isInstantiated(base),
        failedAt(
            base ?? CURRENT_ELEMENT_SPANNABLE,
            "Cannot create subclass type mask for uninstantiated "
            "class $base.\n${closedWorld.classHierarchy.dump(base)}"));
    ClassEntity topmost = closedWorld.getLubOfInstantiatedSubclasses(base);
    if (topmost == null) {
      return TypeMask.empty(hasLateSentinel: hasLateSentinel);
    } else if (closedWorld.classHierarchy.hasAnyStrictSubclass(topmost)) {
      return FlatTypeMask.subclass(topmost, closedWorld,
          hasLateSentinel: hasLateSentinel);
    } else {
      return TypeMask.exact(topmost, closedWorld,
          hasLateSentinel: hasLateSentinel);
    }
  }

  factory TypeMask.subtype(ClassEntity base, JClosedWorld closedWorld,
      {bool hasLateSentinel = false}) {
    ClassEntity topmost = closedWorld.getLubOfInstantiatedSubtypes(base);
    if (topmost == null) {
      return TypeMask.empty(hasLateSentinel: hasLateSentinel);
    }
    if (closedWorld.classHierarchy.hasOnlySubclasses(topmost)) {
      return TypeMask.subclass(topmost, closedWorld,
          hasLateSentinel: hasLateSentinel);
    }
    if (closedWorld.classHierarchy.hasAnyStrictSubtype(topmost)) {
      return FlatTypeMask.subtype(topmost, closedWorld,
          hasLateSentinel: hasLateSentinel);
    } else {
      return TypeMask.exact(topmost, closedWorld,
          hasLateSentinel: hasLateSentinel);
    }
  }

  factory TypeMask.nonNullEmpty({bool hasLateSentinel = false}) =>
      FlatTypeMask.nonNullEmpty(hasLateSentinel: hasLateSentinel);

  factory TypeMask.nonNullExact(ClassEntity base, JClosedWorld closedWorld,
      {bool hasLateSentinel = false}) {
    assert(
        closedWorld.classHierarchy.isInstantiated(base),
        failedAt(
            base ?? CURRENT_ELEMENT_SPANNABLE,
            "Cannot create exact type mask for uninstantiated "
            "class $base.\n${closedWorld.classHierarchy.dump(base)}"));
    return FlatTypeMask.nonNullExact(base, closedWorld,
        hasLateSentinel: hasLateSentinel);
  }

  factory TypeMask.nonNullExactOrEmpty(
      ClassEntity base, JClosedWorld closedWorld,
      {bool hasLateSentinel = false}) {
    if (closedWorld.classHierarchy.isInstantiated(base)) {
      return FlatTypeMask.nonNullExact(base, closedWorld,
          hasLateSentinel: hasLateSentinel);
    }
    return TypeMask.nonNullEmpty(hasLateSentinel: hasLateSentinel);
  }

  factory TypeMask.nonNullSubclass(ClassEntity base, JClosedWorld closedWorld,
      {bool hasLateSentinel = false}) {
    assert(
        closedWorld.classHierarchy.isInstantiated(base),
        failedAt(
            base ?? CURRENT_ELEMENT_SPANNABLE,
            "Cannot create subclass type mask for uninstantiated "
            "class $base.\n${closedWorld.classHierarchy.dump(base)}"));
    ClassEntity topmost = closedWorld.getLubOfInstantiatedSubclasses(base);
    if (topmost == null) {
      return TypeMask.nonNullEmpty(hasLateSentinel: hasLateSentinel);
    } else if (closedWorld.classHierarchy.hasAnyStrictSubclass(topmost)) {
      return FlatTypeMask.nonNullSubclass(topmost, closedWorld,
          hasLateSentinel: hasLateSentinel);
    } else {
      return TypeMask.nonNullExact(topmost, closedWorld,
          hasLateSentinel: hasLateSentinel);
    }
  }

  factory TypeMask.nonNullSubtype(ClassEntity base, JClosedWorld closedWorld,
      {bool hasLateSentinel = false}) {
    ClassEntity topmost = closedWorld.getLubOfInstantiatedSubtypes(base);
    if (topmost == null) {
      return TypeMask.nonNullEmpty(hasLateSentinel: hasLateSentinel);
    }
    if (closedWorld.classHierarchy.hasOnlySubclasses(topmost)) {
      return TypeMask.nonNullSubclass(topmost, closedWorld,
          hasLateSentinel: hasLateSentinel);
    }
    if (closedWorld.classHierarchy.hasAnyStrictSubtype(topmost)) {
      return FlatTypeMask.nonNullSubtype(topmost, closedWorld,
          hasLateSentinel: hasLateSentinel);
    } else {
      return TypeMask.nonNullExact(topmost, closedWorld,
          hasLateSentinel: hasLateSentinel);
    }
  }

  factory TypeMask.unionOf(Iterable<TypeMask> masks, CommonMasks domain) {
    return UnionTypeMask.unionOf(masks, domain);
  }

  /// Deserializes a [TypeMask] object from [source].
  factory TypeMask.readFromDataSource(
      DataSourceReader source, CommonMasks domain) {
    TypeMaskKind kind = source.readEnum(TypeMaskKind.values);
    switch (kind) {
      case TypeMaskKind.flat:
        return FlatTypeMask.readFromDataSource(source, domain);
      case TypeMaskKind.union:
        return UnionTypeMask.readFromDataSource(source, domain);
      case TypeMaskKind.container:
        return ContainerTypeMask.readFromDataSource(source, domain);
      case TypeMaskKind.set:
        return SetTypeMask.readFromDataSource(source, domain);
      case TypeMaskKind.map:
        return MapTypeMask.readFromDataSource(source, domain);
      case TypeMaskKind.dictionary:
        return DictionaryTypeMask.readFromDataSource(source, domain);
      case TypeMaskKind.value:
        return ValueTypeMask.readFromDataSource(source, domain);
    }
    throw UnsupportedError("Unexpected TypeMaskKind $kind.");
  }

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

  /// If [mask] is forwarding, returns the first non-forwarding [TypeMask] in
  /// [mask]'s forwarding chain.
  static TypeMask nonForwardingMask(mask) {
    while (mask.isForwarding) {
      mask = mask.forwardTo;
    }
    return mask;
  }

  /// Asserts that this mask uses the smallest possible representation for
  /// its types. Currently, we normalize subtype and subclass to exact if no
  /// subtypes or subclasses are present and subtype to subclass if only
  /// subclasses exist. We also normalize exact to empty if the corresponding
  /// baseclass was never instantiated.
  static bool assertIsNormalized(TypeMask mask, JClosedWorld closedWorld) {
    String reason = getNotNormalizedReason(mask, closedWorld);
    assert(reason == null,
        failedAt(NO_LOCATION_SPANNABLE, '$mask is not normalized: $reason'));
    return true;
  }

  static String getNotNormalizedReason(
      TypeMask mask, JClosedWorld closedWorld) {
    mask = nonForwardingMask(mask);
    if (mask is FlatTypeMask) {
      if (mask.isEmptyOrFlagged) return null;
      if (mask.base == closedWorld.commonElements.nullClass) {
        return 'The class ${mask.base} is not canonicalized.';
      }
      if (mask.isExact) {
        if (!closedWorld.classHierarchy.isInstantiated(mask.base)) {
          return 'Exact ${mask.base} is not instantiated.';
        }
        return null;
      }
      if (mask.isSubclass) {
        if (!closedWorld.classHierarchy.hasAnyStrictSubclass(mask.base)) {
          return 'Subclass ${mask.base} does not have any subclasses.';
        }
        return null;
      }
      assert(mask.isSubtype);
      if (!closedWorld.classHierarchy.hasAnyStrictSubtype(mask.base)) {
        return 'Subtype ${mask.base} does not have any subclasses.';
      }
      if (closedWorld.classHierarchy.hasOnlySubclasses(mask.base)) {
        return 'Subtype ${mask.base} only has subclasses.';
      }
      return null;
    } else if (mask is UnionTypeMask) {
      for (TypeMask submask in mask.disjointMasks) {
        String submaskReason = getNotNormalizedReason(submask, closedWorld);
        if (submaskReason != null) {
          return 'Submask $submask in $mask: $submaskReason.';
        }
      }
      return null;
    }
    return 'Unknown type mask $mask.';
  }

  /// Returns a nullable variant of [this] type mask.
  TypeMask nullable() => withFlags(isNullable: true);

  /// Returns a non-nullable variant of [this] type mask.
  TypeMask nonNullable() => withFlags(isNullable: false);

  /// Returns a variant of [this] type mask whose value is neither `null` nor
  /// the late sentinel.
  TypeMask withoutFlags() =>
      withFlags(isNullable: false, hasLateSentinel: false);

  TypeMask withFlags({bool isNullable, bool hasLateSentinel});

  /// Whether nothing matches this mask, not even null.
  bool get isEmpty;

  /// Whether null is a valid value of this mask.
  bool get isNullable;

  /// Whether the only possible value in this mask is Null.
  bool get isNull;

  /// Whether [this] is a sentinel for an uninitialized late variable.
  AbstractBool get isLateSentinel;

  /// Whether a late sentinel is a valid value of this mask.
  bool get hasLateSentinel => isLateSentinel.isPotentiallyTrue;

  /// Whether [this] mask is empty or only represents values tracked by flags
  /// (i.e. `null` and the late sentinel).
  bool get isEmptyOrFlagged;

  /// Whether this mask only includes instances of an exact class, and none of
  /// it's subclasses or subtypes.
  bool get isExact;

  /// Returns true if this mask is a union type.
  bool get isUnion;

  /// Returns `true` if this mask is a [ContainerTypeMask].
  bool get isContainer;

  /// Returns `true` if this mask is a [SetTypeMask].
  bool get isSet;

  /// Returns `true` if this mask is a [MapTypeMask].
  bool get isMap;

  /// Returns `true` if this mask is a [MapTypeMask] in dictionary mode, i.e.,
  /// all keys are known string values and we have specific type information for
  /// corresponding values.
  bool get isDictionary;

  /// Returns `true` if this mask is wrapping another mask for the purpose of
  /// tracing.
  bool get isForwarding;

  /// Returns `true` if this mask holds encodes an exact value within a type.
  bool get isValue;

  bool containsOnlyInt(JClosedWorld closedWorld);
  bool containsOnlyNum(JClosedWorld closedWorld);
  bool containsOnlyBool(JClosedWorld closedWorld);
  bool containsOnlyString(JClosedWorld closedWorld);
  bool containsOnly(ClassEntity cls);

  /// Compares two [TypeMask] objects for structural equality.
  ///
  /// Note: This may differ from semantic equality in the set containment sense.
  ///   Use [containsMask] and [isInMask] for that, instead.
  @override
  bool operator ==(other);

  /// If this returns `true`, [other] is guaranteed to be a supertype of this
  /// mask, i.e., this mask is in [other]. However, the inverse does not hold.
  /// Enable [UnionTypeMask.PERFORM_EXTRA_CONTAINS_CHECK] to be notified of
  /// false negatives.
  bool isInMask(TypeMask other, JClosedWorld closedWorld);

  /// If this returns `true`, [other] is guaranteed to be a subtype of this
  /// mask, i.e. this mask contains [other]. However, the inverse does not hold.
  /// Enable [UnionTypeMask.PERFORM_EXTRA_CONTAINS_CHECK] to be notified of
  /// false negatives.
  bool containsMask(TypeMask other, JClosedWorld closedWorld);

  /// Returns whether this type mask is an instance of [cls].
  bool satisfies(ClassEntity cls, JClosedWorld closedWorld);

  /// Returns whether or not this type mask contains the given class [cls].
  bool contains(ClassEntity cls, JClosedWorld closedWorld);

  /// Returns whether or not this type mask contains all types.
  bool containsAll(JClosedWorld closedWorld);

  /// Returns the [ClassEntity] if this type represents a single class,
  /// otherwise returns `null`.  This method is conservative.
  ClassEntity singleClass(JClosedWorld closedWorld);

  /// Returns a type mask representing the union of [this] and [other].
  TypeMask union(TypeMask other, CommonMasks domain);

  /// Returns whether the intersection of this and [other] is empty.
  bool isDisjoint(TypeMask other, JClosedWorld closedWorld);

  /// Returns a type mask representing the intersection of [this] and [other].
  TypeMask intersection(TypeMask other, CommonMasks domain);

  /// Returns whether [element] is a potential target when being invoked on this
  /// type mask.
  ///
  ///
  /// [name] is used to ensure library privacy is taken into account.
  bool canHit(MemberEntity element, Name name, JClosedWorld closedWorld);

  /// Returns whether this [TypeMask] applied to [selector] can hit a
  /// [noSuchMethod].
  bool needsNoSuchMethodHandling(Selector selector, JClosedWorld world);

  /// Returns the [element] that is known to always be hit at runtime
  /// on this mask. Returns null if there is none.
  MemberEntity locateSingleMember(Selector selector, CommonMasks domain);
}
