// 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.

part of masks;

/// A [SetTypeMask] is a [TypeMask] for a specific allocation site of a set
/// (currently only the internal Set class) that will get specialized once the
/// [TypeGraphInferrer] phase finds an element type for it.
class SetTypeMask extends AllocationTypeMask {
  /// Tag used for identifying serialized [SetTypeMask] objects in a debugging
  /// data stream.
  static const String tag = 'set-type-mask';

  @override
  final TypeMask forwardTo;

  // The [Node] where this type mask was created.
  @override
  final ir.TreeNode allocationNode;

  // The [Entity] where this type mask was created.
  @override
  final MemberEntity allocationElement;

  // The element type of this set.
  final TypeMask elementType;

  SetTypeMask(this.forwardTo, this.allocationNode, this.allocationElement,
      this.elementType);

  /// Deserializes a [SetTypeMask] object from [source].
  factory SetTypeMask.readFromDataSource(
      DataSource source, JClosedWorld closedWorld) {
    source.begin(tag);
    TypeMask forwardTo = new TypeMask.readFromDataSource(source, closedWorld);
    ir.TreeNode allocationNode = source.readTreeNodeOrNull();
    MemberEntity allocationElement = source.readMemberOrNull();
    TypeMask elementType = new TypeMask.readFromDataSource(source, closedWorld);
    source.end(tag);
    return new SetTypeMask(
        forwardTo, allocationNode, allocationElement, elementType);
  }

  /// Serializes this [SetTypeMask] to [sink].
  @override
  void writeToDataSink(DataSink sink) {
    sink.writeEnum(TypeMaskKind.set);
    sink.begin(tag);
    forwardTo.writeToDataSink(sink);
    sink.writeTreeNodeOrNull(allocationNode);
    sink.writeMemberOrNull(allocationElement);
    elementType.writeToDataSink(sink);
    sink.end(tag);
  }

  @override
  TypeMask nullable() => isNullable
      ? this
      : new SetTypeMask(
          forwardTo.nullable(), allocationNode, allocationElement, elementType);

  @override
  TypeMask nonNullable() => isNullable
      ? new SetTypeMask(forwardTo.nonNullable(), allocationNode,
          allocationElement, elementType)
      : this;

  @override
  bool get isSet => true;

  @override
  bool get isExact => true;

  @override
  bool equalsDisregardNull(other) {
    if (other is! SetTypeMask) return false;
    return super.equalsDisregardNull(other) &&
        allocationNode == other.allocationNode &&
        elementType == other.elementType;
  }

  @override
  TypeMask intersection(TypeMask other, JClosedWorld closedWorld) {
    TypeMask forwardIntersection = forwardTo.intersection(other, closedWorld);
    if (forwardIntersection.isEmptyOrNull) return forwardIntersection;
    return forwardIntersection.isNullable ? nullable() : nonNullable();
  }

  @override
  TypeMask union(dynamic other, JClosedWorld closedWorld) {
    if (this == other) {
      return this;
    } else if (equalsDisregardNull(other)) {
      return other.isNullable ? other : this;
    } else if (other.isEmptyOrNull) {
      return other.isNullable ? this.nullable() : this;
    } else if (other.isSet &&
        elementType != null &&
        other.elementType != null) {
      TypeMask newElementType =
          elementType.union(other.elementType, closedWorld);
      TypeMask newForwardTo = forwardTo.union(other.forwardTo, closedWorld);
      return new SetTypeMask(newForwardTo, null, null, newElementType);
    } else {
      return forwardTo.union(other, closedWorld);
    }
  }

  @override
  bool operator ==(other) => super == other;

  @override
  int get hashCode =>
      computeHashCode(allocationNode, isNullable, elementType, forwardTo);

  @override
  String toString() => 'Set($forwardTo, element: $elementType)';
}
