blob: a51535d392bb100dadf9ee427ca4a7cc3706bb27 [file] [log] [blame]
// 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_