// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_TORQUE_TYPE_ORACLE_H_
#define V8_TORQUE_TYPE_ORACLE_H_

#include <memory>

#include "src/torque/contextual.h"
#include "src/torque/declarable.h"
#include "src/torque/declarations.h"
#include "src/torque/types.h"
#include "src/torque/utils.h"

namespace v8 {
namespace internal {
namespace torque {

class TypeOracle : public ContextualClass<TypeOracle> {
 public:
  static const AbstractType* GetAbstractType(
      const Type* parent, std::string name, AbstractTypeFlags flags,
      std::string generated, const Type* non_constexpr_version,
      MaybeSpecializationKey specialized_from) {
    auto ptr = std::unique_ptr<AbstractType>(
        new AbstractType(parent, flags, std::move(name), std::move(generated),
                         non_constexpr_version, specialized_from));
    const AbstractType* result = ptr.get();
    if (non_constexpr_version) {
      DCHECK(ptr->IsConstexpr());
      non_constexpr_version->SetConstexprVersion(result);
    }
    Get().nominal_types_.push_back(std::move(ptr));
    return result;
  }

  static StructType* GetStructType(const StructDeclaration* decl,
                                   MaybeSpecializationKey specialized_from) {
    auto ptr = std::unique_ptr<StructType>(
        new StructType(CurrentNamespace(), decl, specialized_from));
    StructType* result = ptr.get();
    Get().aggregate_types_.push_back(std::move(ptr));
    return result;
  }

  static BitFieldStructType* GetBitFieldStructType(
      const Type* parent, const BitFieldStructDeclaration* decl) {
    auto ptr = std::unique_ptr<BitFieldStructType>(
        new BitFieldStructType(CurrentNamespace(), parent, decl));
    BitFieldStructType* result = ptr.get();
    Get().bit_field_struct_types_.push_back(std::move(ptr));
    return result;
  }

  static ClassType* GetClassType(const Type* parent, const std::string& name,
                                 ClassFlags flags, const std::string& generates,
                                 ClassDeclaration* decl,
                                 const TypeAlias* alias) {
    std::unique_ptr<ClassType> type(new ClassType(
        parent, CurrentNamespace(), name, flags, generates, decl, alias));
    ClassType* result = type.get();
    Get().aggregate_types_.push_back(std::move(type));
    return result;
  }

  static const BuiltinPointerType* GetBuiltinPointerType(
      TypeVector argument_types, const Type* return_type) {
    TypeOracle& self = Get();
    const Type* builtin_type = self.GetBuiltinType(BUILTIN_POINTER_TYPE_STRING);
    const BuiltinPointerType* result = self.function_pointer_types_.Add(
        BuiltinPointerType(builtin_type, argument_types, return_type,
                           self.all_builtin_pointer_types_.size()));
    if (result->function_pointer_type_id() ==
        self.all_builtin_pointer_types_.size()) {
      self.all_builtin_pointer_types_.push_back(result);
    }
    return result;
  }

  static const Type* GetGenericTypeInstance(GenericType* generic_type,
                                            TypeVector arg_types);

  static GenericType* GetReferenceGeneric(bool is_const) {
    return Declarations::LookupUniqueGenericType(
        QualifiedName({TORQUE_INTERNAL_NAMESPACE_STRING},
                      is_const ? CONST_REFERENCE_TYPE_STRING
                               : MUTABLE_REFERENCE_TYPE_STRING));
  }
  static GenericType* GetConstReferenceGeneric() {
    return GetReferenceGeneric(true);
  }
  static GenericType* GetMutableReferenceGeneric() {
    return GetReferenceGeneric(false);
  }

  static base::Optional<const Type*> MatchReferenceGeneric(
      const Type* reference_type, bool* is_const = nullptr);

  static GenericType* GetSliceGeneric() {
    return Declarations::LookupUniqueGenericType(
        QualifiedName({TORQUE_INTERNAL_NAMESPACE_STRING}, SLICE_TYPE_STRING));
  }

  static GenericType* GetWeakGeneric() {
    return Declarations::LookupGlobalUniqueGenericType(WEAK_TYPE_STRING);
  }

  static GenericType* GetSmiTaggedGeneric() {
    return Declarations::LookupGlobalUniqueGenericType(SMI_TAGGED_TYPE_STRING);
  }

  static const Type* GetReferenceType(const Type* referenced_type,
                                      bool is_const) {
    return GetGenericTypeInstance(GetReferenceGeneric(is_const),
                                  {referenced_type});
  }
  static const Type* GetConstReferenceType(const Type* referenced_type) {
    return GetReferenceType(referenced_type, true);
  }
  static const Type* GetMutableReferenceType(const Type* referenced_type) {
    return GetReferenceType(referenced_type, false);
  }

