From 9d1e27d8a880aa0d1bd7c61aba2f6f843826b6ba Mon Sep 17 00:00:00 2001 From: Jan de Visser Date: Thu, 21 Oct 2021 18:10:25 -0400 Subject: [PATCH] LibSQL: Implement evaluate() method of BinaryOperatorExpression Mostly just calls the appropriate methods on the Value objects. Exception are the `Concatenate` (string concat), and the logical `and` and `or` operators which are implemented directly in `BinaryOperatorExpression::evaluate` --- Userland/Libraries/LibSQL/AST/AST.h | 1 + Userland/Libraries/LibSQL/AST/Expression.cpp | 66 ++++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/Userland/Libraries/LibSQL/AST/AST.h b/Userland/Libraries/LibSQL/AST/AST.h index 168a61bb1d..06f2f2fdbc 100644 --- a/Userland/Libraries/LibSQL/AST/AST.h +++ b/Userland/Libraries/LibSQL/AST/AST.h @@ -490,6 +490,7 @@ public: } BinaryOperator type() const { return m_type; } + virtual Value evaluate(ExecutionContext&) const override; private: BinaryOperator m_type; diff --git a/Userland/Libraries/LibSQL/AST/Expression.cpp b/Userland/Libraries/LibSQL/AST/Expression.cpp index c9c20d2892..cd53fa66f0 100644 --- a/Userland/Libraries/LibSQL/AST/Expression.cpp +++ b/Userland/Libraries/LibSQL/AST/Expression.cpp @@ -49,6 +49,72 @@ Value ChainedExpression::evaluate(ExecutionContext& context) const return ret; } +Value BinaryOperatorExpression::evaluate(ExecutionContext& context) const +{ + Value lhs_value = lhs()->evaluate(context); + Value rhs_value = rhs()->evaluate(context); + switch (type()) { + case BinaryOperator::Concatenate: { + if (lhs_value.type() != SQLType::Text) { + VERIFY_NOT_REACHED(); + } + AK::StringBuilder builder; + builder.append(lhs_value.to_string()); + builder.append(rhs_value.to_string()); + return Value(builder.to_string()); + } + case BinaryOperator::Multiplication: + return lhs_value.multiply(rhs_value); + case BinaryOperator::Division: + return lhs_value.divide(rhs_value); + case BinaryOperator::Modulo: + return lhs_value.modulo(rhs_value); + case BinaryOperator::Plus: + return lhs_value.add(rhs_value); + case BinaryOperator::Minus: + return lhs_value.subtract(rhs_value); + case BinaryOperator::ShiftLeft: + return lhs_value.shift_left(rhs_value); + case BinaryOperator::ShiftRight: + return lhs_value.shift_right(rhs_value); + case BinaryOperator::BitwiseAnd: + return lhs_value.bitwise_and(rhs_value); + case BinaryOperator::BitwiseOr: + return lhs_value.bitwise_or(rhs_value); + case BinaryOperator::LessThan: + return Value(lhs_value.compare(rhs_value) < 0); + case BinaryOperator::LessThanEquals: + return Value(lhs_value.compare(rhs_value) <= 0); + case BinaryOperator::GreaterThan: + return Value(lhs_value.compare(rhs_value) > 0); + case BinaryOperator::GreaterThanEquals: + return Value(lhs_value.compare(rhs_value) >= 0); + case BinaryOperator::Equals: + return Value(lhs_value.compare(rhs_value) == 0); + case BinaryOperator::NotEquals: + return Value(lhs_value.compare(rhs_value) != 0); + case BinaryOperator::And: { + auto lhs_bool_maybe = lhs_value.to_bool(); + auto rhs_bool_maybe = rhs_value.to_bool(); + if (!lhs_bool_maybe.has_value() || !rhs_bool_maybe.has_value()) { + // TODO Error handling + VERIFY_NOT_REACHED(); + } + return Value(lhs_bool_maybe.value() && rhs_bool_maybe.value()); + } + case BinaryOperator::Or: { + auto lhs_bool_maybe = lhs_value.to_bool(); + auto rhs_bool_maybe = rhs_value.to_bool(); + if (!lhs_bool_maybe.has_value() || !rhs_bool_maybe.has_value()) { + // TODO Error handling + VERIFY_NOT_REACHED(); + } + return Value(lhs_bool_maybe.value() || rhs_bool_maybe.value()); + } + } + VERIFY_NOT_REACHED(); +} + Value UnaryOperatorExpression::evaluate(ExecutionContext& context) const { Value expression_value = NestedExpression::evaluate(context);