/* * Copyright (c) 2020-2021, Andreas Kling * Copyright (c) 2020, Linus Groh * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include #include #include #include #include #include #include #include namespace JS { class VariableDeclaration; class FunctionDeclaration; class Identifier; enum class FunctionKind { Generator, Regular, }; template static inline NonnullRefPtr create_ast_node(SourceRange range, Args&&... args) { return adopt_ref(*new T(range, forward(args)...)); } class ASTNode : public RefCounted { public: virtual ~ASTNode() { } virtual Value execute(Interpreter&, GlobalObject&) const = 0; virtual void generate_bytecode(Bytecode::Generator&) const; virtual void dump(int indent) const; SourceRange const& source_range() const { return m_source_range; } SourceRange& source_range() { return m_source_range; } String class_name() const; template bool fast_is() const = delete; virtual bool is_new_expression() const { return false; } virtual bool is_member_expression() const { return false; } virtual bool is_super_expression() const { return false; } virtual bool is_expression_statement() const { return false; } virtual bool is_identifier() const { return false; } virtual bool is_scope_node() const { return false; } virtual bool is_program() const { return false; } protected: explicit ASTNode(SourceRange source_range) : m_source_range(source_range) { } private: SourceRange m_source_range; }; class Statement : public ASTNode { public: explicit Statement(SourceRange source_range) : ASTNode(source_range) { } FlyString const& label() const { return m_label; } void set_label(FlyString string) { m_label = move(string); } protected: FlyString m_label; }; class EmptyStatement final : public Statement { public: explicit EmptyStatement(SourceRange source_range) : Statement(source_range) { } Value execute(Interpreter&, GlobalObject&) const override { return {}; } virtual void generate_bytecode(Bytecode::Generator&) const override; }; class ErrorStatement final : public Statement { public: explicit ErrorStatement(SourceRange source_range) : Statement(source_range) { } Value execute(Interpreter&, GlobalObject&) const override { return {}; } }; class ExpressionStatement final : public Statement { public: ExpressionStatement(SourceRange source_range, NonnullRefPtr expression) : Statement(source_range) , m_expression(move(expression)) { } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; virtual void generate_bytecode(Bytecode::Generator&) const override; Expression const& expression() const { return m_expression; }; private: virtual bool is_expression_statement() const override { return true; } NonnullRefPtr m_expression; }; class ScopeNode : public Statement { public: template T& append(SourceRange range, Args&&... args) { auto child = create_ast_node(range, forward(args)...); m_children.append(move(child)); return static_cast(m_children.last()); } void append(NonnullRefPtr child) { m_children.append(move(child)); } NonnullRefPtrVector const& children() const { return m_children; } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; virtual void generate_bytecode(Bytecode::Generator&) const override; void add_variables(NonnullRefPtrVector); void add_functions(NonnullRefPtrVector); void add_hoisted_function(NonnullRefPtr); NonnullRefPtrVector const& variables() const { return m_variables; } NonnullRefPtrVector const& functions() const { return m_functions; } NonnullRefPtrVector const& hoisted_functions() const { return m_hoisted_functions; } protected: explicit ScopeNode(SourceRange source_range) : Statement(source_range) { } private: virtual bool is_scope_node() const final { return true; } NonnullRefPtrVector m_children; NonnullRefPtrVector m_variables; NonnullRefPtrVector m_functions; NonnullRefPtrVector m_hoisted_functions; }; class Program final : public ScopeNode { public: explicit Program(SourceRange source_range) : ScopeNode(source_range) { } virtual Value execute(Interpreter&, GlobalObject&) const override; bool is_strict_mode() const { return m_is_strict_mode; } void set_strict_mode() { m_is_strict_mode = true; } private: virtual bool is_program() const override { return true; } bool m_is_strict_mode { false }; }; class BlockStatement final : public ScopeNode { public: explicit BlockStatement(SourceRange source_range) : ScopeNode(source_range) { } }; class Expression : public ASTNode { public: explicit Expression(SourceRange source_range) : ASTNode(source_range) { } virtual Reference to_reference(Interpreter&, GlobalObject&) const; }; class Declaration : public Statement { public: explicit Declaration(SourceRange source_range) : Statement(source_range) { } }; class ErrorDeclaration final : public Declaration { public: explicit ErrorDeclaration(SourceRange source_range) : Declaration(source_range) { } Value execute(Interpreter&, GlobalObject&) const override { return {}; } }; struct BindingPattern : RefCounted { // This covers both BindingProperty and BindingElement, hence the more generic name struct BindingEntry { // If this entry represents a BindingElement, then name will be Empty Variant, NonnullRefPtr, Empty> name { Empty {} }; Variant, NonnullRefPtr, Empty> alias { Empty {} }; RefPtr initializer {}; bool is_rest { false }; bool is_elision() const { return name.has() && alias.has(); } }; enum class Kind { Array, Object, }; void dump(int indent) const; template void for_each_bound_name(C&& callback) const; Vector entries; Kind kind { Kind::Object }; }; class FunctionNode { public: struct Parameter { Variant> binding; RefPtr default_value; bool is_rest { false }; }; FlyString const& name() const { return m_name; } Statement const& body() const { return *m_body; } Vector const& parameters() const { return m_parameters; }; i32 function_length() const { return m_function_length; } bool is_strict_mode() const { return m_is_strict_mode; } bool is_arrow_function() const { return m_is_arrow_function; } FunctionKind kind() const { return m_kind; } protected: FunctionNode(FlyString name, NonnullRefPtr body, Vector parameters, i32 function_length, FunctionKind kind, bool is_strict_mode, bool is_arrow_function) : m_name(move(name)) , m_body(move(body)) , m_parameters(move(parameters)) , m_function_length(function_length) , m_kind(kind) , m_is_strict_mode(is_strict_mode) , m_is_arrow_function(is_arrow_function) { } void dump(int indent, String const& class_name) const; protected: void set_name(FlyString name) { VERIFY(m_name.is_empty()); m_name = move(name); } private: FlyString m_name; NonnullRefPtr m_body; Vector const m_parameters; const i32 m_function_length; FunctionKind m_kind; bool m_is_strict_mode; bool m_is_arrow_function { false }; }; class FunctionDeclaration final : public Declaration , public FunctionNode { public: static bool must_have_name() { return true; } FunctionDeclaration(SourceRange source_range, FlyString const& name, NonnullRefPtr body, Vector parameters, i32 function_length, FunctionKind kind, bool is_strict_mode = false) : Declaration(source_range) , FunctionNode(name, move(body), move(parameters), function_length, kind, is_strict_mode, false) { } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; virtual void generate_bytecode(Bytecode::Generator&) const override; }; class FunctionExpression final : public Expression , public FunctionNode { public: static bool must_have_name() { return false; } FunctionExpression(SourceRange source_range, FlyString const& name, NonnullRefPtr body, Vector parameters, i32 function_length, FunctionKind kind, bool is_strict_mode, bool is_arrow_function = false) : Expression(source_range) , FunctionNode(name, move(body), move(parameters), function_length, kind, is_strict_mode, is_arrow_function) { } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; void set_name_if_possible(FlyString new_name) { if (m_cannot_auto_rename) return; m_cannot_auto_rename = true; if (name().is_empty()) { set_name(move(new_name)); m_is_auto_renamed = true; } } bool cannot_auto_rename() const { return m_cannot_auto_rename; } bool is_auto_renamed() const { return m_is_auto_renamed; } void set_cannot_auto_rename() { m_cannot_auto_rename = true; } virtual void generate_bytecode(Bytecode::Generator&) const override; private: bool m_cannot_auto_rename { false }; bool m_is_auto_renamed { false }; }; class ErrorExpression final : public Expression { public: explicit ErrorExpression(SourceRange source_range) : Expression(source_range) { } Value execute(Interpreter&, GlobalObject&) const override { return {}; } }; class YieldExpression final : public Expression { public: explicit YieldExpression(SourceRange source_range, RefPtr argument, bool is_yield_from) : Expression(source_range) , m_argument(move(argument)) , m_is_yield_from(is_yield_from) { } Expression const* argument() const { return m_argument; } bool is_yield_from() const { return m_is_yield_from; } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; virtual void generate_bytecode(Bytecode::Generator&) const override; private: RefPtr m_argument; bool m_is_yield_from { false }; }; class ReturnStatement final : public Statement { public: explicit ReturnStatement(SourceRange source_range, RefPtr argument) : Statement(source_range) , m_argument(move(argument)) { } Expression const* argument() const { return m_argument; } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; virtual void generate_bytecode(Bytecode::Generator&) const override; private: RefPtr m_argument; }; class IfStatement final : public Statement { public: IfStatement(SourceRange source_range, NonnullRefPtr predicate, NonnullRefPtr consequent, RefPtr alternate) : Statement(source_range) , m_predicate(move(predicate)) , m_consequent(move(consequent)) , m_alternate(move(alternate)) { } Expression const& predicate() const { return *m_predicate; } Statement const& consequent() const { return *m_consequent; } Statement const* alternate() const { return m_alternate; } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; virtual void generate_bytecode(Bytecode::Generator&) const override; private: NonnullRefPtr m_predicate; NonnullRefPtr m_consequent; RefPtr m_alternate; }; class WhileStatement final : public Statement { public: WhileStatement(SourceRange source_range, NonnullRefPtr test, NonnullRefPtr body) : Statement(source_range) , m_test(move(test)) , m_body(move(body)) { } Expression const& test() const { return *m_test; } Statement const& body() const { return *m_body; } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; virtual void generate_bytecode(Bytecode::Generator&) const override; private: NonnullRefPtr m_test; NonnullRefPtr m_body; }; class DoWhileStatement final : public Statement { public: DoWhileStatement(SourceRange source_range, NonnullRefPtr test, NonnullRefPtr body) : Statement(source_range) , m_test(move(test)) , m_body(move(body)) { } Expression const& test() const { return *m_test; } Statement const& body() const { return *m_body; } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; virtual void generate_bytecode(Bytecode::Generator&) const override; private: NonnullRefPtr m_test; NonnullRefPtr m_body; }; class WithStatement final : public Statement { public: WithStatement(SourceRange source_range, NonnullRefPtr object, NonnullRefPtr body) : Statement(source_range) , m_object(move(object)) , m_body(move(body)) { } Expression const& object() const { return *m_object; } Statement const& body() const { return *m_body; } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; private: NonnullRefPtr m_object; NonnullRefPtr m_body; }; class ForStatement final : public Statement { public: ForStatement(SourceRange source_range, RefPtr init, RefPtr test, RefPtr update, NonnullRefPtr body) : Statement(source_range) , m_init(move(init)) , m_test(move(test)) , m_update(move(update)) , m_body(move(body)) { } ASTNode const* init() const { return m_init; } Expression const* test() const { return m_test; } Expression const* update() const { return m_update; } Statement const& body() const { return *m_body; } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; virtual void generate_bytecode(Bytecode::Generator&) const override; private: RefPtr m_init; RefPtr m_test; RefPtr m_update; NonnullRefPtr m_body; }; class ForInStatement final : public Statement { public: ForInStatement(SourceRange source_range, NonnullRefPtr lhs, NonnullRefPtr rhs, NonnullRefPtr body) : Statement(source_range) , m_lhs(move(lhs)) , m_rhs(move(rhs)) , m_body(move(body)) { } ASTNode const& lhs() const { return *m_lhs; } Expression const& rhs() const { return *m_rhs; } Statement const& body() const { return *m_body; } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; private: NonnullRefPtr m_lhs; NonnullRefPtr m_rhs; NonnullRefPtr m_body; }; class ForOfStatement final : public Statement { public: ForOfStatement(SourceRange source_range, NonnullRefPtr lhs, NonnullRefPtr rhs, NonnullRefPtr body) : Statement(source_range) , m_lhs(move(lhs)) , m_rhs(move(rhs)) , m_body(move(body)) { } ASTNode const& lhs() const { return *m_lhs; } Expression const& rhs() const { return *m_rhs; } Statement const& body() const { return *m_body; } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; private: NonnullRefPtr m_lhs; NonnullRefPtr m_rhs; NonnullRefPtr m_body; }; enum class BinaryOp { Addition, Subtraction, Multiplication, Division, Modulo, Exponentiation, TypedEquals, TypedInequals, AbstractEquals, AbstractInequals, GreaterThan, GreaterThanEquals, LessThan, LessThanEquals, BitwiseAnd, BitwiseOr, BitwiseXor, LeftShift, RightShift, UnsignedRightShift, In, InstanceOf, }; class BinaryExpression final : public Expression { public: BinaryExpression(SourceRange source_range, BinaryOp op, NonnullRefPtr lhs, NonnullRefPtr rhs) : Expression(source_range) , m_op(op) , m_lhs(move(lhs)) , m_rhs(move(rhs)) { } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; virtual void generate_bytecode(Bytecode::Generator&) const override; private: BinaryOp m_op; NonnullRefPtr m_lhs; NonnullRefPtr m_rhs; }; enum class LogicalOp { And, Or, NullishCoalescing, }; class LogicalExpression final : public Expression { public: LogicalExpression(SourceRange source_range, LogicalOp op, NonnullRefPtr lhs, NonnullRefPtr rhs) : Expression(source_range) , m_op(op) , m_lhs(move(lhs)) , m_rhs(move(rhs)) { } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; virtual void generate_bytecode(Bytecode::Generator&) const override; private: LogicalOp m_op; NonnullRefPtr m_lhs; NonnullRefPtr m_rhs; }; enum class UnaryOp { BitwiseNot, Not, Plus, Minus, Typeof, Void, Delete, }; class UnaryExpression final : public Expression { public: UnaryExpression(SourceRange source_range, UnaryOp op, NonnullRefPtr lhs) : Expression(source_range) , m_op(op) , m_lhs(move(lhs)) { } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; virtual void generate_bytecode(Bytecode::Generator&) const override; private: UnaryOp m_op; NonnullRefPtr m_lhs; }; class SequenceExpression final : public Expression { public: SequenceExpression(SourceRange source_range, NonnullRefPtrVector expressions) : Expression(source_range) , m_expressions(move(expressions)) { VERIFY(m_expressions.size() >= 2); } virtual void dump(int indent) const override; virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void generate_bytecode(Bytecode::Generator&) const override; private: NonnullRefPtrVector m_expressions; }; class Literal : public Expression { protected: explicit Literal(SourceRange source_range) : Expression(source_range) { } }; class BooleanLiteral final : public Literal { public: explicit BooleanLiteral(SourceRange source_range, bool value) : Literal(source_range) , m_value(value) { } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; virtual void generate_bytecode(Bytecode::Generator&) const override; private: bool m_value { false }; }; class NumericLiteral final : public Literal { public: explicit NumericLiteral(SourceRange source_range, double value) : Literal(source_range) , m_value(value) { } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; virtual void generate_bytecode(Bytecode::Generator&) const override; private: Value m_value; }; class BigIntLiteral final : public Literal { public: explicit BigIntLiteral(SourceRange source_range, String value) : Literal(source_range) , m_value(move(value)) { } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; virtual void generate_bytecode(Bytecode::Generator&) const override; private: String m_value; }; class StringLiteral final : public Literal { public: explicit StringLiteral(SourceRange source_range, String value, bool is_use_strict_directive = false) : Literal(source_range) , m_value(move(value)) , m_is_use_strict_directive(is_use_strict_directive) { } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; virtual void generate_bytecode(Bytecode::Generator&) const override; StringView value() const { return m_value; } bool is_use_strict_directive() const { return m_is_use_strict_directive; }; private: String m_value; bool m_is_use_strict_directive; }; class NullLiteral final : public Literal { public: explicit NullLiteral(SourceRange source_range) : Literal(source_range) { } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; virtual void generate_bytecode(Bytecode::Generator&) const override; }; class RegExpLiteral final : public Literal { public: explicit RegExpLiteral(SourceRange source_range, String pattern, String flags) : Literal(source_range) , m_pattern(move(pattern)) , m_flags(move(flags)) { } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; virtual void generate_bytecode(Bytecode::Generator&) const override; String const& pattern() const { return m_pattern; } String const& flags() const { return m_flags; } private: String m_pattern; String m_flags; }; class Identifier final : public Expression { public: explicit Identifier(SourceRange source_range, FlyString string) : Expression(source_range) , m_string(move(string)) { } FlyString const& string() const { return m_string; } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; virtual Reference to_reference(Interpreter&, GlobalObject&) const override; virtual void generate_bytecode(Bytecode::Generator&) const override; private: virtual bool is_identifier() const override { return true; } FlyString m_string; }; class ClassMethod final : public ASTNode { public: enum class Kind { Method, Getter, Setter, }; ClassMethod(SourceRange source_range, NonnullRefPtr key, NonnullRefPtr function, Kind kind, bool is_static) : ASTNode(source_range) , m_key(move(key)) , m_function(move(function)) , m_kind(kind) , m_is_static(is_static) { } Expression const& key() const { return *m_key; } Kind kind() const { return m_kind; } bool is_static() const { return m_is_static; } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; private: NonnullRefPtr m_key; NonnullRefPtr m_function; Kind m_kind; bool m_is_static; }; class SuperExpression final : public Expression { public: explicit SuperExpression(SourceRange source_range) : Expression(source_range) { } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; virtual bool is_super_expression() const override { return true; } }; class ClassExpression final : public Expression { public: ClassExpression(SourceRange source_range, String name, RefPtr constructor, RefPtr super_class, NonnullRefPtrVector methods) : Expression(source_range) , m_name(move(name)) , m_constructor(move(constructor)) , m_super_class(move(super_class)) , m_methods(move(methods)) { } StringView name() const { return m_name; } RefPtr constructor() const { return m_constructor; } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; private: String m_name; RefPtr m_constructor; RefPtr m_super_class; NonnullRefPtrVector m_methods; }; class ClassDeclaration final : public Declaration { public: ClassDeclaration(SourceRange source_range, NonnullRefPtr class_expression) : Declaration(source_range) , m_class_expression(move(class_expression)) { } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; virtual void generate_bytecode(Bytecode::Generator&) const override; private: NonnullRefPtr m_class_expression; }; class SpreadExpression final : public Expression { public: explicit SpreadExpression(SourceRange source_range, NonnullRefPtr target) : Expression(source_range) , m_target(move(target)) { } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; private: NonnullRefPtr m_target; }; class ThisExpression final : public Expression { public: explicit ThisExpression(SourceRange source_range) : Expression(source_range) { } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; }; class CallExpression : public Expression { public: struct Argument { NonnullRefPtr value; bool is_spread; }; CallExpression(SourceRange source_range, NonnullRefPtr callee, Vector arguments = {}) : Expression(source_range) , m_callee(move(callee)) , m_arguments(move(arguments)) { } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; virtual void generate_bytecode(Bytecode::Generator&) const override; Expression const& callee() const { return m_callee; } protected: void throw_type_error_for_callee(Interpreter&, GlobalObject&, Value callee_value, StringView call_type) const; NonnullRefPtr m_callee; Vector const m_arguments; private: struct ThisAndCallee { Value this_value; Value callee; }; ThisAndCallee compute_this_and_callee(Interpreter&, GlobalObject&) const; }; class NewExpression final : public CallExpression { public: NewExpression(SourceRange source_range, NonnullRefPtr callee, Vector arguments = {}) : CallExpression(source_range, move(callee), move(arguments)) { } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual bool is_new_expression() const override { return true; } }; class SuperCall final : public Expression { public: SuperCall(SourceRange source_range, Vector arguments) : Expression(source_range) , m_arguments(move(arguments)) { } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; private: Vector const m_arguments; }; enum class AssignmentOp { Assignment, AdditionAssignment, SubtractionAssignment, MultiplicationAssignment, DivisionAssignment, ModuloAssignment, ExponentiationAssignment, BitwiseAndAssignment, BitwiseOrAssignment, BitwiseXorAssignment, LeftShiftAssignment, RightShiftAssignment, UnsignedRightShiftAssignment, AndAssignment, OrAssignment, NullishAssignment, }; class AssignmentExpression final : public Expression { public: AssignmentExpression(SourceRange source_range, AssignmentOp op, NonnullRefPtr lhs, NonnullRefPtr rhs) : Expression(source_range) , m_op(op) , m_lhs(move(lhs)) , m_rhs(move(rhs)) { } AssignmentExpression(SourceRange source_range, AssignmentOp op, NonnullRefPtr lhs, NonnullRefPtr rhs) : Expression(source_range) , m_op(op) , m_lhs(move(lhs)) , m_rhs(move(rhs)) { } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; virtual void generate_bytecode(Bytecode::Generator&) const override; private: AssignmentOp m_op; Variant, NonnullRefPtr> m_lhs; NonnullRefPtr m_rhs; }; enum class UpdateOp { Increment, Decrement, }; class UpdateExpression final : public Expression { public: UpdateExpression(SourceRange source_range, UpdateOp op, NonnullRefPtr argument, bool prefixed = false) : Expression(source_range) , m_op(op) , m_argument(move(argument)) , m_prefixed(prefixed) { } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; virtual void generate_bytecode(Bytecode::Generator&) const override; private: UpdateOp m_op; NonnullRefPtr m_argument; bool m_prefixed; }; enum class DeclarationKind { Var, Let, Const, }; class VariableDeclarator final : public ASTNode { public: VariableDeclarator(SourceRange source_range, NonnullRefPtr id) : ASTNode(source_range) , m_target(move(id)) { } VariableDeclarator(SourceRange source_range, NonnullRefPtr target, RefPtr init) : ASTNode(source_range) , m_target(move(target)) , m_init(move(init)) { } VariableDeclarator(SourceRange source_range, Variant, NonnullRefPtr> target, RefPtr init) : ASTNode(source_range) , m_target(move(target)) , m_init(move(init)) { } auto& target() const { return m_target; } Expression const* init() const { return m_init; } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; private: Variant, NonnullRefPtr> m_target; RefPtr m_init; }; class VariableDeclaration final : public Declaration { public: VariableDeclaration(SourceRange source_range, DeclarationKind declaration_kind, NonnullRefPtrVector declarations) : Declaration(source_range) , m_declaration_kind(declaration_kind) , m_declarations(move(declarations)) { } DeclarationKind declaration_kind() const { return m_declaration_kind; } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; virtual void generate_bytecode(Bytecode::Generator&) const override; NonnullRefPtrVector const& declarations() const { return m_declarations; } private: DeclarationKind m_declaration_kind; NonnullRefPtrVector m_declarations; }; class ObjectProperty final : public ASTNode { public: enum class Type { KeyValue, Getter, Setter, Spread, }; ObjectProperty(SourceRange source_range, NonnullRefPtr key, RefPtr value, Type property_type, bool is_method) : ASTNode(source_range) , m_key(move(key)) , m_value(move(value)) , m_property_type(property_type) , m_is_method(is_method) { } Expression const& key() const { return m_key; } Expression const& value() const { VERIFY(m_value); return *m_value; } Type type() const { return m_property_type; } bool is_method() const { return m_is_method; } virtual void dump(int indent) const override; virtual Value execute(Interpreter&, GlobalObject&) const override; private: NonnullRefPtr m_key; RefPtr m_value; Type m_property_type; bool m_is_method { false }; }; class ObjectExpression final : public Expression { public: explicit ObjectExpression(SourceRange source_range, NonnullRefPtrVector properties = {}, Optional first_invalid_property_range = {}) : Expression(source_range) , m_properties(move(properties)) , m_first_invalid_property_range(move(first_invalid_property_range)) { } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; virtual void generate_bytecode(Bytecode::Generator&) const override; Optional const& invalid_property_range() const { return m_first_invalid_property_range; } private: NonnullRefPtrVector m_properties; Optional m_first_invalid_property_range; }; class ArrayExpression final : public Expression { public: ArrayExpression(SourceRange source_range, Vector> elements) : Expression(source_range) , m_elements(move(elements)) { } Vector> const& elements() const { return m_elements; } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; virtual void generate_bytecode(Bytecode::Generator&) const override; private: Vector> m_elements; }; class TemplateLiteral final : public Expression { public: TemplateLiteral(SourceRange source_range, NonnullRefPtrVector expressions) : Expression(source_range) , m_expressions(move(expressions)) { } TemplateLiteral(SourceRange source_range, NonnullRefPtrVector expressions, NonnullRefPtrVector raw_strings) : Expression(source_range) , m_expressions(move(expressions)) , m_raw_strings(move(raw_strings)) { } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; virtual void generate_bytecode(Bytecode::Generator&) const override; NonnullRefPtrVector const& expressions() const { return m_expressions; } NonnullRefPtrVector const& raw_strings() const { return m_raw_strings; } private: NonnullRefPtrVector const m_expressions; NonnullRefPtrVector const m_raw_strings; }; class TaggedTemplateLiteral final : public Expression { public: TaggedTemplateLiteral(SourceRange source_range, NonnullRefPtr tag, NonnullRefPtr template_literal) : Expression(source_range) , m_tag(move(tag)) , m_template_literal(move(template_literal)) { } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; virtual void generate_bytecode(Bytecode::Generator&) const override; private: NonnullRefPtr const m_tag; NonnullRefPtr const m_template_literal; }; class MemberExpression final : public Expression { public: MemberExpression(SourceRange source_range, NonnullRefPtr object, NonnullRefPtr property, bool computed = false) : Expression(source_range) , m_object(move(object)) , m_property(move(property)) , m_computed(computed) { } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; virtual Reference to_reference(Interpreter&, GlobalObject&) const override; virtual void generate_bytecode(Bytecode::Generator&) const override; bool is_computed() const { return m_computed; } Expression const& object() const { return *m_object; } Expression const& property() const { return *m_property; } PropertyName computed_property_name(Interpreter&, GlobalObject&) const; String to_string_approximation() const; private: virtual bool is_member_expression() const override { return true; } NonnullRefPtr m_object; NonnullRefPtr m_property; bool m_computed { false }; }; class MetaProperty final : public Expression { public: enum class Type { NewTarget, ImportMeta, }; MetaProperty(SourceRange source_range, Type type) : Expression(source_range) , m_type(type) { } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; private: Type m_type; }; class ConditionalExpression final : public Expression { public: ConditionalExpression(SourceRange source_range, NonnullRefPtr test, NonnullRefPtr consequent, NonnullRefPtr alternate) : Expression(source_range) , m_test(move(test)) , m_consequent(move(consequent)) , m_alternate(move(alternate)) { } virtual void dump(int indent) const override; virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void generate_bytecode(Bytecode::Generator&) const override; private: NonnullRefPtr m_test; NonnullRefPtr m_consequent; NonnullRefPtr m_alternate; }; class CatchClause final : public ASTNode { public: CatchClause(SourceRange source_range, FlyString parameter, NonnullRefPtr body) : ASTNode(source_range) , m_parameter(move(parameter)) , m_body(move(body)) { } CatchClause(SourceRange source_range, NonnullRefPtr parameter, NonnullRefPtr body) : ASTNode(source_range) , m_parameter(move(parameter)) , m_body(move(body)) { } auto& parameter() const { return m_parameter; } BlockStatement const& body() const { return m_body; } virtual void dump(int indent) const override; virtual Value execute(Interpreter&, GlobalObject&) const override; private: Variant> m_parameter; NonnullRefPtr m_body; }; class TryStatement final : public Statement { public: TryStatement(SourceRange source_range, NonnullRefPtr block, RefPtr handler, RefPtr finalizer) : Statement(source_range) , m_block(move(block)) , m_handler(move(handler)) , m_finalizer(move(finalizer)) { } BlockStatement const& block() const { return m_block; } CatchClause const* handler() const { return m_handler; } BlockStatement const* finalizer() const { return m_finalizer; } virtual void dump(int indent) const override; virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void generate_bytecode(Bytecode::Generator&) const override; private: NonnullRefPtr m_block; RefPtr m_handler; RefPtr m_finalizer; }; class ThrowStatement final : public Statement { public: explicit ThrowStatement(SourceRange source_range, NonnullRefPtr argument) : Statement(source_range) , m_argument(move(argument)) { } Expression const& argument() const { return m_argument; } virtual void dump(int indent) const override; virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void generate_bytecode(Bytecode::Generator&) const override; private: NonnullRefPtr m_argument; }; class SwitchCase final : public ASTNode { public: SwitchCase(SourceRange source_range, RefPtr test, NonnullRefPtrVector consequent) : ASTNode(source_range) , m_test(move(test)) , m_consequent(move(consequent)) { } Expression const* test() const { return m_test; } NonnullRefPtrVector const& consequent() const { return m_consequent; } virtual void dump(int indent) const override; virtual Value execute(Interpreter&, GlobalObject&) const override; private: RefPtr m_test; NonnullRefPtrVector m_consequent; }; class SwitchStatement final : public Statement { public: SwitchStatement(SourceRange source_range, NonnullRefPtr discriminant, NonnullRefPtrVector cases) : Statement(source_range) , m_discriminant(move(discriminant)) , m_cases(move(cases)) { } virtual void dump(int indent) const override; virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void generate_bytecode(Bytecode::Generator&) const override; private: NonnullRefPtr m_discriminant; NonnullRefPtrVector m_cases; }; class BreakStatement final : public Statement { public: BreakStatement(SourceRange source_range, FlyString target_label) : Statement(source_range) , m_target_label(move(target_label)) { } virtual Value execute(Interpreter&, GlobalObject&) const override; FlyString const& target_label() const { return m_target_label; } virtual void generate_bytecode(Bytecode::Generator&) const override; private: FlyString m_target_label; }; class ContinueStatement final : public Statement { public: ContinueStatement(SourceRange source_range, FlyString target_label) : Statement(source_range) , m_target_label(move(target_label)) { } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void generate_bytecode(Bytecode::Generator&) const override; FlyString const& target_label() const { return m_target_label; } private: FlyString m_target_label; }; class DebuggerStatement final : public Statement { public: explicit DebuggerStatement(SourceRange source_range) : Statement(source_range) { } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void generate_bytecode(Bytecode::Generator&) const override; }; template void BindingPattern::for_each_bound_name(C&& callback) const { for (auto& entry : entries) { auto& alias = entry.alias; if (alias.has>()) { callback(alias.get>()->string()); } else if (alias.has>()) { alias.get>()->for_each_bound_name(forward(callback)); } else { auto& name = entry.name; if (name.has>()) callback(name.get>()->string()); } } } template<> inline bool ASTNode::fast_is() const { return is_new_expression(); } template<> inline bool ASTNode::fast_is() const { return is_member_expression(); } template<> inline bool ASTNode::fast_is() const { return is_super_expression(); } template<> inline bool ASTNode::fast_is() const { return is_identifier(); } template<> inline bool ASTNode::fast_is() const { return is_expression_statement(); } template<> inline bool ASTNode::fast_is() const { return is_scope_node(); } template<> inline bool ASTNode::fast_is() const { return is_program(); } }