// 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_TYPES_H_
#define V8_TORQUE_TYPES_H_

#include <algorithm>
#include <map>
#include <set>
#include <string>
#include <vector>

#include "src/base/optional.h"
#include "src/torque/ast.h"
#include "src/torque/constants.h"
#include "src/torque/source-positions.h"
#include "src/torque/utils.h"

namespace v8 {
namespace internal {
namespace torque {

class AggregateType;
struct Identifier;
class Macro;
class Method;
class StructType;
class ClassType;
class Value;
class Namespace;

class TypeBase {
 public:
  enum class Kind {
    kTopType,
    kAbstractType,
    kBuiltinPointerType,
    kReferenceType,
    kUnionType,
    kStructType,
    kClassType
  };
  virtual ~TypeBase() = default;
  bool IsTopType() const { return kind() == Kind::kTopType; }
  bool IsAbstractType() const { return kind() == Kind::kAbstractType; }
  bool IsBuiltinPointerType() const {
    return kind() == Kind::kBuiltinPointerType;
  }
  bool IsReferenceType() const { return kind() == Kind::kReferenceType; }
  bool IsUnionType() const { return kind() == Kind::kUnionType; }
  bool IsStructType() const { return kind() == Kind::kStructType; }
  bool IsClassType() const { return kind() == Kind::kClassType; }
  bool IsAggregateType() const { return IsStructType() || IsClassType(); }

 protected:
  explicit TypeBase(Kind kind) : kind_(kind) {}
  Kind kind() const { return kind_; }

