blob: 0a1d45a510b8293ca4b313a4c121bd30b0e018c5 [file] [log] [blame]
// 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/declarations.h"
#include "src/torque/declarable.h"
#include "src/torque/global-context.h"
#include "src/torque/server-data.h"
#include "src/torque/type-oracle.h"
namespace v8 {
namespace internal {
namespace torque {
namespace {
template <class T>
std::vector<T> EnsureNonempty(std::vector<T> list, const std::string& name,
const char* kind) {
if (list.empty()) {
ReportError("there is no ", kind, " named ", name);
}
return std::move(list);
}
template <class T, class Name>
T EnsureUnique(const std::vector<T>& list, const Name& name, const char* kind) {
if (list.empty()) {
ReportError("there is no ", kind, " named ", name);
}
if (list.size() >= 2) {
ReportError("ambiguous reference to ", kind, " ", name);
}
return list.front();
}
template <class T>
void CheckAlreadyDeclared(const std::string& name, const char* new_type) {
std::vector<T*> declarations =
FilterDeclarables<T>(Declarations::TryLookupShallow(QualifiedName(name)));
if (!declarations.empty()) {
Scope* scope = CurrentScope::Get();
ReportError("cannot redeclare ", name, " (type ", *new_type, scope, ")");
}
}
} // namespace
std::vector<Declarable*> Declarations::LookupGlobalScope(
const QualifiedName& name) {
std::vector<Declarable*> d =
GlobalContext::GetDefaultNamespace()->Lookup(name);
if (d.empty()) {
std::stringstream s;
s << "cannot find \"" << name << "\" in global scope";
ReportError(s.str());
}
return d;
}
const TypeAlias* Declarations::LookupTypeAlias(const QualifiedName& name) {
TypeAlias* declaration =
EnsureUnique(FilterDeclarables<TypeAlias>(Lookup(name)), name, "type");
return declaration;
}
const Type* Declarations::LookupType(const QualifiedName& name) {
return LookupTypeAlias(name)->type();
}
const Type* Declarations::LookupType(const Identifier* name) {
const TypeAlias* alias = LookupTypeAlias(QualifiedName(name->value));
if (GlobalContext::collect_language_server_data()) {
LanguageServerData::AddDefinition(name->pos,
alias->GetDeclarationPosition());
}
return alias->type();
}
base::Optional<const Type*> Declarations::TryLookupType(
const QualifiedName& name) {
auto decls = FilterDeclarables<TypeAlias>(TryLookup(name));
if (decls.empty()) return base::nullopt;
return EnsureUnique(std::move(decls), name, "type")->type();
}
const Type* Declarations::LookupGlobalType(const QualifiedName& name) {
TypeAlias* declaration = EnsureUnique(
FilterDeclarables<TypeAlias>(LookupGlobalScope(name)), name, "type");
return declaration->type();
}
Builtin* Declarations::FindSomeInternalBuiltinWithType(
const BuiltinPointerType* type) {
for (auto& declarable : GlobalContext::AllDeclarables()) {
if (Builtin* builtin = Builtin::DynamicCast(declarable.get())) {
if (!builtin->IsExternal() && builtin->kind() == Builtin::kStub &&
builtin->signature().return_type == type->return_type() &&
builtin->signature().parameter_types.types ==
type->parameter_types()) {
return builtin;
}
}
}
return nullptr;
}
Value* Declarations::LookupValue(const QualifiedName& name) {
return EnsureUnique(FilterDeclarables<Value>(Lookup(name)), name, "value");
}
Macro* Declarations::TryLookupMacro(const std::string& name,
const TypeVector& types) {
std::vector<Macro*> macros = TryLookup<Macro>(QualifiedName(name));
for (auto& m : macros) {
auto signature_types = m->signature().GetExplicitTypes();
if (signature_types == types && !m->signature().parameter_types.var_args) {
return m;
}
}
return nullptr;
}
base::Optional<Builtin*> Declarations::TryLookupBuiltin(
const QualifiedName& name) {
std::vector<Builtin*> builtins = TryLookup<Builtin>(name);
if (builtins.empty()) return base::nullopt;
return EnsureUnique(builtins, name.name, "builtin");
}
std::vector<GenericCallable*> Declarations::LookupGeneric(
const std::string& name) {
return EnsureNonempty(
FilterDeclarables<GenericCallable>(Lookup(QualifiedName(name))), name,
"generic callable");
}
GenericCallable* Declarations::LookupUniqueGeneric(const QualifiedName& name) {
return EnsureUnique(FilterDeclarables<GenericCallable>(Lookup(name)), name,
"generic callable");
}
GenericType* Declarations::LookupUniqueGenericType(const QualifiedName& name) {
return EnsureUnique(FilterDeclarables<GenericType>(Lookup(name)), name,
"generic type");
}
GenericType* Declarations::LookupGlobalUniqueGenericType(
const std::string& name) {
return EnsureUnique(
FilterDeclarables<GenericType>(LookupGlobalScope(QualifiedName(name))),
name, "generic type");
}
base::Optional<GenericType*> Declarations::TryLookupGenericType(
const QualifiedName& name) {
std::vector<GenericType*> results = TryLookup<GenericType>(name);
if (results.empty()) return base::nullopt;
return EnsureUnique(results, name.name, "generic type");
}
Namespace* Declarations::DeclareNamespace(const std::string& name) {
return Declare(name, std::make_unique<Namespace>(name));
}
TypeAlias* Declarations::DeclareType(const Identifier* name, const Type* type) {
CheckAlreadyDeclared<TypeAlias>(name->value, "type");
return Declare(name->value, std::unique_ptr<TypeAlias>(
new TypeAlias(type, true, name->pos)));
}
const TypeAlias* Declarations::PredeclareTypeAlias(const Identifier* name,
TypeDeclaration* type,
bool redeclaration) {
CheckAlreadyDeclared<TypeAlias>(name->value, "type");
std::unique_ptr<TypeAlias> alias_ptr(
new TypeAlias(type, redeclaration, name->pos));
return Declare(name->value, std::move(alias_ptr));
}
TorqueMacro* Declarations::CreateTorqueMacro(std::string external_name,
std::string readable_name,
bool exported_to_csa,
Signature signature,
base::Optional<Statement*> body,
bool is_user_defined) {
external_name = GlobalContext::MakeUniqueName(external_name);
return RegisterDeclarable(std::unique_ptr<TorqueMacro>(new TorqueMacro(
std::move(external_name), std::move(readable_name), std::move(signature),
body, is_user_defined, exported_to_csa)));
}
ExternMacro* Declarations::CreateExternMacro(
std::string name, std::string external_assembler_name,
Signature signature) {
return RegisterDeclarable(std::unique_ptr<ExternMacro>(
new ExternMacro(std::move(name), std::move(external_assembler_name),
std::move(signature))));
}
Macro* Declarations::DeclareMacro(
const std::string& name, bool accessible_from_csa,
base::Optional<std::string> external_assembler_name,
const Signature& signature, base::Optional<Statement*> body,
base::Optional<std::string> op, bool is_user_defined) {
if (TryLookupMacro(name, signature.GetExplicitTypes())) {
ReportError("cannot redeclare macro ", name,
" with identical explicit parameters");
}
Macro* macro;
if (external_assembler_name) {
macro =
CreateExternMacro(name, std::move(*external_assembler_name), signature);
} else {
macro = CreateTorqueMacro(name, name, accessible_from_csa, signature, body,
is_user_defined);
}
Declare(name, macro);
if (op) {
if (TryLookupMacro(*op, signature.GetExplicitTypes())) {
ReportError("cannot redeclare operator ", name,
" with identical explicit parameters");
}
DeclareOperator(*op, macro);
}
return macro;
}
Method* Declarations::CreateMethod(AggregateType* container_type,
const std::string& name, Signature signature,
Statement* body) {
std::string generated_name = GlobalContext::MakeUniqueName(
"Method_" + container_type->SimpleName() + "_" + name);
Method* result = RegisterDeclarable(std::unique_ptr<Method>(new Method(
container_type, generated_name, name, std::move(signature), body)));
container_type->RegisterMethod(result);
return result;
}
Intrinsic* Declarations::CreateIntrinsic(const std::string& name,
const Signature& signature) {
Intrinsic* result = RegisterDeclarable(std::unique_ptr<Intrinsic>(
new Intrinsic(std::move(name), std::move(signature))));
return result;
}
Intrinsic* Declarations::DeclareIntrinsic(const std::string& name,
const Signature& signature) {
Intrinsic* result = CreateIntrinsic(std::move(name), std::move(signature));
Declare(name, result);
return result;
}
Builtin* Declarations::CreateBuiltin(std::string external_name,
std::string readable_name,
Builtin::Kind kind, Signature signature,
base::Optional<Statement*> body) {
return RegisterDeclarable(std::unique_ptr<Builtin>(
new Builtin(std::move(external_name), std::move(readable_name), kind,
std::move(signature), body)));
}
Builtin* Declarations::DeclareBuiltin(const std::string& name,
Builtin::Kind kind,
const Signature& signature,
base::Optional<Statement*> body) {
CheckAlreadyDeclared<Builtin>(name, "builtin");
return Declare(name, CreateBuiltin(name, name, kind, signature, body));
}
RuntimeFunction* Declarations::DeclareRuntimeFunction(
const std::string& name, const Signature& signature) {
CheckAlreadyDeclared<RuntimeFunction>(name, "runtime function");
return Declare(name, RegisterDeclarable(std::unique_ptr<RuntimeFunction>(
new RuntimeFunction(name, signature))));
}
void Declarations::DeclareExternConstant(Identifier* name, const Type* type,
std::string value) {
CheckAlreadyDeclared<Value>(name->value, "constant");
Declare(name->value, std::unique_ptr<ExternConstant>(
new ExternConstant(name, type, value)));
}
NamespaceConstant* Declarations::DeclareNamespaceConstant(Identifier* name,
const Type* type,
Expression* body) {
CheckAlreadyDeclared<Value>(name->value, "constant");
std::string external_name = GlobalContext::MakeUniqueName(name->value);
std::unique_ptr<NamespaceConstant> namespaceConstant(
new NamespaceConstant(name, std::move(external_name), type, body));
NamespaceConstant* result = namespaceConstant.get();
Declare(name->value, std::move(namespaceConstant));
return result;
}
GenericCallable* Declarations::DeclareGenericCallable(
const std::string& name, GenericCallableDeclaration* ast_node) {
return Declare(name, std::unique_ptr<GenericCallable>(
new GenericCallable(name, ast_node)));
}
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(
const std::string& name, const TypeVector& specialized_types) {
std::string result = name;
for (auto type : specialized_types) {
result += "_" + type->SimpleName();
}
return result;
}
Macro* Declarations::DeclareOperator(const std::string& name, Macro* m) {
GlobalContext::GetDefaultNamespace()->AddDeclarable(name, m);
return m;
}
} // namespace torque
} // namespace internal
} // namespace v8