Browse Source

Implement proper getters for terms; fix a bunch of other things.

scossu 2 days ago
parent
commit
be89e9cec2
10 changed files with 567 additions and 238 deletions
  1. 3 5
      lua/Makefile
  2. 4 0
      lua/lua_term.c
  3. 0 114
      lua/lua_triple.c
  4. 0 0
      lua/src/lsup.c
  5. 32 2
      lua/src/lua_lsup.h
  6. 0 114
      lua/src/lua_triple.c
  7. 3 3
      lua/src/namespace.c
  8. 362 0
      lua/src/term.c
  9. 151 0
      lua/src/triple.c
  10. 12 0
      lua/test.lua

+ 3 - 5
lua/Makefile

@@ -1,20 +1,18 @@
 .DEFAULT_GOAL := lib
 
 INCLUDE = -I/usr/local/include/lsup
-CFLAGS = -shared -Wall -fPIC $(INCLUDE)
+CFLAGS = -DDEBUG -shared -Wall -fPIC $(INCLUDE)
 LDFLAGS = -L/usr/local/lib -llua -llsuprdf_dbg
 
 LUAC_SRC = $(wildcard src/*.c)
-#OBJ = $(patsubst lua/%, lua/build/, $(patsubst %.c, %.o, $(LUAC_SRC)))
 OBJ = $(patsubst src/%.c, lib/%.so, $(LUAC_SRC))
-S_OBJ = lsup.so
 
 .PHONY: lib
-lib: $(OBJ)
+lib: $(OBJ) src/lua_lsup.h
 
 lib/%.so: src/%.c
 	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^
 
 .PHONY: clean
 clean:
-	rm -rf build/* lib/*.so
+	rm lib/*.so

+ 4 - 0
lua/src/lua_term.c → lua/lua_term.c

@@ -165,6 +165,10 @@ static int to_string (lua_State *L)
 {
     LSUP_Term *t = check_term (L);
 
+    LSUP_AddrBuffer *addr;
+    sprintf (addr, "%p", t);
+    lua_pushstring (L, "LSUP.Term @ 0x");
+    lua_pushstring (L, 
     lua_pushstring (L, t->data);
 
     return 1;

+ 0 - 114
lua/lua_triple.c

@@ -1,114 +0,0 @@
-#include "lua_lsup.h"
-
-#define check_triple(L) \
-    *(LSUP_Triple **)luaL_checkudata(L, 1, "LSUP.Triple")
-
-
-/*
- * Factory methods.
- */
-
-static int new (lua_State *L)
-{
-    LSUP_Triple **trp_p = lua_newuserdatauv (L, sizeof (*trp_p), 1);
-    luaL_getmetatable (L, "LSUP.Triple");
-    LSUP_Term
-        *s = *(LSUP_Term **)luaL_checkudata(L, 2, "LSUP.Term"),
-        *p = *(LSUP_Term **)luaL_checkudata(L, 3, "LSUP.Term"),
-        *o = *(LSUP_Term **)luaL_checkudata(L, 4, "LSUP.Term");
-
-    lua_setmetatable (L, -4);
-
-    *trp_p = LSUP_triple_new (s, p, o);
-    if (!*trp_p) luaL_error (L, "Error while creating a triple!");
-
-    return 1;
-}
-
-
-/*
- * Class methods.
- */
-
-static int gc (lua_State *L)
-{
-    LSUP_Triple *trp = check_triple (L);
-    if (trp) LSUP_triple_free (trp);
-
-    return 0;
-}
-
-
-static int get_term (lua_State *L)
-{
-    const LSUP_Triple *trp = check_triple (L);
-    const int pos = luaL_checkinteger (L, 2);
-    if (pos < TRP_POS_S || pos > TRP_POS_O)
-        luaL_error(L, "Out of range position: %d.", pos);
-
-    lua_pushlightuserdata (L, LSUP_triple_pos (trp, (LSUP_TriplePos)pos));
-
-    return 1;
-}
-
-
-static int set_term (lua_State *L)
-{
-    LSUP_Triple *trp = check_triple (L);
-    const int pos = luaL_checkinteger (L, 2);
-    const LSUP_Term *t = *(LSUP_Term **)luaL_checkudata(L, 3, "LSUP.Term");
-
-    LSUP_Term *new_t = LSUP_term_copy (t);
-
-    if (pos == TRP_POS_S) {
-        LSUP_term_free (trp->s);
-        trp->s = new_t;
-    } else if (pos == TRP_POS_P) {
-        LSUP_term_free (trp->p);
-        trp->p = new_t;
-    } else if (pos == TRP_POS_O) {
-        LSUP_term_free (trp->o);
-        trp->o = new_t;
-    } else return luaL_error(L, "Out of range position: %d.", pos);
-
-    return 1;
-}
-
-
-/*
- * Library setup.
- */
-
-static const struct luaL_Reg triple_lib_fn [] = {
-    {"new", new},
-    {NULL}
-};
-
-
-static const struct luaL_Reg triple_lib_meth [] = {
-    {"__gc", gc},
-
-    {NULL}
-};
-
-
-int luaopen_triple (lua_State *L)
-{
-    luaL_newmetatable (L, "LSUP.Triple");
-    lua_pushvalue (L, -1);
-    lua_setfield (L, -2, "__index");
-    luaL_setfuncs (L, triple_lib_meth, 0);
-
-    // Enums
-    lua_pushvalue (L, TRP_POS_S);
-    lua_setfield (L, -1, "TRP_POS_S");
-    lua_pushvalue (L, TRP_POS_P);
-    lua_setfield (L, -1, "TRP_POS_P");
-    lua_pushvalue (L, TRP_POS_O);
-    lua_setfield (L, -1, "TRP_POS_O");
-
-    luaL_newlib (L, triple_lib_fn);
-
-    return 1;
-}
-

+ 0 - 0
lua/src/lua_lsup.c → lua/src/lsup.c


+ 32 - 2
lua/src/lua_lsup.h

@@ -1,12 +1,42 @@
 #include <lua.h>
-//#include <lualib.h>
 #include <lauxlib.h>
 
 #include "lsup_rdf.h"
 
+#ifndef _LUA_LSUP_H
+#define _LUA_LSUP_H
 
 /// Raise Lua error including LSUP error message on negative rc.
 #define LUA_PCHECK(exp, message) do {\
     if ((exp) < LSUP_OK) \
-        luaL_error (L, "%s: %s", message, LSUP_strerror (exp)); \
+        return luaL_error (L, "%s: %s", message, LSUP_strerror (exp)); \
 } while (0)
