[Groonga-commit] groonga/groonga [master] remove deprecated grn_query. fixes #1247

Back to archive index

null+****@clear***** null+****@clear*****
2012年 2月 3日 (金) 21:20:23 JST


Kouhei Sutou	2012-01-17 12:10:35 +0900 (Tue, 17 Jan 2012)

  New Revision: 7ed55f166628764e3087745c8ccf0c4cd15b9f26

  Log:
    remove deprecated grn_query. fixes #1247

  Added files:
    lib/ctx_impl.h
  Removed files:
    lib/ql.c
    lib/ql.h
    lib/query.c
    lib/scm.c
    test/unit/core/test-query.c
  Modified files:
    include/groonga.h
    lib/Makefile.am
    lib/com.c
    lib/ctx.c
    lib/db.c
    lib/expr.c
    lib/ii.c
    lib/ii.h
    lib/io.c
    lib/output.c
    lib/output.h
    lib/plugin.c
    lib/proc.c
    lib/store.c
    lib/token.c
    src/grnslap.c
    src/groonga.c
    test/unit/core/Makefile.am
    test/unit/core/test-inverted-index.c

  Modified: include/groonga.h (+0 -16)
===================================================================
--- include/groonga.h    2012-02-03 11:43:41 +0900 (101af22)
+++ include/groonga.h    2012-01-17 12:10:35 +0900 (8a078c2)
@@ -1965,31 +1965,15 @@ GRN_API grn_posting *grn_geo_cursor_next(grn_ctx *ctx, grn_obj *cursor);
 #endif /* GRN_QUERY_COLUMN */
 
 typedef struct _grn_snip grn_snip;
-typedef struct _grn_query grn_query;
 typedef struct _grn_snip_mapping grn_snip_mapping;
 
 struct _grn_snip_mapping {
   void *dummy;
 };
 
-GRN_API grn_query *grn_query_open(grn_ctx *ctx, const char *str, unsigned int str_len,
-                                  grn_operator default_op, int max_exprs);
-GRN_API unsigned int grn_query_rest(grn_ctx *ctx, grn_query *q, const char ** const rest);
-GRN_API grn_rc grn_query_close(grn_ctx *ctx, grn_query *q);
-
-GRN_API grn_rc grn_query_scan(grn_ctx *ctx, grn_query *q, const char **strs, unsigned int *str_lens,
-                              unsigned int nstrs, int flags, int *found, int *score);
-GRN_API grn_snip *grn_query_snip(grn_ctx *ctx, grn_query *query, int flags,
-                                 unsigned int width, unsigned int max_results,
-                                 unsigned int n_tags,
-                                 const char **opentags, unsigned int *opentag_lens,
-                                 const char **closetags, unsigned int *closetag_lens,
-                                 grn_snip_mapping *mapping);
-
 #define GRN_SNIP_NORMALIZE             (0x01<<0)
 #define GRN_SNIP_COPY_TAG              (0x01<<1)
 #define GRN_SNIP_SKIP_LEADING_SPACES   (0x01<<2)
-#define GRN_QUERY_SCAN_NORMALIZE       GRN_SNIP_NORMALIZE
 
 GRN_API grn_snip *grn_snip_open(grn_ctx *ctx, int flags, unsigned int width,
                                 unsigned int max_results,

  Modified: lib/Makefile.am (+2 -5)
===================================================================
--- lib/Makefile.am    2012-02-03 11:43:41 +0900 (a453309)
+++ lib/Makefile.am    2012-01-17 12:10:35 +0900 (07f0b84)
@@ -12,11 +12,8 @@ libgroonga_la_SOURCES =				\
 	str.c					\
 	nfkc.c					\
 	snip.c					\
-	query.c					\
 	store.c					\
 	com.c					\
-	ql.c					\
-	scm.c					\
 	ctx.c					\
 	hash.c					\
 	db.c					\
@@ -39,9 +36,10 @@ libgroonga_la_LDFLAGS =				\
 libgroonga_la_LIBADD =				\
 	dat/libgrndat.la
 
-noinst_HEADERS = 				\
+noinst_HEADERS =				\
 	com.h					\
 	ctx.h					\
+	ctx_impl.h				\
 	dat.h					\
 	db.h					\
 	geo.h					\
@@ -54,7 +52,6 @@ noinst_HEADERS = 				\
 	pat.h					\
 	plugin_in.h				\
 	proc.h					\
-	ql.h					\
 	snip.h					\
 	store.h					\
 	str.h					\

  Modified: lib/com.c (+2 -2)
===================================================================
--- lib/com.c    2012-02-03 11:43:41 +0900 (5fc9f48)
+++ lib/com.c    2012-01-17 12:10:35 +0900 (da028ec)
@@ -1,5 +1,5 @@
 /* -*- c-basic-offset: 2 -*- */
-/* Copyright(C) 2009-2011 Brazil
+/* Copyright(C) 2009-2012 Brazil
 
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
@@ -19,7 +19,7 @@
 
 #include <stdio.h>
 #include <string.h>
-#include "ql.h"
+#include "ctx_impl.h"
 
 #ifdef WIN32
 #  include <ws2tcpip.h>

  Modified: lib/ctx.c (+19 -202)
===================================================================
--- lib/ctx.c    2012-02-03 11:43:41 +0900 (6cbf03d)
+++ lib/ctx.c    2012-01-17 12:10:35 +0900 (69d9a0e)
@@ -19,7 +19,7 @@
 #include "groonga_in.h"
 #include <string.h>
 #include "token.h"
-#include "ql.h"
+#include "ctx_impl.h"
 #include "pat.h"
 #include "plugin_in.h"
 #include "snip.h"
@@ -420,12 +420,20 @@ grn_ctx_impl_init(grn_ctx *ctx)
   ctx->impl->encoding = ctx->encoding;
   ctx->impl->lifoseg = -1;
   ctx->impl->currseg = -1;
-  if (!(ctx->impl->values = grn_array_create(ctx, NULL, sizeof(grn_tmp_db_obj),
+  if (!(ctx->impl->values = grn_array_create(ctx, NULL, sizeof(grn_db_obj *),
                                              GRN_ARRAY_TINY))) {
     grn_io_anon_unmap(ctx, &mi, IMPL_SIZE);
     ctx->impl = NULL;
     return;
   }
+  if (!(ctx->impl->ios = grn_hash_create(ctx, NULL, GRN_TABLE_MAX_KEY_SIZE,
+                                         sizeof(grn_io *),
+                                         GRN_OBJ_KEY_VAR_SIZE|GRN_HASH_TINY))) {
+    grn_array_close(ctx, ctx->impl->values);
+    grn_io_anon_unmap(ctx, &mi, IMPL_SIZE);
+    ctx->impl = NULL;
+    return;
+  }
   CRITICAL_SECTION_INIT(ctx->impl->lock);
   ctx->impl->db = NULL;
 
@@ -454,29 +462,12 @@ grn_ctx_impl_init(grn_ctx *ctx)
 
   ctx->impl->finalizer = NULL;
 
-  ctx->impl->phs = NIL;
-  ctx->impl->code = NIL;
-  ctx->impl->dump = NIL;
   ctx->impl->op = GRN_OP_T0LVL;
-  ctx->impl->args = NIL;
-  ctx->impl->envir = NIL;
-  ctx->impl->value = NIL;
-  ctx->impl->ncells = 0;
   ctx->impl->n_entries = 0;
-  ctx->impl->seqno = 0;
-  ctx->impl->lseqno = 0;
-  ctx->impl->nbinds = 0;
-  ctx->impl->nunbinds = 0;
-  ctx->impl->feed_mode = grn_ql_atonce;
   ctx->impl->cur = NULL;
   ctx->impl->str_end = NULL;
   ctx->impl->batchmode = 0;
-  ctx->impl->gc_verbose = 0;
   ctx->impl->inbuf = NULL;
-  ctx->impl->co.mode = 0;
-  ctx->impl->co.func = NULL;
-  ctx->impl->objects = NULL;
-  ctx->impl->symbols = NULL;
   ctx->impl->com = NULL;
   ctx->impl->outbuf = grn_obj_open(ctx, GRN_BULK, 0, 0);
   ctx->impl->output = NULL /* grn_ctx_concat_func */;
@@ -508,37 +499,6 @@ grn_ctx_impl_err(grn_ctx *ctx)
   }
 }
 
-static void
-grn_ctx_ql_init(grn_ctx *ctx, int flags)
-{
-  if (!ctx->impl) {
-    grn_ctx_impl_init(ctx);
-    if (ERRP(ctx, GRN_ERROR)) { return; }
-  }
-  if (flags & GRN_CTX_BATCH_MODE) { ctx->impl->batchmode = 1; }
-  if ((ctx->impl->objects = grn_array_create(ctx, NULL, sizeof(grn_cell),
-                                             GRN_ARRAY_TINY))) {
-    if ((ctx->impl->symbols = grn_hash_create(ctx, NULL, GRN_TABLE_MAX_KEY_SIZE,
-                                              sizeof(grn_cell),
-                                              GRN_OBJ_KEY_VAR_SIZE|GRN_HASH_TINY))) {
-      if (!ERRP(ctx, GRN_ERROR)) {
-        grn_ql_init_globals(ctx);
-        if (!ERRP(ctx, GRN_ERROR)) {
-          return;
-        }
-      }
-      grn_hash_close(ctx, ctx->impl->symbols);
-      ctx->impl->symbols = NULL;
-    } else {
-      MERR("ctx->impl->symbols init failed");
-    }
-    grn_array_close(ctx, ctx->impl->objects);
-    ctx->impl->objects = NULL;
-  } else {
-    MERR("ctx->impl->objects init failed");
-  }
-}
-
 grn_rc
 grn_ctx_init(grn_ctx *ctx, int flags)
 {
@@ -549,15 +509,14 @@ grn_ctx_init(grn_ctx *ctx, int flags)
   if (getenv("GRN_CTX_PER_DB") && strcmp(getenv("GRN_CTX_PER_DB"), "yes") == 0) {
     ctx->flags |= GRN_CTX_PER_DB;
   }
-  ctx->stat = GRN_QL_WAIT_EXPR;
+  if (ERRP(ctx, GRN_ERROR)) { return ctx->rc; }
+  ctx->stat = GRN_CTX_INITED;
   ctx->encoding = grn_gctx.encoding;
-  ctx->seqno = 0;
-  ctx->seqno2 = 0;
-  ctx->subno = 0;
   ctx->impl = NULL;
   if (flags & GRN_CTX_USE_QL) {
-    grn_ctx_ql_init(ctx, flags);
+    grn_ctx_impl_init(ctx);
     if (ERRP(ctx, GRN_ERROR)) { return ctx->rc; }
+    if (flags & GRN_CTX_BATCH_MODE) { ctx->impl->batchmode = 1; }
   }
   ctx->user_data.ptr = NULL;
   CRITICAL_SECTION_ENTER(grn_glock);
@@ -606,25 +565,18 @@ grn_ctx_fin(grn_ctx *ctx)
       ctx->impl->finalizer(ctx, 0, NULL, &(ctx->user_data));
     }
     grn_ctx_loader_clear(ctx);
-    if (ctx->impl->objects) {
-      grn_cell *o;
-      GRN_ARRAY_EACH(ctx, ctx->impl->objects, 0, 0, id, &o, {
-        grn_cell_clear(ctx, o);
-      });
-      grn_array_close(ctx, ctx->impl->objects);
-    }
     if (ctx->impl->parser) {
       grn_expr_parser_close(ctx);
     }
     if (ctx->impl->values) {
-      grn_tmp_db_obj *o;
+      grn_db_obj *o;
       GRN_ARRAY_EACH(ctx, ctx->impl->values, 0, 0, id, &o, {
-        grn_obj_close(ctx, (grn_obj *)o->obj);
+        grn_obj_close(ctx, *((grn_obj **)o));
       });
       grn_array_close(ctx, ctx->impl->values);
     }
-    if (ctx->impl->symbols) {
-      grn_hash_close(ctx, ctx->impl->symbols);
+    if (ctx->impl->ios) {
+      grn_hash_close(ctx, ctx->impl->ios);
     }
     if (ctx->impl->com) {
       if (ctx->stat != GRN_CTX_QUIT) {
@@ -795,7 +747,6 @@ grn_init(void)
   CRITICAL_SECTION_INIT(grn_glock);
   CRITICAL_SECTION_INIT(grn_logger_lock);
   grn_gtick = 0;
-  grn_ql_init_const();
   ctx->next = ctx;
   ctx->prev = ctx;
   grn_ctx_init(ctx, 0);
@@ -862,11 +813,7 @@ grn_init(void)
     GRN_LOG(ctx, GRN_LOG_ALERT, "grn_com_init failed (%d)", rc);
     return rc;
   }
-  grn_ctx_ql_init(ctx, 0);
-  if ((rc = ctx->rc)) {
-    GRN_LOG(ctx, GRN_LOG_ALERT, "gctx initialize failed (%d)", rc);
-    return rc;
-  }
+  grn_ctx_impl_init(ctx);
   if ((rc = grn_io_init())) {
     GRN_LOG(ctx, GRN_LOG_ALERT, "io initialize failed (%d)", rc);
     return rc;
@@ -1527,45 +1474,6 @@ grn_ctx_info_get(grn_ctx *ctx, grn_ctx_info *info)
 }
 
 
-grn_cell *
-grn_get(const char *key)
-{
-  grn_cell *obj;
-  if (!grn_gctx.impl || !grn_gctx.impl->symbols ||
-      !grn_hash_add(&grn_gctx, grn_gctx.impl->symbols, key, strlen(key),
-                    (void **) &obj, NULL)) {
-    GRN_LOG(&grn_gctx, GRN_LOG_WARNING, "grn_get(%s) failed", key);
-    return F;
-  }
-  if (!obj->header.impl_flags) {
-    obj->header.impl_flags |= GRN_CELL_SYMBOL;
-    obj->header.type = GRN_VOID;
-  }
-  return obj;
-}
-
-grn_cell *
-grn_at(const char *key)
-{
-  grn_cell *obj;
-  if (!grn_gctx.impl || grn_gctx.impl->symbols ||
-      !grn_hash_get(&grn_gctx, grn_gctx.impl->symbols,
-                   key, strlen(key), (void **) &obj)) {
-    return F;
-  }
-  return obj;
-}
-
-grn_rc
-grn_del(const char *key)
-{
-  if (!grn_gctx.impl || !grn_gctx.impl->symbols) {
-    GRN_LOG(&grn_gctx, GRN_LOG_WARNING, "grn_del(%s) failed", key);
-    return GRN_INVALID_ARGUMENT;
-  }
-  return grn_hash_delete(&grn_gctx, grn_gctx.impl->symbols, key, strlen(key), NULL);
-}
-
 typedef struct _grn_cache_entry grn_cache_entry;
 
 typedef struct {
@@ -2323,97 +2231,6 @@ grn_strdup_fail(grn_ctx *ctx, const char *s, const char* file, int line, const c
 }
 #endif /* USE_FAIL_MALLOC */
 
-grn_cell *
-grn_cell_new(grn_ctx *ctx)
-{
-  grn_cell *o = NULL;
-  if (ctx && ctx->impl) {
-    grn_array_add(ctx, ctx->impl->objects, (void **)&o);
-    if (o) {
-      o->header.impl_flags = 0;
-      ctx->impl->n_entries++;
-    }
-  }
-  return o;
-}
-
-grn_cell *
-grn_cell_cons(grn_ctx *ctx, grn_cell *a, grn_cell *b)
-{
-  if (!ctx) { return NULL; }
-  {
-    grn_cell *o;
-    GRN_CELL_NEW(ctx, o);
-    if (o) {
-      o->header.type = GRN_CELL_LIST;
-      o->header.impl_flags = 0;
-      o->u.l.car = a;
-      o->u.l.cdr = b;
-    }
-    return o;
-  }
-}
-
-grn_cell *
-grn_cell_alloc(grn_ctx *ctx, uint32_t size)
-{
-  if (!ctx) { return NULL; }
-  {
-    void *value = GRN_MALLOC(size + 1);
-    if (value) {
-      grn_cell *o = grn_cell_new(ctx);
-      if (!ERRP(ctx, GRN_ERROR)) {
-        o->header.impl_flags = GRN_OBJ_ALLOCATED;
-        o->header.type = GRN_CELL_STR;
-        o->u.b.size = size;
-        o->u.b.value = value;
-        return o;
-      }
-      GRN_FREE(value);
-    } else {
-      MERR("malloc(%d) failed", size + 1);
-    }
-    return NULL;
-  }
-}
-
-void
-grn_cell_clear(grn_ctx *ctx, grn_cell *o)
-{
-  if (!ctx || !ctx->impl) { return; }
-  if (o->header.impl_flags & GRN_OBJ_ALLOCATED) {
-    switch (o->header.type) {
-    case GRN_SNIP :
-      if (o->u.p.value) { grn_snip_close(ctx, (grn_snip *)o->u.p.value); }
-      break;
-    case GRN_TABLE_HASH_KEY :
-    case GRN_TABLE_PAT_KEY :
-    case GRN_TABLE_NO_KEY :
-      grn_obj_close(ctx, grn_ctx_at(ctx, o->u.o.id));
-      break;
-    case GRN_CELL_STR :
-      if (o->u.b.value) {
-        GRN_FREE(o->u.b.value);
-      }
-      break;
-    case GRN_QUERY :
-      if (o->u.p.value) { grn_query_close(ctx, (grn_query *)o->u.p.value); }
-      break;
-    case GRN_UVECTOR :
-    case GRN_VECTOR :
-      if (o->u.p.value) { grn_obj_close(ctx, o->u.p.value); }
-      break;
-    case GRN_PATSNIP :
-      grn_obj_patsnip_spec_close(ctx, (patsnip_spec *)o->u.p.value);
-      break;
-    default :
-      GRN_LOG(ctx, GRN_LOG_WARNING, "obj_clear: invalid type(%x)", o->header.type);
-      break;
-    }
-    o->header.impl_flags &= ~GRN_OBJ_ALLOCATED;
-  }
-}
-
 /* don't handle error inside logger functions */
 
 void

  Added: lib/ctx_impl.h (+177 -0) 100644
===================================================================
--- /dev/null
+++ lib/ctx_impl.h    2012-01-17 12:10:35 +0900 (49ae27a)
@@ -0,0 +1,177 @@
+/* -*- c-basic-offset: 2 -*- */
+/*
+  Copyright(C) 2009-2012 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#ifndef GRN_CTX_IMPL_H
+#define GRN_CTX_IMPL_H
+
+#ifndef GRN_CTX_H
+#include "ctx.h"
+#endif /* GRN_CTX_H */
+
+#ifndef GRN_COM_H
+#include "com.h"
+#endif /* GRN_COM_H */
+
+#ifdef HAVE_MESSAGE_PACK
+#include <msgpack.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**** grn_expr ****/
+
+#define GRN_EXPR_MISSING_NAME          "expr_missing"
+
+/**** grn_ctx_impl ****/
+
+#define GRN_CTX_INITED    0x00
+#define GRN_CTX_QUITTING  0x0f
+
+typedef enum {
+  GRN_LOADER_BEGIN = 0,
+  GRN_LOADER_TOKEN,
+  GRN_LOADER_STRING,
+  GRN_LOADER_SYMBOL,
+  GRN_LOADER_NUMBER,
+  GRN_LOADER_STRING_ESC,
+  GRN_LOADER_UNICODE0,
+  GRN_LOADER_UNICODE1,
+  GRN_LOADER_UNICODE2,
+  GRN_LOADER_UNICODE3,
+  GRN_LOADER_END
+} grn_loader_stat;
+
+typedef struct {
+  grn_obj values;
+  grn_obj level;
+  grn_obj columns;
+  int32_t key_offset;
+  grn_obj *table;
+  grn_obj *last;
+  grn_obj *ifexists;
+  grn_obj *each;
+  uint32_t unichar;
+  uint32_t values_size;
+  uint32_t nrecords;
+  grn_loader_stat stat;
+  grn_content_type input_type;
+} grn_loader;
+
+#define GRN_STACK_SIZE 1024
+#define GRN_CTX_N_SEGMENTS 512
+
+#ifdef ENABLE_MEMORY_DEBUG
+typedef struct _grn_alloc_info grn_alloc_info;
+struct _grn_alloc_info
+{
+  void *address;
+  int freed;
+  char alloc_backtrace[4096];
+  char free_backtrace[4096];
+  grn_alloc_info *next;
+};
+#endif
+
+struct _grn_ctx_impl {
+  grn_encoding encoding;
+
+  /* memory pool portion */
+  int32_t lifoseg;
+  int32_t currseg;
+  grn_critical_section lock;
+  grn_io_mapinfo segs[GRN_CTX_N_SEGMENTS];
+
+#ifdef USE_DYNAMIC_MALLOC_CHANGE
+  /* memory allocation portion */
+  grn_malloc_func malloc_func;
+  grn_calloc_func calloc_func;
+  grn_realloc_func realloc_func;
+  grn_strdup_func strdup_func;
+#endif
+
+#ifdef ENABLE_MEMORY_DEBUG
+  /* memory debug portion */
+  grn_alloc_info *alloc_info;
+#endif
+
+  /* qe portion */
+  grn_obj *stack[GRN_STACK_SIZE];
+  uint32_t stack_curr;
+  grn_hash *expr_vars;
+  grn_obj *curr_expr;
+  grn_obj *qe_next;
+  void *parser;
+  grn_timeval tv;
+
+  /* loader portion */
+  grn_edge *edge;
+  grn_loader loader;
+
+  /* plugin portion */
+  const char *plugin_path;
+
+  /* output portion */
+  grn_content_type output_type;
+  const char *mime_type;
+  grn_obj names;
+  grn_obj levels;
+
+  /* command portion */
+  grn_command_version command_version;
+
+  /* match escalation portion */
+  int64_t match_escalation_threshold;
+
+  /* lifetime portion */
+  grn_proc_func *finalizer;
+
+  /* ql portion */
+  uint8_t batchmode;
+  uint8_t op;
+  int tok;
+  char *cur;
+  char *str_end;
+  grn_obj *db;
+  uint32_t n_entries;
+  grn_array *values;        /* temporary objects */
+  grn_hash *ios;        /* IOs */
+  char *inbuf;
+  grn_obj *outbuf;
+  grn_obj subbuf;
+  unsigned int bufcur;
+  void (*output)(grn_ctx *, int, void *);
+  grn_com *com;
+  unsigned int com_status;
+  union {
+    void *ptr;
+    int fd;
+    uint32_t u32;
+    uint64_t u64;
+  } data;
+
+#ifdef HAVE_MESSAGE_PACK
+  msgpack_packer msgpacker;
+#endif
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GRN_CTX_IMPL_H */

  Modified: lib/db.c (+9 -14)
===================================================================
--- lib/db.c    2012-02-03 11:43:41 +0900 (d534ca9)
+++ lib/db.c    2012-01-17 12:10:35 +0900 (9b64a10)
@@ -20,7 +20,7 @@
 #include "pat.h"
 #include "dat.h"
 #include "ii.h"
-#include "ql.h"
+#include "ctx_impl.h"
 #include "token.h"
 #include "proc.h"
 #include "plugin_in.h"
@@ -264,9 +264,9 @@ grn_db_close(grn_ctx *ctx, grn_obj *db)
       grn_expr_parser_close(ctx);
     }
     if (ctx->impl->values) {
-      grn_tmp_db_obj *o;
+      grn_db_obj *o;
       GRN_ARRAY_EACH(ctx, ctx->impl->values, 0, 0, id, &o, {
-        grn_obj_close(ctx, (grn_obj *)o->obj);
+        grn_obj_close(ctx, *((grn_obj **)o));
       });
       grn_array_truncate(ctx, ctx->impl->values);
     }
@@ -2813,7 +2813,7 @@ grn_obj_search(grn_ctx *ctx, grn_obj *obj, grn_obj *query,
           }
           break;
         case GRN_QUERY :
-          rc = grn_query_search(ctx, (grn_ii *)obj, (grn_query *)query, (grn_hash *)res, op);
+          rc = GRN_FUNCTION_NOT_IMPLEMENTED;
           break;
         }
       }
@@ -6594,11 +6594,8 @@ grn_db_obj_init(grn_ctx *ctx, grn_obj *db, grn_id id, grn_db_obj *obj)
   if (id) {
     if (id & GRN_OBJ_TMP_OBJECT) {
       if (ctx->impl && ctx->impl->values) {
-        grn_tmp_db_obj tmp_obj;
-        tmp_obj.obj = obj;
-        memset(&tmp_obj.cell, 0, sizeof(grn_cell));
         rc = grn_array_set_value(ctx, ctx->impl->values,
-                                 id & ~GRN_OBJ_TMP_OBJECT, &tmp_obj, GRN_OBJ_SET);
+                                 id & ~GRN_OBJ_TMP_OBJECT, &obj, GRN_OBJ_SET);
       }
     } else {
       db_value *vp;
@@ -6665,9 +6662,10 @@ grn_ctx_at(grn_ctx *ctx, grn_id id)
   GRN_API_ENTER;
   if (id & GRN_OBJ_TMP_OBJECT) {
     if (ctx->impl->values) {
-      grn_tmp_db_obj *tmp_obj;
-      if ((tmp_obj = _grn_array_get_value(ctx, ctx->impl->values, id & ~GRN_OBJ_TMP_OBJECT))) {
-        res = (grn_obj *)tmp_obj->obj;
+      grn_obj **tmp_obj;
+      tmp_obj = _grn_array_get_value(ctx, ctx->impl->values, id & ~GRN_OBJ_TMP_OBJECT);
+      if (tmp_obj) {
+        res = *tmp_obj;
       }
     }
   } else {
@@ -6929,9 +6927,6 @@ grn_obj_close(grn_ctx *ctx, grn_obj *obj)
     case GRN_TABLE_VIEW :
       rc = grn_view_close(ctx, (grn_view *)obj);
       break;
-    case GRN_QUERY :
-      rc = grn_query_close(ctx, (grn_query *)obj);
-      break;
     case GRN_COLUMN_VAR_SIZE :
       rc = grn_ja_close(ctx, (grn_ja *)obj);
       break;

  Modified: lib/expr.c (+1 -1)
===================================================================
--- lib/expr.c    2012-02-03 11:43:41 +0900 (6b7483b)
+++ lib/expr.c    2012-01-17 12:10:35 +0900 (3c79202)
@@ -17,7 +17,7 @@
 */
 #include "groonga_in.h"
 #include "db.h"
-#include "ql.h"
+#include "ctx_impl.h"
 #include <string.h>
 #include <float.h>
 #include "ii.h"

  Modified: lib/ii.c (+1 -2)
===================================================================
--- lib/ii.c    2012-02-03 11:43:41 +0900 (3c9ca17)
+++ lib/ii.c    2012-01-17 12:10:35 +0900 (4494aee)
@@ -21,7 +21,7 @@
 #include <sys/stat.h>
 
 #include "ii.h"
-#include "ql.h"
+#include "ctx_impl.h"
 #include "token.h"
 #include "pat.h"
 #include "db.h"
@@ -3566,7 +3566,6 @@ grn_ii_close(grn_ctx *ctx, grn_ii *ii)
 {
   grn_rc rc;
   if (!ii) { return GRN_INVALID_ARGUMENT; }
-  grn_del(grn_io_path(ii->seg));
   if ((rc = grn_io_close(ctx, ii->seg))) { return rc; }
   if ((rc = grn_io_close(ctx, ii->chunk))) { return rc; }
   GRN_GFREE(ii);

  Modified: lib/ii.h (+0 -5)
===================================================================
--- lib/ii.h    2012-02-03 11:43:41 +0900 (5243446)
+++ lib/ii.h    2012-01-17 12:10:35 +0900 (af289d3)
@@ -180,11 +180,6 @@ GRN_API grn_rc grn_ii_select(grn_ctx *ctx, grn_ii *ii, const char *string, unsig
 grn_rc grn_ii_sel(grn_ctx *ctx, grn_ii *ii, const char *string, unsigned int string_len,
                   grn_hash *s, grn_operator op, grn_search_optarg *optarg);
 
-grn_rc grn_ii_query_select(grn_ctx *ctx, grn_ii *i, grn_query *q, grn_hash *r, grn_operator op);
-
-grn_rc grn_query_search(grn_ctx *ctx, grn_ii *i, grn_query *q,
-                        grn_hash *r, grn_operator op);
-
 void grn_ii_resolve_sel_and(grn_ctx *ctx, grn_hash *s, grn_operator op);
 
 grn_rc grn_ii_at(grn_ctx *ctx, grn_ii *ii, grn_id id, grn_hash *s, grn_operator op);

  Modified: lib/io.c (+19 -8)
===================================================================
--- lib/io.c    2012-02-03 11:43:41 +0900 (84c1009)
+++ lib/io.c    2012-01-17 12:10:35 +0900 (dcb0026)
@@ -1,5 +1,5 @@
 /* -*- c-basic-offset: 2 -*- */
-/* Copyright(C) 2009 Brazil
+/* Copyright(C) 2009-2012 Brazil
 
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
@@ -30,7 +30,7 @@
 #include "io.h"
 #include "plugin_in.h"
 #include "hash.h"
-#include "ql.h"
+#include "ctx_impl.h"
 
 #define GRN_IO_IDSTR "GROONGA:IO:00001"
 
@@ -147,8 +147,13 @@ static void
 grn_io_register(grn_io *io)
 {
   if (io->fis && (io->flags & (GRN_IO_EXPIRE_GTICK|GRN_IO_EXPIRE_SEGMENT))) {
-    grn_cell *obj = grn_get(io->path);
-    if (obj != F) { obj->u.p.value = (grn_obj *)io; }
+    if (grn_gctx.impl && grn_gctx.impl->ios &&
+        grn_hash_add(&grn_gctx, grn_gctx.impl->ios, io->path, strlen(io->path),
+                     (void **)&io, NULL)) {
+    } else {
+      GRN_LOG(&grn_gctx, GRN_LOG_WARNING,
+              "grn_io_register(%s) failed", io->path);
+    }
   }
 }
 
@@ -156,7 +161,13 @@ static void
 grn_io_unregister(grn_io *io)
 {
   if (io->fis && (io->flags & (GRN_IO_EXPIRE_GTICK|GRN_IO_EXPIRE_SEGMENT))) {
-    grn_del(io->path);
+    if (grn_gctx.impl && grn_gctx.impl->ios) {
+      grn_hash_delete(&grn_gctx, grn_gctx.impl->ios,
+                      io->path, strlen(io->path), NULL);
+    } else {
+      GRN_LOG(&grn_gctx, GRN_LOG_WARNING,
+              "grn_io_unregister(%s) failed", io->path);
+    }
   }
 }
 
@@ -1388,10 +1399,10 @@ static uint32_t
 grn_expire_(grn_ctx *ctx, int count_thresh, uint32_t limit)
 {
   uint32_t n = 0;
-  grn_cell *obj;
-  GRN_HASH_EACH(ctx, grn_gctx.impl->symbols, id, NULL, NULL, (void **) &obj, {
+  grn_io *io;
+  GRN_HASH_EACH(ctx, grn_gctx.impl->ios, id, NULL, NULL, (void **)&io, {
     grn_plugin_close(ctx, id);
-    n += grn_io_expire(ctx, (grn_io *) obj->u.p.value, count_thresh, limit);
+    n += grn_io_expire(ctx, io, count_thresh, limit);
     if (n >= limit) { break; }
   });
   return n;

  Modified: lib/output.c (+1 -2)
===================================================================
--- lib/output.c    2012-02-03 11:43:41 +0900 (5c5387f)
+++ lib/output.c    2012-01-17 12:10:35 +0900 (35a67c6)
@@ -1,5 +1,5 @@
 /* -*- c-basic-offset: 2 -*- */
-/* Copyright(C) 2009-2010 Brazil
+/* Copyright(C) 2009-2012 Brazil
 
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
@@ -21,7 +21,6 @@
 
 #include <string.h>
 #include "str.h"
-#include "ql.h"
 #include "db.h"
 #include "output.h"
 

  Modified: lib/output.h (+4 -4)
===================================================================
--- lib/output.h    2012-02-03 11:43:41 +0900 (36c5aa7)
+++ lib/output.h    2012-01-17 12:10:35 +0900 (fe91863)
@@ -1,5 +1,5 @@
 /* -*- c-basic-offset: 2 -*- */
-/* Copyright(C) 2010 Brazil
+/* Copyright(C) 2010-2012 Brazil
 
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
@@ -29,9 +29,9 @@
 #include "store.h"
 #endif /* GRN_STORE_H */
 
-#ifndef GRN_QL_H
-#include "ql.h"
-#endif /* GRN_QL_H */
+#ifndef GRN_CTX_IMPL_H
+#include "ctx_impl.h"
+#endif /* GRN_CTX_IMPL_H */
 
 #ifdef __cplusplus
 extern "C" {

  Modified: lib/plugin.c (+2 -2)
===================================================================
--- lib/plugin.c    2012-02-03 11:43:41 +0900 (48e172f)
+++ lib/plugin.c    2012-01-17 12:10:35 +0900 (2c03f93)
@@ -1,5 +1,5 @@
 /* -*- c-basic-offset: 2 -*- */
-/* Copyright(C) 2009-2011 Brazil
+/* Copyright(C) 2009-2012 Brazil
 
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
@@ -17,7 +17,7 @@
 
 #include "db.h"
 #include "plugin_in.h"
-#include "ql.h"
+#include "ctx_impl.h"
 #include "util.h"
 
 #include <stdio.h>

  Modified: lib/proc.c (+0 -1)
===================================================================
--- lib/proc.c    2012-02-03 11:43:41 +0900 (b896eb9)
+++ lib/proc.c    2012-01-17 12:10:35 +0900 (613f1f8)
@@ -17,7 +17,6 @@
 */
 
 #include "proc.h"
-#include "ql.h"
 #include "ii.h"
 #include "db.h"
 #include "util.h"

  Deleted: lib/ql.c (+0 -2763) 100644
===================================================================
--- lib/ql.c    2012-02-03 11:43:41 +0900 (33e9fc3)
+++ /dev/null
@@ -1,2763 +0,0 @@
-/* -*- c-basic-offset: 2 -*- */
-/* Copyright(C) 2009-2012 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
-*/
-
-#include "groonga_in.h"
-#include <string.h>
-#include "ql.h"
-#include "db.h"
-#include "pat.h"
-#include "snip.h"
-
-#define DB_OBJ(obj) ((grn_db_obj *)obj)
-#define RVALUE(obj) (grn_ctx_at(ctx, (obj)->u.o.id))
-#define INTERN2(s,l) (grn_ql_mk_symbol(ctx, s, l))
-
-static grn_cell *ha_object(grn_ctx *ctx, grn_cell *args, grn_ql_co *co);
-static grn_cell *ha_snip(grn_ctx *ctx, grn_cell *args, grn_ql_co *co);
-static grn_cell *ha_sections(grn_ctx *ctx, grn_cell *args, grn_ql_co *co);
-
-#define STRBUF_SIZE (GRN_TABLE_MAX_KEY_SIZE + 1)
-
-static grn_rc
-obj2str(grn_cell *o, char *buf, uint16_t *size)
-{
-  if (SYMBOLP(o)) {
-    const char *r = _grn_hash_strkey_by_val(o, size);
-    if (r && *r == ':') {
-      r++;
-      (*size)--;
-    }
-    memcpy(buf, r, *size);
-    buf[*size] = '\0';
-  } else if (o->header.type == GRN_CELL_STR) {
-    if (STRSIZE(o) > GRN_TABLE_MAX_KEY_SIZE) {
-      memcpy(buf, STRVALUE(o), GRN_TABLE_MAX_KEY_SIZE);
-      buf[GRN_TABLE_MAX_KEY_SIZE] = '\0';
-      *size = GRN_TABLE_MAX_KEY_SIZE + 1;
-    } else {
-      *size = STRSIZE(o);
-      memcpy(buf, STRVALUE(o), *size);
-      buf[*size] = '\0';
-    }
-  } else if (o->header.type == GRN_CELL_INT) {
-    char *rest;
-    grn_lltoa(IVALUE(o), buf, buf + GRN_TABLE_MAX_KEY_SIZE, &rest);
-    *size = rest - buf;
-    *rest = '\0';
-  } else {
-    return GRN_INVALID_ARGUMENT;
-  }
-  return GRN_SUCCESS;
-}
-
-static void
-obj_obj_bind(grn_cell *obj, grn_id domain, grn_id self)
-{
-  obj->header.type = GRN_CELL_OBJECT;
-  obj->header.impl_flags = GRN_CELL_NATIVE;
-  obj->u.o.id = self;
-  obj->header.domain = domain;
-  obj->u.o.func = ha_object;
-}
-
-static grn_cell *
-obj2cell(grn_ctx *ctx, grn_obj *obj, grn_cell *cell)
-{
-  if (GRN_DB_OBJP(obj)) {
-    grn_id id = DB_OBJ(obj)->id;
-    if (id & GRN_OBJ_TMP_OBJECT) {
-      grn_tmp_db_obj *tmp_obj;
-      if ((tmp_obj = _grn_array_get_value(ctx, ctx->impl->values,
-                                          id & ~GRN_OBJ_TMP_OBJECT))) {
-        return &tmp_obj->cell;
-      } else {
-        return F;
-      }
-    } else {
-      char buf[STRBUF_SIZE];
-      int len = grn_obj_name(ctx, obj, buf, STRBUF_SIZE);
-      return INTERN2(buf, len);
-    }
-  }
-  if (!cell) { if (!(cell = grn_cell_new(ctx))) { return F; } }
-  switch (obj->header.type) {
-  case GRN_BULK :
-    {
-      void *v = GRN_BULK_HEAD(obj);
-      grn_id rid = obj->header.domain;
-      grn_obj *range = grn_ctx_at(ctx, rid);
-      if (v) {
-        if (range && range->header.type == GRN_TYPE) {
-          switch (rid) {
-          case GRN_DB_INT32 :
-            SETINT(cell, *((int32_t *)v));
-            break;
-          case GRN_DB_UINT32 :
-            SETINT(cell, *((uint32_t *)v));
-            break;
-          case GRN_DB_INT64 :
-            SETINT(cell, *((int64_t *)v));
-            break;
-          case GRN_DB_FLOAT :
-            SETFLOAT(cell, *((double *)v));
-            break;
-          case GRN_DB_TIME :
-            SETTIME(cell, v);
-            break;
-          default :
-            {
-              uint32_t size = GRN_BULK_VSIZE(obj);
-              void *value = GRN_MALLOC(size);
-              if (!value) { return F; }
-              cell->header.impl_flags |= GRN_OBJ_ALLOCATED;
-              memcpy(value, v, size);
-              SETBULK(cell, value, size);
-            }
-            break;
-          }
-        } else {
-          obj_obj_bind(cell, rid, *((grn_id *)v));
-        }
-      }
-    }
-    break;
-  case GRN_UVECTOR :
-    {
-      grn_obj *sections = grn_obj_graft(ctx, obj);
-      if (sections) {
-        cell->header.type = GRN_UVECTOR;
-        cell->header.impl_flags |= GRN_OBJ_ALLOCATED|GRN_CELL_NATIVE;
-        cell->u.p.value = sections;
-        cell->u.p.func = ha_sections;
-      }
-    }
-    break;
-  case GRN_VECTOR :
-    {
-      grn_obj *sections = grn_obj_graft(ctx, obj);
-      if (sections) {
-        cell->header.type = GRN_VECTOR;
-        cell->header.impl_flags |= GRN_OBJ_ALLOCATED|GRN_CELL_NATIVE;
-        cell->u.p.value = sections;
-        cell->u.p.func = ha_sections;
-      }
-    }
-    break;
-  }
-  return cell;
-}
-
-static int
-keywordp(grn_cell *x)
-{
-  uint16_t name_size;
-  const char *name;
-  return SYMBOLP(x)
-    && (name = _grn_hash_strkey_by_val(x, &name_size))
-    && name_size
-    && *name == ':';
-}
-
-static int
-symbolp(grn_cell *x)
-{
-  uint16_t name_size;
-  const char *name;
-  return SYMBOLP(x)
-    && (name = _grn_hash_strkey_by_val(x, &name_size))
-    && (!name_size || *name != ':');
-}
-
-static int
-descp(grn_cell *x)
-{
-  uint16_t name_size;
-  const char *name;
-  return SYMBOLP(x)
-    && (name = _grn_hash_strkey_by_val(x, &name_size))
-    && (name_size > 1)
-    && (*name == ':')
-    && (name[1] == 'd');
-}
-
-/* column_exp */
-
-typedef struct {
-  grn_cell *expr;
-  grn_table_sort_key *keys;
-  grn_cell **cells;
-  int n_keys;
-  int n_applys;
-} column_exp;
-
-static grn_obj *
-get_accessor(grn_ctx *ctx, grn_obj *table, grn_cell *e)
-{
-  uint16_t msg_size;
-  char msg[STRBUF_SIZE];
-  obj2str(e, msg, &msg_size);
-  return grn_obj_column(ctx, table, msg, msg_size);
-}
-
-#define COLUMN_EXPP(x,ce) ((x) == (ce)->cells[(ce)->n_keys])
-
-static grn_cell *
-column_exp_build_(grn_ctx *ctx, grn_obj *table, grn_cell *e, column_exp *ce, grn_cell *parameter)
-{
-  if (PAIRP(e)) {
-    grn_cell *x, *r, *l = NIL, **d;
-    POP(x, e);
-    if (x == parameter && keywordp(CAR(e))) {
-      if (ce->keys[ce->n_keys].key) { ce->n_keys++; }
-      ce->keys[ce->n_keys].key = get_accessor(ctx, table, CAR(e));
-      d = &ce->cells[ce->n_keys];
-      if (!*d) { *d = grn_cell_new(ctx); }
-      r = *d;
-    } else {
-      r = column_exp_build_(ctx, table, x, ce, parameter);
-      if (COLUMN_EXPP(r, ce) && keywordp(CAR(e))) {
-        get_accessor(ctx, ce->keys[ce->n_keys].key, CAR(e));
-      } else {
-        r = CONS(r, NIL);
-        d = &CDR(r);
-        while (PAIRP(e)) {
-          POP(x, e);
-          if (COLUMN_EXPP(l, ce) && descp(x)) {
-            ce->keys[ce->n_keys].flags |= GRN_TABLE_SORT_DESC;
-          }
-          l = column_exp_build_(ctx, table, x, ce, parameter);
-          *d = CONS(l, NIL);
-          d = &CDR(*d);
-        }
-      }
-    }
-    return r;
-  } else {
-    return e;
-  }
-}
-
-static void
-column_exp_build(grn_ctx *ctx, grn_obj *table, grn_cell *e, column_exp *ce, grn_cell *parameter)
-{
-  grn_cell *x, *r = e, *l = NIL, **d = &r;
-  ce->n_keys = 0;
-  while (PAIRP(e)) {
-    POP(x, e);
-    if (COLUMN_EXPP(l, ce) && descp(x)) {
-      ce->keys[ce->n_keys].flags |= GRN_TABLE_SORT_DESC;
-    }
-    l = column_exp_build_(ctx, table, x, ce, parameter);
-    *d = CONS(l, NIL);
-    d = &CDR(*d);
-  }
-  if (ce->keys[ce->n_keys].key) { ce->n_keys++; }
-  ce->expr = r;
-  grn_ql_obj_mark(ctx, ce->expr);
-}
-
-#define EVAL_BY_FUNCALLP(ce) \
- ((ce)->n_applys == 1 && PAIRP((ce)->expr) && NATIVE_FUNCP(CAR((ce)->expr)))
-
-static void
-column_exp_check(grn_cell *e, int *ns, int *ne, grn_cell *parameter)
-{
-  if (PAIRP(e)) {
-    grn_cell *x;
-    POP(x, e);
-    if (x == parameter) {
-      (*ns)++;
-    } else if (NATIVE_FUNCP(x)) {
-      (*ne)++;
-    } else {
-      column_exp_check(x, ns, ne, parameter);
-    }
-    while (PAIRP(e)) {
-      POP(x, e);
-      column_exp_check(x, ns, ne, parameter);
-    }
-  } else {
-    if (symbolp(e)) { (*ne)++; }
-  }
-}
-
-static column_exp *
-column_exp_open(grn_ctx *ctx, grn_obj *table, grn_cell *expr, grn_cell *parameter)
-{
-  column_exp *ce = GRN_CALLOC(sizeof(column_exp));
-  if (ce) {
-    column_exp_check(expr, &ce->n_keys, &ce->n_applys, parameter);
-    if (ce->n_keys) {
-      if (!(ce->keys = GRN_CALLOC(sizeof(grn_table_sort_key) * ce->n_keys))) {
-        GRN_FREE(ce);
-        return NULL;
-      }
-      if (!(ce->cells = GRN_CALLOC(sizeof(grn_cell *) * ce->n_keys))) {
-        GRN_FREE(ce->keys);
-        GRN_FREE(ce);
-        return NULL;
-      }
-      column_exp_build(ctx, table, expr, ce, parameter);
-    } else {
-      ce->expr = expr;
-    }
-  }
-  return ce;
-}
-
-static grn_rc
-column_exp_exec(grn_ctx *ctx, column_exp *ce, grn_id id)
-{
-  int i;
-  grn_obj v, *vp;
-  GRN_TEXT_INIT(&v, 0);
-  for (i = 0; i < ce->n_keys; i++) {
-    grn_cell *c = ce->cells[i];
-    GRN_BULK_REWIND(&v);
-    vp = grn_obj_get_value(ctx, ce->keys[i].key, id, &v);
-    grn_cell_clear(ctx, c);
-    obj2cell(ctx, vp, c);
-  }
-  grn_obj_close(ctx, &v);
-  return GRN_SUCCESS;
-}
-
-static grn_rc
-column_exp_close(grn_ctx *ctx, column_exp *ce)
-{
-  int i;
-  grn_ql_obj_unmark(ctx, ce->expr);
-  for (i = 0; i < ce->n_keys; i++) {
-    grn_obj_unlink(ctx, ce->keys[i].key);
-  }
-  if (ce->keys) { GRN_FREE(ce->keys); }
-  if (ce->cells) { GRN_FREE(ce->cells); }
-  GRN_FREE(ce);
-  return GRN_SUCCESS;
-}
-
-static grn_cell *
-ha_void(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  if (!ctx->impl->code) { return F; }
-  return ctx->impl->code;
-}
-
-grn_cell *
-grn_ql_obj_new(grn_ctx *ctx, grn_id domain, grn_id self)
-{
-  grn_cell *o;
-  GRN_CELL_NEW(ctx, o);
-  obj_obj_bind(o, domain, self);
-  return o;
-}
-
-static grn_cell *
-get_cell(grn_ctx *ctx, grn_obj *db_obj)
-{
-  if (db_obj) {
-    grn_id id = DB_OBJ(db_obj)->id;
-    if (id & GRN_OBJ_TMP_OBJECT) {
-      grn_tmp_db_obj *tmp_obj;
-      if ((tmp_obj = _grn_array_get_value(ctx, ctx->impl->values,
-                                          id & ~GRN_OBJ_TMP_OBJECT))) {
-        return &tmp_obj->cell;
-      } else {
-        return F;
-      }
-    } else {
-      char buf[STRBUF_SIZE];
-      int len = grn_obj_name(ctx, db_obj, buf, STRBUF_SIZE);
-      return INTERN2(buf, len);
-    }
-  } else {
-    return F;
-  }
-}
-
-static grn_obj *
-get_obj(grn_ctx *ctx, grn_cell *cell)
-{
-  return GRN_DB_OBJP(cell) ? grn_ctx_at(ctx, cell->u.o.id) : NULL;
-}
-
-static grn_obj *
-get_domain(grn_ctx *ctx, grn_cell *cell)
-{
-  return grn_ctx_at(ctx, cell->header.domain);
-}
-
-static void
-unesc(grn_ctx *ctx, grn_cell *obj)
-{
-  char *src, *dest, *end = STRVALUE(obj) + STRSIZE(obj);
-  for (src = dest = STRVALUE(obj);;) {
-    unsigned int len;
-    if (!(len = grn_charlen(ctx, src, end))) { break; }
-    if (src[0] == '\\' && src + 1 < end && len == 1) {
-      src++;
-      switch (*src) {
-      case 'n' :
-        *dest++ = '\n';
-        break;
-      case 'r' :
-        *dest++ = '\r';
-        break;
-      case 't' :
-        *dest++ = '\t';
-        break;
-      default :
-        *dest++ = *src;
-        break;
-      }
-      src++;
-    } else {
-      while (len--) { *dest++ = *src++; }
-    }
-  }
-  STRSIZE(obj) = dest - STRVALUE(obj);
-}
-
-static grn_cell *
-grn_ql_table_add(grn_ctx *ctx, grn_obj *table, const void *key, unsigned int key_size, grn_cell *res)
-{
-  grn_id id = grn_table_add(ctx, table, key, key_size, NULL);
-  if (id) {
-    if (!res) { GRN_CELL_NEW(ctx, res); }
-    obj_obj_bind(res, DB_OBJ(table)->id, id);
-    return res;
-  } else {
-    return F;
-  }
-}
-
-static grn_cell *
-grn_ql_table_get(grn_ctx *ctx, grn_obj *table, const void *key, unsigned int key_size, grn_cell *res)
-{
-  grn_id id = grn_table_get(ctx, table, key, key_size);
-  if (id) {
-    if (!res) { GRN_CELL_NEW(ctx, res); }
-    obj_obj_bind(res, DB_OBJ(table)->id, id);
-    return res;
-  } else {
-    return F;
-  }
-}
-
-static grn_obj *
-get_column(grn_ctx *ctx, grn_id tid, char *msg, unsigned int msg_size, grn_id *id)
-{
-  grn_obj *table = grn_ctx_at(ctx, tid);
-  for (;;) {
-    grn_obj *domain = grn_ctx_at(ctx, DB_OBJ(table)->header.domain);
-    if (!domain || domain->header.type == GRN_TYPE) { break; }
-    if (id) {
-      if (!grn_table_get_key(ctx, table, *id, id, sizeof(grn_id))) { return NULL; }
-    }
-    table = domain;
-  }
-  return grn_obj_column(ctx, table, msg, msg_size);
-}
-
-static grn_cell *
-table_column(grn_ctx *ctx, grn_id base, char *msg, unsigned int msg_size)
-{
-  grn_obj *column = get_column(ctx, base, msg, msg_size, NULL);
-  return column ? get_cell(ctx, column) : F;
-}
-
-static grn_cell *
-ha_sections(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  uint16_t msg_size;
-  grn_cell *car, *res;
-  char msg[STRBUF_SIZE];
-  if (!(res = ctx->impl->code)) { QLERR("invalid receiver"); }
-  POP(car, args);
-  if (obj2str(car, msg, &msg_size)) { QLERR("invalid argument"); }
-  switch (*msg) {
-  case ':' :
-    switch (msg[1]) {
-    case 's' : /* :sexp */
-      {
-        grn_obj *sections = (grn_obj *)res->u.p.value;
-        int n = sections->u.v.n_sections;
-        grn_section *vp = &sections->u.v.sections[n];
-        const char *head = GRN_BULK_HEAD(sections->u.v.body);
-        grn_cell *a = INTERN("@");
-        grn_cell *d = INTERN(":dic");
-        grn_cell *w = INTERN(":weight");
-        grn_cell *v = INTERN(":value");
-        res = NIL;
-        while ((vp--, n--)) {
-          grn_cell *vs = NIL;
-          if (vp->weight || vp->domain) {
-            vs = CONS(v, CONS(grn_ql_mk_string(ctx, head + vp->offset, vp->length), vs));
-            if (vp->weight) {
-              grn_cell *nv;
-              GRN_CELL_NEW(ctx, nv);
-              SETINT(nv, vp->weight);
-              vs = CONS(w, CONS(nv, vs));
-            }
-            if (vp->domain) {
-              grn_cell *nv;
-              GRN_CELL_NEW(ctx, nv);
-              SETINT(nv, vp->domain);
-              vs = CONS(d, CONS(nv, vs));
-            }
-            vs = CONS(a, vs);
-          } else {
-            vs = grn_ql_mk_string(ctx, head + vp->offset, vp->length);
-          }
-          res = CONS(vs, res);
-        }
-      }
-      break;
-    default :
-      QLERR("invalid argument");
-    }
-    break;
-  default :
-    QLERR("invalid argument");
-  }
-  return res;
-}
-
-#define QLWARN(...) ERRSET(ctx, GRN_WARN, GRN_INVALID_ARGUMENT, __VA_ARGS__)
-
-#define STR2DBL(str,len,val) do {\
-  char *end, buf0[128], *buf = (len) < 128 ? buf0 : GRN_MALLOC((len) + 1);\
-  if (buf) {\
-    double d;\
-    memcpy(buf, (str), (len));\
-    buf[len] = '\0';\
-    errno = 0;\
-    d = strtod(buf, &end);\
-    if (!((len) < 128)) { GRN_FREE(buf); }\
-    if (!errno && buf + (len) == end) {\
-      (val) = d;\
-    } else { QLWARN("cast failed"); }\
-  } else { QLWARN("buf alloc failed"); }\
-} while (0)
-
-static void
-list2vector(grn_ctx *ctx, grn_cell *s, grn_obj *v)
-{
-  grn_cell *car, *key, *value;
-  while (PAIRP(s)) {
-    POP(car, s);
-    if (BULKP(car)) {
-      grn_vector_add_element(ctx, v, STRVALUE(car), STRSIZE(car), 0, GRN_ID_NIL);
-    } else if (PAIRP(car)) {
-      const char *str = NULL;
-      grn_id domain = GRN_ID_NIL;
-      unsigned int weight = 0, str_len = 0;
-      POP(key, car);
-      if (key == INTERN("@")) {
-        while (PAIRP(car)) {
-          POP(key, car);
-          POP(value, car);
-          if (key == INTERN(":dic")) {
-            /* todo */
-          } else if (key == INTERN(":weight")) {
-            grn_obj2int(ctx, value);
-            weight = (uint32_t) IVALUE(value);
-          } else if (key == INTERN(":value") && BULKP(value)) {
-            str = STRVALUE(value);
-            str_len = STRSIZE(value);
-          }
-        }
-        if (str) {
-          grn_vector_add_element(ctx, v, str, str_len, weight, domain);
-        }
-      }
-    }
-  }
-}
-
-static grn_obj *
-cell2obj(grn_ctx *ctx, grn_cell *cell, grn_obj *column, grn_obj *obj)
-{
-  if ((column->header.flags & GRN_OBJ_COLUMN_TYPE_MASK) == GRN_OBJ_COLUMN_SCALAR) {
-    grn_id rid = grn_obj_get_range(ctx, column);
-    grn_obj *range = grn_ctx_at(ctx, rid);
-    if (range && range->header.type == GRN_TYPE) {
-      switch (rid) {
-      case GRN_DB_INT32 :
-        {
-          int32_t v;
-          switch (cell->header.type) {
-          case GRN_CELL_STR :
-            {
-              int64_t iv = grn_atoll(STRVALUE(cell), STRVALUE(cell) + STRSIZE(cell), NULL);
-              v = (int32_t) iv;
-            }
-            break;
-          case GRN_CELL_INT :
-            v = (int32_t) IVALUE(cell);
-            break;
-          case GRN_CELL_FLOAT :
-            v = (int32_t) FVALUE(cell);
-            break;
-          case GRN_CELL_TIME :
-            v = (int32_t) cell->u.tv.tv_nsec / GRN_TIME_NSEC_PER_SEC * GRN_TIME_USEC_PER_SEC;
-            break;
-          }
-          if (!obj) { if (!(obj = grn_obj_open(ctx, GRN_BULK, 0, 0))) { return NULL; }}
-          grn_bulk_write(ctx, obj, (const char *)(&v), sizeof(int32_t));
-        }
-        break;
-      case GRN_DB_UINT32 :
-        {
-          uint32_t v;
-          switch (cell->header.type) {
-          case GRN_CELL_STR :
-            {
-              int64_t iv = grn_atoll(STRVALUE(cell), STRVALUE(cell) + STRSIZE(cell), NULL);
-              v = (uint32_t) iv;
-            }
-            break;
-          case GRN_CELL_INT :
-            v = (uint32_t) IVALUE(cell);
-            break;
-          case GRN_CELL_FLOAT :
-            v = (uint32_t) FVALUE(cell);
-            break;
-          case GRN_CELL_TIME :
-            v = (uint32_t) cell->u.tv.tv_nsec / GRN_TIME_NSEC_PER_SEC * GRN_TIME_USEC_PER_SEC;
-            break;
-          }
-          if (!obj) { if (!(obj = grn_obj_open(ctx, GRN_BULK, 0, 0))) { return NULL; }}
-          grn_bulk_write(ctx, obj, (const char *)(&v), sizeof(uint32_t));
-        }
-        break;
-      case GRN_DB_INT64 :
-        {
-          int64_t v;
-          switch (cell->header.type) {
-          case GRN_CELL_STR :
-            v = grn_atoll(STRVALUE(cell), STRVALUE(cell) + STRSIZE(cell), NULL);
-            break;
-          case GRN_CELL_INT :
-            v = IVALUE(cell);
-            break;
-          case GRN_CELL_FLOAT :
-            v = (int64_t) FVALUE(cell);
-            break;
-          case GRN_CELL_TIME :
-            v = (int32_t) cell->u.tv.tv_nsec / GRN_TIME_NSEC_PER_SEC * GRN_TIME_USEC_PER_SEC;
-            break;
-          }
-          if (!obj) { if (!(obj = grn_obj_open(ctx, GRN_BULK, 0, 0))) { return NULL; }}
-          grn_bulk_write(ctx, obj, (const char *)(&v), sizeof(int64_t));
-        }
-        break;
-      case GRN_DB_FLOAT :
-        {
-          double v;
-          switch (cell->header.type) {
-          case GRN_CELL_STR :
-            { /* todo : support #i notation */
-              char *str = STRVALUE(cell);
-              int len = STRSIZE(cell);
-              STR2DBL(str, len, v);
-            }
-            break;
-          case GRN_CELL_INT :
-            v = (double) IVALUE(cell);
-            break;
-          case GRN_CELL_FLOAT :
-            v = FVALUE(cell);
-            break;
-          case GRN_CELL_TIME :
-            v = ((double) cell->u.tv.tv_nsec) / GRN_TIME_NSEC_PER_SEC + cell->u.tv.tv_sec;
-            break;
-          }
-          if (!obj) { if (!(obj = grn_obj_open(ctx, GRN_BULK, 0, 0))) { return NULL; }}
-          grn_bulk_write(ctx, obj, (const char *)(&v), sizeof(double));
-        }
-        break;
-      case GRN_DB_TIME :
-        {
-          grn_timeval v;
-          switch (cell->header.type) {
-          case GRN_CELL_STR :
-            {
-              int len = STRSIZE(cell);
-              char *str = STRVALUE(cell);
-              if (grn_str2timeval(str, len, &v)) {
-                if (len > 3 && *str == '#' && str[1] == ':' && str[2] == '<') {
-                  const char *cur;
-                  v.tv_sec = grn_atoi(str + 3, str + len, &cur);
-                  if (cur >= str + len || *cur != '.') {
-                    QLWARN("illegal time format '%s'", str);
-                  }
-                  v.tv_nsec = grn_atoi(cur + 1, str + len, &cur);
-                  if (cur >= str + len || *cur != '>') {
-                    QLWARN("illegal time format '%s'", str);
-                  }
-                } else {
-                  double dval = 0.0;
-                  char *str = STRVALUE(cell);
-                  int len = cell->u.b.size;
-                  STR2DBL(str, len, dval);
-                  v.tv_sec = (int32_t) dval;
-                  v.tv_nsec = (int32_t) ((dval - v.tv_sec) * GRN_TIME_NSEC_PER_SEC);
-                }
-              }
-            }
-            break;
-          case GRN_CELL_INT :
-            v.tv_sec = (int32_t) IVALUE(cell);
-            v.tv_nsec = 0;
-            break;
-          case GRN_CELL_FLOAT :
-            v.tv_sec = (int32_t) FVALUE(cell);
-            v.tv_nsec = (int32_t) ((FVALUE(cell) - v.tv_sec) * GRN_TIME_NSEC_PER_SEC);
-            break;
-          case GRN_CELL_TIME :
-            v.tv_sec = cell->u.tv.tv_sec;
-            v.tv_nsec = cell->u.tv.tv_nsec;
-            break;
-          }
-          if (!obj) { if (!(obj = grn_obj_open(ctx, GRN_BULK, 0, 0))) { return NULL; }}
-          grn_bulk_write(ctx, obj, (const char *)(&v), sizeof(grn_timeval));
-        }
-        break;
-      default :
-        if (BULKP(cell)) {
-          if (!obj) { if (!(obj = grn_obj_open(ctx, GRN_BULK, 0, 0))) { return NULL; }}
-          grn_bulk_write(ctx, obj, STRVALUE(cell), STRSIZE(cell));
-        } else {
-          if (obj) { GRN_BULK_REWIND(obj); }
-        }
-        break;
-      }
-    } else {
-      /* todo : grn_type_any support
-      grn_bulk_write(ctx, bulk, (const char *)(&cell->header.domain), sizeof(grn_id));
-      */
-      /* todo : nested table support.
-       */
-      grn_id id;
-      switch (cell->header.type) {
-      case GRN_CELL_OBJECT :
-        if (cell->header.domain != rid) { return NULL; }
-        id = cell->u.o.id;
-        break;
-      case GRN_CELL_STR :
-        id = grn_table_add(ctx, range, STRVALUE(cell), STRSIZE(cell), NULL);
-        break;
-      default :
-        if (VOIDP(cell)) { id = GRN_ID_NIL; }
-        break;
-      }
-      if (!obj) { if (!(obj = grn_obj_open(ctx, GRN_BULK, 0, 0))) { return NULL; }}
-      grn_bulk_write(ctx, obj, (const char *)&id, sizeof(grn_id));
-    }
-    obj->header.domain = rid;
-  } else {
-    switch (cell->header.type) {
-    case GRN_CELL_STR :
-      if (BULKP(cell)) {
-        if (!obj) { if (!(obj = grn_obj_open(ctx, GRN_BULK, 0, 0))) { return NULL; }}
-        grn_bulk_write(ctx, obj, STRVALUE(cell), STRSIZE(cell));
-      } else {
-        if (obj) { GRN_BULK_REWIND(obj); }
-      }
-      /* todo */
-      break;
-    case GRN_CELL_INT :
-      /* todo */
-      break;
-    case GRN_CELL_FLOAT :
-      /* todo */
-      break;
-    case GRN_CELL_TIME :
-      /* todo */
-      break;
-    case GRN_CELL_LIST :
-      obj = grn_obj_open(ctx, GRN_VECTOR, 0, 0);
-      list2vector(ctx, cell, obj);
-      break;
-    case GRN_VECTOR :
-      obj = (grn_obj *)cell->u.p.value;
-      break;
-    }
-  }
-  return obj;
-}
-
-inline static grn_cell *
-column_value(grn_ctx *ctx, grn_obj *column, grn_id obj,
-             grn_cell *args, grn_cell *res)
-{
-  grn_obj *value;
-  if (!column) { return F; }
-  if (VOIDP(args) || (PAIRP(args) && VOIDP(CAR(args)))) {
-    if ((value = grn_obj_get_value(ctx, column, obj, NULL))) {
-      switch (column->header.flags & GRN_OBJ_COLUMN_TYPE_MASK) {
-      case GRN_OBJ_COLUMN_VECTOR :
-        {
-          grn_cell **rp = &res;
-          grn_id *v = (grn_id *) GRN_BULK_HEAD(value);
-          uint32_t s = GRN_BULK_VSIZE(value) / sizeof(grn_id);
-          *rp = NIL;
-          while (s--) {
-            grn_cell *cell = grn_cell_new(ctx);
-            if (cell) {
-              obj_obj_bind(cell, column->header.domain, *v);
-              if ((*rp = CONS(cell, NIL))) {
-                rp = &CDR(*rp);
-              }
-            }
-          }
-        }
-        break;
-      default :
-        res = obj2cell(ctx, value, res);
-        break;
-      }
-      grn_obj_close(ctx, value);
-    } else {
-      res = F;
-    }
-  } else {
-    grn_cell *car;
-    int flags = GRN_OBJ_SET;
-    POP(car, args);
-    if ((value = cell2obj(ctx, car, column, NULL))) {
-      res = grn_obj_set_value(ctx, column, obj, value, flags) ? F : car;
-      grn_obj_close(ctx, value);
-    } else {
-      res = F;
-    }
-  }
-  return res;
-}
-
-static grn_cell *
-register_cell(grn_ctx *ctx, grn_obj *db_obj, const char *name, unsigned int name_size)
-{
-  if (name && name_size) {
-    return INTERN2(name, name_size);
-    // grn_ql_obj_bind(db_obj, res);
-  } else {
-    grn_cell *r = get_cell(ctx, db_obj);
-    if (r != F) {
-      r->header.impl_flags = 0;
-      r->header.flags = 0;
-      grn_ql_obj_bind(db_obj, r);
-    }
-    return r;
-  }
-}
-
-static grn_cell *
-table_create(grn_ctx *ctx, const char *name, unsigned int name_size,
-             grn_obj_flags flags, grn_obj *domain,
-             grn_obj *value_type, grn_id tokenizer)
-{
-  grn_obj *table = grn_table_create(ctx, name, name_size,
-                                    NULL, flags, domain, value_type);
-  if (!table) { QLERR("table create failed"); }
-  grn_obj_set_info(ctx, table, GRN_INFO_DEFAULT_TOKENIZER, grn_ctx_at(ctx, tokenizer));
-  return register_cell(ctx, table, name, name_size);
-}
-
-static grn_cell *
-rec_obj_new(grn_ctx *ctx, grn_obj *domain, grn_obj *value_type)
-{
-  return table_create(ctx, NULL, 0, GRN_OBJ_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC,
-                      domain, value_type, GRN_DB_DELIMIT);
-}
-
-typedef struct {
-  column_exp *ce;
-  grn_cell *func;
-  //  grn_cell *exprs;
-  grn_cell *args;
-  grn_operator op;
-  //  grn_cell *objs;
-  int32_t offset;
-  int32_t limit;
-  int mode;
-  char *from;
-  unsigned int fromsize;
-  char *to;
-  unsigned int tosize;
-  column_exp *score_ce;
-  grn_cell *score_func;
-} match_spec;
-
-inline static grn_cell *
-match_prepare(grn_ctx *ctx, match_spec *spec, grn_id base, grn_cell *args)
-{
-  grn_cell *car, *expr;
-  grn_obj *r = grn_ctx_at(ctx, base);
-  POP(expr, args);
-  spec->ce = column_exp_open(ctx, r, expr, NIL);
-  if (EVAL_BY_FUNCALLP(spec->ce)) {
-    spec->func = CAR(expr);
-  } else {
-    spec->func = NULL;
-  }
-  spec->offset = 0;
-  spec->limit = 0;
-  spec->mode = 0;
-  spec->from = NULL;
-  spec->fromsize = 0;
-  spec->to = NULL;
-  spec->tosize = 0;
-  spec->op = GRN_OP_OR;
-  spec->score_ce = NULL;
-  spec->score_func = NULL;
-  POP(car, args);
-  if (car != NIL) {
-    spec->score_ce = column_exp_open(ctx, r, car, NIL);
-    if (EVAL_BY_FUNCALLP(spec->score_ce)) { spec->score_func = CAR(car); }
-  }
-  POP(expr, args);
-  if (RECORDSP(expr)) {
-    char ops[STRBUF_SIZE];
-    uint16_t ops_size;
-    if (expr->header.domain != base) { QLERR("table unmatch"); }
-    POP(car, args);
-    spec->op = GRN_OP_AND;
-    if (!obj2str(car, ops, &ops_size)) {
-      switch (*ops) {
-      case '+': spec->op = GRN_OP_OR; break;
-      case '-': spec->op = GRN_OP_BUT; break;
-      case '*': spec->op = GRN_OP_AND; break;
-      case '>': spec->op = GRN_OP_ADJUST; break;
-      }
-    }
-  } else {
-    char str[STRBUF_SIZE];
-    uint16_t str_size;
-    grn_obj *table = grn_ctx_at(ctx, base);
-    if (INTP(expr)) { spec->offset = IVALUE(expr); }
-    POP(expr, args);
-    if (INTP(expr)) { spec->limit = IVALUE(expr); }
-    if (spec->limit <= 0) { spec->limit += grn_table_size(ctx, table); }
-    POP(expr, args);
-    if (!obj2str(expr, str, &str_size)) {
-      uint16_t i;
-      for (i = 0; i < str_size; i++) {
-        switch (str[i]) {
-        case 'd' : spec->mode |= GRN_CURSOR_DESCENDING; break;
-        case 'g' : spec->mode |= GRN_CURSOR_GT; break;
-        case 'l' : spec->mode |= GRN_CURSOR_LT; break;
-        }
-      }
-    }
-    POP(expr, args);
-    if (BULKP(expr)) {
-      spec->from = STRVALUE(expr);
-      spec->fromsize = STRSIZE(expr);
-    }
-    POP(expr, args);
-    if (BULKP(expr)) {
-      spec->to = STRVALUE(expr);
-      spec->tosize = STRSIZE(expr);
-    }
-    expr = rec_obj_new(ctx, table, NULL);
-    if (ERRP(ctx, GRN_WARN)) { return F; }
-    spec->op = GRN_OP_OR;
-  }
-  //  spec->objs = CONS(expr, spec->exprs);
-  return expr;
-}
-
-grn_obj *
-grn_ql_obj_key(grn_ctx *ctx, grn_cell *obj, grn_obj *value)
-{
-  grn_obj *table = grn_ctx_at(ctx, obj->header.domain);
-  grn_obj *accessor = grn_obj_column(ctx, table, ":key", 4);
-  if (accessor) {
-    value = grn_obj_get_value(ctx, accessor, obj->u.o.id, value);
-    grn_obj_unlink(ctx, accessor);
-  }
-  return value;
-}
-
-inline static grn_cell *
-obj2oid(grn_ctx *ctx, grn_cell *obj, grn_cell *res)
-{
-  grn_obj buf;
-  if (obj->header.type != GRN_CELL_OBJECT) { return F; }
-  GRN_TEXT_INIT(&buf, 0);
-  grn_obj_inspect(ctx, obj, &buf, GRN_OBJ_INSPECT_ESC);
-  if (res) {
-    uint32_t size = GRN_BULK_VSIZE(&buf);
-    char *value = GRN_MALLOC(size + 1);
-    if (!value) {
-      res = F;
-      goto exit;
-    }
-    grn_cell_clear(ctx, res);
-    res->header.impl_flags = GRN_OBJ_ALLOCATED;
-    res->header.type = GRN_CELL_STR;
-    res->u.b.size = size;
-    res->u.b.value = value;
-    memcpy(res->u.b.value, GRN_TEXT_VALUE(&buf), res->u.b.size + 1);
-  } else {
-    if (!(res = grn_ql_mk_string(ctx, GRN_TEXT_VALUE(&buf), GRN_BULK_VSIZE(&buf)))) {
-      res = F;
-    }
-  }
-exit :
-  GRN_OBJ_FIN(ctx, &buf);
-  return res;
-}
-
-inline static int
-match_exec(grn_ctx *ctx, match_spec *spec, grn_id base, grn_id id)
-{
-  grn_cell *res;
-  column_exp_exec(ctx, spec->ce, id);
-  if (spec->func) {
-    grn_cell *code = ctx->impl->code;
-    ctx->impl->code = spec->func;
-    res = spec->func->u.o.func(ctx, CDR(spec->ce->expr), &ctx->impl->co);
-    ctx->impl->code = code;
-  } else {
-    res = grn_ql_eval(ctx, spec->ce->expr, NIL);
-  }
-  return res != F;
-}
-
-inline static int
-score_exec(grn_ctx *ctx, match_spec *spec, grn_id base, grn_id id)
-{
-  grn_cell *res;
-  column_exp_exec(ctx, spec->score_ce, id);
-  if (spec->score_func) {
-    grn_cell *code = ctx->impl->code;
-    ctx->impl->code = spec->score_func;
-    res = spec->score_func->u.o.func(ctx, CDR(spec->score_ce->expr), &ctx->impl->co);
-    ctx->impl->code = code;
-  } else {
-    res = grn_ql_eval(ctx, spec->score_ce->expr, NIL);
-  }
-  switch (res->header.type) {
-  case GRN_CELL_INT :
-    return IVALUE(res);
-  case GRN_CELL_FLOAT :
-    return (int)FVALUE(res);
-  default :
-    return 0;
-  }
-}
-
-static grn_rc
-match_close(grn_ctx *ctx, match_spec *spec)
-{
-  if (spec->score_ce) { column_exp_close(ctx, spec->score_ce); }
-  return column_exp_close(ctx, spec->ce);
-}
-
-// todo : refine
-#define MAXCOLUMNS 0x100
-
-struct _ins_stat {
-  grn_cell *columns;
-  int ncolumns;
-  int nrecs;
-};
-
-typedef struct {
-  grn_encoding encoding;
-  char *cur;
-  char *str_end;
-} jctx;
-
-static grn_cell *json_read(grn_ctx *ctx, jctx *jc, int keyp);
-
-static grn_cell *
-ha_table(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  grn_id base;
-  int load = 0;
-  grn_obj *table;
-  grn_cell *car, *res;
-  char msg[STRBUF_SIZE];
-  uint16_t msg_size;
-  if (!(res = ctx->impl->code)) { QLERR("invalid receiver"); }
-  base = ctx->impl->code->u.o.id;
-  if (!(table = grn_ctx_at(ctx, base))) { QLERR("invalid table"); }
-  GRN_QL_CO_BEGIN(co);
-  POP(car, args);
-  if (obj2str(car, msg, &msg_size)) { QLERR("invalid argument"); }
-  switch (*msg) {
-  case '\0' : /* get instance by key */
-    {
-      POP(car, args);
-      if (obj2str(car, msg, &msg_size)) { QLERR("invalid argument"); }
-      res = grn_ql_table_get(ctx, table, msg, msg_size, NULL);
-    }
-    break;
-  case ':' :
-    switch (msg[1]) {
-    case 'c' :
-    case 'C' :
-      switch (msg[2]) {
-      case 'l' : /* :clearlock */
-      case 'L' :
-        {
-          res = grn_obj_is_locked(ctx, table) ? T : F;
-          grn_obj_clear_lock(ctx, table);
-        }
-        break;
-      case 'o' : /* :common-prefix-search */
-      case 'O' :
-        switch (msg[3]) {
-        case 'm' :
-        case 'M' :
-          {
-            grn_id id;
-            POP(car, args);
-            if (!BULKP(car)) { QLERR("invalid argument"); }
-            id = grn_table_lcp_search(ctx, table, STRVALUE(car), STRSIZE(car));
-            res = id ? grn_ql_obj_new(ctx, base, id) : F;
-          }
-          break;
-        case 'l' : /* :columns */
-        case 'L' :
-          POP(car, args);
-          if (RECORDSP(car)) {
-            msg_size = 0;
-            res = car;
-          } else {
-            if (obj2str(car, msg, &msg_size)) { QLERR("invalid argument"); }
-            POP(res, args);
-            if (res == NIL) {
-              if (!(res = rec_obj_new(ctx, NULL, NULL))) { QLERR("rec_obj_new failed"); }
-            } else if (!RECORDSP(res)) {
-              QLERR("records object expected");
-            }
-          }
-          grn_table_columns(ctx, table, msg, msg_size, get_obj(ctx, res));
-          break;
-        default :
-          res = F;
-          break;
-        }
-        break;
-      }
-      break;
-    case 'd' :
-    case 'D' :
-      switch (msg[2]) {
-      case 'e' :
-      case 'E' :
-        switch (msg[3]) {
-        case 'f' : /* :def */
-        case 'F' :
-          {
-            uint16_t name_size;
-            int nsources = 0;
-            grn_id sources[MAXCOLUMNS];
-            grn_obj *column, *type;
-            char name[STRBUF_SIZE];
-            grn_obj_flags flags = GRN_OBJ_PERSISTENT; /* default */
-            POP(car, args);
-            if (obj2str(car, name, &name_size)) { QLERR("invalid argument"); }
-            if (grn_obj_column(ctx, table, name, name_size)) { return T; }
-            POP(car, args);
-            type = get_obj(ctx, car);
-            while (PAIRP(args)) {
-              POP(car, args);
-              if (PAIRP(car)) {
-                grn_cell *col;
-                while (PAIRP(car) && nsources < MAXCOLUMNS) {
-                  POP(col, car);
-                  if (!obj2str(col, msg, &msg_size)) {
-                    grn_obj *source = grn_obj_column(ctx, type, msg, msg_size);
-                    if (source) { sources[nsources++] = DB_OBJ(source)->id; }
-                  }
-                }
-              } else {
-                if (obj2str(car, msg, &msg_size)) { QLERR("invalid argument"); }
-                switch (*msg) {
-                case 'b' :
-                case 'B' :
-                  flags |= GRN_OBJ_RING_BUFFER;
-                  break;
-                case 'i' :
-                case 'I' :
-                  flags |= GRN_OBJ_COLUMN_INDEX;
-                  break;
-                case 'l' :
-                case 'L' :
-                  flags |= GRN_OBJ_COMPRESS_LZO;
-                  break;
-                case 'p' :
-                case 'P' :
-                  switch (msg[1]) {
-                  case 'e' :
-                  case 'E' :
-                    flags |= GRN_OBJ_PERSISTENT;
-                    break;
-                  case 'o' :
-                  case 'O' :
-                    flags |= GRN_OBJ_WITH_POSITION;
-                    break;
-                  }
-                  break;
-                case 's' :
-                case 'S' :
-                  flags |= GRN_OBJ_WITH_SECTION;
-                  break;
-                case 't' :
-                case 'T' :
-                  flags &= ~GRN_OBJ_PERSISTENT;
-                  break;
-                case 'v' :
-                case 'V' :
-                  flags |= GRN_OBJ_COLUMN_VECTOR;
-                  break;
-                case 'w' :
-                case 'W' :
-                  flags |= GRN_OBJ_WITH_WEIGHT;
-                  break;
-                case 'z' :
-                case 'Z' :
-                  flags |= GRN_OBJ_COMPRESS_ZLIB;
-                  break;
-                }
-              }
-            }
-            column = grn_column_create(ctx, table, name, name_size, NULL, flags, type);
-            if (column) {
-              if (nsources) {
-                grn_obj source;
-                GRN_TEXT_INIT(&source, GRN_OBJ_DO_SHALLOW_COPY);
-                GRN_TEXT_SET_REF(&source, sources, nsources * sizeof(grn_id));
-                grn_obj_set_info(ctx, column, GRN_INFO_SOURCE, &source);
-              }
-              msg_size = grn_obj_name(ctx, column, msg, GRN_PAT_MAX_KEY_SIZE);
-              res = INTERN2(msg, msg_size);
-            } else {
-              res = F;
-            }
-          }
-          break;
-        case 'l' : /* :delete */
-        case 'L' :
-          POP(car, args);
-          if (obj2str(car, msg, &msg_size)) { QLERR("invalid argument"); }
-          res = grn_table_delete(ctx, table, msg, msg_size) ? T : F;
-          break;
-        default :
-          res = F;
-          break;
-        }
-        break;
-      case 'i' : /* :difference */
-      case 'I' :
-        {
-          if (PAIRP(args)) {
-            POP(car, args);
-            if (TABLEP(car)) {
-              grn_obj *table2 = RVALUE(car);
-              res = grn_table_difference(ctx, table, table2, table, table2) ? T : F;
-            }
-          }
-        }
-        break;
-      default :
-        res = F;
-        break;
-      }
-      break;
-    case 'e' : /* :extract */
-    case 'E' :
-      POP(car, args);
-      if (!BULKP(car)) { QLERR("string expected"); }
-      POP(res, args);
-      if (res == NIL) {
-        if (!(res = rec_obj_new(ctx, table, NULL))) { QLERR("rec_obj_new failed"); }
-      } else if (!RECORDSP(res)) {
-        QLERR("records object expected");
-      }
-      if (grn_table_search(ctx, table, STRVALUE(car), STRSIZE(car),
-                           GRN_OP_TERM_EXTRACT, get_obj(ctx, res), GRN_OP_OR)
-          < GRN_SUCCESS) {
-        QLERR("term_extract failed");
-      }
-      break;
-    case 'g' : /* :group */
-    case 'G' :
-      {
-        column_exp *ce;
-        POP(car, args);
-        ce = column_exp_open(ctx, table, car, NIL);
-        if (ce) {
-          int n_results = 0;
-          grn_table_group_result *rp, results[256];
-          POP(car, args);
-          for (rp = results; TABLEP(car); rp++) {
-            memset(rp, 0, sizeof(grn_table_group_result));
-            rp->table = get_obj(ctx, car);
-            POP(car, args);
-            if (INTP(car)) {
-              rp->key_begin = IVALUE(car);
-              POP(car, args);
-              if (INTP(car)) {
-                rp->key_end = IVALUE(car);
-              } else {
-                rp->key_end = rp->key_begin + 1;
-              }
-            } else {
-              rp->key_begin = n_results;
-              rp->key_end = rp->key_begin + 1;
-            }
-            if (++n_results >= 256) { break; }
-          }
-          if (!n_results) {
-            for (rp = results; n_results < ce->n_keys; rp++, n_results++) {
-              grn_id range = grn_obj_get_range(ctx, ce->keys[n_results].key);
-              rp->table = get_obj(ctx, rec_obj_new(ctx, grn_ctx_at(ctx, range), NULL));
-              rp->key_begin = n_results;
-              rp->key_end = rp->key_begin + 1;
-            }
-          }
-          grn_table_group(ctx, table, ce->keys, ce->n_keys, results, n_results);
-          column_exp_close(ctx, ce);
-          res = NIL;
-          while (n_results--) {
-            res = CONS(get_cell(ctx, results[n_results].table), res);
-          }
-        } else {
-          QLERR("group key parse error");
-        }
-      }
-      break;
-    case 'i' : /* :intersect */
-    case 'I' :
-      {
-        while (PAIRP(args)) {
-          POP(car, args);
-          if (!TABLEP(car)) { continue; }
-          grn_table_setoperation(ctx, table, RVALUE(car), table, GRN_OP_AND);
-        }
-      }
-      break;
-    case 'j' : /* :jload */
-    case 'J' :
-      load = 1;
-      break;
-    case 'l' : /* :load */
-    case 'L' :
-      load = 2;
-      break;
-    case 'n' :
-    case 'N' :
-      {
-        switch (msg[2]) {
-        case 'e' : /* :new */
-        case 'E' :
-          {
-            // todo : support array
-            POP(car, args);
-            if (obj2str(car, msg, &msg_size)) { return F; }
-            res = grn_ql_table_add(ctx, table, msg, msg_size, NULL);
-            if (res != F) {
-              grn_cell cons, dummy;
-              grn_obj *column;
-              cons.header.type = GRN_CELL_LIST;
-              cons.header.impl_flags = 0;
-              cons.u.l.cdr = NIL;
-              while (PAIRP(args)) {
-                POP(car, args);
-                if (obj2str(car, msg, &msg_size)) { break; }
-                POP(car, args);
-                cons.u.l.car = car;
-                column = grn_obj_column(ctx, table, msg, msg_size);
-                column_value(ctx, column, res->u.o.id, &cons, &dummy);
-              }
-            }
-          }
-          break;
-        case 'r' : /* :nrecs */
-        case 'R' :
-          GRN_CELL_NEW(ctx, res);
-          SETINT(res, grn_table_size(ctx, table));
-          break;
-        default :
-          /* ambiguous message. todo : return error */
-          res = F;
-        }
-      }
-      break;
-    case 'p' : /* :prefix-search */
-    case 'P' :
-      POP(car, args);
-      if (!BULKP(car)) { QLERR("string expected"); }
-      POP(res, args);
-      if (res == NIL) {
-        if (!(res = rec_obj_new(ctx, table, NULL))) { QLERR("rec_obj_new failed"); }
-      } else if (!RECORDSP(res)) {
-        QLERR("records object expected");
-      }
-      if (grn_table_search(ctx, table, STRVALUE(car), STRSIZE(car),
-                           GRN_OP_PREFIX, get_obj(ctx, res), GRN_OP_OR)
-          < GRN_SUCCESS) {
-        QLERR("prefix search failed");
-      }
-      break;
-    case 's' :
-    case 'S' :
-      switch (msg[2]) {
-      case 'c' :
-      case 'C' :
-        switch (msg[3]) {
-        case 'a' : /* :scan-select */
-        case 'A' :
-          {
-            grn_rset_recinfo *ri;
-            grn_id *rid;
-            match_spec spec;
-            grn_obj *rec;
-            res = match_prepare(ctx, &spec, base, args);
-            if (ERRP(ctx, GRN_WARN)) { return F; }
-            rec = RVALUE(res);
-            switch (spec.op) {
-            case GRN_OP_OR :
-              {
-                grn_id id;
-                grn_table_cursor *c;
-                grn_rset_posinfo *pi = (grn_rset_posinfo *) &id;
-                int n = 0, o = spec.offset, l = spec.limit;
-                if (l) {
-                  if ((c = grn_table_cursor_open(ctx, table,
-                                                 spec.from, spec.fromsize,
-                                                 spec.to, spec.tosize, 0, -1,
-                                                 spec.mode))) {
-                    while ((id = grn_table_cursor_next(ctx, c))) {
-                      if (match_exec(ctx, &spec, base, id)) {
-                        if (n++ >= o) {
-                          /* todo : use GRN_SET_INT_ADD if !n_entries */
-                          grn_table_add_v(ctx, rec, pi, sizeof(grn_id), (void **)&ri, NULL);
-                          if (spec.score_ce) {
-                            int score = score_exec(ctx, &spec, base, id);
-                            grn_table_add_subrec(rec, ri, score, NULL, 0);
-                          }
-                          if (!--l) { break; }
-                        }
-                      }
-                    }
-                    grn_table_cursor_close(ctx, c);
-                  }
-                }
-              }
-              break;
-            case GRN_OP_AND :
-              GRN_HASH_EACH(ctx, (grn_hash *)rec, id, &rid, NULL, &ri, {
-                if (!match_exec(ctx, &spec, base, *rid)) {
-                  grn_hash_delete_by_id(ctx, (grn_hash *)rec, id, NULL);
-                }
-              });
-              break;
-            case GRN_OP_BUT :
-              GRN_HASH_EACH(ctx, (grn_hash *)rec, id, &rid, NULL, &ri, {
-                if (match_exec(ctx, &spec, base, *rid)) {
-                  grn_hash_delete_by_id(ctx, (grn_hash *)rec, id, NULL);
-                }
-              });
-              break;
-            case GRN_OP_ADJUST :
-              /* todo : support it */
-              break;
-            default :
-              break;
-            }
-            match_close(ctx, &spec);
-          }
-          break;
-        case 'h' : /* :schema */
-        case 'H' :
-          {
-            grn_obj_flags flags;
-            grn_encoding encoding;
-            grn_obj *tokenizer;
-            res = NIL;
-            if (!(msg_size = grn_obj_name(ctx, table, msg, STRBUF_SIZE))) {
-              return F;
-            }
-            if (grn_table_get_info(ctx, table, &flags, &encoding, &tokenizer)) {
-              return F;
-            }
-            if (flags & GRN_OBJ_KEY_NORMALIZE) { res = CONS(INTERN(":normalize"), res); }
-            switch (flags & GRN_OBJ_TABLE_TYPE_MASK) {
-            case GRN_OBJ_TABLE_HASH_KEY :
-              res = CONS(INTERN(":hash"), res);
-              break;
-            case GRN_OBJ_TABLE_PAT_KEY :
-              res = CONS(INTERN(":pat"), res);
-              break;
-            case GRN_OBJ_TABLE_NO_KEY :
-              res = CONS(INTERN(":surrogate"), res);
-              break;
-            }
-            {
-              char encstr[32] = ":";
-              strcpy(encstr + 1, grn_enctostr(encoding));
-              res = CONS(INTERN(encstr), res);
-            }
-            res = CONS(INTERN("ptable"),
-                       CONS(CONS(INTERN("quote"),
-                                 CONS(INTERN2(msg, msg_size), NIL)), res));
-          }
-          break;
-        default :
-          res = F;
-          break;
-        }
-        break;
-      case 'o' : /* :sort */
-      case 'O' :
-        {
-          int limit = 0;
-          column_exp *ce;
-          POP(car, args);
-          ce = column_exp_open(ctx, table, car, NIL);
-          POP(car, args);
-          if (!grn_obj2int(ctx, car)) { limit = car->u.i.i; }
-          if (limit <= 0) { limit += grn_table_size(ctx, table); }
-          POP(res, args);
-          if (!RECORDSP(res)) {
-            res = table_create(ctx, NULL, 0, GRN_OBJ_TABLE_NO_KEY,
-                               NULL, table, GRN_DB_DELIMIT);
-          }
-          if (ce) {
-            grn_table_sort(ctx, table, 0, limit, get_obj(ctx, res), ce->keys, ce->n_keys);
-            column_exp_close(ctx, ce);
-          } else {
-            grn_table_sort(ctx, table, 0, limit, get_obj(ctx, res), NULL, 0);
-          }
-        }
-        break;
-      case 'u' :
-      case 'U' :
-        switch (msg[3]) {
-        case 'f' : /* :suffix-search */
-        case 'F' :
-          POP(car, args);
-          if (!BULKP(car)) { QLERR("string expected"); }
-          POP(res, args);
-          if (res == NIL) {
-            if (!(res = rec_obj_new(ctx, table, NULL))) { QLERR("rec_obj_new failed"); }
-          } else if (!RECORDSP(res)) {
-            QLERR("records object expected");
-          }
-          if (grn_table_search(ctx, table, STRVALUE(car), STRSIZE(car),
-                               GRN_OP_SUFFIX, get_obj(ctx, res), GRN_OP_OR)
-              < GRN_SUCCESS) {
-            QLERR("suffix search failed");
-          }
-          break;
-        case 'b' : /* :subtract */
-        case 'B' :
-          {
-            while (PAIRP(args)) {
-              POP(car, args);
-              if (!TABLEP(car)) { continue; }
-              grn_table_setoperation(ctx, table, RVALUE(car), table, GRN_OP_BUT);
-            }
-          }
-          break;
-        default :
-          res = F;
-          break;
-        }
-        break;
-      default :
-        res = F;
-        break;
-      }
-      break;
-    case 't' :
-      {
-        int n;
-        grn_id id = GRN_ID_NIL;
-        for (n = 0; (id = grn_table_next(ctx, table, id)); n++) ;
-        res = (n == grn_table_size(ctx, table)) ? T : F;
-      }
-      break;
-    case 'T' :
-      {
-        int n = 0;
-        grn_id id;
-        grn_table_cursor *c;
-        if ((c = grn_table_cursor_open(ctx, table, NULL, 0, NULL, 0, 0, -1,
-                                       GRN_CURSOR_DESCENDING))) {
-          for (; (id = grn_table_cursor_next(ctx, c)); n++) ;
-          grn_table_cursor_close(ctx, c);
-        }
-        res = (n == grn_table_size(ctx, table)) ? T : F;
-      }
-      break;
-    case 'u' : /* :undef */
-    case 'U' :
-      switch (msg[2]) {
-      case 'n' :
-      case 'N' :
-        switch (msg[3]) {
-        case 'd' :
-        case 'D' :
-          {
-            grn_obj *column;
-            POP(car, args);
-            if (obj2str(car, msg, &msg_size)) { return F; }
-            if (!(column = grn_obj_column(ctx, table, msg, msg_size))) { return F; }
-            if (!(msg_size = grn_obj_name(ctx, column, msg, STRBUF_SIZE))) { return F; }
-            res = grn_table_delete(ctx, ctx->impl->db, msg, msg_size) ? F : T;
-          }
-          break;
-        case 'i' : /* :union */
-        case 'I' :
-          {
-            while (PAIRP(args)) {
-              POP(car, args);
-              if (!TABLEP(car)) { continue; }
-              grn_table_setoperation(ctx, table, RVALUE(car), table, GRN_OP_OR);
-            }
-          }
-          break;
-        default :
-          res = F;
-          break;
-        }
-        break;
-      default :
-        res = F;
-        break;
-      }
-      break;
-    case '+' : /* :+ (iterator next) */
-      {
-        grn_id id;
-        POP(res, args);
-        if (res->header.type == GRN_CELL_OBJECT &&
-            res->header.domain == DB_OBJ(table)->id &&
-            (id = grn_table_next(ctx, table, res->u.o.id))) {
-          res->u.o.id = id;
-        } else {
-          res = F;
-        }
-      }
-      break;
-    case '\0' : /* : (iterator begin) */
-      {
-        grn_id id;
-        id = grn_table_next(ctx, table, GRN_ID_NIL);
-        if (id == GRN_ID_NIL) {
-          res = F;
-        } else {
-          GRN_CELL_NEW(ctx, res);
-          obj_obj_bind(res, DB_OBJ(table)->id, id);
-        }
-      }
-      break;
-    }
-    break;
-  default : /* :columnname */
-    res = table_column(ctx, base, msg, msg_size);
-    break;
-  }
-  if (load == 1) {
-    int i;
-    grn_cell *s, *saved;
-    struct _ins_stat *stat;
-    for (s = args, i = 0; PAIRP(s); s = CDR(s), i++) {
-      car = CAR(s);
-      if (obj2str(car, msg, &msg_size)) { QLERR("invalid argument"); }
-      CAR(s) = table_column(ctx, base, msg, msg_size);
-      if (CAR(s) == F) { QLERR("invalid argument"); }
-    }
-    if (!(saved = grn_cell_alloc(ctx, sizeof(struct _ins_stat)))) { return F; }
-    stat = (struct _ins_stat *)saved->u.b.value;
-    stat->columns = args;
-    stat->ncolumns = i;
-    stat->nrecs = 0;
-    do {
-      GRN_QL_CO_WAIT(co, saved);
-      stat = (struct _ins_stat *)saved->u.b.value;
-      if (BULKP(args) && STRSIZE(args)) {
-        grn_cell *r, *o, obj, cons, dummy;
-        jctx jc;
-        jc.encoding = ctx->encoding;
-        jc.cur = args->u.b.value;
-        jc.str_end = args->u.b.value + args->u.b.size;
-        r = json_read(ctx, &jc, 0);
-        POP(car, r);
-        if (car == INTERN("@")) { /* hash */
-          for (s = r; CAR(s) != INTERN("::key"); s = CDR(s)) {
-            if (!PAIRP(s)) { QLERR("invalid argument"); }
-          }
-          s = CADR(s);
-          o = grn_ql_table_add(ctx, table, s->u.b.value, s->u.b.size, &obj);
-          if (o != F) {
-            cons.header.type = GRN_CELL_LIST;
-            cons.header.impl_flags = 0;
-            cons.u.l.cdr = NIL;
-            while (PAIRP(r)) {
-              grn_obj *column;
-              POP(car, r);
-              if (obj2str(car, msg, &msg_size)) { QLERR("invalid argument"); }
-              POP(car, r);
-              cons.u.l.car = car;
-              column = get_column(ctx, base, msg, msg_size, NULL);
-              column_value(ctx, column, obj.u.o.id, &cons, &dummy);
-              grn_obj_unlink(ctx, column);
-            }
-            stat->nrecs++;
-          }
-        } else { /* array */
-          if (!BULKP(car)) { QLERR("invalid argument"); }
-          o = grn_ql_table_add(ctx, table, car->u.b.value, car->u.b.size, &obj);
-
-          if (o != F) {
-            cons.header.type = GRN_CELL_LIST;
-            cons.header.impl_flags = 0;
-            cons.u.l.cdr = NIL;
-            for (s = stat->columns, i = 0; i < stat->ncolumns; s = CDR(s), i++) {
-              grn_obj *column;
-              POP(car, r);
-              cons.u.l.car = car;
-              column = grn_ctx_at(ctx, CAR(s)->u.o.id);
-              column_value(ctx, column, obj.u.o.id, &cons, &dummy);
-            }
-            stat->nrecs++;
-          }
-        }
-      } else {
-        co->mode |= GRN_CTX_TAIL;
-      }
-      {
-        grn_cell *_value = ctx->impl->value;
-        ctx->impl->value = saved;
-        grn_ctx_mgc(ctx);
-        ctx->impl->value = _value;
-      }
-    } while (!(co->mode & (GRN_CTX_HEAD|GRN_CTX_TAIL)));
-    if ((res = grn_cell_new(ctx))) {
-      res->header.type = GRN_CELL_INT;
-      res->u.i.i = stat->nrecs;
-    } else {
-      res = F;
-    }
-  } else if (load == 2) {
-    int i;
-    grn_cell *s;
-    struct _ins_stat *stat;
-    for (s = args, i = 0; PAIRP(s); s = CDR(s), i++) {
-      car = CAR(s);
-      if (obj2str(car, msg, &msg_size)) { QLERR("invalid argument"); }
-      CAR(s) = table_column(ctx, base, msg, msg_size);
-      if (CAR(s) == F) { QLERR("invalid argument"); }
-    }
-    if (!(s = grn_cell_alloc(ctx, sizeof(struct _ins_stat)))) { return F; }
-    stat = (struct _ins_stat *)s->u.b.value; // todo : not GC safe
-    stat->columns = args;
-    stat->ncolumns = i + 1;
-    stat->nrecs = 0;
-    do {
-      GRN_QL_CO_WAIT(co, stat);
-      if (BULKP(args) && STRSIZE(args)) {
-        const char *tokbuf[MAXCOLUMNS];
-        grn_obj *column;
-        grn_cell val, obj, cons, dummy;
-        cons.header.type = GRN_CELL_LIST;
-        cons.header.impl_flags = 0;
-        cons.u.l.car = &val;
-        cons.u.l.cdr = NIL;
-        val.header.type = GRN_CELL_STR;
-        if (grn_str_tok(args->u.b.value, STRSIZE(args), '\t', tokbuf, MAXCOLUMNS, NULL) == stat->ncolumns) {
-          grn_cell *o;
-          if (grn_obj_lock(ctx, ctx->impl->db, GRN_ID_NIL, -1)) {
-            GRN_LOG(ctx, GRN_LOG_CRIT, "ha_table::load lock failed");
-          } else {
-            o = grn_ql_table_add(ctx, table, args->u.b.value,
-                                tokbuf[0] - args->u.b.value, &obj);
-            if (o != F) {
-              for (s = stat->columns, i = 1; i < stat->ncolumns; s = CDR(s), i++) {
-                val.u.b.value = (char *)tokbuf[i - 1] + 1;
-                val.u.b.size = tokbuf[i] - val.u.b.value;
-                unesc(ctx, &val);
-                column = grn_ctx_at(ctx, CAR(s)->u.o.id);
-                column_value(ctx, column, obj.u.o.id, &cons, &dummy);
-              }
-              stat->nrecs++;
-            }
-            grn_obj_unlock(ctx, ctx->impl->db, GRN_ID_NIL);
-          }
-        }
-      } else {
-        co->mode |= GRN_CTX_TAIL;
-      }
-    } while (!(co->mode & (GRN_CTX_HEAD|GRN_CTX_TAIL)));
-    if ((res = grn_cell_new(ctx))) {
-      res->header.type = GRN_CELL_INT;
-      res->u.i.i = stat->nrecs;
-    } else {
-      res = F;
-    }
-  }
-  GRN_QL_CO_END(co);
-  return res;
-}
-
-static grn_cell *
-ha_object(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  char msg[STRBUF_SIZE];
-  uint16_t msg_size;
-  grn_cell *obj, *car, *res;
-  if (!(obj = res = ctx->impl->code)) { QLERR("invalid receiver"); }
-  while (PAIRP(args)) {
-    POP(car, args);
-    if (obj2str(car, msg, &msg_size)) { QLERR("invalid message"); }
-    if (*msg == ':' && msg[1] == 'i') {
-      res = obj2oid(ctx, obj, NULL);
-    } else {
-      grn_obj *domain = grn_ctx_at(ctx, obj->header.domain);
-      grn_obj *column = grn_obj_column(ctx, domain, msg, msg_size);
-      if (!column) {
-        QLERR("invalid column %s", msg);
-      }
-      res = column_value(ctx, column, obj->u.o.id, args, NULL);
-      grn_obj_unlink(ctx, column);
-      POP(car, args);
-    }
-  }
-  return res;
-}
-
-static grn_cell *
-ha_query(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  /* args: (str1 @ bulk) (str2 @ bulk) .. */
-  grn_rc rc;
-  grn_cell *x;
-  const char **strs;
-  grn_query *q;
-  unsigned int *str_lens;
-  int nstrs, found = 0, score = 0;
-  if (!PAIRP(args) || !BULKP(CAR(args))) { QLERR("invalid argument"); }
-  for (x = args, nstrs = 0; PAIRP(x) && BULKP(CAR(x)); x = CDR(x)) { nstrs++; }
-  if (!(strs = GRN_MALLOC(sizeof(intptr_t) * nstrs * 2))) {
-    QLERR("malloc failed");
-  }
-  str_lens = (unsigned int *)&strs[nstrs];
-  for (x = args, nstrs = 0; PAIRP(x) && BULKP(CAR(x)); x = CDR(x)) {
-    strs[nstrs] = STRVALUE(CAR(x));
-    str_lens[nstrs] = STRSIZE(CAR(x));
-    nstrs++;
-  }
-  q = (grn_query *)ctx->impl->code->u.p.value;
-  rc = grn_query_scan(ctx, q, strs, str_lens, nstrs, GRN_QUERY_SCAN_NORMALIZE, &found, &score);
-  GRN_FREE(strs);
-  if (rc) { QLERR("grn_query_scan failed"); }
-  if (!found) { return F; }
-  GRN_CELL_NEW(ctx, x);
-  SETINT(x, score);
-  return x;
-}
-
-static grn_cell *
-grn_obj_query(grn_ctx *ctx, const char *str, unsigned int str_len,
-              grn_operator default_op, int max_exprs, grn_encoding encoding)
-{
-  grn_query *q;
-  grn_cell *res = grn_cell_new(ctx);
-  if (!res || !(q = grn_query_open(ctx, str, str_len, default_op, max_exprs))) {
-    return NULL;
-  }
-  res->header.type = GRN_QUERY;
-  res->header.impl_flags = GRN_CELL_NATIVE|GRN_OBJ_ALLOCATED;
-  res->u.p.value = (grn_obj *)q;
-  res->u.p.func = ha_query;
- return res;
-}
-
-static void
-uvector2str(grn_ctx *ctx, grn_obj *obj, grn_obj *buf)
-{
-  grn_obj *range = grn_ctx_at(ctx, obj->header.domain);
-  if (range && range->header.type == GRN_TYPE) {
-    // todo
-  } else {
-    grn_id *v = (grn_id *)GRN_BULK_HEAD(obj), *ve = (grn_id *)GRN_BULK_CURR(obj);
-    if (v < ve) {
-      for (;;) {
-        grn_table_get_key2(ctx, range, *v, buf);
-        v++;
-        if (v < ve) {
-          GRN_TEXT_PUTC(ctx, buf, ' ');
-        } else {
-          break;
-        }
-      }
-    }
-  }
-}
-
-static grn_cell *
-ha_column(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  char msg[STRBUF_SIZE];
-  uint16_t msg_size;
-  grn_id base;
-  grn_cell *car, *res;
-  grn_obj *column;
-  if (!(res = ctx->impl->code)) { QLERR("invalid receiver"); }
-  base = ctx->impl->code->u.o.id;
-  if (!(column = grn_ctx_at(ctx, base))) { QLERR("grn_ctx_get failed"); }
-  POP(car, args);
-  if (obj2str(car, msg, &msg_size)) { QLERR("invalid message"); }
-  switch (*msg) {
-  case '\0' :
-    {
-      if (IDX_COLUMNP(ctx->impl->code)) {
-        grn_cell *q;
-        grn_operator op;
-        POP(q, args);
-        if (!QUERYP(q)) {
-          if (!BULKP(q)) { return F; }
-          if (!(q = grn_obj_query(ctx, q->u.b.value, q->u.b.size, GRN_OP_AND, 32, ctx->encoding))) {
-            QLERR("query_obj_new failed");
-          }
-        }
-        /* TODO: specify record unit */
-        /* (idxcolumn query ((column1 weight1) (column2 weight2) ...) records operator+ */
-        POP(car, args);
-        /* TODO: handle weights */
-        POP(res, args);
-        if (RECORDSP(res)) {
-          char ops[STRBUF_SIZE];
-          uint16_t ops_size;
-          op = GRN_OP_AND;
-          POP(car, args);
-          if (!obj2str(car, ops, &ops_size)) {
-            switch (*ops) {
-            case '+': op = GRN_OP_OR; break;
-            case '-': op = GRN_OP_BUT; break;
-            case '*': op = GRN_OP_AND; break;
-            case '>': op = GRN_OP_ADJUST; break;
-            }
-          }
-        } else {
-          grn_obj *table;
-          if (!(table = grn_ctx_at(ctx, DB_OBJ(column)->range))) { return F; }
-          res = rec_obj_new(ctx, table, NULL);
-          if (ERRP(ctx, GRN_WARN)) { return F; }
-          op = GRN_OP_OR;
-        }
-        grn_obj_search(ctx, column, (grn_obj *)q->u.p.value, RVALUE(res), op, NULL);
-      } else {
-        char name[STRBUF_SIZE];
-        uint16_t name_size;
-        grn_obj *table;
-        POP(car, args);
-        if (obj2str(car, name, &name_size)) { return F; }
-        if (!(table = grn_column_table(ctx, column))) { return F; }
-        res = grn_ql_table_get(ctx, table, name, name_size, NULL);
-        if (res != F) {
-          // grn_obj_lock(ctx, ctx->impl->db, GRN_ID_NIL, -1))
-          column_value(ctx, column, res->u.o.id, args, res);
-          // grn_obj_unlock(ctx, ctx->impl->db, GRN_ID_NIL);
-        }
-      }
-    }
-    break;
-  case ':' :
-    switch (msg[1]) {
-    case 's' : /* :schema */
-    case 'S' :
-      {
-        switch (column->header.type) {
-        case GRN_COLUMN_FIX_SIZE  :
-        case GRN_COLUMN_VAR_SIZE  :
-          res = CONS(get_cell(ctx, grn_ctx_at(ctx, DB_OBJ(column)->range)), NIL);
-          break;
-        case GRN_COLUMN_INDEX :
-          {
-            /* todo :
-            grn_db_trigger *t;
-            res = CONS(INTERN("::match"), CONS(NIL, NIL));
-            for (t = column->triggers; t; t = t->next) {
-              if (t->type == grn_db_index_target) {
-                res = CONS(get_cell(ctx, grn_ctx_at(ctx, t->target)), res);
-              }
-            }
-            */
-            res = CONS(INTERN(":index"), CONS(CONS(INTERN("quote"), CONS(res, NIL)), NIL));
-          }
-          break;
-        case GRN_CELL_PSEUDO_COLUMN    :
-          QLERR("not supported yet");
-          break;
-        default :
-          QLERR("invalid column type");
-          break;
-        }
-        /*
-        {
-          char *p, buf[GRN_PAT_MAX_KEY_SIZE];
-          strcpy(buf, _grn_pat_key(ctx, ctx->impl->db->keys, base));
-          if (!(p = strchr(buf, '.'))) { QLERR("invalid columnname %s", buf); }
-          *p = ':';
-          res = CONS(INTERN("::def"), CONS(INTERN(p), res));
-          *p = '\0';
-          res = CONS(INTERN(buf), res);
-        }
-        */
-      }
-      break;
-    }
-    break;
-  }
-  return res;
-}
-
-void
-grn_ql_obj_bind(grn_obj *obj, grn_cell *symbol)
-{
-  symbol->header.type = obj->header.type;
-  symbol->header.impl_flags |= GRN_CELL_NATIVE;
-  symbol->u.o.id = DB_OBJ(obj)->id;
-  symbol->header.domain = DB_OBJ(obj)->header.domain;
-  switch (symbol->header.type) {
-  case GRN_TABLE_HASH_KEY :
-  case GRN_TABLE_PAT_KEY :
-  case GRN_TABLE_NO_KEY :
-    symbol->u.o.func = ha_table;
-    break;
-  case GRN_COLUMN_FIX_SIZE :
-    symbol->u.o.func = ha_column;
-    break;
-  case GRN_COLUMN_VAR_SIZE :
-    symbol->u.o.func = ha_column;
-    break;
-  case GRN_COLUMN_INDEX :
-    symbol->u.o.func = ha_column;
-    break;
-  default :
-    symbol->u.o.func = ha_void;
-    break;
-  }
-}
-
-#define PVALUE(obj,type) ((type *)((obj)->u.p.value))
-
-inline static void
-snip_obj_bind(grn_cell *obj, grn_snip *snip)
-{
-  obj->header.type = GRN_SNIP;
-  obj->header.impl_flags = GRN_CELL_NATIVE|GRN_OBJ_ALLOCATED;
-  obj->u.p.value = (grn_obj *)snip;
-  obj->u.p.func = ha_snip;
-}
-
-struct _patsnip_spec {
-  grn_obj *table;
-  int width;
-  int max_results;
-  column_exp *ce;
-};
-
-void
-grn_obj_patsnip_spec_close(grn_ctx *ctx, patsnip_spec *spec)
-{
-  if (spec) {
-    column_exp_close(ctx, spec->ce);
-    GRN_FREE(spec);
-  }
-}
-
-static grn_cell *
-ha_snip(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  /* args: (str @ bulk) */
-  if (!PAIRP(args) || !BULKP(CAR(args))) { QLERR("invalid argument"); }
-  switch (ctx->impl->code->header.type) {
-  case GRN_SNIP :
-    {
-      grn_obj buf;
-      unsigned int i, len, max_len, nresults;
-      grn_snip *s = PVALUE(ctx->impl->code, grn_snip);
-      grn_cell *v, *str = CAR(args), *spc = PAIRP(CDR(args)) ? CADR(args) : NIL;
-      if ((grn_snip_exec(ctx, s, str->u.b.value, str->u.b.size, &nresults, &max_len))) {
-        QLERR("grn_snip_exec failed");
-      }
-      GRN_TEXT_INIT(&buf, 0);
-      if (grn_bulk_resize(ctx, &buf, max_len)) { QLERR("grn_bulk_resize failed"); }
-
-      if (nresults) {
-        for (i = 0; i < nresults; i++) {
-          if (i && spc != NIL) { grn_obj_inspect(ctx, spc, &buf, 0); }
-          if (grn_bulk_reserve(ctx, &buf, max_len)) {
-            grn_bulk_fin(ctx, &buf);
-            QLERR("grn_bulk_space failed");
-          }
-          if ((grn_snip_get_result(ctx, s, i, buf.u.b.curr, &len))) {
-            grn_bulk_fin(ctx, &buf);
-            QLERR("grn_snip_get_result failed");
-          }
-          buf.u.b.curr += len;
-        }
-      } else {
-        char *ss = str->u.b.value, *se = str->u.b.value + str->u.b.size;
-        if (grn_substring(ctx, &ss, &se, 0, s->width, ctx->encoding)) {
-          QLERR("grn_substring failed");
-        }
-        grn_bulk_write(ctx, &buf, ss, se - ss);
-      }
-      GRN_STR2OBJ(ctx, &buf, v);
-      return v;
-    }
-    break;
-  case GRN_PATSNIP :
-    {
-      grn_obj buf;
-      patsnip_spec *spec = PVALUE(ctx->impl->code, patsnip_spec);
-      off_t off = 0;
-      const char *rest;
-      grn_pat_scan_hit sh[1024];
-      grn_cell *v, *expr, *str = CAR(args);
-      char *string = STRVALUE(str);
-      size_t len = STRSIZE(str);
-      GRN_TEXT_INIT(&buf, 0);
-      if (grn_bulk_resize(ctx, &buf, len)) { QLERR("grn_bulk_resize failed."); }
-      while (off < len) {
-        grn_obj *table = spec->table;
-        int i, nhits = grn_pat_scan(ctx, (grn_pat *)table, string + off, len - off,
-                                    sh, 1024, &rest);
-        for (i = 0, off = 0; i < nhits; i++) {
-          if (sh[i].offset < off) { continue; } /* skip overlapping region. */
-          grn_bulk_write(ctx, &buf, string + off, sh[i].offset - off);
-          column_exp_exec(ctx, spec->ce, sh[i].id);
-          expr = spec->ce->expr;
-          //          expr = grn_ql_eval(ctx, spec->ce->expr, NIL);
-          POP(v, expr);
-          grn_obj_inspect(ctx, grn_ql_eval(ctx, v, NIL), &buf, 0);
-          grn_bulk_write(ctx, &buf, string + sh[i].offset, sh[i].length);
-          POP(v, expr);
-          grn_obj_inspect(ctx, grn_ql_eval(ctx, v, NIL), &buf, 0);
-          off = sh[i].offset + sh[i].length;
-        }
-        if (string + off < rest) {
-          grn_bulk_write(ctx, &buf, string + off, rest - (string + off));
-        }
-        off = rest - string;
-      }
-      GRN_STR2OBJ(ctx, &buf, v);
-      return v;
-    }
-    break;
-  default :
-    QLERR("snip failed. invalid expr");
-  }
-}
-
-static void disp_j(grn_ctx *ctx, grn_cell *obj, grn_obj *buf);
-
-static void
-disp_j_with_format(grn_ctx *ctx, grn_cell *args, grn_obj *buf)
-{
-  grn_cell *car;
-  POP(car, args);
-  switch (car->header.type) {
-  case GRN_TABLE_PAT_KEY :
-  case GRN_TABLE_HASH_KEY :
-  case GRN_TABLE_NO_KEY :
-    {
-      grn_id id, base;
-      grn_cell *columns;
-      int i, offset = 0, limit = 10, flags = GRN_CURSOR_ASCENDING;
-      grn_obj *r = RVALUE(car);
-      column_exp *ce;
-      base = car->u.o.id;
-      POP(columns, args);
-      if (!PAIRP(columns)) {
-        disp_j(ctx, car, buf);
-        return;
-      }
-      if ((ce = column_exp_open(ctx, r, columns, NIL))) {
-        POP(car, args);
-        if (!grn_obj2int(ctx, car)) { offset = car->u.i.i; }
-        POP(car, args);
-        if (!grn_obj2int(ctx, car)) { limit = car->u.i.i; }
-        if (limit <= 0) { limit += grn_table_size(ctx, r); }
-        POP(car, args);
-        {
-          char msg[STRBUF_SIZE];
-          uint16_t msg_size;
-          if (!obj2str(car, msg, &msg_size) && (*msg == 'd')) {
-            flags |= GRN_CURSOR_DESCENDING;
-          }
-        }
-        {
-          grn_table_cursor *tc = grn_table_cursor_open_by_id(ctx, r, offset,
-                                                             offset + limit, flags);
-          GRN_TEXT_PUTC(ctx, buf, '[');
-          for (i = 0; (id = grn_table_cursor_next(ctx, tc)); i++) {
-            if (i) { GRN_TEXT_PUTS(ctx, buf, ", "); }
-            column_exp_exec(ctx, ce, id);
-            disp_j(ctx, ce->expr, buf);
-          }
-          GRN_TEXT_PUTC(ctx, buf, ']');
-          grn_table_cursor_close(ctx, tc);
-        }
-        column_exp_close(ctx, ce);
-      }
-    }
-    break;
-  case GRN_UVECTOR :
-    {
-      column_exp *ce;
-      grn_cell *parameter, *columns;
-      grn_obj *u = car->u.p.value, *r = grn_ctx_at(ctx, u->header.domain);
-      POP(parameter, args);
-      POP(columns, args);
-      if (!PAIRP(columns)) {
-        disp_j(ctx, car, buf);
-        return;
-      }
-      if ((ce = column_exp_open(ctx, r, columns, parameter))) {
-        /*
-        POP(car, args);
-        if (!grn_obj2int(ctx, car)) { offset = car->u.i.i; }
-        POP(car, args);
-        if (!grn_obj2int(ctx, car)) { limit = car->u.i.i; }
-        */
-        {
-          int i;
-          grn_id *v = (grn_id *)GRN_BULK_HEAD(u), *ve = (grn_id *)GRN_BULK_CURR(u);
-          GRN_TEXT_PUTC(ctx, buf, '[');
-          for (i = 0; v < ve; v++, i++) {
-            if (i) { GRN_TEXT_PUTS(ctx, buf, ", "); }
-            column_exp_exec(ctx, ce, *v);
-            disp_j(ctx, ce->expr, buf);
-          }
-          GRN_TEXT_PUTC(ctx, buf, ']');
-        }
-        column_exp_close(ctx, ce);
-      }
-    }
-    break;
-  case GRN_CELL_OBJECT :
-    {
-      grn_cell *columns;
-      column_exp *ce;
-      grn_obj *r = get_domain(ctx, car);
-      POP(columns, args);
-      if (!PAIRP(columns)) {
-        disp_j(ctx, car, buf);
-        return;
-      }
-      if ((ce = column_exp_open(ctx, r, columns, NIL))) {
-        column_exp_exec(ctx, ce, car->u.o.id);
-        disp_j(ctx, ce->expr, buf);
-        column_exp_close(ctx, ce);
-      }
-    }
-    break;
-  default :
-    disp_j(ctx, car, buf);
-    if (ERRP(ctx, GRN_WARN)) { return; }
-    break;
-  }
-}
-
-static void
-disp_j(grn_ctx *ctx, grn_cell *obj, grn_obj *buf)
-{
-  if (!obj || obj == NIL) {
-    GRN_TEXT_PUTS(ctx, buf, "[]");
-  } else if (obj == T) {
-    GRN_TEXT_PUTS(ctx, buf, "true");
-  } else if (obj == F) {
-    GRN_TEXT_PUTS(ctx, buf, "false");
-  } else {
-    switch (obj->header.type) {
-    case GRN_VOID :
-      if (SYMBOLP(obj) && obj != INTERN("null")) {
-        uint16_t size = 0;
-        const char *r = _grn_hash_strkey_by_val(obj, &size);
-        if (size && (*r == ':')) {
-          r++;
-          size--;
-        }
-        grn_text_esc(ctx, buf, r, size);
-      } else {
-        GRN_TEXT_PUTS(ctx, buf, "null");
-      }
-      break;
-    case GRN_TABLE_HASH_KEY :
-    case GRN_TABLE_PAT_KEY :
-    case GRN_TABLE_NO_KEY :
-      {
-        int i;
-        grn_id id;
-        grn_cell o;
-        grn_obj *r = RVALUE(obj);
-        {
-          grn_table_cursor *tc = grn_table_cursor_open_by_id(ctx, r, 0, 0,
-                                                             GRN_CURSOR_ASCENDING);
-          GRN_TEXT_PUTC(ctx, buf, '[');
-          for (i = 0; (id = grn_table_cursor_next(ctx, tc)); i++) {
-            if (i) { GRN_TEXT_PUTS(ctx, buf, ", "); }
-            obj_obj_bind(&o, obj->u.o.id, id);
-            disp_j(ctx, &o, buf);
-            if (ERRP(ctx, GRN_WARN)) { return; }
-          }
-          GRN_TEXT_PUTC(ctx, buf, ']');
-          grn_table_cursor_close(ctx, tc);
-        }
-      }
-      break;
-    case GRN_CELL_LIST :
-      if (CAR(obj) == INTERN(":")) {
-        disp_j_with_format(ctx, CDR(obj), buf);
-        if (ERRP(ctx, GRN_WARN)) { return; }
-      } else if (CAR(obj) == INTERN("@")) {
-        int o;
-        GRN_TEXT_PUTC(ctx, buf, '{');
-        for (obj = CDR(obj), o = 0;; o = 1 - o) {
-          if (PAIRP(obj)) {
-            disp_j(ctx, CAR(obj), buf);
-            if (ERRP(ctx, GRN_WARN)) { return; }
-          }
-          if ((obj = CDR(obj)) && (obj != NIL)) {
-            if (PAIRP(obj)) {
-              GRN_TEXT_PUTS(ctx, buf, o ? ", " : ": ");
-            } else {
-              GRN_TEXT_PUTS(ctx, buf, " . ");
-              disp_j(ctx, obj, buf);
-              if (ERRP(ctx, GRN_WARN)) { return; }
-              GRN_TEXT_PUTC(ctx, buf, '}');
-              break;
-            }
-          } else {
-            GRN_TEXT_PUTC(ctx, buf, '}');
-            break;
-          }
-        }
-      } else {
-        GRN_TEXT_PUTC(ctx, buf, '[');
-        for (;;) {
-          disp_j(ctx, CAR(obj), buf);
-          if (ERRP(ctx, GRN_WARN)) { return; }
-          if ((obj = CDR(obj)) && (obj != NIL)) {
-            if (PAIRP(obj)) {
-              GRN_TEXT_PUTS(ctx, buf, ", ");
-            } else {
-              GRN_TEXT_PUTS(ctx, buf, " . ");
-              disp_j(ctx, obj, buf);
-              if (ERRP(ctx, GRN_WARN)) { return; }
-              GRN_TEXT_PUTC(ctx, buf, ']');
-              break;
-            }
-          } else {
-            GRN_TEXT_PUTC(ctx, buf, ']');
-            break;
-          }
-        }
-      }
-      break;
-    case GRN_CELL_OBJECT :
-      {
-        grn_obj key;
-        GRN_TEXT_INIT(&key, 0);
-        grn_ql_obj_key(ctx, obj, &key);
-        grn_text_esc(ctx, buf, GRN_BULK_HEAD(&key), GRN_BULK_VSIZE(&key));
-        grn_obj_close(ctx, &key);
-      }
-      break;
-    case GRN_CELL_TIME :
-      {
-        double dv= obj->u.tv.tv_sec;
-        dv += obj->u.tv.tv_nsec / GRN_TIME_NSEC_PER_SEC_F;
-        grn_text_ftoa(ctx, buf, dv);
-      }
-      break;
-    case GRN_UVECTOR :
-      {
-        grn_obj tmp;
-        GRN_TEXT_INIT(&tmp, 0);
-        uvector2str(ctx, obj->u.p.value, &tmp);
-        grn_text_esc(ctx, buf, GRN_BULK_HEAD(&tmp), GRN_BULK_VSIZE(&tmp));
-        grn_obj_close(ctx, &tmp);
-      }
-      break;
-    default :
-      grn_obj_inspect(ctx, obj, buf, GRN_OBJ_INSPECT_ESC|GRN_OBJ_INSPECT_SYMBOL_AS_STR);
-      break;
-    }
-  }
-}
-
-static void disp_t(grn_ctx *ctx, grn_cell *obj, grn_obj *buf, int *f);
-
-static void
-disp_t_with_format(grn_ctx *ctx, grn_cell *args, grn_obj *buf, int *f)
-{
-  grn_cell *car;
-  POP(car, args);
-  switch (car->header.type) {
-  case GRN_TABLE_PAT_KEY :
-  case GRN_TABLE_HASH_KEY :
-  case GRN_TABLE_NO_KEY :
-    {
-      grn_id id, base;
-      grn_cell *columns;
-      int i, offset = 0, limit = 10, flags = GRN_CURSOR_ASCENDING;
-      grn_obj *r = RVALUE(car);
-      column_exp *ce;
-      base = car->u.o.id;
-      POP(columns, args);
-      if (!PAIRP(columns)) {
-        disp_t(ctx, car, buf, f);
-        return;
-      }
-      if ((ce = column_exp_open(ctx, r, columns, NIL))) {
-        POP(car, args);
-        if (!grn_obj2int(ctx, car)) { offset = car->u.i.i; }
-        POP(car, args);
-        if (!grn_obj2int(ctx, car)) { limit = car->u.i.i; }
-        if (limit <= 0) { limit += grn_table_size(ctx, r); }
-        POP(car, args);
-        {
-          char msg[STRBUF_SIZE];
-          uint16_t msg_size;
-          if (!obj2str(car, msg, &msg_size) && (*msg == 'd')) {
-            flags |= GRN_CURSOR_DESCENDING;
-          }
-        }
-        {
-          grn_table_cursor *tc = grn_table_cursor_open_by_id(ctx, r, offset,
-                                                             offset + limit, flags);
-          for (i = 0; (id = grn_table_cursor_next(ctx, tc)); i++) {
-            if (*f) { ctx->impl->output(ctx, GRN_CTX_MORE, ctx->impl->data.ptr); *f = 0; }
-            column_exp_exec(ctx, ce, id);
-            disp_t(ctx, ce->expr, buf, f);
-          }
-          grn_table_cursor_close(ctx, tc);
-        }
-        column_exp_close(ctx, ce);
-      }
-    }
-    break;
-  case GRN_CELL_OBJECT :
-    {
-      grn_cell *columns;
-      column_exp *ce;
-      grn_obj *r = get_domain(ctx, car);
-      POP(columns, args);
-      if (!PAIRP(columns)) {
-        disp_t(ctx, car, buf, f);
-        return;
-      }
-      if ((ce = column_exp_open(ctx, r, columns, NIL))) {
-        column_exp_exec(ctx, ce, car->u.o.id);
-        disp_t(ctx, ce->expr, buf, f);
-        column_exp_close(ctx, ce);
-      }
-    }
-    break;
-  default :
-    disp_t(ctx, car, buf, f);
-    break;
-  }
-}
-
-inline static void
-bulk_tsv_esc(grn_ctx *ctx, grn_obj *buf, const char *s, int len)
-{
-  const char *e;
-  unsigned int l;
-  for (e = s + len; s < e; s += l) {
-    if (!(l = grn_charlen(ctx, s, e))) { break; }
-    if (l == 1) {
-      switch (*s) {
-      case '\t' :
-        grn_bulk_write(ctx, buf, "\\t", 2);
-        break;
-#ifdef GRN_QL_ESCAPE_NEWLINE
-      case '\n' :
-        grn_bulk_write(ctx, buf, "\\n", 2);
-        break;
-      case '\r' :
-        grn_bulk_write(ctx, buf, "\\r", 2);
-        break;
-#endif /* GRN_QL_ESCAPE_NEWLINE */
-      case '\\' :
-        grn_bulk_write(ctx, buf, "\\\\", 2);
-        break;
-      default :
-        GRN_TEXT_PUTC(ctx, buf, *s);
-      }
-    } else {
-      grn_bulk_write(ctx, buf, s, l);
-    }
-  }
-}
-
-static void
-disp_t(grn_ctx *ctx, grn_cell *obj, grn_obj *buf, int *f)
-{
-  if (!obj || obj == NIL) {
-    GRN_TEXT_PUTS(ctx, buf, "()"); *f = 1;
-  } else if (obj == T) {
-    GRN_TEXT_PUTS(ctx, buf, "#t"); *f = 1;
-  } else if (obj == F) {
-    GRN_TEXT_PUTS(ctx, buf, "#f"); *f = 1;
-  } else {
-    switch (obj->header.type) {
-    case GRN_TABLE_HASH_KEY :
-    case GRN_TABLE_PAT_KEY :
-    case GRN_TABLE_NO_KEY :
-      {
-        int i;
-        grn_id id;
-        grn_cell o;
-        grn_obj *r = RVALUE(obj);
-        grn_table_cursor *tc = grn_table_cursor_open_by_id(ctx, r, 0, 0,
-                                                           GRN_CURSOR_ASCENDING);
-        for (i = 0; (id = grn_table_cursor_next(ctx, tc)); i++) {
-          obj_obj_bind(&o, obj->u.o.id, id);
-          if (*f) { ctx->impl->output(ctx, GRN_CTX_MORE, ctx->impl->data.ptr); *f = 0; }
-          disp_t(ctx, &o, buf, f);
-        }
-        grn_table_cursor_close(ctx, tc);
-      }
-      break;
-    case GRN_CELL_LIST :
-      if (CAR(obj) == INTERN(":")) {
-        disp_t_with_format(ctx, CDR(obj), buf, f);
-      } else if (CAR(obj) == INTERN("@")) {
-        int o0, o;
-        grn_cell *val = CDR(obj);
-        for (o0 = 0; o0 <= 1; o0++) {
-          if (*f) { ctx->impl->output(ctx, GRN_CTX_MORE, ctx->impl->data.ptr); *f = 0; }
-          for (obj = val, o = o0;; o = 1 - o) {
-            if (!o) { disp_t(ctx, CAR(obj), buf, f); }
-            if ((obj = CDR(obj)) && (obj != NIL)) {
-              if (PAIRP(obj)) {
-                if (!o && PAIRP(CDR(obj))) { GRN_TEXT_PUTC(ctx, buf, '\t'); *f = 1; }
-              } else {
-                if (!o) {
-                  GRN_TEXT_PUTC(ctx, buf, '\t'); *f = 1; /* dot pair */
-                  disp_t(ctx, obj, buf, f);
-                }
-                break;
-              }
-            } else {
-              break;
-            }
-          }
-        }
-      } else {
-        grn_cell *car;
-        for (;;) {
-          POP(car, obj);
-          if (PAIRP(car)) {
-            car = grn_ql_eval(ctx, car, NIL);
-          }
-          disp_t(ctx, car, buf, f);
-          if ((obj != NIL)) {
-            if (PAIRP(obj)) {
-              GRN_TEXT_PUTC(ctx, buf, '\t'); *f = 1;
-            } else {
-              GRN_TEXT_PUTC(ctx, buf, '\t'); *f = 1; /* dot pair */
-              disp_t(ctx, obj, buf, f);
-              break;
-            }
-          } else {
-            break;
-          }
-        }
-      }
-      break;
-    case GRN_CELL_STR :
-      bulk_tsv_esc(ctx, buf, obj->u.b.value, obj->u.b.size);
-      *f = 1;
-      break;
-    case GRN_CELL_TIME :
-      {
-        double dv= obj->u.tv.tv_sec;
-        dv += obj->u.tv.tv_nsec / GRN_TIME_NSEC_PER_SEC_F;
-        grn_text_ftoa(ctx, buf, dv);
-        *f = 1;
-      }
-      break;
-    case GRN_UVECTOR :
-      uvector2str(ctx, obj->u.p.value, buf);
-      break;
-    default :
-      grn_obj_inspect(ctx, obj, buf, 0); *f = 1;
-      break;
-    }
-  }
-}
-
-inline static grn_cell *
-mk_atom(grn_ctx *ctx, char *str, unsigned int len)
-{
-  const char *cur, *str_end = str + len;
-  int64_t ivalue = grn_atoll(str, str_end, &cur);
-  if (cur == str_end) {
-    grn_cell *x;
-    GRN_CELL_NEW(ctx, x);
-    SETINT(x, ivalue);
-    return x;
-  }
-  switch (*str) {
-  case 't' :
-    if (len == 4 && !memcmp(str, "true", 4)) { return T; }
-    break;
-  case 'f' :
-    if (len == 5 && !memcmp(str, "false", 5)) { return F; }
-    break;
-    /*
-  case 'n' :
-    if (len == 4 && !memcmp(str, "null", 4)) { return NIL; }
-    break;
-    */
-  }
-  if (0 < len && len < GRN_PAT_MAX_KEY_SIZE - 1) {
-    char buf[GRN_PAT_MAX_KEY_SIZE];
-    memcpy(buf, str, len);
-    buf[len] = '\0';
-    return INTERN(buf);
-  } else {
-    return F;
-  }
-}
-
-inline static grn_cell *
-json_readstr(grn_ctx *ctx, jctx *jc)
-{
-  char *start, *end;
-  for (start = end = jc->cur;;) {
-    unsigned int len;
-    /* null check and length check */
-    if (!(len = grn_charlen(ctx, end, jc->str_end))) {
-      jc->cur = jc->str_end;
-      break;
-    }
-    if (grn_isspace(end, jc->encoding)
-        || *end == ':' || *end == ','
-        || *end == '[' || *end == '{'
-        || *end == ']' || *end == '}') {
-      jc->cur = end;
-      break;
-    }
-    end += len;
-  }
-  if (start < end || jc->cur < jc->str_end) {
-    return mk_atom(ctx, start, end - start);
-  } else {
-    return F;
-  }
-}
-
-inline static grn_cell *
-json_readstrexp(grn_ctx *ctx, jctx *jc, int keyp)
-{
-  grn_cell *res;
-  char *start, *src, *dest;
-  for (start = src = dest = jc->cur;;) {
-    unsigned int len;
-    /* null check and length check */
-    if (!(len = grn_charlen(ctx, src, jc->str_end))) {
-      jc->cur = jc->str_end;
-      if (start < dest) {
-        res = keyp
-          ? grn_ql_mk_symbol2(ctx, start, dest - start, 1)
-          : grn_ql_mk_string(ctx, start, dest - start);
-        return res ? res : F;
-      }
-      return F;
-    }
-    if (src[0] == '"' && len == 1) {
-      jc->cur = src + 1;
-      res = keyp
-        ? grn_ql_mk_symbol2(ctx, start, dest - start, 1)
-        : grn_ql_mk_string(ctx, start, dest - start);
-      return res ? res : F;
-    } else if (src[0] == '\\' && src + 1 < jc->str_end && len == 1) {
-      src++;
-      *dest++ = *src++;
-    } else {
-      while (len--) { *dest++ = *src++; }
-    }
-  }
-}
-
-static grn_cell *
-json_read(grn_ctx *ctx, jctx *jc, int keyp)
-{
-  for (;;) {
-    SKIPSPACE(jc);
-    if (jc->cur >= jc->str_end) { return NULL; }
-    switch (*jc->cur) {
-    case '[':
-      jc->cur++;
-      {
-        grn_cell *o, *r = NIL, **p = &r;
-        while ((o = json_read(ctx, jc, 0)) && o != F) {
-          *p = CONS(o, NIL);
-          if (ERRP(ctx, GRN_WARN)) { return F; }
-          p = &CDR(*p);
-        }
-        return r;
-      }
-    case '{':
-      jc->cur++;
-      {
-        grn_cell *o, *r = CONS(INTERN("@"), NIL), **p = &(CDR(r));
-        int i = 0;
-        while ((o = json_read(ctx, jc, ((++i)&1))) && o != F) {
-          *p = CONS(o, NIL);
-          if (ERRP(ctx, GRN_WARN)) { return F; }
-          p = &CDR(*p);
-        }
-        return r;
-      }
-    case '}':
-    case ']':
-      jc->cur++;
-      return NULL;
-    case ',':
-      jc->cur++;
-      break;
-    case ':':
-      jc->cur++;
-      break;
-    case '"':
-      jc->cur++;
-      return json_readstrexp(ctx, jc, keyp);
-    default:
-      return json_readstr(ctx, jc);
-    }
-  }
-}

  Deleted: lib/ql.h (+0 -433) 100644
===================================================================
--- lib/ql.h    2012-02-03 11:43:41 +0900 (b7e1bb6)
+++ /dev/null
@@ -1,433 +0,0 @@
-/* -*- c-basic-offset: 2 -*- */
-/* Copyright(C) 2009 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_QL_H
-#define GRN_QL_H
-
-#ifndef GRN_STORE_H
-#include "store.h"
-#endif /* GRN_STORE_H */
-
-#ifndef GRN_COM_H
-#include "com.h"
-#endif /* GRN_COM_H */
-
-#ifndef GRN_CTX_H
-#include "ctx.h"
-#endif /* GRN_CTX_H */
-
-#ifndef _ISOC99_SOURCE
-#define _ISOC99_SOURCE
-#endif /* _ISOC99_SOURCE */
-#if WIN32
-#define _USE_MATH_DEFINES
-#endif /* WIN32 */
-
-#include <math.h>
-
-#ifdef HAVE_MESSAGE_PACK
-#include <msgpack.h>
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**** grn_expr ****/
-
-#define GRN_EXPR_MISSING_NAME          "expr_missing"
-
-/**** grn_cell ****/
-
-/* flag values used for grn_cell.header.impl_flags */
-/* bit 0~2 are reserved */
-#define GRN_CELL_SYMBOL                (1L<<3) /* ql: registered in the symbol table */
-#define GRN_CELL_PROMISE               (1L<<4) /* ql: promise object */
-#define GRN_CELL_NATIVE                (1L<<5) /* ql: native function */
-#define GRN_CELL_MARKED                (1L<<6) /* ql: used in garbage collection */
-#define GRN_CELL_MARK2                 (1L<<7) /* ql: used in callback function */
-
-/* type values used for grn_cell.header.type */
-#define GRN_CELL_INT                   (0x70)
-#define GRN_CELL_FLOAT                 (0x71)
-#define GRN_CELL_STR                   (0x72)
-#define GRN_CELL_OP                    (0x73)
-#define GRN_CELL_OBJECT                (0x74)
-#define GRN_CELL_PROC                  (0x75)
-#define GRN_CELL_SYNTAX                (0x76)
-#define GRN_CELL_TIME                  (0x77)
-#define GRN_CELL_PSEUDO_COLUMN         (0x78)
-#define GRN_CELL_LIST                  (0x80)
-#define GRN_CELL_CLOSURE               (0x81)
-#define GRN_CELL_MACRO                 (0x82)
-#define GRN_CELL_CONTINUATION          (0x83)
-
-typedef struct _grn_ql_co grn_ql_co;
-typedef struct _grn_cell grn_cell;
-typedef grn_cell *grn_ql_native_func(grn_ctx *, grn_cell *, grn_ql_co *);
-typedef struct _grn_tmp_db_obj grn_tmp_db_obj;
-
-struct _grn_cell {
-  grn_obj_header header;
-  union {
-    struct {
-      grn_id id;
-      grn_ql_native_func *func;
-    } o;
-    struct {
-      grn_obj *value;
-      grn_ql_native_func *func;
-    } p;
-    struct {
-      char *value;
-      uint32_t size;
-    } b;
-    struct {
-      grn_cell *car;
-      grn_cell *cdr;
-    } l;
-    struct {
-      int64_t i;
-    } i;
-    struct {
-      double d;
-    } d;
-    struct {
-      int8_t op;
-      int8_t mode;
-      int16_t weight;
-      int32_t option;
-    } op;
-    grn_timeval tv;
-  } u;
-};
-
-struct _grn_ql_co {
-  uint16_t mode;
-  uint16_t last;
-  grn_ql_native_func *func;
-  void *data;
-};
-
-struct _grn_tmp_db_obj {
-  grn_db_obj *obj;
-  grn_cell cell;
-};
-
-grn_cell *grn_get(const char *key);
-grn_cell *grn_at(const char *key);
-grn_rc grn_del(const char *key);
-
-/**** grn_ctx_impl ****/
-
-typedef enum {
-  GRN_LOADER_BEGIN = 0,
-  GRN_LOADER_TOKEN,
-  GRN_LOADER_STRING,
-  GRN_LOADER_SYMBOL,
-  GRN_LOADER_NUMBER,
-  GRN_LOADER_STRING_ESC,
-  GRN_LOADER_UNICODE0,
-  GRN_LOADER_UNICODE1,
-  GRN_LOADER_UNICODE2,
-  GRN_LOADER_UNICODE3,
-  GRN_LOADER_END
-} grn_loader_stat;
-
-typedef struct {
-  grn_obj values;
-  grn_obj level;
-  grn_obj columns;
-  int32_t key_offset;
-  grn_obj *table;
-  grn_obj *last;
-  grn_obj *ifexists;
-  grn_obj *each;
-  uint32_t unichar;
-  uint32_t values_size;
-  uint32_t nrecords;
-  grn_loader_stat stat;
-  grn_content_type input_type;
-} grn_loader;
-
-#define GRN_STACK_SIZE 1024
-#define GRN_CTX_N_SEGMENTS 512
-
-#ifdef ENABLE_MEMORY_DEBUG
-typedef struct _grn_alloc_info grn_alloc_info;
-struct _grn_alloc_info
-{
-  void *address;
-  int freed;
-  char alloc_backtrace[4096];
-  char free_backtrace[4096];
-  grn_alloc_info *next;
-};
-#endif
-
-struct _grn_ctx_impl {
-  grn_encoding encoding;
-
-  /* memory pool portion */
-  int32_t lifoseg;
-  int32_t currseg;
-  grn_critical_section lock;
-  grn_io_mapinfo segs[GRN_CTX_N_SEGMENTS];
-
-#ifdef USE_DYNAMIC_MALLOC_CHANGE
-  /* memory allocation portion */
-  grn_malloc_func malloc_func;
-  grn_calloc_func calloc_func;
-  grn_realloc_func realloc_func;
-  grn_strdup_func strdup_func;
-#endif
-
-#ifdef ENABLE_MEMORY_DEBUG
-  /* memory debug portion */
-  grn_alloc_info *alloc_info;
-#endif
-
-  /* qe portion */
-  grn_obj *stack[GRN_STACK_SIZE];
-  uint32_t stack_curr;
-  grn_hash *expr_vars;
-  grn_obj *curr_expr;
-  grn_obj *qe_next;
-  void *parser;
-  grn_timeval tv;
-
-  /* loader portion */
-  grn_edge *edge;
-  grn_loader loader;
-
-  /* plugin portion */
-  const char *plugin_path;
-
-  /* output portion */
-  grn_content_type output_type;
-  const char *mime_type;
-  grn_obj names;
-  grn_obj levels;
-
-  /* command portion */
-  grn_command_version command_version;
-
-  /* match escalation portion */
-  int64_t match_escalation_threshold;
-
-  /* lifetime portion */
-  grn_proc_func *finalizer;
-
-  /* ql portion */
-  uint32_t ncells;
-  uint32_t seqno;
-  uint32_t lseqno;
-  uint32_t nbinds;
-  uint32_t nunbinds;
-  uint8_t feed_mode;
-  uint8_t batchmode;
-  uint8_t gc_verbose;
-  uint8_t op;
-  int tok;
-  char *cur;
-  char *str_end;
-  grn_cell **pht;       /* tail of placeholders */
-  grn_cell arg;         /* wait_data container (for coroutine) */
-  grn_obj *db;
-  uint32_t n_entries;
-  grn_array *objects;       /* objects */
-  grn_array *values;        /* temporary objects */
-  grn_hash *symbols;        /* symbol table */
-  grn_cell *phs;        /* list of placeholders */
-  grn_ql_co co;             /* coroutine info */
-  grn_cell *args;       /* register for arguments of function */
-  grn_cell *envir;      /* stack register for current environment */
-  grn_cell *code;       /* register for current code */
-  grn_cell *dump;       /* stack register for next evaluation */
-  grn_cell *value;      /* evaluated value */
-  grn_cell *global_env; /* global variables */
-  char *inbuf;
-  grn_obj *outbuf;
-  grn_obj subbuf;
-  unsigned int bufcur;
-  void (*output)(grn_ctx *, int, void *);
-  grn_com *com;
-  unsigned int com_status;
-  union {
-    void *ptr;
-    int fd;
-    uint32_t u32;
-    uint64_t u64;
-  } data;
-
-#ifdef HAVE_MESSAGE_PACK
-  msgpack_packer msgpacker;
-#endif
-};
-
-/**** query language ****/
-
-#define GRN_QL_CO_BEGIN(c) if (c) { switch((c)->last) { case 0:
-#define GRN_QL_CO_WAIT(c,d) \
-  (c)->last = __LINE__; (c)->data = (d); return NULL;\
-  case __LINE__: (d) = (c)->data;
-#define GRN_QL_CO_END(c) (c)->last = 0; }}
-
-#define GRN_QL_PLACEHOLDER_CHAR '?'
-
-#define GRN_QL_SET_MODE(c,m) ((c)->impl->feed_mode = (m))
-#define GRN_QL_GET_MODE(c) ((c)->impl->feed_mode)
-#define GRN_QL_GET_STAT(c) ((c)->stat)
-
-enum {
-  grn_ql_atonce = 0,
-  grn_ql_step
-};
-
-#define GRN_QL_TOPLEVEL  0x00
-#define GRN_CTX_QUITTING  0x0f
-#define GRN_QL_EVAL      0x40
-#define GRN_QL_NATIVE    0x41
-#define GRN_QL_WAIT_EXPR 0xc0
-#define GRN_QL_WAIT_ARG  0xc1
-#define GRN_QL_WAIT_DATA 0xc2
-
-#define GRN_QL_WAITINGP(c) ((c)->stat & 0x80)
-
-extern grn_cell *grn_ql_nil;  /* special cell representing empty cell */
-extern grn_cell *grn_ql_t;    /* special cell representing #t */
-extern grn_cell *grn_ql_f;    /* special cell representing #f */
-
-#define NIL grn_ql_nil
-#define T grn_ql_t
-#define F grn_ql_f
-
-void grn_ql_init_globals(grn_ctx *c);
-
-grn_cell *grn_ql_at(grn_ctx *c, const char *key);
-grn_rc grn_ql_def_db_funcs(grn_ctx *c);
-
-#define GRN_OBJ_INSPECT_ESC 1
-#define GRN_OBJ_INSPECT_SYMBOL_AS_STR 2
-
-void grn_obj_inspect(grn_ctx *c, grn_cell *obj, grn_obj *buf, int flags);
-grn_cell *grn_ql_def_native_func(grn_ctx *c, const char *name, grn_ql_native_func *func);
-grn_cell *grn_ql_feed(grn_ctx *c, char *str, uint32_t str_size, int mode);
-grn_cell *grn_ql_eval(grn_ctx *c, grn_cell *code, grn_cell *objs);
-grn_rc grn_obj2int(grn_ctx *c, grn_cell *o);
-
-const char *_grn_ql_obj_key(grn_ctx *c, grn_cell *obj, uint32_t *key_size);
-grn_obj *grn_ql_obj_key(grn_ctx *ctx, grn_cell *obj, grn_obj *value);
-grn_cell *grn_ql_mk_symbol(grn_ctx *ctx, const char *name, int name_size);
-grn_cell *grn_ql_obj_new(grn_ctx *c, grn_id domain, grn_id self);
-void grn_ql_obj_bind(grn_obj *obj, grn_cell *symbol);
-
-grn_cell *grn_ql_mk_string(grn_ctx *c, const char *str, unsigned int len);
-grn_cell *grn_ql_mk_symbol2(grn_ctx *ctx, const char *q, unsigned int len, int kwdp);
-
-grn_cell *grn_cell_new(grn_ctx *c);
-grn_cell *grn_cell_alloc(grn_ctx *c, uint32_t size);
-void grn_cell_clear(grn_ctx *c, grn_cell *o);
-grn_cell *grn_cell_cons(grn_ctx *ctx, grn_cell *a, grn_cell *b);
-void grn_ql_init_const(void);
-
-grn_rc grn_ql_obj_mark(grn_ctx *ctx, grn_cell *o);
-grn_rc grn_ql_obj_unmark(grn_ctx *ctx, grn_cell *o);
-
-grn_rc grn_ctx_mgc(grn_ctx *ctx);
-
-typedef struct _patsnip_spec patsnip_spec;
-void grn_obj_patsnip_spec_close(grn_ctx *ctx, patsnip_spec *ss);
-
-#define GRN_OBJ2VALUE(o,v,s) ((v) = (o)->u.b.value, (s) = (o)->u.b.size)
-#define GRN_VALUE2OBJ(o,v,s) ((o)->u.b.value = (v), (o)->u.b.size = (s))
-
-#define VOIDP(c) ((c) == NIL || !(c) || (c)->header.type == GRN_VOID)
-#define OBJECTP(c) ((c)->header.type == GRN_CELL_OBJECT)
-#define RECORDSP(c) ((c)->header.type == GRN_TABLE_HASH_KEY)
-#define SNIPP(c) ((c)->header.type == GRN_SNIP)
-#define BULKP(c) ((c)->header.type == GRN_CELL_STR)
-#define PAIRP(c) (((c)->header.type == GRN_CELL_LIST))
-#define LISTP(c) (PAIRP(c) || (c) == NIL)
-#define INTP(c) ((c)->header.type == GRN_CELL_INT)
-#define TABLEP(c) (GRN_TABLE_HASH_KEY <= (c)->header.type && (c)->header.type <= GRN_DB)
-#define RAW_TABLEP(c) ((c)->header.type == GRN_TYPE)
-#define NATIVE_FUNCP(c) ((c)->header.impl_flags & GRN_CELL_NATIVE)
-#define QUERYP(c) ((c)->header.type == GRN_QUERY)
-#define RA_COLUMNP(c) ((c)->header.type == GRN_COLUMN_FIX_SIZE)
-#define JA_COLUMNP(c) ((c)->header.type == GRN_COLUMN_VAR_SIZE)
-#define IDX_COLUMNP(c) ((c)->header.type == GRN_COLUMN_INDEX)
-#define COLUMNP(c) (RA_COLUMNP(c) || JA_COLUMNP(c) || IDX_COLUMNP(c))
-#define OPP(c) ((c)->header.type == GRN_CELL_OP)
-#define STRVALUE(c) ((c)->u.b.value)
-#define STRSIZE(c) ((c)->u.b.size)
-#define NUMBERP(c) ((c)->header.type == GRN_CELL_INT || (c)->header.type == GRN_CELL_FLOAT)
-#define SYMBOLP(c) ((c)->header.impl_flags & GRN_CELL_SYMBOL)
-#define CONTINUATIONP(p) ((p)->header.type == GRN_CELL_CONTINUATION)
-#define CLOSUREP(p) ((p)->header.type == GRN_CELL_CLOSURE || (p)->header.type == GRN_CELL_MACRO)
-#define PROCP(p) ((p)->header.type == GRN_CELL_PROC)
-#define PROCEDUREP(p) (PROCP(p) || CLOSUREP(p) || CONTINUATIONP(p) || NATIVE_FUNCP(p))
-
-#define SETINT(c,v) ((c)->header.type = GRN_CELL_INT, (c)->u.i.i = (v))
-#define SETFLOAT(c,v) ((c)->header.type = GRN_CELL_FLOAT, (c)->u.d.d = (v))
-#define SETBULK(c,v,s) ((c)->header.type = GRN_CELL_STR, (c)->u.b.value = (v), (c)->u.b.size = (s))
-#define SETTIME(c,v) ((c)->header.type = GRN_CELL_TIME, memcpy(&(c)->u.tv, v, sizeof(grn_timeval)))
-
-#define CAR(c)          ((c)->u.l.car)
-#define CDR(c)          ((c)->u.l.cdr)
-#define CAAR(c)         CAR(CAR(c))
-#define CADR(c)         CAR(CDR(c))
-#define CDAR(c)         CDR(CAR(c))
-#define CDDR(c)         CDR(CDR(c))
-#define CADDR(c)        CAR(CDDR(c))
-#define CADAR(p)        CAR(CDAR(p))
-#define CADAAR(p)       CAR(CDR(CAAR(p)))
-#define CADDDR(p)       CAR(CDR(CDDR(p)))
-#define CDDDDR(p)       CDR(CDR(CDDR(p)))
-
-#define IVALUE(p)       ((p)->u.i.i)
-#define FVALUE(p)       ((p)->u.d.d)
-
-#define GRN_CELL_NEW(ctx,o) do {\
-  if (!((o) = grn_cell_new(ctx))) { QLERR("obj_new failed"); }\
-} while(0)
-
-#define GRN_STR2OBJ(ctx,bulk,o) do {\
-  (o) = grn_ql_mk_string(ctx, GRN_BULK_HEAD(bulk), GRN_BULK_VSIZE(bulk));\
-} while(0)
-
-#define CONS(a,b) (grn_cell_cons(ctx, a, b))
-
-#define INTERN(s) (grn_ql_mk_symbol(ctx, s, strlen(s)))
-
-#define POP(x,c) (PAIRP(c) ? ((x) = CAR(c), (c) = CDR(c), (x)) : (x = NIL))
-
-#define SKIPSPACE(c) do {\
-  unsigned int len;\
-  while ((c)->cur < (c)->str_end && grn_isspace((c)->cur, (c)->encoding)) {\
-    if (!(len = grn_charlen(ctx, (c)->cur, (c)->str_end))) { \
-      (c)->cur = (c)->str_end;\
-      break;\
-    }\
-    (c)->cur += len;\
-  }\
-} while (0)
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* GRN_QL_H */

  Deleted: lib/query.c (+0 -842) 100644
===================================================================
--- lib/query.c    2012-02-03 11:43:41 +0900 (cc28bb3)
+++ /dev/null
@@ -1,842 +0,0 @@
-/* -*- c-basic-offset: 2 -*- */
-/* Copyright(C) 2009 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
-*/
-
-#include "groonga_in.h"
-#include <string.h>
-#include <ctype.h>
-#include "snip.h"
-#include "ql.h"
-#include "hash.h"
-#include "ii.h"
-
-/* query string parser and executor */
-
-#define DEFAULT_WEIGHT 5
-#define DEFAULT_DECAYSTEP 2
-#define DEFAULT_MAX_INTERVAL 10
-#define DEFAULT_SIMILARITY_THRESHOLD 10
-#define DEFAULT_TERM_EXTRACT_POLICY 0
-#define DEFAULT_WEIGHT_VECTOR_SIZE 4096
-
-struct _grn_query {
-  grn_obj_header header;
-  char *str;
-  char *cur;
-  char *str_end;
-  grn_operator default_op;
-  grn_select_optarg opt;
-  grn_operator default_mode;
-  int escalation_threshold;
-  int escalation_decaystep;
-  int weight_offset;
-  grn_hash *weight_set;
-  grn_encoding encoding;
-  grn_cell *expr;
-  int max_exprs;
-  int cur_expr;
-  int max_cells;
-  int cur_cell;
-  snip_cond *snip_conds;
-  grn_cell cell_pool[1]; /* dummy */
-};
-
-inline static grn_cell *
-cell_new(grn_query *q)
-{
-  if (q->cur_cell <= q->max_cells) {
-    grn_cell *c = &q->cell_pool[q->cur_cell++];
-    return c;
-  }
-  return NULL;
-}
-
-inline static void
-cell_del(grn_query *q)
-{
-  if (q->cur_cell > 0) { q->cur_cell--; }
-}
-
-inline static grn_cell *
-cons(grn_query *q, grn_cell *car, grn_cell *cdr)
-{
-  grn_cell *c;
-  if ((c = cell_new(q))) {
-    c->header.type = GRN_CELL_LIST;
-    c->u.l.car = car;
-    c->u.l.cdr = cdr;
-    return c;
-  } else {
-    return NIL;
-  }
-}
-
-inline static grn_cell *
-token_new(grn_query *q, const char *start, const char *end)
-{
-  grn_cell *c;
-  if (start >= end) { return NIL; }
-  if ((c = cell_new(q))) {
-    unsigned int len = end - start;
-    c->header.type = GRN_CELL_STR;
-    c->u.b.value = (char *)start;
-    c->u.b.size = len;
-    q->cur_expr++;
-    return c;
-  } else {
-    return NIL;
-  }
-}
-
-inline static grn_cell *
-op_new(grn_query *q, int8_t op, int16_t weight, int8_t mode, int32_t option)
-{
-  grn_cell *c;
-  if ((c = cell_new(q))) {
-    c->header.type = GRN_CELL_OP;
-    c->u.op.op = op;
-    c->u.op.weight = weight;
-    c->u.op.mode = mode;
-    c->u.op.option = option;
-    return c;
-  } else {
-    return NIL;
-  }
-}
-
-inline static void
-skip_space(grn_ctx *ctx, grn_query *q)
-{
-  unsigned int len;
-  while (q->cur < q->str_end && grn_isspace(q->cur, q->encoding)) {
-    /* null check and length check */
-    if (!(len = grn_charlen(ctx, q->cur, q->str_end))) {
-      q->cur = q->str_end;
-      break;
-    }
-    q->cur += len;
-  }
-}
-
-inline static grn_cell *
-get_phrase(grn_ctx *ctx, grn_query *q)
-{
-  char *start, *s, *d;
-  start = s = d = q->cur;
-  while (1) {
-    unsigned int len;
-    if (s >= q->str_end) {
-      q->cur = s;
-      break;
-    }
-    len = grn_charlen(ctx, s, q->str_end);
-    if (len == 0) {
-      /* invalid string containing malformed multibyte char */
-      return NULL;
-    } else if (len == 1) {
-      if (*s == GRN_QUERY_QUOTER) {
-        q->cur = s + 1;
-        break;
-      } else if (*s == GRN_QUERY_ESCAPE && s + 1 < q->str_end) {
-        s++;
-        len = grn_charlen(ctx, s, q->str_end);
-      }
-    }
-    while (len--) { *d++ = *s++; }
-  }
-  return token_new(q, start, d);
-}
-
-inline static grn_cell *
-get_word(grn_ctx *ctx, grn_query *q, int *prefixp)
-{
-  char *start = q->cur, *end;
-  unsigned int len;
-  for (end = q->cur;; ) {
-    /* null check and length check */
-    if (!(len = grn_charlen(ctx, end, q->str_end))) {
-      q->cur = q->str_end;
-      break;
-    }
-    if (grn_isspace(end, q->encoding) ||
-        *end == GRN_QUERY_PARENR) {
-      q->cur = end;
-      break;
-    }
-    if (*end == GRN_QUERY_PREFIX) {
-      *prefixp = 1;
-      q->cur = end + 1;
-      break;
-    }
-    end += len;
-  }
-  return token_new(q, start, end);
-}
-
-inline static grn_cell *
-get_op(grn_query *q, grn_operator op, int weight)
-{
-  char *start, *end = q->cur;
-  int mode, option;
-  switch (*end) {
-  case 'S' :
-    mode = GRN_OP_SIMILAR;
-    start = ++end;
-    option = grn_atoi(start, q->str_end, (const char **)&end);
-    if (start == end) { option = DEFAULT_SIMILARITY_THRESHOLD; }
-    q->cur = end;
-    break;
-  case 'N' :
-    mode = GRN_OP_NEAR;
-    start = ++end;
-    option = grn_atoi(start, q->str_end, (const char **)&end);
-    if (start == end) { option = DEFAULT_MAX_INTERVAL; }
-    q->cur = end;
-    break;
-  case 'n' :
-    mode = GRN_OP_NEAR2;
-    start = ++end;
-    option = grn_atoi(start, q->str_end, (const char **)&end);
-    if (start == end) { option = DEFAULT_MAX_INTERVAL; }
-    q->cur = end;
-    break;
-  case 'T' :
-    mode = GRN_OP_TERM_EXTRACT;
-    start = ++end;
-    option = grn_atoi(start, q->str_end, (const char **)&end);
-    if (start == end) { option = DEFAULT_TERM_EXTRACT_POLICY; }
-    q->cur = end;
-    break;
-  case 'X' : /* force exact mode */
-    op = GRN_OP_AND;
-    mode = GRN_OP_EXACT;
-    option = 0;
-    start = ++end;
-    q->cur = end;
-    break;
-  default :
-    return NIL;
-  }
-  return op_new(q, op, weight, mode, option);
-}
-
-static grn_cell *get_expr(grn_ctx *ctx, grn_query *q);
-
-inline static grn_cell *
-get_token(grn_ctx *ctx, grn_query *q)
-{
-  grn_cell *token = NIL;
-  grn_operator op = q->default_op;
-  {
-    int weight = DEFAULT_WEIGHT, prefixp = 0, mode = -1, option = 0;
-    skip_space(ctx, q);
-    if (q->cur_expr >= q->max_exprs ||
-        q->cur_cell >= q->max_cells ||
-        q->cur >= q->str_end) { return NIL; }
-    switch (*q->cur) {
-    case '\0' :
-      return NIL;
-    case GRN_QUERY_PARENR :
-      q->cur++;
-      return NIL;
-    case GRN_QUERY_QUOTEL :
-      q->cur++;
-      if ((token = get_phrase(ctx, q)) == NULL) {
-	return NIL;
-      }
-      break;
-    case GRN_QUERY_PREFIX :
-      q->cur++;
-      token = get_op(q, op, weight);
-      break;
-    case GRN_QUERY_AND :
-      q->cur++;
-      token = op_new(q, GRN_OP_AND, weight, mode, option);
-      break;
-    case GRN_QUERY_BUT :
-      q->cur++;
-      token = op_new(q, GRN_OP_BUT, weight, mode, option);
-      break;
-    case GRN_QUERY_ADJ_INC :
-      q->cur++;
-      if (weight < 127) { weight++; }
-      token = op_new(q, GRN_OP_ADJUST, weight, mode, option);
-      break;
-    case GRN_QUERY_ADJ_DEC :
-      q->cur++;
-      if (weight > -128) { weight--; }
-      token = op_new(q, GRN_OP_ADJUST, weight, mode, option);
-      break;
-    case GRN_QUERY_ADJ_NEG :
-      q->cur++;
-      token = op_new(q, GRN_OP_ADJUST, -1, mode, option);
-      break;
-    case GRN_QUERY_PARENL :
-      q->cur++;
-      token = get_expr(ctx, q);
-      break;
-    default :
-      if ((token = get_word(ctx, q, &prefixp)) &&
-          token->u.b.value[0] == 'O' &&
-          token->u.b.value[1] == 'R' &&
-          token->u.b.size == 2) {
-        cell_del(q);
-        q->cur_expr--;
-        token = op_new(q, GRN_OP_OR, weight, mode, option);
-      }
-      break;
-    }
-  }
-  return cons(q, token, NIL);
-}
-
-static grn_cell *
-get_expr(grn_ctx *ctx, grn_query *q)
-{
-  grn_cell *r, *c, *c_;
-  for (c = r = get_token(ctx, q); c != NIL; c = c_) {
-    c_ = c->u.l.cdr = get_token(ctx, q);
-  }
-  return r;
-}
-
-static const char *
-get_weight_vector(grn_ctx *ctx, grn_query *query, const char *source)
-{
-  const char *p;
-
-  if (!query->opt.weight_vector &&
-      !query->weight_set &&
-      !(query->opt.weight_vector = GRN_CALLOC(sizeof(int) * DEFAULT_WEIGHT_VECTOR_SIZE))) {
-    GRN_LOG(ctx, GRN_LOG_ALERT, "get_weight_vector malloc fail");
-    return source;
-  }
-  for (p = source; p < query->str_end; ) {
-    unsigned int key;
-    int value;
-
-    /* key, key is not zero */
-    key = grn_atoui(p, query->str_end, &p);
-    if (!key || key > GRN_ID_MAX) { break; }
-
-    /* value */
-    if (*p == ':') {
-      p++;
-      value = grn_atoi(p, query->str_end, &p);
-    } else {
-      value = 1;
-    }
-
-    if (query->weight_set) {
-      int *pval;
-      if (grn_hash_add(ctx, query->weight_set, &key, sizeof(unsigned int), (void **)&pval, NULL)) {
-        *pval = value;
-      }
-    } else if (key < DEFAULT_WEIGHT_VECTOR_SIZE) {
-      query->opt.weight_vector[key - 1] = value;
-    } else {
-      GRN_FREE(query->opt.weight_vector);
-      query->opt.weight_vector = NULL;
-      if (!(query->weight_set = grn_hash_create(ctx, NULL, sizeof(unsigned int), sizeof(int),
-                                                0))) {
-        return source;
-      }
-      p = source;           /* reparse */
-      continue;
-    }
-    if (*p != ',') { break; }
-    p++;
-  }
-  return p;
-}
-
-inline static void
-get_pragma(grn_ctx *ctx, grn_query *q)
-{
-  char *start, *end = q->cur;
-  while (end < q->str_end && *end == GRN_QUERY_PREFIX) {
-    if (++end >= q->str_end) { break; }
-    switch (*end) {
-    case 'E' :
-      start = ++end;
-      q->escalation_threshold = grn_atoi(start, q->str_end, (const char **)&end);
-      while (end < q->str_end && (isdigit(*end) || *end == '-')) { end++; }
-      if (*end == ',') {
-        start = ++end;
-        q->escalation_decaystep = grn_atoi(start, q->str_end, (const char **)&end);
-      }
-      q->cur = end;
-      break;
-    case 'D' :
-      start = ++end;
-      while (end < q->str_end && *end != GRN_QUERY_PREFIX && !grn_isspace(end, q->encoding)) {
-        end++;
-      }
-      if (end > start) {
-        switch (*start) {
-        case 'O' :
-          q->default_op = GRN_OP_OR;
-          break;
-        case GRN_QUERY_AND :
-          q->default_op = GRN_OP_AND;
-          break;
-        case GRN_QUERY_BUT :
-          q->default_op = GRN_OP_BUT;
-          break;
-        case GRN_QUERY_ADJ_INC :
-          q->default_op = GRN_OP_ADJUST;
-          break;
-        }
-      }
-      q->cur = end;
-      break;
-    case 'W' :
-      start = ++end;
-      end = (char *)get_weight_vector(ctx, q, start);
-      q->cur = end;
-      break;
-    }
-  }
-}
-
-static int
-section_weight_cb(grn_ctx *ctx, grn_hash *r, const void *rid, int sid, void *arg)
-{
-  int *w;
-  grn_hash *s = (grn_hash *)arg;
-  if (s && grn_hash_get(ctx, s, &sid, sizeof(grn_id), (void **)&w)) {
-    return *w;
-  } else {
-    return 0;
-  }
-}
-
-grn_query *
-grn_query_open(grn_ctx *ctx, const char *str, unsigned int str_len,
-               grn_operator default_op, int max_exprs)
-{
-  grn_query *q;
-  int max_cells = max_exprs * 4;
-  if (!(q = GRN_MALLOC(sizeof(grn_query) + max_cells * sizeof(grn_cell) + str_len + 1))) {
-    GRN_LOG(ctx, GRN_LOG_ALERT, "grn_query_open malloc fail");
-    return NULL;
-  }
-  q->header.type = GRN_QUERY;
-  q->str = (char *)&q->cell_pool[max_cells];
-  memcpy(q->str, str, str_len);
-  q->str[str_len] = '\0';
-  q->cur = q->str;
-  q->str_end = q->str + str_len;
-  q->default_op = default_op;
-  q->encoding = ctx->encoding;
-  q->max_exprs = max_exprs;
-  q->max_cells = max_cells;
-  q->cur_cell = 0;
-  q->cur_expr = 0;
-  q->escalation_threshold = GRN_DEFAULT_MATCH_ESCALATION_THRESHOLD;
-  q->escalation_decaystep = DEFAULT_DECAYSTEP;
-  q->weight_offset = 0;
-  q->opt.weight_vector = NULL;
-  q->weight_set = NULL;
-  get_pragma(ctx, q);
-  q->expr = get_expr(ctx, q);
-  q->opt.vector_size = DEFAULT_WEIGHT_VECTOR_SIZE;
-  q->opt.func = q->weight_set ? section_weight_cb : NULL;
-  q->opt.func_arg = q->weight_set;
-  q->snip_conds = NULL;
-  return q;
-}
-
-unsigned int
-grn_query_rest(grn_ctx *ctx, grn_query *q, const char ** const rest)
-{
-  if (!q) { return 0; }
-  if (rest) {
-    *rest = q->cur;
-  }
-  return (unsigned int)(q->str_end - q->cur);
-}
-
-grn_rc
-grn_query_close(grn_ctx *ctx, grn_query *q)
-{
-  if (!q) { return GRN_INVALID_ARGUMENT; }
-  if (q->opt.weight_vector) {
-    GRN_FREE(q->opt.weight_vector);
-  }
-  if (q->weight_set) {
-    grn_hash_close(ctx, q->weight_set);
-  }
-  if (q->snip_conds) {
-    snip_cond *sc;
-    for (sc = q->snip_conds; sc < q->snip_conds + q->cur_expr; sc++) {
-      grn_snip_cond_close(ctx, sc);
-    }
-    GRN_FREE(q->snip_conds);
-  }
-  GRN_FREE(q);
-  return GRN_SUCCESS;
-}
-
-/* FIXME: for test */
-grn_rc
-grn_query_str(grn_query *q, const char **str, unsigned int *len)
-{
-  if (str) { *str = q->str; }
-  if (len) { *len = q->str_end - q->str; }
-  return GRN_SUCCESS;
-}
-
-static void
-scan_keyword(snip_cond *sc, grn_str *str, grn_id section,
-             grn_operator op, grn_select_optarg *optarg,
-             int *found, int *score)
-{
-  int tf;
-  int w = 1;
-  for (tf = 0; ; tf++) {
-    grn_bm_tunedbm(sc, str, 0);
-    if (sc->stopflag == SNIPCOND_STOP) { break; }
-  }
-  if (optarg->vector_size) {
-    if (!optarg->weight_vector) {
-      w = optarg->vector_size;
-    } else if (section) {
-      w = (section <= optarg->vector_size ?
-                      optarg->weight_vector[section - 1] : 0);
-    }
-  }
-  switch (op) {
-  case GRN_OP_OR :
-    if (tf) {
-      *found = 1;
-      *score += w * tf;
-    }
-    break;
-  case GRN_OP_AND :
-    if (tf) {
-      *score += w * tf;
-    } else {
-      *found = 0;
-    }
-    break;
-  case GRN_OP_BUT :
-    if (tf) {
-      *found = 0;
-    }
-    break;
-  case GRN_OP_ADJUST :
-    *score += w * tf;
-  default :
-    break;
-  }
-}
-
-/* TODO: delete overlapping logic with exec_query */
-static grn_rc
-scan_query(grn_ctx *ctx, grn_query *q, grn_str *nstr, grn_id section, grn_cell *c, snip_cond **sc,
-           grn_operator op, int flags, int *found, int *score)
-{
-  int _found = 0, _score = 0;
-  grn_cell *e, *ope = NIL;
-  grn_operator op0 = GRN_OP_OR, *opp = &op0, op1 = q->default_op;
-  while (c != NIL) {
-    POP(e, c);
-    switch (e->header.type) {
-    case GRN_CELL_OP :
-      if (opp == &op0 && e->u.op.op == GRN_OP_BUT) {
-        POP(e, c);
-      } else {
-        ope = e;
-        op1 = ope->u.op.op;
-      }
-      continue;
-    case GRN_CELL_STR :
-      if (ope != NIL) {
-        q->opt.mode = ope->u.op.mode == -1 ? q->default_mode : ope->u.op.mode;
-        q->opt.max_interval = q->opt.similarity_threshold = ope->u.op.option;
-        if (!q->opt.weight_vector) {
-          q->opt.vector_size = ope->u.op.weight + q->weight_offset;
-        }
-      } else {
-        q->opt.mode = q->default_mode;
-        q->opt.max_interval = DEFAULT_MAX_INTERVAL;
-        q->opt.similarity_threshold = DEFAULT_SIMILARITY_THRESHOLD;
-        if (!q->opt.weight_vector) {
-          q->opt.vector_size = DEFAULT_WEIGHT + q->weight_offset;
-        }
-      }
-      if ((flags & GRN_QUERY_SCAN_ALLOCCONDS)) {
-        grn_rc rc;
-        /* NOTE: GRN_SNIP_NORMALIZE = GRN_QUERY_SCAN_NORMALIZE */
-        if ((rc = grn_snip_cond_init(ctx, *sc, e->u.b.value, e->u.b.size,
-                                     q->encoding, flags & GRN_SNIP_NORMALIZE))) {
-          return rc;
-        }
-      } else {
-        grn_snip_cond_reinit(*sc);
-      }
-      scan_keyword(*sc, nstr, section, *opp, &q->opt, &_found, &_score);
-      (*sc)++;
-      break;
-    case GRN_CELL_LIST :
-      scan_query(ctx, q, nstr, section, e, sc, *opp, flags, &_found, &_score);
-      break;
-    default :
-      GRN_LOG(ctx, GRN_LOG_NOTICE, "invalid object assigned in query! (%d)", e->header.type);
-      break;
-    }
-    opp = &op1;
-    ope = NIL;
-    op1 = q->default_op;
-  }
-  switch (op) {
-  case GRN_OP_OR :
-    *found |= _found;
-    *score += _score;
-    break;
-  case GRN_OP_AND :
-    *found &= _found;
-    *score += _score;
-    break;
-  case GRN_OP_BUT :
-    *found &= !_found;
-    break;
-  case GRN_OP_ADJUST :
-    *score += _score;
-    break;
-  default :
-    break;
-  }
-  return GRN_SUCCESS;
-}
-
-static grn_rc
-alloc_snip_conds(grn_ctx *ctx, grn_query *q)
-{
-  if (!(q->snip_conds = GRN_CALLOC(sizeof(snip_cond) * q->cur_expr))) {
-    GRN_LOG(ctx, GRN_LOG_ALERT, "snip_cond allocation failed");
-    return GRN_NO_MEMORY_AVAILABLE;
-  }
-  return GRN_SUCCESS;
-}
-
-grn_rc
-grn_query_scan(grn_ctx *ctx, grn_query *q, const char **strs, unsigned int *str_lens, unsigned int nstrs,
-               int flags, int *found, int *score)
-{
-  unsigned int i;
-  grn_rc rc;
-  if (!q || !strs || !nstrs) { return GRN_INVALID_ARGUMENT; }
-  *found = *score = 0;
-  if (!q->snip_conds) {
-    if ((rc = alloc_snip_conds(ctx, q))) { return rc; }
-    flags |= GRN_QUERY_SCAN_ALLOCCONDS;
-  } else if (flags & GRN_QUERY_SCAN_ALLOCCONDS) {
-    GRN_LOG(ctx, GRN_LOG_WARNING, "invalid flags specified on grn_query_scan");
-    return GRN_INVALID_ARGUMENT;
-  }
-  for (i = 0; i < nstrs; i++) {
-    grn_str *n;
-    snip_cond *sc = q->snip_conds;
-    int f = GRN_STR_WITH_CHECKS | GRN_STR_REMOVEBLANK;
-    if (flags & GRN_QUERY_SCAN_NORMALIZE) { f |= GRN_STR_NORMALIZE; }
-    n = grn_str_open(ctx, *(strs + i), *(str_lens + i), f);
-    if (!n) { return GRN_NO_MEMORY_AVAILABLE; }
-    if ((rc = scan_query(ctx, q, n, i + 1, q->expr, &sc, GRN_OP_OR, flags, found, score))) {
-      grn_str_close(ctx, n);
-      return rc;
-    }
-    flags &= ~GRN_QUERY_SCAN_ALLOCCONDS;
-    grn_str_close(ctx, n);
-  }
-  return GRN_SUCCESS;
-}
-
-/* TODO: delete overlapping logic with exec_query */
-static grn_rc
-snip_query(grn_ctx *ctx, grn_query *q, grn_snip *snip, grn_cell *c, grn_operator op,
-           unsigned int n_tags, int c_but,
-           const char **opentags, unsigned int *opentag_lens,
-           const char **closetags, unsigned int *closetag_lens)
-{
-  grn_cell *e, *ope = NIL;
-  grn_operator op0 = GRN_OP_OR, *opp = &op0, op1 = q->default_op;
-  while (c != NIL) {
-    POP(e, c);
-    switch (e->header.type) {
-    case GRN_CELL_OP :
-      ope = e;
-      op1 = ope->u.op.op;
-      continue;
-    case GRN_CELL_STR :
-      if (ope != NIL) {
-        q->opt.mode = ope->u.op.mode == -1 ? q->default_mode : ope->u.op.mode;
-      } else {
-        q->opt.mode = q->default_mode;
-      }
-      if (!(c_but ^ (*opp == GRN_OP_BUT))) {
-        grn_rc rc;
-        unsigned int i = snip->cond_len % n_tags;
-        if ((rc = grn_snip_add_cond(ctx, snip, e->u.b.value, e->u.b.size,
-                                    opentags[i], opentag_lens[i],
-                                    closetags[i], closetag_lens[i]))) {
-          return rc;
-        }
-      }
-      break;
-    case GRN_CELL_LIST :
-      snip_query(ctx, q, snip, e, *opp, n_tags, (*opp == GRN_OP_BUT) ? c_but ^ 1 : c_but,
-                 opentags, opentag_lens, closetags, closetag_lens);
-      break;
-    default :
-      GRN_LOG(ctx, GRN_LOG_NOTICE, "invalid object assigned in query!! (%d)", e->header.type);
-      break;
-    }
-    opp = &op1;
-    ope = NIL;
-    op1 = q->default_op;
-  }
-  return GRN_SUCCESS;
-}
-
-grn_snip *
-grn_query_snip(grn_ctx *ctx, grn_query *query, int flags,
-               unsigned int width, unsigned int max_results,
-               unsigned int n_tags,
-               const char **opentags, unsigned int *opentag_lens,
-               const char **closetags, unsigned int *closetag_lens,
-               grn_snip_mapping *mapping)
-{
-  grn_snip *res;
-  if (!(res = grn_snip_open(ctx, flags, width, max_results,
-                            NULL, 0, NULL, 0, mapping))) {
-    return NULL;
-  }
-  if (snip_query(ctx, query, res, query->expr, GRN_OP_OR, n_tags, 0,
-                 opentags, opentag_lens, closetags, closetag_lens)) {
-    grn_snip_close(ctx, res);
-    return NULL;
-  }
-  return res;
-}
-
-static void
-exec_search(grn_ctx *ctx, grn_ii *i, grn_query *q, grn_cell *c,
-            grn_hash *r, grn_operator op)
-{
-  grn_hash *s;
-  grn_cell *e, *ope = NIL;
-  int n = *r->n_entries;
-  grn_operator op0 = GRN_OP_OR, *opp = &op0, op1 = q->default_op;
-  if (!n && op != GRN_OP_OR) { return; }
-  if (n) {
-    s = grn_hash_create(ctx, NULL, r->key_size, r->value_size, r->obj.header.flags);
-    s->obj.header.impl_flags = 0;
-    s->obj.header.domain = r->obj.header.domain;
-    s->obj.range = r->obj.range;
-    s->obj.max_n_subrecs = r->obj.max_n_subrecs;
-    s->obj.subrec_size = r->obj.subrec_size;
-    s->obj.subrec_offset = r->obj.subrec_offset;
-    s->obj.id = r->obj.id;
-    s->obj.db = r->obj.db;
-    s->obj.source = r->obj.source;
-    s->obj.source_size = r->obj.source_size;
-    /*
-    grn_hook_entry entry;
-    for (entry = 0; entry < N_HOOK_ENTRIES; entry++) {
-      s->obj.hooks[entry] = NULL;
-    }
-    */
-  } else {
-    s = r;
-  }
-  while (c != NIL) {
-    POP(e, c);
-    switch (e->header.type) {
-    case GRN_CELL_OP :
-      if (opp == &op0 && e->u.op.op == GRN_OP_BUT) {
-        POP(e, c);
-      } else {
-        ope = e;
-        op1 = ope->u.op.op;
-      }
-      continue;
-    case GRN_CELL_STR :
-      if (ope != NIL) {
-        q->opt.mode = ope->u.op.mode == -1 ? q->default_mode : ope->u.op.mode;
-        q->opt.max_interval = q->opt.similarity_threshold = ope->u.op.option;
-        if (!q->opt.weight_vector) {
-          q->opt.vector_size = ope->u.op.weight + q->weight_offset;
-        }
-        if (ope->u.op.mode == GRN_OP_SIMILAR) {
-          q->opt.max_interval = q->default_mode;
-        }
-      } else {
-        q->opt.mode = q->default_mode;
-        q->opt.max_interval = DEFAULT_MAX_INTERVAL;
-        q->opt.similarity_threshold = DEFAULT_SIMILARITY_THRESHOLD;
-        if (!q->opt.weight_vector) {
-          q->opt.vector_size = DEFAULT_WEIGHT + q->weight_offset;
-        }
-      }
-      if (grn_ii_select(ctx, i, e->u.b.value, e->u.b.size, s, *opp, &q->opt)) {
-        GRN_LOG(ctx, GRN_LOG_ERROR, "grn_inv_select on exec_search failed !");
-        return;
-      }
-      break;
-    case GRN_CELL_LIST :
-      exec_search(ctx, i, q, e, s, *opp);
-      break;
-    default :
-      GRN_LOG(ctx, GRN_LOG_NOTICE, "invalid object assigned in query (%d)", e->header.type);
-      break;
-    }
-    opp = &op1;
-    ope = NIL;
-    op1 = q->default_op;
-  }
-  if (n) {
-    grn_table_setoperation(ctx, (grn_obj *)r, (grn_obj *)s, (grn_obj *)r, op);
-    grn_hash_close(ctx, s);
-  }
-}
-
-grn_rc
-grn_query_search(grn_ctx *ctx, grn_ii *i, grn_query *q, grn_hash *r, grn_operator op)
-{
-  int p = q->escalation_threshold;
-  // dump_query(q, q->expr, 0);
-  // grn_log("escalation_threshold=%d", p);
-  if (p >= 0 || (-p & 1)) {
-    q->default_mode = GRN_OP_EXACT;
-    exec_search(ctx, i, q, q->expr, r, op);
-    GRN_LOG(ctx, GRN_LOG_INFO, "hits(exact)=%d", *r->n_entries);
-  }
-  if ((p >= 0) ? (p >= *r->n_entries) : (-p & 2)) {
-    q->weight_offset -= q->escalation_decaystep;
-    q->default_mode = GRN_OP_UNSPLIT;
-    exec_search(ctx, i, q, q->expr, r, op);
-    GRN_LOG(ctx, GRN_LOG_INFO, "hits(unsplit)=%d", *r->n_entries);
-  }
-  if ((p >= 0) ? (p >= *r->n_entries) : (-p & 4)) {
-    q->weight_offset -= q->escalation_decaystep;
-    q->default_mode = GRN_OP_PARTIAL;
-    exec_search(ctx, i, q, q->expr, r, op);
-    GRN_LOG(ctx, GRN_LOG_INFO, "hits(partial)=%d", *r->n_entries);
-  }
-  return GRN_SUCCESS;
-}

  Deleted: lib/scm.c (+0 -3494) 100644
===================================================================
--- lib/scm.c    2012-02-03 11:43:41 +0900 (47233f0)
+++ /dev/null
@@ -1,3494 +0,0 @@
-/* -*- c-basic-offset: 2 -*- */
-/*
-  Copyright(C) 2009-2012 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
-*/
-
-/*  Groonga Query Language is based on Mini-Scheme, original credits follow  */
-
-/*
- *      ---------- Mini-Scheme Interpreter Version 0.85 ----------
- *
- *                coded by Atsushi Moriwaki (11/5/1989)
- *
- *            E-MAIL :  moriw****@kurim*****
- *
- *               THIS SOFTWARE IS IN THE PUBLIC DOMAIN
- *               ------------------------------------
- * This software is completely free to copy, modify and/or re-distribute.
- * But I would appreciate it if you left my name on the code as the author.
- *
- */
-/*--
- *
- *  This version has been modified by R.C. Secrist.
- *
- *  Mini-Scheme is now maintained by Akira KIDA.
- *
- *  This is a revised and modified version by Akira KIDA.
- *  current version is 0.85k4 (15 May 1994)
- *
- *  Please send suggestions, bug reports and/or requests to:
- *    <SDI00****@nifty*****>
- *--
- */
-
-#include "groonga_in.h"
-#include <fcntl.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include "ql.h"
-
-#ifdef stat
-#  undef stat
-#endif /* stat */
-
-#define InitFile "init.scm"
-
-/* global variables */
-
-grn_cell *grn_ql_nil;  /* special cell representing empty cell */
-grn_cell *grn_ql_t;    /* special cell representing #t */
-grn_cell *grn_ql_f;    /* special cell representing #f */
-
-/* sen query language */
-
-/* todo : update set-car! set-cdr!
-
-inline static void
-obj_ref(grn_cell *o)
-{
-  if (o->nrefs < 0xffff) { o->nrefs++; }
-  if (PAIRP(o)) { // todo : check cycle
-    if (CAR(o) != NIL) { obj_ref(CAR(o)); }
-    if (CDR(o) != NIL) { obj_ref(CDR(o)); }
-  }
-}
-
-inline static void
-obj_unref(grn_cell *o)
-{
-  if (!o->nrefs) {
-    GRN_LOG(ctx, GRN_LOG_ERROR, "o->nrefs corrupt");
-    return;
-  }
-  if (o->nrefs < 0xffff) { o->nrefs--; }
-  if (PAIRP(o)) { // todo : check cycle
-    if (CAR(o) != NIL) { obj_unref(CAR(o)); }
-    if (CDR(o) != NIL) { obj_unref(CDR(o)); }
-  }
-}
-
-inline static void
-rplaca(grn_ctx *ctx, grn_cell *a, grn_cell *b)
-{
-  if (a->nrefs) {
-    ctx->impl->nbinds++;
-    if (a->u.l.car) {
-      ctx->impl->nunbinds++;
-      obj_unref(a->u.l.car);
-    }
-    if (b) { obj_ref(b); }
-  }
-  a->u.l.car = b;
-}
-
-inline static void
-rplacd(grn_ctx *ctx, grn_cell *a, grn_cell *b)
-{
-  if (a->nrefs) {
-    ctx->impl->nbinds++;
-    if (a->u.l.cdr) {
-      ctx->impl->nunbinds++;
-      obj_unref(a->u.l.cdr);
-    }
-    if (b) { obj_ref(b); }
-  }
-  a->u.l.cdr = b;
-}
-
-*/
-
-grn_rc
-grn_obj2int(grn_ctx *ctx, grn_cell *o)
-{
-  grn_rc rc = GRN_INVALID_ARGUMENT;
-  if (o) {
-    switch (o->header.type) {
-    case GRN_CELL_STR :
-      if (o->u.b.size) {
-        const char *end = o->u.b.value + o->u.b.size, *rest;
-        int64_t i = grn_atoll(o->u.b.value, end, &rest);
-        if (rest == end) {
-          grn_cell_clear(ctx, o);
-          SETINT(o, i);
-          rc = GRN_SUCCESS;
-        }
-      }
-      break;
-    case GRN_CELL_INT :
-      rc = GRN_SUCCESS;
-      break;
-    default :
-      break;
-    }
-  }
-  return rc;
-}
-
-static void
-symbol2str(void *x, char *buf)
-{
-  uint16_t symname_size;
-  const char *symname = _grn_hash_strkey_by_val(x, &symname_size);
-  memcpy(buf, symname, symname_size);
-  buf[symname_size] = '\0';
-}
-
-static int
-keywordp(void *x)
-{
-  uint16_t symname_size;
-  const char *symname = _grn_hash_strkey_by_val(x, &symname_size);
-  return symname_size && *symname == ':';
-}
-
-/* get new symbol */
-grn_cell *
-grn_ql_mk_symbol(grn_ctx *ctx, const char *name, int name_size)
-{
-  grn_cell *x;
-  if (!grn_hash_add(ctx, ctx->impl->symbols, name, name_size, (void **) &x, NULL)) {
-    return F;
-  }
-  if (!x->header.impl_flags) {
-    x->header.impl_flags |= GRN_CELL_SYMBOL;
-    x->header.type = GRN_VOID;
-  }
-  if (x->header.type == GRN_VOID && ctx->impl->db) {
-    uint16_t symname_size;
-    const char *symname = _grn_hash_strkey_by_val(x, &symname_size);
-    grn_obj *obj = grn_ctx_get(ctx, symname, symname_size);
-    if (obj) { grn_ql_obj_bind(obj, x); }
-  }
-  return x;
-}
-
-grn_cell *
-grn_ql_at(grn_ctx *ctx, const char *key)
-{
-  grn_cell *o;
-  if (!grn_hash_get(ctx, ctx->impl->symbols, key, strlen(key), (void **) &o)) {
-    return NULL;
-  }
-  return o;
-}
-
-grn_cell *
-grn_ql_def_native_func(grn_ctx *ctx, const char *name, grn_ql_native_func *func)
-{
-  grn_cell *o = INTERN(name);
-  if (o != F) {
-    o->header.type = GRN_VOID;
-    o->header.impl_flags |= GRN_CELL_NATIVE;
-    o->u.o.func = func;
-  }
-  return o;
-}
-
-/*
-inline static void
-grn_ctx_igc(grn_ctx *ctx)
-{
-  uint32_t i;
-  grn_cell *o;
-  grn_set_eh *ep;
-  for (i = ctx->impl->lseqno; i != ctx->impl->seqno; i++) {
-    if ((ep = grn_set_at(ctx->impl->objects, &i, (void **) &o))) {
-      if (ctx->impl->nbinds &&
-          (o->nrefs ||
-           (BULKP(o) && (o->header.impl_flags & GRN_OBJ_ALLOCATED)))) { continue; }
-      grn_cell_clear(ctx, o);
-      grn_set_del(ctx->impl->objects, ep);
-    }
-  }
-  ctx->impl->lseqno = ctx->impl->seqno;
-  ctx->impl->nbinds = 0;
-}
-*/
-
-#define MARKP(p)        ((p)->header.impl_flags & GRN_CELL_MARKED)
-#define REFERERP(p)     ((p)->header.type & GRN_CELL_LIST)
-#define SETREFERER(p)   ((p)->header.type |= GRN_CELL_LIST)
-#define UNSETREFERER(p) ((p)->header.type &= ~GRN_CELL_LIST)
-
-/*--
- *  We use algorithm E (Knuth, The Art of Computer Programming Vol.1,
- *  sec.3.5) for marking.
- */
-inline static void
-obj_mark(grn_ctx *ctx, grn_cell *o)
-{
-  grn_cell *t, *q, *p;
-  t = NULL;
-  p = o;
-  // if (MARKP(o)) { return; }
-E2:
-  p->header.impl_flags |= GRN_CELL_MARKED;
-  // if (!o->nrefs) { GRN_LOG(ctx, GRN_LOG_ERROR, "obj->nrefs corrupt"); }
-  if (BULKP(o) && !(o->header.impl_flags & GRN_OBJ_ALLOCATED)) {
-    char *b = GRN_MALLOC(o->u.b.size + 1);
-    if (b) {
-      memcpy(b, o->u.b.value, o->u.b.size);
-      b[o->u.b.size] = '\0';
-      o->u.b.value = b;
-      o->header.impl_flags |= GRN_OBJ_ALLOCATED;
-    }
-  }
-  if (!REFERERP(p)) { goto E6; }
-  q = CAR(p);
-  if (q && !MARKP(q)) {
-    UNSETREFERER(p);
-    CAR(p) = t;
-    t = p;
-    p = q;
-    goto E2;
-  }
-E5:
-  q = CDR(p);
-  if (q && !MARKP(q)) {
-    CDR(p) = t;
-    t = p;
-    p = q;
-    goto E2;
-  }
-E6:
-  if (!t) { return; }
-  q = t;
-  if (!REFERERP(q)) {
-    SETREFERER(q);
-    t = CAR(q);
-    CAR(q) = p;
-    p = q;
-    goto E5;
-  } else {
-    t = CDR(q);
-    CDR(q) = p;
-    p = q;
-    goto E6;
-  }
-}
-
-#define MARK2P(p)        ((p)->header.impl_flags & GRN_CELL_MARK2)
-
-grn_rc
-grn_ql_obj_mark(grn_ctx *ctx, grn_cell *o)
-{
-  grn_cell *t, *q, *p;
-  t = NULL;
-  p = o;
-  if (MARK2P(o)) { return GRN_INVALID_ARGUMENT; }
-E2:
-  p->header.impl_flags |= GRN_CELL_MARK2;
-  if (!REFERERP(p)) { goto E6; }
-  q = CAR(p);
-  if (q && !MARK2P(q)) {
-    UNSETREFERER(p);
-    CAR(p) = t;
-    t = p;
-    p = q;
-    goto E2;
-  }
-E5:
-  q = CDR(p);
-  if (q && !MARK2P(q)) {
-    CDR(p) = t;
-    t = p;
-    p = q;
-    goto E2;
-  }
-E6:
-  if (!t) { return GRN_SUCCESS; }
-  q = t;
-  if (!REFERERP(q)) {
-    SETREFERER(q);
-    t = CAR(q);
-    CAR(q) = p;
-    p = q;
-    goto E5;
-  } else {
-    t = CDR(q);
-    CDR(q) = p;
-    p = q;
-    goto E6;
-  }
-  return GRN_SUCCESS;
-}
-
-grn_rc
-grn_ql_obj_unmark(grn_ctx *ctx, grn_cell *o)
-{
-  grn_cell *t, *q, *p;
-  t = NULL;
-  p = o;
-  if (!MARK2P(o)) { return GRN_INVALID_ARGUMENT; }
-E2:
-  p->header.impl_flags &= ~GRN_CELL_MARK2;
-  if (!REFERERP(p)) { goto E6; }
-  q = CAR(p);
-  if (q && MARK2P(q)) {
-    UNSETREFERER(p);
-    CAR(p) = t;
-    t = p;
-    p = q;
-    goto E2;
-  }
-E5:
-  q = CDR(p);
-  if (q && MARK2P(q)) {
-    CDR(p) = t;
-    t = p;
-    p = q;
-    goto E2;
-  }
-E6:
-  if (!t) { return GRN_SUCCESS; }
-  q = t;
-  if (!REFERERP(q)) {
-    SETREFERER(q);
-    t = CAR(q);
-    CAR(q) = p;
-    p = q;
-    goto E5;
-  } else {
-    t = CDR(q);
-    CDR(q) = p;
-    p = q;
-    goto E6;
-  }
-  return GRN_SUCCESS;
-}
-
-grn_rc
-grn_ctx_mgc(grn_ctx *ctx)
-{
-  /*
-  if (!(sc = grn_set_cursor_open(ctx->impl->symbols))) { return GRN_NO_MEMORY_AVAILABLE; }
-  {
-    grn_cell *o;
-    while (grn_set_cursor_next(sc, NULL, (void **) &o)) { obj_mark(o); }
-    grn_set_cursor_close(sc);
-  }
-  */
-  obj_mark(ctx, ctx->impl->global_env);
-
-  /* mark current registers */
-  obj_mark(ctx, ctx->impl->args);
-  obj_mark(ctx, ctx->impl->envir);
-  obj_mark(ctx, ctx->impl->code);
-  obj_mark(ctx, ctx->impl->dump);
-  obj_mark(ctx, ctx->impl->value);
-  obj_mark(ctx, ctx->impl->phs);
-
-  ctx->impl->n_entries = 0;
-  {
-    grn_cell *o;
-    GRN_ARRAY_EACH(ctx, ctx->impl->objects, 0, 0, id, &o, {
-      if (o->header.impl_flags & (GRN_CELL_MARKED|GRN_CELL_MARK2)) {
-        o->header.impl_flags &= ~GRN_CELL_MARKED;
-        ctx->impl->n_entries++;
-      } else {
-        grn_cell_clear(ctx, o);
-        grn_array_delete_by_id(ctx, ctx->impl->objects, id, NULL);
-      }
-    });
-  }
-  {
-    grn_tmp_db_obj *o;
-    GRN_ARRAY_EACH(ctx, ctx->impl->values, 0, 0, id, &o, {
-      if (o->cell.header.impl_flags & (GRN_CELL_MARKED|GRN_CELL_MARK2)) {
-        o->cell.header.impl_flags &= ~GRN_CELL_MARKED;
-        ctx->impl->n_entries++;
-      } else {
-        if (((grn_obj *)o->obj)->header.type != GRN_EXPR &&
-            ((grn_obj *)o->obj)->header.type != GRN_PROC &&
-            ((grn_obj *)o->obj)->header.domain == GRN_ID_NIL) {
-          grn_obj_close(ctx, (grn_obj *)o->obj);
-        }
-      }
-    });
-  }
-  ctx->impl->lseqno = ctx->impl->seqno;
-  ctx->impl->nbinds = 0;
-  ctx->impl->nunbinds = 0;
-  return GRN_SUCCESS;
-}
-
-inline static void Eval_Cycle(grn_ctx *ctx);
-
-/* ========== Evaluation Cycle ========== */
-
-/* operator code */
-
-enum {
-  OP_T0LVL = GRN_OP_T0LVL,
-  OP_ERR0 = GRN_OP_ERR0,
-  OP_LOAD,
-  OP_T1LVL,
-  OP_READ,
-  OP_VALUEPRINT,
-  OP_EVAL,
-  OP_E0ARGS,
-  OP_E1ARGS,
-  OP_APPLY,
-  OP_DOMACRO,
-  OP_LAMBDA,
-  OP_QUOTE,
-  OP_DEF0,
-  OP_DEF1,
-  OP_BEGIN,
-  OP_IF0,
-  OP_IF1,
-  OP_SET0,
-  OP_SET1,
-  OP_LET0,
-  OP_LET1,
-  OP_LET2,
-  OP_LET0AST,
-  OP_LET1AST,
-  OP_LET2AST,
-  OP_LET0REC,
-  OP_LET1REC,
-  OP_LET2REC,
-  OP_COND0,
-  OP_COND1,
-  OP_DELAY,
-  OP_AND0,
-  OP_AND1,
-  OP_OR0,
-  OP_OR1,
-  OP_C0STREAM,
-  OP_C1STREAM,
-  OP_0MACRO,
-  OP_1MACRO,
-  OP_CASE0,
-  OP_CASE1,
-  OP_CASE2,
-  OP_PEVAL,
-  OP_PAPPLY,
-  OP_CONTINUATION,
-  OP_SETCAR,
-  OP_SETCDR,
-  OP_FORCE,
-  OP_ERR1,
-  OP_PUT,
-  OP_GET,
-  OP_QUIT,
-  OP_SDOWN,
-  OP_RDSEXPR,
-  OP_RDLIST,
-  OP_RDDOT,
-  OP_RDQUOTE,
-  OP_RDQQUOTE,
-  OP_RDUNQUOTE,
-  OP_RDUQTSP,
-  OP_NATIVE,
-  OP_QQUOTE0,
-  OP_QQUOTE1,
-  OP_QQUOTE2
-};
-
-grn_cell *
-grn_ql_feed(grn_ctx *ctx, char *str, uint32_t str_size, int mode)
-{
-  if (GRN_QL_WAITINGP(ctx)) {
-    GRN_BULK_REWIND(ctx->impl->outbuf);
-    GRN_BULK_REWIND(&ctx->impl->subbuf);
-    ctx->impl->bufcur = 0;
-  }
-  for (;;) {
-    switch (ctx->stat) {
-    case GRN_QL_TOPLEVEL :
-      ctx->impl->co.mode &= ~GRN_CTX_HEAD;
-      Eval_Cycle(ctx);
-      break;
-    case GRN_QL_WAIT_EXPR :
-      ctx->impl->co.mode = mode;
-      ctx->impl->cur = str;
-      ctx->impl->str_end = str + str_size;
-      Eval_Cycle(ctx);
-      break;
-    case GRN_QL_WAIT_ARG :
-      ctx->impl->co.mode = mode;
-      if ((mode & GRN_CTX_HEAD)) {
-        ctx->impl->cur = str;
-        ctx->impl->str_end = str + str_size;
-      } else {
-        char *buf;
-        grn_cell *ph = CAR(ctx->impl->phs);
-        if (!(buf = GRN_MALLOC(str_size + 1))) {
-          return NIL;
-        }
-        memcpy(buf, str, str_size);
-        buf[str_size] = '\0';
-        ph->header.impl_flags |= GRN_OBJ_ALLOCATED;
-        ph->u.b.value = buf;
-        ph->u.b.size = str_size;
-        ctx->impl->phs = CDR(ctx->impl->phs);
-      }
-      if ((ctx->impl->phs == NIL) || (mode & (GRN_CTX_HEAD|GRN_CTX_TAIL))) {
-        ctx->stat = GRN_QL_EVAL;
-      }
-      break;
-    case GRN_QL_EVAL :
-      Eval_Cycle(ctx);
-      break;
-    case GRN_QL_WAIT_DATA :
-      ctx->impl->co.mode = mode;
-      if ((mode & GRN_CTX_HEAD)) {
-        ctx->impl->args = NIL;
-        ctx->impl->cur = str;
-        ctx->impl->str_end = str + str_size;
-      } else {
-        ctx->impl->arg.u.b.value = str;
-        ctx->impl->arg.u.b.size = str_size;
-        ctx->impl->arg.header.type = GRN_CELL_STR;
-        ctx->impl->arg.header.impl_flags = GRN_OBJ_ALLOCATED;
-        ctx->impl->args = &ctx->impl->arg;
-      }
-      /* fall through */
-    case GRN_QL_NATIVE :
-      GRN_ASSERT(ctx->impl->co.func);
-      ctx->impl->value = ctx->impl->co.func(ctx, ctx->impl->args, &ctx->impl->co);
-      if (ERRP(ctx, GRN_ERROR)) { ctx->stat = GRN_CTX_QUITTING; return F; }
-      ERRCLR(ctx);
-      if (ctx->impl->co.last && !(ctx->impl->co.mode & (GRN_CTX_HEAD|GRN_CTX_TAIL))) {
-        ctx->stat = GRN_QL_WAIT_DATA;
-      } else {
-        ctx->impl->co.mode = 0;
-        Eval_Cycle(ctx);
-      }
-      break;
-    case GRN_CTX_QUITTING :
-    case GRN_CTX_QUIT :
-      return NIL;
-    }
-    if (ERRP(ctx, GRN_ERROR)) { ctx->stat = GRN_CTX_QUITTING; return F; }
-    if (GRN_QL_WAITINGP(ctx)) { /* waiting input data */
-      if (ctx->impl->inbuf) {
-        GRN_FREE(ctx->impl->inbuf);
-        ctx->impl->inbuf = NULL;
-      }
-      break;
-    }
-    if ((ctx->stat & 0x40) && GRN_QL_GET_MODE(ctx) == grn_ql_step) {
-      break;
-    }
-  }
-  return NIL;
-}
-
-/**** sexp parser ****/
-
-inline static void
-skipline(grn_ctx *ctx)
-{
-  while (ctx->impl->cur < ctx->impl->str_end) {
-    if (*ctx->impl->cur++ == '\n') { break; }
-  }
-}
-
-/*************** scheme interpreter ***************/
-
-# define BACKQUOTE '`'
-
-#include <stdio.h>
-#include <ctype.h>
-
-/* macros for cell operations */
-#define HASPROP(p)       ((p)->header.impl_flags & GRN_CELL_SYMBOL)
-#define SYMPROP(p)       CDR(p)
-#define SYNTAXP(p)       ((p)->header.type == GRN_CELL_SYNTAX)
-#define SYNTAXNUM(p)     ((p)->header.domain)
-#define PROCNUM(p)       IVALUE(p)
-#define MACROP(p)        ((p)->header.type == GRN_CELL_MACRO)
-#define CLOSURE_CODE(p)  CAR(p)
-#define CLOSURE_ENV(p)   CDR(p)
-#define CONT_DUMP(p)     CDR(p)
-#define PROMISEP(p)      ((p)->header.impl_flags & GRN_CELL_PROMISE)
-#define SETPROMISE(p)    (p)->header.impl_flags |= GRN_CELL_PROMISE
-#define LAMBDA           (INTERN("lambda"))
-#define QUOTE            (INTERN("quote"))
-#define QQUOTE           (INTERN("quasiquote"))
-#define UNQUOTE          (INTERN("unquote"))
-#define UNQUOTESP        (INTERN("unquote-splicing"))
-
-/* get new cell.  parameter a, b is marked by gc. */
-#define GET_CELL(ctx,a,b,o) GRN_CELL_NEW(ctx, o)
-
-/* get number atom */
-inline static grn_cell *
-mk_number(grn_ctx *ctx, int64_t num)
-{
-  grn_cell *x;
-  GRN_CELL_NEW(ctx, x);
-  SETINT(x, num);
-  return x;
-}
-
-/* get new string */
-grn_cell *
-grn_ql_mk_string(grn_ctx *ctx, const char *str, unsigned int len)
-{
-  grn_cell *x = grn_cell_alloc(ctx, len);
-  if (!x) { return F; }
-  memcpy(x->u.b.value, str, len);
-  x->u.b.value[len] = '\0';
-  return x;
-}
-
-inline static grn_cell *
-mk_const_string(grn_ctx *ctx, const char *str)
-{
-  grn_cell *x;
-  GRN_CELL_NEW(ctx, x);
-  x->header.impl_flags = 0;
-  x->header.type = GRN_CELL_STR;
-  x->u.b.value = (char *)str;
-  x->u.b.size = strlen(str);
-  return x;
-}
-
-grn_cell *
-grn_ql_mk_symbol2(grn_ctx *ctx, const char *q, unsigned int len, int kwdp)
-{
-  char buf[GRN_TABLE_MAX_KEY_SIZE], *p = buf;
-  if (len + 1 >= GRN_TABLE_MAX_KEY_SIZE) { QLERR("too long symbol"); }
-  if (kwdp) {
-    *p++ = ':';
-    memcpy(p, q, len);
-    len++;
-  } else {
-    memcpy(p, q, len);
-  }
-  return grn_ql_mk_symbol(ctx, buf, len);
-}
-
-static grn_cell *
-str2num(grn_ctx *ctx, const char *str, unsigned int len)
-{
-  const char *cur, *str_end = str + len;
-  int64_t i = grn_atoll(str, str_end, &cur);
-  if (cur == str_end) { return mk_number(ctx, i); }
-  if (cur != str) { /* todo : support #i notation */
-    char *end, buf0[128], *buf = len < 128 ? buf0 : GRN_MALLOC(len + 1);
-    if (buf) {
-      double d;
-      memcpy(buf, str, len);
-      buf[len] = '\0';
-      errno = 0;
-      d = strtod(buf, &end);
-      if (!(len < 128)) { GRN_FREE(buf); }
-      if (!errno && buf + len == end) {
-        grn_cell *x;
-        GRN_CELL_NEW(ctx, x);
-        SETFLOAT(x, d);
-        return x;
-      }
-    }
-  }
-  return NIL;
-}
-
-/* make symbol or number atom from string */
-static grn_cell *
-mk_atom(grn_ctx *ctx, char *str, unsigned int len, grn_cell *v)
-{
-  grn_cell **vp = &v, *p;
-  const char *cur, *last, *str_end = str + len;
-  if ((p = str2num(ctx, str, len)) != NIL) { return p; }
-  for (last = cur = str; cur < str_end; cur += len) {
-    if (!(len = grn_charlen(ctx, cur, str_end))) { break; }
-    if (*cur == '.') {
-      if (last < cur) { *vp = grn_ql_mk_symbol2(ctx, last, cur - last, str != last); }
-      v = CONS(v, CONS(NIL, NIL));
-      vp = &CADR(v);
-      last = cur + 1;
-    }
-  }
-  if (last < cur) { *vp = grn_ql_mk_symbol2(ctx, last, cur - last, str != last); }
-  return v;
-}
-
-/* make constant */
-inline static grn_cell *
-mk_const(grn_ctx *ctx, char *name, unsigned int len)
-{
-  char    tmp[256];
-  char    tmp2[256];
-  /* todo : rewirte with grn_str_* functions */
-  if (len == 1) {
-    if (*name == 't') {
-      return T;
-    } else if (*name == 'f') {
-      return F;
-    }
-  } else if (len > 1) {
-    if (*name == 'p' && name[1] == '<' && name[12] == '>') {/* #p (GRN_CELL_OBJECT) */
-      grn_id cls = grn_btoi(name + 2);
-      if (cls) {
-        grn_id self = grn_btoi(name + 7);
-        if (self) {
-          grn_cell * v = grn_ql_obj_new(ctx, cls, self);
-          if (len > 13 && name[13] == '.') {
-            return mk_atom(ctx, name + 13, len - 13, v);
-          } else {
-            return v;
-          }
-        }
-      }
-    } else if (*name == ':' && name[1] == '<') {/* #: (GRN_CELL_TIME) */
-      grn_cell *x;
-      grn_timeval tv;
-      const char *cur;
-      tv.tv_sec = grn_atoi(name + 2, name + len, &cur);
-      if (cur >= name + len || *cur != '.') {
-        QLERR("illegal time format '%s'", name);
-      }
-      tv.tv_nsec = grn_atoi(cur + 1, name + len, &cur);
-      if (cur >= name + len || *cur != '>') {
-        QLERR("illegal time format '%s'", name);
-      }
-      GRN_CELL_NEW(ctx, x);
-      SETTIME(x, &tv);
-      return x;
-    } else if (*name == 'o') {/* #o (octal) */
-      long long unsigned int x;
-      len = (len > 255) ? 255 : len - 1;
-      memcpy(tmp2, name + 1, len);
-      tmp2[len] = '\0';
-      sprintf(tmp, "0%s", tmp2);
-      sscanf(tmp, "%Lo", &x);
-      return mk_number(ctx, x);
-    } else if (*name == 'd') {  /* #d (decimal) */
-      long long int x;
-      sscanf(&name[1], "%Ld", &x);
-      return mk_number(ctx, x);
-    } else if (*name == 'x') {  /* #x (hex) */
-      long long unsigned int x;
-      len = (len > 255) ? 255 : len - 1;
-      memcpy(tmp2, name + 1, len);
-      tmp2[len] = '\0';
-      sprintf(tmp, "0x%s", tmp2);
-      sscanf(tmp, "%Lx", &x);
-      return mk_number(ctx, x);
-    }
-  }
-  return NIL;
-}
-
-/* ========== Routines for Reading ========== */
-
-#define TOK_LPAREN  0
-#define TOK_RPAREN  1
-#define TOK_DOT     2
-#define TOK_ATOM    3
-#define TOK_QUOTE   4
-#define TOK_COMMENT 5
-#define TOK_DQUOTE  6
-#define TOK_BQUOTE  7
-#define TOK_COMMA   8
-#define TOK_ATMARK  9
-#define TOK_SHARP   10
-#define TOK_EOS     11
-#define TOK_QUESTION 12
-
-#define lparenp(c) ((c) == '(' || (c) == '[')
-#define rparenp(c) ((c) == ')' || (c) == ']')
-
-/* read chacters to delimiter */
-inline static char
-readstr(grn_ctx *ctx, char **str, unsigned int *size)
-{
-  char *start, *end;
-  for (start = end = ctx->impl->cur;;) {
-    unsigned int len;
-    /* null check and length check */
-    if (!(len = grn_charlen(ctx, end, ctx->impl->str_end))) {
-      ctx->impl->cur = ctx->impl->str_end;
-      break;
-    }
-    if (grn_isspace(end, ctx->encoding) ||
-        *end == ';' || lparenp(*end) || rparenp(*end)) {
-      ctx->impl->cur = end;
-      break;
-    }
-    end += len;
-  }
-  if (start < end || ctx->impl->cur < ctx->impl->str_end) {
-    *str = start;
-    *size = (unsigned int)(end - start);
-    return TOK_ATOM;
-  } else {
-    return TOK_EOS;
-  }
-}
-
-/* read string expression "xxx...xxx" */
-inline static char
-readstrexp(grn_ctx *ctx, char **str, unsigned int *size)
-{
-  char *start, *src, *dest;
-  for (start = src = dest = ctx->impl->cur;;) {
-    unsigned int len;
-    /* null check and length check */
-    if (!(len = grn_charlen(ctx, src, ctx->impl->str_end))) {
-      ctx->impl->cur = ctx->impl->str_end;
-      if (start < dest) {
-        *str = start;
-        *size = (unsigned int)(dest - start);
-        return TOK_ATOM;
-      }
-      return TOK_EOS;
-    }
-    if (src[0] == '"' && len == 1) {
-      ctx->impl->cur = src + 1;
-      *str = start;
-      *size = (unsigned int)(dest - start);
-      return TOK_ATOM;
-    } else if (src[0] == '\\' && src + 1 < ctx->impl->str_end && len == 1) {
-      src++;
-      switch (*src) {
-      case 'n' :
-        *dest++ = '\n';
-        break;
-      case 'r' :
-        *dest++ = '\r';
-        break;
-      case 't' :
-        *dest++ = '\t';
-        break;
-      default :
-        *dest++ = *src;
-        break;
-      }
-      src++;
-    } else {
-      while (len--) { *dest++ = *src++; }
-    }
-  }
-}
-
-/* get token */
-inline static char
-token(grn_ctx *ctx)
-{
-  SKIPSPACE(ctx->impl);
-  if (ctx->impl->cur >= ctx->impl->str_end) { return TOK_EOS; }
-  switch (*ctx->impl->cur) {
-  case '(':
-  case '[':
-    ctx->impl->cur++;
-    return TOK_LPAREN;
-  case ')':
-  case ']':
-    ctx->impl->cur++;
-    return TOK_RPAREN;
-  case '.':
-    ctx->impl->cur++;
-    if (ctx->impl->cur == ctx->impl->str_end ||
-        grn_isspace(ctx->impl->cur, ctx->encoding) ||
-        *ctx->impl->cur == ';' || lparenp(*ctx->impl->cur) || rparenp(*ctx->impl->cur)) {
-      return TOK_DOT;
-    } else {
-      ctx->impl->cur--;
-      return TOK_ATOM;
-    }
-  case '\'':
-    ctx->impl->cur++;
-    return TOK_QUOTE;
-  case ';':
-    ctx->impl->cur++;
-    return TOK_COMMENT;
-  case '"':
-    ctx->impl->cur++;
-    return TOK_DQUOTE;
-  case BACKQUOTE:
-    ctx->impl->cur++;
-    return TOK_BQUOTE;
-  case ',':
-    ctx->impl->cur++;
-    if (ctx->impl->cur < ctx->impl->str_end && *ctx->impl->cur == '@') {
-      ctx->impl->cur++;
-      return TOK_ATMARK;
-    } else {
-      return TOK_COMMA;
-    }
-  case '#':
-    ctx->impl->cur++;
-    return TOK_SHARP;
-  case '?':
-    ctx->impl->cur++;
-    return TOK_QUESTION;
-  default:
-    return TOK_ATOM;
-  }
-}
-
-/* ========== Routines for Printing ========== */
-#define  ok_abbrev(x)  (PAIRP(x) && CDR(x) == NIL)
-
-void
-grn_obj_inspect(grn_ctx *ctx, grn_cell *obj, grn_obj *buf, int flags)
-{
-  if (!obj) {
-    GRN_TEXT_PUTS(ctx, buf, "NULL");
-  } else if (obj == NIL) {
-    GRN_TEXT_PUTS(ctx, buf, "()");
-  } else if (obj == T) {
-    GRN_TEXT_PUTS(ctx, buf, "#t");
-  } else if (obj == F) {
-    GRN_TEXT_PUTS(ctx, buf, "#f");
-  } else {
-    if (SYMBOLP(obj)) {
-      char b[GRN_TABLE_MAX_KEY_SIZE + 1];
-      symbol2str(obj, b);
-      if (flags & GRN_OBJ_INSPECT_SYMBOL_AS_STR) {
-        grn_text_esc(ctx, buf, (*b == ':') ? b + 1 : b,
-                     strlen(b) - (*b == ':') ? 1 : 0);
-      } else {
-        GRN_TEXT_PUTS(ctx, buf, b);
-      }
-      return;
-    }
-    switch (obj->header.type) {
-    case GRN_VOID :
-      if (SYMBOLP(obj)) {
-        char b[GRN_TABLE_MAX_KEY_SIZE + 1];
-        symbol2str(obj, b);
-        GRN_TEXT_PUTS(ctx, buf, b);
-      } else {
-        GRN_TEXT_PUTS(ctx, buf, "#<VOID>");
-      }
-      break;
-    case GRN_CELL_OBJECT :
-      if (flags & GRN_OBJ_INSPECT_ESC) {
-        GRN_TEXT_PUTS(ctx, buf, "#p<");
-        grn_text_itob(ctx, buf, obj->header.domain);
-        grn_text_itob(ctx, buf, obj->u.o.id);
-        GRN_TEXT_PUTC(ctx, buf, '>');
-      } else {
-        grn_ql_obj_key(ctx, obj, buf);
-      }
-      break;
-    case GRN_SNIP :
-    case GRN_PATSNIP :
-      GRN_TEXT_PUTS(ctx, buf, "#<SNIP>");
-      break;
-    case GRN_CELL_STR :
-      if (flags & GRN_OBJ_INSPECT_ESC) {
-        grn_text_esc(ctx, buf, STRVALUE(obj), STRSIZE(obj));
-      } else {
-        grn_bulk_write(ctx, buf, STRVALUE(obj), STRSIZE(obj));
-      }
-      break;
-    case GRN_CELL_INT :
-      grn_text_lltoa(ctx, buf, IVALUE(obj));
-      break;
-    case GRN_CELL_FLOAT :
-      grn_text_ftoa(ctx, buf, FVALUE(obj));
-      break;
-    case GRN_CELL_TIME :
-      GRN_TEXT_PUTS(ctx, buf, "#:<");
-      grn_text_itoa(ctx, buf, obj->u.tv.tv_sec);
-      GRN_TEXT_PUTS(ctx, buf, ".");
-      grn_text_itoa(ctx, buf, obj->u.tv.tv_nsec);
-      GRN_TEXT_PUTC(ctx, buf, '>');
-      break;
-    case GRN_QUERY :
-      GRN_TEXT_PUTS(ctx, buf, "#<QUERY>");
-      break;
-    case GRN_VECTOR :
-      GRN_TEXT_PUTS(ctx, buf, "#<VECTOR>");
-      break;
-    case GRN_UVECTOR :
-      GRN_TEXT_PUTS(ctx, buf, "#<UVECTOR>");
-      break;
-    case GRN_CELL_OP :
-      GRN_TEXT_PUTS(ctx, buf, "#<OP>");
-      break;
-    case GRN_CELL_SYNTAX :
-      GRN_TEXT_PUTS(ctx, buf, "#<SYNTAX>");
-      break;
-    case GRN_CELL_PROC :
-      GRN_TEXT_PUTS(ctx, buf, "#<PROCEDURE ");
-      grn_text_itoa(ctx, buf, PROCNUM(obj));
-      GRN_TEXT_PUTS(ctx, buf, ">");
-      break;
-    case GRN_CELL_MACRO :
-      GRN_TEXT_PUTS(ctx, buf, "#<MACRO>");
-      break;
-    case GRN_CELL_CLOSURE :
-      GRN_TEXT_PUTS(ctx, buf, "#<CLOSURE>");
-      break;
-    case GRN_CELL_CONTINUATION :
-      GRN_TEXT_PUTS(ctx, buf, "#<CONTINUATION>");
-      break;
-    case GRN_TYPE :
-      GRN_TEXT_PUTS(ctx, buf, "#<TYPE>");
-      break;
-    case GRN_TABLE_HASH_KEY :
-    case GRN_TABLE_NO_KEY :
-    case GRN_TABLE_PAT_KEY :
-      GRN_TEXT_PUTS(ctx, buf, "#<TABLE>");
-      break;
-    case GRN_COLUMN_FIX_SIZE :
-      GRN_TEXT_PUTS(ctx, buf, "#<RA_COLUMN>");
-      break;
-    case GRN_COLUMN_VAR_SIZE :
-      GRN_TEXT_PUTS(ctx, buf, "#<JA_COLUMN>");
-      break;
-    case GRN_COLUMN_INDEX :
-      GRN_TEXT_PUTS(ctx, buf, "#<IDX_COLUMN>");
-      break;
-    case GRN_CELL_LIST :
-      /* todo : detect loop */
-      if (CAR(obj) == QUOTE && ok_abbrev(CDR(obj))) {
-        GRN_TEXT_PUTC(ctx, buf, '\'');
-        grn_obj_inspect(ctx, CADR(obj), buf, flags);
-      } else if (CAR(obj) == QQUOTE && ok_abbrev(CDR(obj))) {
-        GRN_TEXT_PUTC(ctx, buf, '`');
-        grn_obj_inspect(ctx, CADR(obj), buf, flags);
-      } else if (CAR(obj) == UNQUOTE && ok_abbrev(CDR(obj))) {
-        GRN_TEXT_PUTC(ctx, buf, ',');
-        grn_obj_inspect(ctx, CADR(obj), buf, flags);
-      } else if (CAR(obj) == UNQUOTESP && ok_abbrev(CDR(obj))) {
-        GRN_TEXT_PUTS(ctx, buf, ",@");
-        grn_obj_inspect(ctx, CADR(obj), buf, flags);
-      } else {
-        GRN_TEXT_PUTC(ctx, buf, '(');
-        for (;;) {
-          grn_obj_inspect(ctx, CAR(obj), buf, flags);
-          if ((obj = CDR(obj)) && (obj != NIL)) {
-            if (PAIRP(obj)) {
-              GRN_TEXT_PUTC(ctx, buf, ' ');
-            } else {
-              GRN_TEXT_PUTS(ctx, buf, " . ");
-              grn_obj_inspect(ctx, obj, buf, flags);
-              GRN_TEXT_PUTC(ctx, buf, ')');
-              break;
-            }
-          } else {
-            GRN_TEXT_PUTC(ctx, buf, ')');
-            break;
-          }
-        }
-      }
-      break;
-    default :
-      if (SYMBOLP(obj)) {
-        char b[GRN_TABLE_MAX_KEY_SIZE + 1];
-        symbol2str(obj, b);
-        GRN_TEXT_PUTS(ctx, buf, b);
-      } else {
-        GRN_TEXT_PUTS(ctx, buf, "#<?(");
-        grn_text_itoa(ctx, buf, obj->header.type);
-        GRN_TEXT_PUTS(ctx, buf, ")?>");
-      }
-      break;
-    }
-  }
-}
-
-/* ========== Routines for Evaluation Cycle ========== */
-
-/* make closure. c is code. e is environment */
-inline static grn_cell *
-mk_closure(grn_ctx *ctx, grn_cell *c, grn_cell *e)
-{
-  grn_cell *x;
-  GET_CELL(ctx, c, e, x);
-  x->header.type = GRN_CELL_CLOSURE;
-  x->header.impl_flags = 0;
-  CAR(x) = c;
-  CDR(x) = e;
-  return x;
-}
-
-/* make continuation. */
-inline static grn_cell *
-mk_continuation(grn_ctx *ctx, grn_cell *d)
-{
-  grn_cell *x;
-  GET_CELL(ctx, NIL, d, x);
-  x->header.type = GRN_CELL_CONTINUATION;
-  x->header.impl_flags = 0;
-  CONT_DUMP(x) = d;
-  return x;
-}
-
-/* reverse list -- make new cells */
-inline static grn_cell *
-reverse(grn_ctx *ctx, grn_cell *a) /* a must be checked by gc */
-{
-  grn_cell *p = NIL;
-  for ( ; PAIRP(a); a = CDR(a)) {
-    p = CONS(CAR(a), p);
-    if (ERRP(ctx, GRN_ERROR)) { return F; }
-  }
-  return p;
-}
-
-/* reverse list --- no make new cells */
-inline static grn_cell *
-non_alloc_rev(grn_cell *term, grn_cell *list)
-{
-  grn_cell *p = list, *result = term, *q;
-  while (p != NIL) {
-    q = CDR(p);
-    CDR(p) = result;
-    result = p;
-    p = q;
-  }
-  return result;
-}
-
-/* append list -- make new cells */
-inline static grn_cell *
-append(grn_ctx *ctx, grn_cell *a, grn_cell *b)
-{
-  grn_cell *p = b, *q;
-  if (a != NIL) {
-    a = reverse(ctx, a);
-    if (ERRP(ctx, GRN_ERROR)) { return F; }
-    while (a != NIL) {
-      q = CDR(a);
-      CDR(a) = p;
-      p = a;
-      a = q;
-    }
-  }
-  return p;
-}
-
-/* equivalence of atoms */
-inline static int
-eqv(grn_cell *a, grn_cell *b)
-{
-  if (a == b) { return 1; }
-  if (a->header.type != b->header.type) { return 0; }
-  switch (a->header.type) {
-  case GRN_CELL_OBJECT :
-    return (a->u.o.id == b->u.o.id && a->header.domain == b->header.domain);
-    break;
-  case GRN_CELL_STR :
-    return (a->u.b.size == b->u.b.size &&
-            !memcmp(a->u.b.value, b->u.b.value, a->u.b.size));
-    break;
-  case GRN_CELL_INT :
-    return (IVALUE(a) == IVALUE(b));
-    break;
-  case GRN_CELL_FLOAT :
-    return !islessgreater(FVALUE(a), FVALUE(b));
-    break;
-  case GRN_CELL_TIME :
-    return (!memcmp(&a->u.tv, &b->u.tv, sizeof(grn_timeval)));
-    break;
-  default :
-    /* todo : support other types */
-    return 0;
-    break;
-  }
-}
-
-/* expr (&) by int atoms */
-inline static int
-logtest(grn_cell *a, grn_cell *b)
-{
-  if (a == b) { return 1; }
-  if (a->header.type != b->header.type) { return 0; }
-  switch (a->header.type) {
-  case GRN_CELL_INT :
-    return (IVALUE(a) & IVALUE(b) ? 1 : 0);
-    break;
-  default :
-    return 0;
-    break;
-  }
-}
-/* true or false value macro */
-#define istrue(p)       ((p) != NIL && (p) != F)
-#define isfalse(p)      ((p) == F)
-
-/* control macros for Eval_Cycle */
-#define s_goto(ctx,a) do {\
-  ctx->impl->op = (a);\
-  return T;\
-} while (0)
-
-#define s_save(ctx,a,b,args) (\
-    ctx->impl->dump = CONS(ctx->impl->envir, CONS((args), ctx->impl->dump)),\
-    ctx->impl->dump = CONS((b), ctx->impl->dump),\
-    ctx->impl->dump = CONS(mk_number(ctx, (int64_t)(a)), ctx->impl->dump))
-
-#define s_return(ctx,a) do {\
-    ctx->impl->value = (a);\
-    ctx->impl->op = IVALUE(CAR(ctx->impl->dump));\
-    ctx->impl->args = CADR(ctx->impl->dump);\
-    ctx->impl->envir = CADDR(ctx->impl->dump);\
-    ctx->impl->code = CADDDR(ctx->impl->dump);\
-    ctx->impl->dump = CDDDDR(ctx->impl->dump);\
-    return T;\
-} while (0)
-
-#define RTN_NIL_IF_HEAD(ctx) do {\
-  if (((ctx)->impl->co.mode & GRN_CTX_HEAD)) { s_goto(ctx, OP_T0LVL); }\
-} while (0)
-
-#define RTN_NIL_IF_TAIL(ctx) do {\
-  if (((ctx)->impl->co.mode & GRN_CTX_TAIL)) { s_return((ctx), NIL); } else { return NIL; }\
-} while (0)
-
-static grn_cell *
-list_deep_copy(grn_ctx *ctx, grn_cell *c) {
-  /* NOTE: only list is copied */
-  if (PAIRP(c)) {
-    /* TODO: convert recursion to loop */
-    return CONS(list_deep_copy(ctx, CAR(c)), list_deep_copy(ctx, CDR(c)));
-  } else {
-    return c;
-  }
-}
-
-static void
-qquote_uquotelist(grn_ctx *ctx, grn_cell *cl, grn_cell *pcl, int level) {
-  /* reverse list */
-  grn_cell *x, *y;
-  while (PAIRP(cl)) {
-    x = CAR(cl);
-    if (PAIRP(x)) {
-      y = CAR(x);
-      if (y == UNQUOTE) {
-        if (level) {
-          qquote_uquotelist(ctx, CDR(x), x, level - 1);
-        } else {
-          CDR(ctx->impl->args) = CONS(cl, CDR(ctx->impl->args)); /* save (unquote ...) cell */
-        }
-      } else if (y == UNQUOTESP) {
-        if (level) {
-          qquote_uquotelist(ctx, CDR(x), x, level - 1);
-        } else {
-          CDR(ctx->impl->args) = CONS(pcl, CDR(ctx->impl->args)); /* save pre (unquote-splicing) cell */
-        }
-      } else {
-        qquote_uquotelist(ctx, x, cl, level);
-      }
-    } else if (x == QQUOTE) {
-      qquote_uquotelist(ctx, CDR(cl), cl, level + 1);
-      return;
-    }
-    if (!level && CADR(cl) == UNQUOTE) {
-      CDR(ctx->impl->args) = CONS(cl, CDR(ctx->impl->args)); /* save (a . ,b) cell */
-      return;
-    }
-    pcl = cl;
-    cl = CDR(cl);
-  }
-}
-
-#define GC_THRESHOLD 1000000000
-
-static grn_cell *
-opexe(grn_ctx *ctx)
-{
-  register grn_cell *x, *y;
-  if (ctx->impl->op == OP_T0LVL || ctx->impl->n_entries > ctx->impl->ncells + GC_THRESHOLD) {
-    if (ctx->impl->gc_verbose) {
-      grn_obj buf;
-      GRN_TEXT_INIT(&buf, 0);
-      grn_obj_inspect(ctx, ctx->impl->envir, &buf, GRN_OBJ_INSPECT_ESC);
-      GRN_TEXT_PUTC(ctx, &buf, '\0');
-      GRN_LOG(ctx, GRN_LOG_NOTICE, "mgc > ncells=%d envir=<%s>", ctx->impl->n_entries, GRN_TEXT_VALUE(&buf));
-      GRN_OBJ_FIN(ctx, &buf);
-    }
-    grn_ctx_mgc(ctx);
-    if (ctx->impl->gc_verbose) {
-      GRN_LOG(ctx, GRN_LOG_NOTICE, "mgc < ncells=%d", ctx->impl->n_entries);
-    }
-    ctx->impl->ncells = ctx->impl->n_entries;
-  }
-  switch (ctx->impl->op) {
-  case OP_LOAD:    /* load */
-    if (BULKP(CAR(ctx->impl->args))) {
-      struct stat st;
-      char *fname = STRVALUE(CAR(ctx->impl->args));
-      if (fname && !stat(fname, &st)) {
-        if (ctx->impl->inbuf) { GRN_FREE(ctx->impl->inbuf); }
-        if ((ctx->impl->inbuf = GRN_MALLOC(st.st_size))) {
-          int fd;
-          if ((fd = open(fname, O_RDONLY)) != -1) {
-            if (read(fd, ctx->impl->inbuf, st.st_size) == st.st_size) {
-              GRN_TEXT_PUTS(ctx, ctx->impl->outbuf, "loading ");
-              GRN_TEXT_PUTS(ctx, ctx->impl->outbuf, STRVALUE(CAR(ctx->impl->args)));
-              ctx->impl->cur = ctx->impl->inbuf;
-              ctx->impl->str_end = ctx->impl->inbuf + st.st_size;
-            }
-            close(fd);
-          }
-          if (ctx->impl->cur != ctx->impl->inbuf) {
-            GRN_FREE(ctx->impl->inbuf);
-            ctx->impl->inbuf = NULL;
-          }
-        }
-      }
-    }
-    s_goto(ctx, OP_T0LVL);
-
-  case OP_T0LVL:  /* top level */
-    ctx->impl->dump = NIL;
-    ctx->impl->envir = ctx->impl->global_env;
-    if (ctx->impl->batchmode) {
-      s_save(ctx, OP_T0LVL, NIL, NIL);
-    } else {
-      s_save(ctx, OP_VALUEPRINT, NIL, NIL);
-    }
-    s_save(ctx, OP_T1LVL, NIL, NIL);
-    ctx->impl->pht = &ctx->impl->phs;
-    *ctx->impl->pht = NIL;
-    s_goto(ctx, OP_READ);
-
-  case OP_T1LVL:  /* top level */
-    // verbose check?
-    if (ctx->impl->phs != NIL &&
-        !(ctx->impl->co.mode & (GRN_CTX_HEAD|GRN_CTX_TAIL))) { RTN_NIL_IF_TAIL(ctx); }
-    // GRN_TEXT_PUTC(ctx, ctx->impl->outbuf, '\n');
-    ctx->impl->code = ctx->impl->value;
-    s_goto(ctx, OP_EVAL);
-
-  case OP_READ:    /* read */
-    RTN_NIL_IF_HEAD(ctx);
-    if ((ctx->impl->tok = token(ctx)) == TOK_EOS) { RTN_NIL_IF_TAIL(ctx); }
-    s_goto(ctx, OP_RDSEXPR);
-
-  case OP_VALUEPRINT:  /* print evalution result */
-    ctx->impl->args = ctx->impl->value;
-    s_save(ctx, OP_T0LVL, NIL, NIL);
-    grn_obj_inspect(ctx, ctx->impl->args, ctx->impl->outbuf, GRN_OBJ_INSPECT_ESC);
-    s_return(ctx, T);
-
-  case OP_EVAL:    /* main part of evalution */
-    // fixme : quick hack.
-    if (SYMBOLP(ctx->impl->code)) {  /* symbol */
-      if (keywordp(ctx->impl->code)) { s_return(ctx, ctx->impl->code); }
-      for (x = ctx->impl->envir; x != NIL; x = CDR(x)) {
-        for (y = CAR(x); y != NIL; y = CDR(y))
-          if (CAAR(y) == ctx->impl->code)
-            break;
-        if (y != NIL)
-          break;
-      }
-      if (x != NIL) {
-        s_return(ctx, CDAR(y));
-      } else {
-        if (PROCP(ctx->impl->code)) { s_return(ctx, ctx->impl->code); }
-        if (NATIVE_FUNCP(ctx->impl->code)) { s_return(ctx, ctx->impl->code); }
-        {
-          char buf[GRN_TABLE_MAX_KEY_SIZE + 1];
-          symbol2str(ctx->impl->code, buf);
-          QLERR("Unbounded variable %s", buf);
-        }
-      }
-    } else if (PAIRP(ctx->impl->code)) {
-      if (SYNTAXP(x = CAR(ctx->impl->code))) {  /* SYNTAX */
-        ctx->impl->code = CDR(ctx->impl->code);
-        s_goto(ctx, SYNTAXNUM(x));
-      } else {/* first, eval top element and eval arguments */
-        s_save(ctx, OP_E0ARGS, NIL, ctx->impl->code);
-        ctx->impl->code = CAR(ctx->impl->code);
-        // if (NATIVE_FUNCP(ctx->impl->code)) { s_return(ctx, ctx->impl->code); } /* call native funcs. fast */
-        s_goto(ctx, OP_EVAL);
-      }
-    } else {
-      s_return(ctx, ctx->impl->code);
-    }
-
-  case OP_E0ARGS:  /* eval arguments */
-    if (MACROP(ctx->impl->value)) {  /* macro expansion */
-      s_save(ctx, OP_DOMACRO, NIL, NIL);
-      ctx->impl->args = CONS(ctx->impl->code, NIL);
-      ctx->impl->code = ctx->impl->value;
-      s_goto(ctx, OP_APPLY);
-    } else {
-      ctx->impl->code = CDR(ctx->impl->code);
-      s_goto(ctx, OP_E1ARGS);
-    }
-
-  case OP_E1ARGS:  /* eval arguments */
-    ctx->impl->args = CONS(ctx->impl->value, ctx->impl->args);
-    if (PAIRP(ctx->impl->code)) {  /* continue */
-      s_save(ctx, OP_E1ARGS, ctx->impl->args, CDR(ctx->impl->code));
-      ctx->impl->code = CAR(ctx->impl->code);
-      ctx->impl->args = NIL;
-      s_goto(ctx, OP_EVAL);
-    } else {  /* end */
-      ctx->impl->args = reverse(ctx, ctx->impl->args);
-      ctx->impl->code = CAR(ctx->impl->args);
-      ctx->impl->args = CDR(ctx->impl->args);
-      s_goto(ctx, OP_APPLY);
-    }
-
-  case OP_APPLY:    /* apply 'code' to 'args' */
-    if (NATIVE_FUNCP(ctx->impl->code)) {
-      ctx->impl->dump = CONS(ctx->impl->code, ctx->impl->dump);
-      ctx->impl->co.func = ctx->impl->code->u.o.func;
-      s_goto(ctx, OP_NATIVE);
-    } else if (PROCP(ctx->impl->code)) {
-      s_goto(ctx, PROCNUM(ctx->impl->code));  /* PROCEDURE */
-    } else if (CLOSUREP(ctx->impl->code)) {  /* CLOSURE */
-      /* make environment */
-      ctx->impl->envir = CONS(NIL, CLOSURE_ENV(ctx->impl->code));
-      for (x = CAR(CLOSURE_CODE(ctx->impl->code)), y = ctx->impl->args;
-           PAIRP(x); x = CDR(x), y = CDR(y)) {
-        if (y == NIL) {
-          QLERR("Few arguments");
-        } else {
-          CAR(ctx->impl->envir) = CONS(CONS(CAR(x), CAR(y)), CAR(ctx->impl->envir));
-        }
-      }
-      if (x == NIL) {
-        /*--
-         * if (y != NIL) {
-         *   QLERR("Many arguments");
-         * }
-         */
-      } else if (SYMBOLP(x))
-        CAR(ctx->impl->envir) = CONS(CONS(x, y), CAR(ctx->impl->envir));
-      else {
-        QLERR("Syntax error in closure");
-      }
-      ctx->impl->code = CDR(CLOSURE_CODE(ctx->impl->code));
-      ctx->impl->args = NIL;
-      s_goto(ctx, OP_BEGIN);
-    } else if (CONTINUATIONP(ctx->impl->code)) {  /* CONTINUATION */
-      ctx->impl->dump = CONT_DUMP(ctx->impl->code);
-      s_return(ctx, ctx->impl->args != NIL ? CAR(ctx->impl->args) : NIL);
-    } else {
-      QLERR("Illegal function");
-    }
-
-  case OP_DOMACRO:  /* do macro */
-    ctx->impl->code = ctx->impl->value;
-    s_goto(ctx, OP_EVAL);
-
-  case OP_LAMBDA:  /* lambda */
-    s_return(ctx, mk_closure(ctx, ctx->impl->code, ctx->impl->envir));
-
-  case OP_QUOTE:    /* quote */
-    s_return(ctx, CAR(ctx->impl->code));
-
-  case OP_DEF0:  /* define */
-    if (PAIRP(CAR(ctx->impl->code))) {
-      x = CAAR(ctx->impl->code);
-      ctx->impl->code = CONS(LAMBDA, CONS(CDAR(ctx->impl->code), CDR(ctx->impl->code)));
-    } else {
-      x = CAR(ctx->impl->code);
-      ctx->impl->code = CADR(ctx->impl->code);
-    }
-    if (!SYMBOLP(x)) {
-      QLERR("Variable is not symbol");
-    }
-    s_save(ctx, OP_DEF1, NIL, x);
-    s_goto(ctx, OP_EVAL);
-
-  case OP_DEF1:  /* define */
-    for (x = CAR(ctx->impl->envir); x != NIL; x = CDR(x))
-      if (CAAR(x) == ctx->impl->code)
-        break;
-    if (x != NIL)
-      CDAR(x) = ctx->impl->value;
-    else
-      CAR(ctx->impl->envir) = CONS(CONS(ctx->impl->code, ctx->impl->value), CAR(ctx->impl->envir));
-    s_return(ctx, ctx->impl->code);
-
-  case OP_SET0:    /* set! */
-    s_save(ctx, OP_SET1, NIL, CAR(ctx->impl->code));
-    ctx->impl->code = CADR(ctx->impl->code);
-    s_goto(ctx, OP_EVAL);
-
-  case OP_SET1:    /* set! */
-    for (x = ctx->impl->envir; x != NIL; x = CDR(x)) {
-      for (y = CAR(x); y != NIL; y = CDR(y))
-        if (CAAR(y) == ctx->impl->code)
-          break;
-      if (y != NIL)
-        break;
-    }
-    if (x != NIL) {
-      CDAR(y) = ctx->impl->value;
-      s_return(ctx, ctx->impl->value);
-    } else {
-      if (SYMBOLP(ctx->impl->code)) {
-        char buf[GRN_TABLE_MAX_KEY_SIZE + 1];
-        symbol2str(ctx->impl->code, buf);
-        QLERR("Unbounded variable %s", buf);
-      } else {
-        QLERR("Unbounded variable");
-      }
-    }
-
-  case OP_BEGIN:    /* begin */
-    if (!PAIRP(ctx->impl->code)) {
-      s_return(ctx, ctx->impl->code);
-    }
-    if (CDR(ctx->impl->code) != NIL) {
-      s_save(ctx, OP_BEGIN, NIL, CDR(ctx->impl->code));
-    }
-    ctx->impl->code = CAR(ctx->impl->code);
-    s_goto(ctx, OP_EVAL);
-
-  case OP_IF0:    /* if */
-    s_save(ctx, OP_IF1, NIL, CDR(ctx->impl->code));
-    ctx->impl->code = CAR(ctx->impl->code);
-    s_goto(ctx, OP_EVAL);
-
-  case OP_IF1:    /* if */
-    if (istrue(ctx->impl->value))
-      ctx->impl->code = CAR(ctx->impl->code);
-    else
-      ctx->impl->code = CADR(ctx->impl->code);  /* (if #f 1) ==> () because
-             * CAR(NIL) = NIL */
-    s_goto(ctx, OP_EVAL);
-
-  case OP_LET0:    /* let */
-    ctx->impl->args = NIL;
-    ctx->impl->value = ctx->impl->code;
-    ctx->impl->code = SYMBOLP(CAR(ctx->impl->code)) ? CADR(ctx->impl->code) : CAR(ctx->impl->code);
-    s_goto(ctx, OP_LET1);
-
-  case OP_LET1:    /* let (caluculate parameters) */
-    ctx->impl->args = CONS(ctx->impl->value, ctx->impl->args);
-    if (PAIRP(ctx->impl->code)) {  /* continue */
-      QLASSERT(LISTP(CAR(ctx->impl->code)) && LISTP(CDAR(ctx->impl->code)));
-      s_save(ctx, OP_LET1, ctx->impl->args, CDR(ctx->impl->code));
-      ctx->impl->code = CADAR(ctx->impl->code);
-      ctx->impl->args = NIL;
-      s_goto(ctx, OP_EVAL);
-    } else {  /* end */
-      ctx->impl->args = reverse(ctx, ctx->impl->args);
-      ctx->impl->code = CAR(ctx->impl->args);
-      ctx->impl->args = CDR(ctx->impl->args);
-      s_goto(ctx, OP_LET2);
-    }
-
-  case OP_LET2:    /* let */
-    ctx->impl->envir = CONS(NIL, ctx->impl->envir);
-    for (x = SYMBOLP(CAR(ctx->impl->code)) ? CADR(ctx->impl->code) : CAR(ctx->impl->code), y = ctx->impl->args;
-         y != NIL; x = CDR(x), y = CDR(y))
-      CAR(ctx->impl->envir) = CONS(CONS(CAAR(x), CAR(y)), CAR(ctx->impl->envir));
-    if (SYMBOLP(CAR(ctx->impl->code))) {  /* named let */
-      for (x = CADR(ctx->impl->code), ctx->impl->args = NIL; PAIRP(x); x = CDR(x))
-        ctx->impl->args = CONS(CAAR(x), ctx->impl->args);
-      x = mk_closure(ctx, CONS(reverse(ctx, ctx->impl->args), CDDR(ctx->impl->code)),
-                     ctx->impl->envir);
-      CAR(ctx->impl->envir) = CONS(CONS(CAR(ctx->impl->code), x), CAR(ctx->impl->envir));
-      ctx->impl->code = CDDR(ctx->impl->code);
-      ctx->impl->args = NIL;
-    } else {
-      ctx->impl->code = CDR(ctx->impl->code);
-      ctx->impl->args = NIL;
-    }
-    s_goto(ctx, OP_BEGIN);
-
-  case OP_LET0AST:  /* let* */
-    if (CAR(ctx->impl->code) == NIL) {
-      ctx->impl->envir = CONS(NIL, ctx->impl->envir);
-      ctx->impl->code = CDR(ctx->impl->code);
-      s_goto(ctx, OP_BEGIN);
-    }
-    s_save(ctx, OP_LET1AST, CDR(ctx->impl->code), CAR(ctx->impl->code));
-    QLASSERT(LISTP(CAR(ctx->impl->code)) &&
-             LISTP(CAAR(ctx->impl->code)) && LISTP((CDR(CAAR(ctx->impl->code)))));
-    ctx->impl->code = CADAAR(ctx->impl->code);
-    s_goto(ctx, OP_EVAL);
-
-  case OP_LET1AST:  /* let* (make new frame) */
-    ctx->impl->envir = CONS(NIL, ctx->impl->envir);
-    s_goto(ctx, OP_LET2AST);
-
-  case OP_LET2AST:  /* let* (caluculate parameters) */
-    CAR(ctx->impl->envir) = CONS(CONS(CAAR(ctx->impl->code), ctx->impl->value), CAR(ctx->impl->envir));
-    ctx->impl->code = CDR(ctx->impl->code);
-    if (PAIRP(ctx->impl->code)) {  /* continue */
-      QLASSERT(LISTP(CAR(ctx->impl->code)) && LISTP(CDAR(ctx->impl->code)));
-      s_save(ctx, OP_LET2AST, ctx->impl->args, ctx->impl->code);
-      ctx->impl->code = CADAR(ctx->impl->code);
-      ctx->impl->args = NIL;
-      s_goto(ctx, OP_EVAL);
-    } else {  /* end */
-      ctx->impl->code = ctx->impl->args;
-      ctx->impl->args = NIL;
-      s_goto(ctx, OP_BEGIN);
-    }
-
-  case OP_LET0REC:  /* letrec */
-    ctx->impl->envir = CONS(NIL, ctx->impl->envir);
-    ctx->impl->args = NIL;
-    ctx->impl->value = ctx->impl->code;
-    ctx->impl->code = CAR(ctx->impl->code);
-    s_goto(ctx, OP_LET1REC);
-
-  case OP_LET1REC:  /* letrec (caluculate parameters) */
-    ctx->impl->args = CONS(ctx->impl->value, ctx->impl->args);
-    if (PAIRP(ctx->impl->code)) {  /* continue */
-      QLASSERT(LISTP(CAR(ctx->impl->code)) && LISTP(CDAR(ctx->impl->code)));
-      s_save(ctx, OP_LET1REC, ctx->impl->args, CDR(ctx->impl->code));
-      ctx->impl->code = CADAR(ctx->impl->code);
-      ctx->impl->args = NIL;
-      s_goto(ctx, OP_EVAL);
-    } else {  /* end */
-      ctx->impl->args = reverse(ctx, ctx->impl->args);
-      ctx->impl->code = CAR(ctx->impl->args);
-      ctx->impl->args = CDR(ctx->impl->args);
-      s_goto(ctx, OP_LET2REC);
-    }
-
-  case OP_LET2REC:  /* letrec */
-    for (x = CAR(ctx->impl->code), y = ctx->impl->args; y != NIL; x = CDR(x), y = CDR(y))
-      CAR(ctx->impl->envir) = CONS(CONS(CAAR(x), CAR(y)), CAR(ctx->impl->envir));
-    ctx->impl->code = CDR(ctx->impl->code);
-    ctx->impl->args = NIL;
-    s_goto(ctx, OP_BEGIN);
-
-  case OP_COND0:    /* cond */
-    if (!PAIRP(ctx->impl->code)) {
-      QLERR("Syntax error in cond");
-    }
-    s_save(ctx, OP_COND1, NIL, ctx->impl->code);
-    ctx->impl->code = CAAR(ctx->impl->code);
-    s_goto(ctx, OP_EVAL);
-
-  case OP_COND1:    /* cond */
-    if (istrue(ctx->impl->value)) {
-      if ((ctx->impl->code = CDAR(ctx->impl->code)) == NIL) {
-        s_return(ctx, ctx->impl->value);
-      }
-      s_goto(ctx, OP_BEGIN);
-    } else {
-      if ((ctx->impl->code = CDR(ctx->impl->code)) == NIL) {
-        s_return(ctx, NIL);
-      } else {
-        s_save(ctx, OP_COND1, NIL, ctx->impl->code);
-        ctx->impl->code = CAAR(ctx->impl->code);
-        s_goto(ctx, OP_EVAL);
-      }
-    }
-
-  case OP_DELAY:    /* delay */
-    x = mk_closure(ctx, CONS(NIL, ctx->impl->code), ctx->impl->envir);
-    if (ERRP(ctx, GRN_ERROR)) { return F; }
-    SETPROMISE(x);
-    s_return(ctx, x);
-
-  case OP_AND0:    /* and */
-    if (ctx->impl->code == NIL) {
-      s_return(ctx, T);
-    }
-    s_save(ctx, OP_AND1, NIL, CDR(ctx->impl->code));
-    ctx->impl->code = CAR(ctx->impl->code);
-    s_goto(ctx, OP_EVAL);
-
-  case OP_AND1:    /* and */
-    if (isfalse(ctx->impl->value)) {
-      s_return(ctx, ctx->impl->value);
-    } else if (ctx->impl->code == NIL) {
-      s_return(ctx, ctx->impl->value);
-    } else {
-      s_save(ctx, OP_AND1, NIL, CDR(ctx->impl->code));
-      ctx->impl->code = CAR(ctx->impl->code);
-      s_goto(ctx, OP_EVAL);
-    }
-
-  case OP_OR0:    /* or */
-    if (ctx->impl->code == NIL) {
-      s_return(ctx, F);
-    }
-    s_save(ctx, OP_OR1, NIL, CDR(ctx->impl->code));
-    ctx->impl->code = CAR(ctx->impl->code);
-    s_goto(ctx, OP_EVAL);
-
-  case OP_OR1:    /* or */
-    if (istrue(ctx->impl->value)) {
-      s_return(ctx, ctx->impl->value);
-    } else if (ctx->impl->code == NIL) {
-      s_return(ctx, ctx->impl->value);
-    } else {
-      s_save(ctx, OP_OR1, NIL, CDR(ctx->impl->code));
-      ctx->impl->code = CAR(ctx->impl->code);
-      s_goto(ctx, OP_EVAL);
-    }
-
-  case OP_C0STREAM:  /* cons-stream */
-    s_save(ctx, OP_C1STREAM, NIL, CDR(ctx->impl->code));
-    ctx->impl->code = CAR(ctx->impl->code);
-    s_goto(ctx, OP_EVAL);
-
-  case OP_C1STREAM:  /* cons-stream */
-    ctx->impl->args = ctx->impl->value;  /* save ctx->impl->value to register ctx->impl->args for gc */
-    x = mk_closure(ctx, CONS(NIL, ctx->impl->code), ctx->impl->envir);
-    if (ERRP(ctx, GRN_ERROR)) { return F; }
-    SETPROMISE(x);
-    s_return(ctx, CONS(ctx->impl->args, x));
-
-  case OP_0MACRO:  /* macro */
-    x = CAR(ctx->impl->code);
-    ctx->impl->code = CADR(ctx->impl->code);
-    if (!SYMBOLP(x)) {
-      QLERR("Variable is not symbol");
-    }
-    s_save(ctx, OP_1MACRO, NIL, x);
-    s_goto(ctx, OP_EVAL);
-
-  case OP_1MACRO:  /* macro */
-    ctx->impl->value->header.type = GRN_CELL_MACRO;
-    for (x = CAR(ctx->impl->envir); x != NIL; x = CDR(x))
-      if (CAAR(x) == ctx->impl->code)
-        break;
-    if (x != NIL)
-      CDAR(x) = ctx->impl->value;
-    else
-      CAR(ctx->impl->envir) = CONS(CONS(ctx->impl->code, ctx->impl->value), CAR(ctx->impl->envir));
-    s_return(ctx, ctx->impl->code);
-
-  case OP_CASE0:    /* case */
-    s_save(ctx, OP_CASE1, NIL, CDR(ctx->impl->code));
-    ctx->impl->code = CAR(ctx->impl->code);
-    s_goto(ctx, OP_EVAL);
-
-  case OP_CASE1:    /* case */
-    for (x = ctx->impl->code; x != NIL; x = CDR(x)) {
-      if (!PAIRP(y = CAAR(x)))
-        break;
-      for ( ; y != NIL; y = CDR(y))
-        if (eqv(CAR(y), ctx->impl->value))
-          break;
-      if (y != NIL)
-        break;
-    }
-    if (x != NIL) {
-      if (PAIRP(CAAR(x))) {
-        ctx->impl->code = CDAR(x);
-        s_goto(ctx, OP_BEGIN);
-      } else {/* else */
-        s_save(ctx, OP_CASE2, NIL, CDAR(x));
-        ctx->impl->code = CAAR(x);
-        s_goto(ctx, OP_EVAL);
-      }
-    } else {
-      s_return(ctx, NIL);
-    }
-
-  case OP_CASE2:    /* case */
-    if (istrue(ctx->impl->value)) {
-      s_goto(ctx, OP_BEGIN);
-    } else {
-      s_return(ctx, NIL);
-    }
-  case OP_PAPPLY:  /* apply */
-    ctx->impl->code = CAR(ctx->impl->args);
-    ctx->impl->args = CADR(ctx->impl->args);
-    s_goto(ctx, OP_APPLY);
-
-  case OP_PEVAL:  /* eval */
-    ctx->impl->code = CAR(ctx->impl->args);
-    ctx->impl->args = NIL;
-    s_goto(ctx, OP_EVAL);
-
-  case OP_CONTINUATION:  /* call-with-current-continuation */
-    ctx->impl->code = CAR(ctx->impl->args);
-    ctx->impl->args = CONS(mk_continuation(ctx, ctx->impl->dump), NIL);
-    s_goto(ctx, OP_APPLY);
-
-  case OP_SETCAR:  /* set-car! */
-    if (PAIRP(CAR(ctx->impl->args))) {
-      CAAR(ctx->impl->args) = CADR(ctx->impl->args);
-      s_return(ctx, CAR(ctx->impl->args));
-    } else {
-      QLERR("Unable to set-car! for non-cons cell");
-    }
-
-  case OP_SETCDR:  /* set-cdr! */
-    if (PAIRP(CAR(ctx->impl->args))) {
-      CDAR(ctx->impl->args) = CADR(ctx->impl->args);
-      s_return(ctx, CAR(ctx->impl->args));
-    } else {
-      QLERR("Unable to set-cdr! for non-cons cell");
-    }
-
-  case OP_FORCE:    /* force */
-    ctx->impl->code = CAR(ctx->impl->args);
-    if (PROMISEP(ctx->impl->code)) {
-      ctx->impl->args = NIL;
-      s_goto(ctx, OP_APPLY);
-    } else {
-      s_return(ctx, ctx->impl->code);
-    }
-
-  case OP_ERR0:  /* error */
-    GRN_TEXT_PUTS(ctx, ctx->impl->outbuf, "*** ERROR: ");
-    GRN_TEXT_PUTS(ctx, ctx->impl->outbuf, ctx->errbuf);
-    GRN_TEXT_PUTC(ctx, ctx->impl->outbuf, '\n');
-    ctx->impl->args = NIL;
-    s_goto(ctx, OP_T0LVL);
-
-  case OP_ERR1:  /* error */
-    GRN_TEXT_PUTS(ctx, ctx->impl->outbuf, "*** ERROR:");
-    while (ctx->impl->args != NIL) {
-      GRN_TEXT_PUTC(ctx, ctx->impl->outbuf, ' ');
-      grn_obj_inspect(ctx, CAR(ctx->impl->args), ctx->impl->outbuf, GRN_OBJ_INSPECT_ESC);
-      ctx->impl->args = CDR(ctx->impl->args);
-    }
-    GRN_TEXT_PUTC(ctx, ctx->impl->outbuf, '\n');
-    s_goto(ctx, OP_T0LVL);
-
-  case OP_PUT:    /* put */
-    if (!HASPROP(CAR(ctx->impl->args)) || !HASPROP(CADR(ctx->impl->args))) {
-      QLERR("Illegal use of put");
-    }
-    for (x = SYMPROP(CAR(ctx->impl->args)), y = CADR(ctx->impl->args); x != NIL; x = CDR(x))
-      if (CAAR(x) == y)
-        break;
-    if (x != NIL)
-      CDAR(x) = CADDR(ctx->impl->args);
-    else
-      SYMPROP(CAR(ctx->impl->args)) = CONS(CONS(y, CADDR(ctx->impl->args)),
-              SYMPROP(CAR(ctx->impl->args)));
-    s_return(ctx, T);
-
-  case OP_GET:    /* get */
-    if (!HASPROP(CAR(ctx->impl->args)) || !HASPROP(CADR(ctx->impl->args))) {
-      QLERR("Illegal use of get");
-    }
-    for (x = SYMPROP(CAR(ctx->impl->args)), y = CADR(ctx->impl->args); x != NIL; x = CDR(x))
-      if (CAAR(x) == y)
-        break;
-    if (x != NIL) {
-      s_return(ctx, CDAR(x));
-    } else {
-      s_return(ctx, NIL);
-    }
-
-  case OP_SDOWN:   /* shutdown */
-    GRN_LOG(ctx, GRN_LOG_NOTICE, "shutting down..");
-    grn_gctx.stat = GRN_CTX_QUIT;
-    s_goto(ctx, OP_QUIT);
-
-  case OP_RDSEXPR:
-    {
-      char tok, *str;
-      unsigned int len;
-      RTN_NIL_IF_HEAD(ctx);
-      switch (ctx->impl->tok) {
-      case TOK_COMMENT:
-        skipline(ctx);
-        if ((ctx->impl->tok = token(ctx)) == TOK_EOS) { RTN_NIL_IF_TAIL(ctx); }
-        s_goto(ctx, OP_RDSEXPR);
-      case TOK_LPAREN:
-        if ((tok = token(ctx)) == TOK_EOS) { RTN_NIL_IF_TAIL(ctx); }
-        ctx->impl->tok = tok;
-        if (ctx->impl->tok == TOK_RPAREN) {
-          s_return(ctx, NIL);
-        } else if (ctx->impl->tok == TOK_DOT) {
-          QLERR("syntax error: illegal dot expression");
-        } else {
-          s_save(ctx, OP_RDLIST, NIL, NIL);
-          s_goto(ctx, OP_RDSEXPR);
-        }
-      case TOK_QUOTE:
-        s_save(ctx, OP_RDQUOTE, NIL, NIL);
-        if ((ctx->impl->tok = token(ctx)) == TOK_EOS) { RTN_NIL_IF_TAIL(ctx); }
-        s_goto(ctx, OP_RDSEXPR);
-      case TOK_BQUOTE:
-        s_save(ctx, OP_RDQQUOTE, NIL, NIL);
-        if ((ctx->impl->tok = token(ctx)) == TOK_EOS) { RTN_NIL_IF_TAIL(ctx); }
-        s_goto(ctx, OP_RDSEXPR);
-      case TOK_COMMA:
-        s_save(ctx, OP_RDUNQUOTE, NIL, NIL);
-        if ((ctx->impl->tok = token(ctx)) == TOK_EOS) { RTN_NIL_IF_TAIL(ctx); }
-        s_goto(ctx, OP_RDSEXPR);
-      case TOK_ATMARK:
-        s_save(ctx, OP_RDUQTSP, NIL, NIL);
-        if ((ctx->impl->tok = token(ctx)) == TOK_EOS) { RTN_NIL_IF_TAIL(ctx); }
-        s_goto(ctx, OP_RDSEXPR);
-      case TOK_ATOM:
-        if (readstr(ctx, &str, &len) == TOK_EOS) { ctx->impl->tok = TOK_EOS; RTN_NIL_IF_TAIL(ctx); }
-        s_return(ctx, mk_atom(ctx, str, len, NIL));
-      case TOK_DQUOTE:
-        if (readstrexp(ctx, &str, &len) == TOK_EOS) {
-          QLERR("unterminated string");
-        }
-        s_return(ctx, grn_ql_mk_string(ctx, str, len));
-      case TOK_SHARP:
-        if ((readstr(ctx, &str, &len) == TOK_EOS) ||
-            (x = mk_const(ctx, str, len)) == NIL) {
-          QLERR("Undefined sharp expression");
-        } else {
-          s_return(ctx, x);
-        }
-      case TOK_EOS :
-        if ((ctx->impl->tok = token(ctx)) == TOK_EOS) { RTN_NIL_IF_TAIL(ctx); }
-        s_goto(ctx, OP_RDSEXPR);
-      case TOK_QUESTION:
-        {
-          grn_cell *o, *p;
-          GRN_CELL_NEW(ctx, o);
-          p = CONS(o, NIL);
-          o->header.type = GRN_CELL_STR;
-          o->header.impl_flags = 0;
-          o->u.b.size = 1;
-          o->u.b.value = (char *)"?";
-          *ctx->impl->pht = p;
-          ctx->impl->pht = &CDR(p);
-          s_return(ctx, o);
-        }
-      default:
-        QLERR("syntax error: illegal token");
-      }
-    }
-    break;
-
-  case OP_RDLIST:
-    RTN_NIL_IF_HEAD(ctx);
-    if ((ctx->impl->tok = token(ctx)) == TOK_EOS) { RTN_NIL_IF_TAIL(ctx); }
-    if (ctx->impl->tok == TOK_COMMENT) {
-      skipline(ctx);
-      s_goto(ctx, OP_RDLIST);
-    }
-    ctx->impl->args = CONS(ctx->impl->value, ctx->impl->args);
-    if (ctx->impl->tok == TOK_RPAREN) {
-      grn_cell *v = non_alloc_rev(NIL, ctx->impl->args);
-      if (ctx->impl->cur < ctx->impl->str_end && *ctx->impl->cur == '.') {
-        char *str = NULL;
-        unsigned int len = 0;
-        if (readstr(ctx, &str, &len) != TOK_ATOM) { /* error */ }
-        s_return(ctx, mk_atom(ctx, str, len, v));
-      } else {
-        s_return(ctx, v);
-      }
-    } else if (ctx->impl->tok == TOK_DOT) {
-      s_save(ctx, OP_RDDOT, ctx->impl->args, NIL);
-      if ((ctx->impl->tok = token(ctx)) == TOK_EOS) {
-        ctx->impl->op = OP_RDSEXPR; RTN_NIL_IF_TAIL(ctx);
-      }
-      s_goto(ctx, OP_RDSEXPR);
-    } else {
-      s_save(ctx, OP_RDLIST, ctx->impl->args, NIL);;
-      s_goto(ctx, OP_RDSEXPR);
-    }
-
-  case OP_RDDOT:
-    RTN_NIL_IF_HEAD(ctx);
-    if ((ctx->impl->tok = token(ctx)) == TOK_EOS) { RTN_NIL_IF_TAIL(ctx); }
-    if (ctx->impl->tok != TOK_RPAREN) {
-      QLERR("syntax error: illegal dot expression");
-    } else {
-      grn_cell *v = non_alloc_rev(ctx->impl->value, ctx->impl->args);
-      if (ctx->impl->cur < ctx->impl->str_end && *ctx->impl->cur == '.') {
-        char *str = NULL;
-        unsigned int len = 0;
-        if (readstr(ctx, &str, &len) != TOK_ATOM) { /* error */ }
-        s_return(ctx, mk_atom(ctx, str, len, v));
-      } else {
-        s_return(ctx, v);
-      }
-    }
-
-  case OP_RDQUOTE:
-    s_return(ctx, CONS(QUOTE, CONS(ctx->impl->value, NIL)));
-
-  case OP_RDQQUOTE:
-    s_return(ctx, CONS(QQUOTE, CONS(ctx->impl->value, NIL)));
-
-  case OP_RDUNQUOTE:
-    s_return(ctx, CONS(UNQUOTE, CONS(ctx->impl->value, NIL)));
-
-  case OP_RDUQTSP:
-    s_return(ctx, CONS(UNQUOTESP, CONS(ctx->impl->value, NIL)));
-
-  case OP_NATIVE:
-    ctx->impl->dump = CDR(ctx->impl->dump);
-    s_return(ctx, ctx->impl->value);
-  case OP_QQUOTE0:
-    ctx->impl->code = list_deep_copy(ctx, ctx->impl->code);
-    ctx->impl->args = CONS(ctx->impl->code, NIL);
-    qquote_uquotelist(ctx, ctx->impl->code, ctx->impl->code, 0);
-    ctx->impl->code = CDR(ctx->impl->args);
-    s_goto(ctx, OP_QQUOTE1);
-  case OP_QQUOTE1:
-    while (PAIRP(ctx->impl->code)) {
-      x = CAR(ctx->impl->code);
-      if (PAIRP(x) && LISTP(CDR(x))) {
-        s_save(ctx, OP_QQUOTE2, ctx->impl->args, ctx->impl->code);
-        y = CADR(x);
-        if (y == UNQUOTE) {
-          QLASSERT(LISTP(CDDR(x)));
-          ctx->impl->code = CADDR(x);
-        } else if (CAR(y) == UNQUOTESP) {
-          QLASSERT(LISTP(CDR(y)));
-          ctx->impl->code = CADR(y);
-        } else {
-          y = CAR(x);
-          if (CAR(y) == UNQUOTE) {
-            ctx->impl->code = CADR(y);
-          } else if (CAAR(y) == UNQUOTESP) {
-            ctx->impl->code = CADAR(y);
-          } else {
-            /* error */
-          }
-        }
-        s_goto(ctx, OP_EVAL);
-      }
-      ctx->impl->code = CDR(ctx->impl->code);
-    }
-    s_return(ctx, CAAR(ctx->impl->args));
-  case OP_QQUOTE2:
-    x = CAR(ctx->impl->code);
-    if (x) {
-      y = CADR(x);
-      if (y == UNQUOTE) {
-        CDR(x) = ctx->impl->value;
-      } else if (CAR(y) == UNQUOTESP) {
-        if (ctx->impl->value == NIL) {
-          CDR(x) = CDDR(x);
-        } else if (!PAIRP(ctx->impl->value) ) {
-          /* error */
-        } else {
-          ctx->impl->value = list_deep_copy(ctx, ctx->impl->value);
-          for (y = ctx->impl->value; CDR(y) != NIL; y = CDR(y)) {}
-          CDR(y) = CDDR(x);
-          CDR(x) = ctx->impl->value;
-        }
-      } else {
-        y = CAAR(x);
-        if (y == UNQUOTE) {
-          CAR(x) = ctx->impl->value;
-        } else if (CAR(y) == UNQUOTESP) {
-          if (ctx->impl->value == NIL) {
-            CAR(x) = CDAR(x);
-          } else if (!PAIRP(ctx->impl->value) ) {
-            /* error */
-          } else {
-            ctx->impl->value = list_deep_copy(ctx, ctx->impl->value);
-            for (y = ctx->impl->value; CDR(y) != NIL; y = CDR(y)) {}
-            CDR(y) = CDAR(x);
-            CAR(x) = ctx->impl->value;
-          }
-        } else {
-          /* error */
-        }
-      }
-      ctx->impl->code = CDR(ctx->impl->code);
-      s_goto(ctx, OP_QQUOTE1);
-    } else {
-      /* error */
-    }
-  }
-  GRN_LOG(ctx, GRN_LOG_ERROR, "illegal op (%d)", ctx->impl->op);
-  return NIL;
-}
-
-/* kernel of this intepreter */
-inline static void
-Eval_Cycle(grn_ctx *ctx)
-{
-  ctx->impl->co.func = NULL;
-  ctx->impl->co.last = 0;
-  while (opexe(ctx) != NIL) {
-    switch (ctx->impl->op) {
-    case OP_NATIVE :
-      ctx->stat = GRN_QL_NATIVE;
-      return;
-    case OP_T0LVL :
-      ctx->stat = GRN_QL_TOPLEVEL;
-      return;
-    case OP_T1LVL :
-      ctx->stat = (ctx->impl->phs != NIL) ? GRN_QL_WAIT_ARG : GRN_QL_EVAL;
-      return;
-    case OP_QUIT :
-      ctx->stat = GRN_CTX_QUITTING;
-      return;
-    default :
-      break;
-    }
-    if (ERRP(ctx, GRN_ERROR)) { return; }
-  }
-  ctx->stat = GRN_QL_WAIT_EXPR;
-}
-
-grn_cell *
-grn_ql_eval(grn_ctx *ctx, grn_cell *code, grn_cell *objs)
-{
-  grn_ql_co co;
-  uint8_t op = ctx->impl->op;
-  uint8_t stat = ctx->stat;
-  uint8_t feed_mode = ctx->impl->feed_mode;
-  grn_cell *o, *code_ = ctx->impl->code;
-  o = CONS(objs, ctx->impl->envir);
-  memcpy(&co, &ctx->impl->co, sizeof(grn_ql_co));
-  s_save(ctx, OP_QUIT, ctx->impl->args, o);
-  ctx->impl->op = OP_EVAL;
-  ctx->stat = GRN_QL_EVAL;
-  ctx->impl->code = code;
-  ctx->impl->feed_mode = grn_ql_atonce;
-  grn_ql_feed(ctx, NULL, 0, 0);
-  ctx->impl->feed_mode = feed_mode;
-  ctx->stat = stat;
-  ctx->impl->op = op;
-  ctx->impl->envir = CDR(o);
-  ctx->impl->code = code_;
-  memcpy(&ctx->impl->co, &co, sizeof(grn_ql_co));
-  return ctx->impl->value;
-}
-
-/* ========== native functions ========== */
-
-#define s_retbool(tf)  do { return (tf) ? T : F; } while (0)
-
-#define do_op(x,y,op) do {\
-  switch ((x)->header.type) {\
-  case GRN_CELL_INT :\
-    switch ((y)->header.type) {\
-    case GRN_CELL_INT :\
-      IVALUE(x) = IVALUE(x) op IVALUE(y);\
-      break;\
-    case GRN_CELL_FLOAT :\
-      SETFLOAT(x, ((double) IVALUE(x)) op FVALUE(y));\
-      break;\
-    default :\
-      if (grn_obj2int(ctx, y)) { QLERR("can't convert into numeric value"); }\
-      IVALUE(x) = IVALUE(x) op IVALUE(y);\
-    }\
-    break;\
-  case GRN_CELL_FLOAT :\
-    switch ((y)->header.type) {\
-    case GRN_CELL_INT :\
-      FVALUE(x) = FVALUE(x) op IVALUE(y);\
-      break;\
-    case GRN_CELL_FLOAT :\
-      FVALUE(x) = FVALUE(x) op FVALUE(y);\
-      break;\
-    default :\
-      if (grn_obj2int(ctx, y)) { QLERR("can't convert into numeric value"); }\
-      FVALUE(x) = FVALUE(x) op IVALUE(y);\
-    }\
-    break;\
-  default :\
-    QLERR("can't convert into numeric");\
-  }\
-} while (0)
-
-#define do_compare(x,y,r,op) do {\
-  switch (x->header.type) {\
-  case GRN_CELL_INT :\
-    switch (y->header.type) {\
-    case GRN_CELL_INT :\
-      r = (IVALUE(x) op IVALUE(y));\
-      break;\
-    case GRN_CELL_FLOAT :\
-      r = (IVALUE(x) op FVALUE(y));\
-      break;\
-    default :\
-      if (grn_obj2int(ctx, y)) { QLERR("can't convert into numeric value"); }\
-      r = (IVALUE(x) op IVALUE(y));\
-    }\
-    break;\
-  case GRN_CELL_FLOAT :\
-    switch (y->header.type) {\
-    case GRN_CELL_INT :\
-      r = (FVALUE(x) op IVALUE(y));\
-      break;\
-    case GRN_CELL_FLOAT :\
-      r = (FVALUE(x) op FVALUE(y));\
-      break;\
-    default :\
-      if (grn_obj2int(ctx, y)) { QLERR("can't convert into numeric value"); }\
-      r = (FVALUE(x) op IVALUE(y));\
-    }\
-    break;\
-  case GRN_CELL_STR :\
-    if (y->header.type == GRN_CELL_STR) {\
-      int r_;\
-      uint32_t la = x->u.b.size, lb = y->u.b.size;\
-      if (la > lb) {\
-        if (!(r_ = memcmp(x->u.b.value, y->u.b.value, lb))) {\
-          r_ = 1;\
-        }\
-      } else {\
-        if (!(r_ = memcmp(x->u.b.value, y->u.b.value, la))) {\
-          r_ = la == lb ? 0 : -1;\
-        }\
-      }\
-      r = (r_ op 0);\
-    } else {\
-      QLERR("can't compare");\
-    }\
-    break;\
-  case GRN_CELL_TIME :\
-    if (y->header.type == GRN_CELL_TIME) {\
-      if (x->u.tv.tv_sec != y->u.tv.tv_sec) {\
-        r = (x->u.tv.tv_sec op y->u.tv.tv_sec);\
-      } else {\
-        r = (x->u.tv.tv_nsec op y->u.tv.tv_nsec);\
-      }\
-    } else {\
-      QLERR("can't compare");\
-    }\
-    break;\
-  default :\
-    r = (memcmp(&x->u.tv, &y->u.tv, sizeof(grn_timeval)) op 0);\
-  }\
-} while (0)
-
-#define time_op(x,y,v,op) {\
-  switch (y->header.type) {\
-  case GRN_CELL_TIME :\
-    {\
-      double dv= x->u.tv.tv_sec op y->u.tv.tv_sec;\
-      dv += (x->u.tv.tv_nsec op y->u.tv.tv_nsec) / GRN_TIME_NSEC_PER_SEC_F;\
-      SETFLOAT(v, dv);\
-    }\
-    break;\
-  case GRN_CELL_INT :\
-    {\
-      grn_timeval tv;\
-      int64_t sec = x->u.tv.tv_sec op IVALUE(y);\
-      if (sec < INT32_MIN || INT32_MAX < sec) { QLERR("time val overflow"); }\
-      tv.tv_sec = (int)sec;\
-      tv.tv_nsec = x->u.tv.tv_nsec;\
-      SETTIME(v, &tv);\
-    }\
-    break;\
-  case GRN_CELL_FLOAT :\
-    {\
-      grn_timeval tv;\
-      double sec = x->u.tv.tv_sec op (int)FVALUE(y);\
-      int32_t nsec = x->u.tv.tv_nsec op (int)((FVALUE(y) - (int)FVALUE(y)) * GRN_TIME_NSEC_PER_SEC);\
-      if (sec < INT32_MIN || INT32_MAX < sec) { QLERR("time val overflow"); }\
-      tv.tv_sec = (int)sec;\
-      if (nsec < 0) {\
-        tv.tv_sec--;\
-        nsec += GRN_TIME_NSEC_PER_SEC;\
-      } else if (nsec >= GRN_TIME_NSEC_PER_SEC) {\
-        tv.tv_sec++;\
-        nsec -= GRN_TIME_NSEC_PER_SEC;\
-      }\
-      tv.tv_nsec = nsec;\
-      SETTIME(v, &tv);\
-    }\
-    break;\
-  default :\
-    QLERR("can't convert into numeric value");\
-    break;\
-  }\
-} while (0)
-
-static grn_cell *
-nf_add(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  register grn_cell *x, *v;
-  if (!PAIRP(args)) { QLERR("list required"); }
-  switch (CAR(args)->header.type) {
-  case GRN_CELL_STR :
-    {
-      grn_obj buf;
-      GRN_TEXT_INIT(&buf, 0);
-      while (PAIRP(args)) {
-        POP(x, args);
-        grn_obj_inspect(ctx, x, &buf, 0);
-      }
-      GRN_STR2OBJ(ctx, &buf, v);
-    }
-    break;
-  case GRN_CELL_TIME :
-    if (PAIRP(CDR(args)) && NUMBERP(CADR(args))) {
-      GRN_CELL_NEW(ctx, v);
-      time_op(CAR(args), CADR(args), v, +);
-    } else {
-      QLERR("can't convert into numeric value");
-    }
-    break;
-  default :
-    v = mk_number(ctx, 0);
-    while (PAIRP(args)) {
-      POP(x, args);
-      do_op(v, x, +);
-    }
-    break;
-  }
-  return v;
-}
-
-static grn_cell *
-nf_sub(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  register grn_cell *v = mk_number(ctx, 0);
-  register grn_cell *x;
-  if (PAIRP(args) && CDR(args) != NIL) {
-    if (CAR(args)->header.type == GRN_CELL_TIME) {
-      time_op(CAR(args), CADR(args), v, -);
-      return v;
-    }
-    POP(x, args);
-    do_op(v, x, +);
-  }
-  while (PAIRP(args)) {
-    POP(x, args);
-    do_op(v, x, -);
-  }
-  return v;
-}
-
-static grn_cell *
-nf_mul(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  register grn_cell *v, *x;
-  if (CAR(args)->header.type == GRN_CELL_STR && CADR(args)->header.type == GRN_CELL_INT) {
-    int i, n = (int)IVALUE(CADR(args));
-    grn_obj buf;
-    GRN_TEXT_INIT(&buf, 0);
-    POP(x, args);
-    for (i = 0; i < n; i++) {
-      grn_obj_inspect(ctx, x, &buf, 0);
-    }
-    GRN_STR2OBJ(ctx, &buf, v);
-  } else {
-    v = mk_number(ctx, 1);
-    while (PAIRP(args)) {
-      POP(x, args);
-      do_op(v, x, *);
-    }
-  }
-  return v;
-}
-
-static grn_cell *
-nf_div(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  register grn_cell *v;
-  register grn_cell *x;
-  if (PAIRP(args) && CDR(args) != NIL) {
-    v = mk_number(ctx, 0);
-    POP(x, args);
-    do_op(v, x, +);
-  } else {
-    v = mk_number(ctx, 1);
-  }
-  while (PAIRP(args)) {
-    POP(x, args);
-    if (x->header.type == GRN_CELL_INT && IVALUE(x) == 0 && v->header.type == GRN_CELL_INT) {
-      SETFLOAT(v, (double)IVALUE(v));
-    }
-    do_op(v, x, /);
-  }
-  return v;
-}
-static grn_cell *
-nf_rem(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  register int64_t v;
-  register grn_cell *x;
-  x = args;
-  if (grn_obj2int(ctx, CAR(x))) {
-    QLERR("can't convert into integer");
-  }
-  v = IVALUE(CAR(x));
-  while (CDR(x) != NIL) {
-    x = CDR(x);
-    if (grn_obj2int(ctx, CAR(x))) {
-      QLERR("can't convert into integer");
-    }
-    if (IVALUE(CAR(x)) != 0)
-      v %= IVALUE(CAR(x));
-    else {
-      QLERR("Divided by zero");
-    }
-  }
-  return mk_number(ctx, v);
-}
-static grn_cell *
-nf_car(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  if (PAIRP(CAR(args))) {
-    return CAAR(args);
-  } else {
-    QLERR("Unable to car for non-cons cell");
-  }
-}
-static grn_cell *
-nf_cdr(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  if (PAIRP(CAR(args))) {
-    return CDAR(args);
-  } else {
-    QLERR("Unable to cdr for non-cons cell");
-  }
-}
-static grn_cell *
-nf_cons(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  CDR(args) = CADR(args);
-  return args;
-}
-static grn_cell *
-nf_not(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  s_retbool(isfalse(CAR(args)));
-}
-static grn_cell *
-nf_bool(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  s_retbool(CAR(args) == F || CAR(args) == T);
-}
-static grn_cell *
-nf_null(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  s_retbool(CAR(args) == NIL);
-}
-static grn_cell *
-nf_zerop(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  register grn_cell *x = CAR(args);
-  switch (x->header.type) {
-  case GRN_CELL_INT :
-    s_retbool(IVALUE(x) == 0);
-    break;
-  case GRN_CELL_FLOAT :
-    s_retbool(!(islessgreater(FVALUE(x), 0.0)));
-    break;
-  default :
-    QLERR("can't convert into numeric value");
-  }
-}
-static grn_cell *
-nf_posp(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  register grn_cell *x = CAR(args);
-  switch (x->header.type) {
-  case GRN_CELL_INT :
-    s_retbool(IVALUE(x) > 0);
-    break;
-  case GRN_CELL_FLOAT :
-    s_retbool(!(isgreater(FVALUE(x), 0.0)));
-    break;
-  default :
-    QLERR("can't convert into numeric value");
-  }
-}
-static grn_cell *
-nf_negp(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  register grn_cell *x = CAR(args);
-  switch (x->header.type) {
-  case GRN_CELL_INT :
-    s_retbool(IVALUE(x) < 0);
-    break;
-  case GRN_CELL_FLOAT :
-    s_retbool(!(isless(FVALUE(x), 0.0)));
-    break;
-  default :
-    QLERR("can't convert into numeric value");
-  }
-}
-static grn_cell *
-nf_neq(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  int r = 1;
-  register grn_cell *x, *y;
-  POP(x, args);
-  if (!PAIRP(args)) { QLERR("Few arguments"); }
-  do {
-    POP(y, args);
-    switch (x->header.type) {
-    case GRN_CELL_INT :
-      switch (y->header.type) {
-      case GRN_CELL_INT :
-        r = (IVALUE(x) == IVALUE(y));
-        break;
-      case GRN_CELL_FLOAT :
-        r = (IVALUE(x) <= FVALUE(y) && IVALUE(x) >= FVALUE(y));
-        break;
-      default :
-        if (grn_obj2int(ctx, y)) { QLERR("can't convert into numeric value"); }
-        r = (IVALUE(x) == IVALUE(y));
-      }
-      break;
-    case GRN_CELL_FLOAT :
-      switch (y->header.type) {
-      case GRN_CELL_INT :
-        r = (FVALUE(x) <= IVALUE(y) && FVALUE(x) >= IVALUE(y));
-        break;
-      case GRN_CELL_FLOAT :
-        r = (FVALUE(x) <= FVALUE(y) && FVALUE(x) >= FVALUE(y));
-        break;
-      default :
-        if (grn_obj2int(ctx, y)) { QLERR("can't convert into numeric value"); }
-        r = (FVALUE(x) <= IVALUE(y) && FVALUE(x) >= IVALUE(y));
-      }
-      break;
-    case GRN_CELL_STR :
-      if (y->header.type == GRN_CELL_STR) {
-        int r_;
-        uint32_t la = x->u.b.size, lb = y->u.b.size;
-        if (la > lb) {
-          if (!(r_ = memcmp(x->u.b.value, y->u.b.value, lb))) {
-            r_ = 1;
-          }
-        } else {
-          if (!(r_ = memcmp(x->u.b.value, y->u.b.value, la))) {
-            r_ = la == lb ? 0 : -1;
-          }
-        }
-        r = (r_ == 0);
-      } else {
-        QLERR("can't compare");
-      }
-      break;
-    case GRN_CELL_TIME :
-      if (y->header.type == GRN_CELL_TIME) {
-        if (x->u.tv.tv_sec != y->u.tv.tv_sec) {
-          r = (x->u.tv.tv_sec == y->u.tv.tv_sec);
-        } else {
-          r = (x->u.tv.tv_nsec == y->u.tv.tv_nsec);
-        }
-      } else {
-        QLERR("can't compare");
-      }
-      break;
-    case GRN_CELL_OBJECT :
-      r = (y->header.type == GRN_CELL_OBJECT &&
-           x->u.o.id == y->u.o.id && x->header.domain == y->header.domain);
-      break;
-    default :
-      r = (memcmp(&x->u.tv, &y->u.tv, sizeof(grn_timeval)) == 0);
-      break;
-    }
-    x = y;
-  } while (PAIRP(args) && r);
-  return r ? T : F;
-}
-static grn_cell *
-nf_less(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  int r = 1;
-  register grn_cell *x, *y;
-  POP(x, args);
-  if (!PAIRP(args)) { QLERR("Few arguments"); }
-  do {
-    POP(y, args);
-    do_compare(x, y, r, <);
-    x = y;
-  } while (PAIRP(args) && r);
-  return r ? T : F;
-}
-static grn_cell *
-nf_gre(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  int r = 1;
-  register grn_cell *x, *y;
-  POP(x, args);
-  if (!PAIRP(args)) { QLERR("Few arguments"); }
-  do {
-    POP(y, args);
-    do_compare(x, y, r, >);
-    x = y;
-  } while (PAIRP(args) && r);
-  return r ? T : F;
-}
-static grn_cell *
-nf_leq(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  int r = 1;
-  register grn_cell *x, *y;
-  POP(x, args);
-  if (!PAIRP(args)) { QLERR("Few arguments"); }
-  do {
-    POP(y, args);
-    do_compare(x, y, r, <=);
-    x = y;
-  } while (PAIRP(args) && r);
-  return r ? T : F;
-}
-static grn_cell *
-nf_geq(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  int r = 1;
-  register grn_cell *x, *y;
-  POP(x, args);
-  if (!PAIRP(args)) { QLERR("Few arguments"); }
-  do {
-    POP(y, args);
-    do_compare(x, y, r, >=);
-    x = y;
-  } while (PAIRP(args) && r);
-  return r ? T : F;
-}
-static grn_cell *
-nf_symbol(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  s_retbool(SYMBOLP(CAR(args)));
-}
-static grn_cell *
-nf_number(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  s_retbool(NUMBERP(CAR(args)));
-}
-static grn_cell *
-nf_string(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  s_retbool(BULKP(CAR(args)));
-}
-static grn_cell *
-nf_proc(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  /*--
-   * continuation should be procedure by the example
-   * (call-with-current-continuation procedure?) ==> #t
-   * in R^3 report sec. 6.9
-   */
-  s_retbool(PROCEDUREP(CAR(args)));
-}
-static grn_cell *
-nf_pair(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  s_retbool(PAIRP(CAR(args)));
-}
-static grn_cell *
-nf_eq(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  s_retbool(CAR(args) == CADR(args));
-}
-static grn_cell *
-nf_eqv(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  s_retbool(eqv(CAR(args), CADR(args)));
-}
-static grn_cell *
-nf_logtest(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  s_retbool(logtest(CAR(args), CADR(args)));
-}
-static grn_cell *
-nf_write(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  args = CAR(args);
-  grn_obj_inspect(ctx, args, ctx->impl->outbuf, GRN_OBJ_INSPECT_ESC);
-  return T;
-}
-static grn_cell *
-nf_display(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  args = CAR(args);
-  grn_obj_inspect(ctx, args, ctx->impl->outbuf, 0);
-  return T;
-}
-static grn_cell *
-nf_newline(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  GRN_TEXT_PUTC(ctx, ctx->impl->outbuf, '\n');
-  return T;
-}
-static grn_cell *
-nf_reverse(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  return reverse(ctx, CAR(args));
-}
-static grn_cell *
-nf_append(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  return append(ctx, CAR(args), CADR(args));
-}
-static grn_cell *
-nf_gc(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  grn_ctx_mgc(ctx);
-  return T;
-}
-static grn_cell *
-nf_gcverb(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  int  was = ctx->impl->gc_verbose;
-  ctx->impl->gc_verbose = (CAR(args) != F);
-  s_retbool(was);
-}
-static grn_cell *
-nf_nativep(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  s_retbool(NATIVE_FUNCP(CAR(args)));
-}
-static grn_cell *
-nf_length(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  register long v;
-  register grn_cell *x;
-  for (x = CAR(args), v = 0; PAIRP(x); x = CDR(x)) { ++v; }
-  return mk_number(ctx, v);
-}
-static grn_cell *
-nf_assq(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  register grn_cell *x, *y;
-  x = CAR(args);
-  for (y = CADR(args); PAIRP(y); y = CDR(y)) {
-    if (!PAIRP(CAR(y))) {
-      QLERR("Unable to handle non pair element");
-    }
-    if (x == CAAR(y))
-      break;
-  }
-  if (PAIRP(y)) {
-    return CAR(y);
-  } else {
-    return F;
-  }
-}
-static grn_cell *
-nf_get_closure(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  args = CAR(args);
-  if (args == NIL) {
-    return F;
-  } else if (CLOSUREP(args)) {
-    return CONS(LAMBDA, CLOSURE_CODE(ctx->impl->value));
-  }  else {
-    return F;
-  }
-}
-static grn_cell *
-nf_closurep(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  /*
-   * Note, macro object is also a closure.
-   * Therefore, (closure? <#MACRO>) ==> #t
-   */
-  if (CAR(args) == NIL) {
-      return F;
-  }
-  s_retbool(CLOSUREP(CAR(args)));
-}
-static grn_cell *
-nf_macrop(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  if (CAR(args) == NIL) {
-      return F;
-  }
-  s_retbool(MACROP(CAR(args)));
-}
-static grn_cell *
-nf_voidp(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  s_retbool(CAR(args)->header.type == GRN_VOID);
-}
-static grn_cell *
-nf_list(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  if (PAIRP(args)) {
-    return args;
-  } else {
-    QLERR("Unable to handle non-cons argument");
-  }
-}
-static grn_cell *
-nf_batchmode(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  if (CAR(args) == F) {
-    ctx->impl->batchmode = 0;
-    return F;
-  } else {
-    ctx->impl->batchmode = 1;
-    return T;
-  }
-}
-static grn_cell *
-nf_loglevel(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  static grn_logger_info info;
-  grn_cell *x = CAR(args);
-  if (grn_obj2int(ctx, x)) { QLERR("can't convert into integer"); }
-  info.max_level = IVALUE(x);
-  info.flags = GRN_LOG_TIME|GRN_LOG_MESSAGE;
-  info.func = NULL;
-  info.func_arg = NULL;
-  return (grn_logger_info_set(ctx, &info)) ? F : T;
-}
-static grn_cell *
-nf_log_put(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  grn_cell *x, *y;
-  grn_log_level level = GRN_LOG_DEFAULT_LEVEL;
-  POP(x, args);
-  POP(y, args);
-  if (y->header.type == GRN_CELL_INT) { level = IVALUE(y); }
-  if (x->header.type == GRN_CELL_STR) {
-    char *buf = GRN_MALLOC(x->u.b.size + 1);
-    memcpy(buf, x->u.b.value, x->u.b.size);
-    buf[x->u.b.size] = '\0';
-    GRN_LOG(ctx, level, "%s", buf);
-    GRN_FREE(buf);
-    return T;
-  } else {
-    return F;
-  }
-}
-static grn_cell *
-nf_now(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  grn_cell *x;
-  grn_timeval tv;
-  if (grn_timeval_now(ctx, &tv)) { QLERR("sysdate failed"); }
-  GRN_CELL_NEW(ctx, x);
-  SETTIME(x, &tv);
-  return x;
-}
-static grn_cell *
-nf_timestr(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  grn_timeval tv;
-  char buf[GRN_TIMEVAL_STR_SIZE];
-  grn_cell *x = CAR(args);
-  switch (x->header.type) {
-  case GRN_CELL_STR :
-    if (grn_obj2int(ctx, x)) { QLERR("can't convert into integer"); }
-    /* fallthru */
-  case GRN_CELL_INT :
-    tv.tv_sec = IVALUE(x);
-    tv.tv_nsec = 0;
-    break;
-  case GRN_CELL_FLOAT :
-    tv.tv_sec = (int32_t) FVALUE(x);
-    tv.tv_nsec = (int32_t) ((FVALUE(x) - tv.tv_sec) * GRN_TIME_NSEC_PER_SEC);
-    break;
-  case GRN_CELL_TIME :
-    memcpy(&tv, &x->u.tv, sizeof(grn_timeval));
-    break;
-  default :
-    QLERR("can't convert into time");
-  }
-  if (grn_timeval2str(ctx, &tv, buf)) { QLERR("timeval2str failed"); }
-  return grn_ql_mk_string(ctx, buf, strlen(buf));
-}
-static grn_cell *
-nf_tonumber(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  grn_cell *x, *v;
-  if (!PAIRP(args)) { QLERR("list required"); }
-  x = CAR(args);
-  switch (x->header.type) {
-  case GRN_CELL_STR :
-    if ((v = str2num(ctx, STRVALUE(x), x->u.b.size)) == NIL) { v = mk_number(ctx, 0); }
-    break;
-  case GRN_CELL_INT :
-  case GRN_CELL_FLOAT :
-    v = x;
-    break;
-  case GRN_CELL_TIME :
-    {
-      double dv= x->u.tv.tv_sec;
-      dv += x->u.tv.tv_nsec / GRN_TIME_NSEC_PER_SEC_F;
-      GRN_CELL_NEW(ctx, v);
-      SETFLOAT(v, dv);
-    }
-    break;
-  default :
-    v = mk_number(ctx, 0);
-    break;
-  }
-  return v;
-}
-static grn_cell *
-nf_totime(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  grn_timeval tv;
-  grn_cell *x, *v;
-  if (!PAIRP(args)) { QLERR("list required"); }
-  x = CAR(args);
-  switch (x->header.type) {
-  case GRN_CELL_STR :
-    {
-      /*
-      if (PAIRP(CDR(args)) && BULKP(CADR(args))) { fmt = STRVALUE(CADR(args)); }
-      */
-      if (grn_str2timeval(STRVALUE(x), x->u.b.size, &tv)) {
-        QLERR("cast error");
-      }
-      GRN_CELL_NEW(ctx, v);
-      SETTIME(v, &tv);
-    }
-    break;
-  case GRN_CELL_INT :
-    tv.tv_sec = (int32_t) IVALUE(x);
-    tv.tv_nsec = 0;
-    GRN_CELL_NEW(ctx, v);
-    SETTIME(v, &tv);
-    break;
-  case GRN_CELL_FLOAT :
-    tv.tv_sec = (int32_t) FVALUE(x);
-    tv.tv_nsec = (int32_t) ((FVALUE(x) - tv.tv_sec) * GRN_TIME_NSEC_PER_SEC);
-    GRN_CELL_NEW(ctx, v);
-    SETTIME(v, &tv);
-    break;
-  case GRN_CELL_TIME :
-    v = x;
-    break;
-  default :
-    QLERR("can't convert into number");
-  }
-  return v;
-}
-static grn_cell *
-nf_substrb(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  grn_cell *str, *s, *e;
-  int64_t is, ie;
-  if (!PAIRP(args)) { QLERR("list required"); }
-  POP(str, args);
-  if (!BULKP(str)) { QLERR("string required"); }
-  POP(s, args);
-  if (!INTP(s)) { QLERR("integer required"); }
-  POP(e, args);
-  if (!INTP(e)) { QLERR("integer required"); }
-  is = IVALUE(s);
-  ie = IVALUE(e) + 1;
-  if (ie <= 0) {
-    ie = str->u.b.size + ie;
-    if (ie < 0) { ie = 0; }
-  } else if (ie > str->u.b.size) {
-    ie = str->u.b.size;
-  }
-  if (is < 0) {
-    is = str->u.b.size + is + 1;
-    if (is < 0) { is = 0; }
-  } else if (is > str->u.b.size) {
-    is = str->u.b.size;
-  }
-  if (is < ie) {
-    return grn_ql_mk_string(ctx, STRVALUE(str) + is, ie - is);
-  } else {
-    grn_cell *o;
-    GRN_CELL_NEW(ctx, o);
-    o->header.impl_flags = 0;
-    o->header.type = GRN_CELL_STR;
-    o->u.b.size = 0;
-    o->u.b.value = NULL;
-    return o;
-  }
-}
-static grn_cell *
-nf_tob32h(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  grn_cell *x, *v;
-  if (!PAIRP(args)) { QLERR("list required"); }
-  x = CAR(args);
-  switch (x->header.type) {
-  case GRN_CELL_INT :
-    {
-      grn_obj buf;
-      GRN_TEXT_INIT(&buf, 0);
-      grn_bulk_resize(ctx, &buf, 13);
-      if (grn_text_lltob32h(ctx, &buf, IVALUE(x))) {
-        grn_bulk_fin(ctx, &buf);
-        QLERR("lltob32h failed");
-      }
-      GRN_STR2OBJ(ctx, &buf, v);
-    }
-    break;
-  case GRN_CELL_FLOAT :
-    {
-      grn_obj buf;
-      GRN_TEXT_INIT(&buf, 0);
-      grn_bulk_resize(ctx, &buf, 13);
-      if (grn_text_lltob32h(ctx, &buf, (int64_t)FVALUE(x))) {
-        grn_bulk_fin(ctx, &buf);
-        QLERR("lltob32h failed");
-      }
-      GRN_STR2OBJ(ctx, &buf, v);
-    }
-    break;
-  default :
-    QLERR("can't convert into int");
-  }
-  return v;
-}
-static grn_cell *
-nf_intern(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  grn_cell *x, *v;
-  if (!PAIRP(args)) { QLERR("list required"); }
-  x = CAR(args);
-  if SYMBOLP(x) { return x; }
-  switch (x->header.type) {
-  case GRN_CELL_STR :
-    v = grn_ql_mk_symbol2(ctx, STRVALUE(x), STRSIZE(x), 0);
-    break;
-  default :
-    QLERR("can't convert into string");
-  }
-  return v;
-}
-static grn_cell *
-nf_containp(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  int r = 0;
-  grn_id id;
-  grn_cell *e, *car;
-  if (!PAIRP(args)) { QLERR("list required"); }
-  POP(e, args);
-  switch (e->header.type) {
-  case GRN_UVECTOR :
-    {
-      grn_obj *u = e->u.p.value, *range = grn_ctx_at(ctx, u->header.domain);
-      grn_id *v, *ve = (grn_id *)GRN_BULK_CURR(u);
-      POP(e, args);
-      switch (e->header.type) {
-      case GRN_CELL_LIST :
-        r = 1;
-        while (r && PAIRP(e)) {
-          POP(car, e);
-          switch (car->header.type) {
-          case GRN_CELL_OBJECT :
-            if (car->header.domain == u->header.domain && (id = car->u.o.id)) {
-              for (v = (grn_id *)GRN_BULK_HEAD(u);; v++) {
-                if (v == ve) { r = 0; break; }
-                if (*v == id) { break; }
-              }
-            } else {
-              r = 0;
-            }
-            break;
-          case GRN_CELL_STR :
-            id = grn_table_get(ctx, range, STRVALUE(car), STRSIZE(car));
-            if (id) {
-              for (v = (grn_id *)GRN_BULK_HEAD(u);; v++) {
-                if (v == ve) { r = 0; break; }
-                if (*v == id) { break; }
-              }
-            } else {
-              r = 0;
-            }
-            break;
-          default :
-            r = 0;
-            break;
-          }
-        }
-        break;
-      case GRN_CELL_STR :
-        id = grn_table_get(ctx, range, STRVALUE(e), STRSIZE(e));
-        if (id) {
-          for (v = (grn_id *)GRN_BULK_HEAD(u);; v++) {
-            if (v == ve) { r = 0; break; }
-            if (*v == id) { r = 1; break; }
-          }
-        } else {
-          r = 0;
-        }
-        break;
-      case GRN_CELL_OBJECT :
-        if (e->header.domain == u->header.domain && (id = e->u.o.id)) {
-          for (v = (grn_id *)GRN_BULK_HEAD(u);; v++) {
-            if (v == ve) { r = 0; break; }
-            if (*v == id) { r = 1; break; }
-          }
-        } else {
-          r = 0;
-        }
-        break;
-      default :
-        r = 0;
-        break;
-      }
-    }
-    break;
-  case GRN_CELL_OBJECT :
-    {
-      grn_id domain = e->header.domain;
-      id = e->u.o.id;
-      POP(e, args);
-      if (e->header.type == GRN_CELL_LIST) { e = CAR(e); }
-      switch (e->header.type) {
-      case GRN_CELL_STR :
-        {
-          grn_obj *range = grn_ctx_at(ctx, domain);
-          if (grn_table_get(ctx, range, STRVALUE(e), STRSIZE(e)) == id) { r = 1; }
-        }
-        break;
-      case GRN_CELL_OBJECT :
-        if (e->header.domain == domain && e->u.o.id == id) { r = 1; }
-        break;
-      default :
-        r = 0;
-        break;
-      }
-    }
-    break;
-  default :
-    QLERR("uvector or object required");
-    break;
-  }
-  return r ? T : F;
-}
-
-#define GEO_RESOLUTION   3600000
-#define GEO_RADIOUS      6357303
-#define GEO_BES_C1       6334834
-#define GEO_BES_C2       6377397
-#define GEO_BES_C3       0.006674
-#define GEO_GRS_C1       6335439
-#define GEO_GRS_C2       6378137
-#define GEO_GRS_C3       0.006694
-#define GEO_INT2RAD(x)   ((M_PI * x) / (GEO_RESOLUTION * 180))
-
-static grn_cell *
-nf_geo_distance1(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  grn_cell *e;
-  double lng1, lat1, lng2, lat2, x, y, d;
-  if (!PAIRP(args)) { QLERR("list required"); }
-  POP(e, args);
-  if (!INTP(e)) { QLERR("integer required"); }
-  lng1 = GEO_INT2RAD(IVALUE(e));
-  POP(e, args);
-  if (!INTP(e)) { QLERR("integer required"); }
-  lat1 = GEO_INT2RAD(IVALUE(e));
-  POP(e, args);
-  if (!INTP(e)) { QLERR("integer required"); }
-  lng2 = GEO_INT2RAD(IVALUE(e));
-  POP(e, args);
-  if (!INTP(e)) { QLERR("integer required"); }
-  lat2 = GEO_INT2RAD(IVALUE(e));
-  x = (lng2 - lng1) * cos((lat1 + lat2) * 0.5);
-  y = (lat2 - lat1);
-  d = sqrt((x * x) + (y * y)) * GEO_RADIOUS;
-  GRN_CELL_NEW(ctx, e);
-  SETFLOAT(e, d);
-  return e;
-}
-static grn_cell *
-nf_geo_distance2(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  grn_cell *e;
-  double lng1, lat1, lng2, lat2, x, y, d;
-  if (!PAIRP(args)) { QLERR("list required"); }
-  POP(e, args);
-  if (!INTP(e)) { QLERR("integer required"); }
-  lng1 = GEO_INT2RAD(IVALUE(e));
-  POP(e, args);
-  if (!INTP(e)) { QLERR("integer required"); }
-  lat1 = GEO_INT2RAD(IVALUE(e));
-  POP(e, args);
-  if (!INTP(e)) { QLERR("integer required"); }
-  lng2 = GEO_INT2RAD(IVALUE(e));
-  POP(e, args);
-  if (!INTP(e)) { QLERR("integer required"); }
-  lat2 = GEO_INT2RAD(IVALUE(e));
-  x = sin(fabs(lng2 - lng1) * 0.5);
-  y = sin(fabs(lat2 - lat1) * 0.5);
-  d = asin(sqrt((y * y) + cos(lat1) * cos(lat2) * x * x)) * 2 * GEO_RADIOUS;
-  GRN_CELL_NEW(ctx, e);
-  SETFLOAT(e, d);
-  return e;
-}
-static grn_cell *
-nf_geo_distance3(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  grn_cell *e;
-  double lng1, lat1, lng2, lat2, p, q, m, n, x, y, d;
-  if (!PAIRP(args)) { QLERR("list required"); }
-  POP(e, args);
-  if (!INTP(e)) { QLERR("integer required"); }
-  lng1 = GEO_INT2RAD(IVALUE(e));
-  POP(e, args);
-  if (!INTP(e)) { QLERR("integer required"); }
-  lat1 = GEO_INT2RAD(IVALUE(e));
-  POP(e, args);
-  if (!INTP(e)) { QLERR("integer required"); }
-  lng2 = GEO_INT2RAD(IVALUE(e));
-  POP(e, args);
-  if (!INTP(e)) { QLERR("integer required"); }
-  lat2 = GEO_INT2RAD(IVALUE(e));
-  p = (lat1 + lat2) * 0.5;
-  q = (1 - GEO_BES_C3 * sin(p) * sin(p));
-  m = GEO_BES_C1 / sqrt(q * q * q);
-  n = GEO_BES_C2 / sqrt(q);
-  x = n * cos(p) * fabs(lng1 - lng2);
-  y = m * fabs(lat1 - lat2);
-  d = sqrt((x * x) + (y * y));
-  GRN_CELL_NEW(ctx, e);
-  SETFLOAT(e, d);
-  return e;
-}
-static grn_cell *
-nf_geo_distance4(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  grn_cell *e;
-  double lng1, lat1, lng2, lat2, p, q, m, n, x, y, d;
-  if (!PAIRP(args)) { QLERR("list required"); }
-  POP(e, args);
-  if (!INTP(e)) { QLERR("integer required"); }
-  lng1 = GEO_INT2RAD(IVALUE(e));
-  POP(e, args);
-  if (!INTP(e)) { QLERR("integer required"); }
-  lat1 = GEO_INT2RAD(IVALUE(e));
-  POP(e, args);
-  if (!INTP(e)) { QLERR("integer required"); }
-  lng2 = GEO_INT2RAD(IVALUE(e));
-  POP(e, args);
-  if (!INTP(e)) { QLERR("integer required"); }
-  lat2 = GEO_INT2RAD(IVALUE(e));
-  p = (lat1 + lat2) * 0.5;
-  q = (1 - GEO_GRS_C3 * sin(p) * sin(p));
-  m = GEO_GRS_C1 / sqrt(q * q * q);
-  n = GEO_GRS_C2 / sqrt(q);
-  x = n * cos(p) * fabs(lng1 - lng2);
-  y = m * fabs(lat1 - lat2);
-  d = sqrt((x * x) + (y * y));
-  GRN_CELL_NEW(ctx, e);
-  SETFLOAT(e, d);
-  return e;
-}
-static grn_cell *
-nf_geo_withinp(grn_ctx *ctx, grn_cell *args, grn_ql_co *co)
-{
-  grn_cell *e;
-  int64_t ln0, la0, ln1, la1, ln2, la2, ln3, la3;
-  double lng0, lat0, lng1, lat1, lng2, lat2, x, y, d;
-  if (!PAIRP(args)) { QLERR("list required"); }
-  POP(e, args);
-  if (!INTP(e)) { QLERR("integer required"); }
-  ln0 = IVALUE(e);
-  POP(e, args);
-  if (!INTP(e)) { QLERR("integer required"); }
-  la0 = IVALUE(e);
-  POP(e, args);
-  if (!INTP(e)) { QLERR("integer required"); }
-  ln1 = IVALUE(e);
-  POP(e, args);
-  if (!INTP(e)) { QLERR("integer required"); }
-  la1 = IVALUE(e);
-  if (args == NIL) { return T; }
-  POP(e, args);
-  if (args == NIL) {
-    lng0 = GEO_INT2RAD(ln0);
-    lat0 = GEO_INT2RAD(la0);
-    lng1 = GEO_INT2RAD(ln1);
-    lat1 = GEO_INT2RAD(la1);
-    x = (lng1 - lng0) * cos((lat0 + lat1) * 0.5);
-    y = (lat1 - lat0);
-    d = sqrt((x * x) + (y * y)) * GEO_RADIOUS;
-    switch (e->header.type) {
-    case GRN_CELL_INT : return d <= IVALUE(e) ? T : F;
-    case GRN_CELL_FLOAT : return d <= FVALUE(e) ? T : F;
-    default : QLERR("integer or float value required");
-    }
-  }
-  if (!INTP(e)) { QLERR("integer required"); }
-  ln2 = IVALUE(e);
-  POP(e, args);
-  if (!INTP(e)) { QLERR("integer required"); }
-  la2 = IVALUE(e);
-  if (args == NIL) {
-    lng0 = GEO_INT2RAD(ln0);
-    lat0 = GEO_INT2RAD(la0);
-    lng1 = GEO_INT2RAD(ln1);
-    lat1 = GEO_INT2RAD(la1);
-    lng2 = GEO_INT2RAD(ln2);
-    lat2 = GEO_INT2RAD(la2);
-    x = (lng1 - lng0) * cos((lat0 + lat1) * 0.5);
-    y = (lat1 - lat0);
-    d = (x * x) + (y * y);
-    x = (lng2 - lng1) * cos((lat1 + lat2) * 0.5);
-    y = (lat2 - lat1);
-    return d <= (x * x) + (y * y) ? T : F;
-  }
-  POP(e, args);
-  if (!INTP(e)) { QLERR("integer required"); }
-  ln3 = IVALUE(e);
-  POP(e, args);
-  if (!INTP(e)) { QLERR("integer required"); }
-  la3 = IVALUE(e);
-  return ((ln2 <= ln0) && (ln0 <= ln3) && (la2 <= la0) && (la0 <= la3)) ? T : F;
-}
-
-/* ========== Initialization of internal keywords ========== */
-
-inline static void
-mk_syntax(grn_ctx *ctx, uint8_t op, const char *name)
-{
-  grn_cell *x;
-  if ((x = INTERN(name)) != F) {
-    x->header.type = GRN_CELL_SYNTAX;
-    SYNTAXNUM(x) = op;
-  }
-}
-
-inline static void
-mk_proc(grn_ctx *ctx, uint8_t op, const char *name)
-{
-  grn_cell *x;
-  if ((x = INTERN(name)) != F) {
-    x->header.type = GRN_CELL_PROC;
-    IVALUE(x) = (int64_t) op;
-  }
-}
-
-void
-grn_ql_init_const(void)
-{
-  static grn_cell _NIL, _T, _F;
-  /* init NIL */
-  NIL = &_NIL;
-  NIL->header.type = GRN_VOID;
-  CAR(NIL) = CDR(NIL) = NIL;
-  /* init T */
-  T = &_T;
-  T->header.type = GRN_VOID;
-  CAR(T) = CDR(T) = T;
-  /* init F */
-  F = &_F;
-  F->header.type = GRN_VOID;
-  CAR(F) = CDR(F) = F;
-}
-
-inline static void
-init_vars_global(grn_ctx *ctx)
-{
-  grn_cell *x;
-  /* init global_env */
-  ctx->impl->global_env = CONS(NIL, NIL);
-  /* init else */
-  if ((x = INTERN("else")) != F) {
-    CAR(ctx->impl->global_env) = CONS(CONS(x, T), CAR(ctx->impl->global_env));
-  }
-}
-
-inline static void
-init_syntax(grn_ctx *ctx)
-{
-  /* init syntax */
-  mk_syntax(ctx, OP_LAMBDA, "lambda");
-  mk_syntax(ctx, OP_QUOTE, "quote");
-  mk_syntax(ctx, OP_DEF0, "define");
-  mk_syntax(ctx, OP_IF0, "if");
-  mk_syntax(ctx, OP_BEGIN, "begin");
-  mk_syntax(ctx, OP_SET0, "set!");
-  mk_syntax(ctx, OP_LET0, "let");
-  mk_syntax(ctx, OP_LET0AST, "let*");
-  mk_syntax(ctx, OP_LET0REC, "letrec");
-  mk_syntax(ctx, OP_COND0, "cond");
-  mk_syntax(ctx, OP_DELAY, "delay");
-  mk_syntax(ctx, OP_AND0, "and");
-  mk_syntax(ctx, OP_OR0, "or");
-  mk_syntax(ctx, OP_C0STREAM, "cons-stream");
-  mk_syntax(ctx, OP_0MACRO, "define-macro");
-  mk_syntax(ctx, OP_CASE0, "case");
-  mk_syntax(ctx, OP_QQUOTE0, "quasiquote");
-}
-
-inline static void
-init_procs(grn_ctx *ctx)
-{
-  /* init procedure */
-  mk_proc(ctx, OP_PEVAL, "eval");
-  mk_proc(ctx, OP_PAPPLY, "apply");
-  mk_proc(ctx, OP_CONTINUATION, "call-with-current-continuation");
-  mk_proc(ctx, OP_FORCE, "force");
-  mk_proc(ctx, OP_SETCAR, "set-car!");
-  mk_proc(ctx, OP_SETCDR, "set-cdr!");
-  mk_proc(ctx, OP_READ, "read");
-  mk_proc(ctx, OP_LOAD, "load");
-  mk_proc(ctx, OP_ERR1, "error");
-  mk_proc(ctx, OP_PUT, "put");
-  mk_proc(ctx, OP_GET, "get");
-  mk_proc(ctx, OP_QUIT, "quit");
-  mk_proc(ctx, OP_SDOWN, "shutdown");
-  grn_ql_def_native_func(ctx, "+", nf_add);
-  grn_ql_def_native_func(ctx, "-", nf_sub);
-  grn_ql_def_native_func(ctx, "*", nf_mul);
-  grn_ql_def_native_func(ctx, "/", nf_div);
-  grn_ql_def_native_func(ctx, "remainder", nf_rem);
-  grn_ql_def_native_func(ctx, "car", nf_car);
-  grn_ql_def_native_func(ctx, "cdr", nf_cdr);
-  grn_ql_def_native_func(ctx, "cons", nf_cons);
-  grn_ql_def_native_func(ctx, "not", nf_not);
-  grn_ql_def_native_func(ctx, "boolean?", nf_bool);
-  grn_ql_def_native_func(ctx, "symbol?", nf_symbol);
-  grn_ql_def_native_func(ctx, "number?", nf_number);
-  grn_ql_def_native_func(ctx, "string?", nf_string);
-  grn_ql_def_native_func(ctx, "procedure?", nf_proc);
-  grn_ql_def_native_func(ctx, "pair?", nf_pair);
-  grn_ql_def_native_func(ctx, "eqv?", nf_eqv);
-  grn_ql_def_native_func(ctx, "logtest", nf_logtest);
-  grn_ql_def_native_func(ctx, "eq?", nf_eq);
-  grn_ql_def_native_func(ctx, "null?", nf_null);
-  grn_ql_def_native_func(ctx, "zero?", nf_zerop);
-  grn_ql_def_native_func(ctx, "positive?", nf_posp);
-  grn_ql_def_native_func(ctx, "negative?", nf_negp);
-  grn_ql_def_native_func(ctx, "=", nf_neq);
-  grn_ql_def_native_func(ctx, "<", nf_less);
-  grn_ql_def_native_func(ctx, ">", nf_gre);
-  grn_ql_def_native_func(ctx, "<=", nf_leq);
-  grn_ql_def_native_func(ctx, ">=", nf_geq);
-  grn_ql_def_native_func(ctx, "write", nf_write);
-  grn_ql_def_native_func(ctx, "display", nf_display);
-  grn_ql_def_native_func(ctx, "newline", nf_newline);
-  grn_ql_def_native_func(ctx, "reverse", nf_reverse);
-  grn_ql_def_native_func(ctx, "append", nf_append);
-  grn_ql_def_native_func(ctx, "gc", nf_gc);
-  grn_ql_def_native_func(ctx, "gc-verbose", nf_gcverb);
-  grn_ql_def_native_func(ctx, "native?", nf_nativep);
-  grn_ql_def_native_func(ctx, "length", nf_length);  /* a.k */
-  grn_ql_def_native_func(ctx, "assq", nf_assq);  /* a.k */
-  grn_ql_def_native_func(ctx, "get-closure-code", nf_get_closure);  /* a.k */
-  grn_ql_def_native_func(ctx, "closure?", nf_closurep);  /* a.k */
-  grn_ql_def_native_func(ctx, "macro?", nf_macrop);  /* a.k */
-  grn_ql_def_native_func(ctx, "void?", nf_voidp);
-  grn_ql_def_native_func(ctx, "list", nf_list);
-  grn_ql_def_native_func(ctx, "batchmode", nf_batchmode);
-  grn_ql_def_native_func(ctx, "loglevel", nf_loglevel);
-  grn_ql_def_native_func(ctx, "log-put", nf_log_put);
-  grn_ql_def_native_func(ctx, "now", nf_now);
-  grn_ql_def_native_func(ctx, "timestr", nf_timestr);
-  grn_ql_def_native_func(ctx, "x->time", nf_totime);
-  grn_ql_def_native_func(ctx, "x->number", nf_tonumber);
-  grn_ql_def_native_func(ctx, "substrb", nf_substrb);
-  grn_ql_def_native_func(ctx, "x->b32h", nf_tob32h);
-  grn_ql_def_native_func(ctx, "intern", nf_intern);
-  grn_ql_def_native_func(ctx, "contain?", nf_containp);
-  grn_ql_def_native_func(ctx, "geo-distance1", nf_geo_distance1);
-  grn_ql_def_native_func(ctx, "geo-distance2", nf_geo_distance2);
-  grn_ql_def_native_func(ctx, "geo-distance3", nf_geo_distance3);
-  grn_ql_def_native_func(ctx, "geo-distance4", nf_geo_distance4);
-  grn_ql_def_native_func(ctx, "geo-within?", nf_geo_withinp);
-}
-
-/* initialize several globals */
-void
-grn_ql_init_globals(grn_ctx *ctx)
-{
-  init_vars_global(ctx);
-  init_syntax(ctx);
-  init_procs(ctx);
-  ctx->impl->output = grn_ctx_concat_func;
-  /* initialization of global pointers to special symbols */
-}

  Modified: lib/store.c (+1 -1)
===================================================================
--- lib/store.c    2012-02-03 11:43:41 +0900 (983f354)
+++ lib/store.c    2012-01-17 12:10:35 +0900 (80c77b8)
@@ -17,7 +17,7 @@
 #include "groonga_in.h"
 #include "str.h"
 #include "store.h"
-#include "ql.h"
+#include "ctx_impl.h"
 #include "output.h"
 #include <string.h>
 

  Modified: lib/token.c (+1 -1)
===================================================================
--- lib/token.c    2012-02-03 11:43:41 +0900 (f8cc681)
+++ lib/token.c    2012-01-17 12:10:35 +0900 (f387b44)
@@ -18,7 +18,7 @@
 #include "groonga_in.h"
 #include <string.h>
 #include <ctype.h>
-#include "ql.h"
+#include "ctx_impl.h"
 #include "token.h"
 #include "pat.h"
 #include "dat.h"

  Modified: src/grnslap.c (+1 -1)
===================================================================
--- src/grnslap.c    2012-02-03 11:43:41 +0900 (73e09f5)
+++ src/grnslap.c    2012-01-17 12:10:35 +0900 (a2d3ec6)
@@ -17,7 +17,7 @@
 */
 
 #include "lib/com.h"
-#include "lib/ql.h"
+#include "lib/ctx_impl.h"
 #include <string.h>
 #include <stdio.h>
 #ifdef HAVE_SYS_WAIT_H

  Modified: src/groonga.c (+1 -1)
===================================================================
--- src/groonga.c    2012-02-03 11:43:41 +0900 (2da335e)
+++ src/groonga.c    2012-01-17 12:10:35 +0900 (bdcc6c9)
@@ -22,7 +22,7 @@
 #include "lib/groonga_in.h"
 
 #include "lib/com.h"
-#include "lib/ql.h"
+#include "lib/ctx_impl.h"
 #include "lib/proc.h"
 #include "lib/db.h"
 #include "lib/util.h"

  Modified: test/unit/core/Makefile.am (+0 -2)
===================================================================
--- test/unit/core/Makefile.am    2012-02-03 11:43:41 +0900 (473bc7b)
+++ test/unit/core/Makefile.am    2012-01-17 12:10:35 +0900 (3e5c9d3)
@@ -14,7 +14,6 @@ noinst_LTLIBRARIES =				\
 	test-performance.la			\
 	test-stress.la				\
 	test-public-context.la			\
-	test-query.la				\
 	test-table.la				\
 	test-table-patricia-trie-cursor.la	\
 	test-table-sort-geo.la			\
@@ -102,7 +101,6 @@ test_patricia_trie_search_la_SOURCES	= test-patricia-trie-search.c
 test_performance_la_SOURCES		= test-performance.c
 test_stress_la_SOURCES			= test-stress.c
 test_public_context_la_SOURCES		= test-public-context.c
-test_query_la_SOURCES			= test-query.c
 test_table_la_SOURCES			= test-table.c
 test_table_patricia_trie_cursor_la_SOURCES	= test-table-patricia-trie-cursor.c
 test_table_sort_geo_la_SOURCES		= test-table-sort-geo.c

  Modified: test/unit/core/test-inverted-index.c (+42 -10)
===================================================================
--- test/unit/core/test-inverted-index.c    2012-02-03 11:43:41 +0900 (3ad45c4)
+++ test/unit/core/test-inverted-index.c    2012-01-17 12:10:35 +0900 (2d10c6a)
@@ -723,13 +723,28 @@ test_mroonga_index(void)
   /* boolean search */
   {
     grn_id id, docid;
+    grn_obj *match_columns, *match_columns_variable;
+    grn_obj *expression, *expression_variable;
     grn_obj *res;
-    grn_query *query;
     grn_table_cursor *tc;
+    const char *match_columns_expression = "c1";
     const char *qstr = "+22 -55";
+
+    GRN_EXPR_CREATE_FOR_QUERY(context, t1,
+                              match_columns, match_columns_variable);
+    grn_expr_parse(context, match_columns,
+                   match_columns_expression,
+                   strlen(match_columns_expression),
+                   NULL, GRN_OP_MATCH, GRN_OP_AND,
+                   GRN_EXPR_SYNTAX_SCRIPT);
+    GRN_EXPR_CREATE_FOR_QUERY(context, t1, expression, expression_variable);
     res = grn_table_create(context, NULL, 0, NULL, GRN_TABLE_HASH_KEY, t1, 0);
-    query = grn_query_open(context, qstr, strlen(qstr), GRN_OP_OR, 32);
-    grn_obj_search(context, ft, (grn_obj*) query, res, GRN_OP_OR, NULL);
+    grn_test_assert(grn_expr_parse(context, expression,
+                                   qstr, strlen(qstr),
+                                   match_columns,
+                                   GRN_OP_MATCH, GRN_OP_OR,
+                                   GRN_EXPR_SYNTAX_QUERY));
+    grn_table_select(context, t1, expression, res, GRN_OP_OR);
     cut_assert_equal_int(1, grn_table_size(context, res));
     tc = grn_table_cursor_open(context, res, NULL, 0, NULL, 0, 0, -1, 0);
     while ((id = grn_table_cursor_next(context, tc))) {
@@ -740,7 +755,8 @@ test_mroonga_index(void)
       cut_assert_equal_int(8 ,GRN_TEXT_LEN(&buff));
       cut_assert_equal_substring("11 22 33", (char*) GRN_BULK_HEAD(&buff),GRN_TEXT_LEN(&buff));
     }
-    grn_query_close(context, query);
+    grn_obj_close(context, expression);
+    grn_obj_close(context, match_columns);
     grn_table_cursor_close(context ,tc);
     grn_obj_close(context, res);
   }
@@ -862,16 +878,31 @@ test_mroonga_index_score(void)
   {
     grn_id id, docid;
     grn_obj *res;
-    grn_query *query;
+    grn_obj *match_columns, *match_columns_variable;
+    grn_obj *expression, *expression_variable;
     grn_table_cursor *tc;
     grn_obj score, *score_column;
+    const char *match_columns_expression = "c1 * 5";
     const char *qstr = "+22 -55";
+
+    GRN_EXPR_CREATE_FOR_QUERY(context, t1,
+                              match_columns, match_columns_variable);
+    grn_expr_parse(context, match_columns,
+                   match_columns_expression,
+                   strlen(match_columns_expression),
+                   NULL, GRN_OP_MATCH, GRN_OP_AND,
+                   GRN_EXPR_SYNTAX_SCRIPT);
+    GRN_EXPR_CREATE_FOR_QUERY(context, t1, expression, expression_variable);
     res = grn_table_create(context, NULL, 0, NULL,
                            GRN_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC, t1, 0);
-    GRN_UINT32_INIT(&score, 0);
-    query = grn_query_open(context, qstr, strlen(qstr), GRN_OP_OR, 32);
-    grn_obj_search(context, ft, (grn_obj*) query, res, GRN_OP_OR, NULL);
+    grn_test_assert(grn_expr_parse(context, expression,
+                                   qstr, strlen(qstr),
+                                   match_columns,
+                                   GRN_OP_MATCH, GRN_OP_OR,
+                                   GRN_EXPR_SYNTAX_QUERY));
+    grn_table_select(context, t1, expression, res, GRN_OP_OR);
     cut_assert_equal_int(1, grn_table_size(context, res));
+    GRN_UINT32_INIT(&score, 0);
     score_column = grn_obj_column(context, res, "_score", 6);
     tc = grn_table_cursor_open(context, res, NULL, 0, NULL, 0, 0, -1, 0);
     while ((id = grn_table_cursor_next(context, tc))) {
@@ -879,12 +910,13 @@ test_mroonga_index_score(void)
       grn_table_get_key(context, res, id, &docid, sizeof(grn_id));
       cut_assert_equal_int(3, docid);
       cut_assert_not_null(grn_obj_get_value(context, c1, docid, &buff));
-      cut_assert_equal_int(8 ,GRN_TEXT_LEN(&buff));
+      cut_assert_equal_int(8, GRN_TEXT_LEN(&buff));
       cut_assert_equal_substring("11 22 33", (char*) GRN_BULK_HEAD(&buff),GRN_TEXT_LEN(&buff));
       grn_obj_get_value(context, score_column, id, &score);
       cut_assert_equal_uint(5, GRN_UINT32_VALUE(&score));
     }
-    grn_query_close(context, query);
+    grn_obj_close(context, expression);
+    grn_obj_close(context, match_columns);
     grn_table_cursor_close(context ,tc);
     grn_obj_close(context, score_column);
     grn_obj_close(context, res);

  Deleted: test/unit/core/test-query.c (+0 -64) 100644
===================================================================
--- test/unit/core/test-query.c    2012-02-03 11:43:41 +0900 (bd61eb9)
+++ /dev/null
@@ -1,64 +0,0 @@
-/* -*- c-basic-offset: 2; coding: utf-8 -*- */
-/*
-  Copyright (C) 2008-2009  Kouhei Sutou <kou****@cozmi*****>
-
-  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
-*/
-
-#include <groonga.h>
-
-#include <gcutter.h>
-
-#include "../lib/grn-assertions.h"
-
-void attributes_open_broken_utf8(void);
-void test_open_broken_utf8(void);
-
-static grn_ctx *context;
-static grn_query *query;
-
-void
-cut_setup(void)
-{
-  context = g_new0(grn_ctx, 1);
-  grn_ctx_init(context, GRN_CTX_USE_QL);
-  query = NULL;
-}
-
-void
-cut_teardown(void)
-{
-  if (context) {
-    if (query)
-      grn_obj_close(context, (grn_obj *)query);
-    grn_ctx_fin(context);
-    g_free(context);
-  }
-}
-
-void
-attributes_open_broken_utf8(void)
-{
-  cut_set_attributes("ML", "senna-dev:1070",
-                     NULL);
-}
-
-void
-test_open_broken_utf8(void)
-{
-  gchar utf8[] = "\"あ\"";
-  GRN_CTX_SET_ENCODING(context, GRN_ENC_UTF8);
-  query = grn_query_open(context, utf8, 2, GRN_OP_OR, 10);
-  cut_assert_not_null(query);
-}




Groonga-commit メーリングリストの案内
Back to archive index