V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
declaration-visitor.cc
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/declaration-visitor.h"
6 
7 namespace v8 {
8 namespace internal {
9 namespace torque {
10 
11 void DeclarationVisitor::Visit(Declaration* decl) {
12  CurrentSourcePosition::Scope scope(decl->pos);
13  switch (decl->kind) {
14 #define ENUM_ITEM(name) \
15  case AstNode::Kind::k##name: \
16  return Visit(name::cast(decl));
17  AST_DECLARATION_NODE_KIND_LIST(ENUM_ITEM)
18 #undef ENUM_ITEM
19  default:
20  UNIMPLEMENTED();
21  }
22 }
23 
24 void DeclarationVisitor::Visit(CallableNode* decl, const Signature& signature,
25  base::Optional<Statement*> body) {
26  switch (decl->kind) {
27 #define ENUM_ITEM(name) \
28  case AstNode::Kind::k##name: \
29  return Visit(name::cast(decl), signature, body);
30  AST_CALLABLE_NODE_KIND_LIST(ENUM_ITEM)
31 #undef ENUM_ITEM
32  default:
33  UNIMPLEMENTED();
34  }
35 }
36 
37 Builtin* DeclarationVisitor::CreateBuiltin(BuiltinDeclaration* decl,
38  std::string external_name,
39  std::string readable_name,
40  Signature signature,
41  base::Optional<Statement*> body) {
42  const bool javascript = decl->javascript_linkage;
43  const bool varargs = decl->signature->parameters.has_varargs;
44  Builtin::Kind kind = !javascript ? Builtin::kStub
45  : varargs ? Builtin::kVarArgsJavaScript
46  : Builtin::kFixedArgsJavaScript;
47 
48  if (signature.types().size() == 0 ||
49  !(signature.types()[0] ==
50  Declarations::LookupGlobalType(CONTEXT_TYPE_STRING))) {
51  std::stringstream stream;
52  stream << "first parameter to builtin " << decl->name
53  << " is not a context but should be";
54  ReportError(stream.str());
55  }
56 
57  if (varargs && !javascript) {
58  std::stringstream stream;
59  stream << "builtin " << decl->name
60  << " with rest parameters must be a JavaScript builtin";
61  ReportError(stream.str());
62  }
63 
64  if (javascript) {
65  if (signature.types().size() < 2 ||
66  !(signature.types()[1] ==
67  Declarations::LookupGlobalType(OBJECT_TYPE_STRING))) {
68  std::stringstream stream;
69  stream << "second parameter to javascript builtin " << decl->name
70  << " is " << *signature.types()[1] << " but should be Object";
71  ReportError(stream.str());
72  }
73  }
74 
75  if (const StructType* struct_type =
76  StructType::DynamicCast(signature.return_type)) {
77  std::stringstream stream;
78  stream << "builtins (in this case" << decl->name
79  << ") cannot return structs (in this case " << struct_type->name()
80  << ")";
81  ReportError(stream.str());
82  }
83 
84  return Declarations::CreateBuiltin(
85  std::move(external_name), std::move(readable_name), kind,
86  std::move(signature), decl->transitioning, body);
87 }
88 
89 void DeclarationVisitor::Visit(ExternalRuntimeDeclaration* decl,
90  const Signature& signature,
91  base::Optional<Statement*> body) {
92  if (GlobalContext::verbose()) {
93  std::cout << "found declaration of external runtime " << decl->name
94  << " with signature ";
95  }
96 
97  if (signature.parameter_types.types.size() == 0 ||
98  !(signature.parameter_types.types[0] ==
99  Declarations::LookupGlobalType(CONTEXT_TYPE_STRING))) {
100  std::stringstream stream;
101  stream << "first parameter to runtime " << decl->name
102  << " is not a context but should be";
103  ReportError(stream.str());
104  }
105 
106  if (signature.return_type->IsStructType()) {
107  std::stringstream stream;
108  stream << "runtime functions (in this case" << decl->name
109  << ") cannot return structs (in this case "
110  << static_cast<const StructType*>(signature.return_type)->name()
111  << ")";
112  ReportError(stream.str());
113  }
114 
115  Declarations::DeclareRuntimeFunction(decl->name, signature,
116  decl->transitioning);
117 }
118 
119 void DeclarationVisitor::Visit(ExternalMacroDeclaration* decl,
120  const Signature& signature,
121  base::Optional<Statement*> body) {
122  if (GlobalContext::verbose()) {
123  std::cout << "found declaration of external macro " << decl->name
124  << " with signature ";
125  }
126 
127  Declarations::DeclareMacro(decl->name, decl->external_assembler_name,
128  signature, decl->transitioning, body, decl->op);
129 }
130 
131 void DeclarationVisitor::Visit(TorqueBuiltinDeclaration* decl,
132  const Signature& signature,
133  base::Optional<Statement*> body) {
134  Declarations::Declare(
135  decl->name, CreateBuiltin(decl, decl->name, decl->name, signature, body));
136 }
137 
138 void DeclarationVisitor::Visit(TorqueMacroDeclaration* decl,
139  const Signature& signature,
140  base::Optional<Statement*> body) {
141  Declarations::DeclareMacro(decl->name, base::nullopt, signature,
142  decl->transitioning, body, decl->op);
143 }
144 
145 void DeclarationVisitor::Visit(IntrinsicDeclaration* decl,
146  const Signature& signature,
147  base::Optional<Statement*> body) {
148  Declarations::DeclareIntrinsic(decl->name, signature);
149 }
150 
151 void DeclarationVisitor::Visit(ConstDeclaration* decl) {
152  Declarations::DeclareNamespaceConstant(
153  decl->name, Declarations::GetType(decl->type), decl->expression);
154 }
155 
156 void DeclarationVisitor::Visit(StandardDeclaration* decl) {
157  Signature signature = MakeSignature(decl->callable->signature.get());
158  Visit(decl->callable, signature, decl->body);
159 }
160 
161 void DeclarationVisitor::Visit(GenericDeclaration* decl) {
162  Declarations::DeclareGeneric(decl->callable->name, decl);
163 }
164 
165 void DeclarationVisitor::Visit(SpecializationDeclaration* decl) {
166  if ((decl->body != nullptr) == decl->external) {
167  std::stringstream stream;
168  stream << "specialization of " << decl->name
169  << " must either be marked 'extern' or have a body";
170  ReportError(stream.str());
171  }
172 
173  std::vector<Generic*> generic_list = Declarations::LookupGeneric(decl->name);
174  // Find the matching generic specialization based on the concrete parameter
175  // list.
176  Generic* matching_generic = nullptr;
177  Signature signature_with_types = MakeSignature(decl->signature.get());
178  for (Generic* generic : generic_list) {
179  Signature generic_signature_with_types = MakeSpecializedSignature(
180  SpecializationKey{generic, GetTypeVector(decl->generic_parameters)});
181  if (signature_with_types.HasSameTypesAs(generic_signature_with_types,
182  ParameterMode::kIgnoreImplicit)) {
183  if (matching_generic != nullptr) {
184  std::stringstream stream;
185  stream << "specialization of " << decl->name
186  << " is ambigous, it matches more than one generic declaration ("
187  << *matching_generic << " and " << *generic << ")";
188  ReportError(stream.str());
189  }
190  matching_generic = generic;
191  }
192  }
193 
194  if (matching_generic == nullptr) {
195  std::stringstream stream;
196  if (generic_list.size() == 0) {
197  stream << "no generic defined with the name " << decl->name;
198  ReportError(stream.str());
199  }
200  stream << "specialization of " << decl->name
201  << " doesn't match any generic declaration\n";
202  stream << "specialization signature:";
203  stream << "\n " << signature_with_types;
204  stream << "\ncandidates are:";
205  for (Generic* generic : generic_list) {
206  stream << "\n "
207  << MakeSpecializedSignature(SpecializationKey{
208  generic, GetTypeVector(decl->generic_parameters)});
209  }
210  ReportError(stream.str());
211  }
212 
213  Specialize(SpecializationKey{matching_generic,
214  GetTypeVector(decl->generic_parameters)},
215  matching_generic->declaration()->callable, decl->signature.get(),
216  decl->body);
217 }
218 
219 void DeclarationVisitor::Visit(ExternConstDeclaration* decl) {
220  const Type* type = Declarations::GetType(decl->type);
221  if (!type->IsConstexpr()) {
222  std::stringstream stream;
223  stream << "extern constants must have constexpr type, but found: \""
224  << *type << "\"\n";
225  ReportError(stream.str());
226  }
227 
228  Declarations::DeclareExternConstant(decl->name, type, decl->literal);
229 }
230 
231 void DeclarationVisitor::Visit(StructDeclaration* decl) {
232  std::vector<NameAndType> fields;
233  for (auto& field : decl->fields) {
234  const Type* field_type = Declarations::GetType(field.type);
235  fields.push_back({field.name, field_type});
236  }
237  Declarations::DeclareStruct(decl->name, fields);
238 }
239 
240 void DeclarationVisitor::Visit(TypeDeclaration* decl) {
241  std::string generates = decl->generates ? *decl->generates : std::string("");
242  if (decl->generates) {
243  if (generates.length() < 7 || generates.substr(0, 6) != "TNode<" ||
244  generates.substr(generates.length() - 1, 1) != ">") {
245  ReportError("generated type \"", generates,
246  "\" should be of the form \"TNode<...>\"");
247  }
248  generates = generates.substr(6, generates.length() - 7);
249  }
250 
251  const AbstractType* type = Declarations::DeclareAbstractType(
252  decl->name, decl->transient, generates, {}, decl->extends);
253 
254  if (decl->constexpr_generates) {
255  if (decl->transient) {
256  ReportError("cannot declare a transient type that is also constexpr");
257  }
258  std::string constexpr_name = CONSTEXPR_TYPE_PREFIX + decl->name;
259  base::Optional<std::string> constexpr_extends;
260  if (decl->extends)
261  constexpr_extends = CONSTEXPR_TYPE_PREFIX + *decl->extends;
262  Declarations::DeclareAbstractType(constexpr_name, false,
263  *decl->constexpr_generates, type,
264  constexpr_extends);
265  }
266 }
267 
268 void DeclarationVisitor::DeclareSpecializedTypes(const SpecializationKey& key) {
269  size_t i = 0;
270  const std::size_t generic_parameter_count =
271  key.generic->declaration()->generic_parameters.size();
272  if (generic_parameter_count != key.specialized_types.size()) {
273  std::stringstream stream;
274  stream << "Wrong generic argument count for specialization of \""
275  << key.generic->name() << "\", expected: " << generic_parameter_count
276  << ", actual: " << key.specialized_types.size();
277  ReportError(stream.str());
278  }
279 
280  for (auto type : key.specialized_types) {
281  std::string generic_type_name =
282  key.generic->declaration()->generic_parameters[i++];
283  Declarations::DeclareType(generic_type_name, type, true);
284  }
285 }
286 
287 Signature DeclarationVisitor::MakeSpecializedSignature(
288  const SpecializationKey& key) {
289  CurrentScope::Scope generic_scope(key.generic->ParentScope());
290  // Create a temporary fake-namespace just to temporarily declare the
291  // specialization aliases for the generic types to create a signature.
292  Namespace tmp_namespace("_tmp");
293  CurrentScope::Scope tmp_namespace_scope(&tmp_namespace);
294  DeclareSpecializedTypes(key);
295  return MakeSignature(key.generic->declaration()->callable->signature.get());
296 }
297 
298 Callable* DeclarationVisitor::SpecializeImplicit(const SpecializationKey& key) {
299  if (!key.generic->declaration()->body &&
300  IntrinsicDeclaration::DynamicCast(key.generic->declaration()->callable) ==
301  nullptr) {
302  ReportError("missing specialization of ", key.generic->name(),
303  " with types <", key.specialized_types, "> declared at ",
304  key.generic->pos());
305  }
306  CurrentScope::Scope generic_scope(key.generic->ParentScope());
307  Callable* result =
308  Specialize(key, key.generic->declaration()->callable, base::nullopt,
309  key.generic->declaration()->body);
310  CurrentScope::Scope callable_scope(result);
311  DeclareSpecializedTypes(key);
312  return result;
313 }
314 
315 Callable* DeclarationVisitor::Specialize(
316  const SpecializationKey& key, CallableNode* declaration,
317  base::Optional<const CallableNodeSignature*> signature,
318  base::Optional<Statement*> body) {
319  // TODO(tebbi): The error should point to the source position where the
320  // instantiation was requested.
321  CurrentSourcePosition::Scope pos_scope(key.generic->declaration()->pos);
322  size_t generic_parameter_count =
323  key.generic->declaration()->generic_parameters.size();
324  if (generic_parameter_count != key.specialized_types.size()) {
325  std::stringstream stream;
326  stream << "number of template parameters ("
327  << std::to_string(key.specialized_types.size())
328  << ") to intantiation of generic " << declaration->name
329  << " doesnt match the generic's declaration ("
330  << std::to_string(generic_parameter_count) << ")";
331  ReportError(stream.str());
332  }
333  if (key.generic->GetSpecialization(key.specialized_types)) {
334  ReportError("cannot redeclare specialization of ", key.generic->name(),
335  " with types <", key.specialized_types, ">");
336  }
337 
338  Signature type_signature =
339  signature ? MakeSignature(*signature) : MakeSpecializedSignature(key);
340 
341  std::string generated_name = Declarations::GetGeneratedCallableName(
342  declaration->name, key.specialized_types);
343  std::stringstream readable_name;
344  readable_name << declaration->name << "<";
345  bool first = true;
346  for (const Type* t : key.specialized_types) {
347  if (!first) readable_name << ", ";
348  readable_name << *t;
349  first = false;
350  }
351  readable_name << ">";
352  Callable* callable;
353  if (MacroDeclaration::DynamicCast(declaration) != nullptr) {
354  callable = Declarations::CreateMacro(generated_name, readable_name.str(),
355  base::nullopt, type_signature,
356  declaration->transitioning, *body);
357  } else if (IntrinsicDeclaration::DynamicCast(declaration) != nullptr) {
358  callable = Declarations::CreateIntrinsic(declaration->name, type_signature);
359  } else {
360  BuiltinDeclaration* builtin = BuiltinDeclaration::cast(declaration);
361  callable = CreateBuiltin(builtin, generated_name, readable_name.str(),
362  type_signature, *body);
363  }
364  key.generic->AddSpecialization(key.specialized_types, callable);
365  return callable;
366 }
367 
368 } // namespace torque
369 } // namespace internal
370 } // namespace v8
Definition: libplatform.h:13