[Groonga-commit] groonga/grnxx at 82663b1 [master] Implement unary operators +, -, TO_INT, and TO_FLOAT.

Back to archive index

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 



More information about the Groonga-commit mailing list
Back to archive index