susumu.yata
null+****@clear*****
Wed Jul 30 16:57:14 JST 2014
susumu.yata 2014-07-30 16:57:14 +0900 (Wed, 30 Jul 2014) New Revision: 82663b1e9c8a5a0bfc6de2e0950a5c91fd6ca035 https://github.com/groonga/grnxx/commit/82663b1e9c8a5a0bfc6de2e0950a5c91fd6ca035 Message: Implement unary operators +, -, TO_INT, and TO_FLOAT. Modified files: include/grnxx/expression.hpp lib/grnxx/expression.cpp Modified: include/grnxx/expression.hpp (+16 -8) =================================================================== --- include/grnxx/expression.hpp 2014-07-30 16:13:14 +0900 (992f869) +++ include/grnxx/expression.hpp 2014-07-30 16:57:14 +0900 (436d9a8) @@ -13,16 +13,16 @@ enum OperatorType { // BITWISE_NOT_OPERATOR, // For Int. -// POSITIVE_OPERATOR, // For Int, Float. -// NEGATIVE_OPERATOR, // For Int, Float. + POSITIVE_OPERATOR, // For Int, Float. + NEGATIVE_OPERATOR, // For Int, Float. // Typecast operators. -// BOOL_OPERATOR, -// INT_OPERATOR, -// FLOAT_OPERATOR, -// TIME_OPERATOR, -// GEO_POINT_OPERATOR, -// TEXT_OPERATOR, +// TO_BOOL_OPERATOR, + TO_INT_OPERATOR, + TO_FLOAT_OPERATOR, +// TO_TIME_OPERATOR, +// TO_GEO_POINT_OPERATOR, +// TO_TEXT_OPERATOR, // -- Binary operators -- @@ -186,6 +186,14 @@ class ExpressionBuilder { explicit ExpressionBuilder(const Table *table); + // Push a positive operator. + bool push_positive_operator(Error *error); + // Push a negative operator. + bool push_negative_operator(Error *error); + // Push a typecast operator to Int. + bool push_to_int_operator(Error *error); + // Push a typecast operator to Float. + bool push_to_float_operator(Error *error); // Push an operator &&. bool push_logical_and_operator(Error *error); // Push an operator ||. Modified: lib/grnxx/expression.cpp (+202 -0) =================================================================== --- lib/grnxx/expression.cpp 2014-07-30 16:13:14 +0900 (8cdf8e6) +++ lib/grnxx/expression.cpp 2014-07-30 16:57:14 +0900 (cec8a34) @@ -261,6 +261,74 @@ class ColumnNode : public Node<T> { // -- OperatorNode -- +// ---- UnaryNode ---- + +struct Negative { + template <typename T> + struct Functor { + using Arg = T; + using Result = T; + Result operator()(Arg arg) const { + return -arg; + }; + }; +}; + +template <typename T> +struct Typecast { + template <typename U> + struct Functor { + using Arg = U; + using Result = T; + Result operator()(Arg arg) const { + return static_cast<Result>(arg); + }; + }; +}; + +template <typename T> +class UnaryNode : public Node<typename T::Result> { + public: + using Operator = T; + using Arg = typename Operator::Arg; + + UnaryNode(Operator op, + unique_ptr<ExpressionNode> &&arg) + : Node<typename Operator::Result>(), + operator_(op), + arg_(static_cast<Node<Arg> *>(arg.release())) {} + virtual ~UnaryNode() {} + + NodeType node_type() const { + return OPERATOR_NODE; + } + + bool evaluate(Error *error, const RecordSubset &record_set); + + private: + Operator operator_; + unique_ptr<Node<Arg>> arg_; +}; + +template <typename T> +bool UnaryNode<T>::evaluate(Error *error, const RecordSubset &record_set) { + try { + this->values_.resize(error, record_set.size()); + } catch (...) { + GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed"); + return false; + } + if (!arg_->evaluate(error, record_set)) { + return false; + } + for (Int i = 0; i < record_set.size(); ++i) { + this->values_[i] = operator_(arg_->get(i)); + } + return true; +} + +// ---- BinaryNode ---- + struct Equal { template <typename T> struct Functor { @@ -820,6 +888,18 @@ bool ExpressionBuilder::push_column(Error *error, String name) { bool ExpressionBuilder::push_operator(Error *error, OperatorType operator_type) { switch (operator_type) { + case POSITIVE_OPERATOR: { + return push_positive_operator(error); + } + case NEGATIVE_OPERATOR: { + return push_negative_operator(error); + } + case TO_INT_OPERATOR: { + return push_to_int_operator(error); + } + case TO_FLOAT_OPERATOR: { + return push_to_float_operator(error); + } case LOGICAL_AND_OPERATOR: { return push_logical_and_operator(error); } @@ -886,6 +966,128 @@ unique_ptr<Expression> ExpressionBuilder::release(Error *error) { ExpressionBuilder::ExpressionBuilder(const Table *table) : table_(table) {} +bool ExpressionBuilder::push_positive_operator(Error *error) { + if (stack_.size() < 1) { + // TODO: Define a better error code. + GRNXX_ERROR_SET(error, INVALID_ARGUMENT, "Not enough operands"); + return false; + } + auto &arg = stack_[stack_.size() - 1]; + switch (arg->data_type()) { + case INT_DATA: + case FLOAT_DATA: { + // Nothing to do because this operator does nothing. + return true; + } + default: { + // TODO: Define a better error code. + GRNXX_ERROR_SET(error, INVALID_ARGUMENT, "Wrong type"); + return false; + } + } +} + +bool ExpressionBuilder::push_negative_operator(Error *error) { + if (stack_.size() < 1) { + // TODO: Define a better error code. + GRNXX_ERROR_SET(error, INVALID_ARGUMENT, "Not enough operands"); + return false; + } + unique_ptr<ExpressionNode> node; + auto &arg = stack_[stack_.size() - 1]; + switch (arg->data_type()) { + case INT_DATA: { + Negative::Functor<Int> functor; + node.reset( + new (nothrow) UnaryNode<decltype(functor)>(functor, std::move(arg))); + break; + } + case FLOAT_DATA: { + Negative::Functor<Float> functor; + node.reset( + new (nothrow) UnaryNode<decltype(functor)>(functor, std::move(arg))); + break; + } + default: { + // TODO: Define a better error code. + GRNXX_ERROR_SET(error, INVALID_ARGUMENT, "Wrong type"); + return false; + } + } + if (!node) { + GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed"); + return false; + } + stack_.back() = std::move(node); + return true; +} + +bool ExpressionBuilder::push_to_int_operator(Error *error) { + if (stack_.size() < 1) { + // TODO: Define a better error code. + GRNXX_ERROR_SET(error, INVALID_ARGUMENT, "Not enough operands"); + return false; + } + unique_ptr<ExpressionNode> node; + auto &arg = stack_[stack_.size() - 1]; + switch (arg->data_type()) { + case INT_DATA: { + // Nothing to do because this operator does nothing. + return true; + } + case FLOAT_DATA: { + Typecast<Int>::Functor<Float> functor; + node.reset( + new (nothrow) UnaryNode<decltype(functor)>(functor, std::move(arg))); + break; + } + default: { + // TODO: Define a better error code. + GRNXX_ERROR_SET(error, INVALID_ARGUMENT, "Wrong type"); + return false; + } + } + if (!node) { + GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed"); + return false; + } + stack_.back() = std::move(node); + return true; +} + +bool ExpressionBuilder::push_to_float_operator(Error *error) { + if (stack_.size() < 1) { + // TODO: Define a better error code. + GRNXX_ERROR_SET(error, INVALID_ARGUMENT, "Not enough operands"); + return false; + } + unique_ptr<ExpressionNode> node; + auto &arg = stack_[stack_.size() - 1]; + switch (arg->data_type()) { + case INT_DATA: { + Typecast<Float>::Functor<Int> functor; + node.reset( + new (nothrow) UnaryNode<decltype(functor)>(functor, std::move(arg))); + break; + } + case FLOAT_DATA: { + // Nothing to do because this operator does nothing. + return true; + } + default: { + // TODO: Define a better error code. + GRNXX_ERROR_SET(error, INVALID_ARGUMENT, "Wrong type"); + return false; + } + } + if (!node) { + GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed"); + return false; + } + stack_.back() = std::move(node); + return true; +} + bool ExpressionBuilder::push_logical_and_operator(Error *error) { if (stack_.size() < 2) { // TODO: Define a better error code. -------------- next part -------------- HTML����������������������������...Download