From b1b4c9844e63a65a19f5772c614df29015b37ce1 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Thu, 19 Mar 2020 11:12:08 +0100 Subject: [PATCH] LibJS: Add FunctionExpression AST node Most of the code is shared with FunctionDeclaration, so the shared bits are moved up into a common base called FunctionNode. --- Libraries/LibJS/AST.cpp | 23 +++++++++++++++---- Libraries/LibJS/AST.h | 51 ++++++++++++++++++++++++++++++++--------- 2 files changed, 59 insertions(+), 15 deletions(-) diff --git a/Libraries/LibJS/AST.cpp b/Libraries/LibJS/AST.cpp index 00dcd1ccb3..c612c3028c 100644 --- a/Libraries/LibJS/AST.cpp +++ b/Libraries/LibJS/AST.cpp @@ -43,10 +43,15 @@ Value ScopeNode::execute(Interpreter& interpreter) const Value FunctionDeclaration::execute(Interpreter& interpreter) const { auto* function = interpreter.heap().allocate(body(), parameters()); - interpreter.set_variable(m_name, function); + interpreter.set_variable(name(), function); return function; } +Value FunctionExpression::execute(Interpreter& interpreter) const +{ + return interpreter.heap().allocate(body(), parameters()); +} + Value ExpressionStatement::execute(Interpreter& interpreter) const { return m_expression->execute(interpreter); @@ -385,11 +390,11 @@ void NullLiteral::dump(int indent) const printf("null\n"); } -void FunctionDeclaration::dump(int indent) const +void FunctionNode::dump(int indent, const char* class_name) const { bool first_time = true; StringBuilder parameters_builder; - for (const auto& parameter : m_parameters) { + for (const auto& parameter : parameters()) { if (first_time) first_time = false; else @@ -399,10 +404,20 @@ void FunctionDeclaration::dump(int indent) const } print_indent(indent); - printf("%s '%s(%s)'\n", class_name(), name().characters(), parameters_builder.build().characters()); + printf("%s '%s(%s)'\n", class_name, name().characters(), parameters_builder.build().characters()); body().dump(indent + 1); } +void FunctionDeclaration::dump(int indent) const +{ + FunctionNode::dump(indent, class_name()); +} + +void FunctionExpression::dump(int indent) const +{ + FunctionNode::dump(indent, class_name()); +} + void ReturnStatement::dump(int indent) const { ASTNode::dump(indent); diff --git a/Libraries/LibJS/AST.h b/Libraries/LibJS/AST.h index 7915fe7baa..4b942fc8bb 100644 --- a/Libraries/LibJS/AST.h +++ b/Libraries/LibJS/AST.h @@ -123,33 +123,62 @@ private: virtual const char* class_name() const override { return "BlockStatement"; } }; -class FunctionDeclaration : public Statement { +class Expression : public ASTNode { public: - FunctionDeclaration(String name, NonnullRefPtr body, Vector parameters = {}) + virtual bool is_member_expression() const { return false; } +}; + +class FunctionNode { +public: + String name() const { return m_name; } + const ScopeNode& body() const { return *m_body; } + const Vector& parameters() const { return m_parameters; }; + +protected: + FunctionNode(String name, NonnullRefPtr body, Vector parameters = {}) : m_name(move(name)) , m_body(move(body)) , m_parameters(move(parameters)) { } - String name() const { return m_name; } - const ScopeNode& body() const { return *m_body; } - const Vector& parameters() const { return m_parameters; }; + void dump(int indent, const char* class_name) const; + +private: + String m_name; + NonnullRefPtr m_body; + const Vector m_parameters; +}; + +class FunctionDeclaration final + : public Statement + , public FunctionNode { +public: + FunctionDeclaration(String name, NonnullRefPtr body, Vector parameters = {}) + : FunctionNode(move(name), move(body), move(parameters)) + { + } virtual Value execute(Interpreter&) const override; virtual void dump(int indent) const override; private: virtual const char* class_name() const override { return "FunctionDeclaration"; } - - String m_name; - NonnullRefPtr m_body; - const Vector m_parameters; }; -class Expression : public ASTNode { +class FunctionExpression final : public Expression + , public FunctionNode { public: - virtual bool is_member_expression() const { return false; } + FunctionExpression(String name, NonnullRefPtr body, Vector parameters = {}) + : FunctionNode(move(name), move(body), move(parameters)) + { + } + + virtual Value execute(Interpreter&) const override; + virtual void dump(int indent) const override; + +private: + virtual const char* class_name() const override { return "FunctionExpression"; } }; class ErrorExpression final : public Expression {