triple.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. #include "lua_lsup.h"
  2. #define check_triple(L) \
  3. *(LSUP_Triple **)luaL_checkudata(L, 1, "LSUP.Triple")
  4. /*
  5. * Factory methods.
  6. */
  7. static int l_triple_new (lua_State *L)
  8. {
  9. LSUP_Triple **trp_p = lua_newuserdatauv (L, sizeof (*trp_p), 1);
  10. luaL_getmetatable (L, "LSUP.Triple");
  11. lua_setmetatable (L, -2);
  12. LSUP_Term
  13. *s = *(LSUP_Term **)luaL_checkudata(L, 1, "LSUP.Term"),
  14. *p = *(LSUP_Term **)luaL_checkudata(L, 2, "LSUP.Term"),
  15. *o = *(LSUP_Term **)luaL_checkudata(L, 3, "LSUP.Term");
  16. *trp_p = LSUP_triple_new (
  17. LSUP_term_copy (s),
  18. LSUP_term_copy (p),
  19. LSUP_term_copy (o));
  20. if (!*trp_p) return luaL_error (L, "Error while creating a triple!");
  21. return 1;
  22. }
  23. /*
  24. * Class methods.
  25. */
  26. static int l_triple_gc (lua_State *L)
  27. {
  28. LSUP_Triple *trp = check_triple (L);
  29. if (trp) LSUP_triple_free (trp);
  30. return 0;
  31. }
  32. /** @brief Get information about a triple's term.
  33. *
  34. * Note that this is only a visual representation, as terms cannot be modified
  35. * outside of their containing triple (unlike in the C library).
  36. *
  37. * @FIXME this doesn't allow chaining access methods, e.g. trp.s.data
  38. *
  39. * To get an independent copy of a triple term, use triple.copy_term().
  40. */
  41. static int l_triple_get_term (lua_State *L)
  42. {
  43. const LSUP_Triple *trp = check_triple (L);
  44. const char pos = luaL_checkstring (L, 2)[0];
  45. LSUP_TriplePos pn;
  46. if (pos == 's') pn = TRP_POS_S;
  47. else if (pos == 'p') pn = TRP_POS_P;
  48. else if (pos == 'o') pn = TRP_POS_O;
  49. else return luaL_error(L, "Out of range position: %c.", pos);
  50. LSUP_Term *t = LSUP_triple_pos (trp, pn);
  51. char *nt_term = NULL;
  52. CHECK (nt_codec.encode_term (t, NULL, &nt_term), fail);
  53. lua_pushfstring (L, "LSUP.Term @ %p %s", t, nt_term);
  54. return 1;
  55. fail:
  56. if (nt_term) free (nt_term);
  57. return luaL_error (L, "Error encoding triple term for display!");
  58. }
  59. static int l_triple_set_term (lua_State *L)
  60. {
  61. LSUP_Triple *trp = check_triple (L);
  62. const char pos = luaL_checkstring (L, 2)[0];
  63. const LSUP_Term *t = *(LSUP_Term **)luaL_checkudata(L, 3, "LSUP.Term");
  64. LSUP_Term *new_t = LSUP_term_copy (t);
  65. if (pos == 's') {
  66. LSUP_term_free (trp->s);
  67. trp->s = new_t;
  68. } else if (pos == 'p') {
  69. LSUP_term_free (trp->p);
  70. trp->p = new_t;
  71. } else if (pos == 'o') {
  72. LSUP_term_free (trp->o);
  73. trp->o = new_t;
  74. } else return luaL_error(L, "Out of range position: %c.", pos);
  75. return 1;
  76. }
  77. static int l_triple_copy_term (lua_State *L)
  78. {
  79. const LSUP_Triple *trp = check_triple (L);
  80. const char pos = luaL_checkstring (L, 2)[0];
  81. LSUP_TriplePos pn;
  82. if (pos == 's') pn = TRP_POS_S;
  83. else if (pos == 'p') pn = TRP_POS_P;
  84. else if (pos == 'o') pn = TRP_POS_O;
  85. else return luaL_error(L, "Copy: Out of range position: %c.", pos);
  86. LSUP_Term **tp = allocate_term (L);
  87. *tp = LSUP_term_copy (LSUP_triple_pos (trp, pn));
  88. if (!*tp) return luaL_error (L, "Error while copying a triple term!");
  89. return 1;
  90. }
  91. static int l_triple_to_n3 (lua_State *L)
  92. {
  93. const LSUP_Triple *trp = check_triple (L);
  94. char *nt_term = NULL;
  95. for (int i = TRP_POS_S; i <= TRP_POS_O; i++) {
  96. CHECK (nt_codec.encode_term (
  97. LSUP_triple_pos (trp, i), NULL, &nt_term), fail);
  98. lua_pushstring (L, nt_term);
  99. lua_pushstring (L, " ");
  100. }
  101. free (nt_term);
  102. lua_pushstring (L, "."); // N3 statement termination.
  103. lua_concat (L, 7);
  104. return 1;
  105. fail:
  106. if (nt_term) free (nt_term);
  107. return luaL_error (L, "Error encoding triple term.");
  108. }
  109. /*
  110. * Library setup.
  111. */
  112. static const struct luaL_Reg triple_lib_fn [] = {
  113. {"new", l_triple_new},
  114. {NULL}
  115. };
  116. static const struct luaL_Reg triple_lib_meth [] = {
  117. {"__gc", l_triple_gc},
  118. {"__index", l_triple_get_term},
  119. {"__newindex", l_triple_set_term},
  120. {"__tostring", l_triple_to_n3},
  121. {"copy_term", l_triple_copy_term},
  122. {NULL}
  123. };
  124. static const LEnumConst triple_enums[] = {
  125. {"POS_S", TRP_POS_S},
  126. {"POS_P", TRP_POS_P},
  127. {"POS_O", TRP_POS_O},
  128. {NULL, 0}
  129. };
  130. int luaopen_lsup_triple (lua_State *L)
  131. {
  132. LSUP_init(); // This is idempotent: no problem calling it multiple times.
  133. luaL_newmetatable (L, "LSUP.Triple");
  134. lua_pushvalue (L, -1);
  135. // MT
  136. lua_setfield (L, -1, "__index");
  137. luaL_setfuncs (L, triple_lib_meth, 0);
  138. luaL_newlib (L, triple_lib_fn);
  139. // Module-level constants.
  140. push_int_const (L, triple_enums);
  141. return 1;
  142. }