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

#include "src/torque/type-visitor.h"

#include "src/common/globals.h"
#include "src/torque/declarable.h"
#include "src/torque/global-context.h"
#include "src/torque/server-data.h"
#include "src/torque/type-inference.h"
#include "src/torque/type-oracle.h"

namespace v8 {
namespace internal {
namespace torque {

const Type* TypeVisitor::ComputeType(TypeDeclaration* decl,
                                     MaybeSpecializationKey specialized_from,
                                     Scope* specialization_requester) {
  SourcePosition requester_position = CurrentSourcePosition::Get();
  CurrentSourcePosition::Scope scope(decl->pos);
  Scope* current_scope = CurrentScope::Get();
  if (specialized_from) {
    current_scope = TypeOracle::CreateGenericTypeInstantiationNamespace();
    current_scope->SetSpecializationRequester(
        {requester_position, specialization_requester,
         Type::ComputeName(decl->name->value, specialized_from)});
  }
  CurrentScope::Scope new_current_scope_scope(current_scope);
  if (specialized_from) {
    auto& params = specialized_from->generic->generic_parameters();
    auto arg_types_iterator = specialized_from->specialized_types.begin();
    for (auto param : params) {
      TypeAlias* alias =
          Declarations::DeclareType(param.name, *arg_types_iterator);
      alias->SetIsUserDefined(false);
      arg_types_iterator++;
    }
  }

  switch (decl->kind) {
#define ENUM_ITEM(name)        \
  case AstNode::Kind::k##name: \
    return ComputeType(name::cast(decl), specialized_from);
    AST_TYPE_DECLARATION_NODE_KIND_LIST(ENUM_ITEM)
#undef ENUM_ITEM
    default:
      UNIMPLEMENTED();
  }
}

const Type* TypeVisitor::ComputeType(TypeAliasDeclaration* decl,
                                     MaybeSpecializationKey specialized_from) {
  const Type* type = ComputeType(decl->type);
  type->AddAlias(decl->name->value);
  return type;
}

namespace {
std::string ComputeGeneratesType(base::Optional<std::string> opt_gen,
                                 bool enforce_tnode_type) {
  if (!opt_gen) return "";
  const std::string& generates = *opt_gen;
  if (enforce_tnode_type) {
    if (generates.length() < 7 || generates.substr(0, 6) != "TNode<" ||
        generates.substr(generates.length() - 1, 1) != ">") {
      ReportError("generated type \"", generates,
                  "\" should be of the form \"TNode<...>\"");
    }
    return generates.substr(6, generates.length() - 7);
  }
  return generates;
}
}  // namespace

const AbstractType* TypeVisitor::ComputeType(
    AbstractTypeDeclaration* decl, MaybeSpecializationKey specialized_from) {
  std::string generates =
      ComputeGeneratesType(decl->generates, !decl->IsConstexpr());

  const Type* parent_type = nullptr;
  if (decl->extends) {
    parent_type = TypeVisitor::ComputeType(*decl->extends);
    if (parent_type->IsUnionType()) {
      // UnionType::IsSupertypeOf requires that types can only extend from non-
      // union types in order to work correctly.
      ReportError("type \"", decl->name->value,
                  "\" cannot extend a type union");
    }
  }

  if (decl->IsConstexpr() && decl->IsTransient()) {
    ReportError("cannot declare a transient type that is also constexpr");
  }

  const Type* non_constexpr_version = nullptr;
  if (decl->IsConstexpr()) {
    QualifiedName non_constexpr_name{GetNonConstexprName(decl->name->value)};
    if (auto type = Declarations::TryLookupType(non_constexpr_name)) {
      non_constexpr_version = *type;
    }
  }

  return TypeOracle::GetAbstractType(parent_type, decl->name->value,
                                     decl->flags, generates,
                                     non_constexpr_version, specialized_from);
}

void DeclareMethods(AggregateType* container_type,
                    const std::vector<Declaration*>& methods) {
  for (auto declaration : methods) {
    CurrentSourcePosition::Scope pos_scope(declaration->pos);
    TorqueMacroDeclaration* method =
        TorqueMacroDeclaration::DynamicCast(declaration);
    Signature signature = TypeVisitor::MakeSignature(method);
    signature.parameter_names.insert(
        signature.parameter_names.begin() + signature.implicit_count,
        MakeNode<Identifier>(kThisParameterName));
    Statement* body = *(method->body);
    const std::string& method_name(method->name->value);
    signature.parameter_types.types.insert(
        signature.parameter_types.types.begin() + signature.implicit_count,
        container_type);
    Declarations::CreateMethod(container_type, method_name, signature, body);
  }
}

const BitFieldStructType* TypeVisitor::ComputeType(
    BitFieldStructDeclaration* decl, MaybeSpecializationKey specialized_from) {
  CurrentSourcePosition::Scope position_scope(decl->pos);
  if (specialized_from.has_value()) {
    ReportError("Bitfield struct specialization is not supported");
  }
  const Type* parent = TypeVisitor::ComputeType(decl->parent);
  if (!IsAnyUnsignedInteger(parent)) {
    ReportError(
        "Bitfield struct must extend from an unsigned integer type, not ",
        parent->ToString());
  }
  auto opt_size = SizeOf(parent);
  if (!opt_size.has_value()) {
    ReportError("Cannot determine size of bitfield struct ", decl->name->value,
                " because of unsized parent type ", parent->ToString());
  }
  const size_t size = 8 * std::get<0>(*opt_size);  // Convert bytes to bits.
  BitFieldStructType* type = TypeOracle::GetBitFieldStructType(parent, decl);

  // Iterate through all of the declared fields, checking their validity and
  // registering them on the newly-constructed BitFieldStructType instance.
  int offset = 0;
  for (const auto& field : decl->fields) {
    CurrentSourcePosition::Scope field_position_scope(
        field.name_and_type.type->pos);
    const Type* field_type = TypeVisitor::ComputeType(field.name_and_type.type);
    if (!IsAllowedAsBitField(field_type)) {
      ReportError("Type not allowed as bitfield: ",
                  field.name_and_type.name->value);
    }

    // Compute the maximum number of bits that could be used for a field of this
    // type. Booleans are a special case, not included in SizeOf, because their
    // runtime size is 32 bits but they should only occupy 1 bit as a bitfield.
    size_t field_type_size = 0;
    if (field_type->IsSubtypeOf(TypeOracle::GetBoolType())) {
      field_type_size = 1;
    } else {
      auto opt_field_type_size = SizeOf(field_type);
      if (!opt_field_type_size.has_value()) {
        ReportError("Size unknown for type ", field_type->ToString());
      }
      field_type_size = 8 * std::get<0>(*opt_field_type_size);
    }

    if (field.num_bits < 1 ||
        static_cast<size_t>(field.num_bits) > field_type_size) {
      ReportError("Invalid number of bits for ",
                  field.name_and_type.name->value);
    }
    type->RegisterField({field.name_and_type.name->pos,
                         {field.name_and_type.name->value, field_type},
                         offset,
                         field.num_bits});
    offset += field.num_bits;
    if (static_cast<size_t>(offset) > size) {
      ReportError("Too many total bits in ", decl->name->value);
    }
  }

  return type;
}

const StructType* TypeVisitor::ComputeType(
    StructDeclaration* decl, MaybeSpecializationKey specialized_from) {
  StructType* struct_type = TypeOracle::GetStructType(decl, specialized_from);
  CurrentScope::Scope struct_namespace_scope(struct_type->nspace());
  CurrentSourcePosition::Scope position_activator(decl->pos);

  ResidueClass offset = 0;
  for (auto& field : decl->fields) {
    CurrentSourcePosition::Scope position_activator(
        field.name_and_type.type->pos);
    const Type* field_type = TypeVisitor::ComputeType(field.name_and_type.type);
    if (field_type->IsConstexpr()) {
      ReportError("struct field \"", field.name_and_type.name->value,
                  "\" carries constexpr type \"", *field_type, "\"");
    }
    Field f{field.name_and_type.name->pos,
            struct_type,
            base::nullopt,
            {field.name_and_type.name->value, field_type},
            offset.SingleValue(),
            false,
            field.const_qualified,
            false};
    auto optional_size = SizeOf(f.name_and_type.type);
    struct_type->RegisterField(f);
    // Offsets are assigned based on an assumption of no space between members.
    // This might lead to invalid alignment in some cases, but most structs are
    // never actually packed in memory together (they just represent a batch of
    // CSA TNode values that should be passed around together). For any struct
    // that is used as a class field, we verify its offsets when setting up the
    // class type.
    if (optional_size.has_value()) {
      size_t field_size = 0;
      std::tie(field_size, std::ignore) = *optional_size;
      offset += field_size;
    } else {
      // Structs may contain fields that aren't representable in packed form. If
      // so, the offset of subsequent fields are marked as invalid.
      offset = ResidueClass::Unknown();
    }
  }
  return struct_type;
}

const ClassType* TypeVisitor::ComputeType(
    ClassDeclaration* decl, MaybeSpecializationKey specialized_from) {
  // TODO(sigurds): Remove this hack by introducing a declarable for classes.
  const TypeAlias* alias =
      Declarations::LookupTypeAlias(QualifiedName(decl->name->value));
  DCHECK_EQ(*alias->delayed_, decl);
  ClassFlags flags = decl->flags;
  bool is_shape = flags & ClassFlag::kIsShape;
  std::string generates = decl->name->value;
  const Type* super_type = TypeVisitor::ComputeType(decl->super);
  if (is_shape) {
    if (!(flags & ClassFlag::kExtern)) {
      ReportError("Shapes must be extern, add \"extern\" to the declaration.");
    }
    if (flags & ClassFlag::kUndefinedLayout) {
      ReportError("Shapes need to define their layout.");
    }
    const ClassType* super_class = ClassType::DynamicCast(super_type);
    if (!super_class ||
        !super_class->IsSubtypeOf(TypeOracle::GetJSObjectType())) {
      Error("Shapes need to extend a subclass of ",
            *TypeOracle::GetJSObjectType())
          .Throw();
    }
    // Shapes use their super class in CSA code since they have incomplete
    // support for type-checks on the C++ side.
    generates = super_class->name();
  }
  if (super_type != TypeOracle::GetStrongTaggedType()) {
    const ClassType* super_class = ClassType::DynamicCast(super_type);
    if (!super_class) {
      ReportError(
          "class \"", decl->name->value,
          "\" must extend either StrongTagged or an already declared class");
    }
    if (super_class->HasUndefinedLayout() &&
        !(flags & ClassFlag::kUndefinedLayout)) {
      Error("Class \"", decl->name->value,
            "\" defines its layout but extends a class which does not")
          .Position(decl->pos);
    }
    if ((flags & ClassFlag::kExport) &&
        !(super_class->ShouldExport() || super_class->IsExtern())) {
      Error("cannot export class ", decl->name,
            " because superclass is neither @export or extern");
    }
  }
  if ((flags & ClassFlag::kGenerateBodyDescriptor ||
       flags & ClassFlag::kExport) &&
      flags & ClassFlag::kUndefinedLayout) {
    Error("Class \"", decl->name->value,
          "\" requires a layout but doesn't have one");
  }
  if (flags & ClassFlag::kCustomCppClass) {
    if (!(flags & ClassFlag::kExport)) {
      Error("Only exported classes can have a custom C++ class.");
    }
    if (flags & ClassFlag::kExtern) {
      Error("No need to specify ", ANNOTATION_CUSTOM_CPP_CLASS,
            ", extern classes always have a custom C++ class.");
    }
  }
  if (flags & ClassFlag::kExtern) {
    if (decl->generates) {
      bool enforce_tnode_type = true;
      generates = ComputeGeneratesType(decl->generates, enforce_tnode_type);
    }
    if (flags & ClassFlag::kExport) {
      Error("cannot export a class that is marked extern");
    }
  } else {
    if (decl->generates) {
      ReportError("Only extern classes can specify a generated type.");
    }
    if (super_type != TypeOracle::GetStrongTaggedType()) {
      if (flags & ClassFlag::kUndefinedLayout) {
        Error("non-external classes must have defined layouts");
      }
    }
    flags = flags | ClassFlag::kGeneratePrint | ClassFlag::kGenerateVerify |
            ClassFlag::kGenerateBodyDescriptor;
  }
  if (!(flags & ClassFlag::kExtern) &&
      (flags & ClassFlag::kHasSameInstanceTypeAsParent)) {
    Error("non-extern Torque-defined classes must have unique instance types");
  }
  if ((flags & ClassFlag::kHasSameInstanceTypeAsParent) &&
      !(flags & ClassFlag::kDoNotGenerateCast || flags & ClassFlag::kIsShape)) {
    Error(
        "classes that inherit their instance type must be annotated with "
        "@doNotGenerateCast");
  }

  return TypeOracle::GetClassType(super_type, decl->name->value, flags,
                                  generates, decl, alias);
}

const Type* TypeVisitor::ComputeType(TypeExpression* type_expression) {
  if (auto* basic = BasicTypeExpression::DynamicCast(type_expression)) {
    QualifiedName qualified_name{basic->namespace_qualification, basic->name};
    auto& args = basic->generic_arguments;
    const Type* type;
    SourcePosition pos = SourcePosition::Invalid();

    if (args.empty()) {
      auto* alias = Declarations::LookupTypeAlias(qualified_name);
      type = alias->type();
      pos = alias->GetDeclarationPosition();
    } else {
      auto* generic_type =
          Declarations::LookupUniqueGenericType(qualified_name);
      type = TypeOracle::GetGenericTypeInstance(generic_type,
                                                ComputeTypeVector(args));
      pos = generic_type->declaration()->name->pos;
    }

    if (GlobalContext::collect_language_server_data()) {
      LanguageServerData::AddDefinition(type_expression->pos, pos);
    }
    return type;

  } else if (auto* union_type =
                 UnionTypeExpression::DynamicCast(type_expression)) {
    return TypeOracle::GetUnionType(ComputeType(union_type->a),
                                    ComputeType(union_type->b));
  } else if (auto* function_type_exp =
                 FunctionTypeExpression::DynamicCast(type_expression)) {
    TypeVector argument_types;
    for (TypeExpression* type_exp : function_type_exp->parameters) {
      argument_types.push_back(ComputeType(type_exp));
    }
    return TypeOracle::GetBuiltinPointerType(
        argument_types, ComputeType(function_type_exp->return_type));
  } else {
    auto* precomputed = PrecomputedTypeExpression::cast(type_expression);
    return precomputed->type;
  }
}

Signature TypeVisitor::MakeSignature(const CallableDeclaration* declaration) {
  LabelDeclarationVector definition_vector;
  for (const auto& label : declaration->labels) {
    LabelDeclaration def = {label.name, ComputeTypeVector(label.types)};
    definition_vector.push_back(def);
  }
  base::Optional<std::string> arguments_variable;
  if (declaration->parameters.has_varargs)
    arguments_variable = declaration->parameters.arguments_variable;
  Signature result{declaration->parameters.names,
                   arguments_variable,
                   {ComputeTypeVector(declaration->parameters.types),
                    declaration->parameters.has_varargs},
                   declaration->parameters.implicit_count,
                   ComputeType(declaration->return_type),
                   definition_vector,
                   declaration->transitioning};
  return result;
}

void TypeVisitor::VisitClassFieldsAndMethods(
    ClassType* class_type, const ClassDeclaration* class_declaration) {
  const ClassType* super_class = class_type->GetSuperClass();
  ResidueClass class_offset = 0;
  size_t header_size = 0;
  if (super_class) {
    class_offset = super_class->size();
    header_size = super_class->header_size();
  }

  for (const ClassFieldExpression& field_expression :
       class_declaration->fields) {
    CurrentSourcePosition::Scope position_activator(
        field_expression.name_and_type.type->pos);
    const Type* field_type = ComputeType(field_expression.name_and_type.type);
    if (class_type->IsShape()) {
      if (!field_type->IsSubtypeOf(TypeOracle::GetObjectType())) {
        ReportError(
            "in-object properties only support subtypes of Object, but "
            "found type ",
            *field_type);
      }
      if (field_expression.weak) {
        ReportError("in-object properties cannot be weak");
      }
    }
    base::Optional<Expression*> array_length = field_expression.index;
    const Field& field = class_type->RegisterField(
        {field_expression.name_and_type.name->pos,
         class_type,
         array_length,
         {field_expression.name_and_type.name->value, field_type},
         class_offset.SingleValue(),
         field_expression.weak,
         field_expression.const_qualified,
         field_expression.generate_verify});
    ResidueClass field_size = std::get<0>(field.GetFieldSizeInformation());
    if (field.index) {
      // Validate that a value at any index in a packed array is aligned
      // correctly, since it is possible to define a struct whose size is not a
      // multiple of its alignment.
      field.ValidateAlignment(class_offset +
                              field_size * ResidueClass::Unknown());

      if (auto literal = NumberLiteralExpression::DynamicCast(*field.index)) {
        size_t value = static_cast<size_t>(literal->number);
        if (value != literal->number) {
          Error("non-integral array length").Position(field.pos);
        }
        field_size *= value;
      } else {
        field_size *= ResidueClass::Unknown();
      }
    }
    field.ValidateAlignment(class_offset);
    class_offset += field_size;
    // In-object properties are not considered part of the header.
    if (class_offset.SingleValue() && !class_type->IsShape()) {
      header_size = *class_offset.SingleValue();
    }
    if (!field.index && !class_offset.SingleValue()) {
      Error("Indexed fields have to be at the end of the object")
          .Position(field.pos);
    }
  }
  DCHECK_GT(header_size, 0);
  class_type->header_size_ = header_size;
  class_type->size_ = class_offset;
  class_type->GenerateAccessors();
  DeclareMethods(class_type, class_declaration->methods);
}

void TypeVisitor::VisitStructMethods(
    StructType* struct_type, const StructDeclaration* struct_declaration) {
  DeclareMethods(struct_type, struct_declaration->methods);
}

const Type* TypeVisitor::ComputeTypeForStructExpression(
    TypeExpression* type_expression,
    const std::vector<const Type*>& term_argument_types) {
  auto* basic = BasicTypeExpression::DynamicCast(type_expression);
  if (!basic) {
    ReportError("expected basic type expression referring to struct");
  }

  QualifiedName qualified_name{basic->namespace_qualification, basic->name};
  base::Optional<GenericType*> maybe_generic_type =
      Declarations::TryLookupGenericType(qualified_name);

  StructDeclaration* decl =
      maybe_generic_type
          ? StructDeclaration::DynamicCast((*maybe_generic_type)->declaration())
          : nullptr;

  // Compute types of non-generic structs as usual
  if (!(maybe_generic_type && decl)) {
    const Type* type = ComputeType(type_expression);
    if (!type->IsStructType() && !type->IsBitFieldStructType()) {
      ReportError(*type,
                  " is not a struct or bitfield struct, but used like one");
    }
    return type;
  }

  auto generic_type = *maybe_generic_type;
  auto explicit_type_arguments = ComputeTypeVector(basic->generic_arguments);

  std::vector<TypeExpression*> term_parameters;
  auto& fields = decl->fields;
  term_parameters.reserve(fields.size());
  for (auto& field : fields) {
    term_parameters.push_back(field.name_and_type.type);
  }

  CurrentScope::Scope generic_scope(generic_type->ParentScope());
  TypeArgumentInference inference(
      generic_type->generic_parameters(), explicit_type_arguments,
      term_parameters,
      TransformVector<base::Optional<const Type*>>(term_argument_types));

  if (inference.HasFailed()) {
    ReportError("failed to infer type arguments for struct ", basic->name,
                " initialization: ", inference.GetFailureReason());
  }
  if (GlobalContext::collect_language_server_data()) {
    LanguageServerData::AddDefinition(type_expression->pos,
                                      generic_type->declaration()->name->pos);
  }
  return StructType::cast(
      TypeOracle::GetGenericTypeInstance(generic_type, inference.GetResult()));
}

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