From a96bf2c22e80581b173285dbd71b9c29e78dfaed Mon Sep 17 00:00:00 2001 From: 0xtechnobabble <0xtechnobabble@protonmail.com> Date: Sun, 8 Mar 2020 07:55:44 +0200 Subject: [PATCH] LibJS: Implement logical expressions Logical expressions are expressions which can return either true or false according to a provided condition. --- Libraries/LibJS/AST.cpp | 34 ++++++++++++++++++++++++++++++++++ Libraries/LibJS/AST.h | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/Libraries/LibJS/AST.cpp b/Libraries/LibJS/AST.cpp index 1b8a666d31..cc2004895a 100644 --- a/Libraries/LibJS/AST.cpp +++ b/Libraries/LibJS/AST.cpp @@ -114,6 +114,22 @@ Value BinaryExpression::execute(Interpreter& interpreter) const ASSERT_NOT_REACHED(); } + +Value LogicalExpression::execute(Interpreter& interpreter) const +{ + auto lhs_result = m_lhs->execute(interpreter).as_bool(); + + if (m_op == LogicalOp::Not) + return Value(!lhs_result); + + auto rhs_result = m_rhs->execute(interpreter).as_bool(); + switch (m_op) { + case LogicalOp::And: + return Value(lhs_result && rhs_result); + case LogicalOp::Or: + return Value(lhs_result || rhs_result); + case LogicalOp::Not: + ASSERT_NOT_REACHED(); } ASSERT_NOT_REACHED(); @@ -161,6 +177,24 @@ void BinaryExpression::dump(int indent) const m_rhs->dump(indent + 1); } +void LogicalExpression::dump(int indent) const +{ + const char* op_string = nullptr; + switch (m_op) { + case LogicalOp::And: + op_string = "&&"; + break; + case LogicalOp::Or: + op_string = "||"; + break; + case LogicalOp::Not: + op_string = "!"; + print_indent(indent); + printf("%s\n", class_name()); + print_indent(indent + 1); + printf("%s\n", op_string); + m_lhs->dump(indent + 1); + return; } print_indent(indent); diff --git a/Libraries/LibJS/AST.h b/Libraries/LibJS/AST.h index 6d8fbd66c8..f200f7e451 100644 --- a/Libraries/LibJS/AST.h +++ b/Libraries/LibJS/AST.h @@ -27,6 +27,7 @@ #pragma once #include +#include #include #include #include @@ -152,6 +153,39 @@ private: NonnullOwnPtr m_rhs; }; +enum class LogicalOp { + And, + Or, + Not +}; + +class LogicalExpression : public Expression { +public: + LogicalExpression(LogicalOp op, NonnullOwnPtr lhs, NonnullOwnPtr rhs) + : m_op(op) + , m_lhs(move(lhs)) + , m_rhs(move(rhs)) + { + } + + LogicalExpression(LogicalOp op, NonnullOwnPtr lhs) + : m_op(op) + , m_lhs(move(lhs)) + { + ASSERT(op == LogicalOp::Not); + } + + virtual Value execute(Interpreter&) const override; + virtual void dump(int indent) const override; + +private: + virtual const char* class_name() const override { return "LogicalExpression"; } + + LogicalOp m_op; + NonnullOwnPtr m_lhs; + OwnPtr m_rhs; +}; + class Literal : public Expression { public: explicit Literal(Value value)