1// Copyright 2017 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/torque/declarations.h"
6#include "src/torque/declarable.h"
7#include "src/torque/global-context.h"
8#include "src/torque/server-data.h"
9#include "src/torque/type-oracle.h"
10
11namespace v8 {
12namespace internal {
13namespace torque {
14namespace {
15
16template <class T>
17std::vector<T> EnsureNonempty(std::vector<T> list, const std::string& name,
18                              const char* kind) {
19  if (list.empty()) {
20    ReportError("there is no ", kind, " named ", name);
21  }
22  return std::move(list);
23}
24
25template <class T, class Name>
26T EnsureUnique(const std::vector<T>& list, const Name& name, const char* kind) {
27  if (list.empty()) {
28    ReportError("there is no ", kind, " named ", name);
29  }
30  if (list.size() >= 2) {
31    ReportError("ambiguous reference to ", kind, " ", name);
32  }
33  return list.front();
34}
35
36template <class T>
37void CheckAlreadyDeclared(const std::string& name, const char* new_type) {
38  std::vector<T*> declarations =
39      FilterDeclarables<T>(Declarations::TryLookupShallow(QualifiedName(name)));
40  if (!declarations.empty()) {
41    Scope* scope = CurrentScope::Get();
42    ReportError("cannot redeclare ", name, " (type ", *new_type, scope, ")");
43  }
44}
45
46}  // namespace
47
48std::vector<Declarable*> Declarations::LookupGlobalScope(
49    const QualifiedName& name) {
50  std::vector<Declarable*> d =
51      GlobalContext::GetDefaultNamespace()->Lookup(name);
52  if (d.empty()) {
53    std::stringstream s;
54    s << "cannot find \"" << name << "\" in global scope";
55    ReportError(s.str());
56  }
57  return d;
58}
59
60const TypeAlias* Declarations::LookupTypeAlias(const QualifiedName& name) {
61  TypeAlias* declaration =
62      EnsureUnique(FilterDeclarables<TypeAlias>(Lookup(name)), name, "type");
63  return declaration;
64}
65
66const Type* Declarations::LookupType(const QualifiedName& name) {
67  return LookupTypeAlias(name)->type();
68}
69
70const Type* Declarations::LookupType(const Identifier* name) {
71  const TypeAlias* alias = LookupTypeAlias(QualifiedName(name->value));
72  if (GlobalContext::collect_language_server_data()) {
73    LanguageServerData::AddDefinition(name->pos,
74                                      alias->GetDeclarationPosition());
75  }
76  return alias->type();
77}
78
79base::Optional<const Type*> Declarations::TryLookupType(
80    const QualifiedName& name) {
81  auto decls = FilterDeclarables<TypeAlias>(TryLookup(name));
82  if (decls.empty()) return base::nullopt;
83  return EnsureUnique(std::move(decls), name, "type")->type();
84}
85
86const Type* Declarations::LookupGlobalType(const QualifiedName& name) {
87  TypeAlias* declaration = EnsureUnique(
88      FilterDeclarables<TypeAlias>(LookupGlobalScope(name)), name, "type");
89  return declaration->type();
90}
91
92Builtin* Declarations::FindSomeInternalBuiltinWithType(
93    const BuiltinPointerType* type) {
94  for (auto& declarable : GlobalContext::AllDeclarables()) {
95    if (Builtin* builtin = Builtin::DynamicCast(declarable.get())) {
96      if (!builtin->IsExternal() && builtin->kind() == Builtin::kStub &&
97          builtin->signature().return_type == type->return_type() &&
98          builtin->signature().parameter_types.types ==
99              type->parameter_types()) {
100        return builtin;
101      }
102    }
103  }
104  return nullptr;
105}
106
107Value* Declarations::LookupValue(const QualifiedName& name) {
108  return EnsureUnique(FilterDeclarables<Value>(Lookup(name)), name, "value");
109}
110
111Macro* Declarations::TryLookupMacro(const std::string& name,
112                                    const TypeVector& types) {
113  std::vector<Macro*> macros = TryLookup<Macro>(QualifiedName(name));
114  for (auto& m : macros) {
115    auto signature_types = m->signature().GetExplicitTypes();
116    if (signature_types == types && !m->signature().parameter_types.var_args) {
117      return m;
118    }
119  }
120  return nullptr;
121}
122
123base::Optional<Builtin*> Declarations::TryLookupBuiltin(
124    const QualifiedName& name) {
125  std::vector<Builtin*> builtins = TryLookup<Builtin>(name);
126  if (builtins.empty()) return base::nullopt;
127  return EnsureUnique(builtins, name.name, "builtin");
128}
129
130std::vector<GenericCallable*> Declarations::LookupGeneric(
131    const std::string& name) {
132  return EnsureNonempty(
133      FilterDeclarables<GenericCallable>(Lookup(QualifiedName(name))), name,
134      "generic callable");
135}
136
137GenericCallable* Declarations::LookupUniqueGeneric(const QualifiedName& name) {
138  return EnsureUnique(FilterDeclarables<GenericCallable>(Lookup(name)), name,
139                      "generic callable");
140}
141
142GenericType* Declarations::LookupUniqueGenericType(const QualifiedName& name) {
143  return EnsureUnique(FilterDeclarables<GenericType>(Lookup(name)), name,
144                      "generic type");
145}
146
147GenericType* Declarations::LookupGlobalUniqueGenericType(
148    const std::string& name) {
149  return EnsureUnique(
150      FilterDeclarables<GenericType>(LookupGlobalScope(QualifiedName(name))),
151      name, "generic type");
152}
153
154base::Optional<GenericType*> Declarations::TryLookupGenericType(
155    const QualifiedName& name) {
156  std::vector<GenericType*> results = TryLookup<GenericType>(name);
157  if (results.empty()) return base::nullopt;
158  return EnsureUnique(results, name.name, "generic type");
159}
160
161Namespace* Declarations::DeclareNamespace(const std::string& name) {
162  return Declare(name, std::make_unique<Namespace>(name));
163}
164
165TypeAlias* Declarations::DeclareType(const Identifier* name, const Type* type) {
166  CheckAlreadyDeclared<TypeAlias>(name->value, "type");
167  return Declare(name->value, std::unique_ptr<TypeAlias>(
168                                  new TypeAlias(type, true, name->pos)));
169}
170
171TypeAlias* Declarations::PredeclareTypeAlias(const Identifier* name,
172                                             TypeDeclaration* type,
173                                             bool redeclaration) {
174  CheckAlreadyDeclared<TypeAlias>(name->value, "type");
175  std::unique_ptr<TypeAlias> alias_ptr(
176      new TypeAlias(type, redeclaration, name->pos));
177  return Declare(name->value, std::move(alias_ptr));
178}
179
180TorqueMacro* Declarations::CreateTorqueMacro(std::string external_name,
181                                             std::string readable_name,
182                                             bool exported_to_csa,
183                                             Signature signature,
184                                             base::Optional<Statement*> body,
185                                             bool is_user_defined) {
186  external_name = GlobalContext::MakeUniqueName(external_name);
187  return RegisterDeclarable(std::unique_ptr<TorqueMacro>(new TorqueMacro(
188      std::move(external_name), std::move(readable_name), std::move(signature),
189      body, is_user_defined, exported_to_csa)));
190}
191
192ExternMacro* Declarations::CreateExternMacro(
193    std::string name, std::string external_assembler_name,
194    Signature signature) {
195  return RegisterDeclarable(std::unique_ptr<ExternMacro>(
196      new ExternMacro(std::move(name), std::move(external_assembler_name),
197                      std::move(signature))));
198}
199
200Macro* Declarations::DeclareMacro(
201    const std::string& name, bool accessible_from_csa,
202    base::Optional<std::string> external_assembler_name,
203    const Signature& signature, base::Optional<Statement*> body,
204    base::Optional<std::string> op, bool is_user_defined) {
205  if (Macro* existing_macro =
206          TryLookupMacro(name, signature.GetExplicitTypes())) {
207    if (existing_macro->ParentScope() == CurrentScope::Get()) {
208      ReportError("cannot redeclare macro ", name,
209                  " with identical explicit parameters");
210    }
211  }
212  Macro* macro;
213  if (external_assembler_name) {
214    macro =
215        CreateExternMacro(name, std::move(*external_assembler_name), signature);
216  } else {
217    macro = CreateTorqueMacro(name, name, accessible_from_csa, signature, body,
218                              is_user_defined);
219  }
220
221  Declare(name, macro);
222  if (op) {
223    if (TryLookupMacro(*op, signature.GetExplicitTypes())) {
224      ReportError("cannot redeclare operator ", name,
225                  " with identical explicit parameters");
226    }
227    DeclareOperator(*op, macro);
228  }
229  return macro;
230}
231
232Method* Declarations::CreateMethod(AggregateType* container_type,
233                                   const std::string& name, Signature signature,
234                                   Statement* body) {
235  std::string generated_name = GlobalContext::MakeUniqueName(
236      "Method_" + container_type->SimpleName() + "_" + name);
237  Method* result = RegisterDeclarable(std::unique_ptr<Method>(new Method(
238      container_type, generated_name, name, std::move(signature), body)));
239  container_type->RegisterMethod(result);
240  return result;
241}
242
243Intrinsic* Declarations::CreateIntrinsic(const std::string& name,
244                                         const Signature& signature) {
245  Intrinsic* result = RegisterDeclarable(std::unique_ptr<Intrinsic>(
246      new Intrinsic(std::move(name), std::move(signature))));
247  return result;
248}
249
250Intrinsic* Declarations::DeclareIntrinsic(const std::string& name,
251                                          const Signature& signature) {
252  Intrinsic* result = CreateIntrinsic(std::move(name), std::move(signature));
253  Declare(name, result);
254  return result;
255}
256
257Builtin* Declarations::CreateBuiltin(std::string external_name,
258                                     std::string readable_name,
259                                     Builtin::Kind kind, Signature signature,
260
261                                     base::Optional<Statement*> body) {
262  return RegisterDeclarable(std::unique_ptr<Builtin>(
263      new Builtin(std::move(external_name), std::move(readable_name), kind,
264                  std::move(signature), body)));
265}
266
267Builtin* Declarations::DeclareBuiltin(const std::string& name,
268                                      Builtin::Kind kind,
269                                      const Signature& signature,
270
271                                      base::Optional<Statement*> body) {
272  CheckAlreadyDeclared<Builtin>(name, "builtin");
273  return Declare(name, CreateBuiltin(name, name, kind, signature, body));
274}
275
276RuntimeFunction* Declarations::DeclareRuntimeFunction(
277    const std::string& name, const Signature& signature) {
278  CheckAlreadyDeclared<RuntimeFunction>(name, "runtime function");
279  return Declare(name, RegisterDeclarable(std::unique_ptr<RuntimeFunction>(
280                           new RuntimeFunction(name, signature))));
281}
282
283ExternConstant* Declarations::DeclareExternConstant(Identifier* name,
284                                                    const Type* type,
285                                                    std::string value) {
286  CheckAlreadyDeclared<Value>(name->value, "constant");
287  return Declare(name->value, std::unique_ptr<ExternConstant>(
288                                  new ExternConstant(name, type, value)));
289}
290
291NamespaceConstant* Declarations::DeclareNamespaceConstant(Identifier* name,
292                                                          const Type* type,
293                                                          Expression* body) {
294  CheckAlreadyDeclared<Value>(name->value, "constant");
295  std::string external_name = GlobalContext::MakeUniqueName(name->value);
296  std::unique_ptr<NamespaceConstant> namespaceConstant(
297      new NamespaceConstant(name, std::move(external_name), type, body));
298  NamespaceConstant* result = namespaceConstant.get();
299  Declare(name->value, std::move(namespaceConstant));
300  return result;
301}
302
303GenericCallable* Declarations::DeclareGenericCallable(
304    const std::string& name, GenericCallableDeclaration* ast_node) {
305  return Declare(name, std::unique_ptr<GenericCallable>(
306                           new GenericCallable(name, ast_node)));
307}
308
309GenericType* Declarations::DeclareGenericType(
310    const std::string& name, GenericTypeDeclaration* ast_node) {
311  return Declare(name,
312                 std::unique_ptr<GenericType>(new GenericType(name, ast_node)));
313}
314
315std::string Declarations::GetGeneratedCallableName(
316    const std::string& name, const TypeVector& specialized_types) {
317  std::string result = name;
318  for (auto type : specialized_types) {
319    result += "_" + type->SimpleName();
320  }
321  return result;
322}
323
324Macro* Declarations::DeclareOperator(const std::string& name, Macro* m) {
325  GlobalContext::GetDefaultNamespace()->AddDeclarable(name, m);
326  return m;
327}
328
329}  // namespace torque
330}  // namespace internal
331}  // namespace v8
332