1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 07:58:11 +00:00

LibJS: Make the AST reference-counted

This allows function objects to outlive the original parsed program
without their ScopeNode disappearing.
This commit is contained in:
Andreas Kling 2020-03-18 11:23:53 +01:00
parent d98fbd192e
commit ddd69e3660
8 changed files with 138 additions and 130 deletions

View file

@ -100,10 +100,10 @@ Value WhileStatement::execute(Interpreter& interpreter) const
Value ForStatement::execute(Interpreter& interpreter) const Value ForStatement::execute(Interpreter& interpreter) const
{ {
OwnPtr<BlockStatement> wrapper; RefPtr<BlockStatement> wrapper;
if (m_init->is_variable_declaration() && static_cast<const VariableDeclaration*>(m_init.ptr())->declaration_type() != DeclarationType::Var) { if (m_init->is_variable_declaration() && static_cast<const VariableDeclaration*>(m_init.ptr())->declaration_type() != DeclarationType::Var) {
wrapper = make<BlockStatement>(); wrapper = create_ast_node<BlockStatement>();
interpreter.enter_scope(*wrapper, {}, ScopeType::Block); interpreter.enter_scope(*wrapper, {}, ScopeType::Block);
} }

View file

@ -26,8 +26,8 @@
#pragma once #pragma once
#include <AK/NonnullOwnPtrVector.h> #include <AK/NonnullRefPtrVector.h>
#include <AK/OwnPtr.h> #include <AK/RefPtr.h>
#include <AK/String.h> #include <AK/String.h>
#include <AK/Vector.h> #include <AK/Vector.h>
#include <LibJS/Forward.h> #include <LibJS/Forward.h>
@ -35,7 +35,14 @@
namespace JS { namespace JS {
class ASTNode { template<class T, class... Args>
static inline NonnullRefPtr<T>
create_ast_node(Args&&... args)
{
return adopt(*new T(forward<Args>(args)...));
}
class ASTNode : public RefCounted<ASTNode> {
public: public:
virtual ~ASTNode() {} virtual ~ASTNode() {}
virtual const char* class_name() const = 0; virtual const char* class_name() const = 0;
@ -62,7 +69,7 @@ public:
class ExpressionStatement final : public Statement { class ExpressionStatement final : public Statement {
public: public:
ExpressionStatement(NonnullOwnPtr<Expression> expression) ExpressionStatement(NonnullRefPtr<Expression> expression)
: m_expression(move(expression)) : m_expression(move(expression))
{ {
} }
@ -72,7 +79,7 @@ public:
virtual void dump(int indent) const override; virtual void dump(int indent) const override;
private: private:
NonnullOwnPtr<Expression> m_expression; NonnullRefPtr<Expression> m_expression;
}; };
class ScopeNode : public Statement { class ScopeNode : public Statement {
@ -84,12 +91,12 @@ public:
m_children.append(move(child)); m_children.append(move(child));
return static_cast<T&>(m_children.last()); return static_cast<T&>(m_children.last());
} }
void append(NonnullOwnPtr<Statement> child) void append(NonnullRefPtr<Statement> child)
{ {
m_children.append(move(child)); m_children.append(move(child));
} }
const NonnullOwnPtrVector<Statement>& children() const { return m_children; } const NonnullRefPtrVector<Statement>& children() const { return m_children; }
virtual Value execute(Interpreter&) const override; virtual Value execute(Interpreter&) const override;
virtual void dump(int indent) const override; virtual void dump(int indent) const override;
@ -97,7 +104,7 @@ protected:
ScopeNode() {} ScopeNode() {}
private: private:
NonnullOwnPtrVector<Statement> m_children; NonnullRefPtrVector<Statement> m_children;
}; };
class Program : public ScopeNode { class Program : public ScopeNode {
@ -118,7 +125,7 @@ private:
class FunctionDeclaration : public Statement { class FunctionDeclaration : public Statement {
public: public:
FunctionDeclaration(String name, NonnullOwnPtr<ScopeNode> body, Vector<String> parameters = {}) FunctionDeclaration(String name, NonnullRefPtr<ScopeNode> body, Vector<String> parameters = {})
: m_name(move(name)) : m_name(move(name))
, m_body(move(body)) , m_body(move(body))
, m_parameters(move(parameters)) , m_parameters(move(parameters))
@ -136,7 +143,7 @@ private:
virtual const char* class_name() const override { return "FunctionDeclaration"; } virtual const char* class_name() const override { return "FunctionDeclaration"; }
String m_name; String m_name;
NonnullOwnPtr<ScopeNode> m_body; NonnullRefPtr<ScopeNode> m_body;
const Vector<String> m_parameters; const Vector<String> m_parameters;
}; };
@ -153,7 +160,7 @@ public:
class ReturnStatement : public Statement { class ReturnStatement : public Statement {
public: public:
explicit ReturnStatement(OwnPtr<Expression> argument) explicit ReturnStatement(RefPtr<Expression> argument)
: m_argument(move(argument)) : m_argument(move(argument))
{ {
} }
@ -166,12 +173,12 @@ public:
private: private:
virtual const char* class_name() const override { return "ReturnStatement"; } virtual const char* class_name() const override { return "ReturnStatement"; }
OwnPtr<Expression> m_argument; RefPtr<Expression> m_argument;
}; };
class IfStatement : public Statement { class IfStatement : public Statement {
public: public:
IfStatement(NonnullOwnPtr<Expression> predicate, NonnullOwnPtr<ScopeNode> consequent, NonnullOwnPtr<ScopeNode> alternate) IfStatement(NonnullRefPtr<Expression> predicate, NonnullRefPtr<ScopeNode> consequent, NonnullRefPtr<ScopeNode> alternate)
: m_predicate(move(predicate)) : m_predicate(move(predicate))
, m_consequent(move(consequent)) , m_consequent(move(consequent))
, m_alternate(move(alternate)) , m_alternate(move(alternate))
@ -188,14 +195,14 @@ public:
private: private:
virtual const char* class_name() const override { return "IfStatement"; } virtual const char* class_name() const override { return "IfStatement"; }
NonnullOwnPtr<Expression> m_predicate; NonnullRefPtr<Expression> m_predicate;
NonnullOwnPtr<ScopeNode> m_consequent; NonnullRefPtr<ScopeNode> m_consequent;
NonnullOwnPtr<ScopeNode> m_alternate; NonnullRefPtr<ScopeNode> m_alternate;
}; };
class WhileStatement : public Statement { class WhileStatement : public Statement {
public: public:
WhileStatement(NonnullOwnPtr<Expression> predicate, NonnullOwnPtr<ScopeNode> body) WhileStatement(NonnullRefPtr<Expression> predicate, NonnullRefPtr<ScopeNode> body)
: m_predicate(move(predicate)) : m_predicate(move(predicate))
, m_body(move(body)) , m_body(move(body))
{ {
@ -210,13 +217,13 @@ public:
private: private:
virtual const char* class_name() const override { return "WhileStatement"; } virtual const char* class_name() const override { return "WhileStatement"; }
NonnullOwnPtr<Expression> m_predicate; NonnullRefPtr<Expression> m_predicate;
NonnullOwnPtr<ScopeNode> m_body; NonnullRefPtr<ScopeNode> m_body;
}; };
class ForStatement : public Statement { class ForStatement : public Statement {
public: public:
ForStatement(OwnPtr<Statement> init, OwnPtr<Expression> test, OwnPtr<Expression> update, NonnullOwnPtr<ScopeNode> body) ForStatement(RefPtr<Statement> init, RefPtr<Expression> test, RefPtr<Expression> update, NonnullRefPtr<ScopeNode> body)
: m_init(move(init)) : m_init(move(init))
, m_test(move(test)) , m_test(move(test))
, m_update(move(update)) , m_update(move(update))
@ -235,10 +242,10 @@ public:
private: private:
virtual const char* class_name() const override { return "ForStatement"; } virtual const char* class_name() const override { return "ForStatement"; }
OwnPtr<Statement> m_init; RefPtr<Statement> m_init;
OwnPtr<Expression> m_test; RefPtr<Expression> m_test;
OwnPtr<Expression> m_update; RefPtr<Expression> m_update;
NonnullOwnPtr<ScopeNode> m_body; NonnullRefPtr<ScopeNode> m_body;
}; };
enum class BinaryOp { enum class BinaryOp {
@ -263,7 +270,7 @@ enum class BinaryOp {
class BinaryExpression : public Expression { class BinaryExpression : public Expression {
public: public:
BinaryExpression(BinaryOp op, NonnullOwnPtr<Expression> lhs, NonnullOwnPtr<Expression> rhs) BinaryExpression(BinaryOp op, NonnullRefPtr<Expression> lhs, NonnullRefPtr<Expression> rhs)
: m_op(op) : m_op(op)
, m_lhs(move(lhs)) , m_lhs(move(lhs))
, m_rhs(move(rhs)) , m_rhs(move(rhs))
@ -277,8 +284,8 @@ private:
virtual const char* class_name() const override { return "BinaryExpression"; } virtual const char* class_name() const override { return "BinaryExpression"; }
BinaryOp m_op; BinaryOp m_op;
NonnullOwnPtr<Expression> m_lhs; NonnullRefPtr<Expression> m_lhs;
NonnullOwnPtr<Expression> m_rhs; NonnullRefPtr<Expression> m_rhs;
}; };
enum class LogicalOp { enum class LogicalOp {
@ -288,7 +295,7 @@ enum class LogicalOp {
class LogicalExpression : public Expression { class LogicalExpression : public Expression {
public: public:
LogicalExpression(LogicalOp op, NonnullOwnPtr<Expression> lhs, NonnullOwnPtr<Expression> rhs) LogicalExpression(LogicalOp op, NonnullRefPtr<Expression> lhs, NonnullRefPtr<Expression> rhs)
: m_op(op) : m_op(op)
, m_lhs(move(lhs)) , m_lhs(move(lhs))
, m_rhs(move(rhs)) , m_rhs(move(rhs))
@ -302,8 +309,8 @@ private:
virtual const char* class_name() const override { return "LogicalExpression"; } virtual const char* class_name() const override { return "LogicalExpression"; }
LogicalOp m_op; LogicalOp m_op;
NonnullOwnPtr<Expression> m_lhs; NonnullRefPtr<Expression> m_lhs;
NonnullOwnPtr<Expression> m_rhs; NonnullRefPtr<Expression> m_rhs;
}; };
enum class UnaryOp { enum class UnaryOp {
@ -314,7 +321,7 @@ enum class UnaryOp {
class UnaryExpression : public Expression { class UnaryExpression : public Expression {
public: public:
UnaryExpression(UnaryOp op, NonnullOwnPtr<Expression> lhs) UnaryExpression(UnaryOp op, NonnullRefPtr<Expression> lhs)
: m_op(op) : m_op(op)
, m_lhs(move(lhs)) , m_lhs(move(lhs))
{ {
@ -327,7 +334,7 @@ private:
virtual const char* class_name() const override { return "UnaryExpression"; } virtual const char* class_name() const override { return "UnaryExpression"; }
UnaryOp m_op; UnaryOp m_op;
NonnullOwnPtr<Expression> m_lhs; NonnullRefPtr<Expression> m_lhs;
}; };
class Literal : public Expression { class Literal : public Expression {
@ -432,7 +439,7 @@ private:
class CallExpression : public Expression { class CallExpression : public Expression {
public: public:
explicit CallExpression(NonnullOwnPtr<Expression> callee, NonnullOwnPtrVector<Expression> arguments = {}) explicit CallExpression(NonnullRefPtr<Expression> callee, NonnullRefPtrVector<Expression> arguments = {})
: m_callee(move(callee)) : m_callee(move(callee))
, m_arguments(move(arguments)) , m_arguments(move(arguments))
{ {
@ -444,8 +451,8 @@ public:
private: private:
virtual const char* class_name() const override { return "CallExpression"; } virtual const char* class_name() const override { return "CallExpression"; }
NonnullOwnPtr<Expression> m_callee; NonnullRefPtr<Expression> m_callee;
const NonnullOwnPtrVector<Expression> m_arguments; const NonnullRefPtrVector<Expression> m_arguments;
}; };
enum class AssignmentOp { enum class AssignmentOp {
@ -458,7 +465,7 @@ enum class AssignmentOp {
class AssignmentExpression : public Expression { class AssignmentExpression : public Expression {
public: public:
AssignmentExpression(AssignmentOp op, NonnullOwnPtr<ASTNode> lhs, NonnullOwnPtr<Expression> rhs) AssignmentExpression(AssignmentOp op, NonnullRefPtr<ASTNode> lhs, NonnullRefPtr<Expression> rhs)
: m_op(op) : m_op(op)
, m_lhs(move(lhs)) , m_lhs(move(lhs))
, m_rhs(move(rhs)) , m_rhs(move(rhs))
@ -472,8 +479,8 @@ private:
virtual const char* class_name() const override { return "AssignmentExpression"; } virtual const char* class_name() const override { return "AssignmentExpression"; }
AssignmentOp m_op; AssignmentOp m_op;
NonnullOwnPtr<ASTNode> m_lhs; NonnullRefPtr<ASTNode> m_lhs;
NonnullOwnPtr<Expression> m_rhs; NonnullRefPtr<Expression> m_rhs;
}; };
enum class UpdateOp { enum class UpdateOp {
@ -483,7 +490,7 @@ enum class UpdateOp {
class UpdateExpression : public Expression { class UpdateExpression : public Expression {
public: public:
UpdateExpression(UpdateOp op, NonnullOwnPtr<Expression> argument, bool prefixed = false) UpdateExpression(UpdateOp op, NonnullRefPtr<Expression> argument, bool prefixed = false)
: m_op(op) : m_op(op)
, m_argument(move(argument)) , m_argument(move(argument))
, m_prefixed(prefixed) , m_prefixed(prefixed)
@ -497,7 +504,7 @@ private:
virtual const char* class_name() const override { return "UpdateExpression"; } virtual const char* class_name() const override { return "UpdateExpression"; }
UpdateOp m_op; UpdateOp m_op;
NonnullOwnPtr<Identifier> m_argument; NonnullRefPtr<Identifier> m_argument;
bool m_prefixed; bool m_prefixed;
}; };
@ -509,7 +516,7 @@ enum class DeclarationType {
class VariableDeclaration : public Statement { class VariableDeclaration : public Statement {
public: public:
VariableDeclaration(NonnullOwnPtr<Identifier> name, OwnPtr<Expression> initializer, DeclarationType declaration_type) VariableDeclaration(NonnullRefPtr<Identifier> name, RefPtr<Expression> initializer, DeclarationType declaration_type)
: m_declaration_type(declaration_type) : m_declaration_type(declaration_type)
, m_name(move(name)) , m_name(move(name))
, m_initializer(move(initializer)) , m_initializer(move(initializer))
@ -527,8 +534,8 @@ private:
virtual const char* class_name() const override { return "VariableDeclaration"; } virtual const char* class_name() const override { return "VariableDeclaration"; }
DeclarationType m_declaration_type; DeclarationType m_declaration_type;
NonnullOwnPtr<Identifier> m_name; NonnullRefPtr<Identifier> m_name;
OwnPtr<Expression> m_initializer; RefPtr<Expression> m_initializer;
}; };
class ObjectExpression : public Expression { class ObjectExpression : public Expression {
@ -544,7 +551,7 @@ private:
class MemberExpression final : public Expression { class MemberExpression final : public Expression {
public: public:
MemberExpression(NonnullOwnPtr<Expression> object, NonnullOwnPtr<Expression> property) MemberExpression(NonnullRefPtr<Expression> object, NonnullRefPtr<Expression> property)
: m_object(move(object)) : m_object(move(object))
, m_property(move(property)) , m_property(move(property))
{ {
@ -559,8 +566,8 @@ private:
virtual bool is_member_expression() const override { return true; } virtual bool is_member_expression() const override { return true; }
virtual const char* class_name() const override { return "MemberExpression"; } virtual const char* class_name() const override { return "MemberExpression"; }
NonnullOwnPtr<Expression> m_object; NonnullRefPtr<Expression> m_object;
NonnullOwnPtr<Expression> m_property; NonnullRefPtr<Expression> m_property;
}; };
} }

View file

@ -72,7 +72,7 @@ void Interpreter::enter_scope(const ScopeNode& scope_node, Vector<Argument> argu
void Interpreter::exit_scope(const ScopeNode& scope_node) void Interpreter::exit_scope(const ScopeNode& scope_node)
{ {
while (&m_scope_stack.last().scope_node != &scope_node) while (m_scope_stack.last().scope_node.ptr() != &scope_node)
m_scope_stack.take_last(); m_scope_stack.take_last();
} }

View file

@ -47,7 +47,7 @@ struct Variable {
struct ScopeFrame { struct ScopeFrame {
ScopeType type; ScopeType type;
const ScopeNode& scope_node; NonnullRefPtr<ScopeNode> scope_node;
HashMap<String, Variable> variables; HashMap<String, Variable> variables;
}; };

View file

@ -163,9 +163,9 @@ Associativity Parser::operator_associativity(TokenType type) const
} }
} }
NonnullOwnPtr<Program> Parser::parse_program() NonnullRefPtr<Program> Parser::parse_program()
{ {
auto program = make<Program>(); auto program = adopt(*new Program);
while (!done()) { while (!done()) {
if (match(TokenType::Semicolon)) { if (match(TokenType::Semicolon)) {
consume(); consume();
@ -179,10 +179,10 @@ NonnullOwnPtr<Program> Parser::parse_program()
return program; return program;
} }
NonnullOwnPtr<Statement> Parser::parse_statement() NonnullRefPtr<Statement> Parser::parse_statement()
{ {
if (match_expression()) { if (match_expression()) {
return make<JS::ExpressionStatement>(parse_expression(0)); return adopt(*new ExpressionStatement(parse_expression(0)));
} }
switch (m_current_token.type()) { switch (m_current_token.type()) {
@ -202,11 +202,11 @@ NonnullOwnPtr<Statement> Parser::parse_statement()
m_has_errors = true; m_has_errors = true;
expected("statement (missing switch case)"); expected("statement (missing switch case)");
consume(); consume();
return make<ErrorStatement>(); return create_ast_node<ErrorStatement>();
} }
} }
NonnullOwnPtr<Expression> Parser::parse_primary_expression() NonnullRefPtr<Expression> Parser::parse_primary_expression()
{ {
switch (m_current_token.type()) { switch (m_current_token.type()) {
case TokenType::ParenOpen: { case TokenType::ParenOpen: {
@ -216,64 +216,64 @@ NonnullOwnPtr<Expression> Parser::parse_primary_expression()
return expression; return expression;
} }
case TokenType::Identifier: case TokenType::Identifier:
return make<Identifier>(consume().value()); return create_ast_node<Identifier>(consume().value());
case TokenType::NumericLiteral: case TokenType::NumericLiteral:
return make<NumericLiteral>(consume().double_value()); return create_ast_node<NumericLiteral>(consume().double_value());
case TokenType::BoolLiteral: case TokenType::BoolLiteral:
return make<BooleanLiteral>(consume().bool_value()); return create_ast_node<BooleanLiteral>(consume().bool_value());
case TokenType::StringLiteral: case TokenType::StringLiteral:
return make<StringLiteral>(consume().string_value()); return create_ast_node<StringLiteral>(consume().string_value());
case TokenType::NullLiteral: case TokenType::NullLiteral:
consume(); consume();
return make<NullLiteral>(); return create_ast_node<NullLiteral>();
case TokenType::UndefinedLiteral: case TokenType::UndefinedLiteral:
consume(); consume();
return make<UndefinedLiteral>(); return create_ast_node<UndefinedLiteral>();
case TokenType::CurlyOpen: case TokenType::CurlyOpen:
return parse_object_expression(); return parse_object_expression();
default: default:
m_has_errors = true; m_has_errors = true;
expected("primary expression (missing switch case)"); expected("primary expression (missing switch case)");
consume(); consume();
return make<ErrorExpression>(); return create_ast_node<ErrorExpression>();
} }
} }
NonnullOwnPtr<Expression> Parser::parse_unary_prefixed_expression() NonnullRefPtr<Expression> Parser::parse_unary_prefixed_expression()
{ {
switch (m_current_token.type()) { switch (m_current_token.type()) {
case TokenType::PlusPlus: case TokenType::PlusPlus:
consume(); consume();
return make<UpdateExpression>(UpdateOp::Increment, parse_primary_expression(), true); return create_ast_node<UpdateExpression>(UpdateOp::Increment, parse_primary_expression(), true);
case TokenType::MinusMinus: case TokenType::MinusMinus:
consume(); consume();
return make<UpdateExpression>(UpdateOp::Decrement, parse_primary_expression(), true); return create_ast_node<UpdateExpression>(UpdateOp::Decrement, parse_primary_expression(), true);
case TokenType::ExclamationMark: case TokenType::ExclamationMark:
consume(); consume();
return make<UnaryExpression>(UnaryOp::Not, parse_primary_expression()); return create_ast_node<UnaryExpression>(UnaryOp::Not, parse_primary_expression());
case TokenType::Tilde: case TokenType::Tilde:
consume(); consume();
return make<UnaryExpression>(UnaryOp::BitwiseNot, parse_primary_expression()); return create_ast_node<UnaryExpression>(UnaryOp::BitwiseNot, parse_primary_expression());
case TokenType::Typeof: case TokenType::Typeof:
consume(); consume();
return make<UnaryExpression>(UnaryOp::Typeof, parse_primary_expression()); return create_ast_node<UnaryExpression>(UnaryOp::Typeof, parse_primary_expression());
default: default:
m_has_errors = true; m_has_errors = true;
expected("primary expression (missing switch case)"); expected("primary expression (missing switch case)");
consume(); consume();
return make<ErrorExpression>(); return create_ast_node<ErrorExpression>();
} }
} }
NonnullOwnPtr<ObjectExpression> Parser::parse_object_expression() NonnullRefPtr<ObjectExpression> Parser::parse_object_expression()
{ {
// FIXME: Parse actual object expression // FIXME: Parse actual object expression
consume(TokenType::CurlyOpen); consume(TokenType::CurlyOpen);
consume(TokenType::CurlyClose); consume(TokenType::CurlyClose);
return make<ObjectExpression>(); return create_ast_node<ObjectExpression>();
} }
NonnullOwnPtr<Expression> Parser::parse_expression(int min_precedence, Associativity associativity) NonnullRefPtr<Expression> Parser::parse_expression(int min_precedence, Associativity associativity)
{ {
if (match_unary_prefixed_expression()) if (match_unary_prefixed_expression())
return parse_unary_prefixed_expression(); return parse_unary_prefixed_expression();
@ -292,90 +292,90 @@ NonnullOwnPtr<Expression> Parser::parse_expression(int min_precedence, Associati
return expression; return expression;
} }
NonnullOwnPtr<Expression> Parser::parse_secondary_expression(NonnullOwnPtr<Expression> lhs, int min_precedence, Associativity associativity) NonnullRefPtr<Expression> Parser::parse_secondary_expression(NonnullRefPtr<Expression> lhs, int min_precedence, Associativity associativity)
{ {
switch (m_current_token.type()) { switch (m_current_token.type()) {
case TokenType::Plus: case TokenType::Plus:
consume(); consume();
return make<BinaryExpression>(BinaryOp::Plus, move(lhs), parse_expression(min_precedence, associativity)); return create_ast_node<BinaryExpression>(BinaryOp::Plus, move(lhs), parse_expression(min_precedence, associativity));
case TokenType::PlusEquals: case TokenType::PlusEquals:
consume(); consume();
return make<AssignmentExpression>(AssignmentOp::AdditionAssignment, move(lhs), parse_expression(min_precedence, associativity)); return create_ast_node<AssignmentExpression>(AssignmentOp::AdditionAssignment, move(lhs), parse_expression(min_precedence, associativity));
case TokenType::Minus: case TokenType::Minus:
consume(); consume();
return make<BinaryExpression>(BinaryOp::Minus, move(lhs), parse_expression(min_precedence, associativity)); return create_ast_node<BinaryExpression>(BinaryOp::Minus, move(lhs), parse_expression(min_precedence, associativity));
case TokenType::MinusEquals: case TokenType::MinusEquals:
consume(); consume();
return make<AssignmentExpression>(AssignmentOp::SubtractionAssignment, move(lhs), parse_expression(min_precedence, associativity)); return create_ast_node<AssignmentExpression>(AssignmentOp::SubtractionAssignment, move(lhs), parse_expression(min_precedence, associativity));
case TokenType::Asterisk: case TokenType::Asterisk:
consume(); consume();
return make<BinaryExpression>(BinaryOp::Asterisk, move(lhs), parse_expression(min_precedence, associativity)); return create_ast_node<BinaryExpression>(BinaryOp::Asterisk, move(lhs), parse_expression(min_precedence, associativity));
case TokenType::AsteriskEquals: case TokenType::AsteriskEquals:
consume(); consume();
return make<AssignmentExpression>(AssignmentOp::MultiplicationAssignment, move(lhs), parse_expression(min_precedence, associativity)); return create_ast_node<AssignmentExpression>(AssignmentOp::MultiplicationAssignment, move(lhs), parse_expression(min_precedence, associativity));
case TokenType::Slash: case TokenType::Slash:
consume(); consume();
return make<BinaryExpression>(BinaryOp::Slash, move(lhs), parse_expression(min_precedence, associativity)); return create_ast_node<BinaryExpression>(BinaryOp::Slash, move(lhs), parse_expression(min_precedence, associativity));
case TokenType::SlashEquals: case TokenType::SlashEquals:
consume(); consume();
return make<AssignmentExpression>(AssignmentOp::DivisionAssignment, move(lhs), parse_expression(min_precedence, associativity)); return create_ast_node<AssignmentExpression>(AssignmentOp::DivisionAssignment, move(lhs), parse_expression(min_precedence, associativity));
case TokenType::GreaterThan: case TokenType::GreaterThan:
consume(); consume();
return make<BinaryExpression>(BinaryOp::GreaterThan, move(lhs), parse_expression(min_precedence, associativity)); return create_ast_node<BinaryExpression>(BinaryOp::GreaterThan, move(lhs), parse_expression(min_precedence, associativity));
case TokenType::GreaterThanEquals: case TokenType::GreaterThanEquals:
consume(); consume();
return make<BinaryExpression>(BinaryOp::GreaterThanEquals, move(lhs), parse_expression(min_precedence, associativity)); return create_ast_node<BinaryExpression>(BinaryOp::GreaterThanEquals, move(lhs), parse_expression(min_precedence, associativity));
case TokenType::LessThan: case TokenType::LessThan:
consume(); consume();
return make<BinaryExpression>(BinaryOp::LessThan, move(lhs), parse_expression(min_precedence, associativity)); return create_ast_node<BinaryExpression>(BinaryOp::LessThan, move(lhs), parse_expression(min_precedence, associativity));
case TokenType::LessThanEquals: case TokenType::LessThanEquals:
consume(); consume();
return make<BinaryExpression>(BinaryOp::LessThanEquals, move(lhs), parse_expression(min_precedence, associativity)); return create_ast_node<BinaryExpression>(BinaryOp::LessThanEquals, move(lhs), parse_expression(min_precedence, associativity));
case TokenType::EqualsEqualsEquals: case TokenType::EqualsEqualsEquals:
consume(); consume();
return make<BinaryExpression>(BinaryOp::TypedEquals, move(lhs), parse_expression(min_precedence, associativity)); return create_ast_node<BinaryExpression>(BinaryOp::TypedEquals, move(lhs), parse_expression(min_precedence, associativity));
case TokenType::ExclamationMarkEqualsEquals: case TokenType::ExclamationMarkEqualsEquals:
consume(); consume();
return make<BinaryExpression>(BinaryOp::TypedInequals, move(lhs), parse_expression(min_precedence, associativity)); return create_ast_node<BinaryExpression>(BinaryOp::TypedInequals, move(lhs), parse_expression(min_precedence, associativity));
case TokenType::EqualsEquals: case TokenType::EqualsEquals:
consume(); consume();
return make<BinaryExpression>(BinaryOp::AbstractEquals, move(lhs), parse_expression(min_precedence, associativity)); return create_ast_node<BinaryExpression>(BinaryOp::AbstractEquals, move(lhs), parse_expression(min_precedence, associativity));
case TokenType::ExclamationMarkEquals: case TokenType::ExclamationMarkEquals:
consume(); consume();
return make<BinaryExpression>(BinaryOp::AbstractInequals, move(lhs), parse_expression(min_precedence, associativity)); return create_ast_node<BinaryExpression>(BinaryOp::AbstractInequals, move(lhs), parse_expression(min_precedence, associativity));
case TokenType::ParenOpen: case TokenType::ParenOpen:
return parse_call_expression(move(lhs)); return parse_call_expression(move(lhs));
case TokenType::Equals: case TokenType::Equals:
consume(); consume();
return make<AssignmentExpression>(AssignmentOp::Assignment, move(lhs), parse_expression(min_precedence, associativity)); return create_ast_node<AssignmentExpression>(AssignmentOp::Assignment, move(lhs), parse_expression(min_precedence, associativity));
case TokenType::Period: case TokenType::Period:
consume(); consume();
return make<MemberExpression>(move(lhs), parse_expression(min_precedence, associativity)); return create_ast_node<MemberExpression>(move(lhs), parse_expression(min_precedence, associativity));
case TokenType::PlusPlus: case TokenType::PlusPlus:
consume(); consume();
return make<UpdateExpression>(UpdateOp::Increment, move(lhs)); return create_ast_node<UpdateExpression>(UpdateOp::Increment, move(lhs));
case TokenType::MinusMinus: case TokenType::MinusMinus:
consume(); consume();
return make<UpdateExpression>(UpdateOp::Decrement, move(lhs)); return create_ast_node<UpdateExpression>(UpdateOp::Decrement, move(lhs));
case TokenType::DoubleAmpersand: case TokenType::DoubleAmpersand:
consume(); consume();
return make<LogicalExpression>(LogicalOp::And, move(lhs), parse_expression(min_precedence, associativity)); return create_ast_node<LogicalExpression>(LogicalOp::And, move(lhs), parse_expression(min_precedence, associativity));
case TokenType::DoublePipe: case TokenType::DoublePipe:
consume(); consume();
return make<LogicalExpression>(LogicalOp::Or, move(lhs), parse_expression(min_precedence, associativity)); return create_ast_node<LogicalExpression>(LogicalOp::Or, move(lhs), parse_expression(min_precedence, associativity));
default: default:
m_has_errors = true; m_has_errors = true;
expected("secondary expression (missing switch case)"); expected("secondary expression (missing switch case)");
consume(); consume();
return make<ErrorExpression>(); return create_ast_node<ErrorExpression>();
} }
} }
NonnullOwnPtr<CallExpression> Parser::parse_call_expression(NonnullOwnPtr<Expression> lhs) NonnullRefPtr<CallExpression> Parser::parse_call_expression(NonnullRefPtr<Expression> lhs)
{ {
consume(TokenType::ParenOpen); consume(TokenType::ParenOpen);
NonnullOwnPtrVector<Expression> arguments; NonnullRefPtrVector<Expression> arguments;
while (match_expression()) { while (match_expression()) {
arguments.append(parse_expression(0)); arguments.append(parse_expression(0));
@ -386,21 +386,21 @@ NonnullOwnPtr<CallExpression> Parser::parse_call_expression(NonnullOwnPtr<Expres
consume(TokenType::ParenClose); consume(TokenType::ParenClose);
return make<CallExpression>(move(lhs), move(arguments)); return create_ast_node<CallExpression>(move(lhs), move(arguments));
} }
NonnullOwnPtr<ReturnStatement> Parser::parse_return_statement() NonnullRefPtr<ReturnStatement> Parser::parse_return_statement()
{ {
consume(TokenType::Return); consume(TokenType::Return);
if (match_expression()) { if (match_expression()) {
return make<ReturnStatement>(parse_expression(0)); return create_ast_node<ReturnStatement>(parse_expression(0));
} }
return make<ReturnStatement>(nullptr); return create_ast_node<ReturnStatement>(nullptr);
} }
NonnullOwnPtr<BlockStatement> Parser::parse_block_statement() NonnullRefPtr<BlockStatement> Parser::parse_block_statement()
{ {
auto block = make<BlockStatement>(); auto block = create_ast_node<BlockStatement>();
consume(TokenType::CurlyOpen); consume(TokenType::CurlyOpen);
while (!done() && !match(TokenType::CurlyClose)) { while (!done() && !match(TokenType::CurlyClose)) {
if (match(TokenType::Semicolon)) { if (match(TokenType::Semicolon)) {
@ -416,7 +416,7 @@ NonnullOwnPtr<BlockStatement> Parser::parse_block_statement()
return block; return block;
} }
NonnullOwnPtr<FunctionDeclaration> Parser::parse_function_declaration() NonnullRefPtr<FunctionDeclaration> Parser::parse_function_declaration()
{ {
consume(TokenType::Function); consume(TokenType::Function);
auto name = consume(TokenType::Identifier).value(); auto name = consume(TokenType::Identifier).value();
@ -432,10 +432,10 @@ NonnullOwnPtr<FunctionDeclaration> Parser::parse_function_declaration()
} }
consume(TokenType::ParenClose); consume(TokenType::ParenClose);
auto body = parse_block_statement(); auto body = parse_block_statement();
return make<FunctionDeclaration>(name, move(body), move(parameters)); return create_ast_node<FunctionDeclaration>(name, move(body), move(parameters));
} }
NonnullOwnPtr<VariableDeclaration> Parser::parse_variable_declaration() NonnullRefPtr<VariableDeclaration> Parser::parse_variable_declaration()
{ {
DeclarationType declaration_type; DeclarationType declaration_type;
@ -456,21 +456,21 @@ NonnullOwnPtr<VariableDeclaration> Parser::parse_variable_declaration()
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
} }
auto name = consume(TokenType::Identifier).value(); auto name = consume(TokenType::Identifier).value();
OwnPtr<Expression> initializer; RefPtr<Expression> initializer;
if (match(TokenType::Equals)) { if (match(TokenType::Equals)) {
consume(); consume();
initializer = parse_expression(0); initializer = parse_expression(0);
} }
return make<VariableDeclaration>(make<Identifier>(name), move(initializer), declaration_type); return create_ast_node<VariableDeclaration>(create_ast_node<Identifier>(name), move(initializer), declaration_type);
} }
NonnullOwnPtr<ForStatement> Parser::parse_for_statement() NonnullRefPtr<ForStatement> Parser::parse_for_statement()
{ {
consume(TokenType::For); consume(TokenType::For);
consume(TokenType::ParenOpen); consume(TokenType::ParenOpen);
OwnPtr<Statement> init = nullptr; RefPtr<Statement> init;
switch (m_current_token.type()) { switch (m_current_token.type()) {
case TokenType::Semicolon: case TokenType::Semicolon:
break; break;
@ -481,7 +481,7 @@ NonnullOwnPtr<ForStatement> Parser::parse_for_statement()
consume(TokenType::Semicolon); consume(TokenType::Semicolon);
OwnPtr<Expression> test = nullptr; RefPtr<Expression> test;
switch (m_current_token.type()) { switch (m_current_token.type()) {
case TokenType::Semicolon: case TokenType::Semicolon:
break; break;
@ -492,7 +492,7 @@ NonnullOwnPtr<ForStatement> Parser::parse_for_statement()
consume(TokenType::Semicolon); consume(TokenType::Semicolon);
OwnPtr<Expression> update = nullptr; RefPtr<Expression> update;
switch (m_current_token.type()) { switch (m_current_token.type()) {
case TokenType::Semicolon: case TokenType::Semicolon:
break; break;
@ -505,7 +505,7 @@ NonnullOwnPtr<ForStatement> Parser::parse_for_statement()
auto body = parse_block_statement(); auto body = parse_block_statement();
return make<ForStatement>(move(init), move(test), move(update), move(body)); return create_ast_node<ForStatement>(move(init), move(test), move(update), move(body));
} }
bool Parser::match(TokenType type) const bool Parser::match(TokenType type) const

View file

@ -28,7 +28,7 @@
#include "AST.h" #include "AST.h"
#include "Lexer.h" #include "Lexer.h"
#include <AK/NonnullOwnPtr.h> #include <AK/NonnullRefPtr.h>
namespace JS { namespace JS {
@ -41,21 +41,21 @@ class Parser {
public: public:
explicit Parser(Lexer lexer); explicit Parser(Lexer lexer);
NonnullOwnPtr<Program> parse_program(); NonnullRefPtr<Program> parse_program();
NonnullOwnPtr<Statement> parse_statement(); NonnullRefPtr<Statement> parse_statement();
NonnullOwnPtr<BlockStatement> parse_block_statement(); NonnullRefPtr<BlockStatement> parse_block_statement();
NonnullOwnPtr<ReturnStatement> parse_return_statement(); NonnullRefPtr<ReturnStatement> parse_return_statement();
NonnullOwnPtr<FunctionDeclaration> parse_function_declaration(); NonnullRefPtr<FunctionDeclaration> parse_function_declaration();
NonnullOwnPtr<VariableDeclaration> parse_variable_declaration(); NonnullRefPtr<VariableDeclaration> parse_variable_declaration();
NonnullOwnPtr<ForStatement> parse_for_statement(); NonnullRefPtr<ForStatement> parse_for_statement();
NonnullOwnPtr<Expression> parse_expression(int min_precedence, Associativity associate = Associativity::Right); NonnullRefPtr<Expression> parse_expression(int min_precedence, Associativity associate = Associativity::Right);
NonnullOwnPtr<Expression> parse_primary_expression(); NonnullRefPtr<Expression> parse_primary_expression();
NonnullOwnPtr<Expression> parse_unary_prefixed_expression(); NonnullRefPtr<Expression> parse_unary_prefixed_expression();
NonnullOwnPtr<ObjectExpression> parse_object_expression(); NonnullRefPtr<ObjectExpression> parse_object_expression();
NonnullOwnPtr<Expression> parse_secondary_expression(NonnullOwnPtr<Expression>, int min_precedence, Associativity associate = Associativity::Right); NonnullRefPtr<Expression> parse_secondary_expression(NonnullRefPtr<Expression>, int min_precedence, Associativity associate = Associativity::Right);
NonnullOwnPtr<CallExpression> parse_call_expression(NonnullOwnPtr<Expression>); NonnullRefPtr<CallExpression> parse_call_expression(NonnullRefPtr<Expression>);
bool has_errors() const { return m_has_errors; } bool has_errors() const { return m_has_errors; }

View file

@ -24,6 +24,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <LibJS/AST.h>
#include <LibJS/Interpreter.h> #include <LibJS/Interpreter.h>
#include <LibJS/Runtime/ScriptFunction.h> #include <LibJS/Runtime/ScriptFunction.h>
#include <LibJS/Runtime/Value.h> #include <LibJS/Runtime/Value.h>

View file

@ -44,7 +44,7 @@ private:
virtual bool is_script_function() const final { return true; } virtual bool is_script_function() const final { return true; }
virtual const char* class_name() const override { return "ScriptFunction"; } virtual const char* class_name() const override { return "ScriptFunction"; }
const ScopeNode& m_body; NonnullRefPtr<ScopeNode> m_body;
const Vector<String> m_parameters; const Vector<String> m_parameters;
}; };