Commit 5bba6680 authored by Tobias Tebbi's avatar Tobias Tebbi Committed by Commit Bot

[torque] introduce generic abstract types

This expands the existing mechanism for generic structs to also cover
abstract types. This involves:
- Moving the SpecializationKey from StructType to Type, so that it's
  also available to AbstractType.
- Moving the generic parameters out of the StructDeclaration AST node
  and using the existing GenericDeclaration AST node for generic structs
  and abstract types too.
- The GenericStructType declarable gets generalized to GenericType.

This will be useful for defining a Weak<T> type for weak pointers.

Bug: v8:7793
Change-Id: I183b3a038a143cf0ae5888150104c4a025fd736c
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1859623
Commit-Queue: Tobias Tebbi <tebbi@chromium.org>
Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#64533}
parent 7df7efe1
......@@ -71,7 +71,8 @@ namespace torque {
#define AST_DECLARATION_NODE_KIND_LIST(V) \
AST_TYPE_DECLARATION_NODE_KIND_LIST(V) \
V(GenericDeclaration) \
V(GenericCallableDeclaration) \
V(GenericTypeDeclaration) \
V(SpecializationDeclaration) \
V(ExternConstDeclaration) \
V(NamespaceDeclaration) \
......@@ -1017,18 +1018,38 @@ struct ConstDeclaration : Declaration {
Expression* expression;
};
struct GenericDeclaration : Declaration {
DEFINE_AST_NODE_LEAF_BOILERPLATE(GenericDeclaration)
GenericDeclaration(SourcePosition pos,
std::vector<Identifier*> generic_parameters,
CallableDeclaration* declaration)
// The AST re-shuffles generics from the concrete syntax:
// Instead of the generic parameters being part of a normal declaration,
// a declaration with generic parameters gets wrapped in a generic declaration,
// which holds the generic parameters. This corresponds to how you write
// templates in C++, with the template parameters coming before the declaration.
struct GenericCallableDeclaration : Declaration {
DEFINE_AST_NODE_LEAF_BOILERPLATE(GenericCallableDeclaration)
GenericCallableDeclaration(SourcePosition pos,
std::vector<Identifier*> generic_parameters,
CallableDeclaration* declaration)
: Declaration(kKind, pos),
generic_parameters(std::move(generic_parameters)),
declaration(declaration) {}
std::vector<Identifier*> generic_parameters;
CallableDeclaration* declaration;
};
struct GenericTypeDeclaration : Declaration {
DEFINE_AST_NODE_LEAF_BOILERPLATE(GenericTypeDeclaration)
GenericTypeDeclaration(SourcePosition pos,
std::vector<Identifier*> generic_parameters,
TypeDeclaration* declaration)
: Declaration(kKind, pos),
generic_parameters(std::move(generic_parameters)),
declaration(declaration) {}
std::vector<Identifier*> generic_parameters;
TypeDeclaration* declaration;
};
struct SpecializationDeclaration : CallableDeclaration {
DEFINE_AST_NODE_LEAF_BOILERPLATE(SpecializationDeclaration)
SpecializationDeclaration(SourcePosition pos, bool transitioning,
......@@ -1063,19 +1084,14 @@ struct StructDeclaration : TypeDeclaration {
DEFINE_AST_NODE_LEAF_BOILERPLATE(StructDeclaration)
StructDeclaration(SourcePosition pos, StructFlags flags, Identifier* name,
std::vector<Declaration*> methods,
std::vector<StructFieldExpression> fields,
std::vector<Identifier*> generic_parameters)
std::vector<StructFieldExpression> fields)
: TypeDeclaration(kKind, pos, name),
flags(flags),
methods(std::move(methods)),
fields(std::move(fields)),
generic_parameters(std::move(generic_parameters)) {}
fields(std::move(fields)) {}
StructFlags flags;
std::vector<Declaration*> methods;
std::vector<StructFieldExpression> fields;
std::vector<Identifier*> generic_parameters;
bool IsGeneric() const { return !generic_parameters.empty(); }
};
struct ClassBody : AstNode {
......
......@@ -53,7 +53,8 @@ static const char* const CONST_FLOAT64_TYPE_STRING = "constexpr float64";
static const char* const TORQUE_INTERNAL_NAMESPACE_STRING = "torque_internal";
static const char* const REFERENCE_TYPE_STRING = "Reference";
static const char* const SLICE_TYPE_STRING = "Slice";
static const char* const STRUCT_NAMESPACE_STRING = "_struct";
static const char* const GENERIC_TYPE_INSTANTIATION_NAMESPACE_STRING =
"_generic_type_instantiation_namespace";
static const char* const ANNOTATION_GENERATE_PRINT = "@generatePrint";
static const char* const ANNOTATION_NO_VERIFIER = "@noVerifier";
......
......@@ -56,7 +56,7 @@ std::ostream& operator<<(std::ostream& os, const RuntimeFunction& b) {
return os;
}
std::ostream& operator<<(std::ostream& os, const Generic& g) {
std::ostream& operator<<(std::ostream& os, const GenericCallable& g) {
os << "generic " << g.name() << "<";
PrintCommaSeparatedList(
os, g.generic_parameters(),
......@@ -66,7 +66,7 @@ std::ostream& operator<<(std::ostream& os, const Generic& g) {
return os;
}
TypeArgumentInference Generic::InferSpecializationTypes(
TypeArgumentInference GenericCallable::InferSpecializationTypes(
const TypeVector& explicit_specialization_types,
const TypeVector& arguments) {
size_t implicit_count = declaration()->parameters.implicit_count;
......@@ -82,7 +82,7 @@ TypeArgumentInference Generic::InferSpecializationTypes(
return inference;
}
base::Optional<Statement*> Generic::CallableBody() {
base::Optional<Statement*> GenericCallable::CallableBody() {
if (auto* decl = TorqueMacroDeclaration::DynamicCast(declaration())) {
return decl->body;
} else if (auto* decl =
......
......@@ -50,8 +50,8 @@ class Declarable {
kBuiltin,
kRuntimeFunction,
kIntrinsic,
kGeneric,
kGenericStructType,
kGenericCallable,
kGenericType,
kTypeAlias,
kExternConstant,
kNamespaceConstant
......@@ -65,8 +65,8 @@ class Declarable {
bool IsIntrinsic() const { return kind() == kIntrinsic; }
bool IsBuiltin() const { return kind() == kBuiltin; }
bool IsRuntimeFunction() const { return kind() == kRuntimeFunction; }
bool IsGeneric() const { return kind() == kGeneric; }
bool IsGenericStructType() const { return kind() == kGenericStructType; }
bool IsGenericCallable() const { return kind() == kGenericCallable; }
bool IsGenericType() const { return kind() == kGenericType; }
bool IsTypeAlias() const { return kind() == kTypeAlias; }
bool IsExternConstant() const { return kind() == kExternConstant; }
bool IsNamespaceConstant() const { return kind() == kNamespaceConstant; }
......@@ -472,9 +472,9 @@ class SpecializationMap {
Map specializations_;
};
class Generic : public Declarable {
class GenericCallable : public Declarable {
public:
DECLARE_DECLARABLE_BOILERPLATE(Generic, generic)
DECLARE_DECLARABLE_BOILERPLATE(GenericCallable, generic_callable)
const std::string& name() const { return name_; }
CallableDeclaration* declaration() const {
......@@ -493,40 +493,44 @@ class Generic : public Declarable {
private:
friend class Declarations;
Generic(const std::string& name, GenericDeclaration* generic_declaration)
: Declarable(Declarable::kGeneric),
GenericCallable(const std::string& name,
GenericCallableDeclaration* generic_declaration)
: Declarable(Declarable::kGenericCallable),
name_(name),
generic_declaration_(generic_declaration) {}
generic_declaration_(generic_declaration) {
DCHECK(!generic_declaration->generic_parameters.empty());
}
std::string name_;
GenericDeclaration* generic_declaration_;
GenericCallableDeclaration* generic_declaration_;
SpecializationMap<Callable> specializations_;
};
class GenericStructType : public Declarable {
class GenericType : public Declarable {
public:
DECLARE_DECLARABLE_BOILERPLATE(GenericStructType, generic_type)
DECLARE_DECLARABLE_BOILERPLATE(GenericType, generic_type)
const std::string& name() const { return name_; }
StructDeclaration* declaration() const { return declaration_; }
const std::vector<Identifier*>& generic_parameters() const {
return declaration_->generic_parameters;
TypeDeclaration* declaration() const {
return generic_declaration_->declaration;
}
SpecializationMap<const StructType>& specializations() {
return specializations_;
const std::vector<Identifier*>& generic_parameters() const {
return generic_declaration_->generic_parameters;
}
SpecializationMap<const Type>& specializations() { return specializations_; }
private:
friend class Declarations;
GenericStructType(const std::string& name, StructDeclaration* declaration)
: Declarable(Declarable::kGenericStructType),
GenericType(const std::string& name,
GenericTypeDeclaration* generic_declaration)
: Declarable(Declarable::kGenericType),
name_(name),
declaration_(declaration) {
DCHECK_GT(declaration->generic_parameters.size(), 0);
generic_declaration_(generic_declaration) {
DCHECK(!generic_declaration->generic_parameters.empty());
}
std::string name_;
StructDeclaration* declaration_;
SpecializationMap<const StructType> specializations_;
GenericTypeDeclaration* generic_declaration_;
SpecializationMap<const Type> specializations_;
};
class TypeAlias : public Declarable {
......@@ -572,7 +576,7 @@ class TypeAlias : public Declarable {
std::ostream& operator<<(std::ostream& os, const Callable& m);
std::ostream& operator<<(std::ostream& os, const Builtin& b);
std::ostream& operator<<(std::ostream& os, const RuntimeFunction& b);
std::ostream& operator<<(std::ostream& os, const Generic& g);
std::ostream& operator<<(std::ostream& os, const GenericCallable& g);
#undef DECLARE_DECLARABLE_BOILERPLATE
......
......@@ -32,8 +32,11 @@ void PredeclarationVisitor::Predeclare(Declaration* decl) {
#undef ENUM_ITEM
case AstNode::Kind::kNamespaceDeclaration:
return Predeclare(NamespaceDeclaration::cast(decl));
case AstNode::Kind::kGenericDeclaration:
return Predeclare(GenericDeclaration::cast(decl));
case AstNode::Kind::kGenericCallableDeclaration:
return Predeclare(GenericCallableDeclaration::cast(decl));
case AstNode::Kind::kGenericTypeDeclaration:
return Predeclare(GenericTypeDeclaration::cast(decl));
default:
// Only processes type declaration nodes, namespaces and generics.
break;
......@@ -172,15 +175,15 @@ void DeclarationVisitor::Visit(ConstDeclaration* decl) {
}
void DeclarationVisitor::Visit(SpecializationDeclaration* decl) {
std::vector<Generic*> generic_list =
std::vector<GenericCallable*> generic_list =
Declarations::LookupGeneric(decl->name->value);
// Find the matching generic specialization based on the concrete parameter
// list.
Generic* matching_generic = nullptr;
GenericCallable* matching_generic = nullptr;
Signature signature_with_types = TypeVisitor::MakeSignature(decl);
for (Generic* generic : generic_list) {
for (GenericCallable* generic : generic_list) {
Signature generic_signature_with_types =
MakeSpecializedSignature(SpecializationKey<Generic>{
MakeSpecializedSignature(SpecializationKey<GenericCallable>{
generic, TypeVisitor::ComputeTypeVector(decl->generic_parameters)});
if (signature_with_types.HasSameTypesAs(generic_signature_with_types,
ParameterMode::kIgnoreImplicit)) {
......@@ -206,9 +209,9 @@ void DeclarationVisitor::Visit(SpecializationDeclaration* decl) {
stream << "specialization signature:";
stream << "\n " << signature_with_types;
stream << "\ncandidates are:";
for (Generic* generic : generic_list) {
for (GenericCallable* generic : generic_list) {
stream << "\n "
<< MakeSpecializedSignature(SpecializationKey<Generic>{
<< MakeSpecializedSignature(SpecializationKey<GenericCallable>{
generic,
TypeVisitor::ComputeTypeVector(decl->generic_parameters)});
}
......@@ -222,9 +225,9 @@ void DeclarationVisitor::Visit(SpecializationDeclaration* decl) {
CallableDeclaration* generic_declaration = matching_generic->declaration();
Specialize(SpecializationKey<Generic>{matching_generic,
TypeVisitor::ComputeTypeVector(
decl->generic_parameters)},
Specialize(SpecializationKey<GenericCallable>{matching_generic,
TypeVisitor::ComputeTypeVector(
decl->generic_parameters)},
generic_declaration, decl, decl->body, decl->pos);
}
......@@ -245,7 +248,7 @@ void DeclarationVisitor::Visit(CppIncludeDeclaration* decl) {
}
void DeclarationVisitor::DeclareSpecializedTypes(
const SpecializationKey<Generic>& key) {
const SpecializationKey<GenericCallable>& key) {
size_t i = 0;
const std::size_t generic_parameter_count =
key.generic->generic_parameters().size();
......@@ -265,7 +268,7 @@ void DeclarationVisitor::DeclareSpecializedTypes(
}
Signature DeclarationVisitor::MakeSpecializedSignature(
const SpecializationKey<Generic>& key) {
const SpecializationKey<GenericCallable>& key) {
CurrentScope::Scope generic_scope(key.generic->ParentScope());
// Create a temporary fake-namespace just to temporarily declare the
// specialization aliases for the generic types to create a signature.
......@@ -276,7 +279,7 @@ Signature DeclarationVisitor::MakeSpecializedSignature(
}
Callable* DeclarationVisitor::SpecializeImplicit(
const SpecializationKey<Generic>& key) {
const SpecializationKey<GenericCallable>& key) {
base::Optional<Statement*> body = key.generic->CallableBody();
if (!body && IntrinsicDeclaration::DynamicCast(key.generic->declaration()) ==
nullptr) {
......@@ -294,7 +297,8 @@ Callable* DeclarationVisitor::SpecializeImplicit(
}
Callable* DeclarationVisitor::Specialize(
const SpecializationKey<Generic>& key, CallableDeclaration* declaration,
const SpecializationKey<GenericCallable>& key,
CallableDeclaration* declaration,
base::Optional<const SpecializationDeclaration*> explicit_specialization,
base::Optional<Statement*> body, SourcePosition position) {
CurrentSourcePosition::Scope pos_scope(position);
......
......@@ -38,14 +38,15 @@ class PredeclarationVisitor {
Declarations::PredeclareTypeAlias(decl->name, decl, false);
}
static void Predeclare(StructDeclaration* decl) {
if (decl->IsGeneric()) {
Declarations::DeclareGenericStructType(decl->name->value, decl);
} else {
Declarations::PredeclareTypeAlias(decl->name, decl, false);
}
Declarations::PredeclareTypeAlias(decl->name, decl, false);
}
static void Predeclare(GenericTypeDeclaration* generic_decl) {
Declarations::DeclareGenericType(generic_decl->declaration->name->value,
generic_decl);
}
static void Predeclare(GenericDeclaration* decl) {
Declarations::DeclareGeneric(decl->declaration->name->value, decl);
static void Predeclare(GenericCallableDeclaration* generic_decl) {
Declarations::DeclareGenericCallable(generic_decl->declaration->name->value,
generic_decl);
}
};
......@@ -67,9 +68,7 @@ class DeclarationVisitor {
Declarations::LookupType(decl->name);
}
static void Visit(StructDeclaration* decl) {
if (!decl->IsGeneric()) {
Declarations::LookupType(decl->name);
}
Declarations::LookupType(decl->name);
}
static Builtin* CreateBuiltin(BuiltinDeclaration* decl,
......@@ -85,7 +84,10 @@ class DeclarationVisitor {
static void Visit(IntrinsicDeclaration* decl);
static void Visit(ConstDeclaration* decl);
static void Visit(GenericDeclaration* decl) {
static void Visit(GenericCallableDeclaration* decl) {
// The PredeclarationVisitor already handled this case.
}
static void Visit(GenericTypeDeclaration* decl) {
// The PredeclarationVisitor already handled this case.
}
static void Visit(SpecializationDeclaration* decl);
......@@ -93,15 +95,18 @@ class DeclarationVisitor {
static void Visit(CppIncludeDeclaration* decl);
static Signature MakeSpecializedSignature(
const SpecializationKey<Generic>& key);
static Callable* SpecializeImplicit(const SpecializationKey<Generic>& key);
const SpecializationKey<GenericCallable>& key);
static Callable* SpecializeImplicit(
const SpecializationKey<GenericCallable>& key);
static Callable* Specialize(
const SpecializationKey<Generic>& key, CallableDeclaration* declaration,
const SpecializationKey<GenericCallable>& key,
CallableDeclaration* declaration,
base::Optional<const SpecializationDeclaration*> explicit_specialization,
base::Optional<Statement*> body, SourcePosition position);
private:
static void DeclareSpecializedTypes(const SpecializationKey<Generic>& key);
static void DeclareSpecializedTypes(
const SpecializationKey<GenericCallable>& key);
};
} // namespace torque
......
......@@ -120,27 +120,28 @@ base::Optional<Builtin*> Declarations::TryLookupBuiltin(
return EnsureUnique(builtins, name.name, "builtin");
}
std::vector<Generic*> Declarations::LookupGeneric(const std::string& name) {
return EnsureNonempty(FilterDeclarables<Generic>(Lookup(QualifiedName(name))),
name, "generic");
std::vector<GenericCallable*> Declarations::LookupGeneric(
const std::string& name) {
return EnsureNonempty(
FilterDeclarables<GenericCallable>(Lookup(QualifiedName(name))), name,
"generic callable");
}
Generic* Declarations::LookupUniqueGeneric(const QualifiedName& name) {
return EnsureUnique(FilterDeclarables<Generic>(Lookup(name)), name,
"generic");
GenericCallable* Declarations::LookupUniqueGeneric(const QualifiedName& name) {
return EnsureUnique(FilterDeclarables<GenericCallable>(Lookup(name)), name,
"generic callable");
}
GenericStructType* Declarations::LookupUniqueGenericStructType(
const QualifiedName& name) {
return EnsureUnique(FilterDeclarables<GenericStructType>(Lookup(name)), name,
"generic struct");
GenericType* Declarations::LookupUniqueGenericType(const QualifiedName& name) {
return EnsureUnique(FilterDeclarables<GenericType>(Lookup(name)), name,
"generic type");
}
base::Optional<GenericStructType*> Declarations::TryLookupGenericStructType(
base::Optional<GenericType*> Declarations::TryLookupGenericType(
const QualifiedName& name) {
std::vector<GenericStructType*> results = TryLookup<GenericStructType>(name);
std::vector<GenericType*> results = TryLookup<GenericType>(name);
if (results.empty()) return base::nullopt;
return EnsureUnique(results, name.name, "generic struct");
return EnsureUnique(results, name.name, "generic type");
}
Namespace* Declarations::DeclareNamespace(const std::string& name) {
......@@ -279,15 +280,16 @@ NamespaceConstant* Declarations::DeclareNamespaceConstant(Identifier* name,
return result;
}
Generic* Declarations::DeclareGeneric(const std::string& name,
GenericDeclaration* generic) {
return Declare(name, std::unique_ptr<Generic>(new Generic(name, generic)));
GenericCallable* Declarations::DeclareGenericCallable(
const std::string& name, GenericCallableDeclaration* ast_node) {
return Declare(name, std::unique_ptr<GenericCallable>(
new GenericCallable(name, ast_node)));
}
GenericStructType* Declarations::DeclareGenericStructType(
const std::string& name, StructDeclaration* decl) {
return Declare(name, std::unique_ptr<GenericStructType>(
new GenericStructType(name, decl)));
GenericType* Declarations::DeclareGenericType(
const std::string& name, GenericTypeDeclaration* ast_node) {
return Declare(name,
std::unique_ptr<GenericType>(new GenericType(name, ast_node)));
}
std::string Declarations::GetGeneratedCallableName(
......
......@@ -72,12 +72,11 @@ class Declarations {
const TypeVector& types);
static base::Optional<Builtin*> TryLookupBuiltin(const QualifiedName& name);
static std::vector<Generic*> LookupGeneric(const std::string& name);
static Generic* LookupUniqueGeneric(const QualifiedName& name);
static std::vector<GenericCallable*> LookupGeneric(const std::string& name);
static GenericCallable* LookupUniqueGeneric(const QualifiedName& name);
static GenericStructType* LookupUniqueGenericStructType(
const QualifiedName& name);
static base::Optional<GenericStructType*> TryLookupGenericStructType(
static GenericType* LookupUniqueGenericType(const QualifiedName& name);
static base::Optional<GenericType*> TryLookupGenericType(
const QualifiedName& name);
static Namespace* DeclareNamespace(const std::string& name);
......@@ -128,10 +127,10 @@ class Declarations {
const Type* type,
Expression* body);
static Generic* DeclareGeneric(const std::string& name,
GenericDeclaration* generic);
static GenericStructType* DeclareGenericStructType(const std::string& name,
StructDeclaration* decl);
static GenericCallable* DeclareGenericCallable(
const std::string& name, GenericCallableDeclaration* ast_node);
static GenericType* DeclareGenericType(const std::string& name,
GenericTypeDeclaration* ast_node);
template <class T>
static T* Declare(const std::string& name, T* d) {
......
......@@ -1533,12 +1533,13 @@ std::vector<std::string> ImplementationVisitor::GenerateFunctionDeclaration(
namespace {
void FailCallableLookup(const std::string& reason, const QualifiedName& name,
const TypeVector& parameter_types,
const std::vector<Binding<LocalLabel>*>& labels,
const std::vector<Signature>& candidates,
const std::vector<std::tuple<Generic*, const char*>>
inapplicable_generics) {
void FailCallableLookup(
const std::string& reason, const QualifiedName& name,
const TypeVector& parameter_types,
const std::vector<Binding<LocalLabel>*>& labels,
const std::vector<Signature>& candidates,
const std::vector<std::tuple<GenericCallable*, const char*>>
inapplicable_generics) {
std::stringstream stream;
stream << "\n" << reason << ": \n " << name << "(" << parameter_types << ")";
if (labels.size() != 0) {
......@@ -1555,7 +1556,7 @@ void FailCallableLookup(const std::string& reason, const QualifiedName& name,
if (inapplicable_generics.size() != 0) {
stream << "\nfailed to instantiate all of these generic declarations:";
for (auto& failure : inapplicable_generics) {
Generic* generic;
GenericCallable* generic;
const char* reason;
std::tie(generic, reason) = failure;
stream << "\n " << generic->name() << " defined at "
......@@ -1565,7 +1566,8 @@ void FailCallableLookup(const std::string& reason, const QualifiedName& name,
ReportError(stream.str());
}
Callable* GetOrCreateSpecialization(const SpecializationKey<Generic>& key) {
Callable* GetOrCreateSpecialization(
const SpecializationKey<GenericCallable>& key) {
if (base::Optional<Callable*> specialization =
key.generic->specializations().Get(key.specialized_types)) {
return *specialization;
......@@ -1621,9 +1623,9 @@ Callable* ImplementationVisitor::LookupCallable(
std::vector<Declarable*> overloads;
std::vector<Signature> overload_signatures;
std::vector<std::tuple<Generic*, const char*>> inapplicable_generics;
std::vector<std::tuple<GenericCallable*, const char*>> inapplicable_generics;
for (auto* declarable : declaration_container) {
if (Generic* generic = Generic::DynamicCast(declarable)) {
if (GenericCallable* generic = GenericCallable::DynamicCast(declarable)) {
TypeArgumentInference inference = generic->InferSpecializationTypes(
specialization_types, parameter_types);
if (inference.HasFailed()) {
......@@ -1634,7 +1636,8 @@ Callable* ImplementationVisitor::LookupCallable(
overloads.push_back(generic);
overload_signatures.push_back(
DeclarationVisitor::MakeSpecializedSignature(
SpecializationKey<Generic>{generic, inference.GetResult()}));
SpecializationKey<GenericCallable>{generic,
inference.GetResult()}));
} else if (Callable* callable = Callable::DynamicCast(declarable)) {
overloads.push_back(callable);
overload_signatures.push_back(callable->signature());
......@@ -1683,11 +1686,12 @@ Callable* ImplementationVisitor::LookupCallable(
}
}
if (Generic* generic = Generic::DynamicCast(overloads[best])) {
if (GenericCallable* generic =
GenericCallable::DynamicCast(overloads[best])) {
TypeArgumentInference inference = generic->InferSpecializationTypes(
specialization_types, parameter_types);
result = GetOrCreateSpecialization(
SpecializationKey<Generic>{generic, inference.GetResult()});
SpecializationKey<GenericCallable>{generic, inference.GetResult()});
} else {
result = Callable::cast(overloads[best]);
}
......@@ -1936,9 +1940,9 @@ LocationReference ImplementationVisitor::GetLocationReference(
"builtin " + expr->name->value);
}
if (expr->generic_arguments.size() != 0) {
Generic* generic = Declarations::LookupUniqueGeneric(name);
GenericCallable* generic = Declarations::LookupUniqueGeneric(name);
Callable* specialization =
GetOrCreateSpecialization(SpecializationKey<Generic>{
GetOrCreateSpecialization(SpecializationKey<GenericCallable>{
generic, TypeVisitor::ComputeTypeVector(expr->generic_arguments)});
if (Builtin* builtin = Builtin::DynamicCast(specialization)) {
DCHECK(!builtin->IsExternal());
......@@ -2654,8 +2658,8 @@ void ImplementationVisitor::Visit(Declarable* declarable) {
case Declarable::kIntrinsic:
case Declarable::kExternConstant:
case Declarable::kNamespace:
case Declarable::kGeneric:
case Declarable::kGenericStructType:
case Declarable::kGenericCallable:
case Declarable::kGenericType:
return;
}
}
......
......@@ -321,8 +321,8 @@ void HandleDocumentSymbolRequest(DocumentSymbolRequest request,
symbol.set_name(builtin->ReadableName());
symbol.set_kind(SymbolKind::kFunction);
symbol.location().SetTo(builtin->Position());
} else if (symbol->IsGeneric()) {
Generic* generic = Generic::cast(symbol);
} else if (symbol->IsGenericCallable()) {
GenericCallable* generic = GenericCallable::cast(symbol);
SymbolInformation symbol = response.add_result();
symbol.set_name(generic->name());
symbol.set_kind(SymbolKind::kFunction);
......
......@@ -513,7 +513,8 @@ base::Optional<ParseResult> MakeIntrinsicDeclaration(
}
Declaration* result = declaration;
if (!generic_parameters.empty()) {
result = MakeNode<GenericDeclaration>(generic_parameters, declaration);
result =
MakeNode<GenericCallableDeclaration>(generic_parameters, declaration);
}
return ParseResult{result};
}
......@@ -543,7 +544,8 @@ base::Optional<ParseResult> MakeTorqueMacroDeclaration(
if (!body) ReportError("A non-generic declaration needs a body.");
} else {
if (export_to_csa) ReportError("Cannot export generics to CSA.");
result = MakeNode<GenericDeclaration>(generic_parameters, declaration);
result =
MakeNode<GenericCallableDeclaration>(generic_parameters, declaration);
}
return ParseResult{result};
}
......@@ -569,7 +571,8 @@ base::Optional<ParseResult> MakeTorqueBuiltinDeclaration(
if (generic_parameters.empty()) {
if (!body) ReportError("A non-generic declaration needs a body.");
} else {
result = MakeNode<GenericDeclaration>(generic_parameters, declaration);
result =
MakeNode<GenericCallableDeclaration>(generic_parameters, declaration);
}
return ParseResult{result};
}
......@@ -612,10 +615,15 @@ base::Optional<ParseResult> MakeAbstractTypeDeclaration(
if (!IsValidTypeName(name->value)) {
NamingConventionError("Type", name, "UpperCamelCase");
}
auto generic_parameters = child_results->NextAs<GenericParameters>();
auto extends = child_results->NextAs<base::Optional<Identifier*>>();
auto generates = child_results->NextAs<base::Optional<std::string>>();
Declaration* decl = MakeNode<AbstractTypeDeclaration>(
TypeDeclaration* type_decl = MakeNode<AbstractTypeDeclaration>(
name, transient, extends, std::move(generates));
Declaration* decl = type_decl;
if (!generic_parameters.empty()) {
decl = MakeNode<GenericTypeDeclaration>(generic_parameters, type_decl);
}
auto constexpr_generates =
child_results->NextAs<base::Optional<std::string>>();
......@@ -633,10 +641,15 @@ base::Optional<ParseResult> MakeAbstractTypeDeclaration(
MakeNode<Identifier>(CONSTEXPR_TYPE_PREFIX + (*extends)->value);
(*constexpr_extends)->pos = name->pos;
}
AbstractTypeDeclaration* constexpr_decl = MakeNode<AbstractTypeDeclaration>(
TypeDeclaration* constexpr_decl = MakeNode<AbstractTypeDeclaration>(
constexpr_name, transient, constexpr_extends, constexpr_generates);
constexpr_decl->pos = name->pos;
result.push_back(constexpr_decl);
Declaration* decl = constexpr_decl;
if (!generic_parameters.empty()) {
decl =
MakeNode<GenericTypeDeclaration>(generic_parameters, constexpr_decl);
}
result.push_back(decl);
}
return ParseResult{result};
......@@ -885,9 +898,12 @@ base::Optional<ParseResult> MakeStructDeclaration(
LintGenericParameters(generic_parameters);
auto methods = child_results->NextAs<std::vector<Declaration*>>();
auto fields = child_results->NextAs<std::vector<StructFieldExpression>>();
Declaration* result = MakeNode<StructDeclaration>(
flags, name, std::move(methods), std::move(fields),
std::move(generic_parameters));
TypeDeclaration* struct_decl = MakeNode<StructDeclaration>(
flags, name, std::move(methods), std::move(fields));
Declaration* result = struct_decl;
if (!generic_parameters.empty()) {
result = MakeNode<GenericTypeDeclaration>(generic_parameters, struct_decl);
}
return ParseResult{result};
}
......@@ -2008,6 +2024,7 @@ struct TorqueGrammar : Grammar {
List<StructFieldExpression>(&structField), Token("}")},
AsSingletonVector<Declaration*, MakeStructDeclaration>()),
Rule({CheckIf(Token("transient")), Token("type"), &name,
TryOrDefault<GenericParameters>(&genericParameters),
Optional<Identifier*>(Sequence({Token("extends"), &name})),
Optional<std::string>(
Sequence({Token("generates"), &externalString})),
......
......@@ -78,10 +78,7 @@ void TypeArgumentInference::Match(TypeExpression* parameter,
}
// Try to recurse in case of generic types
if (!basic->generic_arguments.empty()) {
auto* argument_struct_type = StructType::DynamicCast(argument_type);
if (argument_struct_type) {
MatchGeneric(basic, argument_struct_type);
}
MatchGeneric(basic, argument_type);
}
// NOTE: We could also check whether ground parameter types match the
// argument types, but we are only interested in inferring type arguments
......@@ -92,13 +89,13 @@ void TypeArgumentInference::Match(TypeExpression* parameter,
}
void TypeArgumentInference::MatchGeneric(BasicTypeExpression* parameter,
const StructType* argument_type) {
const Type* argument_type) {
QualifiedName qualified_name{parameter->namespace_qualification,
parameter->name};
GenericStructType* generic_struct =
Declarations::LookupUniqueGenericStructType(qualified_name);
GenericType* generic_type =
Declarations::LookupUniqueGenericType(qualified_name);
auto& specialized_from = argument_type->GetSpecializedFrom();
if (!specialized_from || specialized_from->generic != generic_struct) {
if (!specialized_from || specialized_from->generic != generic_type) {
return Fail("found conflicting generic type constructors");
}
auto& parameters = parameter->generic_arguments;
......
......@@ -68,8 +68,7 @@ class TypeArgumentInference {
void Fail(const char* reason) { failure_reason_ = {reason}; }
void Match(TypeExpression* parameter, const Type* argument_type);
void MatchGeneric(BasicTypeExpression* parameter,
const StructType* argument_type);
void MatchGeneric(BasicTypeExpression* parameter, const Type* argument_type);
size_t num_explicit_;
std::unordered_map<std::string, size_t> type_parameter_from_name_;
......
......@@ -25,10 +25,10 @@ void TypeOracle::FinalizeAggregateTypes() {
}
// static
const StructType* TypeOracle::GetGenericStructTypeInstance(
GenericStructType* generic_struct, TypeVector arg_types) {
auto& params = generic_struct->generic_parameters();
auto& specializations = generic_struct->specializations();
const Type* TypeOracle::GetGenericTypeInstance(GenericType* generic_type,
TypeVector arg_types) {
auto& params = generic_type->generic_parameters();
auto& specializations = generic_type->specializations();
if (params.size() != arg_types.size()) {
ReportError("Generic struct takes ", params.size(), " parameters, but ",
......@@ -38,14 +38,21 @@ const StructType* TypeOracle::GetGenericStructTypeInstance(
if (auto specialization = specializations.Get(arg_types)) {
return *specialization;
} else {
CurrentScope::Scope generic_scope(generic_struct->ParentScope());
auto struct_type = TypeVisitor::ComputeType(generic_struct->declaration(),
{{generic_struct, arg_types}});
specializations.Add(arg_types, struct_type);
return struct_type;
CurrentScope::Scope generic_scope(generic_type->ParentScope());
auto type = TypeVisitor::ComputeType(generic_type->declaration(),
{{generic_type, arg_types}});
specializations.Add(arg_types, type);
return type;
}
}
// static
Namespace* TypeOracle::CreateGenericTypeInstatiationNamespace() {
Get().generic_type_instantiation_namespaces_.push_back(
std::make_unique<Namespace>(GENERIC_TYPE_INSTANTIATION_NAMESPACE_STRING));
return Get().generic_type_instantiation_namespaces_.back().get();
}
} // namespace torque
} // namespace internal
} // namespace v8
......@@ -21,24 +21,25 @@ class TypeOracle : public ContextualClass<TypeOracle> {
public:
static const AbstractType* GetAbstractType(
const Type* parent, std::string name, bool transient,
std::string generated, const AbstractType* non_constexpr_version) {
AbstractType* result =
new AbstractType(parent, transient, std::move(name),
std::move(generated), non_constexpr_version);
Get().nominal_types_.push_back(std::unique_ptr<AbstractType>(result));
std::string generated, const AbstractType* non_constexpr_version,
MaybeSpecializationKey specialized_from) {
auto ptr = std::unique_ptr<AbstractType>(new AbstractType(
parent, transient, std::move(name), std::move(generated),
non_constexpr_version, specialized_from));
const AbstractType* result = ptr.get();
Get().nominal_types_.push_back(std::move(ptr));
if (non_constexpr_version) {
non_constexpr_version->SetConstexprVersion(result);
}
return result;
}
static StructType* GetStructType(
const StructDeclaration* decl,
StructType::MaybeSpecializationKey specialized_from) {
Namespace* nspace = new Namespace(STRUCT_NAMESPACE_STRING);
StructType* result = new StructType(nspace, decl, specialized_from);
Get().aggregate_types_.push_back(std::unique_ptr<StructType>(result));
Get().struct_namespaces_.push_back(std::unique_ptr<Namespace>(nspace));
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;
}
......@@ -66,26 +67,25 @@ class TypeOracle : public ContextualClass<TypeOracle> {
return result;
}
static const StructType* GetGenericStructTypeInstance(
GenericStructType* generic_struct, TypeVector arg_types);
static const Type* GetGenericTypeInstance(GenericType* generic_type,
TypeVector arg_types);
static GenericStructType* GetReferenceGeneric() {
return Declarations::LookupUniqueGenericStructType(QualifiedName(
static GenericType* GetReferenceGeneric() {
return Declarations::LookupUniqueGenericType(QualifiedName(
{TORQUE_INTERNAL_NAMESPACE_STRING}, REFERENCE_TYPE_STRING));
}
static GenericStructType* GetSliceGeneric() {
return Declarations::LookupUniqueGenericStructType(
static GenericType* GetSliceGeneric() {
return Declarations::LookupUniqueGenericType(
QualifiedName({TORQUE_INTERNAL_NAMESPACE_STRING}, SLICE_TYPE_STRING));
}
static const StructType* GetReferenceType(const Type* referenced_type) {
return GetGenericStructTypeInstance(GetReferenceGeneric(),
{referenced_type});
static const Type* GetReferenceType(const Type* referenced_type) {
return GetGenericTypeInstance(GetReferenceGeneric(), {referenced_type});
}
static const StructType* GetSliceType(const Type* referenced_type) {
return GetGenericStructTypeInstance(GetSliceGeneric(), {referenced_type});
static const Type* GetSliceType(const Type* referenced_type) {
return GetGenericTypeInstance(GetSliceGeneric(), {referenced_type});
}
static const std::vector<const BuiltinPointerType*>&
......@@ -248,7 +248,7 @@ class TypeOracle : public ContextualClass<TypeOracle> {
}
static bool IsImplicitlyConvertableFrom(const Type* to, const Type* from) {
for (Generic* from_constexpr :
for (GenericCallable* from_constexpr :
Declarations::LookupGeneric(kFromConstexprMacroName)) {
if (base::Optional<const Callable*> specialization =
from_constexpr->specializations().Get({to, from})) {
......@@ -267,6 +267,8 @@ class TypeOracle : public ContextualClass<TypeOracle> {
static size_t FreshTypeId() { return Get().next_type_id_++; }
static Namespace* CreateGenericTypeInstatiationNamespace();
private:
const Type* GetBuiltinType(const std::string& name) {
return Declarations::LookupGlobalType(name);
......@@ -278,7 +280,8 @@ class TypeOracle : public ContextualClass<TypeOracle> {
std::vector<std::unique_ptr<Type>> nominal_types_;
std::vector<std::unique_ptr<AggregateType>> aggregate_types_;
std::vector<std::unique_ptr<Type>> top_types_;
std::vector<std::unique_ptr<Namespace>> struct_namespaces_;
std::vector<std::unique_ptr<Namespace>>
generic_type_instantiation_namespaces_;
size_t next_type_id_ = 0;
};
......
......@@ -15,12 +15,28 @@ namespace v8 {
namespace internal {
namespace torque {
const Type* TypeVisitor::ComputeType(TypeDeclaration* decl) {
const Type* TypeVisitor::ComputeType(TypeDeclaration* decl,
MaybeSpecializationKey specialized_from) {
CurrentSourcePosition::Scope scope(decl->pos);
Scope* current_scope = CurrentScope::Get();
if (specialized_from) {
current_scope = TypeOracle::CreateGenericTypeInstatiationNamespace();
}
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, *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));
return ComputeType(name::cast(decl), specialized_from);
AST_TYPE_DECLARATION_NODE_KIND_LIST(ENUM_ITEM)
#undef ENUM_ITEM
default:
......@@ -28,7 +44,8 @@ const Type* TypeVisitor::ComputeType(TypeDeclaration* decl) {
}
}
const Type* TypeVisitor::ComputeType(TypeAliasDeclaration* decl) {
const Type* TypeVisitor::ComputeType(TypeAliasDeclaration* decl,
MaybeSpecializationKey specialized_from) {
const Type* type = ComputeType(decl->type);
type->AddAlias(decl->name->value);
return type;
......@@ -51,7 +68,8 @@ std::string ComputeGeneratesType(base::Optional<std::string> opt_gen,
}
} // namespace
const AbstractType* TypeVisitor::ComputeType(AbstractTypeDeclaration* decl) {
const AbstractType* TypeVisitor::ComputeType(
AbstractTypeDeclaration* decl, MaybeSpecializationKey specialized_from) {
std::string generates =
ComputeGeneratesType(decl->generates, !decl->is_constexpr);
......@@ -85,7 +103,7 @@ const AbstractType* TypeVisitor::ComputeType(AbstractTypeDeclaration* decl) {
return TypeOracle::GetAbstractType(parent_type, decl->name->value,
decl->transient, generates,
non_constexpr_version);
non_constexpr_version, specialized_from);
}
void DeclareMethods(AggregateType* container_type,
......@@ -108,22 +126,11 @@ void DeclareMethods(AggregateType* container_type,
}
const StructType* TypeVisitor::ComputeType(
StructDeclaration* decl,
StructType::MaybeSpecializationKey specialized_from) {
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);
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, *arg_types_iterator);
alias->SetIsUserDefined(false);
arg_types_iterator++;
}
}
size_t offset = 0;
for (auto& field : decl->fields) {
CurrentSourcePosition::Scope position_activator(
......@@ -146,7 +153,8 @@ const StructType* TypeVisitor::ComputeType(
return struct_type;
}
const ClassType* TypeVisitor::ComputeType(ClassDeclaration* decl) {
const ClassType* TypeVisitor::ComputeType(
ClassDeclaration* decl, MaybeSpecializationKey specialized_from) {
ClassType* new_class;
// TODO(sigurds): Remove this hack by introducing a declarable for classes.
const TypeAlias* alias =
......@@ -216,11 +224,11 @@ const Type* TypeVisitor::ComputeType(TypeExpression* type_expression) {
type = alias->type();
pos = alias->GetDeclarationPosition();
} else {
auto* generic_struct =
Declarations::LookupUniqueGenericStructType(qualified_name);
type = TypeOracle::GetGenericStructTypeInstance(generic_struct,
ComputeTypeVector(args));
pos = generic_struct->declaration()->name->pos;
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()) {
......@@ -350,11 +358,16 @@ const StructType* TypeVisitor::ComputeTypeForStructExpression(
}
QualifiedName qualified_name{basic->namespace_qualification, basic->name};
base::Optional<GenericStructType*> maybe_generic_struct =
Declarations::TryLookupGenericStructType(qualified_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_struct) {
if (!(maybe_generic_type && decl)) {
const Type* type = ComputeType(type_expression);
const StructType* struct_type = StructType::DynamicCast(type);
if (!struct_type) {
......@@ -363,20 +376,20 @@ const StructType* TypeVisitor::ComputeTypeForStructExpression(
return struct_type;
}
auto generic_struct = *maybe_generic_struct;
auto generic_type = *maybe_generic_type;
auto explicit_type_arguments = ComputeTypeVector(basic->generic_arguments);
std::vector<TypeExpression*> term_parameters;
auto& fields = generic_struct->declaration()->fields;
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_struct->ParentScope());
TypeArgumentInference inference(
generic_struct->declaration()->generic_parameters,
explicit_type_arguments, term_parameters, term_argument_types);
CurrentScope::Scope generic_scope(generic_type->ParentScope());
TypeArgumentInference inference(generic_type->generic_parameters(),
explicit_type_arguments, term_parameters,
term_argument_types);
if (inference.HasFailed()) {
ReportError("failed to infer type arguments for struct ", basic->name,
......@@ -384,10 +397,10 @@ const StructType* TypeVisitor::ComputeTypeForStructExpression(
}
if (GlobalContext::collect_language_server_data()) {
LanguageServerData::AddDefinition(type_expression->pos,
generic_struct->declaration()->name->pos);
generic_type->declaration()->name->pos);
}
return TypeOracle::GetGenericStructTypeInstance(generic_struct,
inference.GetResult());
return StructType::cast(
TypeOracle::GetGenericTypeInstance(generic_type, inference.GetResult()));
}
} // namespace torque
......
......@@ -37,13 +37,17 @@ class TypeVisitor {
private:
friend class TypeAlias;
friend class TypeOracle;
static const Type* ComputeType(TypeDeclaration* decl);
static const AbstractType* ComputeType(AbstractTypeDeclaration* decl);
static const Type* ComputeType(TypeAliasDeclaration* decl);
static const StructType* ComputeType(
StructDeclaration* decl,
StructType::MaybeSpecializationKey specialized_from = base::nullopt);
static const ClassType* ComputeType(ClassDeclaration* decl);
static const Type* ComputeType(
TypeDeclaration* decl,
MaybeSpecializationKey specialized_from = base::nullopt);
static const AbstractType* ComputeType(
AbstractTypeDeclaration* decl, MaybeSpecializationKey specialized_from);
static const Type* ComputeType(TypeAliasDeclaration* decl,
MaybeSpecializationKey specialized_from);
static const StructType* ComputeType(StructDeclaration* decl,
MaybeSpecializationKey specialized_from);
static const ClassType* ComputeType(ClassDeclaration* decl,
MaybeSpecializationKey specialized_from);
};
} // namespace torque
......
......@@ -21,11 +21,16 @@ Type::Type(const Type& other) V8_NOEXCEPT : TypeBase(other),
parent_(other.parent_),
aliases_(),
id_(TypeOracle::FreshTypeId()) {}
Type::Type(TypeBase::Kind kind, const Type* parent)
: TypeBase(kind), parent_(parent), id_(TypeOracle::FreshTypeId()) {}
Type::Type(TypeBase::Kind kind, const Type* parent,
MaybeSpecializationKey specialized_from)
: TypeBase(kind),
parent_(parent),
id_(TypeOracle::FreshTypeId()),
specialized_from_(specialized_from) {}
std::string Type::ToString() const {
if (aliases_.size() == 0) return ToExplicitString();
if (aliases_.size() == 0)
return ComputeName(ToExplicitString(), GetSpecializedFrom());
if (aliases_.size() == 1) return *aliases_.begin();
std::stringstream result;
int i = 0;
......@@ -44,7 +49,16 @@ std::string Type::ToString() const {
}
std::string Type::SimpleName() const {
if (aliases_.empty()) return SimpleNameImpl();
if (aliases_.empty()) {
std::stringstream result;
result << SimpleNameImpl();
if (GetSpecializedFrom()) {
for (const Type* t : GetSpecializedFrom()->specialized_types) {
result << "_" << t->SimpleName();
}
}
return result.str();
}
return *aliases_.begin();
}
......@@ -290,10 +304,9 @@ const Field& AggregateType::LookupField(const std::string& name) const {
StructType::StructType(Namespace* nspace, const StructDeclaration* decl,
MaybeSpecializationKey specialized_from)
: AggregateType(Kind::kStructType, nullptr, nspace,
ComputeName(decl->name->value, specialized_from)),
decl_(decl),
specialized_from_(specialized_from) {
: AggregateType(Kind::kStructType, nullptr, nspace, decl->name->value,
specialized_from),
decl_(decl) {
if (decl->flags & StructFlag::kExport) {
generated_type_name_ = "TorqueStruct" + name();
} else {
......@@ -307,9 +320,8 @@ std::string StructType::GetGeneratedTypeNameImpl() const {
}
// static
std::string StructType::ComputeName(
const std::string& basename,
StructType::MaybeSpecializationKey specialized_from) {
std::string Type::ComputeName(const std::string& basename,
MaybeSpecializationKey specialized_from) {
if (!specialized_from) return basename;
std::stringstream s;
s << basename << "<";
......@@ -325,20 +337,11 @@ std::string StructType::ComputeName(
return s.str();
}
std::string StructType::SimpleNameImpl() const {
std::stringstream result;
result << decl_->name->value;
if (specialized_from_) {
for (const Type* t : specialized_from_->specialized_types) {
result << "_" << t->SimpleName();
}
}
return result.str();
}
std::string StructType::SimpleNameImpl() const { return decl_->name->value; }
// static
base::Optional<const Type*> StructType::MatchUnaryGeneric(
const Type* type, GenericStructType* generic) {
const Type* type, GenericType* generic) {
if (auto* struct_type = StructType::DynamicCast(type)) {
return MatchUnaryGeneric(struct_type, generic);
}
......@@ -347,12 +350,12 @@ base::Optional<const Type*> StructType::MatchUnaryGeneric(
// static
base::Optional<const Type*> StructType::MatchUnaryGeneric(
const StructType* type, GenericStructType* generic) {
const StructType* type, GenericType* generic) {
DCHECK_EQ(generic->generic_parameters().size(), 1);
if (!type->specialized_from_) {
if (!type->GetSpecializedFrom()) {
return base::nullopt;
}
auto& key = type->specialized_from_.value();
auto& key = type->GetSpecializedFrom().value();
if (key.generic != generic || key.specialized_types.size() != 1) {
return base::nullopt;
}
......
......@@ -25,8 +25,9 @@ class AggregateType;
struct Identifier;
class Macro;
class Method;
class GenericStructType;
class GenericType;
class StructType;
class Type;
class ClassType;
class Value;
class Namespace;
......@@ -80,6 +81,16 @@ class TypeBase {
return static_cast<const x*>(declarable); \
}
using TypeVector = std::vector<const Type*>;
template <typename T>
struct SpecializationKey {
T* generic;
TypeVector specialized_types;
};
using MaybeSpecializationKey = base::Optional<SpecializationKey<GenericType>>;
class V8_EXPORT_PRIVATE Type : public TypeBase {
public:
virtual bool IsSubtypeOf(const Type* supertype) const;
......@@ -112,9 +123,13 @@ class V8_EXPORT_PRIVATE Type : public TypeBase {
static const Type* CommonSupertype(const Type* a, const Type* b);
void AddAlias(std::string alias) const { aliases_.insert(std::move(alias)); }
size_t id() const { return id_; }
const MaybeSpecializationKey& GetSpecializedFrom() const {
return specialized_from_;
}
protected:
Type(TypeBase::Kind kind, const Type* parent);
Type(TypeBase::Kind kind, const Type* parent,
MaybeSpecializationKey specialized_from = base::nullopt);
Type(const Type& other) V8_NOEXCEPT;
Type& operator=(const Type& other) = delete;
const Type* parent() const { return parent_; }
......@@ -125,6 +140,9 @@ class V8_EXPORT_PRIVATE Type : public TypeBase {
virtual std::string GetGeneratedTNodeTypeNameImpl() const = 0;
virtual std::string SimpleNameImpl() const = 0;
static std::string ComputeName(const std::string& basename,
MaybeSpecializationKey specialized_from);
private:
bool IsAbstractName(const std::string& name) const;
......@@ -132,10 +150,9 @@ class V8_EXPORT_PRIVATE Type : public TypeBase {
const Type* parent_;
mutable std::set<std::string> aliases_;
size_t id_;
MaybeSpecializationKey specialized_from_;
};
using TypeVector = std::vector<const Type*>;
inline size_t hash_value(const TypeVector& types) {
size_t hash = 0;
for (const Type* t : types) {
......@@ -151,12 +168,6 @@ struct NameAndType {
std::ostream& operator<<(std::ostream& os, const NameAndType& name_and_type);
template <typename T>
struct SpecializationKey {
T* generic;
TypeVector specialized_types;
};
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
......@@ -236,8 +247,9 @@ class AbstractType final : public Type {
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),
const Type* non_constexpr_version,
MaybeSpecializationKey specialized_from)
: Type(Kind::kAbstractType, parent, specialized_from),
transient_(transient),
name_(name),
generated_type_(generated_type),
......@@ -450,8 +462,9 @@ class AggregateType : public Type {
protected:
AggregateType(Kind kind, const Type* parent, Namespace* nspace,
const std::string& name)
: Type(kind, parent),
const std::string& name,
MaybeSpecializationKey specialized_from = base::nullopt)
: Type(kind, parent, specialized_from),
is_finalized_(false),
namespace_(nspace),
name_(name) {}
......@@ -475,18 +488,12 @@ class StructType final : public AggregateType {
public:
DECLARE_TYPE_BOILERPLATE(StructType)
using MaybeSpecializationKey =
base::Optional<SpecializationKey<GenericStructType>>;
std::string GetGeneratedTypeNameImpl() const override;
const MaybeSpecializationKey& GetSpecializedFrom() const {
return specialized_from_;
}
static base::Optional<const Type*> MatchUnaryGeneric(
const Type* type, GenericStructType* generic);
static base::Optional<const Type*> MatchUnaryGeneric(
const StructType* type, GenericStructType* generic);
static base::Optional<const Type*> MatchUnaryGeneric(const Type* type,
GenericType* generic);
static base::Optional<const Type*> MatchUnaryGeneric(const StructType* type,
GenericType* generic);
private:
friend class TypeOracle;
......@@ -497,12 +504,8 @@ class StructType final : public AggregateType {
std::string ToExplicitString() const override;
std::string SimpleNameImpl() const override;
static std::string ComputeName(const std::string& basename,
MaybeSpecializationKey specialized_from);
const StructDeclaration* decl_;
std::string generated_type_name_;
MaybeSpecializationKey specialized_from_;
};
class TypeAlias;
......
......@@ -64,6 +64,8 @@ type Code extends HeapObject generates 'TNode<Code>';
type BuiltinPtr extends Smi generates 'TNode<BuiltinPtr>';
type Context extends HeapObject generates 'TNode<Context>';
type NativeContext extends Context;
macro FromConstexpr<To: type, From: type>(o: From): To;
)";
TorqueCompilerResult TestCompileTorque(std::string source) {
......@@ -318,6 +320,39 @@ TEST(Torque, LetShouldBeConstIsSkippedForStructs) {
)");
}
TEST(Torque, GenericAbstractType) {
ExpectSuccessfulCompilation(R"(
type Foo<T: type> extends HeapObject;
extern macro F1(HeapObject);
macro F2<T: type>(x: Foo<T>) {
F1(x);
}
@export
macro F3(a: Foo<Smi>, b: Foo<HeapObject>){
F2(a);
F2(b);
}
)");
ExpectFailingCompilation(R"(
type Foo<T: type> extends HeapObject;
macro F1<T: type>(x: Foo<T>) {}
@export
macro F2(a: Foo<Smi>) {
F1<HeapObject>(a);
})",
HasSubstr("cannot find suitable callable"));
ExpectFailingCompilation(R"(
type Foo<T: type> extends HeapObject;
extern macro F1(Foo<HeapObject>);
@export
macro F2(a: Foo<Smi>) {
F1(a);
})",
HasSubstr("cannot find suitable callable"));
}
} // namespace torque
} // namespace internal
} // namespace v8
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment