Browse Source

Rework term sets to use own iterator.

scossu 3 days ago
parent
commit
ae7166f241
8 changed files with 227 additions and 153 deletions
  1. 7 7
      Makefile
  2. 46 69
      src/lua_graph.c
  3. 128 47
      src/lua_term.c
  4. 9 9
      src/lua_triple.c
  5. 11 8
      src/lua_volksdata.h
  6. 4 1
      src/stackdump.h
  7. 18 11
      test.lua
  8. 4 1
      volksdata-scm-1.rockspec

+ 7 - 7
Makefile

@@ -1,8 +1,8 @@
-LOCAL ?= 0
-DEBUG ?= 0
+LOCAL := $(filter 1,$(LOCAL))
+DEBUG := $(filter 1,$(DEBUG))
 
-LOCAL_PREFIX ?= $(HOME)/.local
-ifneq ($(LOCAL), 0)
+LOCAL_PREFIX ?= $(HOME)/.luarocks
+ifeq ($(LOCAL), 1)
 PREFIX ?= $(LOCAL_PREFIX)
 else
 PREFIX ?= /usr/local
@@ -14,7 +14,7 @@ VOLK_LIBDIR = $(VOLK_ROOT)/build
 INCLUDE = -I$(PREFIX)/include
 VOLK_INCLUDE = -I$(VOLK_ROOT)/include
 CFLAGS = -shared -Wall -Wextra -fPIC
-ifneq ($(DEBUG), 0)
+ifeq ($(DEBUG), 1)
 CFLAGS += -DDEBUG -Og -ggdb
 else
 CFLAGS += -DNDEBUG -O3 -g0
