V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
declarable.h
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 #ifndef V8_TORQUE_DECLARABLE_H_
6 #define V8_TORQUE_DECLARABLE_H_
7 
8 #include <cassert>
9 #include <string>
10 #include <unordered_map>
11 
12 #include "src/base/functional.h"
13 #include "src/base/logging.h"
14 #include "src/torque/ast.h"
15 #include "src/torque/types.h"
16 #include "src/torque/utils.h"
17 
18 namespace v8 {
19 namespace internal {
20 namespace torque {
21 
22 class Scope;
23 
24 DECLARE_CONTEXTUAL_VARIABLE(CurrentScope, Scope*);
25 
26 struct QualifiedName {
27  std::vector<std::string> namespace_qualification;
28  std::string name;
29 
30  QualifiedName(std::vector<std::string> namespace_qualification,
31  std::string name)
32  : namespace_qualification(std::move(namespace_qualification)),
33  name(std::move(name)) {}
34  explicit QualifiedName(std::string name)
35  : QualifiedName({}, std::move(name)) {}
36 
37  friend std::ostream& operator<<(std::ostream& os, const QualifiedName& name);
38 };
39 
40 class Declarable {
41  public:
42  virtual ~Declarable() = default;
43  enum Kind {
44  kNamespace,
45  kMacro,
46  kBuiltin,
47  kRuntimeFunction,
48  kIntrinsic,
49  kGeneric,
50  kTypeAlias,
51  kExternConstant,
52  kNamespaceConstant
53  };
54  Kind kind() const { return kind_; }
55  bool IsNamespace() const { return kind() == kNamespace; }
56  bool IsMacro() const { return kind() == kMacro; }
57  bool IsIntrinsic() const { return kind() == kIntrinsic; }
58  bool IsBuiltin() const { return kind() == kBuiltin; }
59  bool IsRuntimeFunction() const { return kind() == kRuntimeFunction; }
60  bool IsGeneric() const { return kind() == kGeneric; }
61  bool IsTypeAlias() const { return kind() == kTypeAlias; }
62  bool IsExternConstant() const { return kind() == kExternConstant; }
63  bool IsNamespaceConstant() const { return kind() == kNamespaceConstant; }
64  bool IsValue() const { return IsExternConstant() || IsNamespaceConstant(); }
65  bool IsScope() const { return IsNamespace() || IsCallable(); }
66  bool IsCallable() const {
67  return IsMacro() || IsBuiltin() || IsRuntimeFunction() || IsIntrinsic();
68  }
69  virtual const char* type_name() const { return "<<unknown>>"; }
70  Scope* ParentScope() const { return parent_scope_; }
71  const SourcePosition& pos() const { return pos_; }
72 
73  protected:
74  explicit Declarable(Kind kind) : kind_(kind) {}
75 
76  private:
77  const Kind kind_;
78  Scope* const parent_scope_ = CurrentScope::Get();
79  SourcePosition pos_ = CurrentSourcePosition::Get();
80 };
81 
82 #define DECLARE_DECLARABLE_BOILERPLATE(x, y) \
83  static x* cast(Declarable* declarable) { \
84  DCHECK(declarable->Is##x()); \
85  return static_cast<x*>(declarable); \
86  } \
87  static const x* cast(const Declarable* declarable) { \
88  DCHECK(declarable->Is##x()); \
89  return static_cast<const x*>(declarable); \
90  } \
91  const char* type_name() const override { return #y; } \
92  static x* DynamicCast(Declarable* declarable) { \
93  if (!declarable) return nullptr; \
94  if (!declarable->Is##x()) return nullptr; \
95  return static_cast<x*>(declarable); \
96  } \
97  static const x* DynamicCast(const Declarable* declarable) { \
98  if (!declarable) return nullptr; \
99  if (!declarable->Is##x()) return nullptr; \
100  return static_cast<const x*>(declarable); \
101  }
102 
103 class Scope : public Declarable {
104  public:
105  DECLARE_DECLARABLE_BOILERPLATE(Scope, scope);
106  explicit Scope(Declarable::Kind kind) : Declarable(kind) {}
107 
108  std::vector<Declarable*> LookupShallow(const QualifiedName& name) {
109  if (name.namespace_qualification.empty()) return declarations_[name.name];
110  Scope* child = nullptr;
111  for (Declarable* declarable :
112  declarations_[name.namespace_qualification.front()]) {
113  if (Scope* scope = Scope::DynamicCast(declarable)) {
114  if (child != nullptr) {
115  ReportError("ambiguous reference to scope ",
116  name.namespace_qualification.front());
117  }
118  child = scope;
119  }
120  }
121  if (child == nullptr) return {};
122  return child->LookupShallow(
123  QualifiedName({name.namespace_qualification.begin() + 1,
124  name.namespace_qualification.end()},
125  name.name));
126  }
127 
128  std::vector<Declarable*> Lookup(const QualifiedName& name) {
129  std::vector<Declarable*> result;
130  if (ParentScope()) {
131  result = ParentScope()->Lookup(name);
132  }
133  for (Declarable* declarable : LookupShallow(name)) {
134  result.push_back(declarable);
135  }
136  return result;
137  }
138  template <class T>
139  T* AddDeclarable(const std::string& name, T* declarable) {
140  declarations_[name].push_back(declarable);
141  return declarable;
142  }
143 
144  private:
145  std::unordered_map<std::string, std::vector<Declarable*>> declarations_;
146 };
147 
148 class Namespace : public Scope {
149  public:
150  DECLARE_DECLARABLE_BOILERPLATE(Namespace, namespace);
151  explicit Namespace(const std::string& name)
152  : Scope(Declarable::kNamespace), name_(name) {}
153  const std::string& name() const { return name_; }
154  std::string ExternalName() const {
155  return CamelifyString(name()) + "BuiltinsFromDSLAssembler";
156  }
157  std::ostream& source_stream() { return source_stream_; }
158  std::ostream& header_stream() { return header_stream_; }
159  std::string source() { return source_stream_.str(); }
160  std::string header() { return header_stream_.str(); }
161 
162  private:
163  std::string name_;
164  std::stringstream header_stream_;
165  std::stringstream source_stream_;
166 };
167 
168 inline Namespace* CurrentNamespace() {
169  Scope* scope = CurrentScope::Get();
170  while (true) {
171  if (Namespace* n = Namespace::DynamicCast(scope)) {
172  return n;
173  }
174  scope = scope->ParentScope();
175  }
176 }
177 
178 class Value : public Declarable {
179  public:
180  DECLARE_DECLARABLE_BOILERPLATE(Value, value);
181  const std::string& name() const { return name_; }
182  virtual bool IsConst() const { return true; }
183  VisitResult value() const { return *value_; }
184  const Type* type() const { return type_; }
185 
186  void set_value(VisitResult value) {
187  DCHECK(!value_);
188  value_ = value;
189  }
190 
191  protected:
192  Value(Kind kind, const Type* type, const std::string& name)
193  : Declarable(kind), type_(type), name_(name) {}
194 
195  private:
196  const Type* type_;
197  std::string name_;
199 };
200 
201 class NamespaceConstant : public Value {
202  public:
203  DECLARE_DECLARABLE_BOILERPLATE(NamespaceConstant, constant);
204 
205  const std::string& constant_name() const { return constant_name_; }
206  Expression* body() { return body_; }
207  std::string ExternalAssemblerName() const {
208  return Namespace::cast(ParentScope())->ExternalName();
209  }
210 
211  private:
212  friend class Declarations;
213  explicit NamespaceConstant(std::string constant_name, const Type* type,
214  Expression* body)
215  : Value(Declarable::kNamespaceConstant, type, constant_name),
216  constant_name_(std::move(constant_name)),
217  body_(body) {}
218 
219  std::string constant_name_;
220  Expression* body_;
221 };
222 
223 class ExternConstant : public Value {
224  public:
225  DECLARE_DECLARABLE_BOILERPLATE(ExternConstant, constant);
226 
227  private:
228  friend class Declarations;
229  explicit ExternConstant(std::string name, const Type* type, std::string value)
230  : Value(Declarable::kExternConstant, type, std::move(name)) {
231  set_value(VisitResult(type, std::move(value)));
232  }
233 };
234 
235 class Callable : public Scope {
236  public:
237  DECLARE_DECLARABLE_BOILERPLATE(Callable, callable);
238  const std::string& ExternalName() const { return external_name_; }
239  const std::string& ReadableName() const { return readable_name_; }
240  const Signature& signature() const { return signature_; }
241  const NameVector& parameter_names() const {
242  return signature_.parameter_names;
243  }
244  bool HasReturnValue() const {
245  return !signature_.return_type->IsVoidOrNever();
246  }
247  void IncrementReturns() { ++returns_; }
248  bool HasReturns() const { return returns_; }
249  bool IsTransitioning() const { return transitioning_; }
250  base::Optional<Statement*> body() const { return body_; }
251  bool IsExternal() const { return !body_.has_value(); }
252 
253  protected:
254  Callable(Declarable::Kind kind, std::string external_name,
255  std::string readable_name, Signature signature, bool transitioning,
257  : Scope(kind),
258  external_name_(std::move(external_name)),
259 
260  readable_name_(std::move(readable_name)),
261  signature_(std::move(signature)),
262  transitioning_(transitioning),
263  returns_(0),
264  body_(body) {
265  DCHECK(!body || *body);
266  }
267 
268  private:
269  std::string external_name_;
270  std::string readable_name_;
271  Signature signature_;
272  bool transitioning_;
273  size_t returns_;
275 };
276 
277 class Macro : public Callable {
278  public:
279  DECLARE_DECLARABLE_BOILERPLATE(Macro, macro);
280 
281  const std::string& external_assembler_name() const {
282  return external_assembler_name_;
283  }
284 
285  private:
286  friend class Declarations;
287  Macro(std::string external_name, std::string readable_name,
288  std::string external_assembler_name, const Signature& signature,
289  bool transitioning, base::Optional<Statement*> body)
290  : Callable(Declarable::kMacro, std::move(external_name),
291  std::move(readable_name), signature, transitioning, body),
292  external_assembler_name_(std::move(external_assembler_name)) {
293  if (signature.parameter_types.var_args) {
294  ReportError("Varargs are not supported for macros.");
295  }
296  }
297 
298  std::string external_assembler_name_;
299 };
300 
301 class Builtin : public Callable {
302  public:
303  enum Kind { kStub, kFixedArgsJavaScript, kVarArgsJavaScript };
304  DECLARE_DECLARABLE_BOILERPLATE(Builtin, builtin);
305  Kind kind() const { return kind_; }
306  bool IsStub() const { return kind_ == kStub; }
307  bool IsVarArgsJavaScript() const { return kind_ == kVarArgsJavaScript; }
308  bool IsFixedArgsJavaScript() const { return kind_ == kFixedArgsJavaScript; }
309 
310  private:
311  friend class Declarations;
312  Builtin(std::string external_name, std::string readable_name,
313  Builtin::Kind kind, const Signature& signature, bool transitioning,
315  : Callable(Declarable::kBuiltin, std::move(external_name),
316  std::move(readable_name), signature, transitioning, body),
317  kind_(kind) {}
318 
319  Kind kind_;
320 };
321 
322 class RuntimeFunction : public Callable {
323  public:
324  DECLARE_DECLARABLE_BOILERPLATE(RuntimeFunction, runtime);
325 
326  private:
327  friend class Declarations;
328  RuntimeFunction(const std::string& name, const Signature& signature,
329  bool transitioning)
330  : Callable(Declarable::kRuntimeFunction, name, name, signature,
331  transitioning, base::nullopt) {}
332 };
333 
334 class Intrinsic : public Callable {
335  public:
336  DECLARE_DECLARABLE_BOILERPLATE(Intrinsic, intrinsic);
337 
338  private:
339  friend class Declarations;
340  Intrinsic(std::string name, const Signature& signature)
341  : Callable(Declarable::kIntrinsic, name, name, signature, false,
342  base::nullopt) {
343  if (signature.parameter_types.var_args) {
344  ReportError("Varargs are not supported for intrinsics.");
345  }
346  }
347 };
348 
349 class Generic : public Declarable {
350  public:
351  DECLARE_DECLARABLE_BOILERPLATE(Generic, generic);
352 
353  GenericDeclaration* declaration() const { return declaration_; }
354  const std::vector<std::string> generic_parameters() const {
355  return declaration()->generic_parameters;
356  }
357  const std::string& name() const { return name_; }
358  void AddSpecialization(const TypeVector& type_arguments,
359  Callable* specialization) {
360  DCHECK_EQ(0, specializations_.count(type_arguments));
361  specializations_[type_arguments] = specialization;
362  }
363  base::Optional<Callable*> GetSpecialization(
364  const TypeVector& type_arguments) const {
365  auto it = specializations_.find(type_arguments);
366  if (it != specializations_.end()) return it->second;
367  return base::nullopt;
368  }
369  base::Optional<TypeVector> InferSpecializationTypes(
370  const TypeVector& explicit_specialization_types,
371  const TypeVector& arguments);
372 
373  private:
374  friend class Declarations;
375  Generic(const std::string& name, GenericDeclaration* declaration)
376  : Declarable(Declarable::kGeneric),
377  name_(name),
378  declaration_(declaration) {}
379  base::Optional<const Type*> InferTypeArgument(size_t i,
380  const TypeVector& arguments);
381 
382  std::string name_;
383  std::unordered_map<TypeVector, Callable*, base::hash<TypeVector>>
384  specializations_;
385  GenericDeclaration* declaration_;
386 };
387 
389  Generic* generic;
390  TypeVector specialized_types;
391 };
392 
393 class TypeAlias : public Declarable {
394  public:
395  DECLARE_DECLARABLE_BOILERPLATE(TypeAlias, type_alias);
396 
397  const Type* type() const { return type_; }
398  bool IsRedeclaration() const { return redeclaration_; }
399 
400  private:
401  friend class Declarations;
402  explicit TypeAlias(const Type* type, bool redeclaration)
403  : Declarable(Declarable::kTypeAlias),
404  type_(type),
405  redeclaration_(redeclaration) {}
406 
407  const Type* type_;
408  bool redeclaration_;
409 };
410 
411 std::ostream& operator<<(std::ostream& os, const Callable& m);
412 std::ostream& operator<<(std::ostream& os, const Builtin& b);
413 std::ostream& operator<<(std::ostream& os, const RuntimeFunction& b);
414 std::ostream& operator<<(std::ostream& os, const Generic& g);
415 
416 #undef DECLARE_DECLARABLE_BOILERPLATE
417 
418 } // namespace torque
419 } // namespace internal
420 } // namespace v8
421 
422 #endif // V8_TORQUE_DECLARABLE_H_
Definition: libplatform.h:13