  static const Type* GetSliceType(const Type* referenced_type) {
    return GetGenericTypeInstance(GetSliceGeneric(), {referenced_type});
  }

  static const std::vector<const BuiltinPointerType*>&
  AllBuiltinPointerTypes() {
    return Get().all_builtin_pointer_types_;
  }

  static const Type* GetUnionType(UnionType type) {
    if (base::Optional<const Type*> single = type.GetSingleMember()) {
      return *single;
    }
    return Get().union_types_.Add(std::move(type));
  }

  static const Type* GetUnionType(const Type* a, const Type* b) {
    if (a->IsSubtypeOf(b)) return b;
    if (b->IsSubtypeOf(a)) return a;
    UnionType result = UnionType::FromType(a);
    result.Extend(b);
    return GetUnionType(std::move(result));
  }

  static const TopType* GetTopType(std::string reason,
                                   const Type* source_type) {
    std::unique_ptr<TopType> type(new TopType(std::move(reason), source_type));
    TopType* result = type.get();
    Get().top_types_.push_back(std::move(type));
    return result;
  }

  static const Type* GetArgumentsType() {
    return Get().GetBuiltinType(ARGUMENTS_TYPE_STRING);
  }

  static const Type* GetBoolType() {
    return Get().GetBuiltinType(BOOL_TYPE_STRING);
  }

  static const Type* GetConstexprBoolType() {
    return Get().GetBuiltinType(CONSTEXPR_BOOL_TYPE_STRING);
  }

  static const Type* GetConstexprStringType() {
    return Get().GetBuiltinType(CONSTEXPR_STRING_TYPE_STRING);
  }

  static const Type* GetConstexprIntPtrType() {
    return Get().GetBuiltinType(CONSTEXPR_INTPTR_TYPE_STRING);
  }

  static const Type* GetConstexprInstanceTypeType() {
    return Get().GetBuiltinType(CONSTEXPR_INSTANCE_TYPE_TYPE_STRING);
  }

  static const Type* GetVoidType() {
    return Get().GetBuiltinType(VOID_TYPE_STRING);
  }

  static const Type* GetRawPtrType() {
    return Get().GetBuiltinType(RAWPTR_TYPE_STRING);
  }

  static const Type* GetExternalPointerType() {
    return Get().GetBuiltinType(EXTERNALPTR_TYPE_STRING);
  }

  static const Type* GetMapType() {
    return Get().GetBuiltinType(MAP_TYPE_STRING);
  }

  static const Type* GetObjectType() {
    return Get().GetBuiltinType(OBJECT_TYPE_STRING);
  }

  static const Type* GetHeapObjectType() {
    return Get().GetBuiltinType(HEAP_OBJECT_TYPE_STRING);
  }

  static const Type* GetJSAnyType() {
    return Get().GetBuiltinType(JSANY_TYPE_STRING);
  }

  static const Type* GetJSObjectType() {
    return Get().GetBuiltinType(JSOBJECT_TYPE_STRING);
  }

  static const Type* GetTaggedType() {
    return Get().GetBuiltinType(TAGGED_TYPE_STRING);
  }

  static const Type* GetStrongTaggedType() {
    return Get().GetBuiltinType(STRONG_TAGGED_TYPE_STRING);
  }

  static const Type* GetUninitializedType() {
    return Get().GetBuiltinType(UNINITIALIZED_TYPE_STRING);
  }

  static const Type* GetUninitializedHeapObjectType() {
    return Get().GetBuiltinType(
        QualifiedName({TORQUE_INTERNAL_NAMESPACE_STRING},
                      UNINITIALIZED_HEAP_OBJECT_TYPE_STRING));
  }

  static const Type* GetSmiType() {
    return Get().GetBuiltinType(SMI_TYPE_STRING);
  }

  static const Type* GetConstStringType() {
    return Get().GetBuiltinType(CONST_STRING_TYPE_STRING);
  }

  static const Type* GetStringType() {
    return Get().GetBuiltinType(STRING_TYPE_STRING);
  }

  static const Type* GetNumberType() {
    return Get().GetBuiltinType(NUMBER_TYPE_STRING);
  }

  static const Type* GetIntPtrType() {
    return Get().GetBuiltinType(INTPTR_TYPE_STRING);
  }

  static const Type* GetUIntPtrType() {
    return Get().GetBuiltinType(UINTPTR_TYPE_STRING);
  }