@@ -27,7 +27,7 @@ LUAC_SRC = $(wildcard src/*.c)
 OBJ = lua_volksdata.so
 OBJPATH = lib/$(OBJ)
 
-ifneq ($(DEBUG), 0)
+ifeq ($(DEBUG), 1)
 VOLK_LIB = $(VOLK_LIBDIR)/libvolksdata_dbg.a
 else
 VOLK_LIB = $(VOLK_LIBDIR)/libvolksdata.a
@@ -55,7 +55,7 @@ $(OBJPATH): src/*.c src/lua_volksdata.h
 
 install: lib
 	mkdir -p $(INSTALL_DIR)
-	cp $(OBJPATH) $(INSTALL_DIR)
+	cp $(OBJPATH) $(INSTALL_DIR)/volksdata.so
 
 
 .PHONY: uninstall

+ 46 - 69
src/lua_graph.c

@@ -54,9 +54,8 @@ static int l_graph_list (lua_State *L)
 
     VOLK_TermSet *ts = VOLK_graph_list (store);
     LUA_NLCHECK (ts, "Error retrieving context list.");
-    LUA_PCHECK (term_set_to_table (L, ts), "Error generating term set table");
 
-    return 1;
+    return tset_to_udata (L, ts);
 }
 
 
@@ -78,7 +77,7 @@ static int l_graph_gc (lua_State *L)
 
 static int l_graph_get_uri (lua_State *L)
 {
-    const VOLK_Graph *gr = check_graph (L);
+    const VOLK_Graph *gr = check_graph (L, 1);
 
     VOLK_Term **tp = lua_newuserdata (L, sizeof *tp);
     luaL_getmetatable (L, "VOLK.Term");
@@ -93,7 +92,7 @@ static int l_graph_get_uri (lua_State *L)
 
 static int l_graph_to_string (lua_State *L)
 {
-    const VOLK_Graph *gr = check_graph (L);
+    const VOLK_Graph *gr = check_graph (L, 1);
     lua_pushfstring (
             L, "VOLK.Graph @%p <%s>: %d triples",
             gr, VOLK_graph_uri (gr)->data, VOLK_graph_size (gr));
@@ -104,7 +103,7 @@ static int l_graph_to_string (lua_State *L)
 
 static int l_graph_len (lua_State *L)
 {
-    const VOLK_Graph *gr = check_graph (L);
+    const VOLK_Graph *gr = check_graph (L, 1);
     lua_pushinteger (L, VOLK_graph_size (gr));
 
     return 1;
@@ -113,16 +112,16 @@ static int l_graph_len (lua_State *L)
 
 static int l_graph_copy (lua_State *L)
 {
-    const VOLK_Graph *src = check_graph (L);
-    VOLK_Graph *dest = *(VOLK_Graph **)luaL_checkudata (L, 2, "VOLK.Graph");
+    const VOLK_Graph *src = check_graph (L, 1);
+    VOLK_Graph *dest = check_graph (L, 2);
     const VOLK_Term *s, *p, *o;
 
     if lua_isnoneornil (L, 3) s = NULL;
-    else s = *(VOLK_Term **)luaL_checkudata (L, 3, "VOLK.Term");
+    else s = check_term (L, 3);
     if lua_isnoneornil (L, 4) p = NULL;
-    else p = *(VOLK_Term **)luaL_checkudata (L, 4, "VOLK.Term");
+    else p = check_term (L, 4);
     if lua_isnoneornil (L, 5) o = NULL;
-    else o = *(VOLK_Term **)luaL_checkudata (L, 5, "VOLK.Term");
+    else o = check_term (L, 5);
 
     LUA_PCHECK (VOLK_graph_copy_contents (
                 src, dest, s, p, o), "Error copying graph.");
@@ -133,9 +132,8 @@ static int l_graph_copy (lua_State *L)
 
 static int l_graph_equals (lua_State *L)
 {
-    const VOLK_Graph *gr1 = check_graph (L);
-    const VOLK_Graph *gr2 =
-        *(VOLK_Graph **)luaL_checkudata (L, 2, "VOLK.Graph");
+    const VOLK_Graph *gr1 = check_graph (L, 1);
+    const VOLK_Graph *gr2 = check_graph (L, 2);
 
     LOG_DEBUG ("Comparing graphs %p %p", gr1, gr2);
     int eq_rc = VOLK_graph_equals (gr1, gr2);
@@ -147,9 +145,8 @@ static int l_graph_equals (lua_State *L)
 
 static int l_graph_contains (lua_State *L)
 {
-    const VOLK_Graph *gr = check_graph (L);
-    const VOLK_Triple *spo =
-        *(VOLK_Triple **)luaL_checkudata (L, 2, "VOLK.Triple");
+    const VOLK_Graph *gr = check_graph (L, 1);
+    const VOLK_Triple *spo = check_triple (L, 2);
 
     lua_pushboolean (L, VOLK_graph_contains (gr, spo));
 
@@ -160,7 +157,7 @@ static int l_graph_contains (lua_State *L)
 /// Initialize iterative addition.
 static int l_graph_add_init (lua_State *L)
 {
-    VOLK_Graph *gr = check_graph (L);
+    VOLK_Graph *gr = check_graph (L, 1);
 
     VOLK_GraphIterator **it_p = lua_newuserdata (L, sizeof *it_p);
     luaL_getmetatable (L, "VOLK.GraphIterator");
@@ -177,9 +174,9 @@ static int l_graph_add_init (lua_State *L)
 static int l_graph_add_iter (lua_State *L)
 {
     VOLK_GraphIterator **it_p = luaL_checkudata (L, 1, "VOLK.GraphIterator");
-    const VOLK_Triple **spo = luaL_checkudata (L, 2, "VOLK.Triple");
+    const VOLK_Triple *spo = check_triple (L, 2);
 
-    LUA_PCHECK (VOLK_graph_add_iter (*it_p, *spo), "Error adding triple");
+    LUA_PCHECK (VOLK_graph_add_iter (*it_p, spo), "Error adding triple");
 
     return 0;
 }
@@ -200,7 +197,7 @@ static int l_graph_add_done (lua_State *L)
  */
 static int l_graph_add (lua_State *L)
 {
-    VOLK_Graph *gr = check_graph (L);
+    VOLK_Graph *gr = check_graph (L, 1);
     int rc;
     VOLK_rc volk_rc= VOLK_NOACTION;
     size_t i = 0, ct = 0;
@@ -208,8 +205,7 @@ static int l_graph_add (lua_State *L)
 
     while ((rc = lua_rawgeti (L, 2, ++i)) != LUA_TNIL) {
         //LOG_DEBUG ("Triple type: %s", lua_typename (L, rc));
-        const VOLK_Triple *spo =
-            *(VOLK_Triple **)luaL_checkudata (L, -1, "VOLK.Triple");
+        const VOLK_Triple *spo = check_triple (L, -1);
         LOG_DEBUG (
                 "Got triple %d: {%s %s %s}\n",
                 i, spo->s->data, spo->p->data, spo->o->data);
@@ -230,14 +226,14 @@ static int l_graph_add (lua_State *L)
 
 static int l_graph_remove (lua_State *L)
 {
-    VOLK_Graph *gr = check_graph (L);
+    VOLK_Graph *gr = check_graph (L, 1);
     const VOLK_Term *s, *p, *o;
     if lua_isnoneornil (L, 2) s = NULL;
-    else s = *(VOLK_Term **)luaL_checkudata (L, 2, "VOLK.Term");
+    else s = check_term (L, 2);
     if lua_isnoneornil (L, 3) p = NULL;
-    else p = *(VOLK_Term **)luaL_checkudata (L, 3, "VOLK.Term");
+    else p = check_term (L, 3);
     if lua_isnoneornil (L, 4) o = NULL;
-    else o = *(VOLK_Term **)luaL_checkudata (L, 4, "VOLK.Term");
+    else o = check_term (L, 4);
 
     size_t ct;
     VOLK_rc rc = VOLK_graph_remove (gr, s, p, o, &ct);
@@ -279,14 +275,14 @@ static int graph_iter_next (lua_State *L)
 
 static int l_graph_lookup (lua_State *L)
 {
-    const VOLK_Graph *gr = check_graph (L);
+    const VOLK_Graph *gr = check_graph (L, 1);
     const VOLK_Term *s, *p, *o;
     if lua_isnoneornil (L, 2) s = NULL;
-    else s = *(VOLK_Term **)luaL_checkudata (L, 2, "VOLK.Term");
+    else s = check_term (L, 2);
     if lua_isnoneornil (L, 3) p = NULL;
-    else p = *(VOLK_Term **)luaL_checkudata (L, 3, "VOLK.Term");
+    else p = check_term (L, 3);
     if lua_isnoneornil (L, 4) o = NULL;
-    else o = *(VOLK_Term **)luaL_checkudata (L, 4, "VOLK.Term");
+    else o = check_term (L, 4);
 
     VOLK_GraphIterator **it_p = lua_newuserdata (L, sizeof *it_p);
     *it_p = NULL;
@@ -306,7 +302,7 @@ static int l_graph_lookup (lua_State *L)
 
 static int l_graph_encode (lua_State *L)
 {
-    const VOLK_Graph *gr = check_graph (L);
+    const VOLK_Graph *gr = check_graph (L, 1);
     const char *codec_str = lua_tostring (L, 2);
 
     VOLK_Codec codec;
@@ -344,7 +340,7 @@ static int l_graph_encode (lua_State *L)
 
 static int l_graph_get (lua_State *L)
 {
-    VOLK_Term *gr_uri = check_term (L);
+    VOLK_Term *gr_uri = check_term (L, 1);
     VOLK_Store *store = *(VOLK_Store **)luaL_checkudata (L, 2, "VOLK.Store");
 
     VOLK_Graph **gp = allocate_graph (L);
@@ -390,16 +386,18 @@ static int graph_iter_gc (lua_State *L)
  */
 static int l_graph_connections (lua_State *L)
 {
-    const VOLK_Graph *gr = check_graph (L);
-    VOLK_Term *t = *(VOLK_Term **)luaL_checkudata (L, 2, "VOLK.Term");
+    const VOLK_Graph *gr = check_graph (L, 1);
+    VOLK_Term *t = check_term (L, 2);
     const VOLK_LinkType type = luaL_checkinteger (L, 3);
     LOG_DEBUG ("Adding term for connections: @%p", *t);
 
+    VOLK_LinkMap *lm = VOLK_graph_connections (gr, t, type);
+    LUA_NLCHECK (lm, "Error creating link map.");
     VOLK_LinkMap **lm_p = lua_newuserdata (L, sizeof *lm_p);
-    *lm_p = VOLK_graph_connections (gr, t, type);
-    LUA_NLCHECK (*lm_p, "Error creating Link map.");
+    *lm_p = lm;
     luaL_getmetatable (L, "VOLK.LinkMap");
     lua_setmetatable (L, -2);
+    LUA_NLCHECK (*lm_p, "Error creating Link map.");
 
     return 1;
 }
@@ -407,30 +405,28 @@ static int l_graph_connections (lua_State *L)
 
 static int l_graph_term_set (lua_State *L)
 {
-    const VOLK_Graph *gr = check_graph (L);
-    const VOLK_Term *t1 = *(VOLK_Term **)luaL_checkudata (L, 2, "VOLK.Term");
+    const VOLK_Graph *gr = check_graph (L, 1);
+    const VOLK_Term *t1 = check_term (L, 2);
     const VOLK_TriplePos t1_pos = luaL_checkinteger (L, 3);
-    const VOLK_Term *t2 = *(VOLK_Term **)luaL_checkudata (L, 4, "VOLK.Term");
+    const VOLK_Term *t2 = check_term (L, 4);
     const VOLK_TriplePos t2_pos = luaL_checkinteger (L, 5);
 
     VOLK_TermSet *ts = VOLK_graph_term_set (gr, t1, t1_pos, t2, t2_pos);
     LUA_NLCHECK (ts, "Error creating term set from graph.");
-    LUA_PCHECK (term_set_to_table (L, ts), "Error generating term set table");
 
-    return 1;
+    return tset_to_udata (L, ts);
 }
 
 
 static int l_graph_unique_terms (lua_State *L)
 {
-    const VOLK_Graph *gr = check_graph (L);
+    const VOLK_Graph *gr = check_graph (L, 1);
     const VOLK_TriplePos pos = luaL_checkinteger (L, 2);
 
     VOLK_TermSet *ts = VOLK_graph_unique_terms (gr, pos);
     LUA_NLCHECK (ts, "Error creating term set from unique terms.");
-    LUA_PCHECK (term_set_to_table (L, ts), "Error generating term set table");
 
-    return 1;
+    return tset_to_udata (L, ts);
 }
 
 
@@ -449,33 +445,14 @@ static int l_graph_unique_terms (lua_State *L)
  */
 static int l_graph_attr (lua_State *L)
 {
-    const VOLK_Graph *gr = check_graph (L);
-    const VOLK_Term *s = *(VOLK_Term **)luaL_checkudata (L, 2, "VOLK.Term");
-    const VOLK_Term *p = *(VOLK_Term **)luaL_checkudata (L, 3, "VOLK.Term");
+    const VOLK_Graph *gr = check_graph (L, 1);
+    const VOLK_Term *s = check_term (L, 2);
+    const VOLK_Term *p = check_term (L, 3);
 
-    size_t ct;
-    VOLK_GraphIterator *it = VOLK_graph_lookup (gr, s, p, NULL, &ct);
+    VOLK_TermSet *ts = VOLK_graph_term_set (gr, s, TRP_POS_S, p, TRP_POS_P);
+    LUA_NLCHECK (ts, "Error creating term set from attribute lookup.");
 
-    lua_createtable (L, ct, 0);
-    VOLK_Triple *spo;
-    VOLK_rc rc;
-    while ((rc = VOLK_graph_iter_next (it, &spo)) == VOLK_OK) {
-        // Table keys are term hashes.
-        lua_pushinteger (L, VOLK_term_hash (spo->o));
-
-        // Table values are the term sets proper.
-        VOLK_Term **op = lua_newuserdata (L, sizeof *op);
-        luaL_getmetatable (L, "VOLK.Term");
-        lua_setmetatable (L, -2);
-        *op = VOLK_term_copy (spo->o);
-
-        lua_rawset (L, -3);
-    }
-    VOLK_graph_iter_free (it);
-
-    if (rc != VOLK_END) LUA_PCHECK (rc, "Error iterating attr values");
-
-    return 1;
+    return tset_to_udata (L, ts);
 }
 
 /*

+ 128 - 47
src/lua_term.c

@@ -12,38 +12,103 @@ VOLK_Term **allocate_term (lua_State *L)
 }
 
 
-VOLK_TermSet **allocate_tset (lua_State *L)
+static int
+tset_gc (lua_State *L)
 {
-    VOLK_TermSet **ts_p = lua_newuserdatauv (L, sizeof (*ts_p), 1);
-    luaL_getmetatable (L, "VOLK.TermSet");
-    lua_setmetatable (L, -2);
+    VOLK_TermSet **ts_p = lua_touserdata (L, 1);
+    LOG_DEBUG ("Garbage collecting term set @%p", *ts_p);
+    if (UNLIKELY (!ts_p || !*ts_p)) return 0;
 
-    return ts_p;
+    VOLK_term_set_free (*ts_p);
+    *ts_p = NULL;
+
+    return 0;
 }
 
 
-VOLK_rc
-term_set_to_table (lua_State *L, VOLK_TermSet *ts)
+static int
+tset_contains (lua_State *L)
+{
+    VOLK_TermSet *ts = check_term_set(L, 1);
+    VOLK_Term *lut = check_term (L, 2);
+
+    VOLK_Key luk = VOLK_term_hash (lut);
+
+    log_info ("Accessing term %s with key %zu in term set", lut->data, luk);
+    const VOLK_Term *t = VOLK_term_set_get (ts, luk);
+    if (t) {
+        lua_pushboolean (L, true);
+
+        return 1;
+
+    } else return 0;
+}
+
+
+static int
+tset_iter_next (lua_State *L)
 {
-    size_t i = 0;
+    VOLK_TermSet *ts;
+    if (lua_islightuserdata (L, lua_upvalueindex (1)))
+        ts = lua_touserdata (L, lua_upvalueindex (1));
+    else ts = check_term_set(L, lua_upvalueindex (1));
+    size_t i = luaL_checkinteger (L, lua_upvalueindex (2));
+    LOG_DEBUG ("TS Iteration #%zu", i);
     VOLK_Term *tmp = NULL;
-    VOLK_rc rc;
-    lua_newtable (L);
-    while ((rc = VOLK_term_set_next (ts, &i, &tmp)) == VOLK_OK) {
-        // Table keys are term hashes.
-        lua_pushinteger (L, VOLK_term_hash (tmp));
-
-        // Table values are the term sets proper.
-        VOLK_Term **tp = (VOLK_Term **)lua_newuserdata (L, sizeof *tp);
-        luaL_getmetatable (L, "VOLK.Term");
-        lua_setmetatable (L, -2);
+
+    VOLK_rc rc = VOLK_term_set_next (ts, &i, &tmp);
+
+    LUA_PCHECK (rc, "Error iterating over term set.");
+
+    if (rc == VOLK_END) return 0;
+    else {
+        lua_pushinteger (L, i);
+        lua_copy (L, -1, lua_upvalueindex (2));  // Update iterator value.
+
+        VOLK_Term **tp = allocate_term (L);
+        LUA_NLCHECK (tp, "Error allocating memory for new term.");
         *tp = VOLK_term_copy (tmp);
 
-        lua_rawset (L, -3);
+        lua_pushboolean (L, true);
+
+        return 2;
     }
+}
+
 
-    if (rc < VOLK_OK) return rc;
-    return VOLK_OK;
+static int
+tset_iter_init (lua_State *L)
+{
+    lua_pushvalue (L, 1);  // Copy provided tset.
+    lua_pushinteger (L, 0);  // term set iterator.
+
+    stack_dump (L, "iter init");
+    lua_pushcclosure (L, tset_iter_next, 2);
+
+    return 1;
+}
+
+
+static int
+tset_size (lua_State *L)
+{
+    VOLK_TermSet *ts = check_term_set(L, 1);
+    lua_pushinteger (L, VOLK_term_set_size (ts));
+
+    return 1;
+}
+
+
+VOLK_rc
+tset_to_udata (lua_State *L, VOLK_TermSet *ts)
+{
+    VOLK_TermSet **ts_p = lua_newuserdata (L, sizeof (*ts_p));
+    LUA_NLCHECK (ts_p, "Error allocating memory for term set.");
+    luaL_getmetatable (L, "VOLK.TermSet");
+    lua_setmetatable (L, -2);
+    *ts_p = ts;
+
+    return 1;
 }
 
 
@@ -80,8 +145,8 @@ static int l_new_iriref_ns (lua_State *L)
 static int l_new_iriref_abs (lua_State *L)
 {
     VOLK_Term
-        *root = check_term (L),
-        *iri = *(VOLK_Term **)luaL_checkudata (L, 2, "VOLK.Term");
+        *root = check_term (L, 1),
+        *iri = check_term (L, 2);
 
     VOLK_Term **tp = allocate_term (L);
 
@@ -95,8 +160,8 @@ static int l_new_iriref_abs (lua_State *L)
 static int l_new_iriref_rel (lua_State *L)
 {
     VOLK_Term
-        *root = check_term (L),
-        *iri = *(VOLK_Term **)luaL_checkudata (L, 2, "VOLK.Term");
+        *root = check_term (L, 1),
+        *iri = check_term (L, 2);
 
     VOLK_Term **tp = allocate_term (L);
 
@@ -152,7 +217,7 @@ static int l_new_bnode (lua_State *L)
 
 static int l_new_copy (lua_State *L)
 {
-    VOLK_Term *src = check_term (L);
+    VOLK_Term *src = check_term (L, 1);
 
     VOLK_Term **tp = allocate_term (L);
 
@@ -169,8 +234,8 @@ static int l_new_copy (lua_State *L)
 static int l_term_equals (lua_State *L)
 {
     VOLK_Term
-        *t1 = check_term (L),
-        *t2 = *(VOLK_Term **)luaL_checkudata (L, 2, "VOLK.Term");
+        *t1 = check_term (L, 1),
+        *t2 = check_term (L, 2);
 
     lua_pushboolean (L, VOLK_term_equals (t1, t2));
 
@@ -181,7 +246,7 @@ static int l_term_equals (lua_State *L)
 static int l_term_gc (lua_State *L)
 {
     VOLK_Term **tp = luaL_checkudata(L, 1, "VOLK.Term");
-    //LOG_TRACE ("Garbage collecting term @%p", *tp);
+    LOG_TRACE ("Garbage collecting term @%p", *tp);
 
     VOLK_term_free (*tp);
     *tp = NULL;
@@ -210,7 +275,7 @@ fail:
 
 static int l_term_to_n3 (lua_State *L)
 {
-    VOLK_Term *t = check_term (L);
+    VOLK_Term *t = check_term (L, 1);
     char *nt_term = NULL;
 
     CHECK (nt_codec.encode_term (t, &nt_term), fail);
@@ -251,7 +316,7 @@ static int l_term_get_attr (lua_State *L)
 
 static int get_data (lua_State *L)
 {
-    VOLK_Term *t = check_term (L);
+    VOLK_Term *t = check_term (L, 1);
     lua_pushstring (L, t->data);
 
     return 1;
@@ -260,7 +325,7 @@ static int get_data (lua_State *L)
 
 static int get_type (lua_State *L)
 {
-    VOLK_Term *t = check_term (L);
+    VOLK_Term *t = check_term (L, 1);
     lua_pushinteger (L, t->type);
 
     return 1;
@@ -269,7 +334,7 @@ static int get_type (lua_State *L)
 
 static int get_iriref_prefix (lua_State *L)
 {
-    VOLK_Term *t = check_term (L);
+    VOLK_Term *t = check_term (L, 1);
     lua_pushstring (L, VOLK_iriref_prefix (t));
 
     return 1;
@@ -278,7 +343,7 @@ static int get_iriref_prefix (lua_State *L)
 
 static int get_iriref_path (lua_State *L)
 {
-    VOLK_Term *t = check_term (L);
+    VOLK_Term *t = check_term (L, 1);
     lua_pushstring (L, VOLK_iriref_path (t));
 
     return 1;
@@ -287,7 +352,7 @@ static int get_iriref_path (lua_State *L)
 
 static int get_iriref_frag (lua_State *L)
 {
-    VOLK_Term *t = check_term (L);
+    VOLK_Term *t = check_term (L, 1);
     lua_pushstring (L, VOLK_iriref_frag (t));
 
     return 1;
@@ -297,7 +362,7 @@ static int get_iriref_frag (lua_State *L)
 static int get_lit_datatype (lua_State *L)
 {
     printf ("Getting datatype.\n");
-    VOLK_Term *t = check_term (L);
+    VOLK_Term *t = check_term (L, 1);
     if (!VOLK_IS_LITERAL (t))
         return luaL_error (L, "Term is not a literal.", 2);
 
@@ -309,7 +374,7 @@ static int get_lit_datatype (lua_State *L)
 
 static int get_lit_lang (lua_State *L)
 {
-    VOLK_Term *t = check_term (L);
+    VOLK_Term *t = check_term (L, 1);
     if (!VOLK_IS_LITERAL (t))
         return luaL_error (L, "Term is not a literal.", 2);
     if (t->type != VOLK_TERM_LT_LITERAL) return 0;
@@ -322,7 +387,7 @@ static int get_lit_lang (lua_State *L)
 
 static int get_hash (lua_State *L)
 {
-    VOLK_Term *t = check_term (L);
+    VOLK_Term *t = check_term (L, 1);
 
     lua_pushinteger (L, VOLK_term_hash (t));
 
@@ -349,11 +414,6 @@ static int lmap_iter_next (lua_State *L)
     VOLK_LinkMapIterator *it =
         *(VOLK_LinkMapIterator **)lua_touserdata (L, lua_upvalueindex (1));
 
-    VOLK_Term **link_p = (VOLK_Term **)lua_newuserdata (L, sizeof *link_p);
-    *link_p = NULL;
-    luaL_getmetatable (L, "VOLK.Term");
-    lua_setmetatable (L, -2);
-
     VOLK_TermSet *ts = NULL;
     VOLK_Term *tmp = NULL;
     VOLK_rc rc = VOLK_link_map_next (it, &tmp, &ts);
@@ -362,10 +422,15 @@ static int lmap_iter_next (lua_State *L)
         if (rc == VOLK_END) return 0;
         else LUA_PCHECK (rc, "Error iterating over link map");
     }
+    VOLK_Term **link_p = allocate_term (L);
+    LUA_NLCHECK (link_p, "Error allocating term.");
     *link_p = VOLK_term_copy (tmp);
-    LUA_NLCHECK (*link_p, "Error allocating term.");
 
-    LUA_PCHECK (term_set_to_table (L, ts), "Error generating term set");
+    lua_pushlightuserdata (L, ts);
+    lua_pushinteger (L, 0);
+    stack_dump (L, "LM set up TS iter closure");
+    lua_pushcclosure (L, tset_iter_next, 2);
+    stack_dump (L, "LM TS iter init");
 
     // linked term + term set.
     return 2;
@@ -413,9 +478,10 @@ static int link_map_gc (lua_State *L)
 
 static int lmap_iter_gc (lua_State *L)
 {
-    VOLK_LinkMapIterator *it = *(VOLK_LinkMapIterator **)lua_touserdata (L, 1);
+    VOLK_LinkMapIterator **it = lua_touserdata (L, 1);
     LOG_DEBUG ("Garbage collecting link map iterator @%p", it);
-    VOLK_link_map_iter_free (it);
+    VOLK_link_map_iter_free (*it);
+    *it = NULL;
 
     return 0;
 }
@@ -519,6 +585,21 @@ int luaopen_volksdata_term (lua_State *L)
     /*
      * Metatables for ancillary types.
      */
+    // Term set.
+    luaL_newmetatable (L, "VOLK.TermSet");
+    lua_pushvalue (L, -1);
+    lua_setfield (L, -2, "__index");
+    lua_pushcfunction (L, tset_gc);
+    lua_setfield (L, -2, "__gc");
+    lua_pushcfunction (L, tset_size);
+    lua_setfield (L, -2, "__len");
+    lua_pushcfunction (L, tset_iter_init);
+    lua_setfield (L, -2, "__pairs");
+    lua_pushcfunction (L, tset_iter_init);
+    lua_setfield (L, -2, "iter");
+    lua_pushcfunction (L, tset_contains);
+    lua_setfield (L, -2, "contains");
+
     // Link map.
     luaL_newmetatable (L, "VOLK.LinkMap");
     lua_pushcfunction (L, link_map_gc);

+ 9 - 9
src/lua_triple.c

@@ -11,9 +11,9 @@ static int l_triple_new (lua_State *L)
     luaL_getmetatable (L, "VOLK.Triple");
     lua_setmetatable (L, -2);
     VOLK_Term
-        *s = *(VOLK_Term **)luaL_checkudata(L, 1, "VOLK.Term"),
-        *p = *(VOLK_Term **)luaL_checkudata(L, 2, "VOLK.Term"),
-        *o = *(VOLK_Term **)luaL_checkudata(L, 3, "VOLK.Term");
+        *s = check_term (L, 1),
+        *p = check_term (L, 2),
+        *o = check_term (L, 3);
 
     *trp_p = VOLK_triple_new (
             VOLK_term_copy (s),
@@ -31,7 +31,7 @@ static int l_triple_new (lua_State *L)
 
 static int l_triple_gc (lua_State *L)
 {
-    VOLK_Triple *trp = check_triple (L);
+    VOLK_Triple *trp = check_triple (L, 1);
     if (trp) VOLK_triple_free (trp);
 
     return 0;
@@ -49,7 +49,7 @@ static int l_triple_gc (lua_State *L)
  */
 static int l_triple_get_term (lua_State *L)
 {
-    const VOLK_Triple *trp = check_triple (L);
+    const VOLK_Triple *trp = check_triple (L, 1);
     const char pos = luaL_checkstring (L, 2)[0];
     VOLK_TriplePos pn;
     if (pos == 's') pn = TRP_POS_S;
@@ -67,9 +67,9 @@ static int l_triple_get_term (lua_State *L)
 
 static int l_triple_set_term (lua_State *L)
 {
-    VOLK_Triple *trp = check_triple (L);
+    VOLK_Triple *trp = check_triple (L, 1);
     const char pos = luaL_checkstring (L, 2)[0];
-    const VOLK_Term *t = *(VOLK_Term **)luaL_checkudata(L, 3, "VOLK.Term");
+    const VOLK_Term *t = check_term (L, 3);
 
     VOLK_Term *new_t = VOLK_term_copy (t);
 
@@ -90,7 +90,7 @@ static int l_triple_set_term (lua_State *L)
 
 static int l_triple_copy_term (lua_State *L)
 {
-    const VOLK_Triple *trp = check_triple (L);
+    const VOLK_Triple *trp = check_triple (L, 1);
     const char pos = luaL_checkstring (L, 2)[0];
     VOLK_TriplePos pn;
     if (pos == 's') pn = TRP_POS_S;
@@ -108,7 +108,7 @@ static int l_triple_copy_term (lua_State *L)
 
 static int l_triple_to_n3 (lua_State *L)
 {
-    const VOLK_Triple *trp = check_triple (L);
+    const VOLK_Triple *trp = check_triple (L, 1);
     char *nt_term = NULL;
 
     for (int i = TRP_POS_S; i <= TRP_POS_O; i++) {

+ 11 - 8
src/lua_volksdata.h

@@ -21,14 +21,17 @@
  * Type check macros.
  */
 
-#define check_term(L) \
-    *(VOLK_Term **)luaL_checkudata(L, 1, "VOLK.Term")
+#define check_term(L, n) \
+    *(VOLK_Term **)luaL_checkudata(L, n, "VOLK.Term")
 
-#define check_triple(L) \
-    *(VOLK_Triple **)luaL_checkudata(L, 1, "VOLK.Triple")
+#define check_term_set(L, n) \
+    *(VOLK_TermSet **)luaL_checkudata(L, n, "VOLK.TermSet")
 
-#define check_graph(L) \
-    *(VOLK_Graph **)luaL_checkudata(L, 1, "VOLK.Graph")
+#define check_triple(L, n) \
+    *(VOLK_Triple **)luaL_checkudata(L, n, "VOLK.Triple")
+
+#define check_graph(L, n) \
+    *(VOLK_Graph **)luaL_checkudata(L, n, "VOLK.Graph")
 
 
 /// Enum (int) constants to be passed to the module.
@@ -55,7 +58,7 @@ int l_nsmap_new (lua_State *L);
 VOLK_Term **allocate_term (lua_State *L);
 
 /// Convert a VOLK_TermSet to a table and push it.
-VOLK_rc
-term_set_to_table (lua_State *L, VOLK_TermSet *ts);
+int
+tset_to_udata (lua_State *L, VOLK_TermSet *ts);
 
 #endif  // _LUA_VOLK_H

+ 4 - 1
src/stackdump.h

@@ -69,7 +69,10 @@ stack_dump (lua_State *L, const char *title)
     printf("]\n"); /* end the listing */
 }
 #else
-static void stack_dump (lua_State *L, const char *title) {}
+static void stack_dump (lua_State *L, const char *title) {
+    (void) L;
+    (void) title;
+}
 #endif  // DEBUG
 
 #endif  // _STACK_DUMP_H

+ 18 - 11
test.lua

@@ -38,15 +38,24 @@ assert(gr1 == gr2)
 assert(gr1 == gr3)
 
 --]]
+print("All triples:")
 for i in gr1:lookup(t1) do print(i) end
+
 ---[[
+print("Terms connected to t1 t2:")
+tset = gr1:term_set(t2, triple.POS_P, t1, triple.POS_S)
+for t in pairs(tset) do print(t) end
+--]]
 
+---[[
 lm = gr1:connections(t1, term.LINK_OUTBOUND)
 print("Connections")
-for t1, ts in pairs(lm) do
-    for t2 in pairs(ts) do print(t1, t2) end
+for t1, tsiter in pairs(lm) do
+    for t2 in tsiter do print(t1, t2) end
 end
+--]]
 
+---[[
 unique_t = gr1:unique_terms(triple.POS_S)
 print("Unique subjects")
 for t in pairs(unique_t) do print(t) end
@@ -56,10 +65,6 @@ for t in pairs(unique_t) do print(t) end
 print("Unique objects")
 unique_t = gr1:unique_terms(triple.POS_O)
 for t in pairs(unique_t) do print(t) end
-
-print("Terms connected to t1 t2:")
-tset = gr1:term_set(t2, triple.POS_P, t1, triple.POS_S)
-for t in pairs(tset) do print(t) end
 --]]
 
 namespace.add("ns1", "urn:ns:1#")
@@ -67,14 +72,14 @@ namespace.add("ns2", "urn:ns:2#")
 namespace.add("ns3", "urn:ns:3#")
 
 local nsm_map = {}
-for k, v in namespace.iter() do nsm_map[k] = v end
+for k, v in namespace:iter() do nsm_map[k] = v end
 assert(nsm_map.ns1 == "urn:ns:1#")
 assert(nsm_map.ns2 == "urn:ns:2#")
 assert(nsm_map.ns3 == "urn:ns:3#")
 
 local mdb_store_ns = store.new(store.MDB, "file:///tmp/volksdata_nsm.db", true)
 
-local mdb_gr2 = graph.new(mdb_store_ns, "ns1:gr2", nsm)
+mdb_gr2 = graph.new(mdb_store_ns, "ns1:gr2", nsm)
 local mdb_gr3 = graph.new(mdb_store_ns, "ns1:gr3", nsm)
 local mdb_gr4 = graph.new(mdb_store_ns, "ns1:gr4", nsm)
 local mdb_gr5 = graph.new(mdb_store_ns, "ns1:gr5", nsm)
@@ -83,11 +88,13 @@ mdb_gr3:add(triples)
 mdb_gr4:add(triples)
 
 local idx = graph.list(mdb_store_ns)
---assert(#idx == 3)
+assert(#idx == 3)
 
 attr = mdb_gr2:attr(t1, t2)
---assert (#attr == 3)
-for t in pairs(attr) do print(t) end
+assert (#attr == 3)
+assert(attr:contains(term.new_lit("Hola", nil, "es_ES")))
+print("Attributes:")
+for a in attr:iter() do print(a) end
 
 local gr1_copy = graph.new(mdb_store)
 local it = gr1_copy:add_init()

+ 4 - 1
volksdata-scm-1.rockspec

@@ -27,5 +27,8 @@ dependencies = {
 build = {
    type = "make",
    -- TODO set this based on parameters passed to luarocks.
-   variables = {LOCAL = "1", DEBUG = "1"},
+   variables = {
+       LOCAL = "1",
+       --DEBUG = "1"
+   },
 }