susumu.yata
null+****@clear*****
Tue Jul 22 15:40:28 JST 2014
susumu.yata 2014-07-22 15:40:28 +0900 (Tue, 22 Jul 2014) New Revision: e22029a9b5caef34052acfb3283323a52357555a https://github.com/groonga/grnxx/commit/e22029a9b5caef34052acfb3283323a52357555a Message: Add arithmetic operators Plus, Minus, and Multiplication. Modified files: include/grnxx/expression.hpp lib/grnxx/expression.cpp test/test_grnxx.cpp Modified: include/grnxx/expression.hpp (+6 -3) =================================================================== --- include/grnxx/expression.hpp 2014-07-22 15:15:31 +0900 (99f5ea9) +++ include/grnxx/expression.hpp 2014-07-22 15:40:28 +0900 (852bbd2) @@ -47,10 +47,10 @@ enum OperatorType { BITWISE_XOR_OPERATOR, // For Bool, Int. // Arithmetic operators. -// PLUS_OPERATOR, // For Int, Float. -// MINUS_OPERATOR, // For Int, Float. + PLUS_OPERATOR, // For Int, Float. + MINUS_OPERATOR, // For Int, Float. + MULTIPLICATION_OPERATOR, // For Int, Float. // DIVISION_OPERATOR, // For Int, Float. -// MULTIPLICATION_OPERATOR, // For Int, Float. // MODULUS_OPERATOR, // For Int. // Array operators. @@ -174,6 +174,9 @@ class ExpressionBuilder { // Push an operator &, |, or ^. template <typename T> bool push_bitwise_operator(Error *error); + // Push an operator +, -, or *. + template <typename T> + bool push_arithmetic_operator(Error *error); }; } // namespace grnxx Modified: lib/grnxx/expression.cpp (+87 -0) =================================================================== --- lib/grnxx/expression.cpp 2014-07-22 15:15:31 +0900 (79feb98) +++ lib/grnxx/expression.cpp 2014-07-22 15:40:28 +0900 (1f100e5) @@ -357,6 +357,42 @@ struct BitwiseXor { }; }; +struct Plus { + template <typename T> + struct Functor { + using Arg1 = T; + using Arg2 = T; + using Result = T; + T operator()(Arg1 lhs, Arg2 rhs) const { + return lhs + rhs; + }; + }; +}; + +struct Minus { + template <typename T> + struct Functor { + using Arg1 = T; + using Arg2 = T; + using Result = T; + T operator()(Arg1 lhs, Arg2 rhs) const { + return lhs - rhs; + }; + }; +}; + +struct Multiplication { + template <typename T> + struct Functor { + using Arg1 = T; + using Arg2 = T; + using Result = T; + T operator()(Arg1 lhs, Arg2 rhs) const { + return lhs * rhs; + }; + }; +}; + template <typename Op> class BinaryNode : public Node<typename Op::Result> { public: @@ -778,6 +814,15 @@ bool ExpressionBuilder::push_operator(Error *error, case BITWISE_XOR_OPERATOR: { return push_bitwise_operator<BitwiseXor>(error); } + case PLUS_OPERATOR: { + return push_arithmetic_operator<Plus>(error); + } + case MINUS_OPERATOR: { + return push_arithmetic_operator<Minus>(error); + } + case MULTIPLICATION_OPERATOR: { + return push_arithmetic_operator<Multiplication>(error); + } default: { // TODO: Not supported yet. GRNXX_ERROR_SET(error, NOT_SUPPORTED_YET, "Not supported yet"); @@ -1018,4 +1063,46 @@ bool ExpressionBuilder::push_bitwise_operator(Error *error) { return true; } +template <typename T> +bool ExpressionBuilder::push_arithmetic_operator(Error *error) { + if (stack_.size() < 2) { + // TODO: Define a better error code. + GRNXX_ERROR_SET(error, INVALID_ARGUMENT, "Not enough operands"); + return false; + } + auto &lhs = stack_[stack_.size() - 2]; + auto &rhs = stack_[stack_.size() - 1]; + if (lhs->data_type() != rhs->data_type()) { + // TODO: Define a better error code. + GRNXX_ERROR_SET(error, INVALID_ARGUMENT, "Type conflict"); + return false; + } + unique_ptr<ExpressionNode> node; + switch (lhs->data_type()) { + case INT_DATA: { + typename T::template Functor<Int> functor; + node.reset(new (nothrow) BinaryNode<decltype(functor)>( + functor, std::move(lhs), std::move(rhs))); + break; + } + case FLOAT_DATA: { + typename T::template Functor<Float> functor; + node.reset(new (nothrow) BinaryNode<decltype(functor)>( + functor, std::move(lhs), std::move(rhs))); + break; + } + default: { + GRNXX_ERROR_SET(error, NOT_SUPPORTED_YET, "Not supported yet"); + return false; + } + } + if (!node) { + GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed"); + return false; + } + stack_.pop_back(); + stack_.back() = std::move(node); + return true; +} + } // namespace grnxx Modified: test/test_grnxx.cpp (+57 -0) =================================================================== --- test/test_grnxx.cpp 2014-07-22 15:15:31 +0900 (0143542) +++ test/test_grnxx.cpp 2014-07-22 15:40:28 +0900 (b82c2ba) @@ -661,6 +661,63 @@ void test_expression() { assert(expression->filter(&error, &record_set)); assert(record_set.size() == 1); assert(record_set.get(0).row_id == 1); + + record_set.clear(); + cursor = table->create_cursor(&error); + assert(cursor); + assert(cursor->read_all(&error, &record_set) == 2); + + // 加算を試す. + assert(builder->push_column(&error, "IntColumn")); + assert(builder->push_datum(&error, grnxx::Int(100))); + assert(builder->push_operator(&error, grnxx::PLUS_OPERATOR)); + assert(builder->push_datum(&error, grnxx::Int(223))); + assert(builder->push_operator(&error, grnxx::EQUAL_OPERATOR)); + expression = builder->release(&error); + assert(expression); + + // フィルタとして使ったときの結果を確認する. + assert(expression->filter(&error, &record_set)); + assert(record_set.size() == 1); + assert(record_set.get(0).row_id == 1); + + record_set.clear(); + cursor = table->create_cursor(&error); + assert(cursor); + assert(cursor->read_all(&error, &record_set) == 2); + + // 減算を試す. + assert(builder->push_column(&error, "FloatColumn")); + assert(builder->push_datum(&error, grnxx::Float(0.25))); + assert(builder->push_operator(&error, grnxx::MINUS_OPERATOR)); + assert(builder->push_datum(&error, grnxx::Float(0.0))); + assert(builder->push_operator(&error, grnxx::EQUAL_OPERATOR)); + expression = builder->release(&error); + assert(expression); + + // フィルタとして使ったときの結果を確認する. + assert(expression->filter(&error, &record_set)); + assert(record_set.size() == 1); + assert(record_set.get(0).row_id == 2); + + record_set.clear(); + cursor = table->create_cursor(&error); + assert(cursor); + assert(cursor->read_all(&error, &record_set) == 2); + + // 乗算を試す. + assert(builder->push_column(&error, "IntColumn")); + assert(builder->push_datum(&error, grnxx::Int(2))); + assert(builder->push_operator(&error, grnxx::MULTIPLICATION_OPERATOR)); + assert(builder->push_datum(&error, grnxx::Int(912))); + assert(builder->push_operator(&error, grnxx::EQUAL_OPERATOR)); + expression = builder->release(&error); + assert(expression); + + // フィルタとして使ったときの結果を確認する. + assert(expression->filter(&error, &record_set)); + assert(record_set.size() == 1); + assert(record_set.get(0).row_id == 2); } } // namespace -------------- next part -------------- HTML����������������������������... Download