+
+// Size of printf("%p", <var>)
+#define ADDR_BUF_SIZE sizeof (size_t) * 2 + 2
+typedef char LSUP_AddrBuffer[ADDR_BUF_SIZE];
+
+
+int term_to_string (lua_State *L, LSUP_Term *t)
+{
+    char *nt_term = NULL;
+    CHECK (nt_codec.encode_term (t, NULL, &nt_term), fail);
+    lua_pushfstring (L, "LSUP.Term @ %p %s", t, nt_term);
+
+    return 1;
+
+fail:
+    if (nt_term) free (nt_term);
+    return luaL_error (L, "Error encoding term for display!");
+}
+
+
+LSUP_Term **allocate_term (lua_State *L)
+{
+    LSUP_Term **tp = lua_newuserdatauv (L, sizeof (*tp), 1);
+    luaL_getmetatable (L, "LSUP.Term");
+    lua_setmetatable (L, -2);
+
+    return tp;
+}
+#endif  // _LUA_LSUP_H

+ 0 - 114
lua/src/lua_triple.c

@@ -1,114 +0,0 @@
-#include "lua_lsup.h"
-
-#define check_triple(L) \
-    *(LSUP_Triple **)luaL_checkudata(L, 1, "LSUP.Triple")
-
-
-/*
- * Factory methods.
- */
-
-static int new (lua_State *L)
-{
-    LSUP_Triple **trp_p = lua_newuserdatauv (L, sizeof (*trp_p), 1);
-    luaL_getmetatable (L, "LSUP.Triple");
-    LSUP_Term
-        *s = *(LSUP_Term **)luaL_checkudata(L, 2, "LSUP.Term"),
-        *p = *(LSUP_Term **)luaL_checkudata(L, 3, "LSUP.Term"),
-        *o = *(LSUP_Term **)luaL_checkudata(L, 4, "LSUP.Term");
-
-    lua_setmetatable (L, -4);
-
-    *trp_p = LSUP_triple_new (s, p, o);
-    if (!*trp_p) luaL_error (L, "Error while creating a triple!");
-
-    return 1;
-}
-
-
-/*
- * Class methods.
- */
-
-static int gc (lua_State *L)
-{
-    LSUP_Triple *trp = check_triple (L);
-    if (trp) LSUP_triple_free (trp);
-
-    return 0;
-}
-
-
-static int get_term (lua_State *L)
-{
-    const LSUP_Triple *trp = check_triple (L);
-    const int pos = luaL_checkinteger (L, 2);
-    if (pos < TRP_POS_S || pos > TRP_POS_O)
-        luaL_error(L, "Out of range position: %d.", pos);
-
-    lua_pushlightuserdata (L, LSUP_triple_pos (trp, (LSUP_TriplePos)pos));
-
-    return 1;
-}
-
-
-static int set_term (lua_State *L)
-{
-    LSUP_Triple *trp = check_triple (L);
-    const int pos = luaL_checkinteger (L, 2);
-    const LSUP_Term *t = *(LSUP_Term **)luaL_checkudata(L, 3, "LSUP.Term");
-
-    LSUP_Term *new_t = LSUP_term_copy (t);
-
-    if (pos == TRP_POS_S) {
-        LSUP_term_free (trp->s);
-        trp->s = new_t;
-    } else if (pos == TRP_POS_P) {
-        LSUP_term_free (trp->p);
-        trp->p = new_t;
-    } else if (pos == TRP_POS_O) {
-        LSUP_term_free (trp->o);
-        trp->o = new_t;
-    } else luaL_error(L, "Out of range position: %d.", pos);
-
-    return 1;
-}
-
-
-/*
- * Library setup.
- */
-
-static const struct luaL_Reg triple_lib_fn [] = {
-    {"new", new},
-    {NULL}
-};
-
-
-static const struct luaL_Reg triple_lib_meth [] = {
-    {"__gc", gc},
-
-    {NULL}
-};
-
-
-int luaopen_triple (lua_State *L)
-{
-    luaL_newmetatable (L, "LSUP.Triple");
-    lua_pushvalue (L, -1);
-    lua_setfield (L, -2, "__index");
-    luaL_setfuncs (L, triple_lib_meth, 0);
-
-    // Enums
-    lua_pushvalue (L, TRP_POS_S);
-    lua_setfield (L, -1, "TRP_POS_S");
-    lua_pushvalue (L, TRP_POS_P);
-    lua_setfield (L, -1, "TRP_POS_P");
-    lua_pushvalue (L, TRP_POS_O);
-    lua_setfield (L, -1, "TRP_POS_O");
-
-    luaL_newlib (L, triple_lib_fn);
-
-    return 1;
-}
-

