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 class Namespace;
24 class TypeArgumentInference;
25
26 DECLARE_CONTEXTUAL_VARIABLE(CurrentScope, Scope*);
27
28 struct QualifiedName {
29 std::vector<std::string> namespace_qualification;
30 std::string name;
31
QualifiedNameQualifiedName32 QualifiedName(std::vector<std::string> namespace_qualification,
33 std::string name)
34 : namespace_qualification(std::move(namespace_qualification)),
35 name(std::move(name)) {}
QualifiedNameQualifiedName36 explicit QualifiedName(std::string name)
37 : QualifiedName({}, std::move(name)) {}
38
HasNamespaceQualificationQualifiedName39 bool HasNamespaceQualification() const {
40 return !namespace_qualification.empty();
41 }
42
DropFirstNamespaceQualificationQualifiedName43 QualifiedName DropFirstNamespaceQualification() const {
44 return QualifiedName{
45 std::vector<std::string>(namespace_qualification.begin() + 1,
46 namespace_qualification.end()),
47 name};
48 }
49
50 friend std::ostream& operator<<(std::ostream& os, const QualifiedName& name);
51 };
52
53 class Declarable {
54 public:
55 virtual ~Declarable() = default;
56 enum Kind {
57 kNamespace,
58 kTorqueMacro,
59 kExternMacro,
60 kMethod,
61 kBuiltin,
62 kRuntimeFunction,
63 kIntrinsic,
64 kGenericCallable,
65 kGenericType,
66 kTypeAlias,
67 kExternConstant,
68 kNamespaceConstant
69 };
kind()70 Kind kind() const { return kind_; }
IsNamespace()71 bool IsNamespace() const { return kind() == kNamespace; }
IsMacro()72 bool IsMacro() const { return IsTorqueMacro() || IsExternMacro(); }
IsTorqueMacro()73 bool IsTorqueMacro() const { return kind() == kTorqueMacro || IsMethod(); }
IsMethod()74 bool IsMethod() const { return kind() == kMethod; }
IsExternMacro()75 bool IsExternMacro() const { return kind() == kExternMacro; }
IsIntrinsic()76 bool IsIntrinsic() const { return kind() == kIntrinsic; }
IsBuiltin()77 bool IsBuiltin() const { return kind() == kBuiltin; }
IsRuntimeFunction()78 bool IsRuntimeFunction() const { return kind() == kRuntimeFunction; }
IsGenericCallable()79 bool IsGenericCallable() const { return kind() == kGenericCallable; }
IsGenericType()80 bool IsGenericType() const { return kind() == kGenericType; }
IsTypeAlias()81 bool IsTypeAlias() const { return kind() == kTypeAlias; }
IsExternConstant()82 bool IsExternConstant() const { return kind() == kExternConstant; }
IsNamespaceConstant()83 bool IsNamespaceConstant() const { return kind() == kNamespaceConstant; }
IsValue()84 bool IsValue() const { return IsExternConstant() || IsNamespaceConstant(); }
IsScope()85 bool IsScope() const { return IsNamespace() || IsCallable(); }
IsCallable()86 bool IsCallable() const {
87 return IsMacro() || IsBuiltin() || IsRuntimeFunction() || IsIntrinsic() ||
88 IsMethod();
89 }
type_name()90 virtual const char* type_name() const { return "<<unknown>>"; }
ParentScope()91 Scope* ParentScope() const { return parent_scope_; }
92
93 // The SourcePosition of the whole declarable. For example, for a macro
94 // this will encompass not only the signature, but also the body.
Position()95 SourcePosition Position() const { return position_; }
SetPosition(const SourcePosition & position)96 void SetPosition(const SourcePosition& position) { position_ = position; }
97
98 // The SourcePosition of the identifying name of the declarable. For example,
99 // for a macro this will be the SourcePosition of the name.
100 // Note that this SourcePosition might not make sense for all kinds of
101 // declarables, in that case, the default SourcePosition is returned.
IdentifierPosition()102 SourcePosition IdentifierPosition() const {
103 return identifier_position_.source.IsValid() ? identifier_position_
104 : position_;
105 }
SetIdentifierPosition(const SourcePosition & position)106 void SetIdentifierPosition(const SourcePosition& position) {
107 identifier_position_ = position;
108 }
109
IsUserDefined()110 bool IsUserDefined() const { return is_user_defined_; }
SetIsUserDefined(bool is_user_defined)111 void SetIsUserDefined(bool is_user_defined) {
112 is_user_defined_ = is_user_defined;
113 }
114
115 protected:
Declarable(Kind kind)116 explicit Declarable(Kind kind) : kind_(kind) {}
117
118 private:
119 const Kind kind_;
120 Scope* const parent_scope_ = CurrentScope::Get();
121 SourcePosition position_ = CurrentSourcePosition::Get();
122 SourcePosition identifier_position_ = SourcePosition::Invalid();
123 bool is_user_defined_ = true;
124 };
125
126 #define DECLARE_DECLARABLE_BOILERPLATE(x, y) \
127 static x* cast(Declarable* declarable) { \
128 DCHECK(declarable->Is##x()); \
129 return static_cast<x*>(declarable); \
130 } \
131 static const x* cast(const Declarable* declarable) { \
132 DCHECK(declarable->Is##x()); \
133 return static_cast<const x*>(declarable); \
134 } \
135 const char* type_name() const override { return #y; } \
136 static x* DynamicCast(Declarable* declarable) { \
137 if (!declarable) return nullptr; \
138 if (!declarable->Is##x()) return nullptr; \
139 return static_cast<x*>(declarable); \
140 } \
141 static const x* DynamicCast(const Declarable* declarable) { \
142 if (!declarable) return nullptr; \
143 if (!declarable->Is##x()) return nullptr; \
144 return static_cast<const x*>(declarable); \
145 }
146
147 // Information about what code caused a specialization to exist. This is used
148 // for error reporting.
149 struct SpecializationRequester {
150 // The position of the expression that caused this specialization.
151 SourcePosition position;
152 // The Scope which contains the expression that caused this specialization.
153 // It may in turn also be within a specialization, which allows us to print
154 // the stack of requesters when an error occurs.
155 Scope* scope;
156 // The name of the specialization.
157 std::string name;
158
NoneSpecializationRequester159 static SpecializationRequester None() {
160 return {SourcePosition::Invalid(), nullptr, ""};
161 }
162
IsNoneSpecializationRequester163 bool IsNone() const {
164 return position == SourcePosition::Invalid() && scope == nullptr &&
165 name == "";
166 }
167 SpecializationRequester(SourcePosition position, Scope* scope,
168 std::string name);
169 };
170
171 class Scope : public Declarable {
172 public:
DECLARE_DECLARABLE_BOILERPLATE(Scope,scope)173 DECLARE_DECLARABLE_BOILERPLATE(Scope, scope)
174 explicit Scope(Declarable::Kind kind) : Declarable(kind) {}
175
LookupShallow(const QualifiedName & name)176 std::vector<Declarable*> LookupShallow(const QualifiedName& name) {
177 if (!name.HasNamespaceQualification()) return declarations_[name.name];
178 Scope* child = nullptr;
179 for (Declarable* declarable :
180 declarations_[name.namespace_qualification.front()]) {
181 if (Scope* scope = Scope::DynamicCast(declarable)) {
182 if (child != nullptr) {
183 ReportError("ambiguous reference to scope ",
184 name.namespace_qualification.front());
185 }
186 child = scope;
187 }
188 }
189 if (child == nullptr) return {};
190 return child->LookupShallow(name.DropFirstNamespaceQualification());
191 }
192
193 std::vector<Declarable*> Lookup(const QualifiedName& name);
194 template <class T>
AddDeclarable(const std::string & name,T * declarable)195 T* AddDeclarable(const std::string& name, T* declarable) {
196 declarations_[name].push_back(declarable);
197 return declarable;
198 }
199
GetSpecializationRequester()200 const SpecializationRequester& GetSpecializationRequester() const {
201 return requester_;
202 }
SetSpecializationRequester(const SpecializationRequester & requester)203 void SetSpecializationRequester(const SpecializationRequester& requester) {
204 requester_ = requester;
205 }
206
207 private:
208 std::unordered_map<std::string, std::vector<Declarable*>> declarations_;
209
210 // If this Scope was created for specializing a generic type or callable,
211 // then {requester_} refers to the place that caused the specialization so we
212 // can construct useful error messages.
213 SpecializationRequester requester_ = SpecializationRequester::None();
214 };
215
216 class Namespace : public Scope {
217 public:
DECLARE_DECLARABLE_BOILERPLATE(Namespace,namespace)218 DECLARE_DECLARABLE_BOILERPLATE(Namespace, namespace)
219 explicit Namespace(const std::string& name)
220 : Scope(Declarable::kNamespace), name_(name) {}
name()221 const std::string& name() const { return name_; }
222 bool IsDefaultNamespace() const;
223 bool IsTestNamespace() const;
224
225 private:
226 std::string name_;
227 };
228
CurrentNamespace()229 inline Namespace* CurrentNamespace() {
230 Scope* scope = CurrentScope::Get();
231 while (true) {
232 if (Namespace* n = Namespace::DynamicCast(scope)) {
233 return n;
234 }
235 scope = scope->ParentScope();
236 }
237 }
238
239 class Value : public Declarable {
240 public:
DECLARE_DECLARABLE_BOILERPLATE(Value,value)241 DECLARE_DECLARABLE_BOILERPLATE(Value, value)
242 const Identifier* name() const { return name_; }
IsConst()243 virtual bool IsConst() const { return true; }
value()244 VisitResult value() const { return *value_; }
type()245 const Type* type() const { return type_; }
246
set_value(VisitResult value)247 void set_value(VisitResult value) {
248 DCHECK(!value_);
249 value_ = value;
250 }
251
252 protected:
Value(Kind kind,const Type * type,Identifier * name)253 Value(Kind kind, const Type* type, Identifier* name)
254 : Declarable(kind), type_(type), name_(name) {}
255
256 private:
257 const Type* type_;
258 Identifier* name_;
259 base::Optional<VisitResult> value_;
260 };
261
262 class NamespaceConstant : public Value {
263 public:
DECLARE_DECLARABLE_BOILERPLATE(NamespaceConstant,constant)264 DECLARE_DECLARABLE_BOILERPLATE(NamespaceConstant, constant)
265
266 const std::string& external_name() const { return external_name_; }
body()267 Expression* body() const { return body_; }
268
269 private:
270 friend class Declarations;
NamespaceConstant(Identifier * constant_name,std::string external_name,const Type * type,Expression * body)271 explicit NamespaceConstant(Identifier* constant_name,
272 std::string external_name, const Type* type,
273 Expression* body)
274 : Value(Declarable::kNamespaceConstant, type, constant_name),
275 external_name_(std::move(external_name)),
276 body_(body) {}
277
278 std::string external_name_;
279 Expression* body_;
280 };
281
282 class ExternConstant : public Value {
283 public:
DECLARE_DECLARABLE_BOILERPLATE(ExternConstant,constant)284 DECLARE_DECLARABLE_BOILERPLATE(ExternConstant, constant)
285
286 private:
287 friend class Declarations;
288 explicit ExternConstant(Identifier* name, const Type* type, std::string value)
289 : Value(Declarable::kExternConstant, type, name) {
290 set_value(VisitResult(type, std::move(value)));
291 }
292 };
293
294 enum class OutputType {
295 kCSA,
296 kCC,
297 };
298
299 class Callable : public Scope {
300 public:
DECLARE_DECLARABLE_BOILERPLATE(Callable,callable)301 DECLARE_DECLARABLE_BOILERPLATE(Callable, callable)
302 const std::string& ExternalName() const { return external_name_; }
ReadableName()303 const std::string& ReadableName() const { return readable_name_; }
signature()304 const Signature& signature() const { return signature_; }
IsTransitioning()305 bool IsTransitioning() const { return signature().transitioning; }
parameter_names()306 const NameVector& parameter_names() const {
307 return signature_.parameter_names;
308 }
HasReturnValue()309 bool HasReturnValue() const {
310 return !signature_.return_type->IsVoidOrNever();
311 }
IncrementReturns()312 void IncrementReturns() { ++returns_; }
HasReturns()313 bool HasReturns() const { return returns_; }
body()314 base::Optional<Statement*> body() const { return body_; }
IsExternal()315 bool IsExternal() const { return !body_.has_value(); }
ShouldBeInlined(OutputType output_type)316 virtual bool ShouldBeInlined(OutputType output_type) const {
317 // C++ output doesn't support exiting to labels, so functions with labels in
318 // the signature must be inlined.
319 return output_type == OutputType::kCC && !signature().labels.empty();
320 }
ShouldGenerateExternalCode(OutputType output_type)321 bool ShouldGenerateExternalCode(OutputType output_type) const {
322 return !ShouldBeInlined(output_type);
323 }
324
PrefixNameForCCOutput(const std::string & name)325 static std::string PrefixNameForCCOutput(const std::string& name) {
326 // If a Torque macro requires a C++ runtime function to be generated, then
327 // the generated function begins with this prefix to avoid any naming
328 // collisions with the generated CSA function for the same macro.
329 return "TqRuntime" + name;
330 }
331
332 // Name to use in runtime C++ code.
CCName()333 virtual std::string CCName() const {
334 return PrefixNameForCCOutput(ExternalName());
335 }
336
337 protected:
Callable(Declarable::Kind kind,std::string external_name,std::string readable_name,Signature signature,base::Optional<Statement * > body)338 Callable(Declarable::Kind kind, std::string external_name,
339 std::string readable_name, Signature signature,
340 base::Optional<Statement*> body)
341 : Scope(kind),
342 external_name_(std::move(external_name)),
343
344 readable_name_(std::move(readable_name)),
345 signature_(std::move(signature)),
346 returns_(0),
347 body_(body) {
348 DCHECK(!body || *body);
349 }
350
351 private:
352 std::string external_name_;
353 std::string readable_name_;
354 Signature signature_;
355 size_t returns_;
356 base::Optional<Statement*> body_;
357 };
358
359 class Macro : public Callable {
360 public:
DECLARE_DECLARABLE_BOILERPLATE(Macro,macro)361 DECLARE_DECLARABLE_BOILERPLATE(Macro, macro)
362 bool ShouldBeInlined(OutputType output_type) const override {
363 for (const LabelDeclaration& label : signature().labels) {
364 for (const Type* type : label.types) {
365 if (type->StructSupertype()) return true;
366 }
367 }
368 // Intrinsics that are used internally in Torque and implemented as torque
369 // code should be inlined and not generate C++ definitions.
370 if (ReadableName()[0] == '%') return true;
371 return Callable::ShouldBeInlined(output_type);
372 }
373
SetUsed()374 void SetUsed() { used_ = true; }
IsUsed()375 bool IsUsed() const { return used_; }
376
377 protected:
Macro(Declarable::Kind kind,std::string external_name,std::string readable_name,const Signature & signature,base::Optional<Statement * > body)378 Macro(Declarable::Kind kind, std::string external_name,
379 std::string readable_name, const Signature& signature,
380 base::Optional<Statement*> body)
381 : Callable(kind, std::move(external_name), std::move(readable_name),
382 signature, body),
383 used_(false) {
384 if (signature.parameter_types.var_args) {
385 ReportError("Varargs are not supported for macros.");
386 }
387 }
388
389 private:
390 bool used_;
391 };
392
393 class ExternMacro : public Macro {
394 public:
DECLARE_DECLARABLE_BOILERPLATE(ExternMacro,ExternMacro)395 DECLARE_DECLARABLE_BOILERPLATE(ExternMacro, ExternMacro)
396
397 const std::string& external_assembler_name() const {
398 return external_assembler_name_;
399 }
400
CCName()401 std::string CCName() const override {
402 return "TorqueRuntimeMacroShims::" + external_assembler_name() +
403 "::" + ExternalName();
404 }
405
406 private:
407 friend class Declarations;
ExternMacro(const std::string & name,std::string external_assembler_name,Signature signature)408 ExternMacro(const std::string& name, std::string external_assembler_name,
409 Signature signature)
410 : Macro(Declarable::kExternMacro, name, name, std::move(signature),
411 base::nullopt),
412 external_assembler_name_(std::move(external_assembler_name)) {}
413
414 std::string external_assembler_name_;
415 };
416
417 class TorqueMacro : public Macro {
418 public:
DECLARE_DECLARABLE_BOILERPLATE(TorqueMacro,TorqueMacro)419 DECLARE_DECLARABLE_BOILERPLATE(TorqueMacro, TorqueMacro)
420 bool IsExportedToCSA() const { return exported_to_csa_; }
CCName()421 std::string CCName() const override {
422 // Exported functions must have unique and C++-friendly readable names, so
423 // prefer those wherever possible.
424 return PrefixNameForCCOutput(IsExportedToCSA() ? ReadableName()
425 : ExternalName());
426 }
427
428 protected:
TorqueMacro(Declarable::Kind kind,std::string external_name,std::string readable_name,const Signature & signature,base::Optional<Statement * > body,bool is_user_defined,bool exported_to_csa)429 TorqueMacro(Declarable::Kind kind, std::string external_name,
430 std::string readable_name, const Signature& signature,
431 base::Optional<Statement*> body, bool is_user_defined,
432 bool exported_to_csa)
433 : Macro(kind, std::move(external_name), std::move(readable_name),
434 signature, body),
435 exported_to_csa_(exported_to_csa) {
436 SetIsUserDefined(is_user_defined);
437 }
438
439 private:
440 friend class Declarations;
TorqueMacro(std::string external_name,std::string readable_name,const Signature & signature,base::Optional<Statement * > body,bool is_user_defined,bool exported_to_csa)441 TorqueMacro(std::string external_name, std::string readable_name,
442 const Signature& signature, base::Optional<Statement*> body,
443 bool is_user_defined, bool exported_to_csa)
444 : TorqueMacro(Declarable::kTorqueMacro, std::move(external_name),
445 std::move(readable_name), signature, body, is_user_defined,
446 exported_to_csa) {}
447
448 bool exported_to_csa_ = false;
449 };
450
451 class Method : public TorqueMacro {
452 public:
DECLARE_DECLARABLE_BOILERPLATE(Method,Method)453 DECLARE_DECLARABLE_BOILERPLATE(Method, Method)
454 bool ShouldBeInlined(OutputType output_type) const override {
455 return Macro::ShouldBeInlined(output_type) ||
456 signature()
457 .parameter_types.types[signature().implicit_count]
458 ->IsStructType();
459 }
aggregate_type()460 AggregateType* aggregate_type() const { return aggregate_type_; }
461
462 private:
463 friend class Declarations;
Method(AggregateType * aggregate_type,std::string external_name,std::string readable_name,const Signature & signature,Statement * body)464 Method(AggregateType* aggregate_type, std::string external_name,
465 std::string readable_name, const Signature& signature, Statement* body)
466 : TorqueMacro(Declarable::kMethod, std::move(external_name),
467 std::move(readable_name), signature, body, true, false),
468 aggregate_type_(aggregate_type) {}
469 AggregateType* aggregate_type_;
470 };
471
472 class Builtin : public Callable {
473 public:
474 enum Kind { kStub, kFixedArgsJavaScript, kVarArgsJavaScript };
DECLARE_DECLARABLE_BOILERPLATE(Builtin,builtin)475 DECLARE_DECLARABLE_BOILERPLATE(Builtin, builtin)
476 Kind kind() const { return kind_; }
IsStub()477 bool IsStub() const { return kind_ == kStub; }
IsVarArgsJavaScript()478 bool IsVarArgsJavaScript() const { return kind_ == kVarArgsJavaScript; }
IsFixedArgsJavaScript()479 bool IsFixedArgsJavaScript() const { return kind_ == kFixedArgsJavaScript; }
480
481 private:
482 friend class Declarations;
Builtin(std::string external_name,std::string readable_name,Builtin::Kind kind,const Signature & signature,base::Optional<Statement * > body)483 Builtin(std::string external_name, std::string readable_name,
484 Builtin::Kind kind, const Signature& signature,
485 base::Optional<Statement*> body)
486 : Callable(Declarable::kBuiltin, std::move(external_name),
487 std::move(readable_name), signature, body),
488 kind_(kind) {}
489
490 Kind kind_;
491 };
492
493 class RuntimeFunction : public Callable {
494 public:
DECLARE_DECLARABLE_BOILERPLATE(RuntimeFunction,runtime)495 DECLARE_DECLARABLE_BOILERPLATE(RuntimeFunction, runtime)
496
497 private:
498 friend class Declarations;
499 RuntimeFunction(const std::string& name, const Signature& signature)
500 : Callable(Declarable::kRuntimeFunction, name, name, signature,
501 base::nullopt) {}
502 };
503
504 class Intrinsic : public Callable {
505 public:
DECLARE_DECLARABLE_BOILERPLATE(Intrinsic,intrinsic)506 DECLARE_DECLARABLE_BOILERPLATE(Intrinsic, intrinsic)
507
508 private:
509 friend class Declarations;
510 Intrinsic(std::string name, const Signature& signature)
511 : Callable(Declarable::kIntrinsic, name, name, signature, base::nullopt) {
512 if (signature.parameter_types.var_args) {
513 ReportError("Varargs are not supported for intrinsics.");
514 }
515 }
516 };
517
518 class TypeConstraint {
519 public:
520 base::Optional<std::string> IsViolated(const Type*) const;
521
Unconstrained()522 static TypeConstraint Unconstrained() { return {}; }
SubtypeConstraint(const Type * upper_bound)523 static TypeConstraint SubtypeConstraint(const Type* upper_bound) {
524 TypeConstraint result;
525 result.upper_bound = {upper_bound};
526 return result;
527 }
528
529 private:
530 base::Optional<const Type*> upper_bound;
531 };
532
533 base::Optional<std::string> FindConstraintViolation(
534 const std::vector<const Type*>& types,
535 const std::vector<TypeConstraint>& constraints);
536
537 std::vector<TypeConstraint> ComputeConstraints(
538 Scope* scope, const GenericParameters& parameters);
539
540 template <class SpecializationType, class DeclarationType>
541 class GenericDeclarable : public Declarable {
542 private:
543 using Map = std::unordered_map<TypeVector, SpecializationType,
544 base::hash<TypeVector>>;
545
546 public:
AddSpecialization(const TypeVector & type_arguments,SpecializationType specialization)547 void AddSpecialization(const TypeVector& type_arguments,
548 SpecializationType specialization) {
549 DCHECK_EQ(0, specializations_.count(type_arguments));
550 if (auto violation =
551 FindConstraintViolation(type_arguments, Constraints())) {
552 Error(*violation).Throw();
553 }
554 specializations_[type_arguments] = specialization;
555 }
GetSpecialization(const TypeVector & type_arguments)556 base::Optional<SpecializationType> GetSpecialization(
557 const TypeVector& type_arguments) const {
558 auto it = specializations_.find(type_arguments);
559 if (it != specializations_.end()) return it->second;
560 return base::nullopt;
561 }
562
563 using iterator = typename Map::const_iterator;
begin()564 iterator begin() const { return specializations_.begin(); }
end()565 iterator end() const { return specializations_.end(); }
566
name()567 const std::string& name() const { return name_; }
declaration()568 auto declaration() const { return generic_declaration_->declaration; }
generic_parameters()569 const GenericParameters& generic_parameters() const {
570 return generic_declaration_->generic_parameters;
571 }
572
Constraints()573 const std::vector<TypeConstraint>& Constraints() {
574 if (!constraints_)
575 constraints_ = {ComputeConstraints(ParentScope(), generic_parameters())};
576 return *constraints_;
577 }
578
579 protected:
GenericDeclarable(Declarable::Kind kind,const std::string & name,DeclarationType generic_declaration)580 GenericDeclarable(Declarable::Kind kind, const std::string& name,
581 DeclarationType generic_declaration)
582 : Declarable(kind),
583 name_(name),
584 generic_declaration_(generic_declaration) {
585 DCHECK(!generic_declaration->generic_parameters.empty());
586 }
587
588 private:
589 std::string name_;
590 DeclarationType generic_declaration_;
591 Map specializations_;
592 base::Optional<std::vector<TypeConstraint>> constraints_;
593 };
594
595 class GenericCallable
596 : public GenericDeclarable<Callable*, GenericCallableDeclaration*> {
597 public:
598 DECLARE_DECLARABLE_BOILERPLATE(GenericCallable, generic_callable)
599
600 base::Optional<Statement*> CallableBody();
601
602 TypeArgumentInference InferSpecializationTypes(
603 const TypeVector& explicit_specialization_types,
604 const std::vector<base::Optional<const Type*>>& arguments);
605
606 private:
607 friend class Declarations;
GenericCallable(const std::string & name,GenericCallableDeclaration * generic_declaration)608 GenericCallable(const std::string& name,
609 GenericCallableDeclaration* generic_declaration)
610 : GenericDeclarable<Callable*, GenericCallableDeclaration*>(
611 Declarable::kGenericCallable, name, generic_declaration) {}
612 };
613
614 class GenericType
615 : public GenericDeclarable<const Type*, GenericTypeDeclaration*> {
616 public:
DECLARE_DECLARABLE_BOILERPLATE(GenericType,generic_type)617 DECLARE_DECLARABLE_BOILERPLATE(GenericType, generic_type)
618
619 private:
620 friend class Declarations;
621 GenericType(const std::string& name,
622 GenericTypeDeclaration* generic_declaration)
623 : GenericDeclarable<const Type*, GenericTypeDeclaration*>(
624 Declarable::kGenericType, name, generic_declaration) {}
625 };
626
627 class TypeAlias : public Declarable {
628 public:
DECLARE_DECLARABLE_BOILERPLATE(TypeAlias,type_alias)629 DECLARE_DECLARABLE_BOILERPLATE(TypeAlias, type_alias)
630
631 const Type* type() const {
632 if (type_) return *type_;
633 return Resolve();
634 }
635 const Type* Resolve() const;
IsRedeclaration()636 bool IsRedeclaration() const { return redeclaration_; }
GetDeclarationPosition()637 SourcePosition GetDeclarationPosition() const {
638 return declaration_position_;
639 }
640
641 private:
642 friend class Declarations;
643 friend class TypeVisitor;
644
645 explicit TypeAlias(
646 const Type* type, bool redeclaration,
647 SourcePosition declaration_position = SourcePosition::Invalid())
Declarable(Declarable::kTypeAlias)648 : Declarable(Declarable::kTypeAlias),
649 type_(type),
650 redeclaration_(redeclaration),
651 declaration_position_(declaration_position) {}
652 explicit TypeAlias(
653 TypeDeclaration* type, bool redeclaration,
654 SourcePosition declaration_position = SourcePosition::Invalid())
Declarable(Declarable::kTypeAlias)655 : Declarable(Declarable::kTypeAlias),
656 delayed_(type),
657 redeclaration_(redeclaration),
658 declaration_position_(declaration_position) {}
659
660 mutable bool being_resolved_ = false;
661 mutable base::Optional<TypeDeclaration*> delayed_;
662 mutable base::Optional<const Type*> type_;
663 bool redeclaration_;
664 const SourcePosition declaration_position_;
665 };
666
667 std::ostream& operator<<(std::ostream& os, const Callable& m);
668 std::ostream& operator<<(std::ostream& os, const Builtin& b);
669 std::ostream& operator<<(std::ostream& os, const RuntimeFunction& b);
670 std::ostream& operator<<(std::ostream& os, const GenericCallable& g);
671
672 #undef DECLARE_DECLARABLE_BOILERPLATE
673
674 } // namespace torque
675 } // namespace internal
676 } // namespace v8
677
678 #endif // V8_TORQUE_DECLARABLE_H_
679