| // Copyright 2018 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef V8_TORQUE_AST_H_ |
| #define V8_TORQUE_AST_H_ |
| |
| #include <algorithm> |
| #include <iostream> |
| #include <map> |
| #include <memory> |
| #include <set> |
| #include <string> |
| #include <vector> |
| |
| #include "src/base/optional.h" |
| #include "src/torque/constants.h" |
| #include "src/torque/source-positions.h" |
| #include "src/torque/utils.h" |
| |
| namespace v8 { |
| namespace internal { |
| namespace torque { |
| |
| #define AST_EXPRESSION_NODE_KIND_LIST(V) \ |
| V(CallExpression) \ |
| V(CallMethodExpression) \ |
| V(IntrinsicCallExpression) \ |
| V(StructExpression) \ |
| V(LogicalOrExpression) \ |
| V(LogicalAndExpression) \ |
| V(SpreadExpression) \ |
| V(ConditionalExpression) \ |
| V(IdentifierExpression) \ |
| V(StringLiteralExpression) \ |
| V(NumberLiteralExpression) \ |
| V(FieldAccessExpression) \ |
| V(ElementAccessExpression) \ |
| V(DereferenceExpression) \ |
| V(AssignmentExpression) \ |
| V(IncrementDecrementExpression) \ |
| V(NewExpression) \ |
| V(AssumeTypeImpossibleExpression) \ |
| V(StatementExpression) \ |
| V(TryLabelExpression) |
| |
| #define AST_TYPE_EXPRESSION_NODE_KIND_LIST(V) \ |
| V(BasicTypeExpression) \ |
| V(FunctionTypeExpression) \ |
| V(PrecomputedTypeExpression) \ |
| V(UnionTypeExpression) |
| |
| #define AST_STATEMENT_NODE_KIND_LIST(V) \ |
| V(BlockStatement) \ |
| V(ExpressionStatement) \ |
| V(IfStatement) \ |
| V(WhileStatement) \ |
| V(ForLoopStatement) \ |
| V(BreakStatement) \ |
| V(ContinueStatement) \ |
| V(ReturnStatement) \ |
| V(DebugStatement) \ |
| V(AssertStatement) \ |
| V(TailCallStatement) \ |
| V(VarDeclarationStatement) \ |
| V(GotoStatement) |
| |
| #define AST_TYPE_DECLARATION_NODE_KIND_LIST(V) \ |
| V(AbstractTypeDeclaration) \ |
| V(TypeAliasDeclaration) \ |
| V(BitFieldStructDeclaration) \ |
| V(ClassDeclaration) \ |
| V(StructDeclaration) |
| |
| #define AST_DECLARATION_NODE_KIND_LIST(V) \ |
| AST_TYPE_DECLARATION_NODE_KIND_LIST(V) \ |
| V(GenericCallableDeclaration) \ |
| V(GenericTypeDeclaration) \ |
| V(SpecializationDeclaration) \ |
| V(ExternConstDeclaration) \ |
| V(NamespaceDeclaration) \ |
| V(ConstDeclaration) \ |
| V(CppIncludeDeclaration) \ |
| V(TorqueMacroDeclaration) \ |
| V(TorqueBuiltinDeclaration) \ |
| V(ExternalMacroDeclaration) \ |
| V(ExternalBuiltinDeclaration) \ |
| V(ExternalRuntimeDeclaration) \ |
| V(IntrinsicDeclaration) |
| |
| #define AST_NODE_KIND_LIST(V) \ |
| AST_EXPRESSION_NODE_KIND_LIST(V) \ |
| AST_TYPE_EXPRESSION_NODE_KIND_LIST(V) \ |
| AST_STATEMENT_NODE_KIND_LIST(V) \ |
| AST_DECLARATION_NODE_KIND_LIST(V) \ |
| V(Identifier) \ |
| V(TryHandler) \ |
| V(ClassBody) |
| |
| struct AstNode { |
| public: |
| enum class Kind { |
| #define ENUM_ITEM(name) k##name, |
| AST_NODE_KIND_LIST(ENUM_ITEM) |
| #undef ENUM_ITEM |
| }; |
| |
| AstNode(Kind kind, SourcePosition pos) : kind(kind), pos(pos) {} |
| virtual ~AstNode() = default; |
| |
| const Kind kind; |
| SourcePosition pos; |
| }; |
| |
| struct AstNodeClassCheck { |
| template <class T> |
| static bool IsInstanceOf(AstNode* node); |
| }; |
| |
| // Boilerplate for most derived classes. |
| #define DEFINE_AST_NODE_LEAF_BOILERPLATE(T) \ |
| static const Kind kKind = Kind::k##T; \ |
| static T* cast(AstNode* node) { \ |
| DCHECK_EQ(node->kind, kKind); \ |
| return static_cast<T*>(node); \ |
| } \ |
| static T* DynamicCast(AstNode* node) { \ |
| if (!node) return nullptr; \ |
| if (node->kind != kKind) return nullptr; \ |
| return static_cast<T*>(node); \ |
| } |
| |
| // Boilerplate for classes with subclasses. |
| #define DEFINE_AST_NODE_INNER_BOILERPLATE(T) \ |
| static T* cast(AstNode* node) { \ |
| DCHECK(AstNodeClassCheck::IsInstanceOf<T>(node)); \ |
| return static_cast<T*>(node); \ |
| } \ |
| static T* DynamicCast(AstNode* node) { \ |
| if (!node) return nullptr; \ |
| if (!AstNodeClassCheck::IsInstanceOf<T>(node)) return nullptr; \ |
| return static_cast<T*>(node); \ |
| } |
| |
| struct Expression : AstNode { |
| Expression(Kind kind, SourcePosition pos) : AstNode(kind, pos) {} |
| DEFINE_AST_NODE_INNER_BOILERPLATE(Expression) |
| |
| using VisitCallback = std::function<void(Expression*)>; |
| virtual void VisitAllSubExpressions(VisitCallback callback) { |
| // TODO(szuend): Hoist this up to AstNode and make it a |
| // general Ast visitor. |
| } |
| }; |
| |
| struct LocationExpression : Expression { |
| LocationExpression(Kind kind, SourcePosition pos) : Expression(kind, pos) {} |
| DEFINE_AST_NODE_INNER_BOILERPLATE(LocationExpression) |
| }; |
| |
| struct TypeExpression : AstNode { |
| TypeExpression(Kind kind, SourcePosition pos) : AstNode(kind, pos) {} |
| DEFINE_AST_NODE_INNER_BOILERPLATE(TypeExpression) |
| }; |
| |
| struct Declaration : AstNode { |
| Declaration(Kind kind, SourcePosition pos) : AstNode(kind, pos) {} |
| DEFINE_AST_NODE_INNER_BOILERPLATE(Declaration) |
| }; |
| |
| struct Statement : AstNode { |
| Statement(Kind kind, SourcePosition pos) : AstNode(kind, pos) {} |
| DEFINE_AST_NODE_INNER_BOILERPLATE(Statement) |
| }; |
| |
| class Namespace; |
| |
| struct NamespaceDeclaration : Declaration { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(NamespaceDeclaration) |
| NamespaceDeclaration(SourcePosition pos, std::string name, |
| std::vector<Declaration*> declarations) |
| : Declaration(kKind, pos), |
| declarations(std::move(declarations)), |
| name(name) {} |
| std::vector<Declaration*> declarations; |
| std::string name; |
| }; |
| |
| struct EnumDescription { |
| SourcePosition pos; |
| std::string name; |
| std::string constexpr_generates; |
| bool is_open; |
| std::vector<std::string> entries; |
| |
| EnumDescription(SourcePosition pos, std::string name, |
| std::string constexpr_generates, bool is_open, |
| std::vector<std::string> entries = {}) |
| : pos(std::move(pos)), |
| name(std::move(name)), |
| constexpr_generates(std::move(constexpr_generates)), |
| is_open(is_open), |
| entries(std::move(entries)) {} |
| }; |
| |
| class Ast { |
| public: |
| Ast() = default; |
| |
| std::vector<Declaration*>& declarations() { return declarations_; } |
| const std::vector<Declaration*>& declarations() const { |
| return declarations_; |
| } |
| template <class T> |
| T* AddNode(std::unique_ptr<T> node) { |
| T* result = node.get(); |
| nodes_.push_back(std::move(node)); |
| return result; |
| } |
| |
| void DeclareImportForCurrentFile(SourceId import_id) { |
| declared_imports_[CurrentSourcePosition::Get().source].insert(import_id); |
| } |
| |
| void AddEnumDescription(EnumDescription description) { |
| std::string name = description.name; |
| DCHECK(!name.empty()); |
| auto f = [&](const auto& d) { return d.name == name; }; |
| USE(f); // Suppress unused in release. |
| DCHECK_EQ( |
| std::find_if(enum_descriptions_.begin(), enum_descriptions_.end(), f), |
| enum_descriptions_.end()); |
| enum_descriptions_.push_back(std::move(description)); |
| } |
| |
| std::vector<EnumDescription>& EnumDescriptions() { |
| return enum_descriptions_; |
| } |
| |
| private: |
| std::vector<Declaration*> declarations_; |
| std::vector<std::unique_ptr<AstNode>> nodes_; |
| std::map<SourceId, std::set<SourceId>> declared_imports_; |
| std::vector<EnumDescription> enum_descriptions_; |
| }; |
| |
| static const char* const kThisParameterName = "this"; |
| |
| // A Identifier is a string with a SourcePosition attached. |
| struct Identifier : AstNode { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(Identifier) |
| Identifier(SourcePosition pos, std::string identifier) |
| : AstNode(kKind, pos), value(std::move(identifier)) {} |
| std::string value; |
| }; |
| |
| inline std::ostream& operator<<(std::ostream& os, Identifier* id) { |
| return os << id->value; |
| } |
| |
| struct IdentifierPtrValueEq { |
| bool operator()(const Identifier* a, const Identifier* b) { |
| return a->value < b->value; |
| } |
| }; |
| |
| struct IdentifierExpression : LocationExpression { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(IdentifierExpression) |
| IdentifierExpression(SourcePosition pos, |
| std::vector<std::string> namespace_qualification, |
| Identifier* name, std::vector<TypeExpression*> args = {}) |
| : LocationExpression(kKind, pos), |
| namespace_qualification(std::move(namespace_qualification)), |
| name(name), |
| generic_arguments(std::move(args)) {} |
| IdentifierExpression(SourcePosition pos, Identifier* name, |
| std::vector<TypeExpression*> args = {}) |
| : IdentifierExpression(pos, {}, name, std::move(args)) {} |
| bool IsThis() const { return name->value == kThisParameterName; } |
| |
| void VisitAllSubExpressions(VisitCallback callback) override { |
| callback(this); |
| } |
| |
| std::vector<std::string> namespace_qualification; |
| Identifier* name; |
| std::vector<TypeExpression*> generic_arguments; |
| }; |
| |
| struct IntrinsicCallExpression : Expression { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(IntrinsicCallExpression) |
| IntrinsicCallExpression(SourcePosition pos, Identifier* name, |
| std::vector<TypeExpression*> generic_arguments, |
| std::vector<Expression*> arguments) |
| : Expression(kKind, pos), |
| name(name), |
| generic_arguments(std::move(generic_arguments)), |
| arguments(std::move(arguments)) {} |
| |
| void VisitAllSubExpressions(VisitCallback callback) override { |
| for (auto argument : arguments) { |
| argument->VisitAllSubExpressions(callback); |
| } |
| callback(this); |
| } |
| |
| Identifier* name; |
| std::vector<TypeExpression*> generic_arguments; |
| std::vector<Expression*> arguments; |
| }; |
| |
| struct CallMethodExpression : Expression { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(CallMethodExpression) |
| CallMethodExpression(SourcePosition pos, Expression* target, |
| IdentifierExpression* method, |
| std::vector<Expression*> arguments, |
| std::vector<Identifier*> labels) |
| : Expression(kKind, pos), |
| target(target), |
| method(method), |
| arguments(std::move(arguments)), |
| labels(std::move(labels)) {} |
| |
| void VisitAllSubExpressions(VisitCallback callback) override { |
| target->VisitAllSubExpressions(callback); |
| method->VisitAllSubExpressions(callback); |
| for (auto argument : arguments) { |
| argument->VisitAllSubExpressions(callback); |
| } |
| callback(this); |
| } |
| |
| Expression* target; |
| IdentifierExpression* method; |
| std::vector<Expression*> arguments; |
| std::vector<Identifier*> labels; |
| }; |
| |
| struct CallExpression : Expression { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(CallExpression) |
| CallExpression(SourcePosition pos, IdentifierExpression* callee, |
| std::vector<Expression*> arguments, |
| std::vector<Identifier*> labels) |
| : Expression(kKind, pos), |
| callee(callee), |
| arguments(std::move(arguments)), |
| labels(std::move(labels)) {} |
| |
| void VisitAllSubExpressions(VisitCallback callback) override { |
| callee->VisitAllSubExpressions(callback); |
| for (auto argument : arguments) { |
| argument->VisitAllSubExpressions(callback); |
| } |
| callback(this); |
| } |
| |
| IdentifierExpression* callee; |
| std::vector<Expression*> arguments; |
| std::vector<Identifier*> labels; |
| }; |
| |
| struct NameAndExpression { |
| Identifier* name; |
| Expression* expression; |
| }; |
| |
| struct StructExpression : Expression { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(StructExpression) |
| StructExpression(SourcePosition pos, TypeExpression* type, |
| std::vector<NameAndExpression> initializers) |
| : Expression(kKind, pos), |
| type(type), |
| initializers(std::move(initializers)) {} |
| |
| void VisitAllSubExpressions(VisitCallback callback) override { |
| for (auto& initializer : initializers) { |
| initializer.expression->VisitAllSubExpressions(callback); |
| } |
| callback(this); |
| } |
| |
| TypeExpression* type; |
| std::vector<NameAndExpression> initializers; |
| }; |
| |
| struct LogicalOrExpression : Expression { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(LogicalOrExpression) |
| LogicalOrExpression(SourcePosition pos, Expression* left, Expression* right) |
| : Expression(kKind, pos), left(left), right(right) {} |
| |
| void VisitAllSubExpressions(VisitCallback callback) override { |
| left->VisitAllSubExpressions(callback); |
| right->VisitAllSubExpressions(callback); |
| callback(this); |
| } |
| |
| Expression* left; |
| Expression* right; |
| }; |
| |
| struct LogicalAndExpression : Expression { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(LogicalAndExpression) |
| LogicalAndExpression(SourcePosition pos, Expression* left, Expression* right) |
| : Expression(kKind, pos), left(left), right(right) {} |
| |
| void VisitAllSubExpressions(VisitCallback callback) override { |
| left->VisitAllSubExpressions(callback); |
| right->VisitAllSubExpressions(callback); |
| callback(this); |
| } |
| |
| Expression* left; |
| Expression* right; |
| }; |
| |
| struct SpreadExpression : Expression { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(SpreadExpression) |
| SpreadExpression(SourcePosition pos, Expression* spreadee) |
| : Expression(kKind, pos), spreadee(spreadee) {} |
| |
| void VisitAllSubExpressions(VisitCallback callback) override { |
| spreadee->VisitAllSubExpressions(callback); |
| callback(this); |
| } |
| |
| Expression* spreadee; |
| }; |
| |
| struct ConditionalExpression : Expression { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(ConditionalExpression) |
| ConditionalExpression(SourcePosition pos, Expression* condition, |
| Expression* if_true, Expression* if_false) |
| : Expression(kKind, pos), |
| condition(condition), |
| if_true(if_true), |
| if_false(if_false) {} |
| |
| void VisitAllSubExpressions(VisitCallback callback) override { |
| condition->VisitAllSubExpressions(callback); |
| if_true->VisitAllSubExpressions(callback); |
| if_false->VisitAllSubExpressions(callback); |
| callback(this); |
| } |
| |
| Expression* condition; |
| Expression* if_true; |
| Expression* if_false; |
| }; |
| |
| struct StringLiteralExpression : Expression { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(StringLiteralExpression) |
| StringLiteralExpression(SourcePosition pos, std::string literal) |
| : Expression(kKind, pos), literal(std::move(literal)) {} |
| |
| void VisitAllSubExpressions(VisitCallback callback) override { |
| callback(this); |
| } |
| |
| std::string literal; |
| }; |
| |
| struct NumberLiteralExpression : Expression { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(NumberLiteralExpression) |
| NumberLiteralExpression(SourcePosition pos, double number) |
| : Expression(kKind, pos), number(number) {} |
| |
| void VisitAllSubExpressions(VisitCallback callback) override { |
| callback(this); |
| } |
| |
| double number; |
| }; |
| |
| struct ElementAccessExpression : LocationExpression { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(ElementAccessExpression) |
| ElementAccessExpression(SourcePosition pos, Expression* array, |
| Expression* index) |
| : LocationExpression(kKind, pos), array(array), index(index) {} |
| |
| void VisitAllSubExpressions(VisitCallback callback) override { |
| array->VisitAllSubExpressions(callback); |
| index->VisitAllSubExpressions(callback); |
| callback(this); |
| } |
| |
| Expression* array; |
| Expression* index; |
| }; |
| |
| struct FieldAccessExpression : LocationExpression { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(FieldAccessExpression) |
| FieldAccessExpression(SourcePosition pos, Expression* object, |
| Identifier* field) |
| : LocationExpression(kKind, pos), object(object), field(field) {} |
| |
| void VisitAllSubExpressions(VisitCallback callback) override { |
| object->VisitAllSubExpressions(callback); |
| callback(this); |
| } |
| |
| Expression* object; |
| Identifier* field; |
| }; |
| |
| struct DereferenceExpression : LocationExpression { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(DereferenceExpression) |
| DereferenceExpression(SourcePosition pos, Expression* reference) |
| : LocationExpression(kKind, pos), reference(reference) {} |
| |
| void VisitAllSubExpressions(VisitCallback callback) override { |
| reference->VisitAllSubExpressions(callback); |
| callback(this); |
| } |
| |
| Expression* reference; |
| }; |
| |
| struct AssignmentExpression : Expression { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(AssignmentExpression) |
| AssignmentExpression(SourcePosition pos, Expression* location, |
| Expression* value) |
| : AssignmentExpression(pos, location, base::nullopt, value) {} |
| AssignmentExpression(SourcePosition pos, Expression* location, |
| base::Optional<std::string> op, Expression* value) |
| : Expression(kKind, pos), |
| location(location), |
| op(std::move(op)), |
| value(value) {} |
| |
| void VisitAllSubExpressions(VisitCallback callback) override { |
| location->VisitAllSubExpressions(callback); |
| value->VisitAllSubExpressions(callback); |
| callback(this); |
| } |
| |
| Expression* location; |
| base::Optional<std::string> op; |
| Expression* value; |
| }; |
| |
| enum class IncrementDecrementOperator { kIncrement, kDecrement }; |
| |
| struct IncrementDecrementExpression : Expression { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(IncrementDecrementExpression) |
| IncrementDecrementExpression(SourcePosition pos, Expression* location, |
| IncrementDecrementOperator op, bool postfix) |
| : Expression(kKind, pos), location(location), op(op), postfix(postfix) {} |
| |
| void VisitAllSubExpressions(VisitCallback callback) override { |
| location->VisitAllSubExpressions(callback); |
| callback(this); |
| } |
| |
| Expression* location; |
| IncrementDecrementOperator op; |
| bool postfix; |
| }; |
| |
| // This expression is only used in the desugaring of typeswitch, and it allows |
| // to bake in the static information that certain types are impossible at a |
| // certain position in the control flow. |
| // The result type is the type of {expression} minus the provided type. |
| struct AssumeTypeImpossibleExpression : Expression { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(AssumeTypeImpossibleExpression) |
| AssumeTypeImpossibleExpression(SourcePosition pos, |
| TypeExpression* excluded_type, |
| Expression* expression) |
| : Expression(kKind, pos), |
| excluded_type(excluded_type), |
| expression(expression) {} |
| |
| void VisitAllSubExpressions(VisitCallback callback) override { |
| expression->VisitAllSubExpressions(callback); |
| callback(this); |
| } |
| |
| TypeExpression* excluded_type; |
| Expression* expression; |
| }; |
| |
| struct NewExpression : Expression { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(NewExpression) |
| NewExpression(SourcePosition pos, TypeExpression* type, |
| std::vector<NameAndExpression> initializers, bool pretenured) |
| : Expression(kKind, pos), |
| type(type), |
| initializers(std::move(initializers)), |
| pretenured(pretenured) {} |
| |
| void VisitAllSubExpressions(VisitCallback callback) override { |
| for (auto& initializer : initializers) { |
| initializer.expression->VisitAllSubExpressions(callback); |
| } |
| callback(this); |
| } |
| |
| TypeExpression* type; |
| std::vector<NameAndExpression> initializers; |
| bool pretenured; |
| }; |
| |
| enum class ImplicitKind { kNoImplicit, kJSImplicit, kImplicit }; |
| |
| struct ParameterList { |
| std::vector<Identifier*> names; |
| std::vector<TypeExpression*> types; |
| ImplicitKind implicit_kind = ImplicitKind::kNoImplicit; |
| SourcePosition implicit_kind_pos = SourcePosition::Invalid(); |
| size_t implicit_count = 0; |
| bool has_varargs = false; |
| std::string arguments_variable = ""; |
| |
| static ParameterList Empty() { return {}; } |
| std::vector<TypeExpression*> GetImplicitTypes() { |
| return std::vector<TypeExpression*>(types.begin(), |
| types.begin() + implicit_count); |
| } |
| std::vector<TypeExpression*> GetExplicitTypes() { |
| return std::vector<TypeExpression*>(types.begin() + implicit_count, |
| types.end()); |
| } |
| }; |
| |
| struct BasicTypeExpression : TypeExpression { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(BasicTypeExpression) |
| BasicTypeExpression(SourcePosition pos, |
| std::vector<std::string> namespace_qualification, |
| std::string name, |
| std::vector<TypeExpression*> generic_arguments) |
| : TypeExpression(kKind, pos), |
| namespace_qualification(std::move(namespace_qualification)), |
| is_constexpr(IsConstexprName(name)), |
| name(std::move(name)), |
| generic_arguments(std::move(generic_arguments)) {} |
| BasicTypeExpression(SourcePosition pos, std::string name) |
| : BasicTypeExpression(pos, {}, std::move(name), {}) {} |
| std::vector<std::string> namespace_qualification; |
| bool is_constexpr; |
| std::string name; |
| std::vector<TypeExpression*> generic_arguments; |
| }; |
| |
| struct FunctionTypeExpression : TypeExpression { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(FunctionTypeExpression) |
| FunctionTypeExpression(SourcePosition pos, |
| std::vector<TypeExpression*> parameters, |
| TypeExpression* return_type) |
| : TypeExpression(kKind, pos), |
| parameters(std::move(parameters)), |
| return_type(return_type) {} |
| std::vector<TypeExpression*> parameters; |
| TypeExpression* return_type; |
| }; |
| |
| // A PrecomputedTypeExpression is never created directly by the parser. Later |
| // stages can use this to insert AST snippets where the type has already been |
| // resolved. |
| class Type; |
| struct PrecomputedTypeExpression : TypeExpression { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(PrecomputedTypeExpression) |
| PrecomputedTypeExpression(SourcePosition pos, const Type* type) |
| : TypeExpression(kKind, pos), type(type) {} |
| const Type* type; |
| }; |
| |
| struct UnionTypeExpression : TypeExpression { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(UnionTypeExpression) |
| UnionTypeExpression(SourcePosition pos, TypeExpression* a, TypeExpression* b) |
| : TypeExpression(kKind, pos), a(a), b(b) {} |
| TypeExpression* a; |
| TypeExpression* b; |
| }; |
| |
| struct ExpressionStatement : Statement { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(ExpressionStatement) |
| ExpressionStatement(SourcePosition pos, Expression* expression) |
| : Statement(kKind, pos), expression(expression) {} |
| Expression* expression; |
| }; |
| |
| struct IfStatement : Statement { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(IfStatement) |
| IfStatement(SourcePosition pos, bool is_constexpr, Expression* condition, |
| Statement* if_true, base::Optional<Statement*> if_false) |
| : Statement(kKind, pos), |
| condition(condition), |
| is_constexpr(is_constexpr), |
| if_true(if_true), |
| if_false(if_false) {} |
| Expression* condition; |
| bool is_constexpr; |
| Statement* if_true; |
| base::Optional<Statement*> if_false; |
| }; |
| |
| struct WhileStatement : Statement { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(WhileStatement) |
| WhileStatement(SourcePosition pos, Expression* condition, Statement* body) |
| : Statement(kKind, pos), condition(condition), body(body) {} |
| Expression* condition; |
| Statement* body; |
| }; |
| |
| struct ReturnStatement : Statement { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(ReturnStatement) |
| ReturnStatement(SourcePosition pos, base::Optional<Expression*> value) |
| : Statement(kKind, pos), value(value) {} |
| base::Optional<Expression*> value; |
| }; |
| |
| struct DebugStatement : Statement { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(DebugStatement) |
| DebugStatement(SourcePosition pos, const std::string& reason, |
| bool never_continues) |
| : Statement(kKind, pos), |
| reason(reason), |
| never_continues(never_continues) {} |
| std::string reason; |
| bool never_continues; |
| }; |
| |
| struct AssertStatement : Statement { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(AssertStatement) |
| enum class AssertKind { kAssert, kCheck, kStaticAssert }; |
| AssertStatement(SourcePosition pos, AssertKind kind, Expression* expression, |
| std::string source) |
| : Statement(kKind, pos), |
| kind(kind), |
| expression(expression), |
| source(std::move(source)) {} |
| AssertKind kind; |
| Expression* expression; |
| std::string source; |
| }; |
| |
| struct TailCallStatement : Statement { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(TailCallStatement) |
| TailCallStatement(SourcePosition pos, CallExpression* call) |
| : Statement(kKind, pos), call(call) {} |
| CallExpression* call; |
| }; |
| |
| struct VarDeclarationStatement : Statement { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(VarDeclarationStatement) |
| VarDeclarationStatement( |
| SourcePosition pos, bool const_qualified, Identifier* name, |
| base::Optional<TypeExpression*> type, |
| base::Optional<Expression*> initializer = base::nullopt) |
| : Statement(kKind, pos), |
| const_qualified(const_qualified), |
| name(name), |
| type(type), |
| initializer(initializer) {} |
| bool const_qualified; |
| Identifier* name; |
| base::Optional<TypeExpression*> type; |
| base::Optional<Expression*> initializer; |
| }; |
| |
| struct BreakStatement : Statement { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(BreakStatement) |
| explicit BreakStatement(SourcePosition pos) : Statement(kKind, pos) {} |
| }; |
| |
| struct ContinueStatement : Statement { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(ContinueStatement) |
| explicit ContinueStatement(SourcePosition pos) : Statement(kKind, pos) {} |
| }; |
| |
| struct GotoStatement : Statement { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(GotoStatement) |
| GotoStatement(SourcePosition pos, Identifier* label, |
| const std::vector<Expression*>& arguments) |
| : Statement(kKind, pos), label(label), arguments(std::move(arguments)) {} |
| Identifier* label; |
| std::vector<Expression*> arguments; |
| }; |
| |
| struct ForLoopStatement : Statement { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(ForLoopStatement) |
| ForLoopStatement(SourcePosition pos, base::Optional<Statement*> declaration, |
| base::Optional<Expression*> test, |
| base::Optional<Statement*> action, Statement* body) |
| : Statement(kKind, pos), |
| var_declaration(), |
| test(std::move(test)), |
| action(std::move(action)), |
| body(std::move(body)) { |
| if (declaration) |
| var_declaration = VarDeclarationStatement::cast(*declaration); |
| } |
| base::Optional<VarDeclarationStatement*> var_declaration; |
| base::Optional<Expression*> test; |
| base::Optional<Statement*> action; |
| Statement* body; |
| }; |
| |
| struct TryHandler : AstNode { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(TryHandler) |
| enum class HandlerKind { kCatch, kLabel }; |
| TryHandler(SourcePosition pos, HandlerKind handler_kind, Identifier* label, |
| const ParameterList& parameters, Statement* body) |
| : AstNode(kKind, pos), |
| handler_kind(handler_kind), |
| label(label), |
| parameters(parameters), |
| body(std::move(body)) {} |
| HandlerKind handler_kind; |
| Identifier* label; |
| ParameterList parameters; |
| Statement* body; |
| }; |
| |
| struct StatementExpression : Expression { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(StatementExpression) |
| StatementExpression(SourcePosition pos, Statement* statement) |
| : Expression(kKind, pos), statement(statement) {} |
| Statement* statement; |
| }; |
| |
| struct TryLabelExpression : Expression { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(TryLabelExpression) |
| TryLabelExpression(SourcePosition pos, Expression* try_expression, |
| TryHandler* label_block) |
| : Expression(kKind, pos), |
| try_expression(try_expression), |
| label_block(label_block) {} |
| Expression* try_expression; |
| TryHandler* label_block; |
| }; |
| |
| struct BlockStatement : Statement { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(BlockStatement) |
| explicit BlockStatement(SourcePosition pos, bool deferred = false, |
| std::vector<Statement*> statements = {}) |
| : Statement(kKind, pos), |
| deferred(deferred), |
| statements(std::move(statements)) {} |
| bool deferred; |
| std::vector<Statement*> statements; |
| }; |
| |
| struct TypeDeclaration : Declaration { |
| DEFINE_AST_NODE_INNER_BOILERPLATE(TypeDeclaration) |
| TypeDeclaration(Kind kKind, SourcePosition pos, Identifier* name) |
| : Declaration(kKind, pos), name(name) {} |
| Identifier* name; |
| }; |
| |
| struct InstanceTypeConstraints { |
| InstanceTypeConstraints() : value(-1), num_flags_bits(-1) {} |
| int value; |
| int num_flags_bits; |
| }; |
| |
| struct AbstractTypeDeclaration : TypeDeclaration { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(AbstractTypeDeclaration) |
| AbstractTypeDeclaration(SourcePosition pos, Identifier* name, |
| AbstractTypeFlags flags, |
| base::Optional<TypeExpression*> extends, |
| base::Optional<std::string> generates) |
| : TypeDeclaration(kKind, pos, name), |
| flags(flags), |
| extends(extends), |
| generates(std::move(generates)) { |
| CHECK_EQ(IsConstexprName(name->value), |
| !!(flags & AbstractTypeFlag::kConstexpr)); |
| } |
| |
| bool IsConstexpr() const { return flags & AbstractTypeFlag::kConstexpr; } |
| bool IsTransient() const { return flags & AbstractTypeFlag::kTransient; } |
| |
| AbstractTypeFlags flags; |
| base::Optional<TypeExpression*> extends; |
| base::Optional<std::string> generates; |
| }; |
| |
| struct TypeAliasDeclaration : TypeDeclaration { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(TypeAliasDeclaration) |
| TypeAliasDeclaration(SourcePosition pos, Identifier* name, |
| TypeExpression* type) |
| : TypeDeclaration(kKind, pos, name), type(type) {} |
| TypeExpression* type; |
| }; |
| |
| struct NameAndTypeExpression { |
| Identifier* name; |
| TypeExpression* type; |
| }; |
| |
| struct ImplicitParameters { |
| Identifier* kind; |
| std::vector<NameAndTypeExpression> parameters; |
| }; |
| |
| struct StructFieldExpression { |
| NameAndTypeExpression name_and_type; |
| bool const_qualified; |
| }; |
| |
| struct BitFieldDeclaration { |
| NameAndTypeExpression name_and_type; |
| int num_bits; |
| }; |
| |
| enum class ConditionalAnnotationType { |
| kPositive, |
| kNegative, |
| }; |
| |
| struct ConditionalAnnotation { |
| std::string condition; |
| ConditionalAnnotationType type; |
| }; |
| |
| struct AnnotationParameter { |
| std::string string_value; |
| int int_value; |
| bool is_int; |
| }; |
| |
| struct Annotation { |
| Identifier* name; |
| base::Optional<AnnotationParameter> param; |
| }; |
| |
| struct ClassFieldExpression { |
| NameAndTypeExpression name_and_type; |
| base::Optional<Expression*> index; |
| std::vector<ConditionalAnnotation> conditions; |
| bool weak; |
| bool const_qualified; |
| bool generate_verify; |
| }; |
| |
| struct LabelAndTypes { |
| Identifier* name; |
| std::vector<TypeExpression*> types; |
| }; |
| |
| using LabelAndTypesVector = std::vector<LabelAndTypes>; |
| |
| struct CallableDeclaration : Declaration { |
| CallableDeclaration(AstNode::Kind kind, SourcePosition pos, |
| bool transitioning, Identifier* name, |
| ParameterList parameters, TypeExpression* return_type, |
| LabelAndTypesVector labels) |
| : Declaration(kind, pos), |
| transitioning(transitioning), |
| name(name), |
| parameters(std::move(parameters)), |
| return_type(return_type), |
| labels(std::move(labels)) {} |
| DEFINE_AST_NODE_INNER_BOILERPLATE(CallableDeclaration) |
| bool transitioning; |
| Identifier* name; |
| ParameterList parameters; |
| TypeExpression* return_type; |
| LabelAndTypesVector labels; |
| }; |
| |
| struct MacroDeclaration : CallableDeclaration { |
| DEFINE_AST_NODE_INNER_BOILERPLATE(MacroDeclaration) |
| MacroDeclaration(AstNode::Kind kind, SourcePosition pos, bool transitioning, |
| Identifier* name, base::Optional<std::string> op, |
| ParameterList parameters, TypeExpression* return_type, |
| const LabelAndTypesVector& labels) |
| : CallableDeclaration(kind, pos, transitioning, name, |
| std::move(parameters), return_type, labels), |
| op(std::move(op)) { |
| if (parameters.implicit_kind == ImplicitKind::kJSImplicit) { |
| Error("Cannot use \"js-implicit\" with macros, use \"implicit\" instead.") |
| .Position(parameters.implicit_kind_pos); |
| } |
| } |
| base::Optional<std::string> op; |
| }; |
| |
| struct ExternalMacroDeclaration : MacroDeclaration { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(ExternalMacroDeclaration) |
| ExternalMacroDeclaration(SourcePosition pos, bool transitioning, |
| std::string external_assembler_name, |
| Identifier* name, base::Optional<std::string> op, |
| ParameterList parameters, |
| TypeExpression* return_type, |
| const LabelAndTypesVector& labels) |
| : MacroDeclaration(kKind, pos, transitioning, name, std::move(op), |
| std::move(parameters), return_type, labels), |
| external_assembler_name(std::move(external_assembler_name)) {} |
| std::string external_assembler_name; |
| }; |
| |
| struct IntrinsicDeclaration : CallableDeclaration { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(IntrinsicDeclaration) |
| IntrinsicDeclaration(SourcePosition pos, Identifier* name, |
| ParameterList parameters, TypeExpression* return_type) |
| : CallableDeclaration(kKind, pos, false, name, std::move(parameters), |
| return_type, {}) { |
| if (parameters.implicit_kind != ImplicitKind::kNoImplicit) { |
| Error("Intinsics cannot have implicit parameters."); |
| } |
| } |
| }; |
| |
| struct TorqueMacroDeclaration : MacroDeclaration { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(TorqueMacroDeclaration) |
| TorqueMacroDeclaration(SourcePosition pos, bool transitioning, |
| Identifier* name, base::Optional<std::string> op, |
| ParameterList parameters, TypeExpression* return_type, |
| const LabelAndTypesVector& labels, bool export_to_csa, |
| base::Optional<Statement*> body) |
| : MacroDeclaration(kKind, pos, transitioning, name, std::move(op), |
| std::move(parameters), return_type, labels), |
| export_to_csa(export_to_csa), |
| body(body) {} |
| bool export_to_csa; |
| base::Optional<Statement*> body; |
| }; |
| |
| struct BuiltinDeclaration : CallableDeclaration { |
| DEFINE_AST_NODE_INNER_BOILERPLATE(BuiltinDeclaration) |
| BuiltinDeclaration(AstNode::Kind kind, SourcePosition pos, |
| bool javascript_linkage, bool transitioning, |
| Identifier* name, ParameterList parameters, |
| TypeExpression* return_type) |
| : CallableDeclaration(kind, pos, transitioning, name, |
| std::move(parameters), return_type, {}), |
| javascript_linkage(javascript_linkage) { |
| if (parameters.implicit_kind == ImplicitKind::kJSImplicit && |
| !javascript_linkage) { |
| Error( |
| "\"js-implicit\" is for implicit parameters passed according to the " |
| "JavaScript calling convention. Use \"implicit\" instead."); |
| } |
| if (parameters.implicit_kind == ImplicitKind::kImplicit && |
| javascript_linkage) { |
| Error( |
| "The JavaScript calling convention implicitly passes a fixed set of " |
| "values. Use \"js-implicit\" to refer to those.") |
| .Position(parameters.implicit_kind_pos); |
| } |
| } |
| bool javascript_linkage; |
| }; |
| |
| struct ExternalBuiltinDeclaration : BuiltinDeclaration { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(ExternalBuiltinDeclaration) |
| ExternalBuiltinDeclaration(SourcePosition pos, bool transitioning, |
| bool javascript_linkage, Identifier* name, |
| ParameterList parameters, |
| TypeExpression* return_type) |
| : BuiltinDeclaration(kKind, pos, javascript_linkage, transitioning, name, |
| std::move(parameters), return_type) {} |
| }; |
| |
| struct TorqueBuiltinDeclaration : BuiltinDeclaration { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(TorqueBuiltinDeclaration) |
| TorqueBuiltinDeclaration(SourcePosition pos, bool transitioning, |
| bool javascript_linkage, Identifier* name, |
| ParameterList parameters, |
| TypeExpression* return_type, |
| base::Optional<Statement*> body) |
| : BuiltinDeclaration(kKind, pos, javascript_linkage, transitioning, name, |
| std::move(parameters), return_type), |
| body(body) {} |
| base::Optional<Statement*> body; |
| }; |
| |
| struct ExternalRuntimeDeclaration : CallableDeclaration { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(ExternalRuntimeDeclaration) |
| ExternalRuntimeDeclaration(SourcePosition pos, bool transitioning, |
| Identifier* name, ParameterList parameters, |
| TypeExpression* return_type) |
| : CallableDeclaration(kKind, pos, transitioning, name, parameters, |
| return_type, {}) {} |
| }; |
| |
| struct ConstDeclaration : Declaration { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(ConstDeclaration) |
| ConstDeclaration(SourcePosition pos, Identifier* name, TypeExpression* type, |
| Expression* expression) |
| : Declaration(kKind, pos), |
| name(name), |
| type(type), |
| expression(expression) {} |
| Identifier* name; |
| TypeExpression* type; |
| Expression* expression; |
| }; |
| |
| struct GenericParameter { |
| Identifier* name; |
| base::Optional<TypeExpression*> constraint; |
| }; |
| |
| using GenericParameters = std::vector<GenericParameter>; |
| |
| // The AST re-shuffles generics from the concrete syntax: |
| // Instead of the generic parameters being part of a normal declaration, |
| // a declaration with generic parameters gets wrapped in a generic declaration, |
| // which holds the generic parameters. This corresponds to how you write |
| // templates in C++, with the template parameters coming before the declaration. |
| |
| struct GenericCallableDeclaration : Declaration { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(GenericCallableDeclaration) |
| GenericCallableDeclaration(SourcePosition pos, |
| GenericParameters generic_parameters, |
| CallableDeclaration* declaration) |
| : Declaration(kKind, pos), |
| generic_parameters(std::move(generic_parameters)), |
| declaration(declaration) {} |
| |
| GenericParameters generic_parameters; |
| CallableDeclaration* declaration; |
| }; |
| |
| struct GenericTypeDeclaration : Declaration { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(GenericTypeDeclaration) |
| GenericTypeDeclaration(SourcePosition pos, |
| GenericParameters generic_parameters, |
| TypeDeclaration* declaration) |
| : Declaration(kKind, pos), |
| generic_parameters(std::move(generic_parameters)), |
| declaration(declaration) {} |
| |
| GenericParameters generic_parameters; |
| TypeDeclaration* declaration; |
| }; |
| |
| struct SpecializationDeclaration : CallableDeclaration { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(SpecializationDeclaration) |
| SpecializationDeclaration(SourcePosition pos, bool transitioning, |
| Identifier* name, |
| std::vector<TypeExpression*> generic_parameters, |
| ParameterList parameters, |
| TypeExpression* return_type, |
| LabelAndTypesVector labels, Statement* body) |
| : CallableDeclaration(kKind, pos, transitioning, name, |
| std::move(parameters), return_type, |
| std::move(labels)), |
| generic_parameters(std::move(generic_parameters)), |
| body(body) {} |
| std::vector<TypeExpression*> generic_parameters; |
| Statement* body; |
| }; |
| |
| struct ExternConstDeclaration : Declaration { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(ExternConstDeclaration) |
| ExternConstDeclaration(SourcePosition pos, Identifier* name, |
| TypeExpression* type, std::string literal) |
| : Declaration(kKind, pos), |
| name(name), |
| type(type), |
| literal(std::move(literal)) {} |
| Identifier* name; |
| TypeExpression* type; |
| std::string literal; |
| }; |
| |
| struct StructDeclaration : TypeDeclaration { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(StructDeclaration) |
| StructDeclaration(SourcePosition pos, StructFlags flags, Identifier* name, |
| std::vector<Declaration*> methods, |
| std::vector<StructFieldExpression> fields) |
| : TypeDeclaration(kKind, pos, name), |
| flags(flags), |
| methods(std::move(methods)), |
| fields(std::move(fields)) {} |
| StructFlags flags; |
| std::vector<Declaration*> methods; |
| std::vector<StructFieldExpression> fields; |
| }; |
| |
| struct BitFieldStructDeclaration : TypeDeclaration { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(BitFieldStructDeclaration) |
| BitFieldStructDeclaration(SourcePosition pos, Identifier* name, |
| TypeExpression* parent, |
| std::vector<BitFieldDeclaration> fields) |
| : TypeDeclaration(kKind, pos, name), |
| parent(parent), |
| fields(std::move(fields)) {} |
| TypeExpression* parent; |
| std::vector<BitFieldDeclaration> fields; |
| }; |
| |
| struct ClassBody : AstNode { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(ClassBody) |
| ClassBody(SourcePosition pos, std::vector<Declaration*> methods, |
| std::vector<ClassFieldExpression> fields) |
| : AstNode(kKind, pos), |
| methods(std::move(methods)), |
| fields(std::move(fields)) {} |
| std::vector<Declaration*> methods; |
| std::vector<ClassFieldExpression> fields; |
| }; |
| |
| struct ClassDeclaration : TypeDeclaration { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(ClassDeclaration) |
| ClassDeclaration(SourcePosition pos, Identifier* name, ClassFlags flags, |
| TypeExpression* super, base::Optional<std::string> generates, |
| std::vector<Declaration*> methods, |
| std::vector<ClassFieldExpression> fields, |
| InstanceTypeConstraints instance_type_constraints) |
| : TypeDeclaration(kKind, pos, name), |
| flags(flags), |
| super(super), |
| generates(std::move(generates)), |
| methods(std::move(methods)), |
| fields(std::move(fields)), |
| instance_type_constraints(std::move(instance_type_constraints)) {} |
| ClassFlags flags; |
| TypeExpression* super; |
| base::Optional<std::string> generates; |
| std::vector<Declaration*> methods; |
| std::vector<ClassFieldExpression> fields; |
| InstanceTypeConstraints instance_type_constraints; |
| }; |
| |
| struct CppIncludeDeclaration : Declaration { |
| DEFINE_AST_NODE_LEAF_BOILERPLATE(CppIncludeDeclaration) |
| CppIncludeDeclaration(SourcePosition pos, std::string include_path) |
| : Declaration(kKind, pos), include_path(std::move(include_path)) {} |
| std::string include_path; |
| }; |
| |
| #define ENUM_ITEM(name) \ |
| case AstNode::Kind::k##name: \ |
| return std::is_base_of<T, name>::value; \ |
| break; |
| |
| template <class T> |
| bool AstNodeClassCheck::IsInstanceOf(AstNode* node) { |
| switch (node->kind) { |
| AST_NODE_KIND_LIST(ENUM_ITEM) |
| default: |
| UNIMPLEMENTED(); |
| } |
| return true; |
| } |
| |
| #undef ENUM_ITEM |
| |
| inline bool IsDeferred(Statement* stmt) { |
| if (auto* block = BlockStatement::DynamicCast(stmt)) { |
| return block->deferred; |
| } |
| return false; |
| } |
| |
| DECLARE_CONTEXTUAL_VARIABLE(CurrentAst, Ast); |
| |
| template <class T, class... Args> |
| T* MakeNode(Args... args) { |
| return CurrentAst::Get().AddNode( |
| std::make_unique<T>(CurrentSourcePosition::Get(), std::move(args)...)); |
| } |
| |
| inline FieldAccessExpression* MakeFieldAccessExpression(Expression* object, |
| std::string field) { |
| return MakeNode<FieldAccessExpression>( |
| object, MakeNode<Identifier>(std::move(field))); |
| } |
| |
| inline IdentifierExpression* MakeIdentifierExpression( |
| std::vector<std::string> namespace_qualification, std::string name, |
| std::vector<TypeExpression*> args = {}) { |
| return MakeNode<IdentifierExpression>(std::move(namespace_qualification), |
| MakeNode<Identifier>(std::move(name)), |
| std::move(args)); |
| } |
| |
| inline IdentifierExpression* MakeIdentifierExpression(std::string name) { |
| return MakeIdentifierExpression({}, std::move(name)); |
| } |
| |
| inline CallExpression* MakeCallExpression( |
| IdentifierExpression* callee, std::vector<Expression*> arguments, |
| std::vector<Identifier*> labels = {}) { |
| return MakeNode<CallExpression>(callee, std::move(arguments), |
| std::move(labels)); |
| } |
| |
| inline CallExpression* MakeCallExpression( |
| std::string callee, std::vector<Expression*> arguments, |
| std::vector<Identifier*> labels = {}) { |
| return MakeCallExpression(MakeIdentifierExpression(std::move(callee)), |
| std::move(arguments), std::move(labels)); |
| } |
| |
| inline VarDeclarationStatement* MakeConstDeclarationStatement( |
| std::string name, Expression* initializer) { |
| return MakeNode<VarDeclarationStatement>( |
| /*const_qualified=*/true, MakeNode<Identifier>(std::move(name)), |
| base::Optional<TypeExpression*>{}, initializer); |
| } |
| |
| inline BasicTypeExpression* MakeBasicTypeExpression( |
| std::vector<std::string> namespace_qualification, std::string name, |
| std::vector<TypeExpression*> generic_arguments = {}) { |
| return MakeNode<BasicTypeExpression>(std::move(namespace_qualification), |
| std::move(name), |
| std::move(generic_arguments)); |
| } |
| |
| inline StructExpression* MakeStructExpression( |
| TypeExpression* type, std::vector<NameAndExpression> initializers) { |
| return MakeNode<StructExpression>(type, std::move(initializers)); |
| } |
| |
| } // namespace torque |
| } // namespace internal |
| } // namespace v8 |
| |
| #endif // V8_TORQUE_AST_H_ |