+ 3 - 3
lua/src/lua_namespace.c → lua/src/namespace.c

@@ -15,7 +15,7 @@ static int l_nsmap_new (lua_State *L)
     lua_setmetatable (L, -2);
 
     *nsm_p = LSUP_nsmap_new ();
-    if (!*nsm_p) luaL_error (L, "Error while creating a term!");
+    if (!*nsm_p) return luaL_error (L, "Error while creating a term!");
 
     return 1;
 }
@@ -140,13 +140,13 @@ static int l_nsmap_iter (lua_State *L)
  * Library setup.
  */
 
-static const struct luaL_Reg nsmap_lib_fn [] = {
+static const luaL_Reg nsmap_lib_fn [] = {
     {"new", l_nsmap_new},
     {NULL}
 };
 
 
-static const struct luaL_Reg nsmap_lib_meth [] = {
+static const luaL_Reg nsmap_lib_meth [] = {
     {"__gc", l_nsmap_gc},
 
     {"add", l_nsmap_add},

+ 362 - 0
lua/src/term.c

@@ -0,0 +1,362 @@
+#include "lua_lsup.h"
+
+#define check_term(L) \
+    *(LSUP_Term **)luaL_checkudata(L, 1, "LSUP.Term")
+
+
+/*
+ * Factory methods.
+ */
+
+static int l_iriref_new (lua_State *L)
+{
+    const char *data = luaL_checkstring (L, 1);
+    // TODO handle nsm.
+    LSUP_NSMap *nsm = lua_touserdata (L, 2);
+
+    LSUP_Term **tp = allocate_term (L);
+
+    *tp = LSUP_iriref_new (data, nsm);
+    if (!*tp) return luaL_error (L, "Error while creating a term!");
+
+    return 1;
+}
+
+
+static int l_iriref_new_abs (lua_State *L)
+{
+    LSUP_Term
+        *root = check_term (L),
+        *iri = *(LSUP_Term **)luaL_checkudata (L, 2, "LSUP.Term");
+
+    LSUP_Term **tp = allocate_term (L);
+
+    *tp = LSUP_iriref_absolute (root, iri);
+    if (!*tp) return luaL_error (L, "Error while creating a term!");
+
+    return 1;
+}
+
+
+static int l_iriref_new_rel (lua_State *L)
+{
+    LSUP_Term
+        *root = check_term (L),
+        *iri = *(LSUP_Term **)luaL_checkudata (L, 2, "LSUP.Term");
+
+    LSUP_Term **tp = allocate_term (L);
+
+    *tp = LSUP_iriref_relative (root, iri);
+    if (!*tp) return luaL_error (L, "Error while creating a term!");
+
+    return 1;
+}
+
+
+static int l_lit_new (lua_State *L)
+{
+    const char
+        *data = luaL_checkstring (L, 1),
+        *dtype_str = luaL_checkstring (L, 2);
+    const char *lang = luaL_checkstring (L, 3);
+
+    LSUP_Term **tp = allocate_term (L);
+    LSUP_Term *dtype;
+
+    if (lang) *tp = LSUP_lt_literal_new (data, (char *)lang);
+    else {
+        dtype = (dtype_str) ? LSUP_iriref_new (dtype_str, NULL) : NULL;
+        *tp = LSUP_literal_new (data, dtype);
+    }
+
+    if (!*tp) return luaL_error (L, "Error while creating a term!");
+
+    return 1;
+}
+
+
+static int l_bnode_new (lua_State *L)
+{
+    const char *data = luaL_checkstring (L, 1);
+
+    LSUP_Term **tp = allocate_term (L);
+
+    *tp = LSUP_bnode_new (data);
+    if (!*tp) return luaL_error (L, "Error while creating a term!");
+
+    return 1;
+}
+
+
+static int new_copy (lua_State *L)
+{
+    LSUP_Term *src = check_term (L);
+
+    LSUP_Term **tp = allocate_term (L);
+
+    *tp = LSUP_term_copy (src);
+    if (!*tp) return luaL_error (L, "Error while creating a term!");
+
+    return 1;
+}
+
+
+/*
+ * Class methods.
+ */
+static int equals (lua_State *L)
+{
+    LSUP_Term
+        *t1 = check_term (L),
+        *t2 = *(LSUP_Term **)luaL_checkudata (L, 2, "LSUP.Term");
+
+    lua_pushboolean (L, LSUP_term_equals (t1, t2));
+
+    return 1;
+}
+
+
+static int gc (lua_State *L)
+{
+    LSUP_Term *t = check_term (L);
+    if (t) LSUP_term_free (t);
+
+    return 0;
+}
+
+
+/*
+static int serialize (lua_State *L)
+{
+    LSUP_Term *t = check_term (L);
+
+    LSUP_Buffer *buf = LSUP_term_serialize (t);
+    if (!buf) return luaL_error (L, "Error while serializing a term!");
+
+    lua_pushfstring (L, buf->addr, buf->size);
+    LSUP_buffer_free (buf);
+
+    return 1;
+}
+*/
+
+
+static int to_string (lua_State *L)
+{
+    LSUP_Term *t = check_term (L);
+
+    return term_to_string(L, t);
+}
+
+
+static int echo (lua_State *L)
+{
+    LSUP_Term *t = check_term (L);
+    const char *s = luaL_checkstring (L, 2);
+    printf("Echo: %s\n", s);
+
+    return 0;
+}
+
+
+/*
+ * Getters.
+ */
+
+// Forward declaration.
+static const luaL_Reg term_getters [];
+
+
+static int get_attr (lua_State *L)
+{
+    const char *attr = luaL_checkstring (L, 2);
+    //printf ("Got attr: %s\n", attr);
+
+    if (luaL_getmetafield (L, 1, attr) != LUA_TNIL)
+        return 1;  // Return metamethod to be called as a function.
+
+    luaL_getmetafield (L, 1, "getters");
+    if (lua_getfield (L, -1, attr) != LUA_TNIL) {
+        //printf ("Found getter: %s\n", attr);
+        int rc = lua_tocfunction (L, -1)(L);
+        lua_pop (L, 2);
+
+        return rc;
+    }
+    lua_pop (L, 1);
+
+    return 0;
+}
+
+
+static int get_data (lua_State *L)
+{
+    LSUP_Term *t = check_term (L);
+    lua_pushstring (L, t->data);
+
+    return 1;
+}
+
+
+static int get_type (lua_State *L)
+{
+    LSUP_Term *t = check_term (L);
+    lua_pushinteger (L, t->type);
+
+    return 1;
+}
+
+
+static int get_iriref_nsm (lua_State *L)
+{
+    LSUP_Term *t = check_term (L);
+    // TODO
+    lua_pushlightuserdata (L, LSUP_iriref_nsm (t));
+
+    return 1;
+}
+
+
+static int get_iriref_prefix (lua_State *L)
+{
+    LSUP_Term *t = check_term (L);
+    lua_pushstring (L, LSUP_iriref_prefix (t));
+
+    return 1;
+}
+
+
+static int get_iriref_path (lua_State *L)
+{
+    LSUP_Term *t = check_term (L);
+    lua_pushstring (L, LSUP_iriref_path (t));
+
+    return 1;
+}
+
+
+static int get_iriref_frag (lua_State *L)
+{
+    LSUP_Term *t = check_term (L);
+    lua_pushstring (L, LSUP_iriref_frag (t));
+
+    return 1;
+}
+
+
+static int get_lit_datatype (lua_State *L)
+{
+    LSUP_Term *t = check_term (L);
+    if (!LSUP_IS_LITERAL (t)) return luaL_error (L, "Term is not a literal.");
+
+    lua_pushstring (L, t->datatype->data);
+
+    return 1;
+}
+
+
+static int get_lit_lang (lua_State *L)
+{
+    LSUP_Term *t = check_term (L);
+    if (!LSUP_IS_LITERAL (t)) return luaL_error (L, "Term is not a literal.");
+
+    lua_pushstring (L, t->lang);
+
+    return 1;
+}
+
+
+static int get_hash (lua_State *L)
+{
+    LSUP_Term *t = check_term (L);
+
+    lua_pushinteger (L, LSUP_term_hash (t));
+
+    return 1;
+}
+
+
+/*
+ * Setters.
+ */
+
+// Very simple for now.
+static int set_attr (lua_State *L)
+{ return luaL_error (L, "Direct setting is not allowed for this type.", 2); }
+
+
+/*
+ * Library setup.
+ */
+
+static const luaL_Reg term_lib_fn [] = {
+    {"iriref_new", l_iriref_new},
+    {"iriref_new_abs", l_iriref_new_abs},
+    {"iriref_new_rel", l_iriref_new_rel},
+    {"lit_new", l_lit_new},
+    {"bnode_new", l_bnode_new},
+    {"term_new_copy", new_copy},
+
+    {NULL}
+};
+
+
+static const luaL_Reg term_getters [] = {
+    // General getters.
+    {"data", get_data},
+    {"type", get_type},
+
+    // IRIRef getters.
+    {"nsm", get_iriref_nsm},
+    {"prefix", get_iriref_prefix},
+    {"path", get_iriref_path},
+    {"frag", get_iriref_frag},
+
+    // Literal getters.
+    {"datatype", get_lit_datatype},
+    {"lang", get_lit_lang},
+
+    // Generic getters.
+    {"hash", get_hash},
+
+    {NULL}
+};
+
+
+/*
+static const luaL_Reg term_setters [] = {
+    {NULL}
+};
+*/
+
+static const luaL_Reg term_lib_meth [] = {
+    {"__eq", equals},
+    {"__gc", gc},
+    {"__index", get_attr},
+    {"__tostring", to_string},
+    {"__newindex", set_attr},
+
+    {"echo", echo},
+    //{"serialize", serialize},
+    {NULL}
+};
+
+
+int luaopen_term (lua_State *L)
+{
+    luaL_newmetatable (L, "LSUP.Term");
+    luaL_setfuncs (L, term_lib_meth, 0);
+
+    // Getters table.
+    lua_newtable (L);
+    for (int i = 0; term_getters[i].name != NULL; i++) {
+        lua_pushcfunction (L, term_getters[i].func);
+        lua_setfield (L, -2, term_getters[i].name);
+    }
+    // Set getters table as a value for the Term metatable.
+    lua_setfield (L, -2, "getters");
+
+    luaL_newlib (L, term_lib_fn);
+
+    return 1;
+}

+ 151 - 0
lua/src/triple.c

@@ -0,0 +1,151 @@
+#include "lua_lsup.h"
+
+#define check_triple(L) \
+    *(LSUP_Triple **)luaL_checkudata(L, 1, "LSUP.Triple")
+
+
+/*
+ * Factory methods.
+ */
+
+static int new (lua_State *L)
+{
+    LSUP_Triple **trp_p = lua_newuserdatauv (L, sizeof (*trp_p), 1);
+    luaL_getmetatable (L, "LSUP.Triple");
+    lua_setmetatable (L, -2);
+    LSUP_Term
+        *s = *(LSUP_Term **)luaL_checkudata(L, 1, "LSUP.Term"),
+        *p = *(LSUP_Term **)luaL_checkudata(L, 2, "LSUP.Term"),
+        *o = *(LSUP_Term **)luaL_checkudata(L, 3, "LSUP.Term");
+
+
+    *trp_p = LSUP_triple_new (
+            LSUP_term_copy (s),
+            LSUP_term_copy (p),
+            LSUP_term_copy (o));
+    if (!*trp_p) return luaL_error (L, "Error while creating a triple!");
+
+    return 1;
+}
+
+
+/*
+ * Class methods.
+ */
+
+static int gc (lua_State *L)
+{
+    LSUP_Triple *trp = check_triple (L);
+    if (trp) LSUP_triple_free (trp);
+
+    return 0;
+}
+
+
+/** @brief Get information about a triple's term.
+ *
+ * Note that this is only a visual representation, as terms cannot be modified
+ * outside of their containing triple (unlike in the C library).
+ *
+ * To get an independent copy of a triple term, use triple.copy_term().
+ */
+static int get_term (lua_State *L)
+{
+    const LSUP_Triple *trp = check_triple (L);
+    const char pos = luaL_checkstring (L, 2)[0];
+    LSUP_TriplePos pn;
+    if (pos == 's') pn = TRP_POS_S;
+    else if (pos == 'p') pn = TRP_POS_P;
+    else if (pos == 'o') pn = TRP_POS_O;
+    else return luaL_error(L, "Out of range position: %c.", pos);
+
+    return term_to_string (L, LSUP_triple_pos (trp, pn));
+}
+
+
+static int set_term (lua_State *L)
+{
+    LSUP_Triple *trp = check_triple (L);
+    const char pos = luaL_checkstring (L, 2)[0];
+    const LSUP_Term *t = *(LSUP_Term **)luaL_checkudata(L, 3, "LSUP.Term");
+
+    LSUP_Term *new_t = LSUP_term_copy (t);
+
+    if (pos == 's') {
+        LSUP_term_free (trp->s);
+        trp->s = new_t;
+    } else if (pos == 'p') {
+        LSUP_term_free (trp->p);
+        trp->p = new_t;
+    } else if (pos == 'o') {
+        LSUP_term_free (trp->o);
+        trp->o = new_t;
+    } else return luaL_error(L, "Out of range position: %c.", pos);
+
+    return 1;
+}
+
+
+static int copy_term (lua_State *L)
+{
+    const LSUP_Triple *trp = check_triple (L);
+    const char pos = luaL_checkstring (L, 2)[0];
+    LSUP_TriplePos pn;
+    if (pos == 's') pn = TRP_POS_S;
+    else if (pos == 'p') pn = TRP_POS_P;
+    else if (pos == 'o') pn = TRP_POS_O;
+    else return luaL_error(L, "Copy: Out of range position: %c.", pos);
+
+    LSUP_Term **tp = allocate_term (L);
+    *tp = LSUP_term_copy (LSUP_triple_pos (trp, pn));
+    if (!*tp) return luaL_error (L, "Error while copying a triple term!");
+
+    return 1;
+}
+
+
+
+
+/*
+ * Library setup.
+ */
+
+static const struct luaL_Reg triple_lib_fn [] = {
+    {"new", new},
+    {NULL}
+};
+
+
+static const struct luaL_Reg triple_lib_meth [] = {
+    {"__gc", gc},
+    {"__index", get_term},
+    {"__newindex", set_term},
+
+    {"copy_term", copy_term},
+
+    {NULL}
+};
+
+
+int luaopen_triple (lua_State *L)
+{
+    luaL_newmetatable (L, "LSUP.Triple");
+    lua_pushvalue (L, -1);
+
+    // Enums
+    lua_pushinteger (L, TRP_POS_S);
+    lua_setfield (L, -2, "TRP_POS_S");
+    lua_pushinteger (L, TRP_POS_P);
+    lua_setfield (L, -2, "TRP_POS_P");
+    lua_pushinteger (L, TRP_POS_O);
+    lua_setfield (L, -2, "TRP_POS_O");
+
+    // MT
+    lua_setfield (L, -1, "__index");
+    luaL_setfuncs (L, triple_lib_meth, 0);
+
+    luaL_newlib (L, triple_lib_fn);
+
+    return 1;
+}
+

+ 12 - 0
lua/test.lua

@@ -0,0 +1,12 @@
+term = require "term"
+triple = require "triple"
+trp = triple.new (
+    term.iriref_new("urn:s:1"),
+    term.iriref_new("urn:p:1"),
+    term.iriref_new("urn:o:1"))
+
+t1 = term.iriref_new("urn:s:11")
+mt = {z =99}
+mt["__index"] = mt
+a = {x = 1, y = 2}
+setmetatable(a, mt)