PageRenderTime 37ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 0ms

/ellrt.h

http://github.com/manuel/ell
C Header | 496 lines | 343 code | 93 blank | 60 comment | 6 complexity | e8179d89a66ea9c1ab571ec2ce8a56e7 MD5 | raw file
  1. /***** Executable and Linkable Lisp Runtime *****/
  2. #ifndef ELL_H
  3. #define ELL_H
  4. #include <gc/gc.h>
  5. #include <setjmp.h>
  6. #include <stdbool.h>
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <unistd.h>
  11. #include <uuid/uuid.h>
  12. #include "dict.h"
  13. #include "list.h"
  14. /**** Allocation ****/
  15. #define ell_alloc GC_MALLOC
  16. /**** Objects, Wrappers, Classes ****/
  17. /* Wrappers introduce a level of indirection between objects and their
  18. classes, which will allow efficient implementation of method
  19. lookup. See the paper ``Efficient Method Dispatch in PCL'' by
  20. Gregor J. Kiczales and Luis H. Rodriguez Jr. */
  21. struct ell_obj;
  22. struct ell_wrapper {
  23. struct ell_obj *class;
  24. list_t *type_args; // class object
  25. };
  26. struct ell_obj {
  27. struct ell_wrapper *wrapper;
  28. void *data;
  29. };
  30. struct ell_class_data {
  31. struct ell_obj *name;
  32. list_t *superclasses;
  33. struct ell_wrapper *wrapper;
  34. unsigned *type_params_ct;
  35. };
  36. struct ell_obj *
  37. ell_make_obj(struct ell_wrapper *wrapper, void *data);
  38. struct ell_obj *
  39. ell_slot_value(struct ell_obj *obj, struct ell_obj *slot_sym);
  40. struct ell_obj *
  41. ell_set_slot_value(struct ell_obj *obj, struct ell_obj *slot_sym, struct ell_obj *val);
  42. struct ell_obj *
  43. ell_obj_class(struct ell_obj *obj);
  44. bool
  45. ell_is_instance(struct ell_obj *obj, struct ell_obj *class);
  46. struct ell_wrapper *
  47. ell_make_wrapper(struct ell_obj *class);
  48. struct ell_obj *
  49. ell_wrapper_class(struct ell_wrapper *wrapper);
  50. void
  51. ell_assert_wrapper(struct ell_obj *obj, struct ell_wrapper *wrapper);
  52. struct ell_obj *
  53. ell_make_class(struct ell_obj *name);
  54. void
  55. ell_add_superclass(struct ell_obj *class, struct ell_obj *superclass);
  56. list_t *
  57. ell_class_superclasses(struct ell_obj *class);
  58. struct ell_wrapper *
  59. ell_class_wrapper(struct ell_obj *class);
  60. bool
  61. ell_is_subclass(struct ell_obj *class, struct ell_obj *superclass);
  62. struct ell_obj *
  63. ell_class_name(struct ell_obj *class);
  64. #define ELL_CLASS(name) __ell_class_##name
  65. #define ELL_WRAPPER(name) __ell_wrapper_##name
  66. /* Class class, the class of which classes are instances.
  67. Is a subclass of <object>.
  68. Is an instance of itself, although that may change. */
  69. struct ell_obj *ELL_CLASS(class);
  70. struct ell_wrapper *ELL_WRAPPER(class);
  71. #define ELL_DEFCLASS(name, lisp_name) \
  72. struct ell_obj *ELL_CLASS(name); \
  73. struct ell_wrapper *ELL_WRAPPER(name);
  74. ELL_DEFCLASS(obj, "<object>")
  75. #include "defclass.h"
  76. #undef ELL_DEFCLASS
  77. /*** Built-in classes exported to Lisp ***/
  78. struct ell_obj *__ell_g_LobjectG_1_;
  79. struct ell_obj *__ell_g_LbooleanG_1_;
  80. struct ell_obj *__ell_g_LclassG_1_;
  81. struct ell_obj *__ell_g_LfunctionG_1_;
  82. struct ell_obj *__ell_g_LgenericDfunctionG_1_;
  83. struct ell_obj *__ell_g_LlinkedDlistG_1_;
  84. struct ell_obj *__ell_g_LlistDrangeG_1_;
  85. struct ell_obj *__ell_g_LstringG_1_;
  86. struct ell_obj *__ell_g_LintegerG_1_;
  87. struct ell_obj *__ell_g_LsymbolG_1_;
  88. struct ell_obj *__ell_g_LsyntaxDlistG_1_;
  89. struct ell_obj *__ell_g_LsyntaxDstringG_1_;
  90. struct ell_obj *__ell_g_LsyntaxDsymbolG_1_;
  91. struct ell_obj *__ell_g_LunspecifiedG_1_;
  92. struct ell_obj *__ell_g_LconditionG_1_;
  93. /* As a special case, `signal' is used from C but written in Lisp. */
  94. struct ell_obj *__ell_g_signal_2_;
  95. /**** Closures ****/
  96. /* The calling convention for closures: the closure receives itself as
  97. first argument, the counts of positional and keyword arguments
  98. next, and finally the actual arguments array, allocated on the
  99. stack by the caller. The array contains the positional arguments,
  100. followed by symbol/argument pairs for the keyword arguments. */
  101. typedef unsigned int ell_arg_ct;
  102. typedef struct ell_obj *
  103. ell_code(struct ell_obj *clo, ell_arg_ct npos, ell_arg_ct nkey,
  104. struct ell_obj **args);
  105. /* A closure consists of a code pointer and an environment pointer.
  106. Usually, the environment contains the free variables of the
  107. closure, and is populated by the compiler, but sometimes the
  108. runtime constructs special-purpose closures (such as the exit
  109. function passed to a block), that make special (or no) use of the
  110. environment pointer. */
  111. struct ell_clo_data {
  112. ell_code *code;
  113. void *env;
  114. };
  115. struct ell_obj *
  116. ell_make_clo(ell_code *code, void *env);
  117. void *
  118. ell_clo_env(struct ell_obj *clo);
  119. struct ell_obj *
  120. ell_call_unchecked(struct ell_obj *clo, ell_arg_ct npos, ell_arg_ct nkey, struct ell_obj **args);
  121. struct ell_obj *
  122. ell_call(struct ell_obj *clo, ell_arg_ct npos, ell_arg_ct nkey, struct ell_obj **args);
  123. void
  124. ell_check_npos(ell_arg_ct formal_npos, ell_arg_ct actual_npos);
  125. #define ELL_CALL(clo, ...) \
  126. ({ \
  127. struct ell_obj *__ell_args[] = { __VA_ARGS__ }; \
  128. ell_arg_ct npos = sizeof(__ell_args) / sizeof(struct ell_obj *); \
  129. ell_call(clo, npos, 0, __ell_args); \
  130. })
  131. /**** Generic Functions ****/
  132. struct ell_method_entry {
  133. struct ell_obj *method; // clo
  134. list_t *specializers; // class
  135. };
  136. struct ell_generic_data {
  137. list_t *method_entries;
  138. };
  139. struct ell_obj *
  140. ell_make_generic();
  141. void
  142. ell_generic_add_method(struct ell_obj *generic, struct ell_obj *clo,
  143. list_t *specializers);
  144. struct ell_obj *
  145. ell_generic_find_method(struct ell_obj *generic, list_t *specialized_args);
  146. #define ELL_GENERIC(name) __ell_g_##name##_2_
  147. #define ELL_DEFGENERIC(name, lisp_name) struct ell_obj *ELL_GENERIC(name);
  148. #include "defgeneric.h"
  149. #undef ELL_DEFGENERIC
  150. /**** Methods ****/
  151. void
  152. ell_put_method(struct ell_obj *gf, struct ell_obj *clo, list_t *specializers);
  153. /* This basically simulates a Smalltalk-like OO system on top of the
  154. built-in generic functions, for bootstrap simplicity. */
  155. void
  156. ell_put_method_legacy(struct ell_obj *class, struct ell_obj *gf,
  157. struct ell_obj *clo, int args_ct);
  158. struct ell_obj *
  159. ell_send(struct ell_obj *rcv, struct ell_obj *generic,
  160. ell_arg_ct npos, ell_arg_ct nkey, struct ell_obj **args);
  161. #define ELL_SEND(rcv, msg, ...) \
  162. ({ \
  163. struct ell_obj *__ell_rcv = rcv; \
  164. struct ell_obj *__ell_send_args[] = { __ell_rcv, __VA_ARGS__ }; \
  165. ell_arg_ct npos = sizeof(__ell_send_args) / sizeof(struct ell_obj *); \
  166. ell_send(__ell_rcv, ELL_GENERIC(msg), npos, 0, __ell_send_args); \
  167. })
  168. #define ELL_METHOD_CODE(class, msg) __ell_method_code_##class##_##msg
  169. #define ELL_DEFMETHOD(class, msg, formal_npos) \
  170. ell_code ELL_METHOD_CODE(class, msg); \
  171. \
  172. __attribute__((constructor(201))) static void \
  173. __ell_init_method_##class##_##msg() \
  174. { \
  175. struct ell_obj *clo = \
  176. ell_make_clo(&ELL_METHOD_CODE(class, msg), NULL); \
  177. ell_put_method_legacy(ELL_CLASS(class), ELL_GENERIC(msg), clo, \
  178. formal_npos); \
  179. } \
  180. \
  181. struct ell_obj * \
  182. ELL_METHOD_CODE(class, msg)(struct ell_obj *clo, ell_arg_ct npos, \
  183. ell_arg_ct nkey, struct ell_obj **args) \
  184. {
  185. #define ELL_PARAM(name, i) \
  186. struct ell_obj *name = args[i];
  187. #define ELL_END \
  188. }
  189. /**** Control Flow ****/
  190. struct ell_unwind_protect {
  191. struct ell_unwind_protect *parent;
  192. struct ell_obj *cleanup;
  193. };
  194. struct ell_block {
  195. struct ell_unwind_protect *parent;
  196. struct ell_obj *volatile val;
  197. jmp_buf dest;
  198. };
  199. struct ell_unwind_protect *ell_current_unwind_protect;
  200. struct ell_obj *
  201. ell_block(struct ell_obj *fun);
  202. struct ell_obj *
  203. ell_unwind_protect(struct ell_obj *protected, struct ell_obj *cleanup);
  204. /**** Strings ****/
  205. struct ell_str_data {
  206. char *chars;
  207. };
  208. struct ell_obj *
  209. ell_make_strn(char *chars, size_t len);
  210. struct ell_obj *
  211. ell_make_str(char *chars);
  212. char *
  213. ell_str_chars(struct ell_obj *str);
  214. size_t
  215. ell_str_len(struct ell_obj *str);
  216. char
  217. ell_str_char_at(struct ell_obj *str, size_t i);
  218. struct ell_obj *
  219. ell_str_poplast(struct ell_obj *str);
  220. /**** Numbers ****/
  221. struct ell_num_int_data {
  222. int int_value;
  223. };
  224. struct ell_obj *
  225. ell_make_num(char *chars);
  226. struct ell_obj *
  227. ell_make_num_from_int(int i);
  228. int
  229. ell_num_int(struct ell_obj *num);
  230. /**** Symbols ****/
  231. struct dict_t ell_sym_tab; // char* -> sym
  232. struct ell_sym_data {
  233. struct ell_obj *name; // str
  234. };
  235. #define ELL_SYM(name) __ell_sym_##name
  236. #define ELL_DEFSYM(name, lisp_name) __attribute__((weak)) struct ell_obj *ELL_SYM(name);
  237. #include "defsym.h"
  238. #undef ELL_DEFSYM
  239. struct ell_obj *
  240. ell_intern(struct ell_obj *str);
  241. struct ell_obj *
  242. ell_sym_name(struct ell_obj *sym);
  243. int
  244. ell_sym_cmp(struct ell_obj *sym_a, struct ell_obj *sym_b);
  245. /**** Booleans ****/
  246. // Lisp names
  247. struct ell_obj *__ell_g_Ot_1_;
  248. struct ell_obj *__ell_g_Of_1_;
  249. // C names for convenience
  250. struct ell_obj *ell_t;
  251. struct ell_obj *ell_f;
  252. bool
  253. ell_is_true(struct ell_obj *obj);
  254. struct ell_obj *
  255. ell_truth(bool b);
  256. /**** Unspecified value ****/
  257. struct ell_obj *__ell_g_unspecified_1_;
  258. struct ell_obj *ell_unspecified;
  259. /**** Unbound marker ****/
  260. struct ell_obj *ell_unbound;
  261. /**** Lists ****/
  262. struct ell_lst_data {
  263. list_t elts;
  264. };
  265. struct ell_obj *
  266. ell_make_lst();
  267. /**** Ranges ****/
  268. struct ell_list_range_data {
  269. list_t *elts;
  270. lnode_t *cur;
  271. };
  272. struct ell_obj *
  273. ell_make_range_from_list(list_t *elts);
  274. /**** Syntax Objects ****/
  275. struct ell_obj *
  276. ell_parse();
  277. struct ell_cx {
  278. uuid_t uuid;
  279. };
  280. struct ell_stx_sym_data {
  281. struct ell_obj *sym;
  282. struct ell_cx *cx; // maybe NULL
  283. };
  284. struct ell_stx_str_data {
  285. struct ell_obj *str;
  286. };
  287. struct ell_stx_num_data {
  288. struct ell_obj *num;
  289. };
  290. struct ell_stx_lst_data {
  291. list_t elts;
  292. };
  293. struct ell_obj *
  294. ell_make_stx_sym(struct ell_obj *sym);
  295. struct ell_obj *
  296. ell_make_stx_sym_cx(struct ell_obj *sym, struct ell_cx *cx);
  297. struct ell_obj *
  298. ell_make_stx_str(struct ell_obj *str);
  299. struct ell_obj *
  300. ell_make_stx_num(struct ell_obj *num);
  301. struct ell_obj *
  302. ell_make_stx_lst();
  303. struct ell_obj *
  304. ell_stx_sym_sym(struct ell_obj *stx_sym);
  305. struct ell_cx *
  306. ell_stx_sym_cx(struct ell_obj *stx_sym);
  307. struct ell_obj *
  308. ell_stx_str_str(struct ell_obj *stx_str);
  309. struct ell_obj *
  310. ell_stx_num_num(struct ell_obj *stx_num);
  311. list_t *
  312. ell_stx_lst_elts(struct ell_obj *stx_lst);
  313. listcount_t
  314. ell_stx_lst_len(struct ell_obj *stx_lst);
  315. void
  316. ell_assert_stx_lst_len(struct ell_obj *stx_lst, listcount_t len);
  317. void
  318. ell_assert_stx_lst_len_min(struct ell_obj *stx_lst, listcount_t len);
  319. struct ell_cx *
  320. ell_make_cx();
  321. bool
  322. ell_cx_equal(struct ell_cx *cxa, struct ell_cx *cxb);
  323. int
  324. ell_cx_cmp(struct ell_cx *cxa, struct ell_cx *cxb);
  325. /* The use of this hygiene context is described in 'ellc.c' a bit
  326. more. Basically, it always holds the hygiene context of the
  327. current quasisyntax, if we're in a quasisyntax, to implement
  328. SRFI-72's hygiene condition, which states that quasiyntaxes
  329. "enclosed" in another quasisyntax share the enclosing quasisyntax's
  330. hygiene context.
  331. Note that SRFI-72 isn't completely clear on what "enclosed" really
  332. means. Our interpretation here, which seems to check out in the
  333. tests done so far, is that "enclosure" stops at lambda boundaries.
  334. This means when the evaluation of a quasisyntax leads to the
  335. evaluation of a nested lambda that returns a quasisyntax, that
  336. quasisyntax is _not_ considered to be enclosed in the outer
  337. quasisyntax. */
  338. static struct ell_cx *__ell_cur_cx = NULL;
  339. /**** Utilities ****/
  340. list_t *
  341. ell_util_make_list();
  342. void
  343. ell_util_list_add(list_t *list, void *elt);
  344. list_t *
  345. ell_util_sublist(list_t *list, listcount_t start);
  346. bool
  347. ell_util_list_contains(list_t *list, void *elt, dict_comp_t compare);
  348. void
  349. ell_util_assert_list_len(list_t *list, listcount_t len);
  350. void
  351. ell_util_assert_list_len_min(list_t *list, listcount_t len);
  352. bool
  353. ell_util_lists_equal(list_t *l1, list_t *l2, dict_comp_t compare);
  354. dict_t *
  355. ell_util_make_dict(dict_comp_t comp);
  356. void *
  357. ell_util_dict_put(dict_t *dict, void *key, void *val);
  358. void
  359. ell_util_set_add(list_t *set, void *elt, dict_comp_t compare);
  360. int
  361. ell_ptr_cmp(void *a, void *b);
  362. /**** Utilities for Generated Code ****/
  363. __attribute__((weak)) struct ell_obj *ell_result;
  364. void
  365. ell_arity_error();
  366. struct ell_obj *
  367. ell_unbound_arg();
  368. struct ell_obj *
  369. ell_unbound_var(char *name);
  370. struct ell_obj *
  371. ell_unbound_fun(char *name);
  372. struct ell_obj **
  373. ell_make_box(struct ell_obj *value);
  374. struct ell_obj *
  375. ell_box_read(struct ell_obj **box);
  376. struct ell_obj *
  377. ell_box_write(struct ell_obj **box, struct ell_obj *value);
  378. struct ell_obj *
  379. ell_lookup_key(struct ell_obj *key_sym, ell_arg_ct npos, ell_arg_ct nkey,
  380. struct ell_obj **args);
  381. /**** Emitted Code Macros ****/
  382. // mid = mangled ID
  383. // sid = original ID literal string
  384. #define ELL_GEN_GLO_REF(mid, sid) (mid != ell_unbound ? mid : ell_unbound_var(sid))
  385. #define ELL_GEN_GLO_FREF(mid, sid) (mid != ell_unbound ? mid : ell_unbound_fun(sid))
  386. #define ELL_GEN_ARG_REF_PLAIN(mid) (mid)
  387. #define ELL_GEN_ARG_REF_BOXED(mid) (ell_box_read(mid))
  388. #define ELL_GEN_ENV_REF_PLAIN(mid) (__ell_env->mid)
  389. #define ELL_GEN_ENV_REF_BOXED(mid) (ell_box_read(__ell_env->mid))
  390. #define ELL_GEN_DEF(mid, val) (mid = val)
  391. #define ELL_GEN_DEFP(mid) (mid != ell_unbound ? ell_t : ell_f)
  392. #define ELL_GEN_GLO_SET(mid, sid, val) ({ if (mid == ell_unbound) ell_unbound_var(sid); mid = val; })
  393. #define ELL_GEN_ARG_SET_PLAIN(mid, val) (mid = val)
  394. #define ELL_GEN_ARG_SET_BOXED(mid, val) (ell_box_write(mid, val))
  395. #define ELL_GEN_ENV_SET_PLAIN(mid, val) (__ell_env->mid = val)
  396. #define ELL_GEN_ENV_SET_BOXED(mid, val) (ell_box_write(__ell_env->mid, val))
  397. #define ELL_GEN_COND(test, _then, _else) (ell_is_true(test) ? _then : _else)
  398. #define ELL_GEN_LOOP(expr) ({ for(;;) { expr; }; ell_unspecified; })
  399. /**** Misc ****/
  400. #define ell_fail(...) \
  401. ({ printf(__VA_ARGS__); exit(EXIT_FAILURE); })
  402. #endif