 private:
  const Kind kind_;
};

#define DECLARE_TYPE_BOILERPLATE(x)                         \
  static x* cast(TypeBase* declarable) {                    \
    DCHECK(declarable->Is##x());                            \
    return static_cast<x*>(declarable);                     \
  }                                                         \
  static const x* cast(const TypeBase* declarable) {        \
    DCHECK(declarable->Is##x());                            \
    return static_cast<const x*>(declarable);               \
  }                                                         \
  static x* DynamicCast(TypeBase* declarable) {             \
    if (!declarable) return nullptr;                        \
    if (!declarable->Is##x()) return nullptr;               \
    return static_cast<x*>(declarable);                     \
  }                                                         \
  static const x* DynamicCast(const TypeBase* declarable) { \
    if (!declarable) return nullptr;                        \
    if (!declarable->Is##x()) return nullptr;               \
    return static_cast<const x*>(declarable);               \
  }

class V8_EXPORT_PRIVATE Type : public TypeBase {
 public:
  virtual bool IsSubtypeOf(const Type* supertype) const;

  std::string ToString() const;
  virtual std::string MangledName() const = 0;
  bool IsVoid() const { return IsAbstractName(VOID_TYPE_STRING); }
  bool IsNever() const { return IsAbstractName(NEVER_TYPE_STRING); }
  bool IsBool() const { return IsAbstractName(BOOL_TYPE_STRING); }
  bool IsConstexprBool() const {
    return IsAbstractName(CONSTEXPR_BOOL_TYPE_STRING);
  }
  bool IsVoidOrNever() const { return IsVoid() || IsNever(); }
  std::string GetGeneratedTypeName() const;
  std::string GetGeneratedTNodeTypeName() const;
  virtual bool IsConstexpr() const {
    if (parent()) DCHECK(!parent()->IsConstexpr());
    return false;
  }
  virtual bool IsTransient() const { return false; }
  virtual const Type* NonConstexprVersion() const { return this; }
  virtual const Type* ConstexprVersion() const { return nullptr; }
  base::Optional<const ClassType*> ClassSupertype() const;
  virtual std::vector<std::string> GetRuntimeTypes() const { return {}; }
  static const Type* CommonSupertype(const Type* a, const Type* b);
  void AddAlias(std::string alias) const { aliases_.insert(std::move(alias)); }

 protected:
  Type(TypeBase::Kind kind, const Type* parent)
      : TypeBase(kind), parent_(parent) {}
  const Type* parent() const { return parent_; }
  void set_parent(const Type* t) { parent_ = t; }
  int Depth() const;
  virtual std::string ToExplicitString() const = 0;
  virtual std::string GetGeneratedTypeNameImpl() const = 0;
  virtual std::string GetGeneratedTNodeTypeNameImpl() const = 0;

 private:
  bool IsAbstractName(const std::string& name) const;

  // If {parent_} is not nullptr, then this type is a subtype of {parent_}.
  const Type* parent_;
  mutable std::set<std::string> aliases_;
};

using TypeVector = std::vector<const Type*>;

inline size_t hash_value(const TypeVector& types) {
  size_t hash = 0;
  for (const Type* t : types) {
    hash = base::hash_combine(hash, t);
  }
  return hash;
}

struct NameAndType {
  std::string name;
  const Type* type;
};

std::ostream& operator<<(std::ostream& os, const NameAndType& name_and_type);

struct Field {
  // TODO(danno): This likely should be refactored, the handling of the types
  // using the universal grab-bag utility with std::tie, as well as the
  // reliance of string types is quite clunky.
  std::tuple<size_t, std::string> GetFieldSizeInformation() const;

  SourcePosition pos;
  const AggregateType* aggregate;
  base::Optional<const Field*> index;
  NameAndType name_and_type;
  size_t offset;
  bool is_weak;
  bool const_qualified;
  bool generate_verify;
};

std::ostream& operator<<(std::ostream& os, const Field& name_and_type);

class TopType final : public Type {
 public:
  DECLARE_TYPE_BOILERPLATE(TopType)
  std::string MangledName() const override { return "top"; }
  std::string GetGeneratedTypeNameImpl() const override { UNREACHABLE(); }
  std::string GetGeneratedTNodeTypeNameImpl() const override {
    return source_type_->GetGeneratedTNodeTypeName();
  }
  std::string ToExplicitString() const override {
    std::stringstream s;
    s << "inaccessible " + source_type_->ToString();
    return s.str();
  }

  const Type* source_type() const { return source_type_; }
  const std::string reason() const { return reason_; }

 private:
  friend class TypeOracle;
  explicit TopType(std::string reason, const Type* source_type)
      : Type(Kind::kTopType, nullptr),
        reason_(std::move(reason)),
        source_type_(source_type) {}
  std::string reason_;
  const Type* source_type_;
};

class AbstractType final : public Type {
 public:
  DECLARE_TYPE_BOILERPLATE(AbstractType)
  const std::string& name() const { return name_; }
  std::string ToExplicitString() const override { return name(); }
  std::string MangledName() const override {
    std::string str(name());
    std::replace(str.begin(), str.end(), ' ', '_');
    return "AT" + str;
  }
  std::string GetGeneratedTypeNameImpl() const override {
    return IsConstexpr() ? generated_type_
                         : "compiler::TNode<" + generated_type_ + ">";
  }
  std::string GetGeneratedTNodeTypeNameImpl() const override;
  bool IsConstexpr() const override {
    bool is_constexpr = non_constexpr_version_ != nullptr;
    DCHECK_EQ(is_constexpr, IsConstexprName(name()));
    return is_constexpr;
  }

  const Type* NonConstexprVersion() const override {
    if (non_constexpr_version_) return non_constexpr_version_;
    if (!IsConstexpr()) return this;
    return nullptr;
  }

  const AbstractType* ConstexprVersion() const override {
    if (constexpr_version_) return constexpr_version_;
    if (IsConstexpr()) return this;
    return nullptr;
  }

  std::vector<std::string> GetRuntimeTypes() const override { return {name()}; }

 private:
  friend class TypeOracle;
  AbstractType(const Type* parent, bool transient, const std::string& name,
               const std::string& generated_type,
               const Type* non_constexpr_version)
      : Type(Kind::kAbstractType, parent),
        transient_(transient),
        name_(name),
        generated_type_(generated_type),
        non_constexpr_version_(non_constexpr_version) {
    if (parent) DCHECK(parent->IsConstexpr() == IsConstexpr());
    DCHECK_EQ(!IsConstexprName(name), non_constexpr_version == nullptr);
    DCHECK_IMPLIES(IsConstexprName(name),
                   !non_constexpr_version->IsConstexpr());
  }

  void SetConstexprVersion(const AbstractType* type) const {
    DCHECK_EQ(GetConstexprName(name()), type->name());
    constexpr_version_ = type;
  }

  bool IsTransient() const override { return transient_; }

  bool transient_;
  const std::string name_;
  const std::string generated_type_;
  const Type* non_constexpr_version_;
  mutable const AbstractType* constexpr_version_ = nullptr;
};

// For now, builtin pointers are restricted to Torque-defined builtins.
class V8_EXPORT_PRIVATE BuiltinPointerType final : public Type {
 public:
  DECLARE_TYPE_BOILERPLATE(BuiltinPointerType)
  std::string ToExplicitString() const override;
  std::string MangledName() const override;
  std::string GetGeneratedTypeNameImpl() const override {
    return parent()->GetGeneratedTypeName();
  }
  std::string GetGeneratedTNodeTypeNameImpl() const override {
    return parent()->GetGeneratedTNodeTypeName();
  }

  const TypeVector& parameter_types() const { return parameter_types_; }
  const Type* return_type() const { return return_type_; }

  friend size_t hash_value(const BuiltinPointerType& p) {
    size_t result = base::hash_value(p.return_type_);
    for (const Type* parameter : p.parameter_types_) {
      result = base::hash_combine(result, parameter);
    }
    return result;
  }
  bool operator==(const BuiltinPointerType& other) const {
    return parameter_types_ == other.parameter_types_ &&
           return_type_ == other.return_type_;
  }
  size_t function_pointer_type_id() const { return function_pointer_type_id_; }

  std::vector<std::string> GetRuntimeTypes() const override { return {"Smi"}; }

 private:
  friend class TypeOracle;
  BuiltinPointerType(const Type* parent, TypeVector parameter_types,
                     const Type* return_type, size_t function_pointer_type_id)
      : Type(Kind::kBuiltinPointerType, parent),
        parameter_types_(parameter_types),
        return_type_(return_type),
        function_pointer_type_id_(function_pointer_type_id) {}

  const TypeVector parameter_types_;
  const Type* const return_type_;
  const size_t function_pointer_type_id_;
};

class ReferenceType final : public Type {
 public:
  DECLARE_TYPE_BOILERPLATE(ReferenceType)
  std::string MangledName() const override {
    return "RT" + referenced_type_->MangledName();
  }
  std::string ToExplicitString() const override {
    std::string s = referenced_type_->ToString();
    if (s.find(' ') != std::string::npos) {
      s = "(" + s + ")";
    }
    return "&" + s;
  }
  std::string GetGeneratedTypeNameImpl() const override {
    return "CodeStubAssembler::Reference";
  }
  std::string GetGeneratedTNodeTypeNameImpl() const override { UNREACHABLE(); }

  const Type* referenced_type() const { return referenced_type_; }

  friend size_t hash_value(const ReferenceType& p) {
    return base::hash_combine(static_cast<size_t>(Kind::kReferenceType),
                              p.referenced_type_);
  }
  bool operator==(const ReferenceType& other) const {
    return referenced_type_ == other.referenced_type_;
  }

 private:
  friend class TypeOracle;
  explicit ReferenceType(const Type* referenced_type)
      : Type(Kind::kReferenceType, nullptr),
        referenced_type_(referenced_type) {}

  const Type* const referenced_type_;
};

bool operator<(const Type& a, const Type& b);
struct TypeLess {
  bool operator()(const Type* const a, const Type* const b) const {
    return *a < *b;
  }
};

class V8_EXPORT_PRIVATE UnionType final : public Type {
 public:
  DECLARE_TYPE_BOILERPLATE(UnionType)
  std::string ToExplicitString() const override;
  std::string MangledName() const override;
  std::string GetGeneratedTypeNameImpl() const override {
    return "compiler::TNode<" + GetGeneratedTNodeTypeName() + ">";
  }
  std::string GetGeneratedTNodeTypeNameImpl() const override;

  friend size_t hash_value(const UnionType& p) {
    size_t result = 0;
    for (const Type* t : p.types_) {
      result = base::hash_combine(result, t);
    }
    return result;
  }
  bool operator==(const UnionType& other) const {
    return types_ == other.types_;
  }

  base::Optional<const Type*> GetSingleMember() const {
    if (types_.size() == 1) {
      DCHECK_EQ(*types_.begin(), parent());
      return *types_.begin();
    }
    return base::nullopt;
  }

  bool IsSubtypeOf(const Type* other) const override {
    for (const Type* member : types_) {
      if (!member->IsSubtypeOf(other)) return false;
    }
    return true;
  }

  bool IsSupertypeOf(const Type* other) const {
    for (const Type* member : types_) {
      if (other->IsSubtypeOf(member)) {
        return true;
      }
    }
    return false;
  }

  bool IsTransient() const override {
    for (const Type* member : types_) {
      if (member->IsTransient()) {
        return true;
      }
    }
    return false;
  }

  void Extend(const Type* t) {
    if (const UnionType* union_type = UnionType::DynamicCast(t)) {
      for (const Type* member : union_type->types_) {
        Extend(member);
      }
    } else {
      if (t->IsSubtypeOf(this)) return;
      set_parent(CommonSupertype(parent(), t));
      EraseIf(&types_,
              [&](const Type* member) { return member->IsSubtypeOf(t); });
      types_.insert(t);
    }
  }

  void Subtract(const Type* t);

  static UnionType FromType(const Type* t) {
    const UnionType* union_type = UnionType::DynamicCast(t);
    return union_type ? UnionType(*union_type) : UnionType(t);
  }

  std::vector<std::string> GetRuntimeTypes() const override {
    std::vector<std::string> result;
    for (const Type* member : types_) {
      std::vector<std::string> sub_result = member->GetRuntimeTypes();
      result.insert(result.end(), sub_result.begin(), sub_result.end());
    }
    return result;
  }

 private:
  explicit UnionType(const Type* t) : Type(Kind::kUnionType, t), types_({t}) {}
  void RecomputeParent();

  std::set<const Type*, TypeLess> types_;
};

const Type* SubtractType(const Type* a, const Type* b);

class AggregateType : public Type {
 public:
  DECLARE_TYPE_BOILERPLATE(AggregateType)
  std::string MangledName() const override { return name_; }
  std::string GetGeneratedTypeNameImpl() const override { UNREACHABLE(); }
  std::string GetGeneratedTNodeTypeNameImpl() const override { UNREACHABLE(); }

  virtual void Finalize() const = 0;

  virtual bool HasIndexedField() const { return false; }

  void SetFields(std::vector<Field> fields) { fields_ = std::move(fields); }
  const std::vector<Field>& fields() const {
    if (!is_finalized_) Finalize();
    return fields_;
  }
  bool HasField(const std::string& name) const;
  const Field& LookupField(const std::string& name) const;
  const std::string& name() const { return name_; }
  Namespace* nspace() const { return namespace_; }

  std::string GetGeneratedMethodName(const std::string& name) const {
    return "_method_" + name_ + "_" + name;
  }

  virtual const Field& RegisterField(Field field) {
    fields_.push_back(field);
    return fields_.back();
  }

  void RegisterMethod(Method* method) { methods_.push_back(method); }
  const std::vector<Method*>& Methods() const {
    if (!is_finalized_) Finalize();
    return methods_;
  }
  std::vector<Method*> Methods(const std::string& name) const;

  std::vector<const AggregateType*> GetHierarchy() const;
  std::vector<std::string> GetRuntimeTypes() const override { return {name_}; }

 protected:
  AggregateType(Kind kind, const Type* parent, Namespace* nspace,
                const std::string& name)
      : Type(kind, parent),
        is_finalized_(false),
        namespace_(nspace),
        name_(name) {}

  void CheckForDuplicateFields() const;
  // Use this lookup if you do not want to trigger finalization on this type.
  const Field& LookupFieldInternal(const std::string& name) const;

 protected:
  mutable bool is_finalized_;
  std::vector<Field> fields_;

 private:
  Namespace* namespace_;
  std::string name_;
  std::vector<Method*> methods_;
};

class StructType final : public AggregateType {
 public:
  DECLARE_TYPE_BOILERPLATE(StructType)
  std::string ToExplicitString() const override;
  std::string GetGeneratedTypeNameImpl() const override;
  std::string MangledName() const override {
    // TODO(gsps): Generate more readable mangled names
    std::string str(name());
    std::replace(str.begin(), str.end(), ',', '_');
    std::replace(str.begin(), str.end(), ' ', '_');
    std::replace(str.begin(), str.end(), '<', '_');
    std::replace(str.begin(), str.end(), '>', '_');
    return str;
  }

  static std::string ComputeName(const std::string& basename,
                                 const std::vector<const Type*>& args);

 private:
  friend class TypeOracle;
  StructType(Namespace* nspace, const std::string& name)
      : AggregateType(Kind::kStructType, nullptr, nspace, name) {}

  void Finalize() const override {
    is_finalized_ = true;
    CheckForDuplicateFields();
  }

  const std::string& GetStructName() const { return name(); }
};

class TypeAlias;

class ClassType final : public AggregateType {
 public:
  static constexpr ClassFlags kInternalFlags = ClassFlag::kHasIndexedField;

  DECLARE_TYPE_BOILERPLATE(ClassType)
  std::string ToExplicitString() const override;
  std::string GetGeneratedTypeNameImpl() const override;
  std::string GetGeneratedTNodeTypeNameImpl() const override;
  bool IsExtern() const { return flags_ & ClassFlag::kExtern; }
  bool ShouldGeneratePrint() const {
    return flags_ & ClassFlag::kGeneratePrint || !IsExtern();
  }
  bool ShouldGenerateVerify() const {
    return flags_ & ClassFlag::kGenerateVerify || !IsExtern();
  }
  bool IsTransient() const override { return flags_ & ClassFlag::kTransient; }
  bool IsAbstract() const { return flags_ & ClassFlag::kAbstract; }
  bool IsInstantiatedAbstractClass() const {
    return flags_ & ClassFlag::kInstantiatedAbstractClass;
  }
  bool HasSameInstanceTypeAsParent() const {
    return flags_ & ClassFlag::kHasSameInstanceTypeAsParent;
  }
  bool GenerateCppClassDefinitions() const {
    return flags_ & ClassFlag::kGenerateCppClassDefinitions || !IsExtern();
  }
  bool HasIndexedField() const override;
  size_t size() const { return size_; }
  const ClassType* GetSuperClass() const {
    if (parent() == nullptr) return nullptr;
    return parent()->IsClassType() ? ClassType::DynamicCast(parent()) : nullptr;
  }
  void SetSize(size_t size) { size_ = size; }
  void GenerateAccessors();
  bool AllowInstantiation() const;
  const Field& RegisterField(Field field) override {
    if (field.index) {
      flags_ |= ClassFlag::kHasIndexedField;
    }
    return AggregateType::RegisterField(field);
  }
  void Finalize() const override;

 private:
  friend class TypeOracle;
  friend class TypeVisitor;
  ClassType(const Type* parent, Namespace* nspace, const std::string& name,
            ClassFlags flags, const std::string& generates,
            const ClassDeclaration* decl, const TypeAlias* alias);

  size_t size_;
  mutable ClassFlags flags_;
  const std::string generates_;
  const ClassDeclaration* decl_;
  const TypeAlias* alias_;
};

inline std::ostream& operator<<(std::ostream& os, const Type& t) {
  os << t.ToString();
  return os;
}

class VisitResult {
 public:
  VisitResult() = default;
  VisitResult(const Type* type, const std::string& constexpr_value)
      : type_(type), constexpr_value_(constexpr_value) {
    DCHECK(type->IsConstexpr());
  }
  static VisitResult NeverResult();
  VisitResult(const Type* type, StackRange stack_range)
      : type_(type), stack_range_(stack_range) {
    DCHECK(!type->IsConstexpr());
  }
  const Type* type() const { return type_; }
  const std::string& constexpr_value() const { return *constexpr_value_; }
  const StackRange& stack_range() const { return *stack_range_; }
  void SetType(const Type* new_type) { type_ = new_type; }
  bool IsOnStack() const { return stack_range_ != base::nullopt; }
  bool operator==(const VisitResult& other) const {
    return type_ == other.type_ && constexpr_value_ == other.constexpr_value_ &&
           stack_range_ == other.stack_range_;
  }

 private:
  const Type* type_ = nullptr;
  base::Optional<std::string> constexpr_value_;
  base::Optional<StackRange> stack_range_;
};

VisitResult ProjectStructField(VisitResult structure,
                               const std::string& fieldname);

class VisitResultVector : public std::vector<VisitResult> {
 public:
  VisitResultVector() : std::vector<VisitResult>() {}
  VisitResultVector(std::initializer_list<VisitResult> init)
      : std::vector<VisitResult>(init) {}
  TypeVector ComputeTypeVector() const {
    TypeVector result;
    for (auto& visit_result : *this) {
      result.push_back(visit_result.type());
    }
    return result;
  }
};

std::ostream& operator<<(std::ostream& os, const TypeVector& types);

using NameAndTypeVector = std::vector<NameAndType>;

struct LabelDefinition {
  std::string name;
  NameAndTypeVector parameters;
};

using LabelDefinitionVector = std::vector<LabelDefinition>;

struct LabelDeclaration {
  Identifier* name;
  TypeVector types;
};

using LabelDeclarationVector = std::vector<LabelDeclaration>;

struct ParameterTypes {
  TypeVector types;
  bool var_args;
};

std::ostream& operator<<(std::ostream& os, const ParameterTypes& parameters);

enum class ParameterMode { kProcessImplicit, kIgnoreImplicit };

using NameVector = std::vector<Identifier*>;

struct Signature {
  Signature(NameVector n, base::Optional<std::string> arguments_variable,
            ParameterTypes p, size_t i, const Type* r, LabelDeclarationVector l)
      : parameter_names(std::move(n)),
        arguments_variable(arguments_variable),
        parameter_types(std::move(p)),
        implicit_count(i),
        return_type(r),
        labels(std::move(l)) {}
  Signature() : implicit_count(0), return_type(nullptr) {}
  const TypeVector& types() const { return parameter_types.types; }
  NameVector parameter_names;
  base::Optional<std::string> arguments_variable;
  ParameterTypes parameter_types;
  size_t implicit_count;
  size_t ExplicitCount() const { return types().size() - implicit_count; }
  const Type* return_type;
  LabelDeclarationVector labels;
  bool HasSameTypesAs(
      const Signature& other,
      ParameterMode mode = ParameterMode::kProcessImplicit) const;
  TypeVector GetImplicitTypes() const {
    return TypeVector(parameter_types.types.begin(),
                      parameter_types.types.begin() + implicit_count);
  }
  TypeVector GetExplicitTypes() const {
    return TypeVector(parameter_types.types.begin() + implicit_count,
                      parameter_types.types.end());
  }
};

void PrintSignature(std::ostream& os, const Signature& sig, bool with_names);
std::ostream& operator<<(std::ostream& os, const Signature& sig);

bool IsAssignableFrom(const Type* to, const Type* from);

TypeVector LowerType(const Type* type);
size_t LoweredSlotCount(const Type* type);
TypeVector LowerParameterTypes(const TypeVector& parameters);
TypeVector LowerParameterTypes(const ParameterTypes& parameter_types,
                               size_t vararg_count = 0);

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

#endif  // V8_TORQUE_TYPES_H_
