/* * Copyright (c) 2020, Andreas Kling * Copyright (c) 2020, Linus Groh * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #include #include #include #include #include #include #include #include #include #include namespace JS { class VariableDeclaration; class FunctionDeclaration; template static inline NonnullRefPtr create_ast_node(SourceRange range, Args&&... args) { return adopt(*new T(range, forward(args)...)); } class ASTNode : public RefCounted { public: virtual ~ASTNode() { } virtual Value execute(Interpreter&, GlobalObject&) const = 0; virtual void dump(int indent) const; const SourceRange& source_range() const { return m_source_range; } SourceRange& source_range() { return m_source_range; } String class_name() const; protected: ASTNode(SourceRange source_range) : m_source_range(move(source_range)) { } private: SourceRange m_source_range; }; class Statement : public ASTNode { public: Statement(SourceRange source_range) : ASTNode(move(source_range)) { } const FlyString& label() const { return m_label; } void set_label(FlyString string) { m_label = string; } protected: FlyString m_label; }; class EmptyStatement final : public Statement { public: EmptyStatement(SourceRange source_range) : Statement(move(source_range)) { } Value execute(Interpreter&, GlobalObject&) const override { return js_undefined(); } }; class ErrorStatement final : public Statement { public: ErrorStatement(SourceRange source_range) : Statement(move(source_range)) { } Value execute(Interpreter&, GlobalObject&) const override { return js_undefined(); } }; class ExpressionStatement final : public Statement { public: ExpressionStatement(SourceRange source_range, NonnullRefPtr expression) : Statement(move(source_range)) , m_expression(move(expression)) { } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; const Expression& expression() const { return m_expression; }; private: 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)); } const NonnullRefPtrVector& children() const { return m_children; } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; void add_variables(NonnullRefPtrVector); void add_functions(NonnullRefPtrVector); const NonnullRefPtrVector& variables() const { return m_variables; } const NonnullRefPtrVector& functions() const { return m_functions; } protected: ScopeNode(SourceRange source_range) : Statement(move(source_range)) { } private: NonnullRefPtrVector m_children; NonnullRefPtrVector m_variables; NonnullRefPtrVector m_functions; }; class Program final : public ScopeNode { public: Program(SourceRange source_range) : ScopeNode(move(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: bool m_is_strict_mode { false }; }; class BlockStatement final : public ScopeNode { public: BlockStatement(SourceRange source_range) : ScopeNode(move(source_range)) { } }; class Expression : public ASTNode { public: Expression(SourceRange source_range) : ASTNode(move(source_range)) { } virtual Reference to_reference(Interpreter&, GlobalObject&) const; }; class Declaration : public Statement { public: Declaration(SourceRange source_range) : Statement(move(source_range)) { } }; class ErrorDeclaration final : public Declaration { public: ErrorDeclaration(SourceRange source_range) : Declaration(move(source_range)) { } Value execute(Interpreter&, GlobalObject&) const override { return js_undefined(); } }; class FunctionNode { public: struct Parameter { FlyString name; RefPtr default_value; bool is_rest { false }; }; const FlyString& name() const { return m_name; } const Statement& body() const { return *m_body; } const Vector& parameters() const { return m_parameters; }; i32 function_length() const { return m_function_length; } bool is_strict_mode() const { return m_is_strict_mode; } protected: FunctionNode(const FlyString& name, NonnullRefPtr body, Vector parameters, i32 function_length, NonnullRefPtrVector variables, bool is_strict_mode) : m_name(name) , m_body(move(body)) , m_parameters(move(parameters)) , m_variables(move(variables)) , m_function_length(function_length) , m_is_strict_mode(is_strict_mode) { } void dump(int indent, const String& class_name) const; const NonnullRefPtrVector& variables() const { return m_variables; } private: FlyString m_name; NonnullRefPtr m_body; const Vector m_parameters; NonnullRefPtrVector m_variables; const i32 m_function_length; bool m_is_strict_mode; }; class FunctionDeclaration final : public Declaration , public FunctionNode { public: static bool must_have_name() { return true; } FunctionDeclaration(SourceRange source_range, const FlyString& name, NonnullRefPtr body, Vector parameters, i32 function_length, NonnullRefPtrVector variables, bool is_strict_mode = false) : Declaration(move(source_range)) , FunctionNode(name, move(body), move(parameters), function_length, move(variables), is_strict_mode) { } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; }; class FunctionExpression final : public Expression , public FunctionNode { public: static bool must_have_name() { return false; } FunctionExpression(SourceRange source_range, const FlyString& name, NonnullRefPtr body, Vector parameters, i32 function_length, NonnullRefPtrVector variables, bool is_strict_mode, bool is_arrow_function = false) : Expression(move(source_range)) , FunctionNode(name, move(body), move(parameters), function_length, move(variables), is_strict_mode) , m_is_arrow_function(is_arrow_function) { } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; private: bool m_is_arrow_function; }; class ErrorExpression final : public Expression { public: explicit ErrorExpression(SourceRange source_range) : Expression(move(source_range)) { } Value execute(Interpreter&, GlobalObject&) const override { return js_undefined(); } }; class ReturnStatement final : public Statement { public: explicit ReturnStatement(SourceRange source_range, RefPtr argument) : Statement(move(source_range)) , m_argument(move(argument)) { } const Expression* argument() const { return m_argument; } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; private: RefPtr m_argument; }; class IfStatement final : public Statement { public: IfStatement(SourceRange source_range, NonnullRefPtr predicate, NonnullRefPtr consequent, RefPtr alternate) : Statement(move(source_range)) , m_predicate(move(predicate)) , m_consequent(move(consequent)) , m_alternate(move(alternate)) { } const Expression& predicate() const { return *m_predicate; } const Statement& consequent() const { return *m_consequent; } const Statement* alternate() const { return m_alternate; } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) 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(move(source_range)) , m_test(move(test)) , m_body(move(body)) { } const Expression& test() const { return *m_test; } const Statement& body() const { return *m_body; } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; private: NonnullRefPtr m_test; NonnullRefPtr m_body; }; class DoWhileStatement final : public Statement { public: DoWhileStatement(SourceRange source_range, NonnullRefPtr test, NonnullRefPtr body) : Statement(move(source_range)) , m_test(move(test)) , m_body(move(body)) { } const Expression& test() const { return *m_test; } const Statement& body() const { return *m_body; } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; private: NonnullRefPtr m_test; NonnullRefPtr m_body; }; class WithStatement final : public Statement { public: WithStatement(SourceRange source_range, NonnullRefPtr object, NonnullRefPtr body) : Statement(move(source_range)) , m_object(move(object)) , m_body(move(body)) { } const Expression& object() const { return *m_object; } const Statement& 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(move(source_range)) , m_init(move(init)) , m_test(move(test)) , m_update(move(update)) , m_body(move(body)) { } const ASTNode* init() const { return m_init; } const Expression* test() const { return m_test; } const Expression* update() const { return m_update; } const Statement& body() const { return *m_body; } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) 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(move(source_range)) , m_lhs(move(lhs)) , m_rhs(move(rhs)) , m_body(move(body)) { } const ASTNode& lhs() const { return *m_lhs; } const Expression& rhs() const { return *m_rhs; } const Statement& 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(move(source_range)) , m_lhs(move(lhs)) , m_rhs(move(rhs)) , m_body(move(body)) { } const ASTNode& lhs() const { return *m_lhs; } const Expression& rhs() const { return *m_rhs; } const Statement& 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(move(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; 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(move(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; 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(move(source_range)) , m_op(op) , m_lhs(move(lhs)) { } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; private: UnaryOp m_op; NonnullRefPtr m_lhs; }; class SequenceExpression final : public Expression { public: SequenceExpression(SourceRange source_range, NonnullRefPtrVector expressions) : Expression(move(source_range)) , m_expressions(move(expressions)) { } virtual void dump(int indent) const override; virtual Value execute(Interpreter&, GlobalObject&) const override; private: NonnullRefPtrVector m_expressions; }; class Literal : public Expression { protected: explicit Literal(SourceRange source_range) : Expression(move(source_range)) { } }; class BooleanLiteral final : public Literal { public: explicit BooleanLiteral(SourceRange source_range, bool value) : Literal(move(source_range)) , m_value(value) { } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; private: bool m_value { false }; }; class NumericLiteral final : public Literal { public: explicit NumericLiteral(SourceRange source_range, double value) : Literal(move(source_range)) , m_value(value) { } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; private: double m_value { 0 }; }; class BigIntLiteral final : public Literal { public: explicit BigIntLiteral(SourceRange source_range, String value) : Literal(move(source_range)) , m_value(move(value)) { } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) 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(move(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; 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(move(source_range)) { } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; }; class RegExpLiteral final : public Literal { public: explicit RegExpLiteral(SourceRange source_range, String content, String flags) : Literal(move(source_range)) , m_content(content) , m_flags(flags) { } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; const String& content() const { return m_content; } const String& flags() const { return m_flags; } private: String m_content; String m_flags; }; class Identifier final : public Expression { public: explicit Identifier(SourceRange source_range, const FlyString& string) : Expression(move(source_range)) , m_string(string) { } const FlyString& 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; private: 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(move(source_range)) , m_key(move(key)) , m_function(move(function)) , m_kind(kind) , m_is_static(is_static) { } const Expression& 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: SuperExpression(SourceRange source_range) : Expression(move(source_range)) { } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; }; class ClassExpression final : public Expression { public: ClassExpression(SourceRange source_range, String name, RefPtr constructor, RefPtr super_class, NonnullRefPtrVector methods) : Expression(move(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; } 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(move(source_range)) , m_class_expression(move(class_expression)) { } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; private: NonnullRefPtr m_class_expression; }; class SpreadExpression final : public Expression { public: explicit SpreadExpression(SourceRange source_range, NonnullRefPtr target) : Expression(move(source_range)) , m_target(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: ThisExpression(SourceRange source_range) : Expression(move(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(move(source_range)) , m_callee(move(callee)) , m_arguments(move(arguments)) { } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; private: struct ThisAndCallee { Value this_value; Value callee; }; ThisAndCallee compute_this_and_callee(Interpreter&, GlobalObject&) const; NonnullRefPtr m_callee; const Vector m_arguments; }; class NewExpression final : public CallExpression { public: NewExpression(SourceRange source_range, NonnullRefPtr callee, Vector arguments = {}) : CallExpression(move(source_range), move(callee), move(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(move(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; private: AssignmentOp m_op; 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(move(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; 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(move(source_range)) , m_id(move(id)) { } VariableDeclarator(SourceRange source_range, NonnullRefPtr id, RefPtr init) : ASTNode(move(source_range)) , m_id(move(id)) , m_init(move(init)) { } const Identifier& id() const { return m_id; } const Expression* init() const { return m_init; } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; private: NonnullRefPtr m_id; RefPtr m_init; }; class VariableDeclaration final : public Declaration { public: VariableDeclaration(SourceRange source_range, DeclarationKind declaration_kind, NonnullRefPtrVector declarations) : Declaration(move(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; const NonnullRefPtrVector& 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(move(source_range)) , m_key(move(key)) , m_value(move(value)) , m_property_type(property_type) , m_is_method(is_method) { } const Expression& key() const { return m_key; } const Expression& value() const { ASSERT(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: ObjectExpression(SourceRange source_range, NonnullRefPtrVector properties = {}) : Expression(move(source_range)) , m_properties(move(properties)) { } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; private: NonnullRefPtrVector m_properties; }; class ArrayExpression final : public Expression { public: ArrayExpression(SourceRange source_range, Vector> elements) : Expression(move(source_range)) , m_elements(move(elements)) { } const Vector>& elements() const { return m_elements; } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; private: Vector> m_elements; }; class TemplateLiteral final : public Expression { public: TemplateLiteral(SourceRange source_range, NonnullRefPtrVector expressions) : Expression(move(source_range)) , m_expressions(move(expressions)) { } TemplateLiteral(SourceRange source_range, NonnullRefPtrVector expressions, NonnullRefPtrVector raw_strings) : Expression(move(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; const NonnullRefPtrVector& expressions() const { return m_expressions; } const NonnullRefPtrVector& raw_strings() const { return m_raw_strings; } private: const NonnullRefPtrVector m_expressions; const NonnullRefPtrVector m_raw_strings; }; class TaggedTemplateLiteral final : public Expression { public: TaggedTemplateLiteral(SourceRange source_range, NonnullRefPtr tag, NonnullRefPtr template_literal) : Expression(move(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; private: const NonnullRefPtr m_tag; const NonnullRefPtr m_template_literal; }; class MemberExpression final : public Expression { public: MemberExpression(SourceRange source_range, NonnullRefPtr object, NonnullRefPtr property, bool computed = false) : Expression(move(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; bool is_computed() const { return m_computed; } const Expression& object() const { return *m_object; } const Expression& property() const { return *m_property; } PropertyName computed_property_name(Interpreter&, GlobalObject&) const; String to_string_approximation() const; private: 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(move(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(move(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; private: NonnullRefPtr m_test; NonnullRefPtr m_consequent; NonnullRefPtr m_alternate; }; class CatchClause final : public ASTNode { public: CatchClause(SourceRange source_range, const FlyString& parameter, NonnullRefPtr body) : ASTNode(move(source_range)) , m_parameter(parameter) , m_body(move(body)) { } const FlyString& parameter() const { return m_parameter; } const BlockStatement& body() const { return m_body; } virtual void dump(int indent) const override; virtual Value execute(Interpreter&, GlobalObject&) const override; private: FlyString m_parameter; NonnullRefPtr m_body; }; class TryStatement final : public Statement { public: TryStatement(SourceRange source_range, NonnullRefPtr block, RefPtr handler, RefPtr finalizer) : Statement(move(source_range)) , m_block(move(block)) , m_handler(move(handler)) , m_finalizer(move(finalizer)) { } const BlockStatement& block() const { return m_block; } const CatchClause* handler() const { return m_handler; } const BlockStatement* finalizer() const { return m_finalizer; } virtual void dump(int indent) const override; virtual Value execute(Interpreter&, GlobalObject&) 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(move(source_range)) , m_argument(move(argument)) { } const Expression& argument() const { return m_argument; } virtual void dump(int indent) const override; virtual Value execute(Interpreter&, GlobalObject&) const override; private: NonnullRefPtr m_argument; }; class SwitchCase final : public ASTNode { public: SwitchCase(SourceRange source_range, RefPtr test, NonnullRefPtrVector consequent) : ASTNode(move(source_range)) , m_test(move(test)) , m_consequent(move(consequent)) { } const Expression* test() const { return m_test; } const NonnullRefPtrVector& 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(move(source_range)) , m_discriminant(move(discriminant)) , m_cases(move(cases)) { } virtual void dump(int indent) const override; virtual Value execute(Interpreter&, GlobalObject&) const override; private: NonnullRefPtr m_discriminant; NonnullRefPtrVector m_cases; }; class BreakStatement final : public Statement { public: BreakStatement(SourceRange source_range, FlyString target_label) : Statement(move(source_range)) , m_target_label(target_label) { } virtual Value execute(Interpreter&, GlobalObject&) const override; const FlyString& target_label() const { return m_target_label; } private: FlyString m_target_label; }; class ContinueStatement final : public Statement { public: ContinueStatement(SourceRange source_range, FlyString target_label) : Statement(move(source_range)) , m_target_label(target_label) { } virtual Value execute(Interpreter&, GlobalObject&) const override; const FlyString& target_label() const { return m_target_label; } private: FlyString m_target_label; }; class DebuggerStatement final : public Statement { public: DebuggerStatement(SourceRange source_range) : Statement(move(source_range)) { } virtual Value execute(Interpreter&, GlobalObject&) const override; }; }