#include "lua_lsup.h" #define check_triple(L) \ *(LSUP_Triple **)luaL_checkudata(L, 1, "LSUP.Triple") /* * Factory methods. */ static int l_triple_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 l_triple_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). * * @FIXME this doesn't allow chaining access methods, e.g. trp.s.data * * To get an independent copy of a triple term, use triple.copy_term(). */ static int l_triple_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); LSUP_Term *t = LSUP_triple_pos (trp, pn); 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 triple term for display!"); } static int l_triple_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 l_triple_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; } static int l_triple_to_n3 (lua_State *L) { const LSUP_Triple *trp = check_triple (L); char *nt_term = NULL; for (int i = TRP_POS_S; i <= TRP_POS_O; i++) { CHECK (nt_codec.encode_term ( LSUP_triple_pos (trp, i), NULL, &nt_term), fail); lua_pushstring (L, nt_term); lua_pushstring (L, " "); } free (nt_term); lua_pushstring (L, "."); // N3 statement termination. lua_concat (L, 7); return 1; fail: if (nt_term) free (nt_term); return luaL_error (L, "Error encoding triple term."); } /* * Library setup. */ static const struct luaL_Reg triple_lib_fn [] = { {"new", l_triple_new}, {NULL} }; static const struct luaL_Reg triple_lib_meth [] = { {"__gc", l_triple_gc}, {"__index", l_triple_get_term}, {"__newindex", l_triple_set_term}, {"__tostring", l_triple_to_n3}, {"copy_term", l_triple_copy_term}, {NULL} }; static const LEnumConst triple_enums[] = { {"POS_S", TRP_POS_S}, {"POS_P", TRP_POS_P}, {"POS_O", TRP_POS_O}, {NULL, 0} }; int luaopen_lsup_triple (lua_State *L) { LSUP_init(); // This is idempotent: no problem calling it multiple times. luaL_newmetatable (L, "LSUP.Triple"); lua_pushvalue (L, -1); // MT lua_setfield (L, -1, "__index"); luaL_setfuncs (L, triple_lib_meth, 0); luaL_newlib (L, triple_lib_fn); // Module-level constants. push_int_const (L, triple_enums); return 1; }