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

// @dart = 2.10

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;

  @override
  final ir.Node allocationNode;

  @override
  final MemberEntity allocationElement;

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

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

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

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

  @override
  SetTypeMask withFlags({bool isNullable, bool hasLateSentinel}) {
    isNullable ??= this.isNullable;
    hasLateSentinel ??= this.hasLateSentinel;
    if (isNullable == this.isNullable &&
        hasLateSentinel == this.hasLateSentinel) {
      return this;
    }
    return SetTypeMask(
        forwardTo.withFlags(
            isNullable: isNullable, hasLateSentinel: hasLateSentinel),
        allocationNode,
        allocationElement,
        elementType);
  }

  @override
  bool get isSet => true;

  @override
  bool get isExact => true;

  @override
  TypeMask _unionSpecialCases(TypeMask other, CommonMasks domain,
      {bool isNullable, bool hasLateSentinel}) {
    assert(isNullable != null);
    assert(hasLateSentinel != null);
    if (other is SetTypeMask &&
        elementType != null &&
        other.elementType != null) {
      TypeMask newElementType = elementType.union(other.elementType, domain);
      TypeMask newForwardTo = forwardTo.union(other.forwardTo, domain);
      return SetTypeMask(newForwardTo, null, null, newElementType);
    }
    return null;
  }

  @override
  bool operator ==(other) {
    if (identical(this, other)) return true;
    if (other is! SetTypeMask) return false;
    return super == other && elementType == other.elementType;
  }

  @override
  int get hashCode => Hashing.objectHash(elementType, super.hashCode);

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