symbol.hpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. /* Declarations for the symbol and package types.
  2. This file is part of khipu.
  3. khipu is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU Lesser General Public License as published by
  5. the Free Software Foundation; either version 3 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public License
  12. along with this program. If not, see <https://www.gnu.org/licenses/>. */
  13. #ifndef __KP_SYMBOL__
  14. #define __KP_SYMBOL__ 1
  15. #include "thread.hpp"
  16. #include "initop.hpp"
  17. KP_DECLS_BEGIN
  18. // Special forms' descriptors.
  19. enum
  20. {
  21. SF_IF,
  22. SF_DO,
  23. SF_FCT,
  24. SF_AND,
  25. SF_OR,
  26. SF_WHILE,
  27. SF_BREAK,
  28. SF_CONTINUE,
  29. SF_RETURN,
  30. SF_SETQ,
  31. SF_QUOTE,
  32. SF_TRY,
  33. SF_LET,
  34. SF_RECUR,
  35. SF_YIELD,
  36. SF_CALLCC,
  37. SF_RAISE,
  38. SF_LAST_NO
  39. };
  40. struct symbol : public finobj
  41. {
  42. static const int literal_flag = 1 << 22;
  43. static const int specform_flag = 1 << 21;
  44. static const int special_flag = 1 << 20;
  45. static const int ctv_flag = 1 << 19;
  46. static const int alias_flag = 1 << 18;
  47. static const int code = typecode::SYMBOL;
  48. object name;
  49. object pkg;
  50. object value;
  51. intptr_t idx;
  52. uintptr_t tl_idx;
  53. static result<object> make_kword (interpreter *interp, object name);
  54. static result<object> make_kword (interpreter *interp, const char *name);
  55. static result<object> make_kword (interpreter *interp,
  56. const char *name, int len);
  57. // Some exported symbols.
  58. static object t;
  59. static object comma;
  60. static object comma_at;
  61. static object comma_dot;
  62. static object backquote;
  63. static object quote;
  64. static object nil;
  65. static object meth_curr;
  66. static const uint32_t N_SPECFORMS = SF_LAST_NO;
  67. static object fast_global_syms[];
  68. static int specform_byname (const void *name, uint32_t len);
  69. static int specform_byname (const void *name);
  70. static result<uintptr_t> alloc_tl_idx (interpreter *interp);
  71. };
  72. struct package : public finobj
  73. {
  74. static const int code = typecode::PKG;
  75. object syms;
  76. object name;
  77. object path;
  78. object canonical_path;
  79. atomic_t lock;
  80. dlist pkg_link;
  81. struct iterator
  82. {
  83. uint32_t idx;
  84. valref symtab;
  85. valref cursym;
  86. iterator (interpreter *interp, object pkg);
  87. iterator (interpreter *interp, uint32_t i,
  88. object tab, object sym) : idx (i),
  89. symtab (interp, tab), cursym (interp, sym)
  90. {
  91. }
  92. bool valid () const;
  93. iterator& operator++ ();
  94. iterator operator++ (int)
  95. {
  96. iterator rv { interpreter::self (),
  97. this->idx, *this->symtab, *this->cursym };
  98. ++*this;
  99. return (rv);
  100. }
  101. object operator* () const
  102. {
  103. return (*this->cursym);
  104. }
  105. };
  106. };
  107. inline symbol* as_symbol (object obj)
  108. {
  109. return ((symbol *)unmask (obj));
  110. }
  111. inline package* as_package (object obj)
  112. {
  113. return ((package *)unmask (obj));
  114. }
  115. inline object& symname (object obj)
  116. {
  117. return (as_symbol(obj)->name);
  118. }
  119. inline object& symval (object obj)
  120. {
  121. return (as_symbol(obj)->value);
  122. }
  123. inline object& sympkg (object obj)
  124. {
  125. return (as_symbol(obj)->pkg);
  126. }
  127. inline uintptr_t& symtlidx (object obj)
  128. {
  129. return (as_symbol(obj)->tl_idx);
  130. }
  131. inline object& symval (interpreter *interp, object obj)
  132. {
  133. symbol *sp = as_symbol (obj);
  134. return (!sp->tl_idx || sp->tl_idx >= interp->n_tlsyms ||
  135. interp->tl_syms[sp->tl_idx - 1] == UNBOUND ?
  136. sp->value : interp->tl_syms[sp->tl_idx - 1]);
  137. }
  138. inline bool symbol_p (object obj)
  139. {
  140. return (itype (obj) == typecode::SYMBOL);
  141. }
  142. inline bool package_p (object obj)
  143. {
  144. return (itype (obj) == typecode::PKG);
  145. }
  146. KP_EXPORT object root_package;
  147. KP_EXPORT object kword_package;
  148. inline bool keyword_p (object obj)
  149. {
  150. return (symbol_p (obj) && sympkg (obj) == kword_package);
  151. }
  152. inline bool nksymbol_p (object obj)
  153. {
  154. return (symbol_p (obj) && sympkg (obj) != kword_package);
  155. }
  156. struct stream;
  157. struct io_info;
  158. struct pack_info;
  159. /* Allocate a package named NAME. If BOOTSTRAP is true, the returned
  160. * package does not inherit any symbols from the root package. */
  161. KP_EXPORT result<object> alloc_pkg (interpreter *interp, object name,
  162. bool bootstrap = false);
  163. // Allocate a package named NAME, from path PATH.
  164. KP_EXPORT result<object> alloc_pkg (interpreter *interp, object name,
  165. object path = UNBOUND);
  166. // Allocate an uninterned symbol.
  167. KP_EXPORT result<object> alloc_sym (interpreter *interp, uint32_t flags = 0);
  168. // Copy a symbol.
  169. KP_EXPORT result<object> copy_S (interpreter *interp, object obj, bool deep);
  170. // Compute the hash value of a symbol.
  171. KP_EXPORT uint32_t hash_S (interpreter *interp, object obj);
  172. // Compute the hash value of a package.
  173. KP_EXPORT uint32_t hash_P (interpreter *interp, object obj);
  174. // Find a symbol named NAME in package PKG. Returns a non-symbol if not found.
  175. KP_EXPORT object find_sym (interpreter *interp, object pkg, object name);
  176. KP_EXPORT object find_sym (interpreter *interp, object pkg, const char *name);
  177. KP_EXPORT object find_sym (interpreter *interp, object pkg,
  178. const char *name, uint32_t len);
  179. inline object find_sym (interpreter *interp, const char *name)
  180. {
  181. return (find_sym (interp, root_package, name));
  182. }
  183. inline object find_sym (interpreter *interp, const char *name, uint32_t len)
  184. {
  185. return (find_sym (interp, root_package, name, len));
  186. }
  187. struct string;
  188. struct reader;
  189. /* Intern a symbol named NAME in package PKGP, with flags FLAGS.
  190. * If the package is null, intern it in the root package. */
  191. KP_EXPORT result<object> intern (interpreter *interp, const char *name,
  192. uint32_t len, package *pkgp = nullptr,
  193. uint32_t flags = 0);
  194. KP_EXPORT result<object> intern (interpreter *interp, const char *name,
  195. package *pkgp = nullptr, uint32_t flags = 0);
  196. KP_EXPORT result<object> intern (interpreter *interp, const string *name,
  197. package *pkgp = nullptr, uint32_t flags = 0);
  198. /* Remove the symbol named NAME from package PKGP.
  199. * If the package is null, remove it from the root package. */
  200. KP_EXPORT result<bool> undef (interpreter *interp, const char *name,
  201. uint32_t len, package *pkgp = nullptr);
  202. KP_EXPORT result<bool> undef (interpreter *interp, object sym);
  203. // Index a package. The key may be a string or keyword.
  204. KP_EXPORT result<object> get_P (interpreter *interp,
  205. object pkg, object key, object dfl);
  206. // Associate the symbol KEY to value VAL in package PKG.
  207. KP_EXPORT result<object> nput_P (interpreter *interp,
  208. object pkg, object key, object val);
  209. // Write a symbol to a stream.
  210. KP_EXPORT result<int64_t> write_S (interpreter* interp,
  211. stream *strm, object obj, io_info& info);
  212. // Write a package to a stream.
  213. KP_EXPORT result<int64_t> write_P (interpreter *interp,
  214. stream *strm, object obj, io_info& info);
  215. // Serialize a symbol to a stream.
  216. KP_EXPORT result<int64_t> pack_S (interpreter *interp,
  217. stream *strm, object obj, pack_info& info);
  218. // Serialize a package to a stream.
  219. KP_EXPORT result<int64_t> pack_P (interpreter *interp,
  220. stream *strm, object obj, pack_info& info);
  221. // Deserialize a package from a stream.
  222. KP_EXPORT result<object> unpack_S (interpreter *interp,
  223. stream *strm, pack_info& info, bool save);
  224. // Deserialize a package from a stream.
  225. KP_EXPORT result<object> unpack_P (interpreter *interp,
  226. stream *strm, pack_info& info, bool save);
  227. // Generate a unique, uninterned symbol.
  228. KP_EXPORT result<object> gensym (interpreter *interp, object *argv, int argc);
  229. // Compile a package, returning the equivalent thunk.
  230. KP_EXPORT result<object> compile_pkg (interpreter *interp, reader& rd);
  231. // Pull a package, or some symbols from it.
  232. KP_EXPORT result<object> pull_pkg (interpreter *interp,
  233. object name, object arg_1, object arg_2);
  234. // Mutate the value associated to a symbol in a package.
  235. KP_EXPORT result<object> nzap_P (interpreter *interp, object obj, object key,
  236. uint32_t flags, object fn,
  237. object *argv, int argc);
  238. // Init OP for symbols.
  239. KP_EXPORT init_op init_symbols;
  240. KP_DECLS_END
  241. #endif