// Copyright (c) 2017, 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 vm.metadata.inferred_type;

import 'package:kernel/ast.dart';

/// Metadata for annotating nodes with an inferred type information.
class InferredType {
  final Reference _concreteClassReference;
  final int _flags;

  static const int flagNullable = 1 << 0;
  static const int flagInt = 1 << 1;

  // For invocations: whether to use the unchecked entry-point.
  static const int flagSkipCheck = 1 << 2;

  // Entire list may be null if no type arguments were inferred.
  // Will always be null if `concreteClass` is null.
  //
  // Each component may be null if that particular type argument was not
  // inferred.
  //
  // Otherwise, a non-null type argument indicates that that particular type
  // argument (in the runtime type) is always exactly a particular `DartType`.
  final List<DartType> exactTypeArguments;

  InferredType(Class concreteClass, bool nullable, bool isInt,
      {List<DartType> exactTypeArguments, bool skipCheck: false})
      : this._byReference(
            getClassReference(concreteClass),
            (nullable ? flagNullable : 0) |
                (isInt ? flagInt : 0) |
                (skipCheck ? flagSkipCheck : 0),
            exactTypeArguments);

  InferredType._byReference(
      this._concreteClassReference, this._flags, this.exactTypeArguments) {
    assert(exactTypeArguments == null || _concreteClassReference != null);
  }

  Class get concreteClass => _concreteClassReference?.asClass;

  bool get nullable => (_flags & flagNullable) != 0;
  bool get isInt => (_flags & flagInt) != 0;
  bool get skipCheck => (_flags & flagSkipCheck) != 0;

  @override
  String toString() {
    final base =
        "${concreteClass != null ? concreteClass : (isInt ? 'int' : '!')}";
    final suffix = "${nullable ? '?' : ''}";
    String typeArgs = "";
    if (exactTypeArguments != null) {
      typeArgs =
          exactTypeArguments.map((t) => t != null ? "$t" : "?").join(", ");
      typeArgs = "<" + typeArgs + ">";
    }
    final skip = skipCheck ? " (skip check)" : "";
    return base + suffix + typeArgs + skip;
  }
}

/// Repository for [InferredType].
class InferredTypeMetadataRepository extends MetadataRepository<InferredType> {
  @override
  final String tag = 'vm.inferred-type.metadata';

  @override
  final Map<TreeNode, InferredType> mapping = <TreeNode, InferredType>{};

  @override
  void writeToBinary(InferredType metadata, Node node, BinarySink sink) {
    // TODO(sjindel/tfa): Implement serialization of type arguments when can use
    // them for optimizations.
    sink.writeNullAllowedCanonicalNameReference(
        getCanonicalNameOfClass(metadata.concreteClass));
    sink.writeByte(metadata._flags);
  }

  @override
  InferredType readFromBinary(Node node, BinarySource source) {
    // TODO(sjindel/tfa): Implement serialization of type arguments when can use
    // them for optimizations.
    final concreteClassReference =
        source.readCanonicalNameReference()?.getReference();
    final flags = source.readByte();
    return new InferredType._byReference(concreteClassReference, flags, null);
  }
}
