[Groonga-commit] groonga/groonga at 77ec0bd [master] grn_ts: move definitions of grn_ts_expr_node into lib/ts/ts_expr_node

Zurück zum Archiv-Index

susumu.yata null+****@clear*****
Thu Nov 12 11:20:53 JST 2015


susumu.yata	2015-11-12 11:20:53 +0900 (Thu, 12 Nov 2015)

  New Revision: 77ec0bdec19dbeb5d8eaf2330e16d6030524af95
  https://github.com/groonga/groonga/commit/77ec0bdec19dbeb5d8eaf2330e16d6030524af95

  Message:
    grn_ts: move definitions of grn_ts_expr_node into lib/ts/ts_expr_node

  Added files:
    lib/ts/ts_expr_node.h
  Copied files:
    lib/ts/ts_expr_node.c
      (from lib/ts/ts_expr.c)
  Modified files:
    lib/ts/sources.am
    lib/ts/ts_expr.c
    lib/ts/ts_expr.h
    lib/ts/ts_types.h

  Modified: lib/ts/sources.am (+2 -0)
===================================================================
--- lib/ts/sources.am    2015-11-12 09:59:27 +0900 (892393b)
+++ lib/ts/sources.am    2015-11-12 11:20:53 +0900 (57faefc)
@@ -3,6 +3,8 @@ libgrnts_la_SOURCES =				\
 	ts_buf.h				\
 	ts_expr.c				\
 	ts_expr.h				\
+	ts_expr_node.c				\
+	ts_expr_node.h				\
 	ts_log.h				\
 	ts_str.c				\
 	ts_str.h				\

  Modified: lib/ts/ts_expr.c (+22 -4499)
===================================================================
--- lib/ts/ts_expr.c    2015-11-12 09:59:27 +0900 (3c4a119)
+++ lib/ts/ts_expr.c    2015-11-12 11:20:53 +0900 (b573ebe)
@@ -33,27 +33,11 @@
 #include "ts_log.h"
 #include "ts_str.h"
 
+
 /*-------------------------------------------------------------
  * Built-in data kinds.
  */
 
-typedef union {
-  grn_ts_bool as_bool;
-  grn_ts_int as_int;
-  grn_ts_float as_float;
-  grn_ts_time as_time;
-  grn_ts_text as_text;
-  grn_ts_geo as_geo;
-  grn_ts_ref as_ref;
-  grn_ts_bool_vector as_bool_vector;
-  grn_ts_int_vector as_int_vector;
-  grn_ts_float_vector as_float_vector;
-  grn_ts_time_vector as_time_vector;
-  grn_ts_text_vector as_text_vector;
-  grn_ts_geo_vector as_geo_vector;
-  grn_ts_ref_vector as_ref_vector;
-} grn_ts_any;
-
 /* grn_ts_bool_is_valid() returns whether a value is valid or not. */
 inline static grn_ts_bool
 grn_ts_bool_is_valid(grn_ts_bool value) {
@@ -143,167 +127,6 @@ grn_ts_geo_vector_is_valid(grn_ts_geo_vector value) {
 }
 #undef GRN_TS_VECTOR_IS_VALID
 
-/* grn_ts_bool_zero() returns a zero. */
-inline static grn_ts_bool
-grn_ts_bool_zero(void) {
-  return GRN_FALSE;
-}
-
-/* grn_ts_int_zero() returns a zero. */
-inline static grn_ts_int
-grn_ts_int_zero(void) {
-  return 0;
-}
-
-/* grn_ts_float_zero() returns a zero. */
-inline static grn_ts_float
-grn_ts_float_zero(void) {
-  return 0.0;
-}
-
-/* grn_ts_time_zero() returns a zero. */
-inline static grn_ts_time
-grn_ts_time_zero(void) {
-  return 0;
-}
-
-/* grn_ts_text_zero() returns a zero. */
-inline static grn_ts_text
-grn_ts_text_zero(void) {
-  return (grn_ts_text){ NULL, 0 };
-}
-
-/* grn_ts_geo_zero() returns a zero. */
-inline static grn_ts_geo
-grn_ts_geo_zero(void) {
-  return (grn_ts_geo){ 0, 0 };
-}
-
-/* grn_ts_ref_zero() returns a zero. */
-inline static grn_ts_ref
-grn_ts_ref_zero(void) {
-  return (grn_ts_ref){ 0, 0.0 };
-}
-
-/* grn_ts_bool_vector_zero() returns a zero. */
-inline static grn_ts_bool_vector
-grn_ts_bool_vector_zero(void) {
-  return (grn_ts_bool_vector){ NULL, 0 };
-}
-
-/* grn_ts_int_vector_zero() returns a zero. */
-inline static grn_ts_int_vector
-grn_ts_int_vector_zero(void) {
-  return (grn_ts_int_vector){ NULL, 0 };
-}
-
-/* grn_ts_float_vector_zero() returns a zero. */
-inline static grn_ts_float_vector
-grn_ts_float_vector_zero(void) {
-  return (grn_ts_float_vector){ NULL, 0 };
-}
-
-/* grn_ts_time_vector_zero() returns a zero. */
-inline static grn_ts_time_vector
-grn_ts_time_vector_zero(void) {
-  return (grn_ts_time_vector){ NULL, 0 };
-}
-
-/* grn_ts_text_vector_zero() returns a zero. */
-inline static grn_ts_text_vector
-grn_ts_text_vector_zero(void) {
-  return (grn_ts_text_vector){ NULL, 0 };
-}
-
-/* grn_ts_geo_vector_zero() returns a zero. */
-inline static grn_ts_geo_vector
-grn_ts_geo_vector_zero(void) {
-  return (grn_ts_geo_vector){ NULL, 0 };
-}
-
-/* grn_ts_ref_vector_zero() returns a zero. */
-inline static grn_ts_ref_vector
-grn_ts_ref_vector_zero(void) {
-  return (grn_ts_ref_vector){ NULL, 0 };
-}
-
-/* grn_ts_data_type_to_kind() returns a kind associated with a type. */
-static grn_ts_data_kind
-grn_ts_data_type_to_kind(grn_ts_data_type type) {
-  switch (type) {
-    case GRN_DB_VOID: {
-      return GRN_TS_VOID;
-    }
-    case GRN_DB_BOOL: {
-      return GRN_TS_BOOL;
-    }
-    case GRN_DB_INT8:
-    case GRN_DB_INT16:
-    case GRN_DB_INT32:
-    case GRN_DB_INT64:
-    case GRN_DB_UINT8:
-    case GRN_DB_UINT16:
-    case GRN_DB_UINT32:
-    case GRN_DB_UINT64: {
-      return GRN_TS_INT;
-    }
-    case GRN_DB_FLOAT: {
-      return GRN_TS_FLOAT;
-    }
-    case GRN_DB_TIME: {
-      return GRN_TS_TIME;
-    }
-    case GRN_DB_SHORT_TEXT:
-    case GRN_DB_TEXT:
-    case GRN_DB_LONG_TEXT: {
-      return GRN_TS_TEXT;
-    }
-    case GRN_DB_TOKYO_GEO_POINT:
-    case GRN_DB_WGS84_GEO_POINT: {
-      return GRN_TS_GEO;
-    }
-    default: {
-      return GRN_TS_REF;
-    }
-  }
-}
-
-/* grn_ts_data_kind_to_type() returns a type associated with a kind. */
-static grn_ts_data_type
-grn_ts_data_kind_to_type(grn_ts_data_kind kind) {
-  switch (kind & ~GRN_TS_VECTOR_FLAG) {
-    case GRN_TS_BOOL: {
-      return GRN_DB_BOOL;
-    }
-    case GRN_TS_INT: {
-      return GRN_DB_INT64;
-    }
-    case GRN_TS_FLOAT: {
-      return GRN_DB_FLOAT;
-    }
-    case GRN_TS_TIME: {
-      return GRN_DB_TIME;
-    }
-    case GRN_TS_TEXT: {
-      return GRN_DB_TEXT;
-    }
-    case GRN_TS_GEO: {
-      /* GRN_DB_TOKYO_GEO_POINT or GRN_DB_WGS84_GEO_POINT. */
-      return GRN_DB_VOID;
-    }
-    case GRN_TS_REF: {
-      /*
-       * grn_ts_data_kind does not have enough information to get a correct
-       * table ID.
-       */
-      return GRN_DB_VOID;
-    }
-    default: {
-      return GRN_DB_VOID;
-    }
-  }
-}
-
 /*-------------------------------------------------------------
  * Operators.
  */
@@ -412,715 +235,30 @@ grn_ts_op_get_precedence(grn_ts_op_type op_type) {
   }
 }
 
-/* grn_ts_op_logical_not_bool() returns !arg. */
-inline static grn_ts_bool
-grn_ts_op_logical_not_bool(grn_ts_bool arg) {
-  return !arg;
-}
-
-/* grn_ts_op_bitwise_not_bool() returns ~arg. */
-inline static grn_ts_bool
-grn_ts_op_bitwise_not_bool(grn_ts_bool arg) {
-  return !arg;
-}
-
-/* grn_ts_op_bitwise_not_int() returns ~arg. */
-inline static grn_ts_int
-grn_ts_op_bitwise_not_int(grn_ts_int arg) {
-  return ~arg;
-}
-
-/* grn_ts_op_positive_int() returns +arg. */
-inline static grn_ts_int
-grn_ts_op_positive_int(grn_ts_int arg) {
-  return arg;
-}
-
-/* grn_ts_op_positive_float() returns +arg. */
-inline static grn_ts_float
-grn_ts_op_positive_float(grn_ts_float arg) {
-  return arg;
-}
-
-/* grn_ts_op_negative_int() returns -arg. */
-inline static grn_ts_int
-grn_ts_op_negative_int(grn_ts_int arg) {
-  return -arg;
-}
-
-/* grn_ts_op_negative_float() returns -arg. */
-inline static grn_ts_float
-grn_ts_op_negative_float(grn_ts_float arg) {
-  return -arg;
-}
-
-/* grn_ts_op_bitwise_and_bool() returns lhs & rhs. */
-inline static grn_ts_bool
-grn_ts_op_bitwise_and_bool(grn_ts_bool lhs, grn_ts_bool rhs) {
-  return lhs & rhs;
-}
-
-/* grn_ts_op_bitwise_and_int() returns lhs & rhs. */
-inline static grn_ts_int
-grn_ts_op_bitwise_and_int(grn_ts_int lhs, grn_ts_int rhs) {
-  return lhs & rhs;
-}
-
-/* grn_ts_op_bitwise_or_bool() returns lhs | rhs. */
-inline static grn_ts_bool
-grn_ts_op_bitwise_or_bool(grn_ts_bool lhs, grn_ts_bool rhs) {
-  return lhs | rhs;
-}
-
-/* grn_ts_op_bitwise_or_int() returns lhs | rhs. */
-inline static grn_ts_int
-grn_ts_op_bitwise_or_int(grn_ts_int lhs, grn_ts_int rhs) {
-  return lhs | rhs;
-}
-
-/* grn_ts_op_bitwise_xor_bool() returns lhs ^ rhs. */
-inline static grn_ts_bool
-grn_ts_op_bitwise_xor_bool(grn_ts_bool lhs, grn_ts_bool rhs) {
-  return lhs ^ rhs;
-}
-
-/* grn_ts_op_bitwise_xor_int() returns lhs ^ rhs. */
-inline static grn_ts_int
-grn_ts_op_bitwise_xor_int(grn_ts_int lhs, grn_ts_int rhs) {
-  return lhs ^ rhs;
-}
-
-/* grn_ts_op_equal_bool() returns lhs == rhs. */
-inline static grn_ts_bool
-grn_ts_op_equal_bool(grn_ts_bool lhs, grn_ts_bool rhs) {
-  return lhs == rhs;
-}
-
-/* grn_ts_op_equal_int() returns lhs == rhs. */
-inline static grn_ts_bool
-grn_ts_op_equal_int(grn_ts_int lhs, grn_ts_int rhs) {
-  return lhs == rhs;
-}
-
-/* grn_ts_op_equal_float() returns lhs == rhs. */
-inline static grn_ts_bool
-grn_ts_op_equal_float(grn_ts_float lhs, grn_ts_float rhs) {
-  /* To suppress warnings, "lhs == rhs" is not used. */
-  return (lhs <= rhs) && (lhs >= rhs);
-}
-
-/* grn_ts_op_equal_time() returns lhs == rhs. */
-inline static grn_ts_bool
-grn_ts_op_equal_time(grn_ts_time lhs, grn_ts_time rhs) {
-  return lhs == rhs;
-}
-
-/* grn_ts_op_equal_text() returns lhs == rhs. */
-inline static grn_ts_bool
-grn_ts_op_equal_text(grn_ts_text lhs, grn_ts_text rhs) {
-  return (lhs.size == rhs.size) && !memcmp(lhs.ptr, rhs.ptr, lhs.size);
-}
-
-/* grn_ts_op_equal_geo() returns lhs == rhs. */
-inline static grn_ts_bool
-grn_ts_op_equal_geo(grn_ts_geo lhs, grn_ts_geo rhs) {
-  return (lhs.latitude == rhs.latitude) && (lhs.longitude == rhs.longitude);
-}
-
-/* grn_ts_op_equal_ref() returns lhs == rhs. */
-inline static grn_ts_bool
-grn_ts_op_equal_ref(grn_ts_ref lhs, grn_ts_ref rhs) {
-  /* Ignore scores. */
-  return lhs.id == rhs.id;
-}
-
-#define GRN_TS_OP_EQUAL_VECTOR(kind)\
-  size_t i;\
-  if (lhs.size != rhs.size) {\
-    return GRN_FALSE;\
-  }\
-  for (i = 0; i < lhs.size; i++) {\
-    if (!grn_ts_op_equal_ ## kind(lhs.ptr[i], rhs.ptr[i])) {\
-      return GRN_FALSE;\
-    }\
-  }\
-  return GRN_TRUE;
-/* grn_ts_op_equal_bool_vector() returns lhs == rhs. */
-inline static grn_ts_bool
-grn_ts_op_equal_bool_vector(grn_ts_bool_vector lhs, grn_ts_bool_vector rhs) {
-  GRN_TS_OP_EQUAL_VECTOR(bool)
-}
-
-/* grn_ts_op_equal_int_vector() returns lhs == rhs. */
-inline static grn_ts_bool
-grn_ts_op_equal_int_vector(grn_ts_int_vector lhs, grn_ts_int_vector rhs) {
-  GRN_TS_OP_EQUAL_VECTOR(int)
-}
-
-/* grn_ts_op_equal_float_vector() returns lhs == rhs. */
-inline static grn_ts_bool
-grn_ts_op_equal_float_vector(grn_ts_float_vector lhs,
-                             grn_ts_float_vector rhs) {
-  GRN_TS_OP_EQUAL_VECTOR(float)
-}
-
-/* grn_ts_op_equal_time_vector() returns lhs == rhs. */
-inline static grn_ts_bool
-grn_ts_op_equal_time_vector(grn_ts_time_vector lhs, grn_ts_time_vector rhs) {
-  GRN_TS_OP_EQUAL_VECTOR(time)
-}
-
-/* grn_ts_op_equal_text_vector() returns lhs == rhs. */
-inline static grn_ts_bool
-grn_ts_op_equal_text_vector(grn_ts_text_vector lhs, grn_ts_text_vector rhs) {
-  GRN_TS_OP_EQUAL_VECTOR(text)
-}
-
-/* grn_ts_op_equal_geo_vector() returns lhs == rhs. */
-inline static grn_ts_bool
-grn_ts_op_equal_geo_vector(grn_ts_geo_vector lhs, grn_ts_geo_vector rhs) {
-  GRN_TS_OP_EQUAL_VECTOR(geo)
-}
-
-/* grn_ts_op_equal_ref_vector() returns lhs == rhs. */
-inline static grn_ts_bool
-grn_ts_op_equal_ref_vector(grn_ts_ref_vector lhs, grn_ts_ref_vector rhs) {
-  GRN_TS_OP_EQUAL_VECTOR(ref)
-}
-#undef GRN_TS_OP_EQUAL_VECTOR
-
-/* grn_ts_op_not_equal_bool() returns lhs != rhs. */
-inline static grn_ts_bool
-grn_ts_op_not_equal_bool(grn_ts_bool lhs, grn_ts_bool rhs) {
-  return lhs != rhs;
-}
-
-/* grn_ts_op_not_equal_int() returns lhs != rhs. */
-inline static grn_ts_bool
-grn_ts_op_not_equal_int(grn_ts_int lhs, grn_ts_int rhs) {
-  return lhs != rhs;
-}
-
-/* grn_ts_op_not_equal_float() returns lhs != rhs. */
-inline static grn_ts_bool
-grn_ts_op_not_equal_float(grn_ts_float lhs, grn_ts_float rhs) {
-  /* To suppress warnings, "lhs != rhs" is not used. */
-  return (lhs < rhs) || (lhs > rhs);
-}
-
-/* grn_ts_op_not_equal_time() returns lhs != rhs. */
-inline static grn_ts_bool
-grn_ts_op_not_equal_time(grn_ts_time lhs, grn_ts_time rhs) {
-  return lhs != rhs;
-}
-
-/* grn_ts_op_not_equal_text() returns lhs != rhs. */
-inline static grn_ts_bool
-grn_ts_op_not_equal_text(grn_ts_text lhs, grn_ts_text rhs) {
-  return (lhs.size != rhs.size) || memcmp(lhs.ptr, rhs.ptr, lhs.size);
-}
-
-/* grn_ts_op_not_equal_geo() returns lhs != rhs. */
-inline static grn_ts_bool
-grn_ts_op_not_equal_geo(grn_ts_geo lhs, grn_ts_geo rhs) {
-  return (lhs.latitude != rhs.latitude) || (lhs.longitude != rhs.longitude);
-}
-
-/* grn_ts_op_not_equal_ref() returns lhs != rhs. */
-inline static grn_ts_bool
-grn_ts_op_not_equal_ref(grn_ts_ref lhs, grn_ts_ref rhs) {
-  /* Ignore scores. */
-  return lhs.id != rhs.id;
-}
-
-#define GRN_TS_OP_NOT_EQUAL_VECTOR(kind)\
-  size_t i;\
-  if (lhs.size != rhs.size) {\
-    return GRN_TRUE;\
-  }\
-  for (i = 0; i < lhs.size; i++) {\
-    if (grn_ts_op_not_equal_ ## kind(lhs.ptr[i], rhs.ptr[i])) {\
-      return GRN_TRUE;\
-    }\
-  }\
-  return GRN_FALSE;
-/* grn_ts_op_not_equal_bool_vector() returns lhs != rhs. */
-inline static grn_ts_bool
-grn_ts_op_not_equal_bool_vector(grn_ts_bool_vector lhs,
-                                grn_ts_bool_vector rhs) {
-  GRN_TS_OP_NOT_EQUAL_VECTOR(bool)
-}
-
-/* grn_ts_op_not_equal_int_vector() returns lhs != rhs. */
-inline static grn_ts_bool
-grn_ts_op_not_equal_int_vector(grn_ts_int_vector lhs, grn_ts_int_vector rhs) {
-  GRN_TS_OP_NOT_EQUAL_VECTOR(int)
-}
-
-/* grn_ts_op_not_equal_float_vector() returns lhs != rhs. */
-inline static grn_ts_bool
-grn_ts_op_not_equal_float_vector(grn_ts_float_vector lhs,
-                             grn_ts_float_vector rhs) {
-  GRN_TS_OP_NOT_EQUAL_VECTOR(float)
-}
-
-/* grn_ts_op_not_equal_time_vector() returns lhs != rhs. */
-inline static grn_ts_bool
-grn_ts_op_not_equal_time_vector(grn_ts_time_vector lhs,
-                                grn_ts_time_vector rhs) {
-  GRN_TS_OP_NOT_EQUAL_VECTOR(time)
-}
-
-/* grn_ts_op_not_equal_text_vector() returns lhs != rhs. */
-inline static grn_ts_bool
-grn_ts_op_not_equal_text_vector(grn_ts_text_vector lhs,
-                                grn_ts_text_vector rhs) {
-  GRN_TS_OP_NOT_EQUAL_VECTOR(text)
-}
-
-/* grn_ts_op_not_equal_geo_vector() returns lhs != rhs. */
-inline static grn_ts_bool
-grn_ts_op_not_equal_geo_vector(grn_ts_geo_vector lhs, grn_ts_geo_vector rhs) {
-  GRN_TS_OP_NOT_EQUAL_VECTOR(geo)
-}
-
-/* grn_ts_op_not_equal_ref_vector() returns lhs != rhs. */
-inline static grn_ts_bool
-grn_ts_op_not_equal_ref_vector(grn_ts_ref_vector lhs, grn_ts_ref_vector rhs) {
-  GRN_TS_OP_NOT_EQUAL_VECTOR(ref)
-}
-#undef GRN_TS_OP_NOT_EQUAL_VECTOR
-
-/* grn_ts_op_less_int() returns lhs < rhs. */
-inline static grn_ts_bool
-grn_ts_op_less_int(grn_ts_int lhs, grn_ts_int rhs) {
-  return lhs < rhs;
-}
-
-/* grn_ts_op_less_float() returns lhs < rhs. */
-inline static grn_ts_bool
-grn_ts_op_less_float(grn_ts_float lhs, grn_ts_float rhs) {
-  return lhs < rhs;
-}
-
-/* grn_ts_op_less_time() returns lhs < rhs. */
-inline static grn_ts_bool
-grn_ts_op_less_time(grn_ts_time lhs, grn_ts_time rhs) {
-  return lhs < rhs;
-}
-
-/* grn_ts_op_less_text() returns lhs < rhs. */
-inline static grn_ts_bool
-grn_ts_op_less_text(grn_ts_text lhs, grn_ts_text rhs) {
-  size_t min_size = (lhs.size < rhs.size) ? lhs.size : rhs.size;
-  int cmp = memcmp(lhs.ptr, rhs.ptr, min_size);
-  return cmp ? (cmp < 0) : (lhs.size < rhs.size);
-}
-
-#define GRN_TS_OP_LESS_VECTOR(kind)\
-  size_t i, min_size = (lhs.size < rhs.size) ? lhs.size : rhs.size;\
-  for (i = 0; i < min_size; i++) {\
-    if (grn_ts_op_not_equal_ ## kind(lhs.ptr[i], rhs.ptr[i])) {\
-      if (grn_ts_op_less_ ## kind(lhs.ptr[i], rhs.ptr[i])) {\
-        return GRN_TRUE;\
-      }\
-    }\
-  }\
-  return lhs.size < rhs.size;
-/* grn_ts_op_less_int_vector() returns lhs < rhs. */
-inline static grn_ts_bool
-grn_ts_op_less_int_vector(grn_ts_int_vector lhs, grn_ts_int_vector rhs) {
-  GRN_TS_OP_LESS_VECTOR(int)
-}
-
-/* grn_ts_op_less_float_vector() returns lhs < rhs. */
-inline static grn_ts_bool
-grn_ts_op_less_float_vector(grn_ts_float_vector lhs, grn_ts_float_vector rhs) {
-  GRN_TS_OP_LESS_VECTOR(float)
-}
-
-/* grn_ts_op_less_time_vector() returns lhs < rhs. */
-inline static grn_ts_bool
-grn_ts_op_less_time_vector(grn_ts_time_vector lhs, grn_ts_time_vector rhs) {
-  GRN_TS_OP_LESS_VECTOR(time)
-}
-
-/* grn_ts_op_less_text_vector() returns lhs < rhs. */
-inline static grn_ts_bool
-grn_ts_op_less_text_vector(grn_ts_text_vector lhs, grn_ts_text_vector rhs) {
-  GRN_TS_OP_LESS_VECTOR(text)
-}
-#undef GRN_TS_OP_LESS_VECTOR
-
-/* grn_ts_op_less_equal_int() returns lhs <= rhs. */
-inline static grn_ts_bool
-grn_ts_op_less_equal_int(grn_ts_int lhs, grn_ts_int rhs) {
-  return lhs <= rhs;
-}
-
-/* grn_ts_op_less_equal_float() returns lhs <= rhs. */
-inline static grn_ts_bool
-grn_ts_op_less_equal_float(grn_ts_float lhs, grn_ts_float rhs) {
-  return lhs <= rhs;
-}
-
-/* grn_ts_op_less_equal_time() returns lhs <= rhs. */
-inline static grn_ts_bool
-grn_ts_op_less_equal_time(grn_ts_time lhs, grn_ts_time rhs) {
-  return lhs <= rhs;
-}
-
-/* grn_ts_op_less_equal_text() returns lhs <= rhs. */
-inline static grn_ts_bool
-grn_ts_op_less_equal_text(grn_ts_text lhs, grn_ts_text rhs) {
-  size_t min_size = (lhs.size < rhs.size) ? lhs.size : rhs.size;
-  int cmp = memcmp(lhs.ptr, rhs.ptr, min_size);
-  return cmp ? (cmp < 0) : (lhs.size <= rhs.size);
-}
-
-#define GRN_TS_OP_LESS_EQUAL_VECTOR(kind)\
-  size_t i, min_size = (lhs.size < rhs.size) ? lhs.size : rhs.size;\
-  for (i = 0; i < min_size; i++) {\
-    if (grn_ts_op_not_equal_ ## kind(lhs.ptr[i], rhs.ptr[i])) {\
-      if (grn_ts_op_less_ ## kind(lhs.ptr[i], rhs.ptr[i])) {\
-        return GRN_TRUE;\
-      }\
-    }\
-  }\
-  return lhs.size <= rhs.size;
-/* grn_ts_op_less_equal_int_vector() returns lhs <= rhs. */
-inline static grn_ts_bool
-grn_ts_op_less_equal_int_vector(grn_ts_int_vector lhs, grn_ts_int_vector rhs) {
-  GRN_TS_OP_LESS_EQUAL_VECTOR(int)
-}
-
-/* grn_ts_op_less_equal_float_vector() returns lhs <= rhs. */
-inline static grn_ts_bool
-grn_ts_op_less_equal_float_vector(grn_ts_float_vector lhs,
-                                  grn_ts_float_vector rhs) {
-  GRN_TS_OP_LESS_EQUAL_VECTOR(float)
-}
+/*-------------------------------------------------------------
+ * Groonga objects.
+ */
 
-/* grn_ts_op_less_equal_time_vector() returns lhs <= rhs. */
-inline static grn_ts_bool
-grn_ts_op_less_equal_time_vector(grn_ts_time_vector lhs,
-                                 grn_ts_time_vector rhs) {
-  GRN_TS_OP_LESS_EQUAL_VECTOR(time)
+/* grn_ts_obj_increment_ref_count() increments an object reference count. */
+static grn_rc
+grn_ts_obj_increment_ref_count(grn_ctx *ctx, grn_obj *obj) {
+  grn_id id = grn_obj_id(ctx, obj);
+  grn_obj *obj_clone = grn_ctx_at(ctx, id);
+  if (!obj_clone) {
+    GRN_TS_ERR_RETURN(GRN_UNKNOWN_ERROR, "grn_ctx_at failed: %d", id);
+  }
+  if (obj_clone != obj) {
+    grn_obj_unlink(ctx, obj_clone);
+    GRN_TS_ERR_RETURN(GRN_UNKNOWN_ERROR, "wrong object: %p != %p",
+                      obj, obj_clone);
+  }
+  return GRN_SUCCESS;
 }
 
-/* grn_ts_op_less_equal_text_vector() returns lhs <= rhs. */
-inline static grn_ts_bool
-grn_ts_op_less_equal_text_vector(grn_ts_text_vector lhs,
-                                 grn_ts_text_vector rhs) {
-  GRN_TS_OP_LESS_EQUAL_VECTOR(text)
-}
-#undef GRN_TS_OP_LESS_EQUAL_VECTOR
-
-/* grn_ts_op_greater_int() returns lhs > rhs. */
-inline static grn_ts_bool
-grn_ts_op_greater_int(grn_ts_int lhs, grn_ts_int rhs) {
-  return lhs > rhs;
-}
-
-/* grn_ts_op_greater_float() returns lhs > rhs. */
-inline static grn_ts_bool
-grn_ts_op_greater_float(grn_ts_float lhs, grn_ts_float rhs) {
-  return lhs > rhs;
-}
-
-/* grn_ts_op_greater_time() returns lhs > rhs. */
-inline static grn_ts_bool
-grn_ts_op_greater_time(grn_ts_time lhs, grn_ts_time rhs) {
-  return lhs > rhs;
-}
-
-/* grn_ts_op_greater_text() returns lhs > rhs. */
-inline static grn_ts_bool
-grn_ts_op_greater_text(grn_ts_text lhs, grn_ts_text rhs) {
-  size_t min_size = (lhs.size < rhs.size) ? lhs.size : rhs.size;
-  int cmp = memcmp(lhs.ptr, rhs.ptr, min_size);
-  return cmp ? (cmp > 0) : (lhs.size > rhs.size);
-}
-
-#define GRN_TS_OP_GREATER_VECTOR(kind)\
-  size_t i, min_size = (lhs.size < rhs.size) ? lhs.size : rhs.size;\
-  for (i = 0; i < min_size; i++) {\
-    if (grn_ts_op_not_equal_ ## kind(lhs.ptr[i], rhs.ptr[i])) {\
-      if (grn_ts_op_greater_ ## kind(lhs.ptr[i], rhs.ptr[i])) {\
-        return GRN_TRUE;\
-      }\
-    }\
-  }\
-  return lhs.size > rhs.size;
-/* grn_ts_op_greater_int_vector() returns lhs > rhs. */
-inline static grn_ts_bool
-grn_ts_op_greater_int_vector(grn_ts_int_vector lhs, grn_ts_int_vector rhs) {
-  GRN_TS_OP_GREATER_VECTOR(int)
-}
-
-/* grn_ts_op_greater_float_vector() returns lhs > rhs. */
-inline static grn_ts_bool
-grn_ts_op_greater_float_vector(grn_ts_float_vector lhs,
-                               grn_ts_float_vector rhs) {
-  GRN_TS_OP_GREATER_VECTOR(float)
-}
-
-/* grn_ts_op_greater_time_vector() returns lhs > rhs. */
-inline static grn_ts_bool
-grn_ts_op_greater_time_vector(grn_ts_time_vector lhs, grn_ts_time_vector rhs) {
-  GRN_TS_OP_GREATER_VECTOR(time)
-}
-
-/* grn_ts_op_greater_text_vector() returns lhs > rhs. */
-inline static grn_ts_bool
-grn_ts_op_greater_text_vector(grn_ts_text_vector lhs, grn_ts_text_vector rhs) {
-  GRN_TS_OP_GREATER_VECTOR(text)
-}
-#undef GRN_TS_OP_GREATER_VECTOR
-
-/* grn_ts_op_greater_equal_int() returns lhs >= rhs. */
-inline static grn_ts_bool
-grn_ts_op_greater_equal_int(grn_ts_int lhs, grn_ts_int rhs) {
-  return lhs >= rhs;
-}
-
-/* grn_ts_op_greater_equal_float() returns lhs >= rhs. */
-inline static grn_ts_bool
-grn_ts_op_greater_equal_float(grn_ts_float lhs, grn_ts_float rhs) {
-  return lhs >= rhs;
-}
-
-/* grn_ts_op_greater_equal_time() returns lhs >= rhs. */
-inline static grn_ts_bool
-grn_ts_op_greater_equal_time(grn_ts_time lhs, grn_ts_time rhs) {
-  return lhs >= rhs;
-}
-
-/* grn_ts_op_greater_equal_text() returns lhs >= rhs. */
-inline static grn_ts_bool
-grn_ts_op_greater_equal_text(grn_ts_text lhs, grn_ts_text rhs) {
-  size_t min_size = (lhs.size < rhs.size) ? lhs.size : rhs.size;
-  int cmp = memcmp(lhs.ptr, rhs.ptr, min_size);
-  return cmp ? (cmp > 0) : (lhs.size >= rhs.size);
-}
-
-#define GRN_TS_OP_GREATER_EQUAL_VECTOR(kind)\
-  size_t i, min_size = (lhs.size < rhs.size) ? lhs.size : rhs.size;\
-  for (i = 0; i < min_size; i++) {\
-    if (grn_ts_op_not_equal_ ## kind(lhs.ptr[i], rhs.ptr[i])) {\
-      if (grn_ts_op_greater_ ## kind(lhs.ptr[i], rhs.ptr[i])) {\
-        return GRN_TRUE;\
-      }\
-    }\
-  }\
-  return lhs.size >= rhs.size;
-/* grn_ts_op_greater_equal_int_vector() returns lhs >= rhs. */
-inline static grn_ts_bool
-grn_ts_op_greater_equal_int_vector(grn_ts_int_vector lhs,
-                                   grn_ts_int_vector rhs) {
-  GRN_TS_OP_GREATER_EQUAL_VECTOR(int)
-}
-
-/* grn_ts_op_greater_equal_float_vector() returns lhs >= rhs. */
-inline static grn_ts_bool
-grn_ts_op_greater_equal_float_vector(grn_ts_float_vector lhs,
-                                     grn_ts_float_vector rhs) {
-  GRN_TS_OP_GREATER_EQUAL_VECTOR(float)
-}
-
-/* grn_ts_op_greater_equal_time_vector() returns lhs >= rhs. */
-inline static grn_ts_bool
-grn_ts_op_greater_equal_time_vector(grn_ts_time_vector lhs,
-                                    grn_ts_time_vector rhs) {
-  GRN_TS_OP_GREATER_EQUAL_VECTOR(time)
-}
-
-/* grn_ts_op_greater_equal_text_vector() returns lhs >= rhs. */
-inline static grn_ts_bool
-grn_ts_op_greater_equal_text_vector(grn_ts_text_vector lhs,
-                                    grn_ts_text_vector rhs) {
-  GRN_TS_OP_GREATER_EQUAL_VECTOR(text)
-}
-#undef GRN_TS_OP_GREATER_EQUAL_VECTOR
-
-/* grn_ts_op_shift_arithmetic_left() returns lhs << rhs. */
-inline static grn_ts_int
-grn_ts_op_shift_arithmetic_left(grn_ts_int lhs, grn_ts_int rhs) {
-  return lhs << rhs;
-}
-
-/* grn_ts_op_shift_arithmetic_right() returns lhs << rhs. */
-inline static grn_ts_int
-grn_ts_op_shift_arithmetic_right(grn_ts_int lhs, grn_ts_int rhs) {
-  return lhs >> rhs;
-}
-
-/* grn_ts_op_shift_logical_left() returns lhs << rhs. */
-inline static grn_ts_int
-grn_ts_op_shift_logical_left(grn_ts_int lhs, grn_ts_int rhs) {
-  return lhs << rhs;
-}
-
-/* grn_ts_op_shift_logical_right() returns lhs << rhs. */
-inline static grn_ts_int
-grn_ts_op_shift_logical_right(grn_ts_int lhs, grn_ts_int rhs) {
-  return (uint64_t)lhs >> rhs;
-}
-
-inline static grn_rc
-grn_ts_op_plus_int_int(grn_ctx *ctx, grn_ts_int lhs, grn_ts_int rhs,
-                       grn_ts_int *out) {
-  *out = lhs + rhs;
-  return GRN_SUCCESS;
-}
-
-inline static grn_rc
-grn_ts_op_plus_float_float(grn_ctx *ctx, grn_ts_float lhs, grn_ts_float rhs,
-                           grn_ts_float *out) {
-  *out = lhs + rhs;
-  if (!grn_ts_float_is_valid(*out)) {
-    GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "%g + %g = %g", lhs, rhs, *out);
-  }
-  return GRN_SUCCESS;
-}
-
-inline static grn_rc
-grn_ts_op_plus_time_int(grn_ctx *ctx, grn_ts_time lhs, grn_ts_int rhs,
-                        grn_ts_time *out) {
-  *out = lhs + (rhs * 1000000);
-  return GRN_SUCCESS;
-}
-
-inline static grn_rc
-grn_ts_op_plus_time_float(grn_ctx *ctx, grn_ts_time lhs, grn_ts_float rhs,
-                          grn_ts_time *out) {
-  *out = (grn_ts_time)(lhs + (rhs * 1000000.0));
-  return GRN_SUCCESS;
-}
-
-inline static grn_rc
-grn_ts_op_minus_int_int(grn_ctx *ctx, grn_ts_int lhs, grn_ts_int rhs,
-                        grn_ts_int *out) {
-  *out = lhs - rhs;
-  return GRN_SUCCESS;
-}
-
-inline static grn_rc
-grn_ts_op_minus_float_float(grn_ctx *ctx, grn_ts_float lhs, grn_ts_float rhs,
-                            grn_ts_float *out) {
-  *out = lhs - rhs;
-  if (!grn_ts_float_is_valid(*out)) {
-    GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "%g - %g = %g", lhs, rhs, *out);
-  }
-  return GRN_SUCCESS;
-}
-
-inline static grn_rc
-grn_ts_op_minus_time_time(grn_ctx *ctx, grn_ts_time lhs, grn_ts_time rhs,
-                          grn_ts_float *out) {
-  *out = (lhs - rhs) * 0.000001;
-  return GRN_SUCCESS;
-}
-
-inline static grn_rc
-grn_ts_op_minus_time_int(grn_ctx *ctx, grn_ts_time lhs, grn_ts_int rhs,
-                         grn_ts_time *out) {
-  *out = lhs - (rhs * 1000000);
-  return GRN_SUCCESS;
-}
-
-inline static grn_rc
-grn_ts_op_minus_time_float(grn_ctx *ctx, grn_ts_time lhs, grn_ts_float rhs,
-                           grn_ts_time *out) {
-  *out = lhs - (grn_ts_int)(rhs * 1000000.0);
-  return GRN_SUCCESS;
-}
-
-inline static grn_rc
-grn_ts_op_multiplication_int_int(grn_ctx *ctx, grn_ts_int lhs, grn_ts_int rhs,
-                                 grn_ts_int *out) {
-  *out = lhs * rhs;
-  return GRN_SUCCESS;
-}
-
-inline static grn_rc
-grn_ts_op_multiplication_float_float(grn_ctx *ctx, grn_ts_float lhs,
-                                     grn_ts_float rhs, grn_ts_float *out) {
-  *out = lhs * rhs;
-  if (!grn_ts_float_is_valid(*out)) {
-    GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "%g * %g = %g", lhs, rhs, *out);
-  }
-  return GRN_SUCCESS;
-}
-
-inline static grn_rc
-grn_ts_op_division_int_int(grn_ctx *ctx, grn_ts_int lhs, grn_ts_int rhs,
-                           grn_ts_int *out) {
-  if (!rhs) {
-    GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT,
-                      "%ld / %ld causes division by zero",
-                      lhs, rhs);
-  }
-  *out = (rhs != -1) ? (lhs / rhs) : -lhs;
-  return GRN_SUCCESS;
-}
-
-inline static grn_rc
-grn_ts_op_division_float_float(grn_ctx *ctx, grn_ts_float lhs,
-                               grn_ts_float rhs, grn_ts_float *out) {
-  *out = lhs / rhs;
-  if (!grn_ts_float_is_valid(*out)) {
-    GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "%g / %g = %g", lhs, rhs, *out);
-  }
-  return GRN_SUCCESS;
-}
-
-inline static grn_rc
-grn_ts_op_modulus_int_int(grn_ctx *ctx, grn_ts_int lhs, grn_ts_int rhs,
-                          grn_ts_int *out) {
-  if (!rhs) {
-    GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT,
-                      "%ld %% %ld causes division by zero",
-                      lhs, rhs);
-  }
-  *out = (rhs != -1) ? (lhs % rhs) : -lhs;
-  return GRN_SUCCESS;
-}
-
-inline static grn_rc
-grn_ts_op_modulus_float_float(grn_ctx *ctx, grn_ts_float lhs, grn_ts_float rhs,
-                              grn_ts_float *out) {
-  *out = fmod(lhs, rhs);
-  if (!grn_ts_float_is_valid(*out)) {
-    GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "%g %% %g = %g", lhs, rhs, *out);
-  }
-  return GRN_SUCCESS;
-}
-
-/*-------------------------------------------------------------
- * Groonga objects.
- */
-
-/* grn_ts_obj_increment_ref_count() increments an object reference count. */
-static grn_rc
-grn_ts_obj_increment_ref_count(grn_ctx *ctx, grn_obj *obj) {
-  grn_id id = grn_obj_id(ctx, obj);
-  grn_obj *obj_clone = grn_ctx_at(ctx, id);
-  if (!obj_clone) {
-    GRN_TS_ERR_RETURN(GRN_UNKNOWN_ERROR, "grn_ctx_at failed: %d", id);
-  }
-  if (obj_clone != obj) {
-    grn_obj_unlink(ctx, obj_clone);
-    GRN_TS_ERR_RETURN(GRN_UNKNOWN_ERROR, "wrong object: %p != %p",
-                      obj, obj_clone);
-  }
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_obj_is_table() returns whether or not an object is a table. */
-static grn_ts_bool
-grn_ts_obj_is_table(grn_ctx *ctx, grn_obj *obj) {
-  return grn_obj_is_table(ctx, obj);
+/* grn_ts_obj_is_table() returns whether or not an object is a table. */
+static grn_ts_bool
+grn_ts_obj_is_table(grn_ctx *ctx, grn_obj *obj) {
+  return grn_obj_is_table(ctx, obj);
 }
 
 /* grn_ts_obj_is_column() returns whether or not an object is a column. */
@@ -1138,3621 +276,6 @@ grn_ts_obj_is_column(grn_ctx *ctx, grn_obj *obj) {
   }
 }
 
-/*
- * grn_ts_ja_get_value() gets a value from ja and writes it to buf. Note the a
- * value is appended to the end of buf.
- */
-static grn_rc
-grn_ts_ja_get_value(grn_ctx *ctx, grn_ja *ja, grn_ts_id id,
-                    grn_ts_buf *buf, size_t *value_size) {
-  grn_rc rc;
-  uint32_t size;
-  grn_io_win iw;
-  char *ptr = (char *)grn_ja_ref(ctx, ja, id, &iw, &size);
-  if (!ptr) {
-    if (value_size) {
-      *value_size = 0;
-    }
-    return GRN_SUCCESS;
-  }
-  rc = grn_ts_buf_write(ctx, buf, ptr, size);
-  grn_ja_unref(ctx, &iw);
-  if (rc != GRN_SUCCESS) {
-    return rc;
-  }
-  if (value_size) {
-    *value_size = size;
-  }
-  return GRN_SUCCESS;
-}
-
-#define GRN_TS_TABLE_GET_KEY(type)\
-  uint32_t key_size;\
-  const void *key_ptr = _grn_ ## type ## _key(ctx, type, id, &key_size);\
-  if (!key_ptr) {\
-    GRN_TS_ERR_RETURN(GRN_UNKNOWN_ERROR, "_grn_" #type "_key failed: %u", id);\
-  }\
-/* grn_ts_hash_get_bool_key() gets a reference to a key (_key). */
-static grn_rc
-grn_ts_hash_get_bool_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id,
-                         grn_ts_bool *key) {
-  GRN_TS_TABLE_GET_KEY(hash)
-  *key = *(const grn_ts_bool *)key_ptr;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_hash_get_int8_key() gets a reference to a key (_key). */
-static grn_rc
-grn_ts_hash_get_int8_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id,
-                         grn_ts_int *key) {
-  GRN_TS_TABLE_GET_KEY(hash)
-  *key = *(const int8_t *)key_ptr;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_hash_get_int16_key() gets a reference to a key (_key). */
-static grn_rc
-grn_ts_hash_get_int16_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id,
-                          grn_ts_int *key) {
-  GRN_TS_TABLE_GET_KEY(hash)
-  *key = *(const int16_t *)key_ptr;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_hash_get_int32_key() gets a reference to a key (_key). */
-static grn_rc
-grn_ts_hash_get_int32_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id,
-                          grn_ts_int *key) {
-  GRN_TS_TABLE_GET_KEY(hash)
-  *key = *(const int32_t *)key_ptr;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_hash_get_int64_key() gets a reference to a key (_key). */
-static grn_rc
-grn_ts_hash_get_int64_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id,
-                          grn_ts_int *key) {
-  GRN_TS_TABLE_GET_KEY(hash)
-  *key = *(const int64_t *)key_ptr;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_hash_get_uint8_key() gets a reference to a key (_key). */
-static grn_rc
-grn_ts_hash_get_uint8_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id,
-                          grn_ts_int *key) {
-  GRN_TS_TABLE_GET_KEY(hash)
-  *key = *(const uint8_t *)key_ptr;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_hash_get_uint16_key() gets a reference to a key (_key). */
-static grn_rc
-grn_ts_hash_get_uint16_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id,
-                           grn_ts_int *key) {
-  GRN_TS_TABLE_GET_KEY(hash)
-  *key = *(const uint16_t *)key_ptr;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_hash_get_uint32_key() gets a reference to a key (_key). */
-static grn_rc
-grn_ts_hash_get_uint32_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id,
-                           grn_ts_int *key) {
-  GRN_TS_TABLE_GET_KEY(hash)
-  *key = *(const uint32_t *)key_ptr;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_hash_get_uint64_key() gets a reference to a key (_key). */
-static grn_rc
-grn_ts_hash_get_uint64_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id,
-                           grn_ts_int *key) {
-  GRN_TS_TABLE_GET_KEY(hash)
-  *key = (grn_ts_int)*(const uint64_t *)key_ptr;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_hash_get_float_key() gets a reference to a key (_key). */
-static grn_rc
-grn_ts_hash_get_float_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id,
-                          grn_ts_float *key) {
-  GRN_TS_TABLE_GET_KEY(hash)
-  *key = *(const grn_ts_float *)key_ptr;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_hash_get_time_key() gets a reference to a key (_key). */
-static grn_rc
-grn_ts_hash_get_time_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id,
-                         grn_ts_time *key) {
-  GRN_TS_TABLE_GET_KEY(hash)
-  *key = *(const grn_ts_time *)key_ptr;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_hash_get_geo_key() gets a reference to a key (_key). */
-static grn_rc
-grn_ts_hash_get_geo_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id,
-                        grn_ts_geo *key) {
-  GRN_TS_TABLE_GET_KEY(hash)
-  *key = *(const grn_ts_geo *)key_ptr;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_hash_get_text_key() gets a reference to a key (_key). */
-static grn_rc
-grn_ts_hash_get_text_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id,
-                         grn_ts_text *key) {
-  GRN_TS_TABLE_GET_KEY(hash)
-  key->ptr = key_ptr;
-  key->size = key_size;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_hash_get_ref_key() gets a reference to a key (_key). */
-static grn_rc
-grn_ts_hash_get_ref_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id,
-                        grn_ts_ref *key) {
-  GRN_TS_TABLE_GET_KEY(hash)
-  key->id = *(const grn_ts_id *)key_ptr;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_pat_get_bool_key() gets a reference to a key (_key). */
-static grn_rc
-grn_ts_pat_get_bool_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id,
-                        grn_ts_bool *key) {
-  GRN_TS_TABLE_GET_KEY(pat)
-  *key = *(const grn_ts_bool *)key_ptr;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_pat_get_int8_key() gets a reference to a key (_key). */
-static grn_rc
-grn_ts_pat_get_int8_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id,
-                        grn_ts_int *key) {
-  int8_t tmp;
-  GRN_TS_TABLE_GET_KEY(pat)
-  grn_ntohi(&tmp, key_ptr, sizeof(tmp));
-  *key = tmp;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_pat_get_int16_key() gets a reference to a key (_key). */
-static grn_rc
-grn_ts_pat_get_int16_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id,
-                         grn_ts_int *key) {
-  int16_t tmp;
-  GRN_TS_TABLE_GET_KEY(pat)
-  grn_ntohi(&tmp, key_ptr, sizeof(tmp));
-  *key = tmp;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_pat_get_int32_key() gets a reference to a key (_key). */
-static grn_rc
-grn_ts_pat_get_int32_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id,
-                         grn_ts_int *key) {
-  int32_t tmp;
-  GRN_TS_TABLE_GET_KEY(pat)
-  grn_ntohi(&tmp, key_ptr, sizeof(tmp));
-  *key = tmp;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_pat_get_int64_key() gets a reference to a key (_key). */
-static grn_rc
-grn_ts_pat_get_int64_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id,
-                         grn_ts_int *key) {
-  GRN_TS_TABLE_GET_KEY(pat)
-  grn_ntohi(key, key_ptr, sizeof(grn_ts_int));
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_pat_get_uint8_key() gets a reference to a key (_key). */
-static grn_rc
-grn_ts_pat_get_uint8_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id,
-                         grn_ts_int *key) {
-  GRN_TS_TABLE_GET_KEY(pat)
-  *key = *(const uint8_t *)key_ptr;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_pat_get_uint16_key() gets a reference to a key (_key). */
-static grn_rc
-grn_ts_pat_get_uint16_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id,
-                          grn_ts_int *key) {
-  uint16_t tmp;
-  GRN_TS_TABLE_GET_KEY(pat)
-  grn_ntoh(&tmp, key_ptr, sizeof(tmp));
-  *key = tmp;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_pat_get_uint32_key() gets a reference to a key (_key). */
-static grn_rc
-grn_ts_pat_get_uint32_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id,
-                          grn_ts_int *key) {
-  uint32_t tmp;
-  GRN_TS_TABLE_GET_KEY(pat)
-  grn_ntoh(&tmp, key_ptr, sizeof(tmp));
-  *key = tmp;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_pat_get_uint64_key() gets a reference to a key (_key). */
-static grn_rc
-grn_ts_pat_get_uint64_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id,
-                          grn_ts_int *key) {
-  GRN_TS_TABLE_GET_KEY(pat)
-  grn_ntoh(key, key_ptr, sizeof(grn_ts_int));
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_pat_get_float_key() gets a reference to a key (_key). */
-static grn_rc
-grn_ts_pat_get_float_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id,
-                         grn_ts_float *key) {
-  int64_t tmp;
-  GRN_TS_TABLE_GET_KEY(pat)
-  grn_ntoh(&tmp, key_ptr, sizeof(tmp));
-  tmp ^= (((tmp ^ ((int64_t)1 << 63)) >> 63) | ((int64_t)1 << 63));
-  *(int64_t *)key = tmp;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_pat_get_time_key() gets a reference to a key (_key). */
-static grn_rc
-grn_ts_pat_get_time_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id,
-                        grn_ts_time *key) {
-  GRN_TS_TABLE_GET_KEY(pat)
-  grn_ntohi(key, key_ptr, sizeof(grn_ts_time));
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_pat_get_geo_key() gets a reference to a key (_key). */
-static grn_rc
-grn_ts_pat_get_geo_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id,
-                       grn_ts_geo *key) {
-  GRN_TS_TABLE_GET_KEY(pat)
-  grn_ntog(key, key_ptr, sizeof(grn_ts_geo));
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_pat_get_text_key() gets a reference to a key (_key). */
-static grn_rc
-grn_ts_pat_get_text_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id,
-                        grn_ts_text *key) {
-  GRN_TS_TABLE_GET_KEY(pat)
-  key->ptr = key_ptr;
-  key->size = key_size;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_pat_get_ref_key() gets a reference to a key (_key). */
-static grn_rc
-grn_ts_pat_get_ref_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id,
-                       grn_ts_ref *key) {
-  GRN_TS_TABLE_GET_KEY(pat)
-  grn_ntoh(&key->id, key_ptr, sizeof(key->id));
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_dat_get_text_key() gets a reference to a key (_key). */
-static grn_rc
-grn_ts_dat_get_text_key(grn_ctx *ctx, grn_dat *dat, grn_ts_id id,
-                        grn_ts_text *key) {
-  GRN_TS_TABLE_GET_KEY(dat)
-  key->ptr = key_ptr;
-  key->size = key_size;
-  return GRN_SUCCESS;
-}
-#undef GRN_TS_TABLE_GET_KEY
-
-/* grn_ts_table_has_key() returns whether or not a table has _key. */
-static grn_ts_bool
-grn_ts_table_has_key(grn_ctx *ctx, grn_obj *table) {
-  switch (table->header.type) {
-    case GRN_TABLE_HASH_KEY:
-    case GRN_TABLE_PAT_KEY:
-    case GRN_TABLE_DAT_KEY: {
-      return GRN_TRUE;
-    }
-    default: {
-      return GRN_FALSE;
-    }
-  }
-}
-
-/* grn_ts_table_has_value() returns whether or not a table has _value. */
-static grn_ts_bool
-grn_ts_table_has_value(grn_ctx *ctx, grn_obj *table) {
-  return DB_OBJ(table)->range != GRN_DB_VOID;
-}
-
-/*
- * grn_ts_table_get_value() gets a reference to a value (_value). On failure,
- * this function returns NULL.
- */
-static const void *
-grn_ts_table_get_value(grn_ctx *ctx, grn_obj *table, grn_ts_id id) {
-  switch (table->header.type) {
-    case GRN_TABLE_HASH_KEY: {
-      uint32_t size;
-      return grn_hash_get_value_(ctx, (grn_hash *)table, id, &size);
-    }
-    case GRN_TABLE_PAT_KEY: {
-      uint32_t size;
-      return grn_pat_get_value_(ctx, (grn_pat *)table, id, &size);
-    }
-    /* GRN_TABLE_DAT_KEY does not support _value. */
-    case GRN_TABLE_NO_KEY: {
-      return _grn_array_get_value(ctx, (grn_array *)table, id);
-    }
-    default: {
-      return NULL;
-    }
-  }
-}
-
-/*-------------------------------------------------------------
- * grn_ts_expr_id_node.
- */
-
-typedef struct {
-  GRN_TS_EXPR_NODE_COMMON_MEMBERS
-} grn_ts_expr_id_node;
-
-/* grn_ts_expr_id_node_init() initializes a node. */
-static void
-grn_ts_expr_id_node_init(grn_ctx *ctx, grn_ts_expr_id_node *node) {
-  memset(node, 0, sizeof(*node));
-  node->type = GRN_TS_EXPR_ID_NODE;
-  node->data_kind = GRN_TS_INT;
-  node->data_type = GRN_DB_UINT32;
-}
-
-/* grn_ts_expr_id_node_fin() finalizes a node. */
-static void
-grn_ts_expr_id_node_fin(grn_ctx *ctx, grn_ts_expr_id_node *node) {
-  /* Nothing to do. */
-}
-
-/* grn_ts_expr_id_node_open() creates a node associated with IDs (_id). */
-static grn_rc
-grn_ts_expr_id_node_open(grn_ctx *ctx, grn_ts_expr_node **node) {
-  grn_ts_expr_id_node *new_node = GRN_MALLOCN(grn_ts_expr_id_node, 1);
-  if (!new_node) {
-    GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %zu x 1",
-                      sizeof(grn_ts_expr_id_node));
-  }
-  grn_ts_expr_id_node_init(ctx, new_node);
-  *node = (grn_ts_expr_node *)new_node;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_expr_id_node_close() destroys a node. */
-static void
-grn_ts_expr_id_node_close(grn_ctx *ctx, grn_ts_expr_id_node *node) {
-  grn_ts_expr_id_node_fin(ctx, node);
-  GRN_FREE(node);
-}
-
-/* grn_ts_expr_id_node_evaluate() outputs IDs. */
-static grn_rc
-grn_ts_expr_id_node_evaluate(grn_ctx *ctx, grn_ts_expr_id_node *node,
-                             const grn_ts_record *in, size_t n_in, void *out) {
-  size_t i;
-  grn_ts_int *out_ptr = (grn_ts_int *)out;
-  for (i = 0; i < n_in; i++) {
-    out_ptr[i] = (grn_ts_int)in[i].id;
-  }
-  return GRN_SUCCESS;
-}
-
-/*-------------------------------------------------------------
- * grn_ts_expr_score_node.
- */
-
-typedef struct {
-  GRN_TS_EXPR_NODE_COMMON_MEMBERS
-} grn_ts_expr_score_node;
-
-/* grn_ts_expr_score_node_init() initializes a node. */
-static void
-grn_ts_expr_score_node_init(grn_ctx *ctx, grn_ts_expr_score_node *node) {
-  memset(node, 0, sizeof(*node));
-  node->type = GRN_TS_EXPR_SCORE_NODE;
-  node->data_kind = GRN_TS_FLOAT;
-  node->data_type = GRN_DB_FLOAT;
-}
-
-/* grn_ts_expr_score_node_fin() finalizes a node. */
-static void
-grn_ts_expr_score_node_fin(grn_ctx *ctx, grn_ts_expr_score_node *node) {
-  /* Nothing to do. */
-}
-
-/*
- * grn_ts_expr_score_node_open() creates a node associated with scores
- * (_score).
- */
-static grn_rc
-grn_ts_expr_score_node_open(grn_ctx *ctx, grn_ts_expr_node **node) {
-  grn_ts_expr_score_node *new_node = GRN_MALLOCN(grn_ts_expr_score_node, 1);
-  if (!new_node) {
-    GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %zu x 1",
-                      sizeof(grn_ts_expr_score_node));
-  }
-  grn_ts_expr_score_node_init(ctx, new_node);
-  *node = (grn_ts_expr_node *)new_node;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_expr_score_node_close() destroys a node. */
-static void
-grn_ts_expr_score_node_close(grn_ctx *ctx, grn_ts_expr_score_node *node) {
-  grn_ts_expr_score_node_fin(ctx, node);
-  GRN_FREE(node);
-}
-
-/* grn_ts_expr_score_node_evaluate() outputs scores. */
-static grn_rc
-grn_ts_expr_score_node_evaluate(grn_ctx *ctx, grn_ts_expr_score_node *node,
-                                const grn_ts_record *in, size_t n_in,
-                                void *out) {
-  size_t i;
-  grn_ts_float *out_ptr = (grn_ts_float *)out;
-  for (i = 0; i < n_in; i++) {
-    out_ptr[i] = (grn_ts_float)in[i].score;
-  }
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_expr_score_node_adjust() does nothing. */
-static grn_rc
-grn_ts_expr_score_node_adjust(grn_ctx *ctx, grn_ts_expr_score_node *node,
-                              grn_ts_record *io, size_t n_io) {
-  /* Nothing to do. */
-  return GRN_SUCCESS;
-}
-
-/*-------------------------------------------------------------
- * grn_ts_expr_key_node.
- */
-
-typedef struct {
-  GRN_TS_EXPR_NODE_COMMON_MEMBERS
-  grn_obj *table;
-  grn_ts_buf buf;
-} grn_ts_expr_key_node;
-
-/* grn_ts_expr_key_node_init() initializes a node. */
-static void
-grn_ts_expr_key_node_init(grn_ctx *ctx, grn_ts_expr_key_node *node) {
-  memset(node, 0, sizeof(*node));
-  node->type = GRN_TS_EXPR_KEY_NODE;
-  node->table = NULL;
-  grn_ts_buf_init(ctx, &node->buf);
-}
-
-/* grn_ts_expr_key_node_fin() finalizes a node. */
-static void
-grn_ts_expr_key_node_fin(grn_ctx *ctx, grn_ts_expr_key_node *node) {
-  grn_ts_buf_fin(ctx, &node->buf);
-  if (node->table) {
-    grn_obj_unlink(ctx, node->table);
-  }
-}
-
-/* grn_ts_expr_key_node_open() creates a node associated with keys (_key). */
-static grn_rc
-grn_ts_expr_key_node_open(grn_ctx *ctx, grn_obj *table,
-                          grn_ts_expr_node **node) {
-  grn_rc rc;
-  grn_ts_expr_key_node *new_node;
-  if (!grn_ts_table_has_key(ctx, table)) {
-    GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "the table has no _key");
-  }
-  new_node = GRN_MALLOCN(grn_ts_expr_key_node, 1);
-  if (!new_node) {
-    GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %zu x 1",
-                      sizeof(grn_ts_expr_key_node));
-  }
-  grn_ts_expr_key_node_init(ctx, new_node);
-  rc = grn_ts_obj_increment_ref_count(ctx, table);
-  if (rc != GRN_SUCCESS) {
-    grn_ts_expr_key_node_fin(ctx, new_node);
-    GRN_FREE(new_node);
-    return rc;
-  }
-  new_node->data_kind = grn_ts_data_type_to_kind(table->header.domain);
-  new_node->data_type = table->header.domain;
-  new_node->table = table;
-  *node = (grn_ts_expr_node *)new_node;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_expr_key_node_close() destroys a node. */
-static void
-grn_ts_expr_key_node_close(grn_ctx *ctx, grn_ts_expr_key_node *node) {
-  grn_ts_expr_key_node_fin(ctx, node);
-  GRN_FREE(node);
-}
-
-#define GRN_TS_EXPR_KEY_NODE_EVALUATE_CASE(table, KIND, kind)\
-  case GRN_TS_ ## KIND: {\
-    grn_ts_ ## kind *out_ptr = (grn_ts_ ## kind *)out;\
-    for (i = 0; i < n_in; i++) {\
-      rc = grn_ts_ ## table ## _get_ ## kind ## _key(ctx, table, in[i].id,\
-                                                     &out_ptr[i]);\
-      if (rc != GRN_SUCCESS) {\
-        out_ptr[i] = grn_ts_ ## kind ## _zero();\
-      }\
-    }\
-    return GRN_SUCCESS;\
-  }
-#define GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(table, TYPE, type)\
-  case GRN_DB_ ## TYPE: {\
-    grn_ts_int *out_ptr = (grn_ts_int *)out;\
-    for (i = 0; i < n_in; i++) {\
-      rc = grn_ts_ ## table ## _get_ ## type ## _key(ctx, table, in[i].id,\
-                                                     &out_ptr[i]);\
-      if (rc != GRN_SUCCESS) {\
-        out_ptr[i] = grn_ts_int_zero();\
-      }\
-    }\
-    return GRN_SUCCESS;\
-  }
-#define GRN_TS_EXPR_KEY_NODE_EVALUATE_TEXT_CASE(table)\
-  case GRN_TS_TEXT: {\
-    char *buf_ptr;\
-    grn_ts_text *out_ptr = (grn_ts_text *)out;\
-    node->buf.pos = 0;\
-    for (i = 0; i < n_in; i++) {\
-      grn_ts_text key;\
-      rc = grn_ts_ ## table ## _get_text_key(ctx, table, in[i].id, &key);\
-      if (rc != GRN_SUCCESS) {\
-        key = grn_ts_text_zero();\
-      }\
-      rc = grn_ts_buf_write(ctx, &node->buf, key.ptr, key.size);\
-      if (rc != GRN_SUCCESS) {\
-        return rc;\
-      }\
-      out_ptr[i].size = key.size;\
-    }\
-    buf_ptr = (char *)node->buf.ptr;\
-    for (i = 0; i < n_in; i++) {\
-      out_ptr[i].ptr = buf_ptr;\
-      buf_ptr += out_ptr[i].size;\
-    }\
-    return GRN_SUCCESS;\
-  }
-#define GRN_TS_EXPR_KEY_NODE_EVALUATE_REF_CASE(table)\
-  case GRN_TS_REF: {\
-    grn_ts_ref *out_ptr = (grn_ts_ref *)out;\
-    for (i = 0; i < n_in; i++) {\
-      rc = grn_ts_ ## table ## _get_ref_key(ctx, table, in[i].id,\
-                                            &out_ptr[i]);\
-      if (rc != GRN_SUCCESS) {\
-        out_ptr[i] = grn_ts_ref_zero();\
-      }\
-      out_ptr[i].score = in[i].score;\
-    }\
-    return GRN_SUCCESS;\
-  }
-/* grn_ts_expr_key_node_evaluate() outputs keys. */
-static grn_rc
-grn_ts_expr_key_node_evaluate(grn_ctx *ctx, grn_ts_expr_key_node *node,
-                              const grn_ts_record *in, size_t n_in,
-                              void *out) {
-  size_t i;
-  grn_rc rc;
-  switch (node->table->header.type) {
-    case GRN_TABLE_HASH_KEY: {
-      grn_hash *hash = (grn_hash *)node->table;
-      switch (node->data_kind) {
-        GRN_TS_EXPR_KEY_NODE_EVALUATE_CASE(hash, BOOL, bool)
-        case GRN_TS_INT: {
-          switch (node->data_type) {
-            GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(hash, INT8, int8)
-            GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(hash, INT16, int16)
-            GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(hash, INT32, int32)
-            GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(hash, INT64, int64)
-            GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(hash, UINT8, uint8)
-            GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(hash, UINT16, uint16)
-            GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(hash, UINT32, uint32)
-            GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(hash, UINT64, uint64)
-          }
-        }
-        GRN_TS_EXPR_KEY_NODE_EVALUATE_CASE(hash, FLOAT, float)
-        GRN_TS_EXPR_KEY_NODE_EVALUATE_CASE(hash, TIME, time)
-        GRN_TS_EXPR_KEY_NODE_EVALUATE_TEXT_CASE(hash)
-        GRN_TS_EXPR_KEY_NODE_EVALUATE_CASE(hash, GEO, geo)
-        GRN_TS_EXPR_KEY_NODE_EVALUATE_REF_CASE(hash)
-        default: {
-          GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d",
-                            node->data_kind);
-        }
-      }
-    }
-    case GRN_TABLE_PAT_KEY: {
-      grn_pat *pat = (grn_pat *)node->table;
-      switch (node->data_kind) {
-        GRN_TS_EXPR_KEY_NODE_EVALUATE_CASE(pat, BOOL, bool)
-        case GRN_TS_INT: {
-          switch (node->data_type) {
-            GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(pat, INT8, int8)
-            GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(pat, INT16, int16)
-            GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(pat, INT32, int32)
-            GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(pat, INT64, int64)
-            GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(pat, UINT8, uint8)
-            GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(pat, UINT16, uint16)
-            GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(pat, UINT32, uint32)
-            GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(pat, UINT64, uint64)
-          }
-        }
-        GRN_TS_EXPR_KEY_NODE_EVALUATE_CASE(pat, FLOAT, float)
-        GRN_TS_EXPR_KEY_NODE_EVALUATE_CASE(pat, TIME, time)
-        GRN_TS_EXPR_KEY_NODE_EVALUATE_TEXT_CASE(pat)
-        GRN_TS_EXPR_KEY_NODE_EVALUATE_CASE(pat, GEO, geo)
-        GRN_TS_EXPR_KEY_NODE_EVALUATE_REF_CASE(pat)
-        default: {
-          GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d",
-                            node->data_kind);
-        }
-      }
-    }
-    case GRN_TABLE_DAT_KEY: {
-      grn_dat *dat = (grn_dat *)node->table;
-      switch (node->data_kind) {
-        GRN_TS_EXPR_KEY_NODE_EVALUATE_TEXT_CASE(dat)
-        /* GRN_TABLE_DAT_KEY supports only Text. */
-        default: {
-          GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d",
-                            node->data_kind);
-        }
-      }
-    }
-    /* GRN_TABLE_NO_KEY doesn't support _key. */
-    default: {
-      GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid table type: %d",
-                        node->table->header.type);
-    }
-  }
-}
-#undef GRN_TS_EXPR_KEY_NODE_EVALUATE_REF_CASE
-#undef GRN_TS_EXPR_KEY_NODE_EVALUATE_TEXT_CASE
-#undef GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE
-#undef GRN_TS_EXPR_KEY_NODE_EVALUATE_CASE
-
-/* grn_ts_expr_key_node_filter() filters records. */
-static grn_rc
-grn_ts_expr_key_node_filter(grn_ctx *ctx, grn_ts_expr_key_node *node,
-                            grn_ts_record *in, size_t n_in,
-                            grn_ts_record *out, size_t *n_out) {
-  size_t i, count;
-  grn_ts_bool key;
-  switch (node->table->header.type) {
-    case GRN_TABLE_HASH_KEY: {
-      grn_hash *hash = (grn_hash *)node->table;
-      for (i = 0, count = 0; i < n_in; i++) {
-        grn_rc rc = grn_ts_hash_get_bool_key(ctx, hash, in[i].id, &key);
-        if (rc != GRN_SUCCESS) {
-          key = grn_ts_bool_zero();
-        }
-        if (key) {
-          out[count++] = in[i];
-        }
-      }
-      *n_out = count;
-      return GRN_SUCCESS;
-    }
-    case GRN_TABLE_PAT_KEY: {
-      grn_pat *pat = (grn_pat *)node->table;
-      for (i = 0, count = 0; i < n_in; i++) {
-        grn_rc rc = grn_ts_pat_get_bool_key(ctx, pat, in[i].id, &key);
-        if (rc != GRN_SUCCESS) {
-          key = grn_ts_bool_zero();
-        }
-        if (key) {
-          out[count++] = in[i];
-        }
-      }
-      *n_out = count;
-      return GRN_SUCCESS;
-    }
-    /* GRN_TABLE_DAT_KEY and GRN_TABLE_NO_KEY don't support a Bool key. */
-    default: {
-      GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid table type: %d",
-                        node->table->header.type);
-    }
-  }
-}
-
-/* grn_ts_expr_key_node_adjust() updates scores. */
-static grn_rc
-grn_ts_expr_key_node_adjust(grn_ctx *ctx, grn_ts_expr_key_node *node,
-                            grn_ts_record *io, size_t n_io) {
-  size_t i;
-  grn_ts_float key;
-  switch (node->table->header.type) {
-    case GRN_TABLE_HASH_KEY: {
-      grn_hash *hash = (grn_hash *)node->table;
-      for (i = 0; i < n_io; i++) {
-        grn_rc rc = grn_ts_hash_get_float_key(ctx, hash, io[i].id, &key);
-        if (rc != GRN_SUCCESS) {
-          key = grn_ts_float_zero();
-        }
-        io[i].score = (grn_ts_score)key;
-      }
-      return GRN_SUCCESS;
-    }
-    case GRN_TABLE_PAT_KEY: {
-      grn_pat *pat = (grn_pat *)node->table;
-      for (i = 0; i < n_io; i++) {
-        grn_rc rc = grn_ts_pat_get_float_key(ctx, pat, io[i].id, &key);
-        if (rc != GRN_SUCCESS) {
-          key = grn_ts_float_zero();
-        }
-        io[i].score = (grn_ts_score)key;
-      }
-      return GRN_SUCCESS;
-    }
-    /* GRN_TABLE_DAT_KEY and GRN_TABLE_NO_KEY don't support a Float key. */
-    default: {
-      GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid table type: %d",
-                        node->table->header.type);
-    }
-  }
-}
-
-/*-------------------------------------------------------------
- * grn_ts_expr_value_node.
- */
-
-typedef struct {
-  GRN_TS_EXPR_NODE_COMMON_MEMBERS
-  grn_obj *table;
-} grn_ts_expr_value_node;
-
-/* grn_ts_expr_value_node_init() initializes a node. */
-static void
-grn_ts_expr_value_node_init(grn_ctx *ctx, grn_ts_expr_value_node *node) {
-  memset(node, 0, sizeof(*node));
-  node->type = GRN_TS_EXPR_VALUE_NODE;
-  node->table = NULL;
-}
-
-/* grn_ts_expr_value_node_fin() finalizes a node. */
-static void
-grn_ts_expr_value_node_fin(grn_ctx *ctx, grn_ts_expr_value_node *node) {
-  if (node->table) {
-    grn_obj_unlink(ctx, node->table);
-  }
-}
-
-/*
- * grn_ts_expr_value_node_open() creates a node associated with values
- * (_value).
- */
-static grn_rc
-grn_ts_expr_value_node_open(grn_ctx *ctx, grn_obj *table,
-                            grn_ts_expr_node **node) {
-  grn_rc rc;
-  grn_ts_expr_value_node *new_node;
-  if (!grn_ts_table_has_value(ctx, table)) {
-    GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "table has no _value");
-  }
-  new_node = GRN_MALLOCN(grn_ts_expr_value_node, 1);
-  if (!new_node) {
-    GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %zu x 1",
-                      sizeof(grn_ts_expr_value_node));
-  }
-  grn_ts_expr_value_node_init(ctx, new_node);
-  rc = grn_ts_obj_increment_ref_count(ctx, table);
-  if (rc != GRN_SUCCESS) {
-    GRN_FREE(new_node);
-    return rc;
-  }
-  new_node->data_kind = grn_ts_data_type_to_kind(DB_OBJ(table)->range);
-  new_node->data_type = DB_OBJ(table)->range;
-  new_node->table = table;
-  *node = (grn_ts_expr_node *)new_node;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_expr_value_node_close() destroys a node. */
-static void
-grn_ts_expr_value_node_close(grn_ctx *ctx, grn_ts_expr_value_node *node) {
-  grn_ts_expr_value_node_fin(ctx, node);
-  GRN_FREE(node);
-}
-
-#define GRN_TS_EXPR_VALUE_NODE_EVALUATE_CASE(KIND, kind)\
-  case GRN_TS_ ## KIND: {\
-    size_t i;\
-    grn_ts_ ## kind *out_ptr = (grn_ts_ ## kind *)out;\
-    for (i = 0; i < n_in; i++) {\
-      const void *ptr = grn_ts_table_get_value(ctx, node->table, in[i].id);\
-      if (ptr) {\
-        out_ptr[i] = *(const grn_ts_ ## kind *)ptr;\
-      } else {\
-        out_ptr[i] = grn_ts_ ## kind ## _zero();\
-      }\
-    }\
-    return GRN_SUCCESS;\
-  }
-#define GRN_TS_EXPR_VALUE_NODE_EVALUATE_INT_CASE(TYPE, type)\
-  case GRN_DB_ ## TYPE: {\
-    size_t i;\
-    grn_ts_int *out_ptr = (grn_ts_int *)out;\
-    for (i = 0; i < n_in; i++) {\
-      const void *ptr = grn_ts_table_get_value(ctx, node->table, in[i].id);\
-      if (ptr) {\
-        out_ptr[i] = (grn_ts_int)*(const type ## _t *)ptr;\
-      } else {\
-        out_ptr[i] = grn_ts_int_zero();\
-      }\
-    }\
-    return GRN_SUCCESS;\
-  }
-/* grn_ts_expr_value_node_evaluate() outputs values. */
-static grn_rc
-grn_ts_expr_value_node_evaluate(grn_ctx *ctx, grn_ts_expr_value_node *node,
-                                const grn_ts_record *in, size_t n_in,
-                                void *out) {
-  switch (node->data_kind) {
-    GRN_TS_EXPR_VALUE_NODE_EVALUATE_CASE(BOOL, bool)
-    case GRN_TS_INT: {
-      switch (node->data_type) {
-        GRN_TS_EXPR_VALUE_NODE_EVALUATE_INT_CASE(INT8, int8)
-        GRN_TS_EXPR_VALUE_NODE_EVALUATE_INT_CASE(INT16, int16)
-        GRN_TS_EXPR_VALUE_NODE_EVALUATE_INT_CASE(INT32, int32)
-        GRN_TS_EXPR_VALUE_NODE_EVALUATE_INT_CASE(INT64, int64)
-        GRN_TS_EXPR_VALUE_NODE_EVALUATE_INT_CASE(UINT8, uint8)
-        GRN_TS_EXPR_VALUE_NODE_EVALUATE_INT_CASE(UINT16, uint16)
-        GRN_TS_EXPR_VALUE_NODE_EVALUATE_INT_CASE(UINT32, uint32)
-        GRN_TS_EXPR_VALUE_NODE_EVALUATE_INT_CASE(UINT64, uint64)
-        default: {
-          GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data type: %d",
-                            node->data_type);
-        }
-      }
-    }
-    GRN_TS_EXPR_VALUE_NODE_EVALUATE_CASE(FLOAT, float)
-    GRN_TS_EXPR_VALUE_NODE_EVALUATE_CASE(TIME, time)
-    GRN_TS_EXPR_VALUE_NODE_EVALUATE_CASE(GEO, geo)
-    case GRN_TS_REF: {
-      size_t i;
-      grn_ts_ref *out_ptr = (grn_ts_ref *)out;
-      for (i = 0; i < n_in; i++) {
-        const void *ptr = grn_ts_table_get_value(ctx, node->table, in[i].id);
-        if (ptr) {
-          out_ptr[i].id = *(const grn_ts_id *)ptr;
-          out_ptr[i].score = in[i].score;
-        } else {
-          out_ptr[i] = grn_ts_ref_zero();
-        }
-      }
-      return GRN_SUCCESS;
-    }
-    default: {
-      GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d",
-                        node->data_kind);
-    }
-  }
-}
-#undef GRN_TS_EXPR_VALUE_NODE_EVALUATE_INT_CASE
-#undef GRN_TS_EXPR_VALUE_NODE_EVALUATE_CASE
-
-/* grn_ts_expr_value_node_filter() filters records. */
-static grn_rc
-grn_ts_expr_value_node_filter(grn_ctx *ctx, grn_ts_expr_value_node *node,
-                              grn_ts_record *in, size_t n_in,
-                              grn_ts_record *out, size_t *n_out) {
-  size_t i, count = 0;
-  for (i = 0; i < n_in; i++) {
-    const void *ptr = grn_ts_table_get_value(ctx, node->table, in[i].id);
-    if (ptr && *(const grn_ts_bool *)ptr) {
-      out[count++] = in[i];
-    }
-  }
-  *n_out = count;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_expr_value_node_adjust() updates scores. */
-static grn_rc
-grn_ts_expr_value_node_adjust(grn_ctx *ctx, grn_ts_expr_value_node *node,
-                              grn_ts_record *io, size_t n_io) {
-  size_t i;
-  for (i = 0; i < n_io; i++) {
-    const void *ptr = grn_ts_table_get_value(ctx, node->table, io[i].id);
-    if (ptr) {
-      io[i].score = (grn_ts_score)*(const grn_ts_float *)ptr;
-    }
-  }
-  return GRN_SUCCESS;
-}
-
-/*-------------------------------------------------------------
- * grn_ts_expr_const_node.
- */
-
-typedef struct {
-  GRN_TS_EXPR_NODE_COMMON_MEMBERS
-  grn_ts_any content;
-  grn_ts_buf text_buf;
-  grn_ts_buf vector_buf;
-} grn_ts_expr_const_node;
-
-/* grn_ts_expr_const_node_init() initializes a node. */
-static void
-grn_ts_expr_const_node_init(grn_ctx *ctx, grn_ts_expr_const_node *node) {
-  memset(node, 0, sizeof(*node));
-  node->type = GRN_TS_EXPR_CONST_NODE;
-  grn_ts_buf_init(ctx, &node->text_buf);
-  grn_ts_buf_init(ctx, &node->vector_buf);
-}
-
-/* grn_ts_expr_const_node_fin() finalizes a node. */
-static void
-grn_ts_expr_const_node_fin(grn_ctx *ctx, grn_ts_expr_const_node *node) {
-  grn_ts_buf_fin(ctx, &node->vector_buf);
-  grn_ts_buf_fin(ctx, &node->text_buf);
-}
-
-#define GRN_TS_EXPR_CONST_NODE_SET_SCALAR_CASE(KIND, kind)\
-  case GRN_TS_ ## KIND: {\
-    node->content.as_ ## kind = *(const grn_ts_ ## kind *)value;\
-    return GRN_SUCCESS;\
-  }
-/* grn_ts_expr_const_node_set_scalar() sets a scalar value. */
-static grn_rc
-grn_ts_expr_const_node_set_scalar(grn_ctx *ctx, grn_ts_expr_const_node *node,
-                                  const void *value) {
-  switch (node->data_kind) {
-    GRN_TS_EXPR_CONST_NODE_SET_SCALAR_CASE(BOOL, bool)
-    GRN_TS_EXPR_CONST_NODE_SET_SCALAR_CASE(INT, int)
-    GRN_TS_EXPR_CONST_NODE_SET_SCALAR_CASE(FLOAT, float)
-    GRN_TS_EXPR_CONST_NODE_SET_SCALAR_CASE(TIME, time)
-    case GRN_TS_TEXT: {
-      grn_ts_text text_value = *(const grn_ts_text *)value;
-      grn_rc rc = grn_ts_buf_write(ctx, &node->text_buf,
-                                   text_value.ptr, text_value.size);
-      if (rc != GRN_SUCCESS) {
-        return rc;
-      }
-      node->content.as_text.ptr = (const char *)node->text_buf.ptr;
-      node->content.as_text.size = text_value.size;
-      return GRN_SUCCESS;
-    }
-    GRN_TS_EXPR_CONST_NODE_SET_SCALAR_CASE(GEO, geo)
-    default: {
-      GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d",
-                        node->data_kind);
-    }
-  }
-}
-#undef GRN_TS_EXPR_CONST_NODE_SET_SCALAR_CASE
-
-#define GRN_TS_EXPR_CONST_NODE_SET_VECTOR_CASE(KIND, kind)\
-  case GRN_TS_ ## KIND ## _VECTOR: {\
-    grn_rc rc;\
-    size_t n_bytes;\
-    const grn_ts_ ## kind *buf_ptr;\
-    grn_ts_ ## kind ## _vector vector;\
-    vector = *(const grn_ts_ ## kind ## _vector *)value;\
-    n_bytes = sizeof(grn_ts_ ## kind) * vector.size;\
-    rc = grn_ts_buf_write(ctx, &node->vector_buf, vector.ptr, n_bytes);\
-    if (rc != GRN_SUCCESS) {\
-      return rc;\
-    }\
-    buf_ptr = (const grn_ts_ ## kind *)node->vector_buf.ptr;\
-    node->content.as_ ## kind ## _vector.ptr = buf_ptr;\
-    node->content.as_ ## kind ## _vector.size = vector.size;\
-    return GRN_SUCCESS;\
-  }
-/* grn_ts_expr_const_node_set_vector() sets a vector value. */
-static grn_rc
-grn_ts_expr_const_node_set_vector(grn_ctx *ctx, grn_ts_expr_const_node *node,
-                                  const void *value) {
-  switch (node->data_kind) {
-    GRN_TS_EXPR_CONST_NODE_SET_VECTOR_CASE(BOOL, bool)
-    GRN_TS_EXPR_CONST_NODE_SET_VECTOR_CASE(INT, int)
-    GRN_TS_EXPR_CONST_NODE_SET_VECTOR_CASE(FLOAT, float)
-    GRN_TS_EXPR_CONST_NODE_SET_VECTOR_CASE(TIME, time)
-    case GRN_TS_TEXT_VECTOR: {
-      grn_rc rc;
-      size_t i, n_bytes, offset, total_size;
-      grn_ts_text_vector vector = *(const grn_ts_text_vector *)value;
-      grn_ts_text *vector_buf;
-      char *text_buf;
-      n_bytes = sizeof(grn_ts_text) * vector.size;
-      rc = grn_ts_buf_resize(ctx, &node->vector_buf, n_bytes);
-      if (rc != GRN_SUCCESS) {
-        return rc;
-      }
-      vector_buf = (grn_ts_text *)node->vector_buf.ptr;
-      total_size = 0;
-      for (i = 0; i < vector.size; i++) {
-        total_size += vector.ptr[i].size;
-      }
-      rc = grn_ts_buf_resize(ctx, &node->text_buf, total_size);
-      if (rc != GRN_SUCCESS) {
-        return rc;
-      }
-      text_buf = (char *)node->text_buf.ptr;
-      offset = 0;
-      for (i = 0; i < vector.size; i++) {
-        grn_memcpy(text_buf + offset, vector.ptr[i].ptr, vector.ptr[i].size);
-        vector_buf[i].ptr = text_buf + offset;
-        vector_buf[i].size = vector.ptr[i].size;
-        offset += vector.ptr[i].size;
-      }
-      node->content.as_text_vector.ptr = vector_buf;
-      node->content.as_text_vector.size = vector.size;
-      return GRN_SUCCESS;
-    }
-    GRN_TS_EXPR_CONST_NODE_SET_VECTOR_CASE(GEO, geo)
-    default: {
-      GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d",
-                        node->data_kind);
-    }
-  }
-}
-#undef GRN_TS_EXPR_CONST_NODE_SET_VECTOR_CASE
-
-/* grn_ts_expr_const_node_open() creates a node associated with a const. */
-static grn_rc
-grn_ts_expr_const_node_open(grn_ctx *ctx, grn_ts_data_kind kind,
-                            const void *value, grn_ts_expr_node **node) {
-  grn_rc rc;
-  grn_ts_expr_const_node *new_node = GRN_MALLOCN(grn_ts_expr_const_node, 1);
-  if (!new_node) {
-    GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %zu x 1",
-                      sizeof(grn_ts_expr_const_node));
-  }
-  grn_ts_expr_const_node_init(ctx, new_node);
-  new_node->data_kind = kind;
-  new_node->data_type = grn_ts_data_kind_to_type(kind);
-  if (kind & GRN_TS_VECTOR_FLAG) {
-    rc = grn_ts_expr_const_node_set_vector(ctx, new_node, value);
-  } else {
-    rc = grn_ts_expr_const_node_set_scalar(ctx, new_node, value);
-  }
-  if (rc != GRN_SUCCESS) {
-    grn_ts_expr_const_node_fin(ctx, new_node);
-    GRN_FREE(new_node);
-    return rc;
-  }
-  *node = (grn_ts_expr_node *)new_node;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_expr_const_node_close() destroys a node. */
-static void
-grn_ts_expr_const_node_close(grn_ctx *ctx, grn_ts_expr_const_node *node) {
-  grn_ts_expr_const_node_fin(ctx, node);
-  GRN_FREE(node);
-}
-
-#define GRN_TS_EXPR_CONST_NODE_EVALUATE_CASE(KIND, kind)\
-  case GRN_TS_ ## KIND: {\
-    size_t i;\
-    grn_ts_ ## kind *out_ptr = (grn_ts_ ## kind *)out;\
-    for (i = 0; i < n_in; i++) {\
-      out_ptr[i] = node->content.as_ ## kind;\
-    }\
-    return GRN_SUCCESS;\
-  }
-#define GRN_TS_EXPR_CONST_NODE_EVALUATE_VECTOR_CASE(KIND, kind)\
-  GRN_TS_EXPR_CONST_NODE_EVALUATE_CASE(KIND ## _VECTOR, kind ## _vector)
-/* grn_ts_expr_const_node_evaluate() outputs the stored const. */
-static grn_rc
-grn_ts_expr_const_node_evaluate(grn_ctx *ctx, grn_ts_expr_const_node *node,
-                                const grn_ts_record *in, size_t n_in,
-                                void *out) {
-  switch (node->data_kind) {
-    GRN_TS_EXPR_CONST_NODE_EVALUATE_CASE(BOOL, bool)
-    GRN_TS_EXPR_CONST_NODE_EVALUATE_CASE(INT, int)
-    GRN_TS_EXPR_CONST_NODE_EVALUATE_CASE(FLOAT, float)
-    GRN_TS_EXPR_CONST_NODE_EVALUATE_CASE(TIME, time)
-    GRN_TS_EXPR_CONST_NODE_EVALUATE_CASE(TEXT, text)
-    GRN_TS_EXPR_CONST_NODE_EVALUATE_CASE(GEO, geo)
-    GRN_TS_EXPR_CONST_NODE_EVALUATE_VECTOR_CASE(BOOL, bool)
-    GRN_TS_EXPR_CONST_NODE_EVALUATE_VECTOR_CASE(INT, int)
-    GRN_TS_EXPR_CONST_NODE_EVALUATE_VECTOR_CASE(FLOAT, float)
-    GRN_TS_EXPR_CONST_NODE_EVALUATE_VECTOR_CASE(TIME, time)
-    GRN_TS_EXPR_CONST_NODE_EVALUATE_VECTOR_CASE(TEXT, text)
-    GRN_TS_EXPR_CONST_NODE_EVALUATE_VECTOR_CASE(GEO, geo)
-    default: {
-      GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d",
-                        node->data_kind);
-    }
-  }
-}
-#undef GRN_TS_EXPR_CONST_NODE_EVALUATE_VECTOR_CASE
-#undef GRN_TS_EXPR_CONST_NODE_EVALUATE_CASE
-
-/* grn_ts_expr_const_node_filter() filters records. */
-static grn_rc
-grn_ts_expr_const_node_filter(grn_ctx *ctx, grn_ts_expr_const_node *node,
-                              grn_ts_record *in, size_t n_in,
-                              grn_ts_record *out, size_t *n_out) {
-  if (node->content.as_bool) {
-    /* All the records pass through the filter. */
-    if (in != out) {
-      size_t i;
-      for (i = 0; i < n_in; i++) {
-        out[i] = in[i];
-      }
-    }
-    *n_out = n_in;
-  } else {
-    /* All the records are discarded. */
-    *n_out = 0;
-  }
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_expr_const_node_adjust() updates scores. */
-static grn_rc
-grn_ts_expr_const_node_adjust(grn_ctx *ctx, grn_ts_expr_const_node *node,
-                              grn_ts_record *io, size_t n_io) {
-  size_t i;
-  grn_ts_score score = (grn_ts_score)node->content.as_float;
-  for (i = 0; i < n_io; i++) {
-    io[i].score = score;
-  }
-  return GRN_SUCCESS;
-}
-
-/*-------------------------------------------------------------
- * grn_ts_expr_column_node.
- */
-
-typedef struct {
-  GRN_TS_EXPR_NODE_COMMON_MEMBERS
-  grn_obj *column;
-  grn_ts_buf buf;
-  grn_ts_buf body_buf;
-} grn_ts_expr_column_node;
-
-/* grn_ts_expr_column_node_init() initializes a node. */
-static void
-grn_ts_expr_column_node_init(grn_ctx *ctx, grn_ts_expr_column_node *node) {
-  memset(node, 0, sizeof(*node));
-  node->type = GRN_TS_EXPR_COLUMN_NODE;
-  node->column = NULL;
-  grn_ts_buf_init(ctx, &node->buf);
-  grn_ts_buf_init(ctx, &node->body_buf);
-}
-
-/* grn_ts_expr_column_node_fin() finalizes a node. */
-static void
-grn_ts_expr_column_node_fin(grn_ctx *ctx, grn_ts_expr_column_node *node) {
-  grn_ts_buf_fin(ctx, &node->body_buf);
-  grn_ts_buf_fin(ctx, &node->buf);
-  if (node->column) {
-    grn_obj_unlink(ctx, node->column);
-  }
-}
-
-#define GRN_TS_EXPR_COLUMN_NODE_OPEN_CASE(TYPE)\
-  case GRN_DB_ ## TYPE: {\
-    GRN_ ## TYPE ## _INIT(&new_node->buf, GRN_OBJ_VECTOR);\
-    break;\
-  }
-/* grn_ts_expr_column_node_open() creates a node associated with a column. */
-static grn_rc
-grn_ts_expr_column_node_open(grn_ctx *ctx, grn_obj *column,
-                             grn_ts_expr_node **node) {
-  grn_rc rc;
-  grn_ts_expr_column_node *new_node = GRN_MALLOCN(grn_ts_expr_column_node, 1);
-  if (!new_node) {
-    GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %zu x 1",
-                      sizeof(grn_ts_expr_column_node));
-  }
-  grn_ts_expr_column_node_init(ctx, new_node);
-  new_node->data_kind = grn_ts_data_type_to_kind(DB_OBJ(column)->range);
-  if (column->header.type == GRN_COLUMN_VAR_SIZE) {
-    grn_obj_flags type = column->header.flags & GRN_OBJ_COLUMN_TYPE_MASK;
-    if (type == GRN_OBJ_COLUMN_VECTOR) {
-      new_node->data_kind |= GRN_TS_VECTOR_FLAG;
-    }
-  }
-  new_node->data_type = DB_OBJ(column)->range;
-  rc = grn_ts_obj_increment_ref_count(ctx, column);
-  if (rc != GRN_SUCCESS) {
-    grn_ts_expr_column_node_fin(ctx, new_node);
-    GRN_FREE(new_node);
-    return rc;
-  }
-  new_node->column = column;
-  *node = (grn_ts_expr_node *)new_node;
-  return GRN_SUCCESS;
-}
-#undef GRN_TS_EXPR_COLUMN_NODE_OPEN_CASE
-
-/* grn_ts_expr_column_node_close() destroys a node. */
-static void
-grn_ts_expr_column_node_close(grn_ctx *ctx, grn_ts_expr_column_node *node) {
-  grn_ts_expr_column_node_fin(ctx, node);
-  GRN_FREE(node);
-}
-
-#define GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_CASE(KIND, kind)\
-  case GRN_TS_ ## KIND: {\
-    size_t i;\
-    grn_ts_ ## kind *out_ptr = (grn_ts_ ## kind *)out;\
-    grn_ra *ra = (grn_ra *)node->column;\
-    grn_ra_cache cache;\
-    GRN_RA_CACHE_INIT(ra, &cache);\
-    for (i = 0; i < n_in; i++) {\
-      grn_ts_ ## kind *ptr = NULL;\
-      if (in[i].id) {\
-        ptr = (grn_ts_ ## kind *)grn_ra_ref_cache(ctx, ra, in[i].id, &cache);\
-      }\
-      out_ptr[i] = ptr ? *ptr : grn_ts_ ## kind ## _zero();\
-    }\
-    GRN_RA_CACHE_FIN(ra, &cache);\
-    return GRN_SUCCESS;\
-  }
-#define GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_INT_CASE(TYPE, type)\
-  case GRN_DB_ ## TYPE: {\
-    size_t i;\
-    grn_ts_int *out_ptr = (grn_ts_int *)out;\
-    grn_ra *ra = (grn_ra *)node->column;\
-    grn_ra_cache cache;\
-    GRN_RA_CACHE_INIT(ra, &cache);\
-    for (i = 0; i < n_in; i++) {\
-      type ## _t *ptr = NULL;\
-      if (in[i].id) {\
-        ptr = (type ## _t *)grn_ra_ref_cache(ctx, ra, in[i].id, &cache);\
-      }\
-      out_ptr[i] = ptr ? (grn_ts_int)*ptr : grn_ts_int_zero();\
-    }\
-    GRN_RA_CACHE_FIN(ra, &cache);\
-    return GRN_SUCCESS;\
-  }
-/* grn_ts_expr_column_node_evaluate_scalar() outputs scalar column values. */
-static grn_rc
-grn_ts_expr_column_node_evaluate_scalar(grn_ctx *ctx,
-                                        grn_ts_expr_column_node *node,
-                                        const grn_ts_record *in, size_t n_in,
-                                        void *out) {
-  switch (node->data_kind) {
-    GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_CASE(BOOL, bool)
-    case GRN_TS_INT: {
-      switch (node->data_type) {
-        GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_INT_CASE(INT8, int8)
-        GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_INT_CASE(INT16, int16)
-        GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_INT_CASE(INT32, int32)
-        GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_INT_CASE(INT64, int64)
-        GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_INT_CASE(UINT8, uint8)
-        GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_INT_CASE(UINT16, uint16)
-        GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_INT_CASE(UINT32, uint32)
-        /* The behavior is undefined if a value is greater than 2^63 - 1. */
-        GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_INT_CASE(UINT64, uint64)
-        default: {
-          GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data type: %d",
-                            node->data_type);
-        }
-      }
-    }
-    GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_CASE(FLOAT, float)
-    GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_CASE(TIME, time)
-    case GRN_TS_TEXT: {
-      size_t i, size;
-      char *buf_ptr;
-      grn_ja *ja = (grn_ja *)node->column;
-      grn_ts_text *out_ptr = (grn_ts_text *)out;
-      /* Read column values into node->buf and save the size of each value. */
-      node->buf.pos = 0;
-      for (i = 0; i < n_in; i++) {
-        grn_rc rc = grn_ts_ja_get_value(ctx, ja, in[i].id, &node->buf, &size);
-        out_ptr[i].size = (rc == GRN_SUCCESS) ? size : 0;
-      }
-      buf_ptr = (char *)node->buf.ptr;
-      for (i = 0; i < n_in; i++) {
-        out_ptr[i].ptr = buf_ptr;
-        buf_ptr += out_ptr[i].size;
-      }
-      return GRN_SUCCESS;
-    }
-    GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_CASE(GEO, geo)
-    case GRN_TS_REF: {
-      size_t i;
-      grn_ts_ref *out_ptr = (grn_ts_ref *)out;
-      grn_ra *ra = (grn_ra *)node->column;
-      grn_ra_cache cache;
-      GRN_RA_CACHE_INIT(ra, &cache);
-      for (i = 0; i < n_in; i++) {
-        grn_ts_id *ptr = NULL;
-        if (in[i].id) {
-          ptr = (grn_ts_id *)grn_ra_ref_cache(ctx, ra, in[i].id, &cache);
-        }
-        out_ptr[i].id = ptr ? *ptr : GRN_ID_NIL;
-        out_ptr[i].score = in[i].score;
-      }
-      GRN_RA_CACHE_FIN(ra, &cache);
-      return GRN_SUCCESS;
-    }
-    default: {
-      GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d",
-                        node->data_kind);
-    }
-  }
-}
-#undef GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_INT_CASE
-#undef GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_CASE
-
-/*
- * grn_ts_expr_column_node_evaluate_text_vector() outputs text vector column
- * values.
- */
-static grn_rc
-grn_ts_expr_column_node_evaluate_text_vector(grn_ctx *ctx,
-                                             grn_ts_expr_column_node *node,
-                                             const grn_ts_record *in,
-                                             size_t n_in, void *out) {
-  grn_rc rc;
-  char *buf_ptr;
-  size_t i, j, n_bytes, n_values, total_n_bytes = 0, total_n_values = 0;
-  grn_ts_text *text_ptr;
-  grn_ts_text_vector *out_ptr = (grn_ts_text_vector *)out;
-  /* Read encoded values into node->body_buf and get the size of each value. */
-  node->body_buf.pos = 0;
-  for (i = 0; i < n_in; i++) {
-    char *ptr;
-    rc = grn_ts_ja_get_value(ctx, (grn_ja *)node->column, in[i].id,
-                             &node->body_buf, &n_bytes);
-    if (rc == GRN_SUCCESS) {
-      ptr = (char *)node->body_buf.ptr + total_n_bytes;
-      GRN_B_DEC(n_values, ptr);
-    } else {
-      n_bytes = 0;
-      n_values = 0;
-    }
-    grn_memcpy(&out_ptr[i].ptr, &n_bytes, sizeof(n_bytes));
-    out_ptr[i].size = n_values;
-    total_n_bytes += n_bytes;
-    total_n_values += n_values;
-  }
-  /* Resize node->buf. */
-  n_bytes = sizeof(grn_ts_text) * total_n_values;
-  rc = grn_ts_buf_reserve(ctx, &node->buf, n_bytes);
-  if (rc != GRN_SUCCESS) {
-    return rc;
-  }
-  /* Decode values and compose the result. */
-  buf_ptr = (char *)node->body_buf.ptr;
-  text_ptr = (grn_ts_text *)node->buf.ptr;
-  for (i = 0; i < n_in; i++) {
-    char *ptr = buf_ptr;
-    grn_memcpy(&n_bytes, &out_ptr[i].ptr, sizeof(n_bytes));
-    buf_ptr += n_bytes;
-    GRN_B_DEC(n_values, ptr);
-    out_ptr[i].ptr = text_ptr;
-    for (j = 0; j < out_ptr[i].size; j++) {
-      GRN_B_DEC(text_ptr[j].size, ptr);
-    }
-    for (j = 0; j < out_ptr[i].size; j++) {
-      text_ptr[j].ptr = ptr;
-      ptr += text_ptr[j].size;
-    }
-    text_ptr += out_ptr[i].size;
-  }
-  return GRN_SUCCESS;
-}
-
-/*
- * grn_ts_expr_column_node_evaluate_ref_vector() outputs ref vector column
- * values.
- */
-static grn_rc
-grn_ts_expr_column_node_evaluate_ref_vector(grn_ctx *ctx,
-                                             grn_ts_expr_column_node *node,
-                                             const grn_ts_record *in,
-                                             size_t n_in, void *out) {
-  grn_rc rc;
-  size_t i, j, n_bytes, offset = 0;
-  grn_ts_id *buf_ptr;
-  grn_ts_ref *ref_ptr;
-  grn_ts_ref_vector *out_ptr = (grn_ts_ref_vector *)out;
-  /* Read column values into node->body_buf and get the size of each value. */
-  node->body_buf.pos = 0;
-  for (i = 0; i < n_in; i++) {
-    size_t size;
-    rc = grn_ts_ja_get_value(ctx, (grn_ja *)node->column, in[i].id,
-                             &node->body_buf, &size);
-    if (rc == GRN_SUCCESS) {
-      out_ptr[i].size = size / sizeof(grn_ts_id);
-      offset += out_ptr[i].size;
-    } else {
-      out_ptr[i].size = 0;
-    }
-  }
-  /* Resize node->buf. */
-  n_bytes = sizeof(grn_ts_ref) * offset;
-  rc = grn_ts_buf_reserve(ctx, &node->buf, n_bytes);
-  if (rc != GRN_SUCCESS) {
-    return rc;
-  }
-  /* Compose the result. */
-  buf_ptr = (grn_ts_id *)node->body_buf.ptr;
-  ref_ptr = (grn_ts_ref *)node->buf.ptr;
-  for (i = 0; i < n_in; i++) {
-    out_ptr[i].ptr = ref_ptr;
-    for (j = 0; j < out_ptr[i].size; j++, buf_ptr++, ref_ptr++) {
-      ref_ptr->id = *buf_ptr;
-      ref_ptr->score = in[i].score;
-    }
-  }
-  return GRN_SUCCESS;
-}
-
-#define GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_CASE(KIND, kind)\
-  case GRN_TS_ ## KIND ## _VECTOR: {\
-    size_t i;\
-    grn_ts_ ## kind *buf_ptr;\
-    grn_ts_ ## kind ## _vector *out_ptr = (grn_ts_ ## kind ## _vector *)out;\
-    /* Read column values into node->buf and save the size of each value. */\
-    node->buf.pos = 0;\
-    for (i = 0; i < n_in; i++) {\
-      size_t n_bytes;\
-      grn_rc rc = grn_ts_ja_get_value(ctx, (grn_ja *)node->column, in[i].id,\
-                                      &node->buf, &n_bytes);\
-      if (rc == GRN_SUCCESS) {\
-        out_ptr[i].size = n_bytes / sizeof(grn_ts_ ## kind);\
-      } else {\
-        out_ptr[i].size = 0;\
-      }\
-    }\
-    buf_ptr = (grn_ts_ ## kind *)node->buf.ptr;\
-    for (i = 0; i < n_in; i++) {\
-      out_ptr[i].ptr = buf_ptr;\
-      buf_ptr += out_ptr[i].size;\
-    }\
-    return GRN_SUCCESS;\
-  }
-#define GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_INT_CASE(TYPE, type)\
-  case GRN_DB_ ## TYPE: {\
-    size_t i, j;\
-    grn_ts_int *buf_ptr;\
-    grn_ts_int_vector *out_ptr = (grn_ts_int_vector *)out;\
-    /*
-     * Read column values into body_buf and typecast the values to grn_ts_int.
-     * Then, store the grn_ts_int values into node->buf and save the size of
-     * each value.
-     */\
-    node->buf.pos = 0;\
-    for (i = 0; i < n_in; i++) {\
-      grn_rc rc;\
-      size_t n_bytes, new_n_bytes;\
-      node->body_buf.pos = 0;\
-      rc = grn_ts_ja_get_value(ctx, (grn_ja *)node->column, in[i].id,\
-                               &node->body_buf, &n_bytes);\
-      if (rc == GRN_SUCCESS) {\
-        out_ptr[i].size = n_bytes / sizeof(type ## _t);\
-      } else {\
-        out_ptr[i].size = 0;\
-      }\
-      new_n_bytes = node->buf.pos + (sizeof(grn_ts_int) * out_ptr[i].size);\
-      rc = grn_ts_buf_reserve(ctx, &node->buf, new_n_bytes);\
-      if (rc == GRN_SUCCESS) {\
-        type ## _t *src_ptr = (type ## _t *)node->body_buf.ptr;\
-        grn_ts_int *dest_ptr;\
-        dest_ptr = (grn_ts_int *)((char *)node->buf.ptr + node->buf.pos);\
-        for (j = 0; j < out_ptr[i].size; j++) {\
-          dest_ptr[j] = (grn_ts_int)src_ptr[j];\
-        }\
-        node->buf.pos = new_n_bytes;\
-      } else {\
-        out_ptr[i].size = 0;\
-      }\
-    }\
-    buf_ptr = (grn_ts_int *)node->buf.ptr;\
-    for (i = 0; i < n_in; i++) {\
-      out_ptr[i].ptr = buf_ptr;\
-      buf_ptr += out_ptr[i].size;\
-    }\
-    return GRN_SUCCESS;\
-  }
-/* grn_ts_expr_column_node_evaluate_vector() outputs vector column values. */
-static grn_rc
-grn_ts_expr_column_node_evaluate_vector(grn_ctx *ctx,
-                                        grn_ts_expr_column_node *node,
-                                        const grn_ts_record *in, size_t n_in,
-                                        void *out) {
-  switch (node->data_kind) {
-    GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_CASE(BOOL, bool)
-    case GRN_TS_INT_VECTOR: {
-      switch (node->data_type) {
-        GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_INT_CASE(INT8, int8)
-        GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_INT_CASE(INT16, int16)
-        GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_INT_CASE(INT32, int32)
-        GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_INT_CASE(INT64, int64)
-        GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_INT_CASE(UINT8, uint8)
-        GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_INT_CASE(UINT16, uint16)
-        GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_INT_CASE(UINT32, uint32)
-        /* The behavior is undefined if a value is greater than 2^63 - 1. */
-        GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_INT_CASE(UINT64, uint64)
-        default: {
-          GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data type: %d",
-                            node->data_type);
-        }
-      }
-    }
-    GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_CASE(FLOAT, float)
-    GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_CASE(TIME, time)
-    case GRN_TS_TEXT_VECTOR: {
-      return grn_ts_expr_column_node_evaluate_text_vector(ctx, node, in, n_in,
-                                                          out);
-    }
-    GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_CASE(GEO, geo)
-    case GRN_TS_REF_VECTOR: {
-      return grn_ts_expr_column_node_evaluate_ref_vector(ctx, node, in, n_in,
-                                                         out);
-    }
-    default: {
-      GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d",
-                        node->data_kind);
-    }
-  }
-}
-#undef GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_INT_CASE
-#undef GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_CASE
-
-/* grn_ts_expr_column_node_evaluate() outputs column values. */
-static grn_rc
-grn_ts_expr_column_node_evaluate(grn_ctx *ctx, grn_ts_expr_column_node *node,
-                                 const grn_ts_record *in, size_t n_in,
-                                 void *out) {
-  if (node->data_kind & GRN_TS_VECTOR_FLAG) {
-    return grn_ts_expr_column_node_evaluate_vector(ctx, node, in, n_in, out);
-  } else {
-    return grn_ts_expr_column_node_evaluate_scalar(ctx, node, in, n_in, out);
-  }
-}
-
-/* grn_ts_expr_column_node_filter() filters records. */
-static grn_rc
-grn_ts_expr_column_node_filter(grn_ctx *ctx, grn_ts_expr_column_node *node,
-                               grn_ts_record *in, size_t n_in,
-                               grn_ts_record *out, size_t *n_out) {
-  size_t i, count = 0;
-  grn_ra *ra = (grn_ra *)node->column;
-  grn_ra_cache cache;
-  GRN_RA_CACHE_INIT(ra, &cache);
-  for (i = 0; i < n_in; i++) {
-    grn_ts_bool *ptr = NULL;
-    if (in[i].id) {
-      ptr = grn_ra_ref_cache(ctx, ra, in[i].id, &cache);
-    }
-    if (ptr && *ptr) {
-      out[count++] = in[i];
-    }
-  }
-  GRN_RA_CACHE_FIN(ra, &cache);
-  *n_out = count;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_expr_column_node_adjust() updates scores. */
-static grn_rc
-grn_ts_expr_column_node_adjust(grn_ctx *ctx, grn_ts_expr_column_node *node,
-                               grn_ts_record *io, size_t n_io) {
-  size_t i;
-  grn_ra *ra = (grn_ra *)node->column;
-  grn_ra_cache cache;
-  GRN_RA_CACHE_INIT(ra, &cache);
-  for (i = 0; i < n_io; i++) {
-    grn_ts_float *ptr = NULL;
-    if (io[i].id) {
-      ptr = grn_ra_ref_cache(ctx, ra, io[i].id, &cache);
-    }
-    if (ptr) {
-      io[i].score = (grn_ts_score)*ptr;
-    }
-  }
-  GRN_RA_CACHE_FIN(ra, &cache);
-  return GRN_SUCCESS;
-}
-
-/*-------------------------------------------------------------
- * grn_ts_expr_op_node.
- */
-
-enum {
-  GRN_TS_EXPR_OP_NODE_MAX_N_ARGS = 3,
-  GRN_TS_EXPR_OP_NODE_N_BUFS = 3
-};
-
-/* Forward declarations. */
-static void grn_ts_expr_node_close(grn_ctx *ctx, grn_ts_expr_node *node);
-static grn_rc grn_ts_expr_node_evaluate(grn_ctx *ctx, grn_ts_expr_node *node,
-                                        const grn_ts_record *in, size_t n_in,
-                                        void *out);
-static grn_rc grn_ts_expr_node_evaluate_to_buf(grn_ctx *ctx,
-                                               grn_ts_expr_node *node,
-                                               const grn_ts_record *in,
-                                               size_t n_in,
-                                               grn_ts_buf *out);
-static grn_rc grn_ts_expr_node_filter(grn_ctx *ctx, grn_ts_expr_node *node,
-                                      grn_ts_record *in, size_t n_in,
-                                      grn_ts_record *out, size_t *n_out);
-static grn_rc grn_ts_expr_node_adjust(grn_ctx *ctx, grn_ts_expr_node *node,
-                                      grn_ts_record *io, size_t n_io);
-
-typedef struct {
-  GRN_TS_EXPR_NODE_COMMON_MEMBERS
-  grn_ts_op_type op_type;
-  grn_ts_expr_node *args[GRN_TS_EXPR_OP_NODE_MAX_N_ARGS];
-  size_t n_args;
-  grn_ts_buf bufs[GRN_TS_EXPR_OP_NODE_N_BUFS];
-} grn_ts_expr_op_node;
-
-/* grn_ts_expr_op_node_init() initializes a node. */
-static void
-grn_ts_expr_op_node_init(grn_ctx *ctx, grn_ts_expr_op_node *node) {
-  size_t i;
-  memset(node, 0, sizeof(*node));
-  node->type = GRN_TS_EXPR_OP_NODE;
-  for (i = 0; i < GRN_TS_EXPR_OP_NODE_MAX_N_ARGS; i++) {
-    node->args[i] = NULL;
-  }
-  for (i = 0; i < GRN_TS_EXPR_OP_NODE_N_BUFS; i++) {
-    grn_ts_buf_init(ctx, &node->bufs[i]);
-  }
-}
-
-/* grn_ts_expr_op_node_fin() finalizes a node. */
-static void
-grn_ts_expr_op_node_fin(grn_ctx *ctx, grn_ts_expr_op_node *node) {
-  size_t i;
-  for (i = 0; i < GRN_TS_EXPR_OP_NODE_N_BUFS; i++) {
-    grn_ts_buf_fin(ctx, &node->bufs[i]);
-  }
-  for (i = 0; i < GRN_TS_EXPR_OP_NODE_MAX_N_ARGS; i++) {
-    if (node->args[i]) {
-      grn_ts_expr_node_close(ctx, node->args[i]);
-    }
-  }
-}
-
-/*
- * grn_ts_op_plus_check_args() checks arguments. Note that arguments are
- * rearranged in some cases.
- */
-static grn_rc
-grn_ts_op_plus_check_args(grn_ctx *ctx, grn_ts_expr_op_node *node) {
-  switch (node->args[0]->data_kind) {
-    case GRN_TS_INT: {
-      switch (node->args[1]->data_kind) {
-        case GRN_TS_INT: {
-          /* Int + Int = Int. */
-          node->data_kind = GRN_TS_INT;
-          node->data_type = GRN_DB_INT64;
-          return GRN_SUCCESS;
-        }
-        case GRN_TS_TIME: {
-          /* Int + Time = Time + Int = Time. */
-          grn_ts_expr_node *tmp = node->args[0];
-          node->args[0] = node->args[1];
-          node->args[1] = tmp;
-          node->data_kind = GRN_TS_TIME;
-          node->data_type = GRN_DB_TIME;
-          return GRN_SUCCESS;
-        }
-        default: {
-          GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d",
-                            node->args[1]->data_kind);
-        }
-      }
-    }
-    case GRN_TS_FLOAT: {
-      switch (node->args[1]->data_kind) {
-        case GRN_TS_FLOAT: {
-          /* Float + Float = Float. */
-          node->data_kind = GRN_TS_FLOAT;
-          node->data_type = GRN_DB_FLOAT;
-          return GRN_SUCCESS;
-        }
-        case GRN_TS_TIME: {
-          /* Float + Time = Time + Float = Time. */
-          grn_ts_expr_node *tmp = node->args[0];
-          node->args[0] = node->args[1];
-          node->args[1] = tmp;
-          node->data_kind = GRN_TS_TIME;
-          node->data_type = GRN_DB_TIME;
-          return GRN_SUCCESS;
-        }
-        default: {
-          GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d",
-                            node->args[1]->data_kind);
-        }
-      }
-    }
-    case GRN_TS_TIME: {
-      switch (node->args[1]->data_kind) {
-        case GRN_TS_INT:
-        case GRN_TS_FLOAT: {
-          /* Time + Int or Float = Time. */
-          node->data_kind = GRN_TS_TIME;
-          node->data_type = GRN_DB_TIME;
-          return GRN_SUCCESS;
-        }
-        default: {
-          GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d",
-                            node->args[1]->data_kind);
-        }
-      }
-    }
-    default: {
-      GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d",
-                        node->args[0]->data_kind);
-    }
-  }
-}
-
-/* grn_ts_op_minus_check_args() checks arguments. */
-static grn_rc
-grn_ts_op_minus_check_args(grn_ctx *ctx, grn_ts_expr_op_node *node) {
-  switch (node->args[0]->data_kind) {
-    case GRN_TS_INT: {
-      if (node->args[1]->data_kind != GRN_TS_INT) {
-        GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d",
-                          node->args[1]->data_kind);
-      }
-      /* Int - Int = Int. */
-      node->data_kind = GRN_TS_INT;
-      node->data_type = GRN_DB_INT64;
-      return GRN_SUCCESS;
-    }
-    case GRN_TS_FLOAT: {
-      if (node->args[1]->data_kind != GRN_TS_FLOAT) {
-        GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d",
-                          node->args[1]->data_kind);
-      }
-      /* Float - Float = Float. */
-      node->data_kind = GRN_TS_FLOAT;
-      node->data_type = GRN_DB_FLOAT;
-      return GRN_SUCCESS;
-    }
-    case GRN_TS_TIME: {
-      switch (node->args[1]->data_kind) {
-        case GRN_TS_INT:
-        case GRN_TS_FLOAT: {
-          /* Time - Int or Float = Time. */
-          node->data_kind = GRN_TS_TIME;
-          node->data_type = GRN_DB_TIME;
-          return GRN_SUCCESS;
-        }
-        case GRN_TS_TIME: {
-          /* Time - Time = Float. */
-          node->data_kind = GRN_TS_FLOAT;
-          node->data_type = GRN_DB_FLOAT;
-          return GRN_SUCCESS;
-        }
-        default: {
-          GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d",
-                            node->args[1]->data_kind);
-        }
-      }
-    }
-    default: {
-      GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d",
-                        node->args[0]->data_kind);
-    }
-  }
-}
-
-/*
- * grn_ts_expr_op_node_check_args() checks the combination of an operator and
- * its arguments.
- */
-static grn_rc
-grn_ts_expr_op_node_check_args(grn_ctx *ctx, grn_ts_expr_op_node *node) {
-  switch (node->op_type) {
-    case GRN_TS_OP_LOGICAL_NOT: {
-      if (node->args[0]->data_kind != GRN_TS_BOOL) {
-        GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d",
-                          node->args[0]->data_kind);
-      }
-      node->data_kind = GRN_TS_BOOL;
-      node->data_type = GRN_DB_BOOL;
-      return GRN_SUCCESS;
-    }
-    case GRN_TS_OP_BITWISE_NOT: {
-      switch (node->args[0]->data_kind) {
-        case GRN_TS_BOOL:
-        case GRN_TS_INT: {
-          node->data_kind = node->args[0]->data_kind;
-          node->data_type = grn_ts_data_kind_to_type(node->data_kind);
-          return GRN_SUCCESS;
-        }
-        default: {
-          GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d",
-                            node->args[0]->data_kind);
-        }
-      }
-    }
-    case GRN_TS_OP_POSITIVE:
-    case GRN_TS_OP_NEGATIVE: {
-      if ((node->args[0]->data_kind != GRN_TS_INT) &&
-          (node->args[0]->data_kind != GRN_TS_FLOAT)) {
-        GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d",
-                          node->args[0]->data_kind);
-      }
-      node->data_kind = node->args[0]->data_kind;
-      node->data_type = grn_ts_data_kind_to_type(node->data_kind);
-      return GRN_SUCCESS;
-    }
-    case GRN_TS_OP_LOGICAL_AND:
-    case GRN_TS_OP_LOGICAL_OR:
-    case GRN_TS_OP_LOGICAL_SUB: {
-      if ((node->args[0]->data_kind != GRN_TS_BOOL) ||
-          (node->args[1]->data_kind != GRN_TS_BOOL)) {
-        GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d, %d",
-                          node->args[0]->data_kind, node->args[1]->data_kind);
-      }
-      node->data_kind = GRN_TS_BOOL;
-      node->data_type = GRN_DB_BOOL;
-      return GRN_SUCCESS;
-    }
-    case GRN_TS_OP_BITWISE_AND:
-    case GRN_TS_OP_BITWISE_OR:
-    case GRN_TS_OP_BITWISE_XOR: {
-      if (node->args[0]->data_kind != node->args[1]->data_kind) {
-        GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "data kind conflict: %d != %d",
-                          node->args[0]->data_kind, node->args[1]->data_kind);
-      }
-      switch (node->args[0]->data_kind) {
-        case GRN_TS_BOOL:
-        case GRN_TS_INT: {
-          node->data_kind = node->args[0]->data_kind;
-          node->data_type = grn_ts_data_kind_to_type(node->data_kind);
-          return GRN_SUCCESS;
-        }
-        default: {
-          GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d",
-                            node->args[0]->data_kind);
-        }
-      }
-      node->data_kind = GRN_TS_BOOL;
-      node->data_type = GRN_DB_BOOL;
-      return GRN_SUCCESS;
-    }
-    case GRN_TS_OP_EQUAL:
-    case GRN_TS_OP_NOT_EQUAL: {
-      grn_ts_data_kind scalar_data_kind;
-      if (node->args[0]->data_kind != node->args[1]->data_kind) {
-        GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "data kind conflict: %d != %d",
-                          node->args[0]->data_kind, node->args[1]->data_kind);
-      }
-      scalar_data_kind = node->args[0]->data_kind & ~GRN_TS_VECTOR_FLAG;
-      if (((scalar_data_kind == GRN_TS_REF) ||
-           (scalar_data_kind == GRN_TS_GEO)) &&
-          (node->args[0]->data_type != node->args[1]->data_type)) {
-        GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "data type conflict: %d != %d",
-                          node->args[0]->data_type, node->args[1]->data_type);
-      }
-      node->data_kind = GRN_TS_BOOL;
-      node->data_type = GRN_DB_BOOL;
-      return GRN_SUCCESS;
-    }
-    case GRN_TS_OP_LESS:
-    case GRN_TS_OP_LESS_EQUAL:
-    case GRN_TS_OP_GREATER:
-    case GRN_TS_OP_GREATER_EQUAL: {
-      if (node->args[0]->data_kind != node->args[1]->data_kind) {
-        GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "data kind conflict: %d != %d",
-                          node->args[0]->data_kind, node->args[1]->data_kind);
-      }
-      switch (node->args[0]->data_kind) {
-        case GRN_TS_INT:
-        case GRN_TS_FLOAT:
-        case GRN_TS_TIME:
-        case GRN_TS_TEXT:
-        case GRN_TS_INT_VECTOR:
-        case GRN_TS_FLOAT_VECTOR:
-        case GRN_TS_TIME_VECTOR:
-        case GRN_TS_TEXT_VECTOR: {
-          node->data_kind = GRN_TS_BOOL;
-          node->data_type = GRN_DB_BOOL;
-          return GRN_SUCCESS;
-        }
-        default: {
-          GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d",
-                            node->args[0]->data_kind);
-        }
-      }
-      case GRN_TS_OP_SHIFT_ARITHMETIC_LEFT:
-      case GRN_TS_OP_SHIFT_ARITHMETIC_RIGHT:
-      case GRN_TS_OP_SHIFT_LOGICAL_LEFT:
-      case GRN_TS_OP_SHIFT_LOGICAL_RIGHT: {
-        if ((node->args[0]->data_kind != GRN_TS_INT) ||
-            (node->args[1]->data_kind != GRN_TS_INT)) {
-          GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d, %d",
-                            node->args[0]->data_kind,
-                            node->args[1]->data_kind);
-        }
-        node->data_kind = GRN_TS_INT;
-        node->data_type = GRN_DB_INT64;
-        return GRN_SUCCESS;
-      }
-      case GRN_TS_OP_PLUS: {
-        return grn_ts_op_plus_check_args(ctx, node);
-      }
-      case GRN_TS_OP_MINUS: {
-        return grn_ts_op_minus_check_args(ctx, node);
-      }
-      case GRN_TS_OP_MULTIPLICATION:
-      case GRN_TS_OP_DIVISION:
-      case GRN_TS_OP_MODULUS: {
-        if (node->args[0]->data_kind != node->args[1]->data_kind) {
-          GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT,
-                            "data kind conflict: %d != %d",
-                            node->args[0]->data_kind,
-                            node->args[1]->data_kind);
-        }
-        switch (node->args[0]->data_kind) {
-          case GRN_TS_INT:
-          case GRN_TS_FLOAT: {
-            node->data_kind = node->args[0]->data_kind;
-            node->data_type = grn_ts_data_kind_to_type(node->data_kind);
-            return GRN_SUCCESS;
-          }
-          default: {
-            GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d",
-                              node->args[0]->data_kind);
-          }
-        }
-      }
-    }
-    default: {
-      GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid operator: %d",
-                        node->op_type);
-    }
-  }
-}
-
-/* grn_ts_expr_op_node_open() creates a node associated with an operator. */
-static grn_rc
-grn_ts_expr_op_node_open(grn_ctx *ctx, grn_ts_op_type op_type,
-                         grn_ts_expr_node **args, size_t n_args,
-                         grn_ts_expr_node **node) {
-  size_t i;
-  grn_rc rc;
-  grn_ts_expr_op_node *new_node = GRN_MALLOCN(grn_ts_expr_op_node, 1);
-  if (!new_node) {
-    for (i = 0; i < n_args; i++) {
-      grn_ts_expr_node_close(ctx, args[i]);
-    }
-    GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %zu x 1",
-                      sizeof(grn_ts_expr_op_node));
-  }
-  grn_ts_expr_op_node_init(ctx, new_node);
-  new_node->op_type = op_type;
-  for (i = 0; i < n_args; i++) {
-    new_node->args[i] = args[i];
-  }
-  new_node->n_args = n_args;
-
-  /* Check arguments. */
-  rc = grn_ts_expr_op_node_check_args(ctx, new_node);
-  if (rc == GRN_SUCCESS) {
-    if (new_node->data_kind == GRN_TS_VOID) {
-      GRN_TS_ERR(GRN_OBJECT_CORRUPT, "invalid data kind: %d", GRN_TS_VOID);
-      rc = ctx->rc;
-    } else if (new_node->data_type == GRN_DB_VOID) {
-      GRN_TS_ERR(GRN_OBJECT_CORRUPT, "invalid data type: %d", GRN_DB_VOID);
-      rc = ctx->rc;
-    }
-  }
-  if (rc != GRN_SUCCESS) {
-    grn_ts_expr_op_node_fin(ctx, new_node);
-    GRN_FREE(new_node);
-    return rc;
-  }
-  *node = (grn_ts_expr_node *)new_node;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_expr_op_node_close() destroys a node. */
-static void
-grn_ts_expr_op_node_close(grn_ctx *ctx, grn_ts_expr_op_node *node) {
-  grn_ts_expr_op_node_fin(ctx, node);
-  GRN_FREE(node);
-}
-
-/* grn_ts_op_logical_not_evaluate() evaluates an operator. */
-static grn_rc
-grn_ts_op_logical_not_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node,
-                               const grn_ts_record *in, size_t n_in,
-                               void *out) {
-  size_t i;
-  grn_ts_bool *out_ptr = (grn_ts_bool *)out;
-  grn_rc rc = grn_ts_expr_node_evaluate(ctx, node->args[0], in, n_in, out);
-  if (rc != GRN_SUCCESS) {
-    return rc;
-  }
-  for (i = 0; i < n_in; i++) {
-    out_ptr[i] = grn_ts_op_logical_not_bool(out_ptr[i]);
-  }
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_op_bitwise_not_evaluate() evaluates an operator. */
-static grn_rc
-grn_ts_op_bitwise_not_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node,
-                               const grn_ts_record *in, size_t n_in,
-                               void *out) {
-  size_t i;
-  grn_rc rc = grn_ts_expr_node_evaluate(ctx, node->args[0], in, n_in, out);
-  if (rc != GRN_SUCCESS) {
-    return rc;
-  }
-  switch (node->data_kind) {
-    case GRN_TS_BOOL: {
-      grn_ts_bool *out_ptr = (grn_ts_bool *)out;
-      for (i = 0; i < n_in; i++) {
-        out_ptr[i] = grn_ts_op_bitwise_not_bool(out_ptr[i]);
-      }
-      return GRN_SUCCESS;
-    }
-    case GRN_TS_INT: {
-      grn_ts_int *out_ptr = (grn_ts_int *)out;
-      for (i = 0; i < n_in; i++) {
-        out_ptr[i] = grn_ts_op_bitwise_not_int(out_ptr[i]);
-      }
-      return GRN_SUCCESS;
-    }
-    default: {
-      GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d",
-                        node->data_kind);
-    }
-  }
-}
-
-#define GRN_TS_OP_SIGN_EVALUATE_CASE(type, KIND, kind) \
-  case GRN_TS_ ## KIND: {\
-    grn_ts_ ## kind *out_ptr = (grn_ts_ ## kind *)out;\
-    for (i = 0; i < n_in; i++) {\
-      out_ptr[i] = grn_ts_op_ ## type ## _ ## kind(out_ptr[i]);\
-    }\
-    return GRN_SUCCESS;\
-  }
-#define GRN_TS_OP_SIGN_EVALUATE(type) \
-  size_t i;\
-  grn_rc rc = grn_ts_expr_node_evaluate(ctx, node->args[0], in, n_in, out);\
-  if (rc != GRN_SUCCESS) {\
-    return rc;\
-  }\
-  switch (node->data_kind) {\
-    GRN_TS_OP_SIGN_EVALUATE_CASE(type, INT, int)\
-    GRN_TS_OP_SIGN_EVALUATE_CASE(type, FLOAT, float)\
-    default: {\
-      GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d",\
-                        node->data_kind);\
-    }\
-  }
-/* grn_ts_op_positive_evaluate() evaluates an operator. */
-static grn_rc
-grn_ts_op_positive_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node,
-                            const grn_ts_record *in, size_t n_in, void *out) {
-  GRN_TS_OP_SIGN_EVALUATE(positive)
-}
-
-/* grn_ts_op_negative_evaluate() evaluates an operator. */
-static grn_rc
-grn_ts_op_negative_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node,
-                            const grn_ts_record *in, size_t n_in, void *out) {
-  GRN_TS_OP_SIGN_EVALUATE(negative)
-}
-#undef GRN_TS_OP_SIGN_EVALUATE
-#undef GRN_TS_OP_SIGN_EVALUATE_CASE
-
-/* grn_ts_op_logical_and_evaluate() evaluates an operator. */
-static grn_rc
-grn_ts_op_logical_and_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node,
-                               const grn_ts_record *in, size_t n_in,
-                               void *out) {
-  size_t i, j, count;
-  grn_rc rc;
-  grn_ts_bool *buf_ptrs[2], *out_ptr = (grn_ts_bool *)out;
-  grn_ts_buf *tmp_in_buf = &node->bufs[2];
-  grn_ts_record *tmp_in;
-
-  /* Evaluate the 1st argument. */
-  rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[0], in, n_in,
-                                        &node->bufs[0]);
-  if (rc != GRN_SUCCESS) {
-    return rc;
-  }
-  buf_ptrs[0] = (grn_ts_bool *)node->bufs[0].ptr;
-
-  /* Create a list of true records. */
-  rc = grn_ts_buf_reserve(ctx, tmp_in_buf, sizeof(grn_ts_record) * n_in);
-  if (rc != GRN_SUCCESS) {
-    return rc;
-  }
-  tmp_in = (grn_ts_record *)tmp_in_buf->ptr;
-  count = 0;
-  for (i = 0; i < n_in; i++) {
-    if (buf_ptrs[0][i]) {
-      tmp_in[count++] = in[i];
-    }
-  }
-
-  /* Evaluate the 2nd argument. */
-  rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[1], tmp_in, count,
-                                        &node->bufs[1]);
-  buf_ptrs[1] = (grn_ts_bool *)node->bufs[1].ptr;
-
-  /* Merge the results. */
-  count = 0;
-  for (i = 0, j = 0; i < n_in; i++) {
-    out_ptr[count++] = buf_ptrs[0][i] && buf_ptrs[1][j++];
-  }
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_op_logical_or_evaluate() evaluates an operator. */
-static grn_rc
-grn_ts_op_logical_or_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node,
-                               const grn_ts_record *in, size_t n_in,
-                               void *out) {
-  size_t i, j, count;
-  grn_rc rc;
-  grn_ts_bool *buf_ptrs[2], *out_ptr = (grn_ts_bool *)out;
-  grn_ts_buf *tmp_in_buf = &node->bufs[2];
-  grn_ts_record *tmp_in;
-
-  /* Evaluate the 1st argument. */
-  rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[0], in, n_in,
-                                        &node->bufs[0]);
-  if (rc != GRN_SUCCESS) {
-    return rc;
-  }
-  buf_ptrs[0] = (grn_ts_bool *)node->bufs[0].ptr;
-
-  /* Create a list of false records. */
-  rc = grn_ts_buf_reserve(ctx, tmp_in_buf, sizeof(grn_ts_record) * n_in);
-  if (rc != GRN_SUCCESS) {
-    return rc;
-  }
-  tmp_in = (grn_ts_record *)tmp_in_buf->ptr;
-  count = 0;
-  for (i = 0; i < n_in; i++) {
-    if (!buf_ptrs[0][i]) {
-      tmp_in[count++] = in[i];
-    }
-  }
-
-  /* Evaluate the 2nd argument. */
-  rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[1], tmp_in, count,
-                                        &node->bufs[1]);
-  buf_ptrs[1] = (grn_ts_bool *)node->bufs[1].ptr;
-
-  /* Merge the results. */
-  count = 0;
-  for (i = 0, j = 0; i < n_in; i++) {
-    out_ptr[count++] = buf_ptrs[0][i] || buf_ptrs[1][j++];
-  }
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_op_logical_sub_evaluate() evaluates an operator. */
-static grn_rc
-grn_ts_op_logical_sub_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node,
-                               const grn_ts_record *in, size_t n_in,
-                               void *out) {
-  size_t i, j, count;
-  grn_rc rc;
-  grn_ts_bool *buf_ptrs[2], *out_ptr = (grn_ts_bool *)out;
-  grn_ts_buf *tmp_in_buf = &node->bufs[2];
-  grn_ts_record *tmp_in;
-
-  /* Evaluate the 1st argument. */
-  rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[0], in, n_in,
-                                        &node->bufs[0]);
-  if (rc != GRN_SUCCESS) {
-    return rc;
-  }
-  buf_ptrs[0] = (grn_ts_bool *)node->bufs[0].ptr;
-
-  /* Create a list of true records. */
-  rc = grn_ts_buf_reserve(ctx, tmp_in_buf, sizeof(grn_ts_record) * n_in);
-  if (rc != GRN_SUCCESS) {
-    return rc;
-  }
-  tmp_in = (grn_ts_record *)tmp_in_buf->ptr;
-  count = 0;
-  for (i = 0; i < n_in; i++) {
-    if (buf_ptrs[0][i]) {
-      tmp_in[count++] = in[i];
-    }
-  }
-
-  /* Evaluate the 2nd argument. */
-  rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[1], tmp_in, count,
-                                        &node->bufs[1]);
-  buf_ptrs[1] = (grn_ts_bool *)node->bufs[1].ptr;
-
-  /* Merge the results. */
-  count = 0;
-  for (i = 0, j = 0; i < n_in; i++) {
-    out_ptr[count++] = buf_ptrs[0][i] &&
-                       grn_ts_op_logical_not_bool(buf_ptrs[1][j++]);
-  }
-  return GRN_SUCCESS;
-}
-
-#define GRN_TS_OP_BITWISE_EVALUATE_CASE(type, KIND, kind)\
-  case GRN_TS_ ## KIND: {\
-    /*
-     * Use the output buffer to put evaluation results of the 1st argument,
-     * because the data kind is same.
-     */\
-    size_t i;\
-    grn_rc rc;\
-    grn_ts_ ## kind *out_ptr = (grn_ts_ ## kind *)out;\
-    rc = grn_ts_expr_node_evaluate(ctx, node->args[0], in, n_in, out);\
-    if (rc == GRN_SUCCESS) {\
-      rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[1],\
-                                            in, n_in, &node->bufs[0]);\
-      if (rc == GRN_SUCCESS) {\
-        grn_ts_ ## kind *buf_ptr = (grn_ts_ ## kind *)node->bufs[0].ptr;\
-        for (i = 0; i < n_in; i++) {\
-          out_ptr[i] = grn_ts_op_bitwise_ ## type ## _ ## kind(out_ptr[i],\
-                                                               buf_ptr[i]);\
-        }\
-      }\
-    }\
-    return rc;\
-  }
-/* grn_ts_op_bitwise_and_evaluate() evaluates an operator. */
-static grn_rc
-grn_ts_op_bitwise_and_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node,
-                               const grn_ts_record *in, size_t n_in,
-                               void *out) {
-  switch (node->args[0]->data_kind) {
-    GRN_TS_OP_BITWISE_EVALUATE_CASE(and, BOOL, bool)
-    GRN_TS_OP_BITWISE_EVALUATE_CASE(and, INT, int)
-    default: {
-      GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d",
-                        node->args[0]->data_kind);
-    }
-  }
-}
-
-/* grn_ts_op_bitwise_or_evaluate() evaluates an operator. */
-static grn_rc
-grn_ts_op_bitwise_or_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node,
-                              const grn_ts_record *in, size_t n_in,
-                              void *out) {
-  switch (node->args[0]->data_kind) {
-    GRN_TS_OP_BITWISE_EVALUATE_CASE(or, BOOL, bool)
-    GRN_TS_OP_BITWISE_EVALUATE_CASE(or, INT, int)
-    default: {
-      GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d",
-                        node->args[0]->data_kind);
-    }
-  }
-}
-
-/* grn_ts_op_bitwise_xor_evaluate() evaluates an operator. */
-static grn_rc
-grn_ts_op_bitwise_xor_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node,
-                               const grn_ts_record *in, size_t n_in,
-                               void *out) {
-  switch (node->args[0]->data_kind) {
-    GRN_TS_OP_BITWISE_EVALUATE_CASE(xor, BOOL, bool)
-    GRN_TS_OP_BITWISE_EVALUATE_CASE(xor, INT, int)
-    default: {
-      GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d",
-                        node->args[0]->data_kind);
-    }
-  }
-}
-#undef GRN_TS_OP_BITWISE_EVALUATE_CASE
-
-#define GRN_TS_OP_CHK_EVALUATE_CASE(type, KIND, kind)\
-  case GRN_TS_ ## KIND: {\
-    grn_ts_ ## kind *buf_ptrs[] = {\
-      (grn_ts_ ## kind *)node->bufs[0].ptr,\
-      (grn_ts_ ## kind *)node->bufs[1].ptr\
-    };\
-    for (i = 0; i < n_in; i++) {\
-      out_ptr[i] = grn_ts_op_ ## type ## _ ## kind(buf_ptrs[0][i],\
-                                                   buf_ptrs[1][i]);\
-    }\
-    return GRN_SUCCESS;\
-  }
-#define GRN_TS_OP_CHK_EVALUATE_VECTOR_CASE(type, KIND, kind)\
-  GRN_TS_OP_CHK_EVALUATE_CASE(type, KIND ## _VECTOR, kind ## _vector)
-#define GRN_TS_OP_CHK_EVALUATE(type)\
-  size_t i;\
-  grn_rc rc;\
-  grn_ts_bool *out_ptr = (grn_ts_bool *)out;\
-  if (node->args[0]->data_kind == GRN_TS_BOOL) {\
-    /*
-     * Use the output buffer to put evaluation results of the 1st argument,
-     * because the data kind is same.
-     */\
-    rc = grn_ts_expr_node_evaluate(ctx, node->args[0], in, n_in, out);\
-    if (rc == GRN_SUCCESS) {\
-      grn_ts_buf *buf = &node->bufs[0];\
-      rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[1],\
-                                            in, n_in, buf);\
-      if (rc == GRN_SUCCESS) {\
-        grn_ts_bool *buf_ptr = (grn_ts_bool *)buf->ptr;\
-        for (i = 0; i < n_in; i++) {\
-          out_ptr[i] = grn_ts_op_ ## type ## _bool(out_ptr[i], buf_ptr[i]);\
-        }\
-      }\
-    }\
-    return rc;\
-  }\
-  for (i = 0; i < 2; i++) {\
-    rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[i], in, n_in,\
-                                          &node->bufs[i]);\
-    if (rc != GRN_SUCCESS) {\
-      return rc;\
-    }\
-  }\
-  switch (node->args[0]->data_kind) {\
-    GRN_TS_OP_CHK_EVALUATE_CASE(type, INT, int)\
-    GRN_TS_OP_CHK_EVALUATE_CASE(type, FLOAT, float)\
-    GRN_TS_OP_CHK_EVALUATE_CASE(type, TIME, time)\
-    GRN_TS_OP_CHK_EVALUATE_CASE(type, TEXT, text)\
-    GRN_TS_OP_CHK_EVALUATE_CASE(type, GEO, geo)\
-    GRN_TS_OP_CHK_EVALUATE_CASE(type, REF, ref)\
-    GRN_TS_OP_CHK_EVALUATE_VECTOR_CASE(type, BOOL, bool)\
-    GRN_TS_OP_CHK_EVALUATE_VECTOR_CASE(type, INT, int)\
-    GRN_TS_OP_CHK_EVALUATE_VECTOR_CASE(type, FLOAT, float)\
-    GRN_TS_OP_CHK_EVALUATE_VECTOR_CASE(type, TIME, time)\
-    GRN_TS_OP_CHK_EVALUATE_VECTOR_CASE(type, TEXT, text)\
-    GRN_TS_OP_CHK_EVALUATE_VECTOR_CASE(type, GEO, geo)\
-    GRN_TS_OP_CHK_EVALUATE_VECTOR_CASE(type, REF, ref)\
-    default: {\
-      GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d",\
-                        node->args[0]->data_kind);\
-    }\
-  }
-/* grn_ts_op_equal_evaluate() evaluates an operator. */
-static grn_rc
-grn_ts_op_equal_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node,
-                         const grn_ts_record *in, size_t n_in, void *out) {
-  GRN_TS_OP_CHK_EVALUATE(equal)
-}
-
-/* grn_ts_op_not_equal_evaluate() evaluates an operator. */
-static grn_rc
-grn_ts_op_not_equal_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node,
-                             const grn_ts_record *in, size_t n_in, void *out) {
-  GRN_TS_OP_CHK_EVALUATE(not_equal)
-}
-#undef GRN_TS_OP_CHK_EVALUATE
-#undef GRN_TS_OP_CHK_EVALUATE_VECTOR_CASE
-#undef GRN_TS_OP_CHK_EVALUATE_CASE
-
-#define GRN_TS_OP_CMP_EVALUATE_CASE(type, KIND, kind)\
-  case GRN_TS_ ## KIND: {\
-    grn_ts_ ## kind *buf_ptrs[] = {\
-      (grn_ts_ ## kind *)node->bufs[0].ptr,\
-      (grn_ts_ ## kind *)node->bufs[1].ptr\
-    };\
-    for (i = 0; i < n_in; i++) {\
-      out_ptr[i] = grn_ts_op_ ## type ## _ ## kind(buf_ptrs[0][i],\
-                                                   buf_ptrs[1][i]);\
-    }\
-    return GRN_SUCCESS;\
-  }
-#define GRN_TS_OP_CMP_EVALUATE_VECTOR_CASE(type, KIND, kind)\
-  GRN_TS_OP_CMP_EVALUATE_CASE(type, KIND ## _VECTOR, kind ## _vector)
-#define GRN_TS_OP_CMP_EVALUATE(type)\
-  size_t i;\
-  grn_rc rc;\
-  grn_ts_bool *out_ptr = (grn_ts_bool *)out;\
-  for (i = 0; i < 2; i++) {\
-    rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[i], in, n_in,\
-                                          &node->bufs[i]);\
-    if (rc != GRN_SUCCESS) {\
-      return rc;\
-    }\
-  }\
-  switch (node->args[0]->data_kind) {\
-    GRN_TS_OP_CMP_EVALUATE_CASE(type, INT, int)\
-    GRN_TS_OP_CMP_EVALUATE_CASE(type, FLOAT, float)\
-    GRN_TS_OP_CMP_EVALUATE_CASE(type, TIME, time)\
-    GRN_TS_OP_CMP_EVALUATE_CASE(type, TEXT, text)\
-    GRN_TS_OP_CMP_EVALUATE_VECTOR_CASE(type, INT, int)\
-    GRN_TS_OP_CMP_EVALUATE_VECTOR_CASE(type, FLOAT, float)\
-    GRN_TS_OP_CMP_EVALUATE_VECTOR_CASE(type, TIME, time)\
-    GRN_TS_OP_CMP_EVALUATE_VECTOR_CASE(type, TEXT, text)\
-    default: {\
-      GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d",\
-                        node->args[0]->data_kind);\
-    }\
-  }
-/* grn_ts_op_less_evaluate() evaluates an operator. */
-static grn_rc
-grn_ts_op_less_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node,
-                        const grn_ts_record *in, size_t n_in, void *out) {
-  GRN_TS_OP_CMP_EVALUATE(less)
-}
-
-/* grn_ts_op_less_equal_evaluate() evaluates an operator. */
-static grn_rc
-grn_ts_op_less_equal_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node,
-                              const grn_ts_record *in, size_t n_in,
-                              void *out) {
-  GRN_TS_OP_CMP_EVALUATE(less_equal)
-}
-
-/* grn_ts_op_greater_evaluate() evaluates an operator. */
-static grn_rc
-grn_ts_op_greater_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node,
-                           const grn_ts_record *in, size_t n_in, void *out) {
-  GRN_TS_OP_CMP_EVALUATE(greater)
-}
-
-/* grn_ts_op_greater_equal_evaluate() evaluates an operator. */
-static grn_rc
-grn_ts_op_greater_equal_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node,
-                                 const grn_ts_record *in, size_t n_in,
-                                 void *out) {
-  GRN_TS_OP_CMP_EVALUATE(greater_equal)
-}
-#undef GRN_TS_OP_CMP_EVALUATE
-#undef GRN_TS_OP_CMP_EVALUATE_VECTOR_CASE
-#undef GRN_TS_OP_CMP_EVALUATE_CASE
-
-#define GRN_TS_OP_SHIFT_EVALUATE(type)\
-  size_t i;\
-  grn_rc rc;\
-  grn_ts_int *out_ptr = (grn_ts_int *)out;\
-  rc = grn_ts_expr_node_evaluate(ctx, node->args[0], in, n_in, out);\
-  if (rc == GRN_SUCCESS) {\
-    rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[1],\
-                                          in, n_in, &node->bufs[0]);\
-    if (rc == GRN_SUCCESS) {\
-      grn_ts_int *buf_ptr = (grn_ts_int *)node->bufs[0].ptr;\
-      for (i = 0; i < n_in; i++) {\
-        out_ptr[i] = grn_ts_op_shift_ ## type(out_ptr[i], buf_ptr[i]);\
-      }\
-    }\
-  }\
-  return rc;
-/* grn_ts_op_shift_arithmetic_left_evaluate() evaluates an operator. */
-static grn_rc
-grn_ts_op_shift_arithmetic_left_evaluate(grn_ctx *ctx,
-                                         grn_ts_expr_op_node *node,
-                                         const grn_ts_record *in, size_t n_in,
-                                         void *out) {
-  GRN_TS_OP_SHIFT_EVALUATE(arithmetic_left)
-}
-
-/* grn_ts_op_shift_arithmetic_right_evaluate() evaluates an operator. */
-static grn_rc
-grn_ts_op_shift_arithmetic_right_evaluate(grn_ctx *ctx,
-                                          grn_ts_expr_op_node *node,
-                                          const grn_ts_record *in, size_t n_in,
-                                          void *out) {
-  GRN_TS_OP_SHIFT_EVALUATE(arithmetic_right)
-}
-
-/* grn_ts_op_shift_logical_left_evaluate() evaluates an operator. */
-static grn_rc
-grn_ts_op_shift_logical_left_evaluate(grn_ctx *ctx,
-                                      grn_ts_expr_op_node *node,
-                                      const grn_ts_record *in, size_t n_in,
-                                      void *out) {
-  GRN_TS_OP_SHIFT_EVALUATE(logical_left)
-}
-
-/* grn_ts_op_shift_logical_right_evaluate() evaluates an operator. */
-static grn_rc
-grn_ts_op_shift_logical_right_evaluate(grn_ctx *ctx,
-                                       grn_ts_expr_op_node *node,
-                                       const grn_ts_record *in, size_t n_in,
-                                       void *out) {
-  GRN_TS_OP_SHIFT_EVALUATE(logical_right)
-}
-#undef GRN_TS_OP_SHIFT_EVALUATE
-
-#define GRN_TS_OP_ARITH_EVALUATE(type, lhs_kind, rhs_kind)\
-  /*
-   * Use the output buffer to put evaluation results of the 1st argument,
-   * because the data kind is same.
-   */\
-  size_t i;\
-  grn_rc rc;\
-  grn_ts_ ## lhs_kind *out_ptr = (grn_ts_ ## lhs_kind *)out;\
-  rc = grn_ts_expr_node_evaluate(ctx, node->args[0], in, n_in, out);\
-  if (rc == GRN_SUCCESS) {\
-    rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[1],\
-                                          in, n_in, &node->bufs[0]);\
-    if (rc == GRN_SUCCESS) {\
-      grn_ts_ ## rhs_kind *buf_ptr = (grn_ts_ ## rhs_kind *)node->bufs[0].ptr;\
-      for (i = 0; i < n_in; i++) {\
-        rc = grn_ts_op_ ## type ## _ ## lhs_kind ## _ ## rhs_kind(\
-          ctx, out_ptr[i], buf_ptr[i], &out_ptr[i]);\
-        if (rc != GRN_SUCCESS) {\
-          return rc;\
-        }\
-      }\
-    }\
-  }\
-  return rc;
-
-#define GRN_TS_OP_ARITH_EVALUATE_CASE(type, KIND, kind)\
-  case GRN_TS_ ## KIND: {\
-    /*
-     * Use the output buffer to put evaluation results of the 1st argument,
-     * because the data kind is same.
-     */\
-    size_t i;\
-    grn_rc rc;\
-    grn_ts_ ## kind *out_ptr = (grn_ts_ ## kind *)out;\
-    rc = grn_ts_expr_node_evaluate(ctx, node->args[0], in, n_in, out);\
-    if (rc == GRN_SUCCESS) {\
-      rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[1],\
-                                            in, n_in, &node->bufs[0]);\
-      if (rc == GRN_SUCCESS) {\
-        grn_ts_ ## kind *buf_ptr = (grn_ts_ ## kind *)node->bufs[0].ptr;\
-        for (i = 0; i < n_in; i++) {\
-          out_ptr[i] = grn_ts_op_ ## type ## _ ## kind(out_ptr[i],\
-                                                       buf_ptr[i]);\
-        }\
-      }\
-    }\
-    return rc;\
-  }
-#define GRN_TS_OP_ARITH_EVALUATE_TIME_CASE(type, KIND, lhs, rhs)\
-  case GRN_TS_ ## KIND: {\
-    /*
-     * Use the output buffer to put evaluation results of the 1st argument,
-     * because the data kind is same.
-     */\
-    size_t i;\
-    grn_rc rc;\
-    grn_ts_ ## lhs *out_ptr = (grn_ts_ ## lhs *)out;\
-    rc = grn_ts_expr_node_evaluate(ctx, node->args[0], in, n_in, out);\
-    if (rc == GRN_SUCCESS) {\
-      rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[1],\
-                                            in, n_in, &node->bufs[0]);\
-      if (rc == GRN_SUCCESS) {\
-        grn_ts_ ## rhs *buf_ptr = (grn_ts_ ## rhs *)node->bufs[0].ptr;\
-        for (i = 0; i < n_in; i++) {\
-          out_ptr[i] = grn_ts_op_ ## type ## _ ## lhs ## _ ## rhs(out_ptr[i],\
-                                                                  buf_ptr[i]);\
-        }\
-      }\
-    }\
-    return rc;\
-  }
-/* grn_ts_op_plus_evaluate() evaluates an operator. */
-static grn_rc
-grn_ts_op_plus_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node,
-                        const grn_ts_record *in, size_t n_in, void *out) {
-  switch (node->args[0]->data_kind) {
-    case GRN_TS_INT: {
-      GRN_TS_OP_ARITH_EVALUATE(plus, int, int)
-    }
-    case GRN_TS_FLOAT: {
-      GRN_TS_OP_ARITH_EVALUATE(plus, float, float)
-    }
-    case GRN_TS_TIME: {
-      switch (node->args[1]->data_kind) {
-        case GRN_TS_INT: {
-          GRN_TS_OP_ARITH_EVALUATE(plus, time, int)
-        }
-        case GRN_TS_FLOAT: {
-          GRN_TS_OP_ARITH_EVALUATE(plus, time, float)
-        }
-        default: {
-          GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "data kind conflict: %d, %d",
-                            node->args[0]->data_kind,
-                            node->args[1]->data_kind);
-        }
-      }
-    }
-    default: {
-      GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d",
-                        node->args[0]->data_kind);
-    }
-  }
-}
-
-/* grn_ts_op_minus_evaluate() evaluates an operator. */
-static grn_rc
-grn_ts_op_minus_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node,
-                         const grn_ts_record *in, size_t n_in, void *out) {
-  switch (node->args[0]->data_kind) {
-    case GRN_TS_INT: {
-      GRN_TS_OP_ARITH_EVALUATE(minus, int, int)
-    }
-    case GRN_TS_FLOAT: {
-      GRN_TS_OP_ARITH_EVALUATE(minus, float, float)
-    }
-    case GRN_TS_TIME: {
-      switch (node->args[1]->data_kind) {
-        case GRN_TS_INT: {
-          GRN_TS_OP_ARITH_EVALUATE(minus, time, int)
-        }
-        case GRN_TS_FLOAT: {
-          GRN_TS_OP_ARITH_EVALUATE(minus, time, float)
-        }
-        case GRN_TS_TIME: {
-          size_t i;
-          grn_rc rc;
-          grn_ts_float *out_ptr = (grn_ts_float *)out;
-          grn_ts_time *buf_ptrs[2];
-          rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[0], in, n_in,
-                                                &node->bufs[0]);
-          if (rc != GRN_SUCCESS) {
-            return rc;
-          }
-          rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[1], in, n_in,
-                                                &node->bufs[1]);
-          if (rc != GRN_SUCCESS) {
-            return rc;
-          }
-          buf_ptrs[0] = (grn_ts_time *)node->bufs[0].ptr;
-          buf_ptrs[1] = (grn_ts_time *)node->bufs[1].ptr;
-          for (i = 0; i < n_in; i++) {
-            rc = grn_ts_op_minus_time_time(ctx, buf_ptrs[0][i], buf_ptrs[1][i],
-                                           &out_ptr[i]);
-            if (rc != GRN_SUCCESS) {
-              return rc;
-            }
-          }
-          return GRN_SUCCESS;
-        }
-        default: {
-          GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "data kind conflict: %d, %d",
-                            node->args[0]->data_kind,
-                            node->args[1]->data_kind);
-        }
-      }
-    }
-    default: {
-      GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d",
-                        node->args[0]->data_kind);
-    }
-  }
-}
-#undef GRN_TS_OP_ARITH_EVALUATE_TIME_CASE
-
-/* grn_ts_op_multiplication_evaluate() evaluates an operator. */
-static grn_rc
-grn_ts_op_multiplication_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node,
-                                  const grn_ts_record *in, size_t n_in,
-                                  void *out) {
-  switch (node->data_kind) {
-    case GRN_TS_INT: {
-      GRN_TS_OP_ARITH_EVALUATE(multiplication, int, int)
-    }
-    case GRN_TS_FLOAT: {
-      GRN_TS_OP_ARITH_EVALUATE(multiplication, float, float)
-    }
-    default: {
-      GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d",
-                        node->data_kind);
-    }
-  }
-}
-
-/* grn_ts_op_division_evaluate() evaluates an operator. */
-static grn_rc
-grn_ts_op_division_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node,
-                            const grn_ts_record *in, size_t n_in, void *out) {
-  switch (node->data_kind) {
-    case GRN_TS_INT: {
-      GRN_TS_OP_ARITH_EVALUATE(division, int, int)
-    }
-    case GRN_TS_FLOAT: {
-      GRN_TS_OP_ARITH_EVALUATE(division, float, float)
-    }
-    default: {
-      GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d",
-                        node->data_kind);
-    }
-  }
-}
-
-/* grn_ts_op_modulus_evaluate() evaluates an operator. */
-static grn_rc
-grn_ts_op_modulus_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node,
-                           const grn_ts_record *in, size_t n_in, void *out) {
-  switch (node->data_kind) {
-    case GRN_TS_INT: {
-      GRN_TS_OP_ARITH_EVALUATE(modulus, int, int)
-    }
-    case GRN_TS_FLOAT: {
-      GRN_TS_OP_ARITH_EVALUATE(modulus, float, float)
-    }
-    default: {
-      GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d",
-                        node->data_kind);
-    }
-  }
-}
-#undef GRN_TS_OP_ARITH_EVALUATE_CASE
-
-/* grn_ts_expr_op_node_evaluate() evaluates an operator. */
-static grn_rc
-grn_ts_expr_op_node_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node,
-                             const grn_ts_record *in, size_t n_in,
-                             void *out) {
-  switch (node->op_type) {
-    case GRN_TS_OP_LOGICAL_NOT: {
-      return grn_ts_op_logical_not_evaluate(ctx, node, in, n_in, out);
-    }
-    case GRN_TS_OP_BITWISE_NOT: {
-      return grn_ts_op_bitwise_not_evaluate(ctx, node, in, n_in, out);
-    }
-    case GRN_TS_OP_POSITIVE: {
-      return grn_ts_op_positive_evaluate(ctx, node, in, n_in, out);
-    }
-    case GRN_TS_OP_NEGATIVE: {
-      return grn_ts_op_negative_evaluate(ctx, node, in, n_in, out);
-    }
-    case GRN_TS_OP_LOGICAL_AND: {
-      return grn_ts_op_logical_and_evaluate(ctx, node, in, n_in, out);
-    }
-    case GRN_TS_OP_LOGICAL_OR: {
-      return grn_ts_op_logical_or_evaluate(ctx, node, in, n_in, out);
-    }
-    case GRN_TS_OP_LOGICAL_SUB: {
-      return grn_ts_op_logical_sub_evaluate(ctx, node, in, n_in, out);
-    }
-    case GRN_TS_OP_BITWISE_AND: {
-      return grn_ts_op_bitwise_and_evaluate(ctx, node, in, n_in, out);
-    }
-    case GRN_TS_OP_BITWISE_OR: {
-      return grn_ts_op_bitwise_or_evaluate(ctx, node, in, n_in, out);
-    }
-    case GRN_TS_OP_BITWISE_XOR: {
-      return grn_ts_op_bitwise_xor_evaluate(ctx, node, in, n_in, out);
-    }
-    case GRN_TS_OP_EQUAL: {
-      return grn_ts_op_equal_evaluate(ctx, node, in, n_in, out);
-    }
-    case GRN_TS_OP_NOT_EQUAL: {
-      return grn_ts_op_not_equal_evaluate(ctx, node, in, n_in, out);
-    }
-    case GRN_TS_OP_LESS: {
-      return grn_ts_op_less_evaluate(ctx, node, in, n_in, out);
-    }
-    case GRN_TS_OP_LESS_EQUAL: {
-      return grn_ts_op_less_equal_evaluate(ctx, node, in, n_in, out);
-    }
-    case GRN_TS_OP_GREATER: {
-      return grn_ts_op_greater_evaluate(ctx, node, in, n_in, out);
-    }
-    case GRN_TS_OP_GREATER_EQUAL: {
-      return grn_ts_op_greater_equal_evaluate(ctx, node, in, n_in, out);
-    }
-    case GRN_TS_OP_SHIFT_ARITHMETIC_LEFT: {
-      return grn_ts_op_shift_arithmetic_left_evaluate(ctx, node, in, n_in, out);
-    }
-    case GRN_TS_OP_SHIFT_ARITHMETIC_RIGHT: {
-      return grn_ts_op_shift_arithmetic_right_evaluate(ctx, node, in, n_in, out);
-    }
-    case GRN_TS_OP_SHIFT_LOGICAL_LEFT: {
-      return grn_ts_op_shift_logical_left_evaluate(ctx, node, in, n_in, out);
-    }
-    case GRN_TS_OP_SHIFT_LOGICAL_RIGHT: {
-      return grn_ts_op_shift_logical_right_evaluate(ctx, node, in, n_in, out);
-    }
-    case GRN_TS_OP_PLUS: {
-      return grn_ts_op_plus_evaluate(ctx, node, in, n_in, out);
-    }
-    case GRN_TS_OP_MINUS: {
-      return grn_ts_op_minus_evaluate(ctx, node, in, n_in, out);
-    }
-    case GRN_TS_OP_MULTIPLICATION: {
-      return grn_ts_op_multiplication_evaluate(ctx, node, in, n_in, out);
-    }
-    case GRN_TS_OP_DIVISION: {
-      return grn_ts_op_division_evaluate(ctx, node, in, n_in, out);
-    }
-    case GRN_TS_OP_MODULUS: {
-      return grn_ts_op_modulus_evaluate(ctx, node, in, n_in, out);
-    }
-    // TODO: Add operators.
-    default: {
-      GRN_TS_ERR_RETURN(GRN_OPERATION_NOT_SUPPORTED,
-                        "operator not supported: %d", node->op_type);
-    }
-  }
-}
-
-/* grn_ts_op_logical_not_filter() filters records. */
-static grn_rc
-grn_ts_op_logical_not_filter(grn_ctx *ctx, grn_ts_expr_op_node *node,
-                             grn_ts_record *in, size_t n_in,
-                             grn_ts_record *out, size_t *n_out) {
-  size_t i, count;
-  grn_rc rc;
-  grn_ts_bool *buf_ptr;
-  rc = grn_ts_buf_reserve(ctx, &node->bufs[0], sizeof(grn_ts_bool) * n_in);
-  if (rc != GRN_SUCCESS) {
-    return rc;
-  }
-  buf_ptr = (grn_ts_bool *)node->bufs[0].ptr;
-  rc = grn_ts_expr_node_evaluate(ctx, node->args[0], in, n_in, buf_ptr);
-  if (rc != GRN_SUCCESS) {
-    return rc;
-  }
-  for (i = 0, count = 0; i < n_in; i++) {
-    if (grn_ts_op_logical_not_bool(buf_ptr[i])) {
-      out[count++] = in[i];
-    }
-  }
-  *n_out = count;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_op_bitwise_not_filter() filters records. */
-static grn_rc
-grn_ts_op_bitwise_not_filter(grn_ctx *ctx, grn_ts_expr_op_node *node,
-                             grn_ts_record *in, size_t n_in,
-                             grn_ts_record *out, size_t *n_out) {
-  size_t i, count;
-  grn_rc rc;
-  grn_ts_bool *buf_ptr;
-  rc = grn_ts_buf_reserve(ctx, &node->bufs[0], sizeof(grn_ts_bool) * n_in);
-  if (rc != GRN_SUCCESS) {
-    return rc;
-  }
-  buf_ptr = (grn_ts_bool *)node->bufs[0].ptr;
-  rc = grn_ts_expr_node_evaluate(ctx, node->args[0], in, n_in, buf_ptr);
-  if (rc != GRN_SUCCESS) {
-    return rc;
-  }
-  for (i = 0, count = 0; i < n_in; i++) {
-    if (grn_ts_op_bitwise_not_bool(buf_ptr[i])) {
-      out[count++] = in[i];
-    }
-  }
-  *n_out = count;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_op_logical_and_filter() filters records. */
-static grn_rc
-grn_ts_op_logical_and_filter(grn_ctx *ctx, grn_ts_expr_op_node *node,
-                             grn_ts_record *in, size_t n_in,
-                             grn_ts_record *out, size_t *n_out) {
-  grn_rc rc = grn_ts_expr_node_filter(ctx, node->args[0], in, n_in,
-                                      out, n_out);
-  if (rc != GRN_SUCCESS) {
-    return rc;
-  }
-  return grn_ts_expr_node_filter(ctx, node->args[1], out, *n_out, out, n_out);
-}
-
-/* grn_ts_op_logical_or_filter() filters records. */
-static grn_rc
-grn_ts_op_logical_or_filter(grn_ctx *ctx, grn_ts_expr_op_node *node,
-                            grn_ts_record *in, size_t n_in,
-                            grn_ts_record *out, size_t *n_out) {
-  size_t i, j, count;
-  grn_rc rc;
-  grn_ts_bool *buf_ptrs[2];
-  grn_ts_buf *tmp_in_buf = &node->bufs[2];
-  grn_ts_record *tmp_in;
-
-  /* Evaluate the 1st argument. */
-  rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[0], in, n_in,
-                                        &node->bufs[0]);
-  if (rc != GRN_SUCCESS) {
-    return rc;
-  }
-  buf_ptrs[0] = (grn_ts_bool *)node->bufs[0].ptr;
-
-  /* Create a list of false records. */
-  rc = grn_ts_buf_reserve(ctx, tmp_in_buf, sizeof(grn_ts_record) * n_in);
-  if (rc != GRN_SUCCESS) {
-    return rc;
-  }
-  tmp_in = (grn_ts_record *)tmp_in_buf->ptr;
-  count = 0;
-  for (i = 0; i < n_in; i++) {
-    if (!buf_ptrs[0][i]) {
-      tmp_in[count++] = in[i];
-    }
-  }
-
-  /* Evaluate the 2nd argument. */
-  rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[1], tmp_in, count,
-                                        &node->bufs[1]);
-  buf_ptrs[1] = (grn_ts_bool *)node->bufs[1].ptr;
-
-  /* Merge the results. */
-  count = 0;
-  for (i = 0, j = 0; i < n_in; i++) {
-    if (buf_ptrs[0][i] || buf_ptrs[1][j++]) {
-      out[count++] = in[i];
-    }
-  }
-  *n_out = count;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_op_logical_sub_filter() filters records. */
-static grn_rc
-grn_ts_op_logical_sub_filter(grn_ctx *ctx, grn_ts_expr_op_node *node,
-                             grn_ts_record *in, size_t n_in,
-                             grn_ts_record *out, size_t *n_out) {
-  size_t i, n, count;
-  grn_ts_bool *buf_ptr;
-  grn_rc rc = grn_ts_expr_node_filter(ctx, node->args[0], in, n_in, out, &n);
-  if (rc != GRN_SUCCESS) {
-    return rc;
-  }
-  rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[1], out, n,
-                                        &node->bufs[0]);
-  buf_ptr = (grn_ts_bool *)node->bufs[0].ptr;
-  for (i = 0, count = 0; i < n; i++) {
-    if (grn_ts_op_logical_not_bool(buf_ptr[i])) {
-      out[count++] = out[i];
-    }
-  }
-  *n_out = count;
-  return GRN_SUCCESS;
-}
-
-#define GRN_TS_OP_BITWISE_FILTER(type)\
-  size_t i, count = 0;\
-  grn_ts_bool *buf_ptrs[2];\
-  for (i = 0; i < 2; i++) {\
-    grn_rc rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[i], in, n_in,\
-                                                 &node->bufs[i]);\
-    if (rc != GRN_SUCCESS) {\
-      return rc;\
-    }\
-    buf_ptrs[i] = (grn_ts_bool *)node->bufs[i].ptr;\
-  }\
-  for (i = 0; i < n_in; i++) {\
-    if (grn_ts_op_bitwise_ ## type ## _bool(buf_ptrs[0][i], buf_ptrs[1][i])) {\
-      out[count++] = in[i];\
-    }\
-  }\
-  *n_out = count;\
-  return GRN_SUCCESS;\
-/* grn_ts_op_bitwise_and_filter() filters records. */
-static grn_rc
-grn_ts_op_bitwise_and_filter(grn_ctx *ctx, grn_ts_expr_op_node *node,
-                             grn_ts_record *in, size_t n_in,
-                             grn_ts_record *out, size_t *n_out) {
-  GRN_TS_OP_BITWISE_FILTER(and);
-}
-
-/* grn_ts_op_bitwise_or_filter() filters records. */
-static grn_rc
-grn_ts_op_bitwise_or_filter(grn_ctx *ctx, grn_ts_expr_op_node *node,
-                            grn_ts_record *in, size_t n_in,
-                            grn_ts_record *out, size_t *n_out) {
-  GRN_TS_OP_BITWISE_FILTER(or);
-}
-
-/* grn_ts_op_bitwise_xor_filter() filters records. */
-static grn_rc
-grn_ts_op_bitwise_xor_filter(grn_ctx *ctx, grn_ts_expr_op_node *node,
-                             grn_ts_record *in, size_t n_in,
-                             grn_ts_record *out, size_t *n_out) {
-  GRN_TS_OP_BITWISE_FILTER(xor);
-}
-#undef GRN_TS_OP_BITWISE_FILTER_CASE
-
-#define GRN_TS_OP_CHK_FILTER_CASE(type, KIND, kind)\
-  case GRN_TS_ ## KIND: {\
-    grn_ts_ ## kind *buf_ptrs[] = {\
-      (grn_ts_ ## kind *)node->bufs[0].ptr,\
-      (grn_ts_ ## kind *)node->bufs[1].ptr\
-    };\
-    for (i = 0; i < n_in; i++) {\
-      if (grn_ts_op_ ## type ## _ ## kind(buf_ptrs[0][i], buf_ptrs[1][i])) {\
-        out[count++] = in[i];\
-      }\
-    }\
-    *n_out = count;\
-    return GRN_SUCCESS;\
-  }
-#define GRN_TS_OP_CHK_FILTER_VECTOR_CASE(type, KIND, kind)\
-  GRN_TS_OP_CHK_FILTER_CASE(type, KIND ## _VECTOR, kind ## _vector)
-#define GRN_TS_OP_CHK_FILTER(type)\
-  size_t i, count = 0;\
-  for (i = 0; i < 2; i++) {\
-    grn_rc rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[i], in, n_in,\
-                                                 &node->bufs[i]);\
-    if (rc != GRN_SUCCESS) {\
-      return rc;\
-    }\
-  }\
-  switch (node->args[0]->data_kind) {\
-    GRN_TS_OP_CHK_FILTER_CASE(type, BOOL, bool)\
-    GRN_TS_OP_CHK_FILTER_CASE(type, INT, int)\
-    GRN_TS_OP_CHK_FILTER_CASE(type, FLOAT, float)\
-    GRN_TS_OP_CHK_FILTER_CASE(type, TIME, time)\
-    GRN_TS_OP_CHK_FILTER_CASE(type, TEXT, text)\
-    GRN_TS_OP_CHK_FILTER_CASE(type, GEO, geo)\
-    GRN_TS_OP_CHK_FILTER_CASE(type, REF, ref)\
-    GRN_TS_OP_CHK_FILTER_VECTOR_CASE(type, BOOL, bool)\
-    GRN_TS_OP_CHK_FILTER_VECTOR_CASE(type, INT, int)\
-    GRN_TS_OP_CHK_FILTER_VECTOR_CASE(type, FLOAT, float)\
-    GRN_TS_OP_CHK_FILTER_VECTOR_CASE(type, TIME, time)\
-    GRN_TS_OP_CHK_FILTER_VECTOR_CASE(type, TEXT, text)\
-    GRN_TS_OP_CHK_FILTER_VECTOR_CASE(type, GEO, geo)\
-    GRN_TS_OP_CHK_FILTER_VECTOR_CASE(type, REF, ref)\
-    default: {\
-      GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d",\
-                        node->args[0]->data_kind);\
-    }\
-  }
-/* grn_ts_op_equal_filter() filters records. */
-static grn_rc
-grn_ts_op_equal_filter(grn_ctx *ctx, grn_ts_expr_op_node *node,
-                       const grn_ts_record *in, size_t n_in,
-                       grn_ts_record *out, size_t *n_out) {
-  GRN_TS_OP_CHK_FILTER(equal)
-}
-
-/* grn_ts_op_not_equal_filter() filters records. */
-static grn_rc
-grn_ts_op_not_equal_filter(grn_ctx *ctx, grn_ts_expr_op_node *node,
-                           const grn_ts_record *in, size_t n_in,
-                           grn_ts_record *out, size_t *n_out) {
-  GRN_TS_OP_CHK_FILTER(not_equal)
-}
-#undef GRN_TS_OP_CHK_FILTER
-#undef GRN_TS_OP_CHK_FILTER_VECTOR_CASE
-#undef GRN_TS_OP_CHK_FILTER_CASE
-
-#define GRN_TS_OP_CMP_FILTER_CASE(type, KIND, kind)\
-  case GRN_TS_ ## KIND: {\
-    grn_ts_ ## kind *buf_ptrs[] = {\
-      (grn_ts_ ## kind *)node->bufs[0].ptr,\
-      (grn_ts_ ## kind *)node->bufs[1].ptr\
-    };\
-    for (i = 0; i < n_in; i++) {\
-      if (grn_ts_op_ ## type ## _ ## kind(buf_ptrs[0][i], buf_ptrs[1][i])) {\
-        out[count++] = in[i];\
-      }\
-    }\
-    *n_out = count;\
-    return GRN_SUCCESS;\
-  }
-#define GRN_TS_OP_CMP_FILTER_VECTOR_CASE(type, KIND, kind)\
-  GRN_TS_OP_CMP_FILTER_CASE(type, KIND ## _VECTOR, kind ## _vector)
-#define GRN_TS_OP_CMP_FILTER(type)\
-  size_t i, count = 0;\
-  for (i = 0; i < 2; i++) {\
-    grn_rc rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[i], in, n_in,\
-                                                 &node->bufs[i]);\
-    if (rc != GRN_SUCCESS) {\
-      return rc;\
-    }\
-  }\
-  switch (node->args[0]->data_kind) {\
-    GRN_TS_OP_CMP_FILTER_CASE(type, INT, int)\
-    GRN_TS_OP_CMP_FILTER_CASE(type, FLOAT, float)\
-    GRN_TS_OP_CMP_FILTER_CASE(type, TIME, time)\
-    GRN_TS_OP_CMP_FILTER_CASE(type, TEXT, text)\
-    GRN_TS_OP_CMP_FILTER_VECTOR_CASE(type, INT, int)\
-    GRN_TS_OP_CMP_FILTER_VECTOR_CASE(type, FLOAT, float)\
-    GRN_TS_OP_CMP_FILTER_VECTOR_CASE(type, TIME, time)\
-    GRN_TS_OP_CMP_FILTER_VECTOR_CASE(type, TEXT, text)\
-    default: {\
-      GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d",\
-                        node->args[0]->data_kind);\
-    }\
-  }
-/* grn_ts_op_less_filter() filters records. */
-static grn_rc
-grn_ts_op_less_filter(grn_ctx *ctx, grn_ts_expr_op_node *node,
-                      const grn_ts_record *in, size_t n_in,
-                      grn_ts_record *out, size_t *n_out) {
-  GRN_TS_OP_CMP_FILTER(less)
-}
-
-/* grn_ts_op_less_equal_filter() filters records. */
-static grn_rc
-grn_ts_op_less_equal_filter(grn_ctx *ctx, grn_ts_expr_op_node *node,
-                            const grn_ts_record *in, size_t n_in,
-                            grn_ts_record *out, size_t *n_out) {
-  GRN_TS_OP_CMP_FILTER(less_equal)
-}
-
-/* grn_ts_op_greater_filter() filters records. */
-static grn_rc
-grn_ts_op_greater_filter(grn_ctx *ctx, grn_ts_expr_op_node *node,
-                         const grn_ts_record *in, size_t n_in,
-                         grn_ts_record *out, size_t *n_out) {
-  GRN_TS_OP_CMP_FILTER(greater)
-}
-
-/* grn_ts_op_greater_equal_filter() filters records. */
-static grn_rc
-grn_ts_op_greater_equal_filter(grn_ctx *ctx, grn_ts_expr_op_node *node,
-                               const grn_ts_record *in, size_t n_in,
-                               grn_ts_record *out, size_t *n_out) {
-  GRN_TS_OP_CMP_FILTER(greater_equal)
-}
-#undef GRN_TS_OP_CMP_FILTER
-#undef GRN_TS_OP_CMP_FILTER_VECTOR_CASE
-#undef GRN_TS_OP_CMP_FILTER_CASE
-
-/* grn_ts_expr_op_node_filter() filters records. */
-static grn_rc
-grn_ts_expr_op_node_filter(grn_ctx *ctx, grn_ts_expr_op_node *node,
-                           grn_ts_record *in, size_t n_in,
-                           grn_ts_record *out, size_t *n_out) {
-  switch (node->op_type) {
-    case GRN_TS_OP_LOGICAL_NOT: {
-      return grn_ts_op_logical_not_filter(ctx, node, in, n_in, out, n_out);
-    }
-    case GRN_TS_OP_BITWISE_NOT: {
-      return grn_ts_op_bitwise_not_filter(ctx, node, in, n_in, out, n_out);
-    }
-    case GRN_TS_OP_LOGICAL_AND: {
-      return grn_ts_op_logical_and_filter(ctx, node, in, n_in, out, n_out);
-    }
-    case GRN_TS_OP_LOGICAL_OR: {
-      return grn_ts_op_logical_or_filter(ctx, node, in, n_in, out, n_out);
-    }
-    case GRN_TS_OP_LOGICAL_SUB: {
-      return grn_ts_op_logical_sub_filter(ctx, node, in, n_in, out, n_out);
-    }
-    case GRN_TS_OP_BITWISE_AND: {
-      return grn_ts_op_bitwise_and_filter(ctx, node, in, n_in, out, n_out);
-    }
-    case GRN_TS_OP_BITWISE_OR: {
-      return grn_ts_op_bitwise_or_filter(ctx, node, in, n_in, out, n_out);
-    }
-    case GRN_TS_OP_BITWISE_XOR: {
-      return grn_ts_op_bitwise_xor_filter(ctx, node, in, n_in, out, n_out);
-    }
-    case GRN_TS_OP_EQUAL: {
-      return grn_ts_op_equal_filter(ctx, node, in, n_in, out, n_out);
-    }
-    case GRN_TS_OP_NOT_EQUAL: {
-      return grn_ts_op_not_equal_filter(ctx, node, in, n_in, out, n_out);
-    }
-    case GRN_TS_OP_LESS: {
-      return grn_ts_op_less_filter(ctx, node, in, n_in, out, n_out);
-    }
-    case GRN_TS_OP_LESS_EQUAL: {
-      return grn_ts_op_less_equal_filter(ctx, node, in, n_in, out, n_out);
-    }
-    case GRN_TS_OP_GREATER: {
-      return grn_ts_op_greater_filter(ctx, node, in, n_in, out, n_out);
-    }
-    case GRN_TS_OP_GREATER_EQUAL: {
-      return grn_ts_op_greater_equal_filter(ctx, node, in, n_in, out, n_out);
-    }
-    // TODO: Add operators.
-    default: {
-      GRN_TS_ERR_RETURN(GRN_OPERATION_NOT_SUPPORTED,
-                        "operator not supported: %d", node->op_type);
-    }
-  }
-}
-
-#define GRN_TS_OP_SIGN_ADJUST(type)\
-  size_t i, count = 0;\
-  grn_ts_float *buf_ptr;\
-  grn_rc rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[0], io, n_io,\
-                                               &node->bufs[0]);\
-  if (rc != GRN_SUCCESS) {\
-    return rc;\
-  }\
-  buf_ptr = (grn_ts_float *)node->bufs[0].ptr;\
-  for (i = 0; i < n_io; i++) {\
-    grn_ts_float result = grn_ts_op_ ## type ## _float(buf_ptr[i]);\
-    io[count++].score = (grn_ts_score)result;\
-  }\
-  return GRN_SUCCESS;
-/* grn_ts_op_positive_adjust() updates scores. */
-static grn_rc
-grn_ts_op_positive_adjust(grn_ctx *ctx, grn_ts_expr_op_node *node,
-                          grn_ts_record *io, size_t n_io) {
-  GRN_TS_OP_SIGN_ADJUST(positive)
-}
-
-/* grn_ts_op_negative_adjust() updates scores. */
-static grn_rc
-grn_ts_op_negative_adjust(grn_ctx *ctx, grn_ts_expr_op_node *node,
-                          grn_ts_record *io, size_t n_io) {
-  GRN_TS_OP_SIGN_ADJUST(negative)
-}
-#undef GRN_TS_OP_SIGN_ADJUST
-
-#define GRN_TS_OP_ARITH_ADJUST(type)\
-  grn_rc rc;\
-  size_t i, count = 0;\
-  grn_ts_float *buf_ptrs[2];\
-  for (i = 0; i < 2; i++) {\
-    rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[i], io, n_io,\
-                                          &node->bufs[i]);\
-    if (rc != GRN_SUCCESS) {\
-      return rc;\
-    }\
-  }\
-  buf_ptrs[0] = (grn_ts_float *)node->bufs[0].ptr;\
-  buf_ptrs[1] = (grn_ts_float *)node->bufs[1].ptr;\
-  for (i = 0; i < n_io; i++) {\
-    grn_ts_float result;\
-    rc = grn_ts_op_ ## type ## _float_float(ctx, buf_ptrs[0][i],\
-                                            buf_ptrs[1][i], &result);\
-    io[count].score = (grn_ts_score)result;\
-    if (!isfinite(io[count].score)) {\
-      GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid score: %g", result);\
-    }\
-    count++;\
-  }\
-  return GRN_SUCCESS;
-/* grn_ts_op_plus_adjust() updates scores. */
-static grn_rc
-grn_ts_op_plus_adjust(grn_ctx *ctx, grn_ts_expr_op_node *node,
-                      grn_ts_record *io, size_t n_io) {
-  GRN_TS_OP_ARITH_ADJUST(plus)
-}
-
-/* grn_ts_op_minus_adjust() updates scores. */
-static grn_rc
-grn_ts_op_minus_adjust(grn_ctx *ctx, grn_ts_expr_op_node *node,
-                       grn_ts_record *io, size_t n_io) {
-  GRN_TS_OP_ARITH_ADJUST(minus)
-}
-
-/* grn_ts_op_multiplication_adjust() updates scores. */
-static grn_rc
-grn_ts_op_multiplication_adjust(grn_ctx *ctx, grn_ts_expr_op_node *node,
-                                grn_ts_record *io, size_t n_io) {
-  GRN_TS_OP_ARITH_ADJUST(multiplication)
-}
-
-/* grn_ts_op_division_adjust() updates scores. */
-static grn_rc
-grn_ts_op_division_adjust(grn_ctx *ctx, grn_ts_expr_op_node *node,
-                          grn_ts_record *io, size_t n_io) {
-  GRN_TS_OP_ARITH_ADJUST(division)
-}
-
-/* grn_ts_op_modulus_adjust() updates scores. */
-static grn_rc
-grn_ts_op_modulus_adjust(grn_ctx *ctx, grn_ts_expr_op_node *node,
-                         grn_ts_record *io, size_t n_io) {
-  GRN_TS_OP_ARITH_ADJUST(modulus)
-}
-#undef GRN_TS_OP_ARITH_ADJUST
-
-/* grn_ts_expr_op_node_adjust() updates scores. */
-static grn_rc
-grn_ts_expr_op_node_adjust(grn_ctx *ctx, grn_ts_expr_op_node *node,
-                           grn_ts_record *io, size_t n_io) {
-  switch (node->op_type) {
-    case GRN_TS_OP_POSITIVE: {
-      return grn_ts_op_positive_adjust(ctx, node, io, n_io);
-    }
-    case GRN_TS_OP_NEGATIVE: {
-      return grn_ts_op_negative_adjust(ctx, node, io, n_io);
-    }
-    case GRN_TS_OP_PLUS: {
-      return grn_ts_op_plus_adjust(ctx, node, io, n_io);
-    }
-    case GRN_TS_OP_MINUS: {
-      return grn_ts_op_minus_adjust(ctx, node, io, n_io);
-    }
-    case GRN_TS_OP_MULTIPLICATION: {
-      return grn_ts_op_multiplication_adjust(ctx, node, io, n_io);
-    }
-    case GRN_TS_OP_DIVISION: {
-      return grn_ts_op_division_adjust(ctx, node, io, n_io);
-    }
-    case GRN_TS_OP_MODULUS: {
-      return grn_ts_op_modulus_adjust(ctx, node, io, n_io);
-    }
-    // TODO: Add operators.
-    default: {
-      GRN_TS_ERR_RETURN(GRN_OPERATION_NOT_SUPPORTED,
-                        "operator not supported: %d", node->op_type);
-    }
-  }
-}
-
-/*-------------------------------------------------------------
- * grn_ts_expr_bridge_node.
- */
-
-enum { GRN_TS_EXPR_BRIDGE_NODE_N_BUFS = 2 };
-
-typedef struct {
-  GRN_TS_EXPR_NODE_COMMON_MEMBERS
-  grn_ts_expr_node *src;
-  grn_ts_expr_node *dest;
-  grn_ts_buf bufs[GRN_TS_EXPR_BRIDGE_NODE_N_BUFS];
-} grn_ts_expr_bridge_node;
-
-/* grn_ts_expr_bridge_node_init() initializes a node. */
-static void
-grn_ts_expr_bridge_node_init(grn_ctx *ctx, grn_ts_expr_bridge_node *node) {
-  size_t i;
-  memset(node, 0, sizeof(*node));
-  node->type = GRN_TS_EXPR_BRIDGE_NODE;
-  node->src = NULL;
-  node->dest = NULL;
-  for (i = 0; i < GRN_TS_EXPR_BRIDGE_NODE_N_BUFS; i++) {
-    grn_ts_buf_init(ctx, &node->bufs[i]);
-  }
-}
-
-/* grn_ts_expr_bridge_node_fin() finalizes a node. */
-static void
-grn_ts_expr_bridge_node_fin(grn_ctx *ctx, grn_ts_expr_bridge_node *node) {
-  size_t i;
-  for (i = 0; i < GRN_TS_EXPR_BRIDGE_NODE_N_BUFS; i++) {
-    grn_ts_buf_fin(ctx, &node->bufs[i]);
-  }
-}
-
-/* grn_ts_expr_bridge_node_open() creates a node associated with a bridge. */
-static grn_rc
-grn_ts_expr_bridge_node_open(grn_ctx *ctx, grn_ts_expr_node *src,
-                             grn_ts_expr_node *dest, grn_ts_expr_node **node) {
-  grn_ts_expr_bridge_node *new_node = GRN_MALLOCN(grn_ts_expr_bridge_node, 1);
-  if (!new_node) {
-    GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %zu x 1",
-                      sizeof(grn_ts_expr_bridge_node));
-  }
-  grn_ts_expr_bridge_node_init(ctx, new_node);
-  new_node->data_kind = dest->data_kind;
-  new_node->data_type = dest->data_type;
-  new_node->src = src;
-  new_node->dest = dest;
-  *node = (grn_ts_expr_node *)new_node;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_expr_bridge_node_close() destroys a node. */
-static void
-grn_ts_expr_bridge_node_close(grn_ctx *ctx, grn_ts_expr_bridge_node *node) {
-  grn_ts_expr_bridge_node_fin(ctx, node);
-  GRN_FREE(node);
-}
-
-/* grn_ts_expr_bridge_node_evaluate() evaluates a bridge. */
-static grn_rc
-grn_ts_expr_bridge_node_evaluate(grn_ctx *ctx, grn_ts_expr_bridge_node *node,
-                                 const grn_ts_record *in, size_t n_in,
-                                 void *out) {
-  grn_ts_record *tmp;
-  grn_rc rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->src, in, n_in,
-                                               &node->bufs[0]);
-  if (rc != GRN_SUCCESS) {
-    return rc;
-  }
-  tmp = (grn_ts_record *)node->bufs[0].ptr;
-  return grn_ts_expr_node_evaluate(ctx, node->dest, tmp, n_in, out);
-}
-
-/* grn_ts_expr_bridge_node_filter() filters records. */
-static grn_rc
-grn_ts_expr_bridge_node_filter(grn_ctx *ctx, grn_ts_expr_bridge_node *node,
-                               grn_ts_record *in, size_t n_in,
-                               grn_ts_record *out, size_t *n_out) {
-  size_t i, count;
-  grn_ts_bool *values;
-  grn_ts_record *tmp;
-  grn_rc rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->src, in, n_in,
-                                               &node->bufs[0]);
-  if (rc != GRN_SUCCESS) {
-    return rc;
-  }
-  tmp = (grn_ts_record *)node->bufs[0].ptr;
-  rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->dest, in, n_in,
-                                        &node->bufs[1]);
-  if (rc != GRN_SUCCESS) {
-    return rc;
-  }
-  values = (grn_ts_bool *)&node->bufs[1].ptr;
-  for (i = 0, count = 0; i < n_in; i++) {
-    if (values[i]) {
-      out[count++] = in[i];
-    }
-  }
-  *n_out = count;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_expr_bridge_node_adjust() updates scores. */
-static grn_rc
-grn_ts_expr_bridge_node_adjust(grn_ctx *ctx, grn_ts_expr_bridge_node *node,
-                               grn_ts_record *io, size_t n_io) {
-  size_t i;
-  grn_ts_record *tmp;
-  grn_rc rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->src, io, n_io,
-                                               &node->bufs[0]);
-  if (rc != GRN_SUCCESS) {
-    return rc;
-  }
-  tmp = (grn_ts_record *)node->bufs[0].ptr;
-  rc = grn_ts_expr_node_adjust(ctx, node->dest, tmp, n_io);
-  if (rc != GRN_SUCCESS) {
-    return rc;
-  }
-  for (i = 0; i < n_io; i++) {
-    io[i].score = tmp[i].score;
-  }
-  return GRN_SUCCESS;
-}
-
-/*-------------------------------------------------------------
- * grn_ts_expr_node.
- */
-
-#define GRN_TS_EXPR_NODE_CLOSE_CASE(TYPE, type)\
-  case GRN_TS_EXPR_ ## TYPE ## _NODE: {\
-    grn_ts_expr_ ## type ## _node *type ## _node;\
-    type ## _node = (grn_ts_expr_ ## type ## _node *)node;\
-    grn_ts_expr_ ## type ## _node_close(ctx, type ## _node);\
-    return;\
-  }
-/* grn_ts_expr_node_close() destroys a node. */
-static void
-grn_ts_expr_node_close(grn_ctx *ctx, grn_ts_expr_node *node) {
-  switch (node->type) {
-    GRN_TS_EXPR_NODE_CLOSE_CASE(ID, id)
-    GRN_TS_EXPR_NODE_CLOSE_CASE(SCORE, score)
-    GRN_TS_EXPR_NODE_CLOSE_CASE(KEY, key)
-    GRN_TS_EXPR_NODE_CLOSE_CASE(VALUE, value)
-    GRN_TS_EXPR_NODE_CLOSE_CASE(CONST, const)
-    GRN_TS_EXPR_NODE_CLOSE_CASE(COLUMN, column)
-    GRN_TS_EXPR_NODE_CLOSE_CASE(OP, op)
-    GRN_TS_EXPR_NODE_CLOSE_CASE(BRIDGE, bridge)
-  }
-}
-#undef GRN_TS_EXPR_NODE_CLOSE_CASE
-
-#define GRN_TS_EXPR_NODE_EVALUATE_CASE(TYPE, type)\
-  case GRN_TS_EXPR_ ## TYPE ## _NODE: {\
-    grn_ts_expr_ ## type ## _node *type ## _node;\
-    type ## _node = (grn_ts_expr_ ## type ## _node *)node;\
-    return grn_ts_expr_ ## type ## _node_evaluate(ctx, type ## _node,\
-                                                  in, n_in, out);\
-  }
-/* grn_ts_expr_node_evaluate() evaluates a subtree. */
-static grn_rc
-grn_ts_expr_node_evaluate(grn_ctx *ctx, grn_ts_expr_node *node,
-                          const grn_ts_record *in, size_t n_in, void *out) {
-  switch (node->type) {
-    GRN_TS_EXPR_NODE_EVALUATE_CASE(ID, id)
-    GRN_TS_EXPR_NODE_EVALUATE_CASE(SCORE, score)
-    GRN_TS_EXPR_NODE_EVALUATE_CASE(KEY, key)
-    GRN_TS_EXPR_NODE_EVALUATE_CASE(VALUE, value)
-    GRN_TS_EXPR_NODE_EVALUATE_CASE(CONST, const)
-    GRN_TS_EXPR_NODE_EVALUATE_CASE(COLUMN, column)
-    GRN_TS_EXPR_NODE_EVALUATE_CASE(OP, op)
-    GRN_TS_EXPR_NODE_EVALUATE_CASE(BRIDGE, bridge)
-    default: {
-      GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT,
-                        "invalid node type: %d", node->type);
-    }
-  }
-}
-#undef GRN_TS_EXPR_NODE_EVALUATE_CASE
-
-#define GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_CASE(KIND, kind)\
-  case GRN_TS_ ## KIND: {\
-    grn_rc rc = grn_ts_buf_reserve(ctx, out, sizeof(grn_ts_ ## kind) * n_in);\
-    if (rc != GRN_SUCCESS) {\
-      return rc;\
-    }\
-    return grn_ts_expr_node_evaluate(ctx, node, in, n_in, out->ptr);\
-  }
-#define GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_VECTOR_CASE(KIND, kind)\
-  GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_CASE(KIND ## _VECTOR, kind ## _vector)
-/* grn_ts_expr_node_evaluate_to_buf() evaluates a subtree. */
-static grn_rc
-grn_ts_expr_node_evaluate_to_buf(grn_ctx *ctx, grn_ts_expr_node *node,
-                                 const grn_ts_record *in, size_t n_in,
-                                 grn_ts_buf *out) {
-  switch (node->data_kind) {
-    GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_CASE(BOOL, bool)
-    GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_CASE(INT, int)
-    GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_CASE(FLOAT, float)
-    GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_CASE(TIME, time)
-    GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_CASE(TEXT, text)
-    GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_CASE(GEO, geo)
-    GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_CASE(REF, ref)
-    GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_VECTOR_CASE(BOOL, bool)
-    GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_VECTOR_CASE(INT, int)
-    GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_VECTOR_CASE(FLOAT, float)
-    GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_VECTOR_CASE(TIME, time)
-    GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_VECTOR_CASE(TEXT, text)
-    GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_VECTOR_CASE(GEO, geo)
-    GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_VECTOR_CASE(REF, ref)
-    default: {
-      GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT,
-                        "invalid data kind: %d", node->data_kind);
-    }
-  }
-}
-#undef GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_VECTOR_CASE
-#undef GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_CASE
-
-#define GRN_TS_EXPR_NODE_FILTER_CASE(TYPE, type)\
-  case GRN_TS_EXPR_ ## TYPE ## _NODE: {\
-    grn_ts_expr_ ## type ## _node *type ## _node;\
-    type ## _node = (grn_ts_expr_ ## type ## _node *)node;\
-    return grn_ts_expr_ ## type ## _node_filter(ctx, type ## _node,\
-                                                in, n_in, out, n_out);\
-  }
-/* grn_ts_expr_node_filter() filters records. */
-static grn_rc
-grn_ts_expr_node_filter(grn_ctx *ctx, grn_ts_expr_node *node,
-                        grn_ts_record *in, size_t n_in,
-                        grn_ts_record *out, size_t *n_out) {
-  if (node->data_kind != GRN_TS_BOOL) {
-    GRN_TS_ERR_RETURN(GRN_OPERATION_NOT_SUPPORTED,
-                      "invalid data kind: %d", node->data_kind);
-  }
-  switch (node->type) {
-    GRN_TS_EXPR_NODE_FILTER_CASE(KEY, key)
-    GRN_TS_EXPR_NODE_FILTER_CASE(VALUE, value)
-    GRN_TS_EXPR_NODE_FILTER_CASE(CONST, const)
-    GRN_TS_EXPR_NODE_FILTER_CASE(COLUMN, column)
-    GRN_TS_EXPR_NODE_FILTER_CASE(OP, op)
-    GRN_TS_EXPR_NODE_FILTER_CASE(BRIDGE, bridge)
-    default: {
-      GRN_TS_ERR_RETURN(GRN_OPERATION_NOT_SUPPORTED,
-                        "invalid node type: %d", node->type);
-    }
-  }
-}
-#undef GRN_TS_EXPR_NODE_FILTER_CASE
-
-#define GRN_TS_EXPR_NODE_ADJUST_CASE(TYPE, type)\
-  case GRN_TS_EXPR_ ## TYPE ## _NODE: {\
-    grn_ts_expr_ ## type ## _node *type ## _node;\
-    type ## _node = (grn_ts_expr_ ## type ## _node *)node;\
-    return grn_ts_expr_ ## type ## _node_adjust(ctx, type ## _node, io, n_io);\
-  }
-/* grn_ts_expr_node_adjust() updates scores. */
-static grn_rc
-grn_ts_expr_node_adjust(grn_ctx *ctx, grn_ts_expr_node *node,
-                        grn_ts_record *io, size_t n_io) {
-  if (node->data_kind != GRN_TS_FLOAT) {
-    GRN_TS_ERR_RETURN(GRN_OPERATION_NOT_SUPPORTED,
-                      "invalid data kind: %d", node->data_kind);
-  }
-  switch (node->type) {
-    GRN_TS_EXPR_NODE_ADJUST_CASE(SCORE, score)
-    GRN_TS_EXPR_NODE_ADJUST_CASE(KEY, key)
-    GRN_TS_EXPR_NODE_ADJUST_CASE(VALUE, value)
-    GRN_TS_EXPR_NODE_ADJUST_CASE(CONST, const)
-    GRN_TS_EXPR_NODE_ADJUST_CASE(COLUMN, column)
-    GRN_TS_EXPR_NODE_ADJUST_CASE(OP, op)
-    GRN_TS_EXPR_NODE_ADJUST_CASE(BRIDGE, bridge)
-    default: {
-      GRN_TS_ERR_RETURN(GRN_OPERATION_NOT_SUPPORTED,
-                        "invalid node type: %d", node->type);
-    }
-  }
-}
-#undef GRN_TS_EXPR_NODE_ADJUST_CASE
-
 /*-------------------------------------------------------------
  * grn_ts_expr_parser.
  */

  Modified: lib/ts/ts_expr.h (+1 -54)
===================================================================
--- lib/ts/ts_expr.h    2015-11-12 09:59:27 +0900 (67f7022)
+++ lib/ts/ts_expr.h    2015-11-12 11:20:53 +0900 (9b6b130)
@@ -20,6 +20,7 @@
 #define GRN_TS_EXPR_H
 
 #include "ts_buf.h"
+#include "ts_expr_node.h"
 #include "ts_types.h"
 
 #ifdef __cplusplus
@@ -31,40 +32,6 @@ extern "C" {
  */
 
 typedef enum {
-  /* Invalid operator. */
-  GRN_TS_OP_NOP,
-
-  /* Unary operators. */
-  GRN_TS_OP_LOGICAL_NOT,    /* !X */
-  GRN_TS_OP_BITWISE_NOT,    /* ~X */
-  GRN_TS_OP_POSITIVE,       /* +X */
-  GRN_TS_OP_NEGATIVE,       /* -X */
-
-  /* Binary operators. */
-  GRN_TS_OP_LOGICAL_AND,            /* X && Y  */
-  GRN_TS_OP_LOGICAL_OR,             /* X || Y  */
-  GRN_TS_OP_LOGICAL_SUB,            /* X &! Y  */
-  GRN_TS_OP_BITWISE_AND,            /* X & Y   */
-  GRN_TS_OP_BITWISE_OR,             /* X | Y   */
-  GRN_TS_OP_BITWISE_XOR,            /* X ^ Y   */
-  GRN_TS_OP_EQUAL,                  /* X == Y  */
-  GRN_TS_OP_NOT_EQUAL,              /* X != Y  */
-  GRN_TS_OP_LESS,                   /* X < Y   */
-  GRN_TS_OP_LESS_EQUAL,             /* X <= Y  */
-  GRN_TS_OP_GREATER,                /* X > Y   */
-  GRN_TS_OP_GREATER_EQUAL,          /* X >= Y  */
-  GRN_TS_OP_SHIFT_ARITHMETIC_LEFT,  /* X << Y  */
-  GRN_TS_OP_SHIFT_ARITHMETIC_RIGHT, /* X >> Y  */
-  GRN_TS_OP_SHIFT_LOGICAL_LEFT,     /* X <<< Y */
-  GRN_TS_OP_SHIFT_LOGICAL_RIGHT,    /* X >>> Y */
-  GRN_TS_OP_PLUS,                   /* X + Y   */
-  GRN_TS_OP_MINUS,                  /* X - Y   */
-  GRN_TS_OP_MULTIPLICATION,         /* X * Y   */
-  GRN_TS_OP_DIVISION,               /* X / Y   */
-  GRN_TS_OP_MODULUS                 /* X % Y   */
-} grn_ts_op_type;
-
-typedef enum {
   GRN_TS_EXPR_INCOMPLETE, /* An incomplete expression. */
   GRN_TS_EXPR_BROKEN,     /* A broken expression. */
                           /* Any operation fails for a broken expression. */
@@ -74,30 +41,10 @@ typedef enum {
   GRN_TS_EXPR_VARIABLE    /* An expression that contains a variable. */
 } grn_ts_expr_type;
 
-typedef enum {
-  GRN_TS_EXPR_ID_NODE,     /* Associated with the ID (_id). */
-  GRN_TS_EXPR_SCORE_NODE,  /* Asscoaited with the score (_score). */
-  GRN_TS_EXPR_KEY_NODE,    /* Asscoaited with the key (_key). */
-  GRN_TS_EXPR_VALUE_NODE,  /* Asscoaited with the embedded value (_value). */
-  GRN_TS_EXPR_CONST_NODE,  /* Associated with a const. */
-  GRN_TS_EXPR_COLUMN_NODE, /* Associated with a column. */
-  GRN_TS_EXPR_OP_NODE,     /* Associated with an operator. */
-  GRN_TS_EXPR_BRIDGE_NODE  /* Associated with a bridge to a subexpression. */
-} grn_ts_expr_node_type;
-
 /*-------------------------------------------------------------
  * Expression components.
  */
 
-#define GRN_TS_EXPR_NODE_COMMON_MEMBERS\
-  grn_ts_expr_node_type type; /* Node type. */\
-  grn_ts_data_kind data_kind; /* Abstract data type. */\
-  grn_ts_data_type data_type; /* Detailed data type. */
-
-typedef struct {
-  GRN_TS_EXPR_NODE_COMMON_MEMBERS
-} grn_ts_expr_node;
-
 typedef struct {
   grn_obj *src_table;  /* The source table of a bridge (no ref. count). */
   grn_obj *dest_table; /* The destination table of a bridge. */

  Copied: lib/ts/ts_expr_node.c (+14 -2343) 66%
===================================================================
--- lib/ts/ts_expr.c    2015-11-12 09:59:27 +0900 (3c4a119)
+++ lib/ts/ts_expr_node.c    2015-11-12 11:20:53 +0900 (fed0eb2)
@@ -16,7 +16,7 @@
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
 
-#include "ts_expr.h"
+#include "ts_expr_node.h"
 
 #include <math.h>
 #include <stdlib.h>
@@ -37,23 +37,6 @@
  * Built-in data kinds.
  */
 
-typedef union {
-  grn_ts_bool as_bool;
-  grn_ts_int as_int;
-  grn_ts_float as_float;
-  grn_ts_time as_time;
-  grn_ts_text as_text;
-  grn_ts_geo as_geo;
-  grn_ts_ref as_ref;
-  grn_ts_bool_vector as_bool_vector;
-  grn_ts_int_vector as_int_vector;
-  grn_ts_float_vector as_float_vector;
-  grn_ts_time_vector as_time_vector;
-  grn_ts_text_vector as_text_vector;
-  grn_ts_geo_vector as_geo_vector;
-  grn_ts_ref_vector as_ref_vector;
-} grn_ts_any;
-
 /* grn_ts_bool_is_valid() returns whether a value is valid or not. */
 inline static grn_ts_bool
 grn_ts_bool_is_valid(grn_ts_bool value) {
@@ -311,107 +294,6 @@ grn_ts_data_kind_to_type(grn_ts_data_kind kind) {
 /* Operator precedence. */
 typedef int grn_ts_op_precedence;
 
-/* grn_ts_op_get_n_args() returns the number of arguments. */
-static size_t
-grn_ts_op_get_n_args(grn_ts_op_type op_type) {
-  switch (op_type) {
-    case GRN_TS_OP_LOGICAL_NOT: /* !X */
-    case GRN_TS_OP_BITWISE_NOT: /* ~X */
-    case GRN_TS_OP_POSITIVE:    /* +X */
-    case GRN_TS_OP_NEGATIVE: {  /* -X */
-      return 1;
-    }
-    case GRN_TS_OP_LOGICAL_AND:            /* X && Y  */
-    case GRN_TS_OP_LOGICAL_OR:             /* X || Y  */
-    case GRN_TS_OP_LOGICAL_SUB:            /* X &! Y  */
-    case GRN_TS_OP_BITWISE_AND:            /* X & Y   */
-    case GRN_TS_OP_BITWISE_OR:             /* X | Y   */
-    case GRN_TS_OP_BITWISE_XOR:            /* X ^ Y   */
-    case GRN_TS_OP_EQUAL:                  /* X == Y  */
-    case GRN_TS_OP_NOT_EQUAL:              /* X != Y  */
-    case GRN_TS_OP_LESS:                   /* X < Y   */
-    case GRN_TS_OP_LESS_EQUAL:             /* X <= Y  */
-    case GRN_TS_OP_GREATER:                /* X > Y   */
-    case GRN_TS_OP_GREATER_EQUAL:          /* X >= Y  */
-    case GRN_TS_OP_SHIFT_ARITHMETIC_LEFT:  /* X << Y  */
-    case GRN_TS_OP_SHIFT_ARITHMETIC_RIGHT: /* X >> Y  */
-    case GRN_TS_OP_SHIFT_LOGICAL_LEFT:     /* X <<< Y */
-    case GRN_TS_OP_SHIFT_LOGICAL_RIGHT:    /* X >>> Y */
-    case GRN_TS_OP_PLUS:                   /* X + Y   */
-    case GRN_TS_OP_MINUS:                  /* X - Y   */
-    case GRN_TS_OP_MULTIPLICATION:         /* X * Y   */
-    case GRN_TS_OP_DIVISION:               /* X / Y   */
-    case GRN_TS_OP_MODULUS: {              /* X % Y   */
-      return 2;
-    }
-    default: {
-      return 0;
-    }
-  }
-}
-
-/*
- * grn_ts_op_get_precedence() returns the precedence.
- * A prior operator has a higher precedence.
- */
-static grn_ts_op_precedence
-grn_ts_op_get_precedence(grn_ts_op_type op_type) {
-  switch (op_type) {
-    case GRN_TS_OP_LOGICAL_NOT:
-    case GRN_TS_OP_BITWISE_NOT:
-    case GRN_TS_OP_POSITIVE:
-    case GRN_TS_OP_NEGATIVE: {
-      return 14;
-    }
-    case GRN_TS_OP_LOGICAL_AND: {
-      return 5;
-    }
-    case GRN_TS_OP_LOGICAL_OR: {
-      return 3;
-    }
-    case GRN_TS_OP_LOGICAL_SUB: {
-      return 4;
-    }
-    case GRN_TS_OP_BITWISE_AND: {
-      return 8;
-    }
-    case GRN_TS_OP_BITWISE_OR: {
-      return 6;
-    }
-    case GRN_TS_OP_BITWISE_XOR: {
-      return 7;
-    }
-    case GRN_TS_OP_EQUAL:
-    case GRN_TS_OP_NOT_EQUAL: {
-      return 9;
-    }
-    case GRN_TS_OP_LESS:
-    case GRN_TS_OP_LESS_EQUAL:
-    case GRN_TS_OP_GREATER:
-    case GRN_TS_OP_GREATER_EQUAL: {
-      return 10;
-    }
-    case GRN_TS_OP_SHIFT_ARITHMETIC_LEFT:
-    case GRN_TS_OP_SHIFT_ARITHMETIC_RIGHT:
-    case GRN_TS_OP_SHIFT_LOGICAL_LEFT:
-    case GRN_TS_OP_SHIFT_LOGICAL_RIGHT: {
-      return 11;
-    }
-    case GRN_TS_OP_PLUS:
-    case GRN_TS_OP_MINUS: {
-      return 12;
-    }
-    case GRN_TS_OP_MULTIPLICATION:
-    case GRN_TS_OP_DIVISION:
-    case GRN_TS_OP_MODULUS: {
-      return 13;
-    }
-    default: {
-      return 0;
-    }
-  }
-}
-
 /* grn_ts_op_logical_not_bool() returns !arg. */
 inline static grn_ts_bool
 grn_ts_op_logical_not_bool(grn_ts_bool arg) {
@@ -1117,27 +999,6 @@ grn_ts_obj_increment_ref_count(grn_ctx *ctx, grn_obj *obj) {
   return GRN_SUCCESS;
 }
 
-/* grn_ts_obj_is_table() returns whether or not an object is a table. */
-static grn_ts_bool
-grn_ts_obj_is_table(grn_ctx *ctx, grn_obj *obj) {
-  return grn_obj_is_table(ctx, obj);
-}
-
-/* grn_ts_obj_is_column() returns whether or not an object is a column. */
-static grn_ts_bool
-grn_ts_obj_is_column(grn_ctx *ctx, grn_obj *obj) {
-  switch (obj->header.type) {
-    case GRN_COLUMN_FIX_SIZE:
-    case GRN_COLUMN_VAR_SIZE: {
-      return GRN_TRUE;
-    }
-    /* GRN_COLUMN_INDEX is not supported. */
-    default: {
-      return GRN_FALSE;
-    }
-  }
-}
-
 /*
  * grn_ts_ja_get_value() gets a value from ja and writes it to buf. Note the a
  * value is appended to the end of buf.
@@ -1519,8 +1380,7 @@ grn_ts_expr_id_node_fin(grn_ctx *ctx, grn_ts_expr_id_node *node) {
   /* Nothing to do. */
 }
 
-/* grn_ts_expr_id_node_open() creates a node associated with IDs (_id). */
-static grn_rc
+grn_rc
 grn_ts_expr_id_node_open(grn_ctx *ctx, grn_ts_expr_node **node) {
   grn_ts_expr_id_node *new_node = GRN_MALLOCN(grn_ts_expr_id_node, 1);
   if (!new_node) {
@@ -1574,11 +1434,7 @@ grn_ts_expr_score_node_fin(grn_ctx *ctx, grn_ts_expr_score_node *node) {
   /* Nothing to do. */
 }
 
-/*
- * grn_ts_expr_score_node_open() creates a node associated with scores
- * (_score).
- */
-static grn_rc
+grn_rc
 grn_ts_expr_score_node_open(grn_ctx *ctx, grn_ts_expr_node **node) {
   grn_ts_expr_score_node *new_node = GRN_MALLOCN(grn_ts_expr_score_node, 1);
   if (!new_node) {
@@ -1646,8 +1502,7 @@ grn_ts_expr_key_node_fin(grn_ctx *ctx, grn_ts_expr_key_node *node) {
   }
 }
 
-/* grn_ts_expr_key_node_open() creates a node associated with keys (_key). */
-static grn_rc
+grn_rc
 grn_ts_expr_key_node_open(grn_ctx *ctx, grn_obj *table,
                           grn_ts_expr_node **node) {
   grn_rc rc;
@@ -1933,11 +1788,7 @@ grn_ts_expr_value_node_fin(grn_ctx *ctx, grn_ts_expr_value_node *node) {
   }
 }
 
-/*
- * grn_ts_expr_value_node_open() creates a node associated with values
- * (_value).
- */
-static grn_rc
+grn_rc
 grn_ts_expr_value_node_open(grn_ctx *ctx, grn_obj *table,
                             grn_ts_expr_node **node) {
   grn_rc rc;
@@ -2205,8 +2056,7 @@ grn_ts_expr_const_node_set_vector(grn_ctx *ctx, grn_ts_expr_const_node *node,
 }
 #undef GRN_TS_EXPR_CONST_NODE_SET_VECTOR_CASE
 
-/* grn_ts_expr_const_node_open() creates a node associated with a const. */
-static grn_rc
+grn_rc
 grn_ts_expr_const_node_open(grn_ctx *ctx, grn_ts_data_kind kind,
                             const void *value, grn_ts_expr_node **node) {
   grn_rc rc;
@@ -2346,8 +2196,7 @@ grn_ts_expr_column_node_fin(grn_ctx *ctx, grn_ts_expr_column_node *node) {
     GRN_ ## TYPE ## _INIT(&new_node->buf, GRN_OBJ_VECTOR);\
     break;\
   }
-/* grn_ts_expr_column_node_open() creates a node associated with a column. */
-static grn_rc
+grn_rc
 grn_ts_expr_column_node_open(grn_ctx *ctx, grn_obj *column,
                              grn_ts_expr_node **node) {
   grn_rc rc;
@@ -2772,22 +2621,6 @@ enum {
   GRN_TS_EXPR_OP_NODE_N_BUFS = 3
 };
 
-/* Forward declarations. */
-static void grn_ts_expr_node_close(grn_ctx *ctx, grn_ts_expr_node *node);
-static grn_rc grn_ts_expr_node_evaluate(grn_ctx *ctx, grn_ts_expr_node *node,
-                                        const grn_ts_record *in, size_t n_in,
-                                        void *out);
-static grn_rc grn_ts_expr_node_evaluate_to_buf(grn_ctx *ctx,
-                                               grn_ts_expr_node *node,
-                                               const grn_ts_record *in,
-                                               size_t n_in,
-                                               grn_ts_buf *out);
-static grn_rc grn_ts_expr_node_filter(grn_ctx *ctx, grn_ts_expr_node *node,
-                                      grn_ts_record *in, size_t n_in,
-                                      grn_ts_record *out, size_t *n_out);
-static grn_rc grn_ts_expr_node_adjust(grn_ctx *ctx, grn_ts_expr_node *node,
-                                      grn_ts_record *io, size_t n_io);
-
 typedef struct {
   GRN_TS_EXPR_NODE_COMMON_MEMBERS
   grn_ts_op_type op_type;
@@ -3121,8 +2954,7 @@ grn_ts_expr_op_node_check_args(grn_ctx *ctx, grn_ts_expr_op_node *node) {
   }
 }
 
-/* grn_ts_expr_op_node_open() creates a node associated with an operator. */
-static grn_rc
+grn_rc
 grn_ts_expr_op_node_open(grn_ctx *ctx, grn_ts_op_type op_type,
                          grn_ts_expr_node **args, size_t n_args,
                          grn_ts_expr_node **node) {
@@ -4507,8 +4339,7 @@ grn_ts_expr_bridge_node_fin(grn_ctx *ctx, grn_ts_expr_bridge_node *node) {
   }
 }
 
-/* grn_ts_expr_bridge_node_open() creates a node associated with a bridge. */
-static grn_rc
+grn_rc
 grn_ts_expr_bridge_node_open(grn_ctx *ctx, grn_ts_expr_node *src,
                              grn_ts_expr_node *dest, grn_ts_expr_node **node) {
   grn_ts_expr_bridge_node *new_node = GRN_MALLOCN(grn_ts_expr_bridge_node, 1);
@@ -4609,8 +4440,7 @@ grn_ts_expr_bridge_node_adjust(grn_ctx *ctx, grn_ts_expr_bridge_node *node,
     grn_ts_expr_ ## type ## _node_close(ctx, type ## _node);\
     return;\
   }
-/* grn_ts_expr_node_close() destroys a node. */
-static void
+void
 grn_ts_expr_node_close(grn_ctx *ctx, grn_ts_expr_node *node) {
   switch (node->type) {
     GRN_TS_EXPR_NODE_CLOSE_CASE(ID, id)
@@ -4632,8 +4462,7 @@ grn_ts_expr_node_close(grn_ctx *ctx, grn_ts_expr_node *node) {
     return grn_ts_expr_ ## type ## _node_evaluate(ctx, type ## _node,\
                                                   in, n_in, out);\
   }
-/* grn_ts_expr_node_evaluate() evaluates a subtree. */
-static grn_rc
+grn_rc
 grn_ts_expr_node_evaluate(grn_ctx *ctx, grn_ts_expr_node *node,
                           const grn_ts_record *in, size_t n_in, void *out) {
   switch (node->type) {
@@ -4663,8 +4492,7 @@ grn_ts_expr_node_evaluate(grn_ctx *ctx, grn_ts_expr_node *node,
   }
 #define GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_VECTOR_CASE(KIND, kind)\
   GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_CASE(KIND ## _VECTOR, kind ## _vector)
-/* grn_ts_expr_node_evaluate_to_buf() evaluates a subtree. */
-static grn_rc
+grn_rc
 grn_ts_expr_node_evaluate_to_buf(grn_ctx *ctx, grn_ts_expr_node *node,
                                  const grn_ts_record *in, size_t n_in,
                                  grn_ts_buf *out) {
@@ -4699,8 +4527,7 @@ grn_ts_expr_node_evaluate_to_buf(grn_ctx *ctx, grn_ts_expr_node *node,
     return grn_ts_expr_ ## type ## _node_filter(ctx, type ## _node,\
                                                 in, n_in, out, n_out);\
   }
-/* grn_ts_expr_node_filter() filters records. */
-static grn_rc
+grn_rc
 grn_ts_expr_node_filter(grn_ctx *ctx, grn_ts_expr_node *node,
                         grn_ts_record *in, size_t n_in,
                         grn_ts_record *out, size_t *n_out) {
@@ -4729,8 +4556,7 @@ grn_ts_expr_node_filter(grn_ctx *ctx, grn_ts_expr_node *node,
     type ## _node = (grn_ts_expr_ ## type ## _node *)node;\
     return grn_ts_expr_ ## type ## _node_adjust(ctx, type ## _node, io, n_io);\
   }
-/* grn_ts_expr_node_adjust() updates scores. */
-static grn_rc
+grn_rc
 grn_ts_expr_node_adjust(grn_ctx *ctx, grn_ts_expr_node *node,
                         grn_ts_record *io, size_t n_io) {
   if (node->data_kind != GRN_TS_FLOAT) {
@@ -4752,2158 +4578,3 @@ grn_ts_expr_node_adjust(grn_ctx *ctx, grn_ts_expr_node *node,
   }
 }
 #undef GRN_TS_EXPR_NODE_ADJUST_CASE
-
-/*-------------------------------------------------------------
- * grn_ts_expr_parser.
- */
-
-/*
- * FIXME: A grn_ts_expr_parser object is designed to parse one expression
- *        string. grn_ts_expr_parser_parse() should not be called more than
- *        once.
- */
-
-typedef enum {
-  GRN_TS_EXPR_DUMMY_TOKEN,  /* No extra data. */
-  GRN_TS_EXPR_START_TOKEN,  /* No extra data. */
-  GRN_TS_EXPR_END_TOKEN,    /* No extra data. */
-  GRN_TS_EXPR_CONST_TOKEN,  /* +data_kind, content and buf. */
-  GRN_TS_EXPR_NAME_TOKEN,   /* +name. */
-  GRN_TS_EXPR_OP_TOKEN,     /* +op_type. */
-  GRN_TS_EXPR_BRIDGE_TOKEN, /* No extra data. */
-  GRN_TS_EXPR_BRACKET_TOKEN /* No extra data. */
-} grn_ts_expr_token_type;
-
-#define GRN_TS_EXPR_TOKEN_COMMON_MEMBERS\
-  grn_ts_str src;              /* Source string. */\
-  grn_ts_expr_token_type type; /* Token type. */
-
-typedef struct {
-  GRN_TS_EXPR_TOKEN_COMMON_MEMBERS
-} grn_ts_expr_token;
-
-typedef grn_ts_expr_token grn_ts_expr_dummy_token;
-typedef grn_ts_expr_token grn_ts_expr_start_token;
-typedef grn_ts_expr_token grn_ts_expr_end_token;
-
-typedef struct {
-  GRN_TS_EXPR_TOKEN_COMMON_MEMBERS
-  grn_ts_data_kind data_kind; /* The data kind of the const. */
-  grn_ts_any content;         /* The const. */
-  grn_ts_buf buf;             /* Buffer for content.as_text. */
-} grn_ts_expr_const_token;
-
-typedef grn_ts_expr_token grn_ts_expr_name_token;
-
-typedef struct {
-  GRN_TS_EXPR_TOKEN_COMMON_MEMBERS
-  grn_ts_op_type op_type;     /* Operator type. */
-} grn_ts_expr_op_token;
-
-typedef grn_ts_expr_token grn_ts_expr_bridge_token;
-typedef grn_ts_expr_token grn_ts_expr_bracket_token;
-
-typedef struct {
-  grn_ts_expr *expr;                     /* Associated expression. */
-  grn_ts_buf str_buf;                    /* Buffer for a source string. */
-  grn_ts_expr_token **tokens;            /* Tokens. */
-  size_t n_tokens;                       /* Number of tokens. */
-  size_t max_n_tokens;                   /* Max. number of tokens. */
-  grn_ts_expr_dummy_token *dummy_tokens; /* Dummy tokens. */
-  size_t n_dummy_tokens;                 /* Number of dummy tokens. */
-  grn_ts_expr_token **stack;             /* Token stack. */
-  size_t stack_depth;                    /* Token stack's current depth. */
-} grn_ts_expr_parser;
-
-#define GRN_TS_EXPR_TOKEN_INIT(TYPE)\
-  memset(token, 0, sizeof(*token));\
-  token->type = GRN_TS_EXPR_ ## TYPE ## _TOKEN;\
-  token->src = src;
-/* grn_ts_expr_dummy_token_init() initializes a token. */
-static void
-grn_ts_expr_dummy_token_init(grn_ctx *ctx, grn_ts_expr_dummy_token *token,
-                             grn_ts_str src) {
-  GRN_TS_EXPR_TOKEN_INIT(DUMMY)
-}
-
-/* grn_ts_expr_start_token_init() initializes a token. */
-static void
-grn_ts_expr_start_token_init(grn_ctx *ctx, grn_ts_expr_start_token *token,
-                             grn_ts_str src) {
-  GRN_TS_EXPR_TOKEN_INIT(START)
-}
-
-/* grn_ts_expr_end_token_init() initializes a token. */
-static void
-grn_ts_expr_end_token_init(grn_ctx *ctx, grn_ts_expr_end_token *token,
-                           grn_ts_str src) {
-  GRN_TS_EXPR_TOKEN_INIT(END)
-}
-
-/* grn_ts_expr_const_token_init() initializes a token. */
-static void
-grn_ts_expr_const_token_init(grn_ctx *ctx, grn_ts_expr_const_token *token,
-                             grn_ts_str src) {
-  GRN_TS_EXPR_TOKEN_INIT(CONST);
-  grn_ts_buf_init(ctx, &token->buf);
-}
-
-/* grn_ts_expr_name_token_init() initializes a token. */
-static void
-grn_ts_expr_name_token_init(grn_ctx *ctx, grn_ts_expr_name_token *token,
-                            grn_ts_str src) {
-  GRN_TS_EXPR_TOKEN_INIT(NAME);
-}
-
-/* grn_ts_expr_op_token_init() initializes a token. */
-static void
-grn_ts_expr_op_token_init(grn_ctx *ctx, grn_ts_expr_op_token *token,
-                          grn_ts_str src) {
-  GRN_TS_EXPR_TOKEN_INIT(OP);
-}
-
-/* grn_ts_expr_bridge_token_init() initializes a token. */
-static void
-grn_ts_expr_bridge_token_init(grn_ctx *ctx, grn_ts_expr_bridge_token *token,
-                              grn_ts_str src) {
-  GRN_TS_EXPR_TOKEN_INIT(BRIDGE)
-}
-
-/* grn_ts_expr_bracket_token_init() initializes a token. */
-static void
-grn_ts_expr_bracket_token_init(grn_ctx *ctx, grn_ts_expr_bracket_token *token,
-                               grn_ts_str src) {
-  GRN_TS_EXPR_TOKEN_INIT(BRACKET)
-}
-#undef GRN_TS_EXPR_TOKEN_INIT
-
-/* grn_ts_expr_dummy_token_fin() finalizes a token. */
-static void
-grn_ts_expr_dummy_token_fin(grn_ctx *ctx, grn_ts_expr_dummy_token *token) {
-  /* Nothing to do. */
-}
-
-/* grn_ts_expr_start_token_fin() finalizes a token. */
-static void
-grn_ts_expr_start_token_fin(grn_ctx *ctx, grn_ts_expr_start_token *token) {
-  /* Nothing to do. */
-}
-
-/* grn_ts_expr_end_token_fin() finalizes a token. */
-static void
-grn_ts_expr_end_token_fin(grn_ctx *ctx, grn_ts_expr_end_token *token) {
-  /* Nothing to do. */
-}
-
-/* grn_ts_expr_const_token_fin() finalizes a token. */
-static void
-grn_ts_expr_const_token_fin(grn_ctx *ctx, grn_ts_expr_const_token *token) {
-  grn_ts_buf_fin(ctx, &token->buf);
-}
-
-/* grn_ts_expr_name_token_fin() finalizes a token. */
-static void
-grn_ts_expr_name_token_fin(grn_ctx *ctx, grn_ts_expr_name_token *token) {
-  /* Nothing to do. */
-}
-
-/* grn_ts_expr_op_token_fin() finalizes a token. */
-static void
-grn_ts_expr_op_token_fin(grn_ctx *ctx, grn_ts_expr_op_token *token) {
-  /* Nothing to do. */
-}
-
-/* grn_ts_expr_bridge_token_fin() finalizes a token. */
-static void
-grn_ts_expr_bridge_token_fin(grn_ctx *ctx, grn_ts_expr_bridge_token *token) {
-  /* Nothing to do. */
-}
-
-/* grn_ts_expr_bracket_token_fin() finalizes a token. */
-static void
-grn_ts_expr_bracket_token_fin(grn_ctx *ctx, grn_ts_expr_bracket_token *token) {
-  /* Nothing to do. */
-}
-
-#define GRN_TS_EXPR_TOKEN_OPEN(TYPE, type)\
-  grn_ts_expr_ ## type ## _token *new_token;\
-  new_token = GRN_MALLOCN(grn_ts_expr_ ## type ## _token, 1);\
-  if (!new_token) {\
-    GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %zu x 1",\
-                      sizeof(grn_ts_expr_ ## type ## _token));\
-  }\
-  grn_ts_expr_ ## type ## _token_init(ctx, new_token, src);\
-  *token = new_token;
-/* grn_ts_expr_dummy_token_open() creates a token. */
-/*
-static grn_rc
-grn_ts_expr_dummy_token_open(grn_ctx *ctx, grn_ts_str src,
-                             grn_ts_expr_dummy_token **token) {
-  GRN_TS_EXPR_TOKEN_OPEN(DUMMY, dummy)
-  return GRN_SUCCESS;
-}
-*/
-
-/* grn_ts_expr_start_token_open() creates a token. */
-static grn_rc
-grn_ts_expr_start_token_open(grn_ctx *ctx, grn_ts_str src,
-                             grn_ts_expr_start_token **token) {
-  GRN_TS_EXPR_TOKEN_OPEN(START, start)
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_expr_end_token_open() creates a token. */
-static grn_rc
-grn_ts_expr_end_token_open(grn_ctx *ctx, grn_ts_str src,
-                           grn_ts_expr_end_token **token) {
-  GRN_TS_EXPR_TOKEN_OPEN(END, end)
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_expr_const_token_open() creates a token. */
-static grn_rc
-grn_ts_expr_const_token_open(grn_ctx *ctx, grn_ts_str src,
-                             grn_ts_expr_const_token **token) {
-  GRN_TS_EXPR_TOKEN_OPEN(CONST, const)
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_expr_name_token_open() creates a token. */
-static grn_rc
-grn_ts_expr_name_token_open(grn_ctx *ctx, grn_ts_str src,
-                            grn_ts_expr_name_token **token) {
-  GRN_TS_EXPR_TOKEN_OPEN(NAME, name)
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_expr_op_token_open() creates a token. */
-static grn_rc
-grn_ts_expr_op_token_open(grn_ctx *ctx, grn_ts_str src, grn_ts_op_type op_type,
-                          grn_ts_expr_op_token **token) {
-  GRN_TS_EXPR_TOKEN_OPEN(OP, op)
-  new_token->op_type = op_type;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_expr_bridge_token_open() creates a token. */
-static grn_rc
-grn_ts_expr_bridge_token_open(grn_ctx *ctx, grn_ts_str src,
-                              grn_ts_expr_bridge_token **token) {
-  GRN_TS_EXPR_TOKEN_OPEN(BRIDGE, bridge)
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_expr_bracket_token_open() creates a token. */
-static grn_rc
-grn_ts_expr_bracket_token_open(grn_ctx *ctx, grn_ts_str src,
-                               grn_ts_expr_bracket_token **token) {
-  GRN_TS_EXPR_TOKEN_OPEN(BRACKET, bracket)
-  return GRN_SUCCESS;
-}
-#undef GRN_TS_EXPR_TOKEN_OPEN
-
-#define GRN_TS_EXPR_TOKEN_CLOSE_CASE(TYPE, type)\
-  case GRN_TS_EXPR_ ## TYPE ## _TOKEN: {\
-    grn_ts_expr_ ## type ## _token *type ## _token;\
-    type ## _token = (grn_ts_expr_ ## type ## _token *)token;\
-    grn_ts_expr_ ## type ## _token_fin(ctx, type ## _token);\
-    break;\
-  }
-/* grn_ts_expr_token_close() destroys a token. */
-static void
-grn_ts_expr_token_close(grn_ctx *ctx, grn_ts_expr_token *token) {
-  switch (token->type) {
-    GRN_TS_EXPR_TOKEN_CLOSE_CASE(DUMMY, dummy)
-    GRN_TS_EXPR_TOKEN_CLOSE_CASE(START, start)
-    GRN_TS_EXPR_TOKEN_CLOSE_CASE(END, end)
-    GRN_TS_EXPR_TOKEN_CLOSE_CASE(CONST, const)
-    GRN_TS_EXPR_TOKEN_CLOSE_CASE(NAME, name)
-    GRN_TS_EXPR_TOKEN_CLOSE_CASE(OP, op)
-    GRN_TS_EXPR_TOKEN_CLOSE_CASE(BRACKET, bracket)
-    GRN_TS_EXPR_TOKEN_CLOSE_CASE(BRIDGE, bridge)
-  }
-  GRN_FREE(token);
-}
-#undef GRN_TS_EXPR_TOKEN_CLOSE_CASE
-
-/* grn_ts_expr_parser_init() initializes a parser. */
-static void
-grn_ts_expr_parser_init(grn_ctx *ctx, grn_ts_expr *expr,
-                        grn_ts_expr_parser *parser) {
-  memset(parser, 0, sizeof(*parser));
-  parser->expr = expr;
-  grn_ts_buf_init(ctx, &parser->str_buf);
-  parser->tokens = NULL;
-  parser->dummy_tokens = NULL;
-  parser->stack = NULL;
-}
-
-/* grn_ts_expr_parser_fin() finalizes a parser. */
-static void
-grn_ts_expr_parser_fin(grn_ctx *ctx, grn_ts_expr_parser *parser) {
-  if (parser->stack) {
-    GRN_FREE(parser->stack);
-  }
-  if (parser->dummy_tokens) {
-    size_t i;
-    for (i = 0; i < parser->n_dummy_tokens; i++) {
-      grn_ts_expr_dummy_token_fin(ctx, &parser->dummy_tokens[i]);
-    }
-    GRN_FREE(parser->dummy_tokens);
-  }
-  if (parser->tokens) {
-    size_t i;
-    for (i = 0; i < parser->n_tokens; i++) {
-      grn_ts_expr_token_close(ctx, parser->tokens[i]);
-    }
-    GRN_FREE(parser->tokens);
-  }
-  grn_ts_buf_fin(ctx, &parser->str_buf);
-}
-
-/* grn_ts_expr_parser_open() creates a parser. */
-static grn_rc
-grn_ts_expr_parser_open(grn_ctx *ctx, grn_ts_expr *expr,
-                        grn_ts_expr_parser **parser) {
-  grn_ts_expr_parser *new_parser = GRN_MALLOCN(grn_ts_expr_parser, 1);
-  if (!new_parser) {
-    GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %zu x 1",
-                      sizeof(grn_ts_expr_parser));
-  }
-  grn_ts_expr_parser_init(ctx, expr, new_parser);
-  *parser = new_parser;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_expr_parser_close() destroys a parser. */
-static void
-grn_ts_expr_parser_close(grn_ctx *ctx, grn_ts_expr_parser *parser) {
-  grn_ts_expr_parser_fin(ctx, parser);
-  GRN_FREE(parser);
-}
-
-/* grn_ts_expr_parser_tokenize_start() creates the start token. */
-static grn_rc
-grn_ts_expr_parser_tokenize_start(grn_ctx *ctx, grn_ts_expr_parser *parser,
-                                  grn_ts_str str, grn_ts_expr_token **token) {
-  grn_ts_str token_str = { str.ptr, 0 };
-  grn_ts_expr_start_token *new_token;
-  grn_rc rc = grn_ts_expr_start_token_open(ctx, token_str, &new_token);
-  if (rc != GRN_SUCCESS) {
-    return rc;
-  }
-  *token = (grn_ts_expr_token *)new_token;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_expr_parser_tokenize_end() creates the end token. */
-static grn_rc
-grn_ts_expr_parser_tokenize_end(grn_ctx *ctx, grn_ts_expr_parser *parser,
-                                grn_ts_str str, grn_ts_expr_token **token) {
-  grn_ts_str token_str = { str.ptr, 0 };
-  grn_ts_expr_end_token *new_token;
-  grn_rc rc = grn_ts_expr_end_token_open(ctx, token_str, &new_token);
-  if (rc != GRN_SUCCESS) {
-    return rc;
-  }
-  *token = (grn_ts_expr_token *)new_token;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_expr_parser_tokenize_number() tokenizes an Int or Float literal. */
-static grn_rc
-grn_ts_expr_parser_tokenize_number(grn_ctx *ctx, grn_ts_expr_parser *parser,
-                                   grn_ts_str str, grn_ts_expr_token **token) {
-  char *end;
-  grn_rc rc;
-  grn_ts_int int_value;
-  grn_ts_str token_str;
-  grn_ts_expr_const_token *new_token;
-
-  int_value = strtol(str.ptr, &end, 0);
-  if ((end != str.ptr) && (*end != '.') && (*end != 'e')) {
-    if (grn_ts_byte_is_name_char(*end)) {
-      GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT,
-                        "unterminated Int literal: \"%.*s\"",
-                        (int)str.size, str.ptr);
-    }
-    token_str.ptr = str.ptr;
-    token_str.size = end - str.ptr;
-    rc = grn_ts_expr_const_token_open(ctx, token_str, &new_token);
-    if (rc != GRN_SUCCESS) {
-      return rc;
-    }
-    new_token->data_kind = GRN_TS_INT;
-    new_token->content.as_int = int_value;
-  } else {
-    grn_ts_float float_value = strtod(str.ptr, &end);
-    if (end == str.ptr) {
-      GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid number literal: \"%.*s\"",
-                        (int)str.size, str.ptr);
-    }
-    if (grn_ts_byte_is_name_char(*end)) {
-      GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT,
-                        "unterminated Float literal: \"%.*s\"",
-                        (int)str.size, str.ptr);
-    }
-    token_str.ptr = str.ptr;
-    token_str.size = end - str.ptr;
-    rc = grn_ts_expr_const_token_open(ctx, token_str, &new_token);
-    if (rc != GRN_SUCCESS) {
-      return rc;
-    }
-    new_token->data_kind = GRN_TS_FLOAT;
-    new_token->content.as_float = float_value;
-  }
-  *token = (grn_ts_expr_token *)new_token;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_expr_parser_tokenize_text() tokenizes a Text literal. */
-static grn_rc
-grn_ts_expr_parser_tokenize_text(grn_ctx *ctx, grn_ts_expr_parser *parser,
-                                 grn_ts_str str, grn_ts_expr_token **token) {
-  size_t i, n_escapes = 0;
-  grn_rc rc;
-  grn_ts_str token_str;
-  grn_ts_expr_const_token *new_token;
-  for (i = 1; i < str.size; i++) {
-    if (str.ptr[i] == '\\') {
-      i++;
-      n_escapes++;
-    } else if (str.ptr[i] == '"') {
-      break;
-    }
-  }
-  if (i >= str.size) {
-    GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "no closing double quote: \"%.*s\"",
-                      (int)str.size, str.ptr);
-  }
-  token_str.ptr = str.ptr;
-  token_str.size = i + 1;
-  rc = grn_ts_expr_const_token_open(ctx, token_str, &new_token);
-  if (rc != GRN_SUCCESS) {
-    return rc;
-  }
-  new_token->data_kind = GRN_TS_TEXT;
-  if (n_escapes) {
-    char *buf_ptr;
-    const char *str_ptr = str.ptr + 1;
-    size_t size = token_str.size - 2 - n_escapes;
-    rc = grn_ts_buf_resize(ctx, &new_token->buf, size);
-    if (rc != GRN_SUCCESS) {
-      grn_ts_expr_token_close(ctx, (grn_ts_expr_token *)new_token);
-      return rc;
-    }
-    buf_ptr = (char *)new_token->buf.ptr;
-    for (i = 0; i < size; i++) {
-      if (str_ptr[i] == '\\') {
-        str_ptr++;
-      }
-      buf_ptr[i] = str_ptr[i];
-    }
-    new_token->content.as_text.ptr = buf_ptr;
-    new_token->content.as_text.size = size;
-  } else {
-    new_token->content.as_text.ptr = token_str.ptr + 1;
-    new_token->content.as_text.size = token_str.size - 2;
-  }
-  *token = (grn_ts_expr_token *)new_token;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_expr_parser_tokenize_name() tokenizes a Bool literal or a name. */
-static grn_rc
-grn_ts_expr_parser_tokenize_name(grn_ctx *ctx, grn_ts_expr_parser *parser,
-                                 grn_ts_str str, grn_ts_expr_token **token) {
-  size_t i;
-  grn_ts_str token_str;
-  for (i = 1; i < str.size; i++) {
-    if (!grn_ts_byte_is_name_char(str.ptr[i])) {
-      break;
-    }
-  }
-  token_str.ptr = str.ptr;
-  token_str.size = i;
-
-  if (grn_ts_str_is_bool(token_str)) {
-    grn_ts_expr_const_token *new_token;
-    grn_rc rc = grn_ts_expr_const_token_open(ctx, token_str, &new_token);
-    if (rc != GRN_SUCCESS) {
-      return rc;
-    }
-    new_token->data_kind = GRN_TS_BOOL;
-    if (token_str.ptr[0] == 't') {
-      new_token->content.as_bool = GRN_TRUE;
-    } else {
-      new_token->content.as_bool = GRN_FALSE;
-    }
-    *token = (grn_ts_expr_token *)new_token;
-    return GRN_SUCCESS;
-  }
-  return grn_ts_expr_name_token_open(ctx, token_str, token);
-}
-
-/* grn_ts_expr_parser_tokenize_bridge() tokenizes a bridge. */
-static grn_rc
-grn_ts_expr_parser_tokenize_bridge(grn_ctx *ctx, grn_ts_expr_parser *parser,
-                                   grn_ts_str str, grn_ts_expr_token **token) {
-  grn_ts_str token_str = { str.ptr, 1 };
-  grn_ts_expr_bridge_token *new_token;
-  grn_rc rc = grn_ts_expr_bridge_token_open(ctx, token_str, &new_token);
-  if (rc != GRN_SUCCESS) {
-    return rc;
-  }
-  *token = (grn_ts_expr_token *)new_token;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_expr_parser_tokenize_bracket() tokenizes a bracket. */
-static grn_rc
-grn_ts_expr_parser_tokenize_bracket(grn_ctx *ctx, grn_ts_expr_parser *parser,
-                                    grn_ts_str str,
-                                    grn_ts_expr_token **token) {
-  grn_ts_str token_str = { str.ptr, 1 };
-  grn_ts_expr_bracket_token *new_token;
-  grn_rc rc = grn_ts_expr_bracket_token_open(ctx, token_str, &new_token);
-  if (rc != GRN_SUCCESS) {
-    return rc;
-  }
-  *token = (grn_ts_expr_token *)new_token;
-  return GRN_SUCCESS;
-}
-
-/*
- * grn_ts_expr_parsre_tokenize_sign() tokenizes an operator '+' or '-'.
- * Note that '+' and '-' have two roles each.
- * '+' is GRN_TS_OP_POSITIVE or GRN_TS_OP_PLUS.
- * '-' is GRN_TS_OP_NEGATIVE or GRN_TS_OP_MINUS.
- */
-static grn_rc
-grn_ts_expr_parser_tokenize_sign(grn_ctx *ctx, grn_ts_expr_parser *parser,
-                                 grn_ts_str str, grn_ts_expr_token **token) {
-  size_t n_args;
-  grn_rc rc;
-  grn_ts_op_type op_type;
-  grn_ts_str token_str = { str.ptr, 1 };
-  grn_ts_expr_token *prev_token = parser->tokens[parser->n_tokens - 1];
-  grn_ts_expr_op_token *new_token;
-  switch (prev_token->type) {
-    case GRN_TS_EXPR_START_TOKEN:
-    case GRN_TS_EXPR_OP_TOKEN: {
-      n_args = 1;
-      break;
-    }
-    case GRN_TS_EXPR_CONST_TOKEN:
-    case GRN_TS_EXPR_NAME_TOKEN: {
-      n_args = 2;
-      break;
-    }
-    case GRN_TS_EXPR_BRACKET_TOKEN: {
-      grn_ts_str bracket;
-      const grn_ts_expr_bracket_token *bracket_token;
-      bracket_token = (const grn_ts_expr_bracket_token *)prev_token;
-      bracket = bracket_token->src;
-      switch (bracket.ptr[0]) {
-        case '(': case '[': {
-          n_args = 1;
-          break;
-        }
-        case ')': case ']': {
-          n_args = 2;
-          break;
-        }
-        default: {
-          GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "undefined bracket: \"%.*s\"",
-                            (int)bracket.size, bracket.ptr);
-        }
-      }
-      break;
-    }
-    default: {
-      GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid token sequence: %d",
-                        prev_token->type);
-    }
-  }
-  if (token_str.ptr[0] == '+') {
-    op_type = (n_args == 1) ? GRN_TS_OP_POSITIVE : GRN_TS_OP_PLUS;
-  } else {
-    op_type = (n_args == 1) ? GRN_TS_OP_NEGATIVE : GRN_TS_OP_MINUS;
-  }
-  rc = grn_ts_expr_op_token_open(ctx, token_str, op_type, &new_token);
-  if (rc != GRN_SUCCESS) {
-    return rc;
-  }
-  *token = (grn_ts_expr_token *)new_token;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_expr_parser_tokenize_op() tokenizes an operator. */
-static grn_rc
-grn_ts_expr_parser_tokenize_op(grn_ctx *ctx, grn_ts_expr_parser *parser,
-                               grn_ts_str str, grn_ts_expr_token **token) {
-  grn_rc rc = GRN_SUCCESS;
-  grn_ts_str token_str = str;
-  grn_ts_op_type op_type;
-  grn_ts_expr_op_token *new_token;
-  switch (str.ptr[0]) {
-    case '+': case '-': {
-      return grn_ts_expr_parser_tokenize_sign(ctx, parser, str, token);
-    }
-    case '!': {
-      if ((str.size >= 2) && (str.ptr[1] == '=')) {
-        token_str.size = 2;
-        op_type = GRN_TS_OP_NOT_EQUAL;
-      } else {
-        token_str.size = 1;
-        op_type = GRN_TS_OP_LOGICAL_NOT;
-      }
-      rc = grn_ts_expr_op_token_open(ctx, token_str, op_type, &new_token);
-      break;
-    }
-#define GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE(label, TYPE_1, TYPE_2, TYPE_3,\
-                                            TYPE_EQUAL)\
-  case label: {\
-    if ((str.size >= 2) && (str.ptr[1] == '=')) {\
-      token_str.size = 2;\
-      op_type = GRN_TS_OP_ ## TYPE_EQUAL;\
-    } else if ((str.size >= 2) && (str.ptr[1] == label)) {\
-      if ((str.size >= 3) && (str.ptr[2] == label)) {\
-        token_str.size = 3;\
-        op_type = GRN_TS_OP_ ## TYPE_3;\
-      } else {\
-        token_str.size = 2;\
-        op_type = GRN_TS_OP_ ## TYPE_2;\
-      }\
-    } else {\
-      token_str.size = 1;\
-      op_type = GRN_TS_OP_ ## TYPE_1;\
-    }\
-    rc = grn_ts_expr_op_token_open(ctx, token_str, op_type, &new_token);\
-    break;\
-  }
-    GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE('<', LESS, SHIFT_ARITHMETIC_LEFT,
-                                        SHIFT_LOGICAL_LEFT, LESS_EQUAL)
-    GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE('>', GREATER, SHIFT_ARITHMETIC_RIGHT,
-                                        SHIFT_LOGICAL_RIGHT, GREATER_EQUAL)
-#undef GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE
-    case '&': {
-      if ((str.size >= 2) && (str.ptr[1] == '&')) {
-        token_str.size = 2;
-        op_type = GRN_TS_OP_LOGICAL_AND;
-      } else if ((str.size >= 2) && (str.ptr[1] == '&')) {
-        token_str.size = 2;
-        op_type = GRN_TS_OP_LOGICAL_SUB;
-      } else {
-        token_str.size = 1;
-        op_type = GRN_TS_OP_BITWISE_AND;
-      }
-      rc = grn_ts_expr_op_token_open(ctx, token_str, op_type, &new_token);
-      break;
-    }
-    case '|': {
-      if ((str.size >= 2) && (str.ptr[1] == '|')) {
-        token_str.size = 2;
-        op_type = GRN_TS_OP_LOGICAL_OR;
-      } else {
-        token_str.size = 1;
-        op_type = GRN_TS_OP_BITWISE_OR;
-      }
-      rc = grn_ts_expr_op_token_open(ctx, token_str, op_type, &new_token);
-      break;
-    }
-    case '=': {
-      if ((str.size < 2) || (str.ptr[1] != '=')) {
-        GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT,
-                          "single equal not available: =\"%.*s\"",
-                          (int)str.size, str.ptr);
-      }
-      token_str.size = 2;
-      rc = grn_ts_expr_op_token_open(ctx, token_str, GRN_TS_OP_EQUAL,
-                                     &new_token);
-      break;
-    }
-#define GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE(label, TYPE)\
-  case label: {\
-    token_str.size = 1;\
-    rc = grn_ts_expr_op_token_open(ctx, token_str, GRN_TS_OP_ ## TYPE,\
-                                   &new_token);\
-    break;\
-  }
-    GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE('~', BITWISE_NOT)
-    GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE('^', BITWISE_XOR)
-    GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE('*', MULTIPLICATION)
-    GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE('/', DIVISION)
-    GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE('%', MODULUS)
-#undef GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE
-    default: {
-      GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid character: \"%.*s\"",
-                        (int)str.size, str.ptr);
-    }
-  }
-  if (rc != GRN_SUCCESS) {
-    return rc;
-  }
-  *token = (grn_ts_expr_token *)new_token;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_expr_parser_tokenize_next() extracts the next token. */
-static grn_rc
-grn_ts_expr_parser_tokenize_next(grn_ctx *ctx, grn_ts_expr_parser *parser,
-                                 grn_ts_str str, grn_ts_expr_token **token) {
-  grn_ts_str rest;
-  if (!parser->n_tokens) {
-    return grn_ts_expr_parser_tokenize_start(ctx, parser, str, token);
-  }
-  rest = grn_ts_str_trim_left(str);
-  if (!rest.size) {
-    return grn_ts_expr_parser_tokenize_end(ctx, parser, rest, token);
-  }
-  if (grn_ts_str_has_number_prefix(rest)) {
-    grn_ts_expr_token *prev_token;
-    if ((rest.ptr[0] != '+') && (rest.ptr[0] != '-')) {
-      return grn_ts_expr_parser_tokenize_number(ctx, parser, rest, token);
-    }
-    prev_token = parser->tokens[parser->n_tokens - 1];
-    switch (prev_token->type) {
-      case GRN_TS_EXPR_START_TOKEN:
-      case GRN_TS_EXPR_OP_TOKEN: {
-        return grn_ts_expr_parser_tokenize_number(ctx, parser, rest, token);
-      }
-      case GRN_TS_EXPR_BRACKET_TOKEN: {
-        if ((prev_token->src.ptr[0] == '(') ||
-            (prev_token->src.ptr[0] == '[')) {
-          return grn_ts_expr_parser_tokenize_number(ctx, parser, rest, token);
-        }
-        break;
-      }
-      default: {
-        break;
-      }
-    }
-  }
-  if (rest.ptr[0] == '"') {
-    return grn_ts_expr_parser_tokenize_text(ctx, parser, rest, token);
-  }
-  if (grn_ts_byte_is_name_char(rest.ptr[0])) {
-    return grn_ts_expr_parser_tokenize_name(ctx, parser, rest, token);
-  }
-  switch (rest.ptr[0]) {
-    case '(': case ')': case '[': case ']': {
-      return grn_ts_expr_parser_tokenize_bracket(ctx, parser, rest, token);
-    }
-    case '.': {
-      return grn_ts_expr_parser_tokenize_bridge(ctx, parser, rest, token);
-    }
-    default: {
-      return grn_ts_expr_parser_tokenize_op(ctx, parser, rest, token);
-    }
-  }
-}
-
-/*
- * grn_ts_expr_parser_reserve_tokens() extends a token buffer for a new token.
- */
-static grn_rc
-grn_ts_expr_parser_reserve_tokens(grn_ctx *ctx, grn_ts_expr_parser *parser) {
-  size_t i, n_bytes, new_max_n_tokens;
-  grn_ts_expr_token **new_tokens;
-  if (parser->n_tokens < parser->max_n_tokens) {
-    return GRN_SUCCESS;
-  }
-  new_max_n_tokens = parser->n_tokens * 2;
-  if (!new_max_n_tokens) {
-    new_max_n_tokens = 1;
-  }
-  n_bytes = sizeof(grn_ts_expr_token *) * new_max_n_tokens;
-  new_tokens = (grn_ts_expr_token **)GRN_REALLOC(parser->tokens, n_bytes);
-  if (!new_tokens) {
-    GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_REALLOC failed: %zu",
-                      n_bytes);
-  }
-  for (i = parser->n_tokens; i < new_max_n_tokens; i++) {
-    new_tokens[i] = NULL;
-  }
-  parser->tokens = new_tokens;
-  parser->max_n_tokens = new_max_n_tokens;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_expr_parser_tokenize() tokenizes a string. */
-static grn_rc
-grn_ts_expr_parser_tokenize(grn_ctx *ctx, grn_ts_expr_parser *parser,
-                            grn_ts_str str) {
-  grn_ts_str rest = str;
-  const char *end = str.ptr + str.size;
-  grn_ts_expr_token *token = NULL;
-  GRN_TS_DEBUG("str = \"%.*s\"", (int)str.size, str.ptr);
-  do {
-    grn_rc rc = grn_ts_expr_parser_reserve_tokens(ctx, parser);
-    if (rc != GRN_SUCCESS) {
-      return rc;
-    }
-    rc = grn_ts_expr_parser_tokenize_next(ctx, parser, rest, &token);
-    if (rc != GRN_SUCCESS) {
-      return rc;
-    }
-    if ((token->type != GRN_TS_EXPR_START_TOKEN) &&
-        (token->type != GRN_TS_EXPR_END_TOKEN)) {
-      GRN_TS_DEBUG("token = \"%.*s\"", (int)token->src.size, token->src.ptr);
-    }
-    parser->tokens[parser->n_tokens++] = token;
-    rest.ptr = token->src.ptr + token->src.size;
-    rest.size = end - rest.ptr;
-  } while (token->type != GRN_TS_EXPR_END_TOKEN);
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_expr_parser_push_const() pushes a token to an expression. */
-static grn_rc
-grn_ts_expr_parser_push_const(grn_ctx *ctx, grn_ts_expr_parser *parser,
-                              grn_ts_expr_const_token *token) {
-  switch (token->data_kind) {
-    case GRN_TS_BOOL: {
-      return grn_ts_expr_push_bool(ctx, parser->expr, token->content.as_bool);
-    }
-    case GRN_TS_INT: {
-      return grn_ts_expr_push_int(ctx, parser->expr, token->content.as_int);
-    }
-    case GRN_TS_FLOAT: {
-      return grn_ts_expr_push_float(ctx, parser->expr,
-                                    token->content.as_float);
-    }
-    case GRN_TS_TEXT: {
-      return grn_ts_expr_push_text(ctx, parser->expr, token->content.as_text);
-    }
-    default: {
-      GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d",
-                        token->data_kind);
-    }
-  }
-}
-
-/* grn_ts_expr_parser_push_name() pushes a token to an expression. */
-static grn_rc
-grn_ts_expr_parser_push_name(grn_ctx *ctx, grn_ts_expr_parser *parser,
-                             grn_ts_expr_name_token *token) {
-  return grn_ts_expr_push_name(ctx, parser->expr,
-                               token->src.ptr, token->src.size);
-}
-
-/* grn_ts_expr_parser_push_op() pushes a token to an expression. */
-static grn_rc
-grn_ts_expr_parser_push_op(grn_ctx *ctx, grn_ts_expr_parser *parser,
-                           grn_ts_expr_op_token *token) {
-  return grn_ts_expr_push_op(ctx, parser->expr, token->op_type);
-}
-
-/*
- * grn_ts_expr_parser_apply_one() applies a bridge or prior operator.
- * If there is no target, this function returns GRN_END_OF_DATA.
- */
-// FIXME: Support a ternary operator.
-static grn_rc
-grn_ts_expr_parser_apply_one(grn_ctx *ctx, grn_ts_expr_parser *parser,
-                             grn_ts_op_precedence precedence_threshold) {
-  grn_rc rc;
-  grn_ts_str src;
-  grn_ts_expr_token **stack = parser->stack;
-  grn_ts_expr_dummy_token *dummy_token;
-  size_t n_args, depth = parser->stack_depth;
-  if (depth < 2) {
-    return GRN_END_OF_DATA;
-  }
-  if (stack[depth - 1]->type != GRN_TS_EXPR_DUMMY_TOKEN) {
-    GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "argument must be dummy token");
-  }
-
-  /* Check the number of arguments. */
-  switch (stack[depth - 2]->type) {
-    case GRN_TS_EXPR_BRIDGE_TOKEN: {
-      rc = grn_ts_expr_end_subexpr(ctx, parser->expr);
-      if (rc != GRN_SUCCESS) {
-        return rc;
-      }
-      n_args = 2;
-      break;
-    }
-    case GRN_TS_EXPR_OP_TOKEN: {
-      grn_ts_expr_op_token *op_token;
-      grn_ts_op_precedence precedence;
-      op_token = (grn_ts_expr_op_token *)stack[depth - 2];
-      precedence = grn_ts_op_get_precedence(op_token->op_type);
-      if (precedence < precedence_threshold) {
-        return GRN_END_OF_DATA;
-      }
-      rc = grn_ts_expr_parser_push_op(ctx, parser, op_token);
-      if (rc != GRN_SUCCESS) {
-        return rc;
-      }
-      n_args = grn_ts_op_get_n_args(op_token->op_type);
-      break;
-    }
-    default: {
-      return GRN_END_OF_DATA;
-    }
-  }
-
-  /* Concatenate the source strings. */
-  switch (n_args) {
-    case 1: {
-      grn_ts_expr_token *arg = stack[depth - 1];
-      src.ptr = stack[depth - 2]->src.ptr;
-      src.size = (arg->src.ptr + arg->src.size) - src.ptr;
-      break;
-    }
-    case 2: {
-      grn_ts_expr_token *args[2] = { stack[depth - 3], stack[depth - 1] };
-      src.ptr = args[0]->src.ptr;
-      src.size = (args[1]->src.ptr + args[1]->src.size) - src.ptr;
-      break;
-    }
-    default: {
-      GRN_TS_ERR_RETURN(GRN_OPERATION_NOT_SUPPORTED,
-                        "invalid #arguments: %zu", n_args);
-    }
-  }
-
-  /* Replace the operator and argument tokens with a dummy token. */
-  dummy_token = &parser->dummy_tokens[parser->n_dummy_tokens++];
-  GRN_TS_DEBUG("dummy token: \"%.*s\"", (int)src.size, src.ptr);
-  grn_ts_expr_dummy_token_init(ctx, dummy_token, src);
-  depth -= n_args + 1;
-  stack[depth++] = dummy_token;
-  parser->stack_depth = depth;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_expr_parser_apply() applies bridges and prior operators. */
-static grn_rc
-grn_ts_expr_parser_apply(grn_ctx *ctx, grn_ts_expr_parser *parser,
-                         grn_ts_op_precedence precedence_threshold) {
-  for ( ; ; ) {
-    grn_rc rc = grn_ts_expr_parser_apply_one(ctx, parser,
-                                             precedence_threshold);
-    if (rc == GRN_END_OF_DATA) {
-      return GRN_SUCCESS;
-    } else if (rc != GRN_SUCCESS) {
-      return rc;
-    }
-  }
-}
-
-/* grn_ts_expr_parser_analyze_op() analyzes a token. */
-static grn_rc
-grn_ts_expr_parser_analyze_op(grn_ctx *ctx, grn_ts_expr_parser *parser,
-                              grn_ts_expr_op_token *token) {
-  size_t n_args = grn_ts_op_get_n_args(token->op_type);
-  grn_ts_expr_token *ex_token = parser->stack[parser->stack_depth - 1];
-  if (n_args == 1) {
-    if (ex_token->type == GRN_TS_EXPR_DUMMY_TOKEN) {
-      GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid token sequence");
-    }
-  } else if (n_args == 2) {
-    grn_ts_op_precedence precedence = grn_ts_op_get_precedence(token->op_type);
-    grn_rc rc = grn_ts_expr_parser_apply(ctx, parser, precedence);
-    if (rc != GRN_SUCCESS) {
-      return rc;
-    }
-  }
-  parser->stack[parser->stack_depth++] = (grn_ts_expr_token *)token;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_expr_parser_analyze_bridge() analyzes a token. */
-static grn_rc
-grn_ts_expr_parser_analyze_bridge(grn_ctx *ctx, grn_ts_expr_parser *parser,
-                                  grn_ts_expr_bridge_token *token) {
-  grn_rc rc = grn_ts_expr_begin_subexpr(ctx, parser->expr);
-  if (rc != GRN_SUCCESS) {
-    return rc;
-  }
-  parser->stack[parser->stack_depth++] = (grn_ts_expr_token *)token;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_expr_parser_analyze_bracket() analyzes a token. */
-static grn_rc
-grn_ts_expr_parser_analyze_bracket(grn_ctx *ctx, grn_ts_expr_parser *parser,
-                                   grn_ts_expr_bracket_token *token) {
-  grn_ts_expr_token *ex_token = parser->stack[parser->stack_depth - 1];
-  switch (token->src.ptr[0]) {
-    case '(': {
-      if (ex_token->type == GRN_TS_EXPR_DUMMY_TOKEN) {
-        GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid token sequence");
-      }
-      parser->stack[parser->stack_depth++] = (grn_ts_expr_token *)token;
-      return GRN_SUCCESS;
-    }
-    case '[': {
-      if (ex_token->type != GRN_TS_EXPR_DUMMY_TOKEN) {
-        GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid token sequence");
-      }
-      parser->stack[parser->stack_depth++] = (grn_ts_expr_token *)token;
-      return GRN_SUCCESS;
-    }
-    case ')': case ']': {
-      grn_ts_expr_token *ex_ex_token;
-      grn_rc rc = grn_ts_expr_parser_apply(ctx, parser, 0);
-      if (rc != GRN_SUCCESS) {
-        return rc;
-      }
-      if (parser->stack_depth < 2) {
-        GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid token sequence");
-      }
-      ex_ex_token = parser->stack[parser->stack_depth - 2];
-      if (ex_ex_token->type != GRN_TS_EXPR_BRACKET_TOKEN) {
-        GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid token sequence");
-      }
-      if (token->src.ptr[0] == ')') {
-        size_t depth = parser->stack_depth;
-        grn_ts_str src;
-        grn_ts_expr_dummy_token *dummy_token;
-        if (ex_ex_token->src.ptr[0] != '(') {
-          GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid token sequence");
-        }
-        src.ptr = ex_ex_token->src.ptr;
-        src.size = (token->src.ptr + token->src.size) - src.ptr;
-        dummy_token = &parser->dummy_tokens[parser->n_dummy_tokens++];
-        GRN_TS_DEBUG("dummy token: \"%.*s\"", (int)src.size, src.ptr);
-        grn_ts_expr_dummy_token_init(ctx, dummy_token, src);
-        parser->stack[depth - 2] = dummy_token;
-        parser->stack_depth--;
-        // TODO: Apply a function.
-      } else if (token->src.ptr[0] == ']') {
-        size_t depth = parser->stack_depth;
-        if (ex_ex_token->src.ptr[0] != '[') {
-          GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid token sequence");
-        }
-        parser->stack[depth - 2] = parser->stack[depth - 1];
-        parser->stack_depth--;
-        // TODO: Push a subscript operator.
-      }
-      return GRN_SUCCESS;
-    }
-    default: {
-      GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "undefined bracket: \"%.*s\"",
-                        (int)token->src.size, token->src.ptr);
-    }
-  }
-}
-
-/* grn_ts_expr_parser_analyze_token() analyzes a token. */
-static grn_rc
-grn_ts_expr_parser_analyze_token(grn_ctx *ctx, grn_ts_expr_parser *parser,
-                                 grn_ts_expr_token *token) {
-  switch (token->type) {
-    case GRN_TS_EXPR_START_TOKEN: {
-      parser->stack[parser->stack_depth++] = token;
-      return GRN_SUCCESS;
-    }
-    case GRN_TS_EXPR_END_TOKEN: {
-      return grn_ts_expr_parser_apply(ctx, parser, 0);
-    }
-    case GRN_TS_EXPR_CONST_TOKEN: {
-      grn_ts_expr_const_token *const_token = (grn_ts_expr_const_token *)token;
-      grn_ts_expr_dummy_token *dummy_token;
-      grn_rc rc = grn_ts_expr_parser_push_const(ctx, parser, const_token);
-      if (rc != GRN_SUCCESS) {
-        return rc;
-      }
-      dummy_token = &parser->dummy_tokens[parser->n_dummy_tokens++];
-      grn_ts_expr_dummy_token_init(ctx, dummy_token, token->src);
-      parser->stack[parser->stack_depth++] = dummy_token;
-      return GRN_SUCCESS;
-    }
-    case GRN_TS_EXPR_NAME_TOKEN: {
-      grn_ts_expr_name_token *name_token = (grn_ts_expr_name_token *)token;
-      grn_ts_expr_dummy_token *dummy_token;
-      grn_rc rc = grn_ts_expr_parser_push_name(ctx, parser, name_token);
-      if (rc != GRN_SUCCESS) {
-        return rc;
-      }
-      dummy_token = &parser->dummy_tokens[parser->n_dummy_tokens++];
-      grn_ts_expr_dummy_token_init(ctx, dummy_token, token->src);
-      parser->stack[parser->stack_depth++] = dummy_token;
-      return GRN_SUCCESS;
-    }
-    case GRN_TS_EXPR_OP_TOKEN: {
-      grn_ts_expr_op_token *op_token = (grn_ts_expr_op_token *)token;
-      return grn_ts_expr_parser_analyze_op(ctx, parser, op_token);
-    }
-    case GRN_TS_EXPR_BRIDGE_TOKEN: {
-      grn_ts_expr_bridge_token *bridge_token;
-      bridge_token = (grn_ts_expr_bridge_token *)token;
-      return grn_ts_expr_parser_analyze_bridge(ctx, parser, bridge_token);
-    }
-    case GRN_TS_EXPR_BRACKET_TOKEN: {
-      grn_ts_expr_bracket_token *bracket_token;
-      bracket_token = (grn_ts_expr_bracket_token *)token;
-      return grn_ts_expr_parser_analyze_bracket(ctx, parser, bracket_token);
-    }
-    default: {
-      GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid token type: %d",
-                        token->type);
-    }
-  }
-}
-
-/* grn_ts_expr_parser_analyze() analyzes tokens. */
-static grn_rc
-grn_ts_expr_parser_analyze(grn_ctx *ctx, grn_ts_expr_parser *parser) {
-  size_t i;
-
-  /* Reserve temporary work spaces. */
-  parser->dummy_tokens = GRN_MALLOCN(grn_ts_expr_dummy_token,
-                                     parser->n_tokens);
-  if (!parser->dummy_tokens) {
-    GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %zu x %zu",
-                      sizeof(grn_ts_expr_dummy_token), parser->n_tokens);
-  }
-  parser->stack = GRN_MALLOCN(grn_ts_expr_token *, parser->n_tokens);
-  if (!parser->stack) {
-    GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %zu x %zu",
-                      sizeof(grn_ts_expr_token *), parser->n_tokens);
-  }
-
-  /* Analyze tokens. */
-  for (i = 0; i < parser->n_tokens; i++) {
-    grn_rc rc;
-    rc = grn_ts_expr_parser_analyze_token(ctx, parser, parser->tokens[i]);
-    if (rc != GRN_SUCCESS) {
-      return rc;
-    }
-  }
-  if (parser->stack_depth != 2) {
-    GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "tokens left in stack: %zu",
-                      parser->stack_depth);
-  }
-  return GRN_SUCCESS;
-}
-
-/*
- * grn_ts_expr_parser_parse() parses a string and pushes nodes into an
- * expression.
- */
-static grn_rc
-grn_ts_expr_parser_parse(grn_ctx *ctx, grn_ts_expr_parser *parser,
-                         const char *str_ptr, size_t str_size) {
-  grn_rc rc;
-  grn_ts_str str;
-  rc = grn_ts_buf_reserve(ctx, &parser->str_buf, str_size + 1);
-  if (rc != GRN_SUCCESS) {
-    return rc;
-  }
-  grn_memcpy(parser->str_buf.ptr, str_ptr, str_size);
-  ((char *)parser->str_buf.ptr)[str_size] = '\0';
-  str.ptr = (const char *)parser->str_buf.ptr;
-  str.size = str_size;
-  rc = grn_ts_expr_parser_tokenize(ctx, parser, str);
-  if (rc != GRN_SUCCESS) {
-    return rc;
-  }
-  rc = grn_ts_expr_parser_analyze(ctx, parser);
-  if (rc != GRN_SUCCESS) {
-    return rc;
-  }
-  return GRN_SUCCESS;
-}
-
-/*-------------------------------------------------------------
- * grn_ts_expr_bridge.
- */
-
-/* grn_ts_expr_bridge_init() initializes a bridge. */
-static void
-grn_ts_expr_bridge_init(grn_ctx *ctx, grn_ts_expr_bridge *bridge) {
-  memset(bridge, 0, sizeof(*bridge));
-  bridge->src_table = NULL;
-  bridge->dest_table = NULL;
-}
-
-/* grn_ts_expr_bridge_fin() finalizes a bridge. */
-static void
-grn_ts_expr_bridge_fin(grn_ctx *ctx, grn_ts_expr_bridge *bridge) {
-  if (bridge->dest_table) {
-    grn_obj_unlink(ctx, bridge->dest_table);
-  }
-  /* Note: bridge->src_table does not increment a reference count. */
-}
-
-/*-------------------------------------------------------------
- * grn_ts_expr.
- */
-
-/* grn_ts_expr_init() initializes an expression. */
-static void
-grn_ts_expr_init(grn_ctx *ctx, grn_ts_expr *expr) {
-  memset(expr, 0, sizeof(*expr));
-  expr->table = NULL;
-  expr->curr_table = NULL;
-  expr->root = NULL;
-  expr->stack = NULL;
-  expr->bridges = NULL;
-}
-
-/* grn_ts_expr_fin() finalizes an expression. */
-static void
-grn_ts_expr_fin(grn_ctx *ctx, grn_ts_expr *expr) {
-  size_t i;
-  if (expr->bridges) {
-    for (i = 0; i < expr->n_bridges; i++) {
-      grn_ts_expr_bridge_fin(ctx, &expr->bridges[i]);
-    }
-    GRN_FREE(expr->bridges);
-  }
-  if (expr->stack) {
-    for (i = 0; i < expr->stack_depth; i++) {
-      if (expr->stack[i]) {
-        grn_ts_expr_node_close(ctx, expr->stack[i]);
-      }
-    }
-    GRN_FREE(expr->stack);
-  }
-  /* Note: expr->curr_table does not increment a reference count. */
-  if (expr->table) {
-    grn_obj_unlink(ctx, expr->table);
-  }
-}
-
-grn_rc
-grn_ts_expr_open(grn_ctx *ctx, grn_obj *table, grn_ts_expr **expr) {
-  grn_rc rc;
-  grn_ts_expr *new_expr;
-  if (!ctx) {
-    return GRN_INVALID_ARGUMENT;
-  }
-  if (!table || !grn_ts_obj_is_table(ctx, table) || !expr) {
-    GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument");
-  }
-  new_expr = GRN_MALLOCN(grn_ts_expr, 1);
-  if (!new_expr) {
-    GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %zu x 1",
-                      sizeof(grn_ts_expr));
-  }
-  rc = grn_ts_obj_increment_ref_count(ctx, table);
-  if (rc != GRN_SUCCESS) {
-    GRN_FREE(new_expr);
-    return rc;
-  }
-  grn_ts_expr_init(ctx, new_expr);
-  new_expr->table = table;
-  new_expr->curr_table = table;
-  *expr = new_expr;
-  return GRN_SUCCESS;
-}
-
-grn_rc
-grn_ts_expr_parse(grn_ctx *ctx, grn_obj *table,
-                  const char *str_ptr, size_t str_size, grn_ts_expr **expr) {
-  grn_rc rc;
-  grn_ts_expr *new_expr;
-  if (!ctx) {
-    return GRN_INVALID_ARGUMENT;
-  }
-  if (!table || !grn_ts_obj_is_table(ctx, table) ||
-      (!str_ptr && str_size) || !expr) {
-    GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument");
-  }
-  rc = grn_ts_expr_open(ctx, table, &new_expr);
-  if (rc != GRN_SUCCESS) {
-    return rc;
-  }
-  rc = grn_ts_expr_push(ctx, new_expr, str_ptr, str_size);
-  if (rc == GRN_SUCCESS) {
-    rc = grn_ts_expr_complete(ctx, new_expr);
-  }
-  if (rc != GRN_SUCCESS) {
-    grn_ts_expr_close(ctx, new_expr);
-    return rc;
-  }
-  *expr = new_expr;
-  return GRN_SUCCESS;
-}
-
-grn_rc
-grn_ts_expr_close(grn_ctx *ctx, grn_ts_expr *expr) {
-  if (!ctx || !expr) {
-    return GRN_INVALID_ARGUMENT;
-  }
-  grn_ts_expr_fin(ctx, expr);
-  GRN_FREE(expr);
-  return GRN_SUCCESS;
-}
-
-grn_obj *
-grn_ts_expr_get_table(grn_ctx *ctx, grn_ts_expr *expr) {
-  if (!ctx || !expr) {
-    return NULL;
-  }
-  /* The reference counting will never fail in practice. */
-  if (grn_ts_obj_increment_ref_count(ctx, expr->table) != GRN_SUCCESS) {
-    return NULL;
-  }
-  return expr->table;
-}
-
-grn_ts_expr_type
-grn_ts_expr_get_type(grn_ctx *ctx, grn_ts_expr *expr) {
-  return (!ctx || !expr) ? GRN_TS_EXPR_BROKEN : expr->type;
-}
-
-grn_ts_data_kind
-grn_ts_expr_get_data_kind(grn_ctx *ctx, grn_ts_expr *expr) {
-  return (!ctx || !expr) ? GRN_TS_VOID : expr->data_kind;
-}
-
-grn_ts_data_type
-grn_ts_expr_get_data_type(grn_ctx *ctx, grn_ts_expr *expr) {
-  return (!ctx || !expr) ? GRN_DB_VOID : expr->data_type;
-}
-
-grn_ts_expr_node *
-grn_ts_expr_get_root(grn_ctx *ctx, grn_ts_expr *expr) {
-  return (!ctx || !expr) ? NULL : expr->root;
-}
-
-/* grn_ts_expr_reserve_stack() extends a stack. */
-static grn_rc
-grn_ts_expr_reserve_stack(grn_ctx *ctx, grn_ts_expr *expr) {
-  size_t i, n_bytes, new_size;
-  grn_ts_expr_node **new_stack;
-  if (expr->stack_depth < expr->stack_size) {
-    return GRN_SUCCESS;
-  }
-  new_size = expr->stack_size ? (expr->stack_size * 2) : 1;
-  n_bytes = sizeof(grn_ts_expr_node *) * new_size;
-  new_stack = GRN_REALLOC(expr->stack, n_bytes);
-  if (!new_stack) {
-    GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_REALLOC failed: %zu",
-                      n_bytes);
-  }
-  for (i = expr->stack_size; i < new_size; i++) {
-    new_stack[i] = NULL;
-  }
-  expr->stack = new_stack;
-  expr->stack_size = new_size;
-  return GRN_SUCCESS;
-}
-
-/* grn_ts_expr_deref() dereferences a node. */
-static grn_rc
-grn_ts_expr_deref(grn_ctx *ctx, grn_ts_expr *expr,
-                  grn_ts_expr_node **node_ptr) {
-  grn_ts_expr_node *node = *node_ptr;
-  while (node->data_kind == GRN_TS_REF) {
-    grn_rc rc;
-    grn_ts_expr_node *key_node, *bridge_node;
-    grn_id table_id = node->data_type;
-    grn_obj *table = grn_ctx_at(ctx, table_id);
-    if (!table) {
-      return GRN_OBJECT_CORRUPT;
-    }
-    if (!grn_ts_obj_is_table(ctx, table)) {
-      grn_obj_unlink(ctx, table);
-      return GRN_OBJECT_CORRUPT;
-    }
-    rc = grn_ts_expr_key_node_open(ctx, table, &key_node);
-    grn_obj_unlink(ctx, table);
-    if (rc != GRN_SUCCESS) {
-      return rc;
-    }
-    rc = grn_ts_expr_bridge_node_open(ctx, node, key_node, &bridge_node);
-    if (rc != GRN_SUCCESS) {
-      return rc;
-    }
-    node = bridge_node;
-  }
-  *node_ptr = node;
-  return GRN_SUCCESS;
-}
-
-grn_rc
-grn_ts_expr_push(grn_ctx *ctx, grn_ts_expr *expr,
-                 const char *str_ptr, size_t str_size) {
-  grn_rc rc;
-  grn_ts_expr_parser *parser;
-  if (!ctx) {
-    return GRN_INVALID_ARGUMENT;
-  }
-  if (!expr || (expr->type != GRN_TS_EXPR_INCOMPLETE) ||
-      (!str_ptr && str_size)) {
-    GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument");
-  }
-  rc = grn_ts_expr_parser_open(ctx, expr, &parser);
-  if (rc != GRN_SUCCESS) {
-    return rc;
-  }
-  rc = grn_ts_expr_parser_parse(ctx, parser, str_ptr, str_size);
-  grn_ts_expr_parser_close(ctx, parser);
-  return rc;
-}
-
-grn_rc
-grn_ts_expr_push_name(grn_ctx *ctx, grn_ts_expr *expr,
-                     const char *name_ptr, size_t name_size) {
-  grn_obj *column;
-  grn_ts_str name = { name_ptr, name_size };
-  if (!ctx) {
-    return GRN_INVALID_ARGUMENT;
-  }
-  if (!expr || (expr->type != GRN_TS_EXPR_INCOMPLETE) ||
-      !grn_ts_str_is_name(name)) {
-    GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument");
-  }
-  if (grn_ts_str_is_id_name(name)) {
-    return grn_ts_expr_push_id(ctx, expr);
-  }
-  if (grn_ts_str_is_score_name(name)) {
-    return grn_ts_expr_push_score(ctx, expr);
-  }
-  if (grn_ts_str_is_key_name(name)) {
-    return grn_ts_expr_push_key(ctx, expr);
-  }
-  if (grn_ts_str_is_value_name(name)) {
-    return grn_ts_expr_push_value(ctx, expr);
-  }
-  /* grn_obj_column() returns a column or accessor. */
-  column = grn_obj_column(ctx, expr->curr_table, name.ptr, name.size);
-  if (!column) {
-    GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "object not found: \"%.*s\"",
-                      (int)name.size, name.ptr);
-  }
-  return grn_ts_expr_push_obj(ctx, expr, column);
-}
-
-#define GRN_TS_EXPR_PUSH_BULK_CASE(TYPE, kind)\
-  case GRN_DB_ ## TYPE: {\
-    return grn_ts_expr_push_ ## kind(ctx, expr, GRN_ ## TYPE ## _VALUE(obj));\
-  }
-/* grn_ts_expr_push_bulk() pushes a scalar. */
-static grn_rc
-grn_ts_expr_push_bulk(grn_ctx *ctx, grn_ts_expr *expr, grn_obj *obj) {
-  switch (obj->header.domain) {
-    GRN_TS_EXPR_PUSH_BULK_CASE(BOOL, bool)
-    GRN_TS_EXPR_PUSH_BULK_CASE(INT8, int)
-    GRN_TS_EXPR_PUSH_BULK_CASE(INT16, int)
-    GRN_TS_EXPR_PUSH_BULK_CASE(INT32, int)
-    GRN_TS_EXPR_PUSH_BULK_CASE(INT64, int)
-    GRN_TS_EXPR_PUSH_BULK_CASE(UINT8, int)
-    GRN_TS_EXPR_PUSH_BULK_CASE(UINT16, int)
-    GRN_TS_EXPR_PUSH_BULK_CASE(UINT32, int)
-    /* The behavior is undefined if a value is greater than 2^63 - 1. */
-    GRN_TS_EXPR_PUSH_BULK_CASE(UINT64, int)
-    GRN_TS_EXPR_PUSH_BULK_CASE(FLOAT, float)
-    GRN_TS_EXPR_PUSH_BULK_CASE(TIME, time)
-    case GRN_DB_SHORT_TEXT:
-    case GRN_DB_TEXT:
-    case GRN_DB_LONG_TEXT: {
-      grn_ts_text value = { GRN_TEXT_VALUE(obj), GRN_TEXT_LEN(obj) };
-      return grn_ts_expr_push_text(ctx, expr, value);
-    }
-    case GRN_DB_TOKYO_GEO_POINT: {
-      grn_ts_geo value;
-      GRN_GEO_POINT_VALUE(obj, value.latitude, value.longitude);
-      return grn_ts_expr_push_tokyo_geo(ctx, expr, value);
-    }
-    case GRN_DB_WGS84_GEO_POINT: {
-      grn_ts_geo value;
-      GRN_GEO_POINT_VALUE(obj, value.latitude, value.longitude);
-      return grn_ts_expr_push_wgs84_geo(ctx, expr, value);
-    }
-    default: {
-      GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "not bulk");
-    }
-  }
-}
-#undef GRN_TS_EXPR_PUSH_BULK_CASE
-
-#define GRN_TS_EXPR_PUSH_UVECTOR_CASE(TYPE, kind)\
-  case GRN_DB_ ## TYPE: {\
-    grn_ts_ ## kind ##_vector value = { (grn_ts_ ## kind *)GRN_BULK_HEAD(obj),\
-                                        grn_uvector_size(ctx, obj) };\
-    return grn_ts_expr_push_ ## kind ## _vector(ctx, expr, value);\
-  }
-#define GRN_TS_EXPR_PUSH_UVECTOR_CASE_WITH_TYPECAST(TYPE, kind)\
-  case GRN_DB_ ## TYPE: {\
-    size_t i;\
-    grn_rc rc;\
-    grn_ts_ ## kind *buf;\
-    grn_ts_ ## kind ## _vector value = { NULL, grn_uvector_size(ctx, obj) };\
-    if (!value.size) {\
-      return grn_ts_expr_push_ ## kind ## _vector(ctx, expr, value);\
-    }\
-    buf = GRN_MALLOCN(grn_ts_ ## kind, value.size);\
-    if (!buf) {\
-      GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE,\
-                        "GRN_MALLOCN failed: %zu x 1",\
-                        sizeof(grn_ts_ ## kind));\
-    }\
-    for (i = 0; i < value.size; i++) {\
-      buf[i] = GRN_ ## TYPE ##_VALUE_AT(obj, i);\
-    }\
-    value.ptr = buf;\
-    rc = grn_ts_expr_push_ ## kind ## _vector(ctx, expr, value);\
-    GRN_FREE(buf);\
-    return rc;\
-  }
-/* grn_ts_expr_push_uvector() pushes an array of fixed-size values. */
-static grn_rc
-grn_ts_expr_push_uvector(grn_ctx *ctx, grn_ts_expr *expr, grn_obj *obj) {
-  switch (obj->header.domain) {
-    GRN_TS_EXPR_PUSH_UVECTOR_CASE(BOOL, bool)
-    GRN_TS_EXPR_PUSH_UVECTOR_CASE_WITH_TYPECAST(INT8, int)
-    GRN_TS_EXPR_PUSH_UVECTOR_CASE_WITH_TYPECAST(INT16, int)
-    GRN_TS_EXPR_PUSH_UVECTOR_CASE_WITH_TYPECAST(INT32, int)
-    GRN_TS_EXPR_PUSH_UVECTOR_CASE(INT64, int)
-    GRN_TS_EXPR_PUSH_UVECTOR_CASE_WITH_TYPECAST(UINT8, int)
-    GRN_TS_EXPR_PUSH_UVECTOR_CASE_WITH_TYPECAST(UINT16, int)
-    GRN_TS_EXPR_PUSH_UVECTOR_CASE_WITH_TYPECAST(UINT32, int)
-    GRN_TS_EXPR_PUSH_UVECTOR_CASE(UINT64, int)
-    GRN_TS_EXPR_PUSH_UVECTOR_CASE(TIME, time)
-    GRN_TS_EXPR_PUSH_UVECTOR_CASE(TOKYO_GEO_POINT, tokyo_geo)
-    GRN_TS_EXPR_PUSH_UVECTOR_CASE(WGS84_GEO_POINT, wgs84_geo)
-    default: {
-      GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data type: %d",
-                        obj->header.domain);
-    }
-  }
-}
-#undef GRN_TS_EXPR_PUSH_UVECTOR_CASE_WITH_TYPECAST
-#undef GRN_TS_EXPR_PUSH_UVECTOR_CASE
-
-/* grn_ts_expr_push_vector() pushes an array of texts. */
-static grn_rc
-grn_ts_expr_push_vector(grn_ctx *ctx, grn_ts_expr *expr, grn_obj *obj) {
-  switch (obj->header.domain) {
-    case GRN_DB_SHORT_TEXT:
-    case GRN_DB_TEXT:
-    case GRN_DB_LONG_TEXT: {
-      size_t i;
-      grn_rc rc;
-      grn_ts_text *buf;
-      grn_ts_text_vector value = { NULL, grn_vector_size(ctx, obj) };
-      if (!value.size) {
-        return grn_ts_expr_push_text_vector(ctx, expr, value);
-      }
-      buf = GRN_MALLOCN(grn_ts_text, value.size);
-      if (!buf) {
-        GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE,
-                          "GRN_MALLOCN failed: %zu x %zu",
-                          sizeof(grn_ts_text), value.size);
-      }
-      for (i = 0; i < value.size; i++) {
-        buf[i].size = grn_vector_get_element(ctx, obj, i, &buf[i].ptr,
-                                             NULL, NULL);
-      }
-      value.ptr = buf;
-      rc = grn_ts_expr_push_text_vector(ctx, expr, value);
-      GRN_FREE(buf);
-      return rc;
-    }
-    default: {
-      GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data type: %d",
-                        obj->header.domain);
-    }
-  }
-}
-
-static grn_rc
-grn_ts_expr_push_single_accessor(grn_ctx *ctx, grn_ts_expr *expr,
-                                 grn_accessor *accessor) {
-  switch (accessor->action) {
-    case GRN_ACCESSOR_GET_ID: {
-      return grn_ts_expr_push_id(ctx, expr);
-    }
-    case GRN_ACCESSOR_GET_SCORE: {
-      return grn_ts_expr_push_score(ctx, expr);
-    }
-    case GRN_ACCESSOR_GET_KEY: {
-      if (accessor->obj != expr->curr_table) {
-        GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "table conflict");
-      }
-      return grn_ts_expr_push_key(ctx, expr);
-    }
-    case GRN_ACCESSOR_GET_VALUE: {
-      if (accessor->obj != expr->curr_table) {
-        GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "table conflict");
-      }
-      return grn_ts_expr_push_value(ctx, expr);
-    }
-    case GRN_ACCESSOR_GET_COLUMN_VALUE: {
-      return grn_ts_expr_push_column(ctx, expr, accessor->obj);
-    }
-    default: {
-      GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid accessor action: %d",
-                        accessor->action);
-    }
-  }
-}
-
-static grn_rc
-grn_ts_expr_push_accessor(grn_ctx *ctx, grn_ts_expr *expr,
-                          grn_accessor *accessor) {
-  grn_rc rc = grn_ts_expr_push_single_accessor(ctx, expr, accessor);
-  if (rc != GRN_SUCCESS) {
-    return rc;
-  }
-  for (accessor = accessor->next; accessor; accessor = accessor->next) {
-    rc = grn_ts_expr_begin_subexpr(ctx, expr);
-    if (rc != GRN_SUCCESS) {
-      return rc;
-    }
-    rc = grn_ts_expr_push_single_accessor(ctx, expr, accessor);
-    if (rc != GRN_SUCCESS) {
-      return rc;
-    }
-    rc = grn_ts_expr_end_subexpr(ctx, expr);
-    if (rc != GRN_SUCCESS) {
-      return rc;
-    }
-  }
-  return GRN_SUCCESS;
-}
-
-grn_rc
-grn_ts_expr_push_obj(grn_ctx *ctx, grn_ts_expr *expr, grn_obj *obj) {
-  if (!ctx) {
-    return GRN_INVALID_ARGUMENT;
-  }
-  if (!expr || (expr->type != GRN_TS_EXPR_INCOMPLETE) || !obj) {
-    GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument");
-  }
-  switch (obj->header.type) {
-    case GRN_BULK: {
-      return grn_ts_expr_push_bulk(ctx, expr, obj);
-    }
-    case GRN_UVECTOR: {
-      return grn_ts_expr_push_uvector(ctx, expr, obj);
-    }
-    case GRN_VECTOR: {
-      return grn_ts_expr_push_vector(ctx, expr, obj);
-    }
-    case GRN_ACCESSOR: {
-      return grn_ts_expr_push_accessor(ctx, expr, (grn_accessor *)obj);
-    }
-    case GRN_COLUMN_FIX_SIZE:
-    case GRN_COLUMN_VAR_SIZE: {
-      return grn_ts_expr_push_column(ctx, expr, obj);
-    }
-    default: {
-      GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid object type: %d",
-                        obj->header.type);
-    }
-  }
-}
-
-grn_rc
-grn_ts_expr_push_id(grn_ctx *ctx, grn_ts_expr *expr) {
-  grn_rc rc;
-  grn_ts_expr_node *node;
-  if (!ctx) {
-    return GRN_INVALID_ARGUMENT;
-  }
-  if (!expr || (expr->type != GRN_TS_EXPR_INCOMPLETE)) {
-    GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument");
-  }
-  rc = grn_ts_expr_reserve_stack(ctx, expr);
-  if (rc == GRN_SUCCESS) {
-    rc = grn_ts_expr_id_node_open(ctx, &node);
-    if (rc == GRN_SUCCESS) {
-      expr->stack[expr->stack_depth++] = node;
-    }
-  }
-  return rc;
-}
-
-grn_rc
-grn_ts_expr_push_score(grn_ctx *ctx, grn_ts_expr *expr) {
-  grn_rc rc;
-  grn_ts_expr_node *node;
-  if (!ctx) {
-    return GRN_INVALID_ARGUMENT;
-  }
-  if (!expr || (expr->type != GRN_TS_EXPR_INCOMPLETE)) {
-    GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument");
-  }
-  rc = grn_ts_expr_reserve_stack(ctx, expr);
-  if (rc == GRN_SUCCESS) {
-    rc = grn_ts_expr_score_node_open(ctx, &node);
-    if (rc == GRN_SUCCESS) {
-      expr->stack[expr->stack_depth++] = node;
-    }
-  }
-  return rc;
-}
-
-grn_rc
-grn_ts_expr_push_key(grn_ctx *ctx, grn_ts_expr *expr) {
-  grn_rc rc;
-  grn_ts_expr_node *node;
-  if (!ctx) {
-    return GRN_INVALID_ARGUMENT;
-  }
-  if (!expr || (expr->type != GRN_TS_EXPR_INCOMPLETE)) {
-    GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument");
-  }
-  rc = grn_ts_expr_reserve_stack(ctx, expr);
-  if (rc == GRN_SUCCESS) {
-    rc = grn_ts_expr_key_node_open(ctx, expr->curr_table, &node);
-    if (rc == GRN_SUCCESS) {
-      expr->stack[expr->stack_depth++] = node;
-    }
-  }
-  return rc;
-}
-
-grn_rc
-grn_ts_expr_push_value(grn_ctx *ctx, grn_ts_expr *expr) {
-  grn_rc rc;
-  grn_ts_expr_node *node;
-  if (!ctx) {
-    return GRN_INVALID_ARGUMENT;
-  }
-  if (!expr || (expr->type != GRN_TS_EXPR_INCOMPLETE)) {
-    GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument");
-  }
-  rc = grn_ts_expr_reserve_stack(ctx, expr);
-  if (rc == GRN_SUCCESS) {
-    rc = grn_ts_expr_value_node_open(ctx, expr->curr_table, &node);
-    if (rc == GRN_SUCCESS) {
-      expr->stack[expr->stack_depth++] = node;
-    }
-  }
-  return rc;
-}
-
-#define GRN_TS_EXPR_PUSH_CONST_CASE(KIND, kind)\
-  case GRN_TS_ ## KIND: {\
-    return grn_ts_expr_push_ ## kind(ctx, expr,\
-                                     *(const grn_ts_ ## kind *)value);\
-  }
-grn_rc
-grn_ts_expr_push_const(grn_ctx *ctx, grn_ts_expr *expr,
-                       grn_ts_data_kind kind, const void *value) {
-  if (!ctx) {
-    return GRN_INVALID_ARGUMENT;
-  }
-  if (!expr || (expr->type != GRN_TS_EXPR_INCOMPLETE) || !value) {
-    GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument");
-  }
-  switch (kind) {
-    GRN_TS_EXPR_PUSH_CONST_CASE(BOOL, bool)
-    GRN_TS_EXPR_PUSH_CONST_CASE(INT, int)
-    GRN_TS_EXPR_PUSH_CONST_CASE(FLOAT, float)
-    GRN_TS_EXPR_PUSH_CONST_CASE(TIME, time)
-    GRN_TS_EXPR_PUSH_CONST_CASE(TEXT, text)
-    GRN_TS_EXPR_PUSH_CONST_CASE(GEO, geo)
-    GRN_TS_EXPR_PUSH_CONST_CASE(BOOL_VECTOR, bool_vector)
-    GRN_TS_EXPR_PUSH_CONST_CASE(INT_VECTOR, int_vector)
-    GRN_TS_EXPR_PUSH_CONST_CASE(FLOAT_VECTOR, float_vector)
-    GRN_TS_EXPR_PUSH_CONST_CASE(TIME_VECTOR, time_vector)
-    GRN_TS_EXPR_PUSH_CONST_CASE(TEXT_VECTOR, text_vector)
-    GRN_TS_EXPR_PUSH_CONST_CASE(GEO_VECTOR, geo_vector)
-    default: {
-      GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", kind);
-    }
-  }
-}
-#undef GRN_TS_EXPR_PUSH_CONST_CASE
-
-grn_rc
-grn_ts_expr_push_column(grn_ctx *ctx, grn_ts_expr *expr, grn_obj *column) {
-  grn_rc rc;
-  grn_ts_expr_node *node;
-  if (!ctx) {
-    return GRN_INVALID_ARGUMENT;
-  }
-  if (!expr || (expr->type != GRN_TS_EXPR_INCOMPLETE) ||
-      !column || !grn_ts_obj_is_column(ctx, column) ||
-      (DB_OBJ(expr->curr_table)->id != column->header.domain)) {
-    GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument");
-  }
-  rc = grn_ts_expr_reserve_stack(ctx, expr);
-  if (rc == GRN_SUCCESS) {
-    rc = grn_ts_expr_column_node_open(ctx, column, &node);
-    if (rc == GRN_SUCCESS) {
-      expr->stack[expr->stack_depth++] = node;
-    }
-  }
-  return rc;
-}
-
-grn_rc
-grn_ts_expr_push_op(grn_ctx *ctx, grn_ts_expr *expr, grn_ts_op_type op_type) {
-  grn_rc rc;
-  grn_ts_expr_node **args, *node;
-  size_t i, n_args;
-  if (!ctx) {
-    return GRN_INVALID_ARGUMENT;
-  }
-  if (!expr || (expr->type != GRN_TS_EXPR_INCOMPLETE)) {
-    GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument");
-  }
-  n_args = grn_ts_op_get_n_args(op_type);
-  if (!n_args) {
-    GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid #arguments: %zu", n_args);
-  }
-  if (n_args > expr->stack_depth) {
-    GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid #arguments: %zu, %zu",
-                      n_args, expr->stack_depth);
-  }
-  /* Arguments are the top n_args nodes in the stack. */
-  args = &expr->stack[expr->stack_depth - n_args];
-  for (i = 0; i < n_args; i++) {
-    /*
-     * FIXME: Operators "==" and "!=" should compare arguments as references
-     *        if possible.
-     */
-    rc = grn_ts_expr_deref(ctx, expr, &args[i]);
-    if (rc != GRN_SUCCESS) {
-      return rc;
-    }
-  }
-  expr->stack_depth -= n_args;
-  rc = grn_ts_expr_op_node_open(ctx, op_type, args, n_args, &node);
-  if (rc == GRN_SUCCESS) {
-    expr->stack[expr->stack_depth++] = node;
-  }
-  return rc;
-}
-
-#define GRN_TS_EXPR_PUSH_CONST(KIND, kind)\
-  grn_rc rc;\
-  grn_ts_expr_node *node;\
-  if (!ctx) {\
-    return GRN_INVALID_ARGUMENT;\
-  }\
-  if (!expr || (expr->type != GRN_TS_EXPR_INCOMPLETE) ||\
-      !grn_ts_ ## kind ## _is_valid(value)) {\
-    GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument");\
-  }\
-  rc = grn_ts_expr_reserve_stack(ctx, expr);\
-  if (rc == GRN_SUCCESS) {\
-    rc = grn_ts_expr_const_node_open(ctx, GRN_TS_ ## KIND, &value, &node);\
-    if (rc == GRN_SUCCESS) {\
-      expr->stack[expr->stack_depth++] = node;\
-    }\
-  }
-grn_rc
-grn_ts_expr_push_bool(grn_ctx *ctx, grn_ts_expr *expr, grn_ts_bool value) {
-  GRN_TS_EXPR_PUSH_CONST(BOOL, bool)
-  return rc;
-}
-
-grn_rc
-grn_ts_expr_push_int(grn_ctx *ctx, grn_ts_expr *expr, grn_ts_int value) {
-  GRN_TS_EXPR_PUSH_CONST(INT, int)
-  return rc;
-}
-
-grn_rc
-grn_ts_expr_push_float(grn_ctx *ctx, grn_ts_expr *expr, grn_ts_float value) {
-  GRN_TS_EXPR_PUSH_CONST(FLOAT, float)
-  return rc;
-}
-
-grn_rc
-grn_ts_expr_push_time(grn_ctx *ctx, grn_ts_expr *expr, grn_ts_time value) {
-  GRN_TS_EXPR_PUSH_CONST(TIME, time)
-  return rc;
-}
-
-grn_rc
-grn_ts_expr_push_text(grn_ctx *ctx, grn_ts_expr *expr, grn_ts_text value) {
-  GRN_TS_EXPR_PUSH_CONST(TEXT, text)
-  return rc;
-}
-
-grn_rc
-grn_ts_expr_push_geo(grn_ctx *ctx, grn_ts_expr *expr, grn_ts_geo value) {
-  GRN_TS_EXPR_PUSH_CONST(GEO, geo)
-  return rc;
-}
-
-grn_rc
-grn_ts_expr_push_tokyo_geo(grn_ctx *ctx, grn_ts_expr *expr, grn_ts_geo value) {
-  GRN_TS_EXPR_PUSH_CONST(GEO, geo)
-  node->data_type = GRN_DB_TOKYO_GEO_POINT;
-  return rc;
-}
-
-grn_rc
-grn_ts_expr_push_wgs84_geo(grn_ctx *ctx, grn_ts_expr *expr, grn_ts_geo value) {
-  GRN_TS_EXPR_PUSH_CONST(GEO, geo)
-  node->data_type = GRN_DB_WGS84_GEO_POINT;
-  return rc;
-}
-
-grn_rc
-grn_ts_expr_push_bool_vector(grn_ctx *ctx, grn_ts_expr *expr,
-                             grn_ts_bool_vector value) {
-  GRN_TS_EXPR_PUSH_CONST(BOOL_VECTOR, bool_vector)
-  return rc;
-}
-
-grn_rc
-grn_ts_expr_push_int_vector(grn_ctx *ctx, grn_ts_expr *expr,
-                            grn_ts_int_vector value) {
-  GRN_TS_EXPR_PUSH_CONST(INT_VECTOR, int_vector)
-  return rc;
-}
-
-grn_rc
-grn_ts_expr_push_float_vector(grn_ctx *ctx, grn_ts_expr *expr,
-                              grn_ts_float_vector value) {
-  GRN_TS_EXPR_PUSH_CONST(FLOAT_VECTOR, float_vector)
-  return rc;
-}
-
-grn_rc
-grn_ts_expr_push_time_vector(grn_ctx *ctx, grn_ts_expr *expr,
-                             grn_ts_time_vector value) {
-  GRN_TS_EXPR_PUSH_CONST(TIME_VECTOR, time_vector)
-  return rc;
-}
-
-grn_rc
-grn_ts_expr_push_text_vector(grn_ctx *ctx, grn_ts_expr *expr,
-                             grn_ts_text_vector value) {
-  GRN_TS_EXPR_PUSH_CONST(TEXT_VECTOR, text_vector)
-  return rc;
-}
-
-grn_rc
-grn_ts_expr_push_geo_vector(grn_ctx *ctx, grn_ts_expr *expr,
-                            grn_ts_geo_vector value) {
-  GRN_TS_EXPR_PUSH_CONST(GEO_VECTOR, geo_vector)
-  return rc;
-}
-
-grn_rc
-grn_ts_expr_push_tokyo_geo_vector(grn_ctx *ctx, grn_ts_expr *expr,
-                                  grn_ts_geo_vector value) {
-  GRN_TS_EXPR_PUSH_CONST(GEO_VECTOR, geo_vector)
-  node->data_type = GRN_DB_TOKYO_GEO_POINT;
-  return rc;
-}
-
-grn_rc
-grn_ts_expr_push_wgs84_geo_vector(grn_ctx *ctx, grn_ts_expr *expr,
-                                  grn_ts_geo_vector value) {
-  GRN_TS_EXPR_PUSH_CONST(GEO_VECTOR, geo_vector)
-  node->data_type = GRN_DB_TOKYO_GEO_POINT;
-  return rc;
-}
-#undef GRN_TS_EXPR_PUSH_CONST
-
-/* grn_ts_expr_reserve_bridges() extends a bridge buffer for a new bridge. */
-static grn_rc
-grn_ts_expr_reserve_bridges(grn_ctx *ctx, grn_ts_expr *expr) {
-  size_t n_bytes, new_max_n_bridges;
-  grn_ts_expr_bridge *new_bridges;
-  if (expr->n_bridges < expr->max_n_bridges) {
-    return GRN_SUCCESS;
-  }
-  new_max_n_bridges = expr->n_bridges * 2;
-  if (!new_max_n_bridges) {
-    new_max_n_bridges = 1;
-  }
-  n_bytes = sizeof(grn_ts_expr_bridge) * new_max_n_bridges;
-  new_bridges = (grn_ts_expr_bridge *)GRN_REALLOC(expr->bridges, n_bytes);
-  if (!new_bridges) {
-    GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_REALLOC failed: %zu",
-                      n_bytes);
-  }
-  expr->bridges = new_bridges;
-  expr->max_n_bridges = new_max_n_bridges;
-  return GRN_SUCCESS;
-}
-
-grn_rc
-grn_ts_expr_begin_subexpr(grn_ctx *ctx, grn_ts_expr *expr) {
-  grn_rc rc;
-  grn_obj *obj;
-  grn_ts_expr_node *node;
-  grn_ts_expr_bridge *bridge;
-  if (!ctx) {
-    return GRN_INVALID_ARGUMENT;
-  }
-  if (!expr || (expr->type != GRN_TS_EXPR_INCOMPLETE) || !expr->stack_depth) {
-    GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument");
-  }
-
-  /* Check whehter or not the latest node refers to a table. */
-  node = expr->stack[expr->stack_depth - 1];
-  if ((node->data_kind & ~GRN_TS_VECTOR_FLAG) != GRN_TS_REF) {
-    GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d",
-                      node->data_kind);
-  }
-  obj = grn_ctx_at(ctx, node->data_type);
-  if (!obj) {
-    GRN_TS_ERR_RETURN(GRN_UNKNOWN_ERROR, "grn_ctx_at failed: %d",
-                      node->data_type);
-  }
-  if (!grn_ts_obj_is_table(ctx, obj)) {
-    grn_obj_unlink(ctx, obj);
-    GRN_TS_ERR_RETURN(GRN_UNKNOWN_ERROR, "not table: %d", node->data_type);
-  }
-
-  /* Creates a bridge to a subexpression. */
-  rc = grn_ts_expr_reserve_bridges(ctx, expr);
-  if (rc != GRN_SUCCESS) {
-    grn_obj_unlink(ctx, obj);
-    return rc;
-  }
-  bridge = &expr->bridges[expr->n_bridges++];
-  grn_ts_expr_bridge_init(ctx, bridge);
-  bridge->src_table = expr->curr_table;
-  bridge->dest_table = obj;
-  bridge->stack_depth = expr->stack_depth;
-  expr->curr_table = bridge->dest_table;
-  return GRN_SUCCESS;
-}
-
-grn_rc
-grn_ts_expr_end_subexpr(grn_ctx *ctx, grn_ts_expr *expr) {
-  grn_rc rc;
-  grn_ts_expr_node **args, *node;
-  grn_ts_expr_bridge *bridge;
-  if (!ctx || !expr || (expr->type != GRN_TS_EXPR_INCOMPLETE) ||
-      (expr->stack_depth < 2) || !expr->n_bridges) {
-    return GRN_INVALID_ARGUMENT;
-  }
-  /* Check whehter or not the subexpression is complete.*/
-  bridge = &expr->bridges[expr->n_bridges - 1];
-  if (expr->stack_depth != (bridge->stack_depth + 1)) {
-    return GRN_INVALID_ARGUMENT;
-  }
-  /* Creates a bridge node. */
-  args = &expr->stack[expr->stack_depth - 2];
-  rc = grn_ts_expr_bridge_node_open(ctx, args[0], args[1], &node);
-  if (rc != GRN_SUCCESS) {
-    return rc;
-  }
-  /* Note: grn_ts_expr_reserve_stack() is not required. */
-  expr->stack_depth -= 2;
-  expr->stack[expr->stack_depth++] = node;
-  expr->curr_table = bridge->src_table;
-  grn_ts_expr_bridge_fin(ctx, bridge);
-  expr->n_bridges--;
-  return GRN_SUCCESS;
-}
-
-grn_rc
-grn_ts_expr_complete(grn_ctx *ctx, grn_ts_expr *expr) {
-  grn_rc rc;
-  grn_ts_expr_node *root;
-  if (!ctx || !expr || (expr->type != GRN_TS_EXPR_INCOMPLETE)) {
-    return GRN_INVALID_ARGUMENT;
-  }
-  if (expr->stack_depth != 1) {
-    return GRN_INVALID_ARGUMENT;
-  }
-  rc = grn_ts_expr_deref(ctx, expr, &expr->stack[0]);
-  if (rc != GRN_SUCCESS) {
-    return rc;
-  }
-  root = expr->stack[0];
-  switch (root->data_kind) {
-    case GRN_TS_REF:
-    case GRN_TS_REF_VECTOR: {
-      return GRN_INVALID_ARGUMENT;
-    }
-    default: {
-      break;
-    }
-  }
-  switch (root->type) {
-    case GRN_TS_EXPR_ID_NODE: {
-      expr->type = GRN_TS_EXPR_ID;
-      break;
-    }
-    case GRN_TS_EXPR_SCORE_NODE: {
-      expr->type = GRN_TS_EXPR_SCORE;
-      break;
-    }
-    case GRN_TS_EXPR_KEY_NODE:
-    case GRN_TS_EXPR_VALUE_NODE: {
-      expr->type = GRN_TS_EXPR_VARIABLE;
-      break;
-    }
-    case GRN_TS_EXPR_CONST_NODE: {
-      expr->type = GRN_TS_EXPR_CONST;
-      break;
-    }
-    case GRN_TS_EXPR_COLUMN_NODE:
-    case GRN_TS_EXPR_OP_NODE:
-    case GRN_TS_EXPR_BRIDGE_NODE: {
-      expr->type = GRN_TS_EXPR_VARIABLE;
-      break;
-    }
-    default: {
-      return GRN_INVALID_ARGUMENT;
-    }
-  }
-  expr->data_type = root->data_type;
-  expr->data_kind = root->data_kind;
-  expr->root = root;
-  return GRN_SUCCESS;
-}
-
-grn_rc
-grn_ts_expr_evaluate_to_buf(grn_ctx *ctx, grn_ts_expr *expr,
-                            const grn_ts_record *in, size_t n_in,
-                            grn_ts_buf *out) {
-  if (!ctx || !expr || (expr->type == GRN_TS_EXPR_INCOMPLETE) ||
-      (expr->type == GRN_TS_EXPR_BROKEN) || (!in && n_in) || !out) {
-    return GRN_INVALID_ARGUMENT;
-  }
-  if (!n_in) {
-    return GRN_SUCCESS;
-  }
-  return grn_ts_expr_node_evaluate_to_buf(ctx, expr->root, in, n_in, out);
-}
-
-grn_rc
-grn_ts_expr_evaluate(grn_ctx *ctx, grn_ts_expr *expr,
-                     const grn_ts_record *in, size_t n_in, void *out) {
-  if (!ctx || !expr || (expr->type == GRN_TS_EXPR_INCOMPLETE) ||
-      (expr->type == GRN_TS_EXPR_BROKEN) || (!in && n_in) || (n_in && !out)) {
-    return GRN_INVALID_ARGUMENT;
-  }
-  if (!n_in) {
-    return GRN_SUCCESS;
-  }
-  return grn_ts_expr_node_evaluate(ctx, expr->root, in, n_in, out);
-}
-
-grn_rc
-grn_ts_expr_filter(grn_ctx *ctx, grn_ts_expr *expr,
-                   grn_ts_record *in, size_t n_in,
-                   grn_ts_record *out, size_t *n_out) {
-  if (!ctx || !expr || (expr->type == GRN_TS_EXPR_INCOMPLETE) ||
-      (expr->type == GRN_TS_EXPR_BROKEN) || (!in && n_in) ||
-      !out || !n_out) {
-    return GRN_INVALID_ARGUMENT;
-  }
-  if (!n_in) {
-    *n_out = 0;
-    return GRN_SUCCESS;
-  }
-  return grn_ts_expr_node_filter(ctx, expr->root, in, n_in, out, n_out);
-}
-
-grn_rc
-grn_ts_expr_adjust(grn_ctx *ctx, grn_ts_expr *expr,
-                   grn_ts_record *io, size_t n_io) {
-  if (!ctx || !expr || (expr->type == GRN_TS_EXPR_INCOMPLETE) ||
-      (expr->type == GRN_TS_EXPR_BROKEN) || (!io && n_io)) {
-    return GRN_INVALID_ARGUMENT;
-  }
-  if (!n_io) {
-    return GRN_SUCCESS;
-  }
-  return grn_ts_expr_node_adjust(ctx, expr->root, io, n_io);
-}

  Added: lib/ts/ts_expr_node.h (+113 -0) 100644
===================================================================
--- /dev/null
+++ lib/ts/ts_expr_node.h    2015-11-12 11:20:53 +0900 (6cbb03e)
@@ -0,0 +1,113 @@
+/* -*- c-basic-offset: 2 -*- */
+/*
+  Copyright(C) 2015 Brazil
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License version 2.1 as published by the Free Software Foundation.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef GRN_TS_EXPR_NODE_H
+#define GRN_TS_EXPR_NODE_H
+
+#include "ts_buf.h"
+#include "ts_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+  GRN_TS_EXPR_ID_NODE,     /* ID (_id). */
+  GRN_TS_EXPR_SCORE_NODE,  /* Score (_score). */
+  GRN_TS_EXPR_KEY_NODE,    /* Key (_key). */
+  GRN_TS_EXPR_VALUE_NODE,  /* Embedded value (_value). */
+  GRN_TS_EXPR_CONST_NODE,  /* Const. */
+  GRN_TS_EXPR_COLUMN_NODE, /* Column. */
+  GRN_TS_EXPR_OP_NODE,     /* Operator. */
+  GRN_TS_EXPR_BRIDGE_NODE  /* Bridge to a subexpression. */
+} grn_ts_expr_node_type;
+
+#define GRN_TS_EXPR_NODE_COMMON_MEMBERS\
+  grn_ts_expr_node_type type; /* Node type. */\
+  grn_ts_data_kind data_kind; /* Abstract data type. */\
+  grn_ts_data_type data_type; /* Detailed data type. */
+
+typedef struct {
+  GRN_TS_EXPR_NODE_COMMON_MEMBERS
+} grn_ts_expr_node;
+
+/* grn_ts_expr_id_node_open() creates a node associated with IDs (_id). */
+grn_rc grn_ts_expr_id_node_open(grn_ctx *ctx, grn_ts_expr_node **node);
+
+/*
+ * grn_ts_expr_score_node_open() creates a node associated with scores
+ * (_score).
+ */
+grn_rc grn_ts_expr_score_node_open(grn_ctx *ctx, grn_ts_expr_node **node);
+
+/* grn_ts_expr_key_node_open() creates a node associated with keys (_key). */
+grn_rc grn_ts_expr_key_node_open(grn_ctx *ctx, grn_obj *table,
+                                 grn_ts_expr_node **node);
+
+/*
+ * grn_ts_expr_value_node_open() creates a node associated with values
+ * (_value).
+ */
+grn_rc grn_ts_expr_value_node_open(grn_ctx *ctx, grn_obj *table,
+                                   grn_ts_expr_node **node);
+
+/* grn_ts_expr_const_node_open() creates a node associated with a const. */
+grn_rc grn_ts_expr_const_node_open(grn_ctx *ctx, grn_ts_data_kind kind,
+                                   const void *value, grn_ts_expr_node **node);
+
+/* grn_ts_expr_column_node_open() creates a node associated with a column. */
+grn_rc grn_ts_expr_column_node_open(grn_ctx *ctx, grn_obj *column,
+                                    grn_ts_expr_node **node);
+
+/* grn_ts_expr_op_node_open() creates a node associated with an operator. */
+grn_rc grn_ts_expr_op_node_open(grn_ctx *ctx, grn_ts_op_type op_type,
+                                grn_ts_expr_node **args, size_t n_args,
+                                grn_ts_expr_node **node);
+
+/* grn_ts_expr_bridge_node_open() creates a node associated with a bridge. */
+grn_rc grn_ts_expr_bridge_node_open(grn_ctx *ctx, grn_ts_expr_node *src,
+                                    grn_ts_expr_node *dest,
+                                    grn_ts_expr_node **node);
+
+/* grn_ts_expr_node_close() destroys a node. */
+void grn_ts_expr_node_close(grn_ctx *ctx, grn_ts_expr_node *node);
+
+/* grn_ts_expr_node_evaluate() evaluates a subtree. */
+grn_rc grn_ts_expr_node_evaluate(grn_ctx *ctx, grn_ts_expr_node *node,
+                                 const grn_ts_record *in, size_t n_in,
+                                 void *out);
+
+/* grn_ts_expr_node_evaluate_to_buf() evaluates a subtree. */
+grn_rc grn_ts_expr_node_evaluate_to_buf(grn_ctx *ctx, grn_ts_expr_node *node,
+                                        const grn_ts_record *in, size_t n_in,
+                                        grn_ts_buf *out);
+
+/* grn_ts_expr_node_filter() filters records. */
+grn_rc grn_ts_expr_node_filter(grn_ctx *ctx, grn_ts_expr_node *node,
+                               grn_ts_record *in, size_t n_in,
+                               grn_ts_record *out, size_t *n_out);
+
+/* grn_ts_expr_node_adjust() updates scores. */
+grn_rc grn_ts_expr_node_adjust(grn_ctx *ctx, grn_ts_expr_node *node,
+                               grn_ts_record *io, size_t n_io);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GRN_TS_EXPR_NODE_H */

  Modified: lib/ts/ts_types.h (+79 -24)
===================================================================
--- lib/ts/ts_types.h    2015-11-12 09:59:27 +0900 (13088b7)
+++ lib/ts/ts_types.h    2015-11-12 11:20:53 +0900 (970afec)
@@ -26,6 +26,44 @@ extern "C" {
 #endif
 
 /*-------------------------------------------------------------
+ * Enumeration types.
+ */
+
+typedef enum {
+  /* Invalid operator. */
+  GRN_TS_OP_NOP,
+
+  /* Unary operators. */
+  GRN_TS_OP_LOGICAL_NOT, /* !X */
+  GRN_TS_OP_BITWISE_NOT, /* ~X */
+  GRN_TS_OP_POSITIVE,    /* +X */
+  GRN_TS_OP_NEGATIVE,    /* -X */
+
+  /* Binary operators. */
+  GRN_TS_OP_LOGICAL_AND,            /* X && Y  */
+  GRN_TS_OP_LOGICAL_OR,             /* X || Y  */
+  GRN_TS_OP_LOGICAL_SUB,            /* X &! Y  */
+  GRN_TS_OP_BITWISE_AND,            /* X & Y   */
+  GRN_TS_OP_BITWISE_OR,             /* X | Y   */
+  GRN_TS_OP_BITWISE_XOR,            /* X ^ Y   */
+  GRN_TS_OP_EQUAL,                  /* X == Y  */
+  GRN_TS_OP_NOT_EQUAL,              /* X != Y  */
+  GRN_TS_OP_LESS,                   /* X < Y   */
+  GRN_TS_OP_LESS_EQUAL,             /* X <= Y  */
+  GRN_TS_OP_GREATER,                /* X > Y   */
+  GRN_TS_OP_GREATER_EQUAL,          /* X >= Y  */
+  GRN_TS_OP_SHIFT_ARITHMETIC_LEFT,  /* X << Y  */
+  GRN_TS_OP_SHIFT_ARITHMETIC_RIGHT, /* X >> Y  */
+  GRN_TS_OP_SHIFT_LOGICAL_LEFT,     /* X <<< Y */
+  GRN_TS_OP_SHIFT_LOGICAL_RIGHT,    /* X >>> Y */
+  GRN_TS_OP_PLUS,                   /* X + Y   */
+  GRN_TS_OP_MINUS,                  /* X - Y   */
+  GRN_TS_OP_MULTIPLICATION,         /* X * Y   */
+  GRN_TS_OP_DIVISION,               /* X / Y   */
+  GRN_TS_OP_MODULUS                 /* X % Y   */
+} grn_ts_op_type;
+
+/*-------------------------------------------------------------
  * Built-in data types.
  */
 
@@ -45,30 +83,6 @@ typedef struct {
 } grn_ts_record;
 
 /*-------------------------------------------------------------
- * Built-in data kinds.
- */
-
-enum { GRN_TS_VECTOR_FLAG = 1 << 7 };
-
-typedef enum {
-  GRN_TS_VOID         = 0, /* GRN_DB_VOID */
-  GRN_TS_BOOL         = 1, /* GRN_DB_BOOL */
-  GRN_TS_INT          = 2, /* GRN_DB_[U]INT(8/16/32/64) */
-  GRN_TS_FLOAT        = 3, /* GRN_DB_FLOAT */
-  GRN_TS_TIME         = 4, /* GRN_DB_TIME */
-  GRN_TS_TEXT         = 5, /* GRN_DB_[SHORT_/LONG_]TEST */
-  GRN_TS_GEO          = 6, /* GRN_DB_(TOKYO/WGS84)_GEO_POINT */
-  GRN_TS_REF          = 7, /* Table reference. */
-  GRN_TS_BOOL_VECTOR  = GRN_TS_VECTOR_FLAG | GRN_TS_BOOL,
-  GRN_TS_INT_VECTOR   = GRN_TS_VECTOR_FLAG | GRN_TS_INT,
-  GRN_TS_FLOAT_VECTOR = GRN_TS_VECTOR_FLAG | GRN_TS_FLOAT,
-  GRN_TS_TIME_VECTOR  = GRN_TS_VECTOR_FLAG | GRN_TS_TIME,
-  GRN_TS_TEXT_VECTOR  = GRN_TS_VECTOR_FLAG | GRN_TS_TEXT,
-  GRN_TS_GEO_VECTOR   = GRN_TS_VECTOR_FLAG | GRN_TS_GEO,
-  GRN_TS_REF_VECTOR   = GRN_TS_VECTOR_FLAG | GRN_TS_REF
-} grn_ts_data_kind;
-
-/*-------------------------------------------------------------
  * Built-in scalar data kinds.
  */
 
@@ -146,6 +160,47 @@ typedef struct {
   size_t size;
 } grn_ts_ref_vector;
 
+/*-------------------------------------------------------------
+ * Built-in data kinds.
+ */
+
+enum { GRN_TS_VECTOR_FLAG = 1 << 7 };
+
+typedef enum {
+  GRN_TS_VOID         = 0, /* GRN_DB_VOID */
+  GRN_TS_BOOL         = 1, /* GRN_DB_BOOL */
+  GRN_TS_INT          = 2, /* GRN_DB_[U]INT(8/16/32/64) */
+  GRN_TS_FLOAT        = 3, /* GRN_DB_FLOAT */
+  GRN_TS_TIME         = 4, /* GRN_DB_TIME */
+  GRN_TS_TEXT         = 5, /* GRN_DB_[SHORT_/LONG_]TEST */
+  GRN_TS_GEO          = 6, /* GRN_DB_(TOKYO/WGS84)_GEO_POINT */
+  GRN_TS_REF          = 7, /* Table reference. */
+  GRN_TS_BOOL_VECTOR  = GRN_TS_VECTOR_FLAG | GRN_TS_BOOL,
+  GRN_TS_INT_VECTOR   = GRN_TS_VECTOR_FLAG | GRN_TS_INT,
+  GRN_TS_FLOAT_VECTOR = GRN_TS_VECTOR_FLAG | GRN_TS_FLOAT,
+  GRN_TS_TIME_VECTOR  = GRN_TS_VECTOR_FLAG | GRN_TS_TIME,
+  GRN_TS_TEXT_VECTOR  = GRN_TS_VECTOR_FLAG | GRN_TS_TEXT,
+  GRN_TS_GEO_VECTOR   = GRN_TS_VECTOR_FLAG | GRN_TS_GEO,
+  GRN_TS_REF_VECTOR   = GRN_TS_VECTOR_FLAG | GRN_TS_REF
+} grn_ts_data_kind;
+
+typedef union {
+  grn_ts_bool as_bool;
+  grn_ts_int as_int;
+  grn_ts_float as_float;
+  grn_ts_time as_time;
+  grn_ts_text as_text;
+  grn_ts_geo as_geo;
+  grn_ts_ref as_ref;
+  grn_ts_bool_vector as_bool_vector;
+  grn_ts_int_vector as_int_vector;
+  grn_ts_float_vector as_float_vector;
+  grn_ts_time_vector as_time_vector;
+  grn_ts_text_vector as_text_vector;
+  grn_ts_geo_vector as_geo_vector;
+  grn_ts_ref_vector as_ref_vector;
+} grn_ts_any;
+
 #ifdef __cplusplus
 }
 #endif




More information about the Groonga-commit mailing list
Zurück zum Archiv-Index