  static const Type* GetInt32Type() {
    return Get().GetBuiltinType(INT32_TYPE_STRING);
  }

  static const Type* GetUint32Type() {
    return Get().GetBuiltinType(UINT32_TYPE_STRING);
  }

  static const Type* GetUint31Type() {
    return Get().GetBuiltinType(UINT31_TYPE_STRING);
  }

  static const Type* GetInt16Type() {
    return Get().GetBuiltinType(INT16_TYPE_STRING);
  }

  static const Type* GetUint16Type() {
    return Get().GetBuiltinType(UINT16_TYPE_STRING);
  }

  static const Type* GetInt8Type() {
    return Get().GetBuiltinType(INT8_TYPE_STRING);
  }

  static const Type* GetUint8Type() {
    return Get().GetBuiltinType(UINT8_TYPE_STRING);
  }

  static const Type* GetFloat64Type() {
    return Get().GetBuiltinType(FLOAT64_TYPE_STRING);
  }

  static const Type* GetFloat64OrHoleType() {
    return Get().GetBuiltinType(FLOAT64_OR_HOLE_TYPE_STRING);
  }

  static const Type* GetConstFloat64Type() {
    return Get().GetBuiltinType(CONST_FLOAT64_TYPE_STRING);
  }

  static const Type* GetNeverType() {
    return Get().GetBuiltinType(NEVER_TYPE_STRING);
  }

  static const Type* GetConstInt31Type() {
    return Get().GetBuiltinType(CONST_INT31_TYPE_STRING);
  }

  static const Type* GetConstInt32Type() {
    return Get().GetBuiltinType(CONST_INT32_TYPE_STRING);
  }

  static const Type* GetContextType() {
    return Get().GetBuiltinType(CONTEXT_TYPE_STRING);
  }

  static const Type* GetNoContextType() {
    return Get().GetBuiltinType(NO_CONTEXT_TYPE_STRING);
  }

  static const Type* GetNativeContextType() {
    return Get().GetBuiltinType(NATIVE_CONTEXT_TYPE_STRING);
  }

  static const Type* GetJSFunctionType() {
    return Get().GetBuiltinType(JS_FUNCTION_TYPE_STRING);
  }

  static const Type* GetUninitializedIteratorType() {
    return Get().GetBuiltinType(UNINITIALIZED_ITERATOR_TYPE_STRING);
  }

  static const Type* GetFixedArrayBaseType() {
    return Get().GetBuiltinType(FIXED_ARRAY_BASE_TYPE_STRING);
  }

  static base::Optional<const Type*> ImplicitlyConvertableFrom(
      const Type* to, const Type* from) {
    while (from != nullptr) {
      for (GenericCallable* from_constexpr :
           Declarations::LookupGeneric(kFromConstexprMacroName)) {
        if (base::Optional<const Callable*> specialization =
                from_constexpr->GetSpecialization({to, from})) {
          if ((*specialization)->signature().GetExplicitTypes() ==
              TypeVector{from}) {
            return from;
          }
        }
      }
      from = from->parent();
    }
    return base::nullopt;
  }

  static const std::vector<std::unique_ptr<AggregateType>>& GetAggregateTypes();
  static const std::vector<std::unique_ptr<BitFieldStructType>>&
  GetBitFieldStructTypes();

  // By construction, this list of all classes is topologically sorted w.r.t.
  // inheritance.
  static std::vector<const ClassType*> GetClasses();

  static void FinalizeAggregateTypes();

  static size_t FreshTypeId() { return Get().next_type_id_++; }

  static Namespace* CreateGenericTypeInstantiationNamespace();

 private:
  const Type* GetBuiltinType(const QualifiedName& name) {
    return Declarations::LookupGlobalType(name);
  }
  const Type* GetBuiltinType(const std::string& name) {
    return GetBuiltinType(QualifiedName(name));
  }

  Deduplicator<BuiltinPointerType> function_pointer_types_;
  std::vector<const BuiltinPointerType*> all_builtin_pointer_types_;
  Deduplicator<UnionType> union_types_;
  std::vector<std::unique_ptr<Type>> nominal_types_;
  std::vector<std::unique_ptr<AggregateType>> aggregate_types_;
  std::vector<std::unique_ptr<BitFieldStructType>> bit_field_struct_types_;
  std::vector<std::unique_ptr<Type>> top_types_;
  std::vector<std::unique_ptr<Namespace>>
      generic_type_instantiation_namespaces_;
  size_t next_type_id_ = 0;
};

}  // namespace torque
}  // namespace internal
}  // namespace v8

#endif  // V8_TORQUE_TYPE_ORACLE_H_
