v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
torque-parser.cc
Go to the documentation of this file.
1// Copyright 2018 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
6
7#include <algorithm>
8#include <cctype>
9#include <optional>
10#include <set>
11#include <stdexcept>
12#include <unordered_map>
13
14#include "include/v8config.h"
15#include "src/common/globals.h"
16#include "src/flags/flags.h"
17#include "src/torque/ast.h"
22#include "src/torque/utils.h"
23
24namespace v8::internal::torque {
25
26using TypeList = std::vector<TypeExpression*>;
27
32
35 std::optional<Identifier*> name;
38};
39
40struct EnumEntry {
42 std::optional<TypeExpression*> type;
43 std::optional<std::string> alias_entry;
44};
45
46class BuildFlags : public base::ContextualClass<BuildFlags> {
47 public:
49 build_flags_["V8_EXTERNAL_CODE_SPACE"] = V8_EXTERNAL_CODE_SPACE_BOOL;
50 build_flags_["TAGGED_SIZE_8_BYTES"] = TargetArchitecture::TaggedSize() == 8;
51 build_flags_["V8_ENABLE_EXPERIMENTAL_UNDEFINED_DOUBLE"] =
53#ifdef V8_INTL_SUPPORT
54 build_flags_["V8_INTL_SUPPORT"] = true;
55#else
56 build_flags_["V8_INTL_SUPPORT"] = false;
57#endif
58 build_flags_["V8_ENABLE_SWISS_NAME_DICTIONARY"] =
60#ifdef V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS
61 build_flags_["V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS"] = true;
62#else
63 build_flags_["V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS"] = false;
64#endif
65#ifdef V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA
66 build_flags_["V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA"] = true;
67#else
68 build_flags_["V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA"] = false;
69#endif
70 build_flags_["TRUE_FOR_TESTING"] = true;
71 build_flags_["FALSE_FOR_TESTING"] = false;
72#ifdef V8_SCRIPTORMODULE_LEGACY_LIFETIME
73 build_flags_["V8_SCRIPTORMODULE_LEGACY_LIFETIME"] = true;
74#else
75 build_flags_["V8_SCRIPTORMODULE_LEGACY_LIFETIME"] = false;
76#endif
77#ifdef V8_ENABLE_WEBASSEMBLY
78 build_flags_["V8_ENABLE_WEBASSEMBLY"] = true;
79 build_flags_["WASM_CODE_POINTER_NEEDS_PADDING"] =
81#else
82 build_flags_["V8_ENABLE_WEBASSEMBLY"] = false;
83#endif
84 build_flags_["V8_ENABLE_SANDBOX"] = V8_ENABLE_SANDBOX_BOOL;
85 build_flags_["V8_ENABLE_LEAPTIERING"] = V8_ENABLE_LEAPTIERING_BOOL;
86 build_flags_["V8_ENABLE_LEAPTIERING_TAGGED_SIZE_8_BYTES"] =
87 V8_ENABLE_LEAPTIERING_BOOL && build_flags_["TAGGED_SIZE_8_BYTES"];
88 build_flags_["DEBUG"] = DEBUG_BOOL;
89#ifdef V8_ENABLE_DRUMBRAKE
90 build_flags_["V8_ENABLE_DRUMBRAKE"] = true;
91#else
92 build_flags_["V8_ENABLE_DRUMBRAKE"] = false;
93#endif
94 }
95 static bool GetFlag(const std::string& name, const char* production) {
96 auto it = Get().build_flags_.find(name);
97 if (it == Get().build_flags_.end()) {
98 ReportError("Unknown flag used in ", production, ": ", name,
99 ". Please add it to the list in BuildFlags.");
100 }
101 return it->second;
102 }
103
104 private:
105 std::unordered_map<std::string, bool> build_flags_;
106};
107
108template <>
110 ParseResultTypeId::kStdString;
111template <>
113 ParseResultTypeId::kBool;
114template <>
116 ParseResultTypeId::kInt32;
117template <>
119 ParseResultTypeId::kDouble;
120template <>
122 ParseResultHolder<IntegerLiteral>::id = ParseResultTypeId::kIntegerLiteral;
123template <>
126 ParseResultTypeId::kStdVectorOfString;
127template <>
129 ParseResultTypeId::kDeclarationPtr;
130template <>
133 ParseResultTypeId::kTypeExpressionPtr;
134template <>
137 ParseResultTypeId::kOptionalTypeExpressionPtr;
138template <>
140 ParseResultTypeId::kTryHandlerPtr;
141template <>
143 ParseResultTypeId::kExpressionPtr;
144template <>
146 ParseResultTypeId::kIdentifierPtr;
147template <>
150 ParseResultTypeId::kOptionalIdentifierPtr;
151template <>
153 ParseResultTypeId::kStatementPtr;
154template <>
157 ParseResultTypeId::kNameAndTypeExpression;
158template <>
160 ParseResultTypeId::kEnumEntry;
161template <>
164 ParseResultTypeId::kStdVectorOfEnumEntry;
165template <>
168 ParseResultTypeId::kNameAndExpression;
169template <>
171 ParseResultTypeId::kAnnotation;
172template <>
175 ParseResultTypeId::kVectorOfAnnotation;
176template <>
179 ParseResultTypeId::kAnnotationParameter;
180template <>
183 ParseResultTypeId::kOptionalAnnotationParameter;
184template <>
187 ParseResultTypeId::kClassFieldExpression;
188template <>
191 ParseResultTypeId::kStructFieldExpression;
192template <>
195 ParseResultTypeId::kBitFieldDeclaration;
196template <>
199 ParseResultTypeId::kStdVectorOfNameAndTypeExpression;
200template <>
203 ParseResultTypeId::kImplicitParameters;
204template <>
207 ParseResultTypeId::kOptionalImplicitParameters;
208template <>
211 ParseResultTypeId::kStdVectorOfNameAndExpression;
212template <>
215 ParseResultTypeId::kStdVectorOfClassFieldExpression;
216template <>
219 ParseResultTypeId::kStdVectorOfStructFieldExpression;
220template <>
223 ParseResultTypeId::kStdVectorOfBitFieldDeclaration;
224template <>
227 ParseResultTypeId::kIncrementDecrementOperator;
228template <>
231 ParseResultTypeId::kOptionalStdString;
232template <>
235 ParseResultTypeId::kStdVectorOfStatementPtr;
236template <>
239 ParseResultTypeId::kStdVectorOfDeclarationPtr;
240template <>
243 ParseResultTypeId::kStdVectorOfStdVectorOfDeclarationPtr;
244template <>
247 ParseResultTypeId::kStdVectorOfExpressionPtr;
248template <>
251 ParseResultTypeId::kExpressionWithSource;
252template <>
254 ParseResultTypeId::kParameterList;
255template <>
257 ParseResultTypeId::kTypeList;
258template <>
261 ParseResultTypeId::kOptionalTypeList;
262template <>
264 ParseResultTypeId::kLabelAndTypes;
265template <>
268 ParseResultTypeId::kStdVectorOfLabelAndTypes;
269template <>
272 ParseResultTypeId::kStdVectorOfTryHandlerPtr;
273template <>
276 ParseResultTypeId::kOptionalStatementPtr;
277template <>
280 ParseResultTypeId::kOptionalExpressionPtr;
281template <>
283 ParseResultHolder<TypeswitchCase>::id = ParseResultTypeId::kTypeswitchCase;
284template <>
287 ParseResultTypeId::kStdVectorOfTypeswitchCase;
288template <>
291 ParseResultTypeId::kStdVectorOfIdentifierPtr;
292template <>
295 ParseResultTypeId::kOptionalClassBody;
296template <>
299 ParseResultTypeId::kGenericParameter;
300template <>
303 ParseResultTypeId::kGenericParameters;
304
305namespace {
306
307bool ProcessIfAnnotation(ParseResultIterator* child_results);
308class AnnotationSet;
309bool ProcessIfAnnotation(const AnnotationSet& annotations);
310
311std::optional<ParseResult> AddGlobalDeclarations(
312 ParseResultIterator* child_results) {
313 auto declarations = child_results->NextAs<std::vector<Declaration*>>();
314 for (Declaration* declaration : declarations) {
315 CurrentAst::Get().declarations().push_back(declaration);
316 }
317 return std::nullopt;
318}
319
320void NamingConventionError(const std::string& type, const std::string& name,
321 const std::string& convention,
322 SourcePosition pos = CurrentSourcePosition::Get()) {
323 Lint(type, " \"", name, "\" does not follow \"", convention,
324 "\" naming convention.")
325 .Position(pos);
326}
327
328void NamingConventionError(const std::string& type, const Identifier* name,
329 const std::string& convention) {
330 NamingConventionError(type, name->value, convention, name->pos);
331}
332
333void LintGenericParameters(const GenericParameters& parameters) {
334 for (auto parameter : parameters) {
335 if (!IsUpperCamelCase(parameter.name->value)) {
336 NamingConventionError("Generic parameter", parameter.name,
337 "UpperCamelCase");
338 }
339 }
340}
341
342std::optional<ParseResult> ConcatList(ParseResultIterator* child_results) {
343 auto list_of_lists =
344 child_results->NextAs<std::vector<std::vector<Declaration*>>>();
345 std::vector<Declaration*> result;
346 for (auto& list : list_of_lists) {
347 result.insert(result.end(), list.begin(), list.end());
348 }
349 return ParseResult{std::move(result)};
350}
351
352void CheckNotDeferredStatement(Statement* statement) {
353 CurrentSourcePosition::Scope source_position(statement->pos);
354 if (BlockStatement* block = BlockStatement::DynamicCast(statement)) {
355 if (block->deferred) {
356 Lint(
357 "cannot use deferred with a statement block here, it will have no "
358 "effect");
359 }
360 }
361}
362
363TypeExpression* AddConstexpr(TypeExpression* type) {
364 BasicTypeExpression* basic = BasicTypeExpression::DynamicCast(type);
365 if (!basic) Error("Unsupported extends clause.").Throw();
367 basic->namespace_qualification,
368 MakeNode<Identifier>(CONSTEXPR_TYPE_PREFIX + basic->name->value),
369 basic->generic_arguments);
370}
371
372Expression* MakeCall(IdentifierExpression* callee,
373 std::optional<Expression*> target,
374 std::vector<Expression*> arguments,
375 const std::vector<Statement*>& otherwise) {
376 std::vector<Identifier*> labels;
377
378 // All IdentifierExpressions are treated as label names and can be directly
379 // used as labels identifiers. All other statements in a call's otherwise
380 // must create intermediate Labels for the otherwise's statement code.
381 size_t label_id_count = 0;
382 std::vector<TryHandler*> temp_labels;
383 for (auto* statement : otherwise) {
384 if (auto* e = ExpressionStatement::DynamicCast(statement)) {
385 if (auto* id = IdentifierExpression::DynamicCast(e->expression)) {
386 if (!id->generic_arguments.empty()) {
387 ReportError("An otherwise label cannot have generic parameters");
388 }
389 labels.push_back(id->name);
390 continue;
391 }
392 }
393 auto label_name = std::string("__label") + std::to_string(label_id_count++);
394 auto label_id = MakeNode<Identifier>(label_name);
395 label_id->pos = SourcePosition::Invalid();
396 labels.push_back(label_id);
397 auto* handler =
400 temp_labels.push_back(handler);
401 }
402
403 // Create nested try-label expression for all of the temporary Labels that
404 // were created.
405 Expression* result = nullptr;
406 if (target) {
408 *target, callee, std::move(arguments), std::move(labels));
409 } else {
410 result = MakeNode<CallExpression>(callee, std::move(arguments),
411 std::move(labels));
412 }
413
414 for (auto* label : temp_labels) {
416 }
417 return result;
418}
419
420Expression* MakeCall(Identifier* callee,
421 const std::vector<TypeExpression*>& generic_arguments,
422 const std::vector<Expression*>& arguments,
423 const std::vector<Statement*>& otherwise) {
424 return MakeCall(MakeNode<IdentifierExpression>(callee, generic_arguments),
425 std::nullopt, arguments, otherwise);
426}
427
428std::optional<ParseResult> MakeCall(ParseResultIterator* child_results) {
429 auto callee = child_results->NextAs<Expression*>();
430 auto args = child_results->NextAs<std::vector<Expression*>>();
431 auto otherwise = child_results->NextAs<std::vector<Statement*>>();
432 IdentifierExpression* target = IdentifierExpression::cast(callee);
433 return ParseResult{
434 MakeCall(target, std::nullopt, std::move(args), otherwise)};
435}
436
437std::optional<ParseResult> MakeMethodCall(ParseResultIterator* child_results) {
438 auto this_arg = child_results->NextAs<Expression*>();
439 auto callee = child_results->NextAs<Identifier*>();
440 auto args = child_results->NextAs<std::vector<Expression*>>();
441 auto otherwise = child_results->NextAs<std::vector<Statement*>>();
442 return ParseResult{MakeCall(MakeNode<IdentifierExpression>(callee), this_arg,
443 std::move(args), otherwise)};
444}
445
446std::optional<ParseResult> MakeNewExpression(
447 ParseResultIterator* child_results) {
448 bool pretenured = child_results->NextAs<bool>();
449 bool clear_padding = child_results->NextAs<bool>();
450
451 auto type = child_results->NextAs<TypeExpression*>();
452 auto initializers = child_results->NextAs<std::vector<NameAndExpression>>();
453
454 Expression* result = MakeNode<NewExpression>(type, std::move(initializers),
455 pretenured, clear_padding);
456 return ParseResult{result};
457}
458
459std::optional<ParseResult> MakeBinaryOperator(
460 ParseResultIterator* child_results) {
461 auto left = child_results->NextAs<Expression*>();
462 auto op = child_results->NextAs<Identifier*>();
463 auto right = child_results->NextAs<Expression*>();
464 return ParseResult{MakeCall(op, TypeList{},
465 std::vector<Expression*>{left, right},
466 std::vector<Statement*>{})};
467}
468
469std::optional<ParseResult> MakeIntrinsicCallExpression(
470 ParseResultIterator* child_results) {
471 auto callee = child_results->NextAs<Identifier*>();
472 auto generic_arguments =
473 child_results->NextAs<std::vector<TypeExpression*>>();
474 auto args = child_results->NextAs<std::vector<Expression*>>();
476 callee, std::move(generic_arguments), std::move(args));
477 return ParseResult{result};
478}
479
480std::optional<ParseResult> MakeUnaryOperator(
481 ParseResultIterator* child_results) {
482 auto op = child_results->NextAs<Identifier*>();
483 auto e = child_results->NextAs<Expression*>();
484 return ParseResult{MakeCall(op, TypeList{}, std::vector<Expression*>{e},
485 std::vector<Statement*>{})};
486}
487
488std::optional<ParseResult> MakeSpreadExpression(
489 ParseResultIterator* child_results) {
490 auto spreadee = child_results->NextAs<Expression*>();
492 return ParseResult{result};
493}
494
495std::optional<ParseResult> MakeImplicitParameterList(
496 ParseResultIterator* child_results) {
497 auto kind = child_results->NextAs<Identifier*>();
498 auto parameters = child_results->NextAs<std::vector<NameAndTypeExpression>>();
499 return ParseResult{ImplicitParameters{kind, std::move(parameters)}};
500}
501
502void AddParameter(ParameterList* parameter_list,
503 const NameAndTypeExpression& param) {
504 if (!IsLowerCamelCase(param.name->value)) {
505 NamingConventionError("Parameter", param.name, "lowerCamelCase");
506 }
507 parameter_list->names.push_back(param.name);
508 parameter_list->types.push_back(param.type);
509}
510
511template <bool has_varargs, bool has_explicit_parameter_names>
512std::optional<ParseResult> MakeParameterList(
513 ParseResultIterator* child_results) {
514 auto implicit_params =
515 child_results->NextAs<std::optional<ImplicitParameters>>();
517 result.has_varargs = has_varargs;
518 result.implicit_count = 0;
519 result.implicit_kind = ImplicitKind::kNoImplicit;
520 if (implicit_params) {
521 result.implicit_count = implicit_params->parameters.size();
522 if (implicit_params->kind->value == "implicit") {
523 result.implicit_kind = ImplicitKind::kImplicit;
524 } else {
525 DCHECK_EQ(implicit_params->kind->value, "js-implicit");
526 result.implicit_kind = ImplicitKind::kJSImplicit;
527 }
528 result.implicit_kind_pos = implicit_params->kind->pos;
529 for (NameAndTypeExpression& implicit_param : implicit_params->parameters) {
530 AddParameter(&result, implicit_param);
531 }
532 }
533 if (has_explicit_parameter_names) {
534 auto explicit_params =
535 child_results->NextAs<std::vector<NameAndTypeExpression>>();
536 std::string arguments_variable = "";
537 if (has_varargs) {
538 arguments_variable = child_results->NextAs<std::string>();
539 }
540 for (NameAndTypeExpression& param : explicit_params) {
541 AddParameter(&result, param);
542 }
543 result.arguments_variable = arguments_variable;
544 } else {
545 auto explicit_types = child_results->NextAs<TypeList>();
546 for (auto* explicit_type : explicit_types) {
547 result.types.push_back(explicit_type);
548 }
549 }
550 return ParseResult{std::move(result)};
551}
552
553std::optional<ParseResult> MakeAssertStatement(
554 ParseResultIterator* child_results) {
555 auto kind_string = child_results->NextAs<Identifier*>()->value;
556 auto expr_with_source = child_results->NextAs<ExpressionWithSource>();
558 if (kind_string == "dcheck") {
560 } else if (kind_string == "check") {
562 } else if (kind_string == "sbxcheck") {
563#ifdef V8_ENABLE_SANDBOX
565#else
567#endif // V8_ENABLE_SANDBOX
568 } else if (kind_string == "static_assert") {
570 } else {
571 UNREACHABLE();
572 }
574 kind, expr_with_source.expression, expr_with_source.source);
575 return ParseResult{result};
576}
577
578std::optional<ParseResult> MakeDebugStatement(
579 ParseResultIterator* child_results) {
580 auto kind = child_results->NextAs<Identifier*>()->value;
581 DCHECK(kind == "unreachable" || kind == "debug");
585 return ParseResult{result};
586}
587
588std::optional<ParseResult> DeprecatedMakeVoidType(
589 ParseResultIterator* child_results) {
590 Error("Default void return types are deprecated. Add `: void`.");
592 std::vector<std::string>{}, MakeNode<Identifier>("void"),
593 std::vector<TypeExpression*>{});
594 return ParseResult{result};
595}
596
597std::optional<ParseResult> MakeExternalMacro(
598 ParseResultIterator* child_results) {
599 bool enabled = ProcessIfAnnotation(child_results);
600 auto transitioning = child_results->NextAs<bool>();
601 auto operator_name = child_results->NextAs<std::optional<std::string>>();
602 auto external_assembler_name =
603 child_results->NextAs<std::optional<std::string>>();
604 auto name = child_results->NextAs<Identifier*>();
605 auto generic_parameters = child_results->NextAs<GenericParameters>();
606 LintGenericParameters(generic_parameters);
607
608 auto args = child_results->NextAs<ParameterList>();
609 auto return_type = child_results->NextAs<TypeExpression*>();
610 auto labels = child_results->NextAs<LabelAndTypesVector>();
611
612 std::vector<Declaration*> result = {};
613 if (enabled) {
615 transitioning,
616 external_assembler_name ? *external_assembler_name
617 : "CodeStubAssembler",
618 name, operator_name, args, return_type, std::move(labels))};
619 }
620 if (!generic_parameters.empty()) {
621 Error("External builtins cannot be generic.");
622 }
623 return ParseResult{std::move(result)};
624}
625
626std::optional<ParseResult> MakeIntrinsicDeclaration(
627 ParseResultIterator* child_results) {
628 auto name = child_results->NextAs<Identifier*>();
629 auto generic_parameters = child_results->NextAs<GenericParameters>();
630 LintGenericParameters(generic_parameters);
631
632 auto args = child_results->NextAs<ParameterList>();
633 auto return_type = child_results->NextAs<TypeExpression*>();
634 auto body = child_results->NextAs<std::optional<Statement*>>();
636 if (body) {
638 false, name, std::optional<std::string>{}, args, return_type,
639 LabelAndTypesVector{}, false, body);
640 } else {
641 declaration = MakeNode<IntrinsicDeclaration>(name, args, return_type);
642 }
644 if (!generic_parameters.empty()) {
645 result = MakeNode<GenericCallableDeclaration>(std::move(generic_parameters),
647 }
648 return ParseResult{result};
649}
650
651namespace {
652bool HasAnnotation(ParseResultIterator* child_results, const char* annotation,
653 const char* declaration) {
654 auto annotations = child_results->NextAs<std::vector<Annotation>>();
655 if (!annotations.empty()) {
656 if (annotations.size() > 1 || annotations[0].name->value != annotation) {
657 Error(declaration, " declarations only support a single ", annotation,
658 " annotation");
659 }
660 return true;
661 }
662 return false;
663}
664
665bool HasExportAnnotation(ParseResultIterator* child_results,
666 const char* declaration) {
667 return HasAnnotation(child_results, ANNOTATION_EXPORT, declaration);
668}
669} // namespace
670
671class AnnotationSet {
672 public:
673 AnnotationSet(ParseResultIterator* iter,
674 const std::set<std::string>& allowed_without_param,
675 const std::set<std::string>& allowed_with_param) {
676 auto list = iter->NextAs<std::vector<Annotation>>();
677 for (const Annotation& a : list) {
678 if (a.param.has_value()) {
679 if (allowed_with_param.find(a.name->value) ==
680 allowed_with_param.end()) {
681 const char* error_message =
682 allowed_without_param.find(a.name->value) ==
683 allowed_without_param.end()
684 ? " is not allowed here"
685 : " cannot have parameter here";
686 Lint("Annotation ", a.name->value, error_message)
687 .Position(a.name->pos);
688 }
689 if (!map_.insert({a.name->value, {*a.param, a.name->pos}}).second) {
690 Lint("Duplicate annotation ", a.name->value).Position(a.name->pos);
691 }
692 } else {
693 if (allowed_without_param.find(a.name->value) ==
694 allowed_without_param.end()) {
695 const char* error_message =
696 allowed_with_param.find(a.name->value) == allowed_with_param.end()
697 ? " is not allowed here"
698 : " requires a parameter here";
699 Lint("Annotation ", a.name->value, error_message)
700 .Position(a.name->pos);
701 }
702 if (!set_.insert(a.name->value).second) {
703 Lint("Duplicate annotation ", a.name->value).Position(a.name->pos);
704 }
705 }
706 }
707 }
708
709 bool Contains(const std::string& s) const {
710 return set_.find(s) != set_.end();
711 }
712 std::optional<std::string> GetStringParam(const std::string& s) const {
713 auto it = map_.find(s);
714 if (it == map_.end()) {
715 return {};
716 }
717 if (it->second.first.is_int) {
718 Error("Annotation ", s, " requires a string parameter but has an int")
719 .Position(it->second.second);
720 }
721 return it->second.first.string_value;
722 }
723 std::optional<int32_t> GetIntParam(const std::string& s) const {
724 auto it = map_.find(s);
725 if (it == map_.end()) {
726 return {};
727 }
728 if (!it->second.first.is_int) {
729 Error("Annotation ", s, " requires an int parameter but has a string")
730 .Position(it->second.second);
731 }
732 return it->second.first.int_value;
733 }
734
735 private:
736 std::set<std::string> set_;
737 std::map<std::string, std::pair<AnnotationParameter, SourcePosition>> map_;
738};
739
740std::optional<ParseResult> MakeTorqueMacroDeclaration(
741 ParseResultIterator* child_results) {
742 AnnotationSet annotations(child_results, {ANNOTATION_EXPORT},
744 bool enabled = ProcessIfAnnotation(annotations);
745 bool export_to_csa = annotations.Contains(ANNOTATION_EXPORT);
746 auto transitioning = child_results->NextAs<bool>();
747 auto operator_name = child_results->NextAs<std::optional<std::string>>();
748 auto name = child_results->NextAs<Identifier*>();
749 if (!IsUpperCamelCase(name->value)) {
750 NamingConventionError("Macro", name, "UpperCamelCase");
751 }
752
753 auto generic_parameters = child_results->NextAs<GenericParameters>();
754 LintGenericParameters(generic_parameters);
755
756 auto args = child_results->NextAs<ParameterList>();
757 auto return_type = child_results->NextAs<TypeExpression*>();
758 auto labels = child_results->NextAs<LabelAndTypesVector>();
759 auto body = child_results->NextAs<std::optional<Statement*>>();
760 std::vector<Declaration*> result = {};
761 if (enabled) {
762 CallableDeclaration* declaration = MakeNode<TorqueMacroDeclaration>(
763 transitioning, name, operator_name, args, return_type,
764 std::move(labels), export_to_csa, body);
766 if (generic_parameters.empty()) {
767 if (!body) ReportError("A non-generic declaration needs a body.");
768 } else {
769 if (export_to_csa) ReportError("Cannot export generics to CSA.");
771 std::move(generic_parameters), declaration)};
772 }
773 }
774 return ParseResult{std::move(result)};
775}
776
777std::optional<ParseResult> MakeConstDeclaration(
778 ParseResultIterator* child_results) {
779 bool enabled = ProcessIfAnnotation(child_results);
780 auto name = child_results->NextAs<Identifier*>();
781 if (!IsValidNamespaceConstName(name->value)) {
782 NamingConventionError("Constant", name, "kUpperCamelCase");
783 }
784
785 auto type = child_results->NextAs<TypeExpression*>();
786 auto expression = child_results->NextAs<Expression*>();
787 std::vector<Declaration*> result = {};
788 if (enabled) result = {MakeNode<ConstDeclaration>(name, type, expression)};
789 return ParseResult{std::move(result)};
790}
791
792std::optional<ParseResult> MakeExternConstDeclaration(
793 ParseResultIterator* child_results) {
794 auto name = child_results->NextAs<Identifier*>();
795 auto type = child_results->NextAs<TypeExpression*>();
796 auto literal = child_results->NextAs<std::string>();
797 Declaration* result =
798 MakeNode<ExternConstDeclaration>(name, type, std::move(literal));
799 return ParseResult{result};
800}
801
802std::optional<ParseResult> MakeTypeAliasDeclaration(
803 ParseResultIterator* child_results) {
804 bool enabled = ProcessIfAnnotation(child_results);
805 auto name = child_results->NextAs<Identifier*>();
806 auto type = child_results->NextAs<TypeExpression*>();
807 std::vector<Declaration*> result = {};
808 if (enabled) result = {MakeNode<TypeAliasDeclaration>(name, type)};
809 return ParseResult{std::move(result)};
810}
811
812std::optional<ParseResult> MakeAbstractTypeDeclaration(
813 ParseResultIterator* child_results) {
814 bool use_parent_type_checker = HasAnnotation(
815 child_results, ANNOTATION_USE_PARENT_TYPE_CHECKER, "abstract type");
816 auto transient = child_results->NextAs<bool>();
817 auto name = child_results->NextAs<Identifier*>();
818 if (!IsValidTypeName(name->value)) {
819 NamingConventionError("Type", name, "UpperCamelCase");
820 }
821 auto generic_parameters = child_results->NextAs<GenericParameters>();
822 auto extends = child_results->NextAs<std::optional<TypeExpression*>>();
823 auto generates = child_results->NextAs<std::optional<std::string>>();
825 if (transient) flags |= AbstractTypeFlag::kTransient;
826 if (use_parent_type_checker) flags |= AbstractTypeFlag::kUseParentTypeChecker;
827 TypeDeclaration* type_decl = MakeNode<AbstractTypeDeclaration>(
828 name, flags, extends, std::move(generates));
829 Declaration* decl = type_decl;
830 if (!generic_parameters.empty()) {
831 decl = MakeNode<GenericTypeDeclaration>(generic_parameters, type_decl);
832 }
833
834 auto constexpr_generates =
835 child_results->NextAs<std::optional<std::string>>();
836 std::vector<Declaration*> result{decl};
837
838 if (constexpr_generates) {
839 // Create a AbstractTypeDeclaration for the associated constexpr type.
840 Identifier* constexpr_name =
842 constexpr_name->pos = name->pos;
843
844 std::optional<TypeExpression*> constexpr_extends;
845 if (extends) {
846 constexpr_extends = AddConstexpr(*extends);
847 }
848 TypeDeclaration* constexpr_decl = MakeNode<AbstractTypeDeclaration>(
849 constexpr_name, flags | AbstractTypeFlag::kConstexpr, constexpr_extends,
850 constexpr_generates);
851 constexpr_decl->pos = name->pos;
852 decl = constexpr_decl;
853 if (!generic_parameters.empty()) {
854 decl = MakeNode<GenericTypeDeclaration>(std::move(generic_parameters),
855 constexpr_decl);
856 }
857 result.push_back(decl);
858 }
859
860 return ParseResult{std::move(result)};
861}
862
863std::optional<ParseResult> MakeMethodDeclaration(
864 ParseResultIterator* child_results) {
865 auto transitioning = child_results->NextAs<bool>();
866 auto operator_name = child_results->NextAs<std::optional<std::string>>();
867 auto name = child_results->NextAs<Identifier*>();
868 if (!IsUpperCamelCase(name->value)) {
869 NamingConventionError("Method", name, "UpperCamelCase");
870 }
871
872 auto args = child_results->NextAs<ParameterList>();
873 auto return_type = child_results->NextAs<TypeExpression*>();
874 auto labels = child_results->NextAs<LabelAndTypesVector>();
875 auto body = child_results->NextAs<Statement*>();
877 transitioning, name, operator_name, args, return_type, std::move(labels),
878 false, body);
879 return ParseResult{result};
880}
881
882bool ProcessIfAnnotation(const AnnotationSet& annotations) {
883 if (std::optional<std::string> condition =
884 annotations.GetStringParam(ANNOTATION_IF)) {
885 if (!BuildFlags::GetFlag(*condition, ANNOTATION_IF)) return false;
886 }
887 if (std::optional<std::string> condition =
888 annotations.GetStringParam(ANNOTATION_IFNOT)) {
890 }
891 return true;
892}
893
894bool ProcessIfAnnotation(ParseResultIterator* child_results) {
895 AnnotationSet annotations(child_results, {},
897 return ProcessIfAnnotation(annotations);
898}
899
900std::optional<ParseResult> YieldInt32(ParseResultIterator* child_results) {
901 std::string value = child_results->matched_input().ToString();
902 size_t num_chars_converted = 0;
903 int result = 0;
904 try {
905 result = std::stoi(value, &num_chars_converted, 0);
906 } catch (const std::invalid_argument&) {
907 Error("Expected an integer");
908 return ParseResult{result};
909 } catch (const std::out_of_range&) {
910 Error("Integer out of 32-bit range");
911 return ParseResult{result};
912 }
913 // Tokenizer shouldn't have included extra trailing characters.
914 DCHECK_EQ(num_chars_converted, value.size());
915 return ParseResult{result};
916}
917
918std::optional<ParseResult> YieldDouble(ParseResultIterator* child_results) {
919 std::string value = child_results->matched_input().ToString();
920 size_t num_chars_converted = 0;
921 double result = 0;
922 try {
923 result = std::stod(value, &num_chars_converted);
924 } catch (const std::out_of_range&) {
925 Error("double literal out-of-range");
926 return ParseResult{result};
927 }
928 // Tokenizer shouldn't have included extra trailing characters.
929 DCHECK_EQ(num_chars_converted, value.size());
930 return ParseResult{result};
931}
932
933std::optional<ParseResult> YieldIntegerLiteral(
934 ParseResultIterator* child_results) {
935 std::string value = child_results->matched_input().ToString();
936 // Consume a leading minus.
937 bool negative = false;
938 if (!value.empty() && value[0] == '-') {
939 negative = true;
940 value = value.substr(1);
941 }
942 uint64_t absolute_value;
943 try {
944 size_t parsed = 0;
945 absolute_value = std::stoull(value, &parsed, 0);
946 DCHECK_EQ(parsed, value.size());
947 } catch (const std::invalid_argument&) {
948 Error("integer literal could not be parsed").Throw();
949 } catch (const std::out_of_range&) {
950 Error("integer literal value out of range").Throw();
951 }
952 return ParseResult(IntegerLiteral(negative, absolute_value));
953}
954
955std::optional<ParseResult> MakeStringAnnotationParameter(
956 ParseResultIterator* child_results) {
957 std::string value = child_results->NextAs<std::string>();
958 AnnotationParameter result{value, 0, false};
959 return ParseResult{result};
960}
961
962std::optional<ParseResult> MakeIntAnnotationParameter(
963 ParseResultIterator* child_results) {
964 int32_t value = child_results->NextAs<int32_t>();
965 AnnotationParameter result{"", value, true};
966 return ParseResult{result};
967}
968
969int GetAnnotationValue(const AnnotationSet& annotations, const char* name,
970 int default_value) {
971 auto opt_value = annotations.GetIntParam(name);
972 return opt_value.has_value() ? *opt_value : default_value;
973}
974
975std::optional<ParseResult> MakeTorqueBuiltinDeclaration(
976 ParseResultIterator* child_results) {
977 AnnotationSet annotations(child_results,
980 const bool has_custom_interface_descriptor =
982 std::optional<std::string> use_counter_name =
984 auto transitioning = child_results->NextAs<bool>();
985 auto javascript_linkage = child_results->NextAs<bool>();
986 auto name = child_results->NextAs<Identifier*>();
987 if (!IsUpperCamelCase(name->value)) {
988 NamingConventionError("Builtin", name, "UpperCamelCase");
989 }
990
991 auto generic_parameters = child_results->NextAs<GenericParameters>();
992 LintGenericParameters(generic_parameters);
993
994 auto args = child_results->NextAs<ParameterList>();
995 auto return_type = child_results->NextAs<TypeExpression*>();
996 auto body = child_results->NextAs<std::optional<Statement*>>();
997 CallableDeclaration* declaration = MakeNode<TorqueBuiltinDeclaration>(
998 transitioning, javascript_linkage, name, args, return_type,
999 has_custom_interface_descriptor, use_counter_name, body);
1000 Declaration* result = declaration;
1001 if (generic_parameters.empty()) {
1002 if (!body) ReportError("A non-generic declaration needs a body.");
1003 } else {
1004 result = MakeNode<GenericCallableDeclaration>(std::move(generic_parameters),
1005 declaration);
1006 }
1007 if (use_counter_name && !body) {
1008 ReportError("@incrementUseCounter needs a body.");
1009 }
1010 std::vector<Declaration*> results;
1011 if (std::optional<std::string> condition =
1012 annotations.GetStringParam(ANNOTATION_IF)) {
1014 return ParseResult{std::move(results)};
1015 }
1016 }
1017 results.push_back(result);
1018 return ParseResult{std::move(results)};
1019}
1020
1021InstanceTypeConstraints MakeInstanceTypeConstraints(
1022 const AnnotationSet& annotations) {
1023 InstanceTypeConstraints result;
1024 result.value =
1025 GetAnnotationValue(annotations, ANNOTATION_INSTANCE_TYPE_VALUE, -1);
1026 result.num_flags_bits = GetAnnotationValue(
1028 return result;
1029}
1030
1031std::optional<ParseResult> MakeClassBody(ParseResultIterator* child_results) {
1032 auto methods = child_results->NextAs<std::vector<Declaration*>>();
1033 auto fields = child_results->NextAs<std::vector<ClassFieldExpression>>();
1034 std::optional<ClassBody*> result =
1035 MakeNode<ClassBody>(std::move(methods), std::move(fields));
1036 return ParseResult(result);
1037}
1038
1039std::optional<ParseResult> MakeClassDeclaration(
1040 ParseResultIterator* child_results) {
1041 AnnotationSet annotations(
1042 child_results,
1055 if (annotations.Contains(ANNOTATION_ABSTRACT)) {
1056 flags |= ClassFlag::kAbstract;
1057 }
1060 }
1061 bool do_not_generate_cpp_class =
1064 Error(
1065 "@customCppClass is deprecated. Use 'extern' instead. "
1066 "@generateBodyDescriptor, @generateUniqueMap, and "
1067 "@generateFactoryFunction accomplish most of what '@export "
1068 "@customCppClass' used to.");
1069 }
1070 if (annotations.Contains(ANNOTATION_CUSTOM_MAP)) {
1071 Error(
1072 "@customMap is deprecated. Generating a unique map is opt-in now using "
1073 "@generateUniqueMap.");
1074 }
1077 }
1080 }
1083 }
1086 }
1087 if (annotations.Contains(ANNOTATION_EXPORT)) {
1088 flags |= ClassFlag::kExport;
1089 }
1092 }
1095 }
1098 }
1101 }
1102
1103 auto is_extern = child_results->NextAs<bool>();
1104 if (is_extern) flags |= ClassFlag::kExtern;
1105 auto transient = child_results->NextAs<bool>();
1106 if (transient) flags |= ClassFlag::kTransient;
1107 std::string kind = child_results->NextAs<Identifier*>()->value;
1108 if (kind == "shape") {
1109 flags |= ClassFlag::kIsShape;
1110 flags |= ClassFlag::kTransient;
1113 } else {
1114 DCHECK_EQ(kind, "class");
1115 }
1116 auto name = child_results->NextAs<Identifier*>();
1117 if (!IsValidTypeName(name->value)) {
1118 NamingConventionError("Type", name, "UpperCamelCase");
1119 }
1120 auto extends = child_results->NextAs<TypeExpression*>();
1121 if (!BasicTypeExpression::DynamicCast(extends)) {
1122 ReportError("Expected type name in extends clause.");
1123 }
1124 auto generates = child_results->NextAs<std::optional<std::string>>();
1125 auto body = child_results->NextAs<std::optional<ClassBody*>>();
1126 std::vector<Declaration*> methods;
1127 std::vector<ClassFieldExpression> fields_raw;
1128 if (body.has_value()) {
1129 methods = (*body)->methods;
1130 fields_raw = (*body)->fields;
1131 } else {
1133 }
1134
1135 if (is_extern && body.has_value()) {
1136 if (!do_not_generate_cpp_class) {
1138 }
1139 } else if (do_not_generate_cpp_class) {
1140 Lint("Annotation @doNotGenerateCppClass has no effect");
1141 }
1142
1143 // Filter to only include fields that should be present based on decoration.
1144 std::vector<ClassFieldExpression> fields;
1145 std::copy_if(
1146 fields_raw.begin(), fields_raw.end(), std::back_inserter(fields),
1147 [](const ClassFieldExpression& exp) {
1148 for (const ConditionalAnnotation& condition : exp.conditions) {
1149 if (condition.type == ConditionalAnnotationType::kPositive
1150 ? !BuildFlags::GetFlag(condition.condition, ANNOTATION_IF)
1151 : BuildFlags::GetFlag(condition.condition,
1152 ANNOTATION_IFNOT)) {
1153 return false;
1154 }
1155 }
1156 return true;
1157 });
1158
1159 std::vector<Declaration*> result;
1160
1162 name, flags, extends, generates, std::move(methods), std::move(fields),
1163 MakeInstanceTypeConstraints(annotations)));
1164
1165 Identifier* constexpr_name =
1167 constexpr_name->pos = name->pos;
1168 TypeExpression* constexpr_extends = AddConstexpr(extends);
1170 if (transient) abstract_type_flags |= AbstractTypeFlag::kTransient;
1171 TypeDeclaration* constexpr_decl = MakeNode<AbstractTypeDeclaration>(
1172 constexpr_name, abstract_type_flags, constexpr_extends,
1173 generates ? UnwrapTNodeTypeName(*generates) : name->value);
1174 constexpr_decl->pos = name->pos;
1175 result.push_back(constexpr_decl);
1176
1177 if ((flags & ClassFlag::kDoNotGenerateCast) == 0 &&
1178 (flags & ClassFlag::kIsShape) == 0) {
1179 ParameterList parameters;
1180 parameters.names.push_back(MakeNode<Identifier>("obj"));
1181 parameters.types.push_back(MakeNode<BasicTypeExpression>(
1182 std::vector<std::string>{}, MakeNode<Identifier>("HeapObject"),
1183 std::vector<TypeExpression*>{}));
1184 LabelAndTypesVector labels;
1185 labels.push_back(LabelAndTypes{MakeNode<Identifier>("CastError"),
1186 std::vector<TypeExpression*>{}});
1187
1188 TypeExpression* class_type = MakeNode<BasicTypeExpression>(
1189 std::vector<std::string>{}, name, std::vector<TypeExpression*>{});
1190
1191 std::vector<std::string> namespace_qualification{
1193
1194 IdentifierExpression* internal_downcast_target =
1196 std::move(namespace_qualification),
1197 MakeNode<Identifier>("DownCastForTorqueClass"),
1198 std::vector<TypeExpression*>{class_type});
1199 IdentifierExpression* internal_downcast_otherwise =
1200 MakeNode<IdentifierExpression>(std::vector<std::string>{},
1201 MakeNode<Identifier>("CastError"));
1202
1203 Expression* argument = MakeNode<IdentifierExpression>(
1204 std::vector<std::string>{}, MakeNode<Identifier>("obj"));
1205
1206 auto value = MakeCall(internal_downcast_target, std::nullopt,
1207 std::vector<Expression*>{argument},
1208 std::vector<Statement*>{MakeNode<ExpressionStatement>(
1209 internal_downcast_otherwise)});
1210
1211 auto cast_body = MakeNode<ReturnStatement>(value);
1212
1213 std::vector<TypeExpression*> generic_parameters;
1214 generic_parameters.push_back(MakeNode<BasicTypeExpression>(
1215 std::vector<std::string>{}, name, std::vector<TypeExpression*>{}));
1216
1217 Declaration* specialization = MakeNode<SpecializationDeclaration>(
1218 false, MakeNode<Identifier>("Cast"), std::move(generic_parameters),
1219 std::move(parameters), class_type, std::move(labels), cast_body);
1220 result.push_back(specialization);
1221 }
1222
1223 return ParseResult{std::move(result)};
1224}
1225
1226std::optional<ParseResult> MakeNamespaceDeclaration(
1227 ParseResultIterator* child_results) {
1228 auto name = child_results->NextAs<std::string>();
1229 if (!IsSnakeCase(name)) {
1230 NamingConventionError("Namespace", name, "snake_case");
1231 }
1232 auto declarations = child_results->NextAs<std::vector<Declaration*>>();
1233 Declaration* result =
1234 MakeNode<NamespaceDeclaration>(std::move(name), std::move(declarations));
1235 return ParseResult{result};
1236}
1237
1238std::optional<ParseResult> MakeSpecializationDeclaration(
1239 ParseResultIterator* child_results) {
1240 bool enabled = ProcessIfAnnotation(child_results);
1241 auto transitioning = child_results->NextAs<bool>();
1242 auto name = child_results->NextAs<Identifier*>();
1243 auto generic_parameters =
1244 child_results->NextAs<std::vector<TypeExpression*>>();
1245 auto parameters = child_results->NextAs<ParameterList>();
1246 auto return_type = child_results->NextAs<TypeExpression*>();
1247 auto labels = child_results->NextAs<LabelAndTypesVector>();
1248 auto body = child_results->NextAs<Statement*>();
1249 CheckNotDeferredStatement(body);
1250 std::vector<Declaration*> result = {};
1251 if (enabled) {
1252 result = {MakeNode<SpecializationDeclaration>(
1253 transitioning, std::move(name), std::move(generic_parameters),
1254 std::move(parameters), return_type, std::move(labels), body)};
1255 }
1256 return ParseResult{std::move(result)};
1257}
1258
1259std::optional<ParseResult> MakeStructDeclaration(
1260 ParseResultIterator* child_results) {
1261 bool is_export = HasExportAnnotation(child_results, "Struct");
1262
1263 StructFlags flags = StructFlag::kNone;
1264 if (is_export) flags |= StructFlag::kExport;
1265
1266 auto name = child_results->NextAs<Identifier*>();
1267 if (!IsValidTypeName(name->value)) {
1268 NamingConventionError("Struct", name, "UpperCamelCase");
1269 }
1270 auto generic_parameters = child_results->NextAs<GenericParameters>();
1271 LintGenericParameters(generic_parameters);
1272 auto methods = child_results->NextAs<std::vector<Declaration*>>();
1273 auto fields = child_results->NextAs<std::vector<StructFieldExpression>>();
1274 TypeDeclaration* struct_decl = MakeNode<StructDeclaration>(
1275 flags, name, std::move(methods), std::move(fields));
1276 Declaration* result = struct_decl;
1277 if (!generic_parameters.empty()) {
1278 result = MakeNode<GenericTypeDeclaration>(std::move(generic_parameters),
1279 struct_decl);
1280 }
1281 return ParseResult{result};
1282}
1283
1284std::optional<ParseResult> MakeBitFieldStructDeclaration(
1285 ParseResultIterator* child_results) {
1286 auto name = child_results->NextAs<Identifier*>();
1287 if (!IsValidTypeName(name->value)) {
1288 NamingConventionError("Bitfield struct", name, "UpperCamelCase");
1289 }
1290 auto extends = child_results->NextAs<TypeExpression*>();
1291 auto fields = child_results->NextAs<std::vector<BitFieldDeclaration>>();
1292 Declaration* decl =
1293 MakeNode<BitFieldStructDeclaration>(name, extends, std::move(fields));
1294 return ParseResult{decl};
1295}
1296
1297std::optional<ParseResult> MakeCppIncludeDeclaration(
1298 ParseResultIterator* child_results) {
1299 auto include_path = child_results->NextAs<std::string>();
1300 Declaration* result =
1301 MakeNode<CppIncludeDeclaration>(std::move(include_path));
1302 return ParseResult{result};
1303}
1304
1305std::optional<ParseResult> ProcessTorqueImportDeclaration(
1306 ParseResultIterator* child_results) {
1307 auto import_path = child_results->NextAs<std::string>();
1308 if (!SourceFileMap::FileRelativeToV8RootExists(import_path)) {
1309 Error("File '", import_path, "' not found.");
1310 }
1311
1312 auto import_id = SourceFileMap::GetSourceId(import_path);
1313 if (!import_id.IsValid()) {
1314 // TODO(szuend): Instead of reporting and error. Queue the file up
1315 // for compilation.
1316 Error("File '", import_path, "'is not part of the source set.").Throw();
1317 }
1318
1319 CurrentAst::Get().DeclareImportForCurrentFile(import_id);
1320
1321 return std::nullopt;
1322}
1323
1324std::optional<ParseResult> MakeExternalBuiltin(
1325 ParseResultIterator* child_results) {
1326 auto transitioning = child_results->NextAs<bool>();
1327 auto js_linkage = child_results->NextAs<bool>();
1328 auto name = child_results->NextAs<Identifier*>();
1329 auto generic_parameters = child_results->NextAs<GenericParameters>();
1330 LintGenericParameters(generic_parameters);
1331
1332 auto args = child_results->NextAs<ParameterList>();
1333 auto return_type = child_results->NextAs<TypeExpression*>();
1334 Declaration* result = MakeNode<ExternalBuiltinDeclaration>(
1335 transitioning, js_linkage, name, args, return_type);
1336 if (!generic_parameters.empty()) {
1337 Error("External builtins cannot be generic.");
1338 }
1339 return ParseResult{result};
1340}
1341
1342std::optional<ParseResult> MakeExternalRuntime(
1343 ParseResultIterator* child_results) {
1344 auto transitioning = child_results->NextAs<bool>();
1345 auto name = child_results->NextAs<Identifier*>();
1346 auto args = child_results->NextAs<ParameterList>();
1347 auto return_type = child_results->NextAs<TypeExpression*>();
1348 Declaration* result = MakeNode<ExternalRuntimeDeclaration>(
1349 transitioning, name, args, return_type);
1350 return ParseResult{result};
1351}
1352
1353std::optional<ParseResult> StringLiteralUnquoteAction(
1354 ParseResultIterator* child_results) {
1355 return ParseResult{
1356 StringLiteralUnquote(child_results->NextAs<std::string>())};
1357}
1358
1359std::optional<ParseResult> MakeBasicTypeExpression(
1360 ParseResultIterator* child_results) {
1361 auto namespace_qualification =
1362 child_results->NextAs<std::vector<std::string>>();
1363 auto is_constexpr = child_results->NextAs<bool>();
1364 auto name = child_results->NextAs<std::string>();
1365 auto generic_arguments =
1366 child_results->NextAs<std::vector<TypeExpression*>>();
1367 TypeExpression* result = MakeNode<BasicTypeExpression>(
1368 std::move(namespace_qualification),
1369 MakeNode<Identifier>(is_constexpr ? GetConstexprName(name)
1370 : std::move(name)),
1371 std::move(generic_arguments));
1372 return ParseResult{result};
1373}
1374
1375std::optional<ParseResult> MakeFunctionTypeExpression(
1376 ParseResultIterator* child_results) {
1377 auto parameters = child_results->NextAs<std::vector<TypeExpression*>>();
1378 auto return_type = child_results->NextAs<TypeExpression*>();
1379 TypeExpression* result =
1380 MakeNode<FunctionTypeExpression>(std::move(parameters), return_type);
1381 return ParseResult{result};
1382}
1383
1384std::optional<ParseResult> MakeReferenceTypeExpression(
1385 ParseResultIterator* child_results) {
1386 auto is_const = child_results->NextAs<bool>();
1387 auto referenced_type = child_results->NextAs<TypeExpression*>();
1388 std::vector<std::string> namespace_qualification{
1389 TORQUE_INTERNAL_NAMESPACE_STRING};
1390 std::vector<TypeExpression*> generic_arguments{referenced_type};
1391 TypeExpression* result = MakeNode<BasicTypeExpression>(
1392 std::move(namespace_qualification),
1393 MakeNode<Identifier>(is_const ? CONST_REFERENCE_TYPE_STRING
1394 : MUTABLE_REFERENCE_TYPE_STRING),
1395 std::move(generic_arguments));
1396 return ParseResult{result};
1397}
1398
1399std::optional<ParseResult> MakeUnionTypeExpression(
1400 ParseResultIterator* child_results) {
1401 auto a = child_results->NextAs<TypeExpression*>();
1402 auto b = child_results->NextAs<TypeExpression*>();
1403 TypeExpression* result = MakeNode<UnionTypeExpression>(a, b);
1404 return ParseResult{result};
1405}
1406
1407std::optional<ParseResult> MakeGenericParameter(
1408 ParseResultIterator* child_results) {
1409 auto name = child_results->NextAs<Identifier*>();
1410 auto constraint = child_results->NextAs<std::optional<TypeExpression*>>();
1411 return ParseResult{GenericParameter{name, constraint}};
1412}
1413
1414std::optional<ParseResult> MakeExpressionStatement(
1415 ParseResultIterator* child_results) {
1416 auto expression = child_results->NextAs<Expression*>();
1417 Statement* result = MakeNode<ExpressionStatement>(expression);
1418 return ParseResult{result};
1419}
1420
1421std::optional<ParseResult> MakeIfStatement(ParseResultIterator* child_results) {
1422 auto is_constexpr = child_results->NextAs<bool>();
1423 auto condition = child_results->NextAs<Expression*>();
1424 auto if_true = child_results->NextAs<Statement*>();
1425 auto if_false = child_results->NextAs<std::optional<Statement*>>();
1426
1427 if (if_false && !(BlockStatement::DynamicCast(if_true) &&
1428 (BlockStatement::DynamicCast(*if_false) ||
1429 IfStatement::DynamicCast(*if_false)))) {
1430 ReportError("if-else statements require curly braces");
1431 }
1432
1433 if (is_constexpr) {
1434 CheckNotDeferredStatement(if_true);
1435 if (if_false) CheckNotDeferredStatement(*if_false);
1436 }
1437
1438 Statement* result =
1439 MakeNode<IfStatement>(is_constexpr, condition, if_true, if_false);
1440 return ParseResult{result};
1441}
1442
1443std::optional<ParseResult> MakeEnumDeclaration(
1444 ParseResultIterator* child_results) {
1445 const bool is_extern = child_results->NextAs<bool>();
1446 auto name_identifier = child_results->NextAs<Identifier*>();
1447 auto name = name_identifier->value;
1448 auto base_type_expression =
1449 child_results->NextAs<std::optional<TypeExpression*>>();
1450 auto constexpr_generates_opt =
1451 child_results->NextAs<std::optional<std::string>>();
1452 auto entries = child_results->NextAs<std::vector<EnumEntry>>();
1453 const bool is_open = child_results->NextAs<bool>();
1454 CurrentSourcePosition::Scope current_source_position(
1455 child_results->matched_input().pos);
1456
1457 if (!is_extern) {
1458 ReportError("non-extern enums are not supported yet");
1459 }
1460
1461 if (!IsValidTypeName(name)) {
1462 NamingConventionError("Type", name, "UpperCamelCase");
1463 }
1464
1465 if (constexpr_generates_opt && *constexpr_generates_opt == name) {
1466 Lint("Unnecessary 'constexpr' clause for enum ", name);
1467 }
1468 auto constexpr_generates =
1469 constexpr_generates_opt ? *constexpr_generates_opt : name;
1470 const bool generate_nonconstexpr = base_type_expression.has_value();
1471
1472 std::vector<Declaration*> result;
1473 // Build non-constexpr types.
1474 if (generate_nonconstexpr) {
1475 DCHECK(base_type_expression.has_value());
1476
1477 if (is_open) {
1478 // For open enumerations, we define an abstract type and inherit all
1479 // entries' types from that:
1480 // type Enum extends Base;
1481 // namespace Enum {
1482 // type kEntry0 extends Enum;
1483 // ...
1484 // type kEntryN extends Enum;
1485 // }
1486 auto type_decl = MakeNode<AbstractTypeDeclaration>(
1487 name_identifier, AbstractTypeFlag::kNone, base_type_expression,
1488 std::nullopt);
1489
1490 TypeExpression* name_type_expression =
1491 MakeNode<BasicTypeExpression>(name_identifier);
1492 name_type_expression->pos = name_identifier->pos;
1493
1494 std::vector<Declaration*> entry_decls;
1495 entry_decls.reserve(entries.size());
1496 for (const auto& entry : entries) {
1497 entry_decls.push_back(MakeNode<AbstractTypeDeclaration>(
1498 entry.name, AbstractTypeFlag::kNone,
1499 entry.type.value_or(name_type_expression), std::nullopt));
1500 }
1501
1502 result.push_back(type_decl);
1503 result.push_back(
1504 MakeNode<NamespaceDeclaration>(name, std::move(entry_decls)));
1505 } else {
1506 // For closed enumerations, we define abstract types for all entries and
1507 // define the enumeration as a union of those:
1508 // namespace Enum {
1509 // type kEntry0 extends Base;
1510 // ...
1511 // type kEntryN extends Base;
1512 // }
1513 // type Enum = Enum::kEntry0 | ... | Enum::kEntryN;
1514 TypeExpression* union_type = nullptr;
1515 std::vector<Declaration*> entry_decls;
1516 for (const auto& entry : entries) {
1517 entry_decls.push_back(MakeNode<AbstractTypeDeclaration>(
1518 entry.name, AbstractTypeFlag::kNone,
1519 entry.type.value_or(*base_type_expression), std::nullopt));
1520
1521 auto entry_type = MakeNode<BasicTypeExpression>(
1522 std::vector<std::string>{name}, entry.name,
1523 std::vector<TypeExpression*>{});
1524 if (union_type) {
1525 union_type = MakeNode<UnionTypeExpression>(union_type, entry_type);
1526 } else {
1527 union_type = entry_type;
1528 }
1529 }
1530
1531 result.push_back(
1532 MakeNode<NamespaceDeclaration>(name, std::move(entry_decls)));
1533 result.push_back(
1534 MakeNode<TypeAliasDeclaration>(name_identifier, union_type));
1535 }
1536 }
1537
1538 // Build constexpr types.
1539 {
1540 // The constexpr entries inherit from an abstract enumeration type:
1541 // type constexpr Enum extends constexpr Base;
1542 // namespace Enum {
1543 // type constexpr kEntry0 extends constexpr Enum;
1544 // ...
1545 // type constexpr kEntry1 extends constexpr Enum;
1546 // }
1547 Identifier* constexpr_type_identifier =
1548 MakeNode<Identifier>(std::string(CONSTEXPR_TYPE_PREFIX) + name);
1549 TypeExpression* constexpr_type_expression = MakeNode<BasicTypeExpression>(
1550 MakeNode<Identifier>(std::string(CONSTEXPR_TYPE_PREFIX) + name));
1551 std::optional<TypeExpression*> base_constexpr_type_expression =
1552 std::nullopt;
1553 if (base_type_expression) {
1554 base_constexpr_type_expression = AddConstexpr(*base_type_expression);
1555 }
1556 result.push_back(MakeNode<AbstractTypeDeclaration>(
1557 constexpr_type_identifier, AbstractTypeFlag::kConstexpr,
1558 base_constexpr_type_expression, constexpr_generates));
1559
1560 TypeExpression* type_expr = nullptr;
1561 Identifier* fromconstexpr_identifier = nullptr;
1562 Identifier* fromconstexpr_parameter_identifier = nullptr;
1563 Statement* fromconstexpr_body = nullptr;
1564 if (generate_nonconstexpr) {
1565 DCHECK(base_type_expression.has_value());
1566 type_expr = MakeNode<BasicTypeExpression>(std::vector<std::string>{},
1567 MakeNode<Identifier>(name),
1568 std::vector<TypeExpression*>{});
1569
1570 // return %RawDownCast<Enum>(%FromConstexpr<Base>(o)))
1571 fromconstexpr_identifier = MakeNode<Identifier>("FromConstexpr");
1572 fromconstexpr_parameter_identifier = MakeNode<Identifier>("o");
1573 fromconstexpr_body =
1574 MakeNode<ReturnStatement>(MakeNode<IntrinsicCallExpression>(
1575 MakeNode<Identifier>("%RawDownCast"),
1576 std::vector<TypeExpression*>{type_expr},
1577 std::vector<Expression*>{MakeNode<IntrinsicCallExpression>(
1578 MakeNode<Identifier>("%FromConstexpr"),
1579 std::vector<TypeExpression*>{*base_type_expression},
1580 std::vector<Expression*>{MakeNode<IdentifierExpression>(
1581 std::vector<std::string>{},
1582 fromconstexpr_parameter_identifier)})}));
1583 }
1584
1585 EnumDescription enum_description{CurrentSourcePosition::Get(), name,
1586 constexpr_generates, is_open};
1587 std::vector<Declaration*> entry_decls;
1588 for (const auto& entry : entries) {
1589 const std::string entry_name = entry.name->value;
1590 const std::string entry_constexpr_type =
1591 CONSTEXPR_TYPE_PREFIX + entry_name;
1592 std::string alias_entry;
1593 if (entry.alias_entry) {
1594 alias_entry = constexpr_generates + "::" + *entry.alias_entry;
1595 }
1596 enum_description.entries.emplace_back(
1597 constexpr_generates + "::" + entry_name, alias_entry);
1598
1599 entry_decls.push_back(MakeNode<AbstractTypeDeclaration>(
1600 MakeNode<Identifier>(entry_constexpr_type),
1601 AbstractTypeFlag::kConstexpr, constexpr_type_expression,
1602 constexpr_generates));
1603
1604 bool generate_typed_constant = entry.type.has_value();
1605 if (generate_typed_constant) {
1606 // namespace Enum {
1607 // const constexpr_constant_kEntry0: constexpr kEntry0 constexpr
1608 // 'Enum::kEntry0'; const kEntry0 = %RawDownCast<T,
1609 // Base>(FromConstexpr<Enum>(constexpr_constant_kEntry0));
1610 // }
1611 if (!generate_nonconstexpr) {
1612 Error(
1613 "Enum constants with custom types require an enum with an "
1614 "extends clause.")
1615 .Position((*entry.type)->pos);
1616 }
1617 Identifier* constexpr_constant_name =
1618 MakeNode<Identifier>("constexpr constant " + entry_name);
1619 entry_decls.push_back(MakeNode<ExternConstDeclaration>(
1620 constexpr_constant_name,
1621 MakeNode<BasicTypeExpression>(
1622 std::vector<std::string>{},
1623 MakeNode<Identifier>(entry_constexpr_type),
1624 std::vector<TypeExpression*>{}),
1625 constexpr_generates + "::" + entry_name));
1626 entry_decls.push_back(MakeNode<ConstDeclaration>(
1627 entry.name, *entry.type,
1628 MakeNode<IntrinsicCallExpression>(
1629 MakeNode<Identifier>("%RawDownCast"),
1630 std::vector<TypeExpression*>{*entry.type,
1631 *base_type_expression},
1632 std::vector<Expression*>{MakeCall(
1633 MakeNode<Identifier>("FromConstexpr"), {type_expr},
1634 {MakeNode<IdentifierExpression>(std::vector<std::string>{},
1635 constexpr_constant_name)},
1636 {})})));
1637 } else {
1638 // namespace Enum {
1639 // const kEntry0: constexpr kEntry0 constexpr 'Enum::kEntry0';
1640 // }
1641 entry_decls.push_back(MakeNode<ExternConstDeclaration>(
1642 entry.name,
1643 MakeNode<BasicTypeExpression>(
1644 std::vector<std::string>{},
1645 MakeNode<Identifier>(entry_constexpr_type),
1646 std::vector<TypeExpression*>{}),
1647 constexpr_generates + "::" + entry_name));
1648 }
1649
1650 // FromConstexpr<Enum, Enum::constexpr kEntry0>(
1651 // : Enum::constexpr kEntry0): Enum
1652 if (generate_nonconstexpr) {
1653 TypeExpression* entry_constexpr_type_expr =
1654 MakeNode<BasicTypeExpression>(
1655 std::vector<std::string>{name},
1656 MakeNode<Identifier>(entry_constexpr_type),
1657 std::vector<TypeExpression*>{});
1658
1659 ParameterList parameters;
1660 parameters.names.push_back(fromconstexpr_parameter_identifier);
1661 parameters.types.push_back(entry_constexpr_type_expr);
1662 result.push_back(MakeNode<SpecializationDeclaration>(
1663 false, fromconstexpr_identifier,
1664 std::vector<TypeExpression*>{type_expr, entry_constexpr_type_expr},
1665 std::move(parameters), type_expr, LabelAndTypesVector{},
1666 fromconstexpr_body));
1667 }
1668 }
1669
1670 result.push_back(
1671 MakeNode<NamespaceDeclaration>(name, std::move(entry_decls)));
1672 CurrentAst::Get().AddEnumDescription(std::move(enum_description));
1673 }
1674
1675 return ParseResult{std::move(result)};
1676}
1677
1678std::optional<ParseResult> MakeTypeswitchStatement(
1679 ParseResultIterator* child_results) {
1680 auto expression = child_results->NextAs<Expression*>();
1681 auto cases = child_results->NextAs<std::vector<TypeswitchCase>>();
1682 CurrentSourcePosition::Scope matched_input_current_source_position(
1683 child_results->matched_input().pos);
1684
1685 // typeswitch (expression) case (x1 : T1) {
1686 // ...b1
1687 // } case (x2 : T2) {
1688 // ...b2
1689 // } case (x3 : T3) {
1690 // ...b3
1691 // }
1692 //
1693 // desugars to
1694 //
1695 // {
1696 // const _value = expression;
1697 // try {
1698 // const x1 : T1 = cast<T1>(_value) otherwise _NextCase;
1699 // ...b1
1700 // } label _NextCase {
1701 // try {
1702 // const x2 : T2 = cast<T2>(%assume_impossible<T1>(_value));
1703 // ...b2
1704 // } label _NextCase {
1705 // const x3 : T3 = %assume_impossible<T1|T2>(_value);
1706 // ...b3
1707 // }
1708 // }
1709 // }
1710
1711 BlockStatement* current_block = MakeNode<BlockStatement>();
1712 Statement* result = current_block;
1713 {
1714 CurrentSourcePosition::Scope current_source_position(expression->pos);
1715 current_block->statements.push_back(MakeNode<VarDeclarationStatement>(
1716 true, MakeNode<Identifier>("__value"), std::nullopt, expression));
1717 }
1718
1719 TypeExpression* accumulated_types;
1720 for (size_t i = 0; i < cases.size(); ++i) {
1721 CurrentSourcePosition::Scope current_source_position(cases[i].pos);
1722 Expression* value =
1723 MakeNode<IdentifierExpression>(MakeNode<Identifier>("__value"));
1724 if (i >= 1) {
1725 value =
1726 MakeNode<AssumeTypeImpossibleExpression>(accumulated_types, value);
1727 }
1728 BlockStatement* case_block;
1729 if (i < cases.size() - 1) {
1730 value = MakeCall(MakeNode<Identifier>("Cast"),
1731 std::vector<TypeExpression*>{cases[i].type},
1732 std::vector<Expression*>{value},
1733 std::vector<Statement*>{MakeNode<ExpressionStatement>(
1734 MakeNode<IdentifierExpression>(
1735 MakeNode<Identifier>(kNextCaseLabelName)))});
1736 case_block = MakeNode<BlockStatement>();
1737 } else {
1738 case_block = current_block;
1739 }
1740 Identifier* name =
1741 cases[i].name ? *cases[i].name : MakeNode<Identifier>("__case_value");
1742 if (cases[i].name) name = *cases[i].name;
1743 case_block->statements.push_back(
1744 MakeNode<VarDeclarationStatement>(true, name, cases[i].type, value));
1745 case_block->statements.push_back(cases[i].block);
1746 if (i < cases.size() - 1) {
1747 BlockStatement* next_block = MakeNode<BlockStatement>();
1748 current_block->statements.push_back(
1749 MakeNode<ExpressionStatement>(MakeNode<TryLabelExpression>(
1750 MakeNode<StatementExpression>(case_block),
1751 MakeNode<TryHandler>(TryHandler::HandlerKind::kLabel,
1752 MakeNode<Identifier>(kNextCaseLabelName),
1753 ParameterList::Empty(), next_block))));
1754 current_block = next_block;
1755 }
1756 accumulated_types =
1757 i > 0 ? MakeNode<UnionTypeExpression>(accumulated_types, cases[i].type)
1758 : cases[i].type;
1759 }
1760 return ParseResult{result};
1761}
1762
1763std::optional<ParseResult> MakeTypeswitchCase(
1764 ParseResultIterator* child_results) {
1765 auto name = child_results->NextAs<std::optional<Identifier*>>();
1766 auto type = child_results->NextAs<TypeExpression*>();
1767 auto block = child_results->NextAs<Statement*>();
1768 return ParseResult{
1769 TypeswitchCase{child_results->matched_input().pos, name, type, block}};
1770}
1771
1772std::optional<ParseResult> MakeWhileStatement(
1773 ParseResultIterator* child_results) {
1774 auto condition = child_results->NextAs<Expression*>();
1775 auto body = child_results->NextAs<Statement*>();
1776 Statement* result = MakeNode<WhileStatement>(condition, body);
1777 CheckNotDeferredStatement(result);
1778 return ParseResult{result};
1779}
1780
1781std::optional<ParseResult> MakeReturnStatement(
1782 ParseResultIterator* child_results) {
1783 auto value = child_results->NextAs<std::optional<Expression*>>();
1784 Statement* result = MakeNode<ReturnStatement>(value);
1785 return ParseResult{result};
1786}
1787
1788std::optional<ParseResult> MakeTailCallStatement(
1789 ParseResultIterator* child_results) {
1790 auto value = child_results->NextAs<Expression*>();
1791 Statement* result = MakeNode<TailCallStatement>(CallExpression::cast(value));
1792 return ParseResult{result};
1793}
1794
1795std::optional<ParseResult> MakeVarDeclarationStatement(
1796 ParseResultIterator* child_results) {
1797 auto kind = child_results->NextAs<Identifier*>();
1798 bool const_qualified = kind->value == "const";
1799 if (!const_qualified) DCHECK_EQ("let", kind->value);
1800 auto name = child_results->NextAs<Identifier*>();
1801 if (!IsLowerCamelCase(name->value)) {
1802 NamingConventionError("Variable", name, "lowerCamelCase");
1803 }
1804
1805 auto type = child_results->NextAs<std::optional<TypeExpression*>>();
1806 std::optional<Expression*> initializer;
1807 if (child_results->HasNext())
1808 initializer = child_results->NextAs<Expression*>();
1809 if (!initializer && !type) {
1810 ReportError("Declaration is missing a type.");
1811 }
1812 Statement* result = MakeNode<VarDeclarationStatement>(const_qualified, name,
1813 type, initializer);
1814 return ParseResult{result};
1815}
1816
1817std::optional<ParseResult> MakeBreakStatement(
1818 ParseResultIterator* child_results) {
1819 Statement* result = MakeNode<BreakStatement>();
1820 return ParseResult{result};
1821}
1822
1823std::optional<ParseResult> MakeContinueStatement(
1824 ParseResultIterator* child_results) {
1825 Statement* result = MakeNode<ContinueStatement>();
1826 return ParseResult{result};
1827}
1828
1829std::optional<ParseResult> MakeGotoStatement(
1830 ParseResultIterator* child_results) {
1831 auto label = child_results->NextAs<Identifier*>();
1832 auto arguments = child_results->NextAs<std::vector<Expression*>>();
1833 Statement* result = MakeNode<GotoStatement>(label, std::move(arguments));
1834 return ParseResult{result};
1835}
1836
1837std::optional<ParseResult> MakeBlockStatement(
1838 ParseResultIterator* child_results) {
1839 auto deferred = child_results->NextAs<bool>();
1840 auto statements = child_results->NextAs<std::vector<Statement*>>();
1841 for (Statement* statement : statements) {
1842 CheckNotDeferredStatement(statement);
1843 }
1844 Statement* result = MakeNode<BlockStatement>(deferred, std::move(statements));
1845 return ParseResult{result};
1846}
1847
1848std::optional<ParseResult> MakeTryLabelExpression(
1849 ParseResultIterator* child_results) {
1850 auto try_block = child_results->NextAs<Statement*>();
1851 CheckNotDeferredStatement(try_block);
1852 Statement* result = try_block;
1853 auto handlers = child_results->NextAs<std::vector<TryHandler*>>();
1854 if (handlers.empty()) {
1855 Error("Try blocks without catch or label don't make sense.");
1856 }
1857 for (size_t i = 0; i < handlers.size(); ++i) {
1858 if (i != 0 &&
1859 handlers[i]->handler_kind == TryHandler::HandlerKind::kCatch) {
1860 Error(
1861 "A catch handler always has to be first, before any label handler, "
1862 "to avoid ambiguity about whether it catches exceptions from "
1863 "preceding handlers or not.")
1864 .Position(handlers[i]->pos);
1865 }
1866 result = MakeNode<ExpressionStatement>(MakeNode<TryLabelExpression>(
1867 MakeNode<StatementExpression>(result), handlers[i]));
1868 }
1869 return ParseResult{result};
1870}
1871
1872std::optional<ParseResult> MakeForLoopStatement(
1873 ParseResultIterator* child_results) {
1874 auto var_decl = child_results->NextAs<std::optional<Statement*>>();
1875 auto test = child_results->NextAs<std::optional<Expression*>>();
1876 auto action = child_results->NextAs<std::optional<Expression*>>();
1877 std::optional<Statement*> action_stmt;
1878 if (action) action_stmt = MakeNode<ExpressionStatement>(*action);
1879 auto body = child_results->NextAs<Statement*>();
1880 CheckNotDeferredStatement(body);
1881 Statement* result =
1882 MakeNode<ForLoopStatement>(var_decl, test, action_stmt, body);
1883 return ParseResult{result};
1884}
1885
1886std::optional<ParseResult> MakeLabelBlock(ParseResultIterator* child_results) {
1887 auto label = child_results->NextAs<Identifier*>();
1888 if (!IsUpperCamelCase(label->value)) {
1889 NamingConventionError("Label", label, "UpperCamelCase");
1890 }
1891 auto parameters = child_results->NextAs<ParameterList>();
1892 auto body = child_results->NextAs<Statement*>();
1893 TryHandler* result = MakeNode<TryHandler>(TryHandler::HandlerKind::kLabel,
1894 label, std::move(parameters), body);
1895 return ParseResult{result};
1896}
1897
1898std::optional<ParseResult> MakeCatchBlock(ParseResultIterator* child_results) {
1899 auto parameter_names = child_results->NextAs<std::vector<std::string>>();
1900 auto body = child_results->NextAs<Statement*>();
1901 for (const std::string& variable : parameter_names) {
1902 if (!IsLowerCamelCase(variable)) {
1903 NamingConventionError("Exception", variable, "lowerCamelCase");
1904 }
1905 }
1906 if (parameter_names.size() != 2) {
1908 "A catch clause needs to have exactly two parameters: The exception "
1909 "and the message. How about: \"catch (exception, message) { ...\".");
1910 }
1911 ParameterList parameters;
1912
1913 parameters.names.push_back(MakeNode<Identifier>(parameter_names[0]));
1914 parameters.types.push_back(MakeNode<BasicTypeExpression>(
1915 std::vector<std::string>{}, MakeNode<Identifier>("JSAny"),
1916 std::vector<TypeExpression*>{}));
1917 parameters.names.push_back(MakeNode<Identifier>(parameter_names[1]));
1918 parameters.types.push_back(MakeNode<UnionTypeExpression>(
1919 MakeNode<BasicTypeExpression>(std::vector<std::string>{},
1920 MakeNode<Identifier>("JSMessageObject"),
1921 std::vector<TypeExpression*>{}),
1922 MakeNode<BasicTypeExpression>(std::vector<std::string>{},
1923 MakeNode<Identifier>("TheHole"),
1924 std::vector<TypeExpression*>{})));
1925 parameters.has_varargs = false;
1926 TryHandler* result = MakeNode<TryHandler>(
1927 TryHandler::HandlerKind::kCatch, MakeNode<Identifier>(kCatchLabelName),
1928 std::move(parameters), body);
1929 return ParseResult{result};
1930}
1931
1932std::optional<ParseResult> MakeExpressionWithSource(
1933 ParseResultIterator* child_results) {
1934 auto e = child_results->NextAs<Expression*>();
1935 return ParseResult{
1936 ExpressionWithSource{e, child_results->matched_input().ToString()}};
1937}
1938
1939std::optional<ParseResult> MakeIdentifier(ParseResultIterator* child_results) {
1940 auto name = child_results->NextAs<std::string>();
1941 Identifier* result = MakeNode<Identifier>(std::move(name));
1942 return ParseResult{result};
1943}
1944
1945std::optional<ParseResult> MakeIdentifierFromMatchedInput(
1946 ParseResultIterator* child_results) {
1947 return ParseResult{
1948 MakeNode<Identifier>(child_results->matched_input().ToString())};
1949}
1950
1951std::optional<ParseResult> MakeRightShiftIdentifier(
1952 ParseResultIterator* child_results) {
1953 std::string str = child_results->matched_input().ToString();
1954 for (auto character : str) {
1955 if (character != '>') {
1956 ReportError("right-shift operators may not contain any whitespace");
1957 }
1958 }
1959 return ParseResult{MakeNode<Identifier>(str)};
1960}
1961
1962std::optional<ParseResult> MakeNamespaceQualification(
1963 ParseResultIterator* child_results) {
1964 bool global_namespace = child_results->NextAs<bool>();
1965 auto namespace_qualification =
1966 child_results->NextAs<std::vector<std::string>>();
1967 if (global_namespace) {
1968 namespace_qualification.insert(namespace_qualification.begin(), "");
1969 }
1970 return ParseResult(std::move(namespace_qualification));
1971}
1972
1973std::optional<ParseResult> MakeIdentifierExpression(
1974 ParseResultIterator* child_results) {
1975 auto namespace_qualification =
1976 child_results->NextAs<std::vector<std::string>>();
1977 auto name = child_results->NextAs<Identifier*>();
1978 auto generic_arguments =
1979 child_results->NextAs<std::vector<TypeExpression*>>();
1980 Expression* result = MakeNode<IdentifierExpression>(
1981 std::move(namespace_qualification), name, std::move(generic_arguments));
1982 return ParseResult{result};
1983}
1984
1985std::optional<ParseResult> MakeFieldAccessExpression(
1986 ParseResultIterator* child_results) {
1987 auto object = child_results->NextAs<Expression*>();
1988 auto field = child_results->NextAs<Identifier*>();
1989 Expression* result = MakeNode<FieldAccessExpression>(object, field);
1990 return ParseResult{result};
1991}
1992
1993std::optional<ParseResult> MakeReferenceFieldAccessExpression(
1994 ParseResultIterator* child_results) {
1995 auto object = child_results->NextAs<Expression*>();
1996 auto field = child_results->NextAs<Identifier*>();
1997 // `a->b` is equivalent to `(*a).b`.
1998 Expression* deref = MakeNode<DereferenceExpression>(object);
1999 Expression* result = MakeNode<FieldAccessExpression>(deref, field);
2000 return ParseResult{result};
2001}
2002
2003std::optional<ParseResult> MakeElementAccessExpression(
2004 ParseResultIterator* child_results) {
2005 auto object = child_results->NextAs<Expression*>();
2006 auto field = child_results->NextAs<Expression*>();
2007 Expression* result = MakeNode<ElementAccessExpression>(object, field);
2008 return ParseResult{result};
2009}
2010
2011std::optional<ParseResult> MakeDereferenceExpression(
2012 ParseResultIterator* child_results) {
2013 auto reference = child_results->NextAs<Expression*>();
2014 Expression* result = MakeNode<DereferenceExpression>(reference);
2015 return ParseResult{result};
2016}
2017
2018std::optional<ParseResult> MakeStructExpression(
2019 ParseResultIterator* child_results) {
2020 auto type = child_results->NextAs<TypeExpression*>();
2021 auto initializers = child_results->NextAs<std::vector<NameAndExpression>>();
2022 Expression* result =
2023 MakeNode<StructExpression>(type, std::move(initializers));
2024 return ParseResult{result};
2025}
2026
2027std::optional<ParseResult> MakeAssignmentExpression(
2028 ParseResultIterator* child_results) {
2029 auto location = child_results->NextAs<Expression*>();
2030 auto op = child_results->NextAs<std::optional<std::string>>();
2031 auto value = child_results->NextAs<Expression*>();
2032 Expression* result =
2033 MakeNode<AssignmentExpression>(location, std::move(op), value);
2034 return ParseResult{result};
2035}
2036
2037std::optional<ParseResult> MakeFloatingPointLiteralExpression(
2038 ParseResultIterator* child_results) {
2039 auto value = child_results->NextAs<double>();
2040 Expression* result = MakeNode<FloatingPointLiteralExpression>(value);
2041 return ParseResult{result};
2042}
2043
2044std::optional<ParseResult> MakeIntegerLiteralExpression(
2045 ParseResultIterator* child_results) {
2046 auto value = child_results->NextAs<IntegerLiteral>();
2047 Expression* result = MakeNode<IntegerLiteralExpression>(std::move(value));
2048 return ParseResult{result};
2049}
2050
2051std::optional<ParseResult> MakeStringLiteralExpression(
2052 ParseResultIterator* child_results) {
2053 auto literal = child_results->NextAs<std::string>();
2054 Expression* result = MakeNode<StringLiteralExpression>(std::move(literal));
2055 return ParseResult{result};
2056}
2057
2058std::optional<ParseResult> MakeIncrementDecrementExpressionPostfix(
2059 ParseResultIterator* child_results) {
2060 auto location = child_results->NextAs<Expression*>();
2061 auto op = child_results->NextAs<IncrementDecrementOperator>();
2062 Expression* result =
2063 MakeNode<IncrementDecrementExpression>(location, op, true);
2064 return ParseResult{result};
2065}
2066
2067std::optional<ParseResult> MakeIncrementDecrementExpressionPrefix(
2068 ParseResultIterator* child_results) {
2069 auto op = child_results->NextAs<IncrementDecrementOperator>();
2070 auto location = child_results->NextAs<Expression*>();
2071 Expression* result =
2072 MakeNode<IncrementDecrementExpression>(location, op, false);
2073 return ParseResult{result};
2074}
2075
2076std::optional<ParseResult> MakeLogicalOrExpression(
2077 ParseResultIterator* child_results) {
2078 auto left = child_results->NextAs<Expression*>();
2079 auto right = child_results->NextAs<Expression*>();
2080 Expression* result = MakeNode<LogicalOrExpression>(left, right);
2081 return ParseResult{result};
2082}
2083
2084std::optional<ParseResult> MakeLogicalAndExpression(
2085 ParseResultIterator* child_results) {
2086 auto left = child_results->NextAs<Expression*>();
2087 auto right = child_results->NextAs<Expression*>();
2088 Expression* result = MakeNode<LogicalAndExpression>(left, right);
2089 return ParseResult{result};
2090}
2091
2092std::optional<ParseResult> MakeConditionalExpression(
2093 ParseResultIterator* child_results) {
2094 auto condition = child_results->NextAs<Expression*>();
2095 auto if_true = child_results->NextAs<Expression*>();
2096 auto if_false = child_results->NextAs<Expression*>();
2097 Expression* result =
2098 MakeNode<ConditionalExpression>(condition, if_true, if_false);
2099 return ParseResult{result};
2100}
2101
2102std::optional<ParseResult> MakeLabelAndTypes(
2103 ParseResultIterator* child_results) {
2104 auto name = child_results->NextAs<Identifier*>();
2105 if (!IsUpperCamelCase(name->value)) {
2106 NamingConventionError("Label", name, "UpperCamelCase");
2107 }
2108 auto types = child_results->NextAs<std::vector<TypeExpression*>>();
2109 return ParseResult{LabelAndTypes{name, std::move(types)}};
2110}
2111
2112std::optional<ParseResult> MakeNameAndType(ParseResultIterator* child_results) {
2113 auto name = child_results->NextAs<Identifier*>();
2114 auto type = child_results->NextAs<TypeExpression*>();
2115 return ParseResult{NameAndTypeExpression{name, type}};
2116}
2117
2118std::optional<ParseResult> MakeEnumEntry(ParseResultIterator* child_results) {
2119 AnnotationSet annotations(child_results, {}, {ANNOTATION_SAME_ENUM_VALUE_AS});
2120 std::vector<ConditionalAnnotation> conditions;
2121 std::optional<std::string> alias_entry =
2122 annotations.GetStringParam(ANNOTATION_SAME_ENUM_VALUE_AS);
2123
2124 auto name = child_results->NextAs<Identifier*>();
2125 auto type = child_results->NextAs<std::optional<TypeExpression*>>();
2126 return ParseResult{EnumEntry{name, type, alias_entry}};
2127}
2128
2129std::optional<ParseResult> MakeNameAndExpression(
2130 ParseResultIterator* child_results) {
2131 auto name = child_results->NextAs<Identifier*>();
2132 auto expression = child_results->NextAs<Expression*>();
2133 return ParseResult{NameAndExpression{name, expression}};
2134}
2135
2136std::optional<ParseResult> MakeNameAndExpressionFromExpression(
2137 ParseResultIterator* child_results) {
2138 auto expression = child_results->NextAs<Expression*>();
2139 if (auto* id = IdentifierExpression::DynamicCast(expression)) {
2140 if (!id->generic_arguments.empty() ||
2141 !id->namespace_qualification.empty()) {
2142 ReportError("expected a plain identifier without qualification");
2143 }
2144 return ParseResult{NameAndExpression{id->name, id}};
2145 }
2146 ReportError("Constructor parameters need to be named.");
2147}
2148
2149std::optional<ParseResult> MakeAnnotation(ParseResultIterator* child_results) {
2150 return ParseResult{
2151 Annotation{child_results->NextAs<Identifier*>(),
2152 child_results->NextAs<std::optional<AnnotationParameter>>()}};
2153}
2154
2155std::optional<ParseResult> MakeClassField(ParseResultIterator* child_results) {
2156 AnnotationSet annotations(
2157 child_results,
2158 {ANNOTATION_CPP_RELAXED_STORE, ANNOTATION_CPP_RELAXED_LOAD,
2159 ANNOTATION_CPP_RELEASE_STORE, ANNOTATION_CPP_ACQUIRE_LOAD,
2160 ANNOTATION_CUSTOM_WEAK_MARKING},
2161 {ANNOTATION_IF, ANNOTATION_IFNOT});
2162 FieldSynchronization synchronization = FieldSynchronization::kNone;
2163 if (annotations.Contains(ANNOTATION_CPP_RELEASE_STORE)) {
2164 synchronization = FieldSynchronization::kAcquireRelease;
2165 } else if (annotations.Contains(ANNOTATION_CPP_RELAXED_STORE)) {
2166 synchronization = FieldSynchronization::kRelaxed;
2167 }
2168 {
2169 FieldSynchronization read_synchronization = FieldSynchronization::kNone;
2170 if (annotations.Contains(ANNOTATION_CPP_ACQUIRE_LOAD)) {
2171 read_synchronization = FieldSynchronization::kAcquireRelease;
2172 } else if (annotations.Contains(ANNOTATION_CPP_RELAXED_LOAD)) {
2173 read_synchronization = FieldSynchronization::kRelaxed;
2174 }
2175 if (read_synchronization != synchronization) {
2176 Error("Incompatible read/write synchronization annotations for a field.");
2177 }
2178 }
2179 std::vector<ConditionalAnnotation> conditions;
2180 std::optional<std::string> if_condition =
2181 annotations.GetStringParam(ANNOTATION_IF);
2182 std::optional<std::string> ifnot_condition =
2183 annotations.GetStringParam(ANNOTATION_IFNOT);
2184 if (if_condition.has_value()) {
2185 conditions.push_back({*if_condition, ConditionalAnnotationType::kPositive});
2186 }
2187 if (ifnot_condition.has_value()) {
2188 conditions.push_back(
2189 {*ifnot_condition, ConditionalAnnotationType::kNegative});
2190 }
2191 bool custom_weak_marking =
2192 annotations.Contains(ANNOTATION_CUSTOM_WEAK_MARKING);
2193 auto deprecated_weak = child_results->NextAs<bool>();
2194 if (deprecated_weak) {
2195 Error(
2196 "The keyword 'weak' is deprecated. For a field that can contain a "
2197 "normal weak pointer, use type Weak<T>. For a field that should be "
2198 "marked in some custom way, use @customWeakMarking.");
2199 custom_weak_marking = true;
2200 }
2201 auto const_qualified = child_results->NextAs<bool>();
2202 auto name = child_results->NextAs<Identifier*>();
2203 auto optional = child_results->NextAs<bool>();
2204 auto index = child_results->NextAs<std::optional<Expression*>>();
2205 if (optional && !index) {
2206 Error(
2207 "Fields using optional specifier must also provide an expression "
2208 "indicating the condition for whether the field is present");
2209 }
2210 std::optional<ClassFieldIndexInfo> index_info;
2211 if (index) {
2212 if (optional) {
2213 // Internally, an optional field is just an indexed field where the count
2214 // is zero or one.
2215 index = MakeNode<ConditionalExpression>(
2216 *index,
2217 MakeCall(
2218 MakeNode<Identifier>("FromConstexpr"),
2219 {MakeNode<BasicTypeExpression>(std::vector<std::string>{},
2220 MakeNode<Identifier>("intptr"),
2221 std::vector<TypeExpression*>{})},
2222 {MakeNode<IntegerLiteralExpression>(IntegerLiteral(1))}, {}),
2223 MakeCall(
2224 MakeNode<Identifier>("FromConstexpr"),
2225 {MakeNode<BasicTypeExpression>(std::vector<std::string>{},
2226 MakeNode<Identifier>("intptr"),
2227 std::vector<TypeExpression*>{})},
2228 {MakeNode<IntegerLiteralExpression>(IntegerLiteral(0))}, {}));
2229 }
2230 index_info = ClassFieldIndexInfo{*index, optional};
2231 }
2232 auto type = child_results->NextAs<TypeExpression*>();
2233 return ParseResult{ClassFieldExpression{{name, type},
2234 index_info,
2235 std::move(conditions),
2236 custom_weak_marking,
2237 const_qualified,
2238 synchronization}};
2239}
2240
2241std::optional<ParseResult> MakeStructField(ParseResultIterator* child_results) {
2242 auto const_qualified = child_results->NextAs<bool>();
2243 auto name = child_results->NextAs<Identifier*>();
2244 auto type = child_results->NextAs<TypeExpression*>();
2245 return ParseResult{StructFieldExpression{{name, type}, const_qualified}};
2246}
2247
2248std::optional<ParseResult> MakeBitFieldDeclaration(
2249 ParseResultIterator* child_results) {
2250 auto name = child_results->NextAs<Identifier*>();
2251 auto type = child_results->NextAs<TypeExpression*>();
2252 auto num_bits = child_results->NextAs<int32_t>();
2253 return ParseResult{BitFieldDeclaration{{name, type}, num_bits}};
2254}
2255
2256std::optional<ParseResult> ExtractAssignmentOperator(
2257 ParseResultIterator* child_results) {
2258 auto op = child_results->NextAs<Identifier*>();
2259 std::optional<std::string> result =
2260 std::string(op->value.begin(), op->value.end() - 1);
2261 return ParseResult(std::move(result));
2262}
2263
2264struct TorqueGrammar : Grammar {
2265 static bool MatchWhitespace(InputPosition* pos) {
2266 while (true) {
2267 if (MatchChar(std::isspace, pos)) continue;
2268 if (MatchString("//", pos)) {
2269 while (MatchChar([](char c) { return c != '\n'; }, pos)) {
2270 }
2271 continue;
2272 }
2273 if (MatchString("/*", pos)) {
2274 while (!MatchString("*/", pos)) ++*pos;
2275 continue;
2276 }
2277 return true;
2278 }
2279 }
2280
2281 static bool MatchIdentifier(InputPosition* pos) {
2282 InputPosition current = *pos;
2283 MatchString("_", &current);
2284 if (!MatchChar(std::isalpha, &current)) return false;
2285 while (MatchChar(std::isalnum, &current) || MatchString("_", &current)) {
2286 }
2287 *pos = current;
2288 return true;
2289 }
2290
2291 static bool MatchAnnotation(InputPosition* pos) {
2292 InputPosition current = *pos;
2293 if (!MatchString("@", &current)) return false;
2294 if (!MatchIdentifier(&current)) return false;
2295 *pos = current;
2296 return true;
2297 }
2298
2299 static bool MatchIntrinsicName(InputPosition* pos) {
2300 InputPosition current = *pos;
2301 if (!MatchString("%", &current)) return false;
2302 if (!MatchIdentifier(&current)) return false;
2303 *pos = current;
2304 return true;
2305 }
2306
2307 static bool MatchStringLiteral(InputPosition* pos) {
2308 InputPosition current = *pos;
2309 if (MatchString("\"", &current)) {
2310 while (
2311 (MatchString("\\", &current) && MatchAnyChar(&current)) ||
2312 MatchChar([](char c) { return c != '"' && c != '\n'; }, &current)) {
2313 }
2314 if (MatchString("\"", &current)) {
2315 *pos = current;
2316 return true;
2317 }
2318 }
2319 current = *pos;
2320 if (MatchString("'", &current)) {
2321 while (
2322 (MatchString("\\", &current) && MatchAnyChar(&current)) ||
2323 MatchChar([](char c) { return c != '\'' && c != '\n'; }, &current)) {
2324 }
2325 if (MatchString("'", &current)) {
2326 *pos = current;
2327 return true;
2328 }
2329 }
2330 return false;
2331 }
2332
2333 static bool MatchHexLiteral(InputPosition* pos) {
2334 InputPosition current = *pos;
2335 MatchString("-", &current);
2336 if (MatchString("0x", &current) && MatchChar(std::isxdigit, &current)) {
2337 while (MatchChar(std::isxdigit, &current)) {
2338 }
2339 *pos = current;
2340 return true;
2341 }
2342 return false;
2343 }
2344
2345 static bool MatchIntegerLiteral(InputPosition* pos) {
2346 InputPosition current = *pos;
2347 bool found_digit = false;
2348 MatchString("-", &current);
2349 while (MatchChar(std::isdigit, &current)) found_digit = true;
2350 if (found_digit) {
2351 *pos = current;
2352 return true;
2353 }
2354 return false;
2355 }
2356
2357 static bool MatchFloatingPointLiteral(InputPosition* pos) {
2358 InputPosition current = *pos;
2359 bool found_digit = false;
2360 MatchString("-", &current);
2361 while (MatchChar(std::isdigit, &current)) found_digit = true;
2362 if (!MatchString(".", &current)) return false;
2363 while (MatchChar(std::isdigit, &current)) found_digit = true;
2364 if (!found_digit) return false;
2365 *pos = current;
2366 if ((MatchString("e", &current) || MatchString("E", &current)) &&
2367 (MatchString("+", &current) || MatchString("-", &current) || true) &&
2368 MatchChar(std::isdigit, &current)) {
2369 while (MatchChar(std::isdigit, &current)) {
2370 }
2371 *pos = current;
2372 return true;
2373 }
2374 return true;
2375 }
2376
2377 template <class T, bool first>
2378 static std::optional<ParseResult> MakeExtendedVectorIfAnnotation(
2379 ParseResultIterator* child_results) {
2380 std::vector<T> l = {};
2381 if (!first) l = child_results->NextAs<std::vector<T>>();
2382 bool enabled = ProcessIfAnnotation(child_results);
2383 T x = child_results->NextAs<T>();
2384
2385 if (enabled) l.push_back(std::move(x));
2386 return ParseResult{std::move(l)};
2387 }
2388
2389 template <class T>
2390 Symbol* NonemptyListAllowIfAnnotation(Symbol* element,
2391 std::optional<Symbol*> separator = {}) {
2392 Symbol* list = NewSymbol();
2393 *list = {
2394 Rule({annotations, element}, MakeExtendedVectorIfAnnotation<T, true>),
2395 separator ? Rule({list, annotations, *separator, element},
2396 MakeExtendedVectorIfAnnotation<T, false>)
2397 : Rule({list, annotations, element},
2398 MakeExtendedVectorIfAnnotation<T, false>)};
2399 return list;
2400 }
2401
2402 template <class T>
2403 Symbol* ListAllowIfAnnotation(Symbol* element,
2404 std::optional<Symbol*> separator = {}) {
2405 return TryOrDefault<std::vector<T>>(
2406 NonemptyListAllowIfAnnotation<T>(element, separator));
2407 }
2408
2409 TorqueGrammar() : Grammar(&file) { SetWhitespace(MatchWhitespace); }
2410
2411 // Result: Expression*
2412 Symbol* expression = &assignmentExpression;
2413
2414 // Result: std::string
2415 Symbol identifier = {Rule({Pattern(MatchIdentifier)}, YieldMatchedInput),
2416 Rule({Token("runtime")}, YieldMatchedInput)};
2417
2418 // Result: Identifier*
2419 Symbol name = {Rule({&identifier}, MakeIdentifier)};
2420
2421 // Result: Identifier*
2423 Rule({Pattern(MatchAnnotation)}, MakeIdentifierFromMatchedInput)};
2424
2425 // Result: std::string
2426 Symbol intrinsicName = {
2427 Rule({Pattern(MatchIntrinsicName)}, MakeIdentifierFromMatchedInput)};
2428
2429 // Result: std::string
2430 Symbol stringLiteral = {
2431 Rule({Pattern(MatchStringLiteral)}, YieldMatchedInput)};
2432
2433 // Result: std::string
2434 Symbol externalString = {Rule({&stringLiteral}, StringLiteralUnquoteAction)};
2435
2436 // Result: IntegerLiteral
2438 Rule({Pattern(MatchIntegerLiteral)}, YieldIntegerLiteral),
2439 Rule({Pattern(MatchHexLiteral)}, YieldIntegerLiteral)};
2440
2441 // Result: double
2443 Rule({Pattern(MatchFloatingPointLiteral)}, YieldDouble)};
2444
2445 // Result: int32_t
2446 Symbol int32Literal = {Rule({Pattern(MatchIntegerLiteral)}, YieldInt32),
2447 Rule({Pattern(MatchHexLiteral)}, YieldInt32)};
2448
2449 // Result: AnnotationParameter
2451 Rule({&identifier}, MakeStringAnnotationParameter),
2452 Rule({&int32Literal}, MakeIntAnnotationParameter),
2453 Rule({&externalString}, MakeStringAnnotationParameter)};
2454
2455 // Result: AnnotationParameter
2457 Rule({Token("("), &annotationParameter, Token(")")})};
2458
2459 // Result: Annotation
2460 Symbol annotation = {Rule(
2461 {&annotationName, Optional<AnnotationParameter>(&annotationParameters)},
2462 MakeAnnotation)};
2463
2464 // Result: std::vector<Annotation>
2465 Symbol* annotations = List<Annotation>(&annotation);
2466
2467 // Result: std::vector<std::string>
2469 Rule({CheckIf(Token("::")),
2470 List<std::string>(Sequence({&identifier, Token("::")}))},
2471 MakeNamespaceQualification)};
2472
2473 // Result: TypeList
2474 Symbol* typeList = List<TypeExpression*>(&type, Token(","));
2475
2476 // Result: TypeExpression*
2477 Symbol simpleType = {
2478 Rule({Token("("), &type, Token(")")}),
2479 Rule({&namespaceQualification, CheckIf(Token("constexpr")), &identifier,
2480 TryOrDefault<std::vector<TypeExpression*>>(
2482 MakeBasicTypeExpression),
2483 Rule({Token("builtin"), Token("("), typeList, Token(")"), Token("=>"),
2484 &simpleType},
2485 MakeFunctionTypeExpression),
2486 Rule({CheckIf(Token("const")), Token("&"), &simpleType},
2487 MakeReferenceTypeExpression)};
2488
2489 // Result: TypeExpression*
2490 Symbol type = {Rule({&simpleType}), Rule({&type, Token("|"), &simpleType},
2491 MakeUnionTypeExpression)};
2492
2493 // Result: GenericParameter
2495 Rule({&name, Token(":"), Token("type"),
2496 Optional<TypeExpression*>(Sequence({Token("extends"), &type}))},
2497 MakeGenericParameter)};
2498
2499 // Result: GenericParameters
2501 Rule({Token("<"), List<GenericParameter>(&genericParameter, Token(",")),
2502 Token(">")})};
2503
2504 // Result: TypeList
2506 Rule({Token("<"), typeList, Token(">")})};
2507
2508 // Result: std::optional<GenericParameters>
2509 Symbol* optionalGenericParameters = Optional<TypeList>(&genericParameters);
2510
2512 Rule({Token("("), OneOf({"implicit", "js-implicit"}),
2513 List<NameAndTypeExpression>(&nameAndType, Token(",")), Token(")")},
2514 MakeImplicitParameterList)};
2515
2517 Optional<ImplicitParameters>(&implicitParameterList)};
2518
2519 // Result: ParameterList
2521 Rule({optionalImplicitParameterList, Token("("),
2522 List<TypeExpression*>(Sequence({&type, Token(",")})), Token("..."),
2523 Token(")")},
2524 MakeParameterList<true, false>),
2525 Rule({optionalImplicitParameterList, Token("("), typeList, Token(")")},
2526 MakeParameterList<false, false>)};
2527
2528 // Result: LabelAndTypes
2529 Symbol labelParameter = {Rule(
2530 {&name,
2531 TryOrDefault<TypeList>(Sequence({Token("("), typeList, Token(")")}))},
2532 MakeLabelAndTypes)};
2533
2534 // Result: TypeExpression*
2535 Symbol returnType = {Rule({Token(":"), &type}),
2536 Rule({}, DeprecatedMakeVoidType)};
2537
2538 // Result: LabelAndTypesVector
2539 Symbol* optionalLabelList{TryOrDefault<LabelAndTypesVector>(
2540 Sequence({Token("labels"),
2541 NonemptyList<LabelAndTypes>(&labelParameter, Token(","))}))};
2542
2543 // Result: std::vector<Statement*>
2544 Symbol* optionalOtherwise{TryOrDefault<std::vector<Statement*>>(
2545 Sequence({Token("otherwise"),
2546 NonemptyList<Statement*>(&atomarStatement, Token(","))}))};
2547
2548 // Result: NameAndTypeExpression
2549 Symbol nameAndType = {Rule({&name, Token(":"), &type}, MakeNameAndType)};
2550
2551 // Result: std::optional<Expression*>
2553 Optional<Expression*>(Sequence({Token("["), expression, Token("]")}));
2554
2555 // Result: ClassFieldExpression
2556 Symbol classField = {
2557 Rule({annotations, CheckIf(Token("weak")), CheckIf(Token("const")), &name,
2558 CheckIf(Token("?")), optionalArraySpecifier, Token(":"), &type,
2559 Token(";")},
2560 MakeClassField)};
2561
2562 // Result: StructFieldExpression
2563 Symbol structField = {
2564 Rule({CheckIf(Token("const")), &name, Token(":"), &type, Token(";")},
2565 MakeStructField)};
2566
2567 // Result: BitFieldDeclaration
2568 Symbol bitFieldDeclaration = {Rule({&name, Token(":"), &type, Token(":"),
2569 &int32Literal, Token("bit"), Token(";")},
2570 MakeBitFieldDeclaration)};
2571
2572 // Result: ParameterList
2574 Rule({optionalImplicitParameterList, Token("("),
2575 List<NameAndTypeExpression>(&nameAndType, Token(",")), Token(")")},
2576 MakeParameterList<false, true>)};
2577
2578 // Result: ParameterList
2580 Rule({&parameterListNoVararg}),
2581 Rule({optionalImplicitParameterList, Token("("),
2582 List<NameAndTypeExpression>(Sequence({&nameAndType, Token(",")})),
2583 Token("..."), &identifier, Token(")")},
2584 MakeParameterList<true, true>)};
2585
2586 // Result: Identifier*
2587 Symbol* OneOf(const std::vector<std::string>& alternatives) {
2588 Symbol* result = NewSymbol();
2589 for (const std::string& s : alternatives) {
2590 result->AddRule(Rule({Token(s)}, MakeIdentifierFromMatchedInput));
2591 }
2592 return result;
2593 }
2594
2595 // Result: Expression*
2596 Symbol* BinaryOperator(Symbol* nextLevel, Symbol* op) {
2597 Symbol* result = NewSymbol();
2598 *result = {Rule({nextLevel}),
2599 Rule({result, op, nextLevel}, MakeBinaryOperator)};
2600 return result;
2601 }
2602
2603 // Result: IncrementDecrementOperator
2605 Rule({Token("++")},
2606 YieldIntegralConstant<IncrementDecrementOperator,
2607 IncrementDecrementOperator::kIncrement>),
2608 Rule({Token("--")},
2609 YieldIntegralConstant<IncrementDecrementOperator,
2610 IncrementDecrementOperator::kDecrement>)};
2611
2612 // Result: Expression*
2615 TryOrDefault<TypeList>(&genericSpecializationTypeList)},
2616 MakeIdentifierExpression),
2617 };
2618
2619 // Result: std::vector<Expression*>
2620 Symbol argumentList = {Rule(
2621 {Token("("), List<Expression*>(expression, Token(",")), Token(")")})};
2622
2623 // Result: Expression*
2626
2627 // Result: Expression*
2628 Symbol callMethodExpression = {Rule(
2630 MakeMethodCall)};
2631
2632 // Result: NameAndExpression
2634 Rule({&name, Token(":"), expression}, MakeNameAndExpression),
2635 Rule({expression}, MakeNameAndExpressionFromExpression)};
2636
2637 // Result: std::vector<NameAndExpression>
2639 Rule({Token("{"), List<NameAndExpression>(&namedExpression, Token(",")),
2640 Token("}")})};
2641
2642 // Result: Expression*
2644 {&intrinsicName, TryOrDefault<TypeList>(&genericSpecializationTypeList),
2645 &argumentList},
2646 MakeIntrinsicCallExpression)};
2647
2648 // Result: Expression*
2649 Symbol newExpression = {
2650 Rule({Token("new"),
2651 CheckIf(Sequence({Token("("), Token("Pretenured"), Token(")")})),
2652 CheckIf(Sequence({Token("("), Token("ClearPadding"), Token(")")})),
2654 MakeNewExpression)};
2655
2656 // Result: Expression*
2658 Rule({&callExpression}),
2659 Rule({&callMethodExpression}),
2660 Rule({&intrinsicCallExpression}),
2661 Rule({&identifierExpression}),
2662 Rule({&primaryExpression, Token("."), &name}, MakeFieldAccessExpression),
2663 Rule({&primaryExpression, Token("->"), &name},
2664 MakeReferenceFieldAccessExpression),
2665 Rule({&primaryExpression, Token("["), expression, Token("]")},
2666 MakeElementAccessExpression),
2667 Rule({&integerLiteral}, MakeIntegerLiteralExpression),
2668 Rule({&floatingPointLiteral}, MakeFloatingPointLiteralExpression),
2669 Rule({&stringLiteral}, MakeStringLiteralExpression),
2670 Rule({&simpleType, &initializerList}, MakeStructExpression),
2671 Rule({&newExpression}),
2672 Rule({Token("("), expression, Token(")")})};
2673
2674 // Result: Expression*
2676 Rule({&primaryExpression}),
2677 Rule({OneOf({"+", "-", "!", "~", "&"}), &unaryExpression},
2678 MakeUnaryOperator),
2679 Rule({Token("*"), &unaryExpression}, MakeDereferenceExpression),
2680 Rule({Token("..."), &unaryExpression}, MakeSpreadExpression),
2682 MakeIncrementDecrementExpressionPrefix),
2684 MakeIncrementDecrementExpressionPostfix)};
2685
2686 // Result: Expression*
2688 BinaryOperator(&unaryExpression, OneOf({"*", "/", "%"}));
2689
2690 // Result: Expression*
2692 BinaryOperator(multiplicativeExpression, OneOf({"+", "-"}));
2693
2694 // Result: Identifier*
2695 Symbol shiftOperator = {
2696 Rule({Token("<<")}, MakeIdentifierFromMatchedInput),
2697 Rule({Token(">"), Token(">")}, MakeRightShiftIdentifier),
2698 Rule({Token(">"), Token(">"), Token(">")}, MakeRightShiftIdentifier)};
2699
2700 // Result: Expression*
2702
2703 // Do not allow expressions like a < b > c because this is never
2704 // useful and ambiguous with template parameters.
2705 // Result: Expression*
2707 Rule({shiftExpression}),
2708 Rule({shiftExpression, OneOf({"<", ">", "<=", ">="}), shiftExpression},
2709 MakeBinaryOperator)};
2710
2711 // Result: Expression*
2713 BinaryOperator(&relationalExpression, OneOf({"==", "!="}));
2714
2715 // Result: Expression*
2717 BinaryOperator(equalityExpression, OneOf({"&", "|"}));
2718
2719 // Result: Expression*
2721 Rule({bitwiseExpression}),
2722 Rule({&logicalAndExpression, Token("&&"), bitwiseExpression},
2723 MakeLogicalAndExpression)};
2724
2725 // Result: Expression*
2727 Rule({&logicalAndExpression}),
2728 Rule({&logicalOrExpression, Token("||"), &logicalAndExpression},
2729 MakeLogicalOrExpression)};
2730
2731 // Result: Expression*
2733 Rule({&logicalOrExpression}),
2734 Rule({&logicalOrExpression, Token("?"), expression, Token(":"),
2736 MakeConditionalExpression)};
2737
2738 // Result: std::optional<std::string>
2740 Rule({Token("=")}, YieldDefaultValue<std::optional<std::string>>),
2741 Rule({OneOf({"*=", "/=", "%=", "+=", "-=", "<<=", ">>=", ">>>=", "&=",
2742 "^=", "|="})},
2743 ExtractAssignmentOperator)};
2744
2745 // Result: Expression*
2747 Rule({&conditionalExpression}),
2749 MakeAssignmentExpression)};
2750
2751 // Result: Statement*
2752 Symbol block = {
2753 Rule({CheckIf(Token("deferred")), Token("{"),
2754 ListAllowIfAnnotation<Statement*>(&statement), Token("}")},
2755 MakeBlockStatement)};
2756
2757 // Result: TryHandler*
2758 Symbol tryHandler = {
2759 Rule({Token("label"), &name,
2760 TryOrDefault<ParameterList>(&parameterListNoVararg), &block},
2761 MakeLabelBlock),
2762 Rule({Token("catch"), Token("("),
2763 List<std::string>(&identifier, Token(",")), Token(")"), &block},
2764 MakeCatchBlock)};
2765
2766 // Result: ExpressionWithSource
2767 Symbol expressionWithSource = {Rule({expression}, MakeExpressionWithSource)};
2768
2770 Optional<TypeExpression*>(Sequence({Token(":"), &type}));
2771
2772 // Result: EnumEntry
2773 Symbol enumEntry = {
2774 Rule({annotations, &name, optionalTypeSpecifier}, MakeEnumEntry)};
2775
2776 // Result: Statement*
2778 Rule({OneOf({"let", "const"}), &name, optionalTypeSpecifier},
2779 MakeVarDeclarationStatement)};
2780
2781 // Result: Statement*
2783 Rule({OneOf({"let", "const"}), &name, optionalTypeSpecifier, Token("="),
2784 expression},
2785 MakeVarDeclarationStatement)};
2786
2787 // Result: Statement*
2789 Rule({expression}, MakeExpressionStatement),
2790 Rule({Token("return"), Optional<Expression*>(expression)},
2791 MakeReturnStatement),
2792 Rule({Token("tail"), &callExpression}, MakeTailCallStatement),
2793 Rule({Token("break")}, MakeBreakStatement),
2794 Rule({Token("continue")}, MakeContinueStatement),
2795 Rule({Token("goto"), &name,
2796 TryOrDefault<std::vector<Expression*>>(&argumentList)},
2797 MakeGotoStatement),
2798 Rule({OneOf({"debug", "unreachable"})}, MakeDebugStatement)};
2799
2800 // Result: Statement*
2801 Symbol statement = {
2802 Rule({&block}),
2803 Rule({&atomarStatement, Token(";")}),
2804 Rule({&varDeclaration, Token(";")}),
2805 Rule({&varDeclarationWithInitialization, Token(";")}),
2806 Rule({Token("if"), CheckIf(Token("constexpr")), Token("("), expression,
2807 Token(")"), &statement,
2808 Optional<Statement*>(Sequence({Token("else"), &statement}))},
2809 MakeIfStatement),
2810 Rule(
2811 {
2812 Token("typeswitch"),
2813 Token("("),
2814 expression,
2815 Token(")"),
2816 Token("{"),
2817 NonemptyListAllowIfAnnotation<TypeswitchCase>(&typeswitchCase),
2818 Token("}"),
2819 },
2820 MakeTypeswitchStatement),
2821 Rule({Token("try"), &block, List<TryHandler*>(&tryHandler)},
2822 MakeTryLabelExpression),
2823 Rule({OneOf({"dcheck", "check", "sbxcheck", "static_assert"}), Token("("),
2824 &expressionWithSource, Token(")"), Token(";")},
2825 MakeAssertStatement),
2826 Rule({Token("while"), Token("("), expression, Token(")"), &statement},
2827 MakeWhileStatement),
2828 Rule({Token("for"), Token("("),
2829 Optional<Statement*>(&varDeclarationWithInitialization), Token(";"),
2830 Optional<Expression*>(expression), Token(";"),
2831 Optional<Expression*>(expression), Token(")"), &statement},
2832 MakeForLoopStatement)};
2833
2834 // Result: TypeswitchCase
2836 Rule({Token("case"), Token("("),
2837 Optional<Identifier*>(Sequence({&name, Token(":")})), &type,
2838 Token(")"), Token(":"), &block},
2839 MakeTypeswitchCase)};
2840
2841 // Result: std::optional<Statement*>
2842 Symbol optionalBody = {
2843 Rule({&block}, CastParseResult<Statement*, std::optional<Statement*>>),
2844 Rule({Token(";")}, YieldDefaultValue<std::optional<Statement*>>)};
2845
2846 // Result: Declaration*
2847 Symbol method = {Rule(
2848 {CheckIf(Token("transitioning")),
2849 Optional<std::string>(Sequence({Token("operator"), &externalString})),
2850 Token("macro"), &name, &parameterListNoVararg, &returnType,
2851 optionalLabelList, &block},
2852 MakeMethodDeclaration)};
2853
2854 // Result: std::optional<ClassBody*>
2856 Rule({Token("{"), List<Declaration*>(&method),
2857 List<ClassFieldExpression>(&classField), Token("}")},
2858 MakeClassBody),
2859 Rule({Token(";")}, YieldDefaultValue<std::optional<ClassBody*>>)};
2860
2861 // Result: std::vector<Declaration*>
2862 Symbol declaration = {
2863 Rule({annotations, Token("const"), &name, Token(":"), &type, Token("="),
2864 expression, Token(";")},
2865 MakeConstDeclaration),
2866 Rule({Token("const"), &name, Token(":"), &type, Token("generates"),
2867 &externalString, Token(";")},
2868 AsSingletonVector<Declaration*, MakeExternConstDeclaration>()),
2869 Rule({annotations, CheckIf(Token("extern")), CheckIf(Token("transient")),
2870 OneOf({"class", "shape"}), &name, Token("extends"), &type,
2871 Optional<std::string>(
2872 Sequence({Token("generates"), &externalString})),
2874 MakeClassDeclaration),
2875 Rule({annotations, Token("struct"), &name,
2876 TryOrDefault<GenericParameters>(&genericParameters), Token("{"),
2877 ListAllowIfAnnotation<Declaration*>(&method),
2878 ListAllowIfAnnotation<StructFieldExpression>(&structField),
2879 Token("}")},
2880 AsSingletonVector<Declaration*, MakeStructDeclaration>()),
2881 Rule({Token("bitfield"), Token("struct"), &name, Token("extends"), &type,
2882 Token("{"),
2883 ListAllowIfAnnotation<BitFieldDeclaration>(&bitFieldDeclaration),
2884 Token("}")},
2885 AsSingletonVector<Declaration*, MakeBitFieldStructDeclaration>()),
2886 Rule({annotations, CheckIf(Token("transient")), Token("type"), &name,
2887 TryOrDefault<GenericParameters>(&genericParameters),
2888 Optional<TypeExpression*>(Sequence({Token("extends"), &type})),
2889 Optional<std::string>(
2890 Sequence({Token("generates"), &externalString})),
2891 Optional<std::string>(
2892 Sequence({Token("constexpr"), &externalString})),
2893 Token(";")},
2894 MakeAbstractTypeDeclaration),
2895 Rule({annotations, Token("type"), &name, Token("="), &type, Token(";")},
2896 MakeTypeAliasDeclaration),
2897 Rule({Token("intrinsic"), &intrinsicName,
2898 TryOrDefault<GenericParameters>(&genericParameters),
2900 AsSingletonVector<Declaration*, MakeIntrinsicDeclaration>()),
2901 Rule({annotations, Token("extern"), CheckIf(Token("transitioning")),
2902 Optional<std::string>(
2903 Sequence({Token("operator"), &externalString})),
2904 Token("macro"),
2905 Optional<std::string>(Sequence({&identifier, Token("::")})), &name,
2906 TryOrDefault<GenericParameters>(&genericParameters),
2908 MakeExternalMacro),
2909 Rule({Token("extern"), CheckIf(Token("transitioning")),
2910 CheckIf(Token("javascript")), Token("builtin"), &name,
2911 TryOrDefault<GenericParameters>(&genericParameters),
2912 &typeListMaybeVarArgs, &returnType, Token(";")},
2913 AsSingletonVector<Declaration*, MakeExternalBuiltin>()),
2914 Rule({Token("extern"), CheckIf(Token("transitioning")), Token("runtime"),
2915 &name, &typeListMaybeVarArgs, &returnType, Token(";")},
2916 AsSingletonVector<Declaration*, MakeExternalRuntime>()),
2917 Rule({annotations, CheckIf(Token("transitioning")),
2918 Optional<std::string>(
2919 Sequence({Token("operator"), &externalString})),
2920 Token("macro"), &name,
2921 TryOrDefault<GenericParameters>(&genericParameters),
2923 &optionalBody},
2924 MakeTorqueMacroDeclaration),
2925 Rule({annotations, CheckIf(Token("transitioning")),
2926 CheckIf(Token("javascript")), Token("builtin"), &name,
2927 TryOrDefault<GenericParameters>(&genericParameters),
2929 MakeTorqueBuiltinDeclaration),
2930 Rule({annotations, CheckIf(Token("transitioning")), &name,
2932 &returnType, optionalLabelList, &block},
2933 MakeSpecializationDeclaration),
2934 Rule({Token("#include"), &externalString},
2935 AsSingletonVector<Declaration*, MakeCppIncludeDeclaration>()),
2936 Rule({CheckIf(Token("extern")), Token("enum"), &name,
2937 Optional<TypeExpression*>(Sequence({Token("extends"), &type})),
2938 Optional<std::string>(
2939 Sequence({Token("constexpr"), &externalString})),
2940 Token("{"),
2941 NonemptyListAllowIfAnnotation<EnumEntry>(&enumEntry, Token(",")),
2942 CheckIf(Sequence({Token(","), Token("...")})), Token("}")},
2943 MakeEnumDeclaration),
2944 Rule({Token("namespace"), &identifier, Token("{"), &declarationList,
2945 Token("}")},
2946 AsSingletonVector<Declaration*, MakeNamespaceDeclaration>())};
2947
2948 // Result: std::vector<Declaration*>
2950 Rule({List<std::vector<Declaration*>>(&declaration)}, ConcatList)};
2951
2952 Symbol file = {Rule({&file, Token("import"), &externalString},
2953 ProcessTorqueImportDeclaration),
2954 Rule({&file, &declaration}, AddGlobalDeclarations), Rule({})};
2955};
2956
2957} // namespace
2958
2959void ParseTorque(const std::string& input) {
2960 BuildFlags::Scope build_flags_scope;
2961 TorqueGrammar().Parse(input);
2962}
2963
2964} // namespace v8::internal::torque
const char * name
Definition builtins.cc:39
Builtins::Kind kind
Definition builtins.cc:40
SourcePosition pos
static VarType & Get()
Definition contextual.h:64
std::unordered_map< std::string, bool > build_flags_
static bool GetFlag(const std::string &name, const char *production)
MessageBuilder & Position(SourcePosition position)
Definition utils.h:52
#define V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL
Definition globals.h:242
#define V8_ENABLE_LEAPTIERING_BOOL
Definition globals.h:151
#define V8_EXTERNAL_CODE_SPACE_BOOL
Definition globals.h:255
#define DEBUG_BOOL
Definition globals.h:87
#define V8_ENABLE_SANDBOX_BOOL
Definition globals.h:160
#define V8_EXPERIMENTAL_UNDEFINED_DOUBLE_BOOL
Definition globals.h:359
const MapRef map_
LineAndColumn current
base::Vector< const DirectHandle< Object > > args
Definition execution.cc:74
Label label
OptionalOpIndex index
TNode< Object > this_arg
double second
RpoNumber block
ZoneVector< RpoNumber > & result
ZoneVector< Entry > entries
int x
FunctionLiteral * literal
Definition liveedit.cc:294
ZoneVector< InstructionOperand > * set_
int int32_t
Definition unicode.cc:40
static const char *const ANNOTATION_GENERATE_BODY_DESCRIPTOR
Definition constants.h:111
static const char *const TORQUE_INTERNAL_NAMESPACE_STRING
Definition constants.h:78
static const char *const ANNOTATION_HIGHEST_INSTANCE_TYPE_WITHIN_PARENT
Definition constants.h:101
std::vector< TypeExpression * > TypeList
static const char *const ANNOTATION_DO_NOT_GENERATE_CAST
Definition constants.h:117
base::Flags< ClassFlag > ClassFlags
Definition constants.h:186
bool IsUpperCamelCase(const std::string &s)
Definition utils.cc:228
std::string UnwrapTNodeTypeName(const std::string &generates)
static const char *const ANNOTATION_CUSTOM_MAP
Definition constants.h:99
BasicTypeExpression * MakeBasicTypeExpression(std::vector< std::string > namespace_qualification, Identifier *name, std::vector< TypeExpression * > generic_arguments={})
Definition ast.h:1330
void ReportError(Args &&... args)
Definition utils.h:96
const char * InputPosition
StructExpression * MakeStructExpression(TypeExpression *type, std::vector< NameAndExpression > initializers)
Definition ast.h:1337
static const char *const ANNOTATION_USE_PARENT_TYPE_CHECKER
Definition constants.h:118
T * MakeNode(Args... args)
Definition ast.h:1286
static const char *const ANNOTATION_RESERVE_BITS_IN_INSTANCE_TYPE
Definition constants.h:105
static const char *const ANNOTATION_CUSTOM_INTERFACE_DESCRIPTOR
Definition constants.h:137
std::vector< GenericParameter > GenericParameters
Definition ast.h:1129
base::Flags< StructFlag > StructFlags
Definition constants.h:189
static const char *const ANNOTATION_DO_NOT_GENERATE_CPP_CLASS
Definition constants.h:97
MessageBuilder Lint(Args &&... args)
Definition utils.h:85
static const char *const ANNOTATION_IF
Definition constants.h:109
static const char *const ANNOTATION_IFNOT
Definition constants.h:110
static const char *const CONSTEXPR_TYPE_PREFIX
Definition constants.h:17
FieldAccessExpression * MakeFieldAccessExpression(Expression *object, std::string field)
Definition ast.h:1291
static const char *const ANNOTATION_CUSTOM_CPP_CLASS
Definition constants.h:100
static const char *const ANNOTATION_CPP_OBJECT_LAYOUT_DEFINITION
Definition constants.h:122
bool IsValidTypeName(const std::string &s)
Definition utils.cc:247
bool IsSnakeCase(const std::string &s)
Definition utils.cc:235
static const char *const ANNOTATION_GENERATE_FACTORY_FUNCTION
Definition constants.h:114
static const char *const ANNOTATION_EXPORT
Definition constants.h:116
static const char *const ANNOTATION_LOWEST_INSTANCE_TYPE_WITHIN_PARENT
Definition constants.h:103
static const char *const ANNOTATION_CPP_OBJECT_DEFINITION
Definition constants.h:120
bool IsLowerCamelCase(const std::string &s)
Definition utils.cc:221
static const char *const ANNOTATION_INCREMENT_USE_COUNTER
Definition constants.h:141
bool IsValidNamespaceConstName(const std::string &s)
Definition utils.cc:240
static const char *const ANNOTATION_HAS_SAME_INSTANCE_TYPE_AS_PARENT
Definition constants.h:95
IdentifierExpression * MakeIdentifierExpression(std::vector< std::string > namespace_qualification, std::string name, std::vector< TypeExpression * > args={})
Definition ast.h:1297
base::Flags< AbstractTypeFlag > AbstractTypeFlags
Definition constants.h:165
void ParseTorque(const std::string &input)
std::string GetConstexprName(const std::string &name)
Definition constants.h:154
static const char *const ANNOTATION_INSTANCE_TYPE_VALUE
Definition constants.h:107
static const char *const ANNOTATION_ABSTRACT
Definition constants.h:94
std::vector< LabelAndTypes > LabelAndTypesVector
Definition ast.h:967
static const char *const ANNOTATION_GENERATE_UNIQUE_MAP
Definition constants.h:113
MessageBuilder Error(Args &&... args)
Definition utils.h:81
std::string StringLiteralUnquote(const std::string &s)
Definition utils.cc:23
too high values may cause the compiler to set high thresholds for inlining to as much as possible avoid inlined allocation of objects that cannot escape trace load stores from virtual maglev objects use TurboFan fast string builder analyze liveness of environment slots and zap dead values trace TurboFan load elimination emit data about basic block usage in builtins to this enable builtin reordering when run mksnapshot flag for emit warnings when applying builtin profile data verify register allocation in TurboFan randomly schedule instructions to stress dependency tracking enable store store elimination in TurboFan rewrite far to near simulate GC compiler thread race related to allow float parameters to be passed in simulator mode JS Wasm Run additional turbo_optimize_inlined_js_wasm_wrappers enable experimental feedback collection in generic lowering enable Turboshaft s WasmLoadElimination enable Turboshaft s low level load elimination for JS enable Turboshaft s escape analysis for string concatenation use enable Turbolev features that we want to ship in the not too far future trace individual Turboshaft reduction steps trace intermediate Turboshaft reduction steps invocation count threshold for early optimization Enables optimizations which favor memory size over execution speed Enables sampling allocation profiler with X as a sample interval min size of a semi the new space consists of two semi spaces max size of the Collect garbage after Collect garbage after keeps maps alive for< n > old space garbage collections print one detailed trace line in name
Definition flags.cc:2086
Flag flags[]
Definition flags.cc:3797
return value
Definition map-inl.h:893
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
#define V8_EXPORT_PRIVATE
Definition macros.h:460
std::optional< TypeExpression * > type
std::optional< std::string > alias_entry
std::vector< TypeExpression * > types
Definition ast.h:627
static ParameterList Empty()
Definition ast.h:634
std::vector< Identifier * > names
Definition ast.h:626
std::optional< Identifier * > name
Symbol optionalBody
Symbol * optionalOtherwise
Symbol labelParameter
Symbol genericSpecializationTypeList
Symbol identifier
Symbol simpleType
Symbol primaryExpression
Symbol * annotations
Symbol * optionalLabelList
Symbol * bitwiseExpression
Symbol conditionalExpression
Symbol atomarStatement
Symbol annotationParameters
Symbol genericParameter
Symbol relationalExpression
Symbol floatingPointLiteral
Symbol assignmentExpression
Symbol declaration
Symbol int32Literal
Symbol annotationName
Symbol intrinsicName
Symbol expressionWithSource
Symbol * optionalImplicitParameterList
Symbol shiftOperator
Symbol externalString
Symbol structField
Symbol varDeclarationWithInitialization
Symbol * optionalArraySpecifier
Symbol * optionalTypeSpecifier
Symbol enumEntry
Symbol annotation
Symbol name
Symbol typeListMaybeVarArgs
Symbol logicalOrExpression
Symbol * optionalGenericParameters
Symbol typeswitchCase
Symbol newExpression
Symbol tryHandler
Symbol genericParameters
Symbol declarationList
Symbol file
Symbol varDeclaration
Symbol * expression
Symbol logicalAndExpression
Symbol optionalClassBody
Symbol parameterListNoVararg
Symbol callExpression
Symbol method
Symbol returnType
Symbol * equalityExpression
Symbol namedExpression
Symbol classField
Symbol initializerList
Symbol statement
Symbol integerLiteral
Symbol argumentList
Symbol assignmentOperator
Symbol nameAndType
Symbol stringLiteral
Symbol annotationParameter
Symbol incrementDecrementOperator
Symbol * typeList
Symbol intrinsicCallExpression
Symbol unaryExpression
Symbol identifierExpression
Symbol type
Symbol bitFieldDeclaration
Symbol callMethodExpression
Symbol implicitParameterList
Symbol * additiveExpression
Symbol * multiplicativeExpression
Symbol namespaceQualification
Symbol parameterListAllowVararg
Symbol * shiftExpression
wasm::ValueType type