builtins.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615
  1. #include <assert.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <unistd.h>
  6. #include "objects.h"
  7. #include "interpreter.h"
  8. #include "symboltable.h"
  9. //#include "gc.h"
  10. #include "information.h"
  11. #include "loader.h"
  12. #include "vm.h"
  13. #include "allocator.h"
  14. #include "glovars.h"
  15. #include "ports.h"
  16. // get Nth thing on the stack
  17. #define STACK(N) stack[reg_rbp + 1 + N]
  18. // list functions
  19. scm bltn_cons(void) {
  20. scm p = stack[reg_rbp + 1];
  21. scm q = stack[reg_rbp + 2];
  22. return allocate_cons(p, q);
  23. }
  24. scm bltn_car(void) {
  25. scm a = stack[reg_rbp + 1];
  26. info_assert(scm_gettag(a) == TAG_CONS);
  27. return get_cons_car(a);
  28. }
  29. scm bltn_cdr(void) {
  30. scm a = stack[reg_rbp + 1];
  31. info_assert(scm_gettag(a) == TAG_CONS);
  32. return get_cons_cdr(a);
  33. }
  34. scm bltn_nullq(void) {
  35. if (stack[reg_rbp + 1] == ATOM_NUL)
  36. return ATOM_TRU;
  37. else
  38. return ATOM_FLS;
  39. }
  40. scm bltn_pairq(void) {
  41. return mk_bool(scm_gettag(stack[reg_rbp + 1]) == TAG_CONS);
  42. }
  43. scm bltn_symbolq(void) {
  44. return mk_bool(scm_gettag(stack[reg_rbp + 1]) == ATOM_SYM);
  45. }
  46. scm bltn_stringq(void) {
  47. return mk_bool(scm_gettag(stack[reg_rbp + 1]) == TAG_STRG);
  48. }
  49. scm bltn_charq(void) {
  50. return mk_bool(scm_gettag(stack[reg_rbp + 1]) == ATOM_CHR);
  51. }
  52. scm bltn_booleanq(void) {
  53. scm x = scm_gettag(stack[reg_rbp + 1]);
  54. return mk_bool(x == ATOM_TRU || x == ATOM_FLS);
  55. }
  56. scm bltn_numberq(void) {
  57. return mk_bool(scm_gettag(stack[reg_rbp + 1]) == TAG_NUMB);
  58. }
  59. scm bltn_display(void);
  60. scm bltn_error(void) {
  61. stack_trace();
  62. bltn_display();
  63. exit(1);
  64. }
  65. scm bltn_exit(void) {
  66. exit(1);
  67. }
  68. // printing functions
  69. scm bltn_display(void) {
  70. scm atom;
  71. atom = stack[reg_rbp + 1];
  72. switch (scm_gettag(atom)) {
  73. case ATOM_FLS:
  74. printf("#f");
  75. break;
  76. case ATOM_TRU:
  77. printf("#t");
  78. break;
  79. case ATOM_NUL:
  80. printf("()");
  81. break;
  82. case ATOM_SYM:
  83. printf("%s", lookup(get_sym(atom)));
  84. break;
  85. case ATOM_CHR:
  86. printf("%c", (char)get_chr(atom));
  87. break;
  88. case TAG_NUMB:
  89. printf("%ld", get_numb(atom));
  90. break;
  91. case TAG_STRG:
  92. printf("%s", get_strg_data(atom));
  93. break;
  94. default:
  95. fprintf(stderr, "Unsupported type in call to print, atom=%lu\n", atom);
  96. break;
  97. }
  98. return ATOM_FLS;
  99. }
  100. scm bltn_display_port(void) {
  101. scm atom;
  102. atom = STACK(0);
  103. scm port = STACK(1);
  104. FILE *to = port_get_file(port);
  105. switch (scm_gettag(atom)) {
  106. case ATOM_FLS:
  107. fprintf(to, "#f");
  108. break;
  109. case ATOM_TRU:
  110. fprintf(to, "#t");
  111. break;
  112. case ATOM_NUL:
  113. fprintf(to, "()");
  114. break;
  115. case ATOM_SYM:
  116. fprintf(to, "%s", lookup(get_sym(atom)));
  117. break;
  118. case ATOM_CHR:
  119. fprintf(to, "%c", (char)get_chr(atom));
  120. break;
  121. case TAG_NUMB:
  122. fprintf(to, "%ld", get_numb(atom));
  123. break;
  124. case TAG_STRG:
  125. fprintf(to, "%s", get_strg_data(atom));
  126. break;
  127. default:
  128. fprintf(stderr, "Unsupported type in call to print, atom=%lu\n", atom);
  129. break;
  130. }
  131. return ATOM_FLS;
  132. }
  133. scm bltn_newline(void) {
  134. puts("");
  135. return ATOM_FLS;
  136. }
  137. // equality functions
  138. scm bltn_eq(void) {
  139. if (stack[reg_rbp + 1] == stack[reg_rbp + 2])
  140. return ATOM_TRU;
  141. else
  142. return ATOM_FLS;
  143. }
  144. scm bltn_equals(void) {
  145. scm p = stack[reg_rbp + 1];
  146. scm q = stack[reg_rbp + 2];
  147. info_assert(scm_gettag(p) == TAG_NUMB);
  148. info_assert(scm_gettag(q) == TAG_NUMB);
  149. if (p == q)
  150. return ATOM_TRU;
  151. else
  152. return ATOM_FLS;
  153. }
  154. // arithmetic operators
  155. scm bltn_mul(void) {
  156. scm p = stack[reg_rbp + 1];
  157. scm q = stack[reg_rbp + 2];
  158. info_assert(scm_gettag(p) == TAG_NUMB);
  159. info_assert(scm_gettag(q) == TAG_NUMB);
  160. return mk_numb(get_numb(p) * get_numb(q));
  161. }
  162. scm bltn_div(void) {
  163. scm p = stack[reg_rbp + 1];
  164. scm q = stack[reg_rbp + 2];
  165. info_assert(scm_gettag(p) == TAG_NUMB);
  166. info_assert(scm_gettag(q) == TAG_NUMB);
  167. return mk_numb(get_numb(p) / get_numb(q));
  168. }
  169. scm bltn_add(void) {
  170. scm p = stack[reg_rbp + 1];
  171. scm q = stack[reg_rbp + 2];
  172. info_assert(scm_gettag(p) == TAG_NUMB);
  173. info_assert(scm_gettag(q) == TAG_NUMB);
  174. return mk_numb(get_numb(p) + get_numb(q));
  175. }
  176. scm bltn_sub(void) {
  177. scm p = stack[reg_rbp + 1];
  178. scm q = stack[reg_rbp + 2];
  179. info_assert(scm_gettag(p) == TAG_NUMB);
  180. info_assert(scm_gettag(q) == TAG_NUMB);
  181. return mk_numb(get_numb(p) - get_numb(q));
  182. }
  183. scm bltn_mod(void) {
  184. scm p = stack[reg_rbp + 1];
  185. scm q = stack[reg_rbp + 2];
  186. info_assert(scm_gettag(p) == TAG_NUMB);
  187. info_assert(scm_gettag(q) == TAG_NUMB);
  188. return mk_numb(get_numb(p) % get_numb(q));
  189. }
  190. // inequalities
  191. scm bltn_lt(void) {
  192. scm p = stack[reg_rbp + 1];
  193. scm q = stack[reg_rbp + 2];
  194. info_assert(scm_gettag(p) == TAG_NUMB);
  195. info_assert(scm_gettag(q) == TAG_NUMB);
  196. return mk_bool(get_numb(p) < get_numb(q));
  197. }
  198. scm bltn_gt(void) {
  199. scm p = stack[reg_rbp + 1];
  200. scm q = stack[reg_rbp + 2];
  201. info_assert(scm_gettag(p) == TAG_NUMB);
  202. info_assert(scm_gettag(q) == TAG_NUMB);
  203. return mk_bool(get_numb(p) > get_numb(q));
  204. }
  205. scm bltn_le(void) {
  206. scm p = stack[reg_rbp + 1];
  207. scm q = stack[reg_rbp + 2];
  208. info_assert(scm_gettag(p) == TAG_NUMB);
  209. info_assert(scm_gettag(q) == TAG_NUMB);
  210. return mk_bool(get_numb(p) <= get_numb(q));
  211. }
  212. scm bltn_ge(void) {
  213. scm p = stack[reg_rbp + 1];
  214. scm q = stack[reg_rbp + 2];
  215. info_assert(scm_gettag(p) == TAG_NUMB);
  216. info_assert(scm_gettag(q) == TAG_NUMB);
  217. return mk_bool(get_numb(p) >= get_numb(q));
  218. }
  219. // mutation
  220. scm bltn_set_car(void) {
  221. scm p = stack[reg_rbp + 1];
  222. scm q = stack[reg_rbp + 2];
  223. set_cons_car(p, q);
  224. return ATOM_FLS;
  225. }
  226. scm bltn_set_cdr(void) {
  227. scm p = stack[reg_rbp + 1];
  228. scm q = stack[reg_rbp + 2];
  229. set_cons_cdr(p, q);
  230. return ATOM_FLS;
  231. }
  232. // vectors
  233. scm bltn_make_vector(void) {
  234. scm p = stack[reg_rbp + 1];
  235. scm q = stack[reg_rbp + 2];
  236. info_assert(scm_gettag(p) == TAG_NUMB);
  237. return allocate_vect(get_numb(p), q);
  238. }
  239. scm bltn_vectorq(void) {
  240. return mk_bool(scm_gettag(stack[reg_rbp + 1]) == TAG_VECT);
  241. }
  242. scm bltn_vector_ref(void) {
  243. scm vec = stack[reg_rbp + 1];
  244. scm idx = stack[reg_rbp + 2];
  245. info_assert(scm_gettag(idx) == TAG_NUMB);
  246. info_assert(get_numb(idx) < get_hdr_scm_size(get_vect(stack[reg_rbp + 1])[0]));
  247. return get_vect(vec)[1 + get_numb(idx)];
  248. }
  249. scm bltn_vector_set(void) {
  250. scm vec = stack[reg_rbp + 1];
  251. scm idx = stack[reg_rbp + 2];
  252. scm val = stack[reg_rbp + 3];
  253. info_assert(scm_gettag(idx) == TAG_NUMB);
  254. get_vect(vec)[1 + get_numb(idx)] = val;
  255. return val;
  256. }
  257. scm bltn_vector_length(void) {
  258. return mk_numb(get_hdr_scm_size(get_vect(stack[reg_rbp + 1])[0]));
  259. }
  260. ///// string ones
  261. scm bltn_make_string(void) {
  262. scm args_0 = stack[reg_rbp + 1];
  263. scm args_1 = stack[reg_rbp + 2];
  264. char string_tmp_buf[51200] = { 0 };
  265. int len;
  266. //assert(bytecode_args_num == 2);
  267. info_assert(scm_gettag(args_0) == TAG_NUMB);
  268. info_assert(scm_gettag(args_1) == ATOM_CHR);
  269. int i;
  270. char c;
  271. len = get_numb(args_0);
  272. c = (char)get_chr(args_1);
  273. for(i = 0; i < len; i++) {
  274. string_tmp_buf[i] = c;
  275. }
  276. string_tmp_buf[i] = '\0';
  277. return allocate_strg(string_tmp_buf, len);
  278. }
  279. scm bltn_string_set(void) {
  280. scm args_0 = stack[reg_rbp + 1];
  281. scm args_1 = stack[reg_rbp + 2];
  282. scm args_2 = stack[reg_rbp + 3];
  283. // info_assert(args_num == 3);
  284. info_assert(scm_gettag(args_0) == TAG_STRG);
  285. info_assert(scm_gettag(args_1) == TAG_NUMB);
  286. info_assert(scm_gettag(args_2) == ATOM_CHR);
  287. int i = get_numb(args_1);
  288. info_assert(i < get_strg_len(args_0));
  289. get_strg_data(args_0)[i] = get_chr(args_2);
  290. return 0;
  291. }
  292. scm bltn_string_ref(void) {
  293. scm args_0 = stack[reg_rbp + 1];
  294. scm args_1 = stack[reg_rbp + 2];
  295. // info_assert(args_num == 2);
  296. info_assert(scm_gettag(args_0) == TAG_STRG);
  297. info_assert(scm_gettag(args_1) == TAG_NUMB);
  298. int i = get_numb(args_1);
  299. info_assert(i < get_strg_len(args_0));
  300. return mk_chr(get_strg_data(args_0)[i]);
  301. }
  302. scm bltn_string_length(void) {
  303. scm args_0 = stack[reg_rbp + 1];
  304. info_assert(scm_gettag(args_0) == TAG_STRG);
  305. return mk_numb(get_strg_len(args_0));
  306. }
  307. scm bltn_string_to_symbol(void) {
  308. scm args_0 = stack[reg_rbp + 1];
  309. //info_assert(bytecode_args_num == 1);
  310. info_assert(scm_gettag(args_0) == TAG_STRG);
  311. scm res = intern((char*)get_strg_data(args_0));
  312. //printf("SYM:[%s][%lu]\n", get_strg_data(args_0), res);
  313. return res;
  314. }
  315. scm bltn_string_eql(void) {
  316. scm args_0 = stack[reg_rbp + 1];
  317. scm args_1 = stack[reg_rbp + 2];
  318. //info_assert(bytecode_args_num == 2);
  319. info_assert(scm_gettag(args_0) == TAG_STRG);
  320. info_assert(scm_gettag(args_1) == TAG_STRG);
  321. if(get_strg_len(args_0) != get_strg_len(args_1))
  322. return ATOM_FLS;
  323. if(strcmp((char*)get_strg_data(args_0), (char*)get_strg_data(args_1)))
  324. return ATOM_FLS;
  325. return ATOM_TRU;
  326. }
  327. scm bltn_number_to_char(void) {
  328. return mk_chr(get_numb(stack[reg_rbp + 1]));
  329. }
  330. scm bltn_char_to_number(void) {
  331. return mk_numb(get_chr(stack[reg_rbp + 1]));
  332. }
  333. scm bltn_symb_to_strn(void) {
  334. char *s = lookup(get_sym(STACK(0)));
  335. info_assert(s);
  336. return allocate_strg(s, strlen(s));
  337. }
  338. scm bltn_strn_append(void) {
  339. scm p = STACK(0);
  340. scm q = STACK(1);
  341. scm s = allocate_strg(NULL, get_strg_len(p) + get_strg_len(q));
  342. memcpy(get_strg_data(s), get_strg_data(p), get_strg_len(p));
  343. memcpy(get_strg_data(s) + get_strg_len(p), get_strg_data(q), get_strg_len(q));
  344. get_strg_data(s)[get_strg_len(p) + get_strg_len(q)] = '\0';
  345. return s;
  346. }
  347. // io
  348. scm bltn_eof_objectq(void) {
  349. int r = get_chr(STACK(0)) == -1;
  350. // if(r)puts("OEOF");
  351. return mk_bool(r);
  352. }
  353. scm bltn_read_char(void) {
  354. info_assert(scm_gettag(STACK(0)) == ATOM_PRT);
  355. char c=fgetc(port_get_file(STACK(0)));
  356. // printf("CHR:%c\n", c);
  357. return mk_chr(c);
  358. }
  359. scm bltn_open_input_port(void) {
  360. info_assert(scm_gettag(STACK(0)) == TAG_STRG);
  361. FILE *f = fopen((char *)get_strg_data(STACK(0)), "r");
  362. if(!f) {
  363. fprintf(stderr, "couldn't open file %s\n", get_strg_data(STACK(0)));
  364. }
  365. info_assert(f);
  366. return mk_port(f);
  367. }
  368. scm bltn_close_port(void) {
  369. info_assert(scm_gettag(STACK(0)) == ATOM_PRT);
  370. port_close(STACK(0));
  371. return ATOM_FLS;
  372. }
  373. int fpeek(FILE *stream)
  374. {
  375. int c;
  376. c = fgetc(stream);
  377. ungetc(c, stream);
  378. return c;
  379. }
  380. scm bltn_peek_char(void) {
  381. info_assert(scm_gettag(STACK(0)) == ATOM_PRT);
  382. return mk_chr(fpeek(port_get_file(STACK(0))));
  383. }
  384. // VM
  385. scm bltn_vm_open() {
  386. int fd[2];
  387. // make a pipe
  388. info_assert(!pipe(&fd[0]));
  389. // make a port out of it
  390. return mk_pipe(fdopen(fd[1], "w"), fdopen(fd[0], "r"));
  391. }
  392. scm bltn_vm_finish() {
  393. scm p = STACK(0);
  394. info_assert(scm_gettag(p) == ATOM_PRT);
  395. FILE *f1, *f2;
  396. scm *tmp = vm_code + vm_code_size;
  397. f1 = port_get_file(p);
  398. f2 = port_get_pipe_end(p);
  399. fclose(f1);
  400. load_code(f2);
  401. fclose(f2);
  402. // TODO remove it from the table
  403. // but dont re-close the fds
  404. vm_exec(tmp);
  405. return reg_acc;
  406. }
  407. scm bltn_gensym(void) {
  408. char string_tmp_buf[512] = { 0 };
  409. info_assert(scm_gettag(STACK(0)) == TAG_STRG);
  410. snprintf(string_tmp_buf, sizeof(string_tmp_buf), "%s%08x", get_strg_data(STACK(0)), rand()%0xFFFFFFFF);
  411. return intern(string_tmp_buf);
  412. }
  413. /////////////////////////////
  414. void builtins_init(scm argv) {
  415. // list functions
  416. glo_define(intern("cons"), mk_numb(2), mk_bltn(bltn_cons));
  417. glo_define(intern("car"), mk_numb(1), mk_bltn(bltn_car));
  418. glo_define(intern("cdr"), mk_numb(1), mk_bltn(bltn_cdr));
  419. glo_define(intern("set-car!"), mk_numb(2), mk_bltn(bltn_set_car));
  420. glo_define(intern("set-cdr!"), mk_numb(2), mk_bltn(bltn_set_cdr));
  421. glo_define(intern("null?"), mk_numb(1), mk_bltn(bltn_nullq));
  422. glo_define(intern("pair?"), mk_numb(1), mk_bltn(bltn_pairq));
  423. glo_define(intern("symbol?"), mk_numb(1), mk_bltn(bltn_symbolq));
  424. glo_define(intern("string?"), mk_numb(1), mk_bltn(bltn_stringq));
  425. glo_define(intern("char?"), mk_numb(1), mk_bltn(bltn_charq));
  426. glo_define(intern("boolean?"), mk_numb(1), mk_bltn(bltn_booleanq));
  427. glo_define(intern("number?"), mk_numb(1), mk_bltn(bltn_numberq));
  428. glo_define(intern("%display"), mk_numb(1), mk_bltn(bltn_display));
  429. glo_define(intern("newline"), mk_numb(0), mk_bltn(bltn_newline));
  430. // printing functions
  431. // glo_define(intern("print"), mk_numb(), mk_bltn(bltn_display)); // JUST FOR DEBUGGING
  432. glo_define(intern("error"), mk_numb(1), mk_bltn(bltn_error));
  433. glo_define(intern("exit"), mk_numb(0), mk_bltn(bltn_exit));
  434. // equality functions
  435. glo_define(intern("eq?"), mk_numb(2), mk_bltn(bltn_eq));
  436. glo_define(intern("="), mk_numb(2), mk_bltn(bltn_equals));
  437. // arithmetic operators
  438. glo_define(intern("*"), mk_numb(2), mk_bltn(bltn_mul));
  439. glo_define(intern("+"), mk_numb(2), mk_bltn(bltn_add));
  440. glo_define(intern("-"), mk_numb(2), mk_bltn(bltn_sub));
  441. glo_define(intern("modulo"), mk_numb(2), mk_bltn(bltn_mod));
  442. glo_define(intern("quotient"), mk_numb(2), mk_bltn(bltn_div));
  443. glo_define(intern("remainder"), mk_numb(2), mk_bltn(bltn_mod));
  444. // inequalities
  445. glo_define(intern("<"), mk_numb(2), mk_bltn(bltn_lt));
  446. glo_define(intern(">"), mk_numb(2), mk_bltn(bltn_gt));
  447. glo_define(intern("<="), mk_numb(2), mk_bltn(bltn_le));
  448. glo_define(intern(">="), mk_numb(2), mk_bltn(bltn_ge));
  449. // vectors
  450. glo_define(intern("make-vector"), mk_numb(2), mk_bltn(bltn_make_vector));
  451. glo_define(intern("vector?"), mk_numb(1), mk_bltn(bltn_vectorq));
  452. glo_define(intern("vector-ref"), mk_numb(2), mk_bltn(bltn_vector_ref));
  453. glo_define(intern("vector-set!"), mk_numb(3), mk_bltn(bltn_vector_set));
  454. glo_define(intern("vector-length"), mk_numb(1), mk_bltn(bltn_vector_length));
  455. // strings
  456. glo_define(intern("make-string"), mk_numb(2), mk_bltn(bltn_make_string));
  457. glo_define(intern("string-set!"), mk_numb(3), mk_bltn(bltn_string_set));
  458. glo_define(intern("string-ref"), mk_numb(2), mk_bltn(bltn_string_ref));
  459. glo_define(intern("string->symbol"), mk_numb(1), mk_bltn(bltn_string_to_symbol));
  460. glo_define(intern("string-length"), mk_numb(1), mk_bltn(bltn_string_length));
  461. glo_define(intern("string=?"), mk_numb(2), mk_bltn(bltn_string_eql));
  462. glo_define(intern("integer->char"), mk_numb(1), mk_bltn(bltn_number_to_char));
  463. glo_define(intern("char->integer"), mk_numb(1), mk_bltn(bltn_char_to_number));
  464. glo_define(intern("symbol->string"), mk_numb(1), mk_bltn(bltn_symb_to_strn));
  465. glo_define(intern("string-append"), mk_numb(2), mk_bltn(bltn_strn_append));
  466. // io
  467. glo_define(intern("eof-object?"), mk_numb(1), mk_bltn(bltn_eof_objectq));
  468. glo_define(intern("read-char"), mk_numb(1), mk_bltn(bltn_read_char));
  469. glo_define(intern("peek-char"), mk_numb(1), mk_bltn(bltn_peek_char));
  470. glo_define(intern("open-input-port"), mk_numb(1), mk_bltn(bltn_open_input_port));
  471. glo_define(intern("close-port"), mk_numb(1), mk_bltn(bltn_close_port));
  472. glo_define(intern("standard-input"), ATOM_FLS, mk_port(stdin));
  473. glo_define(intern("argv"), ATOM_FLS, argv);
  474. // vm
  475. glo_define(intern("vm:open"), mk_numb(0), mk_bltn(bltn_vm_open));
  476. glo_define(intern("vm:finish"), mk_numb(1), mk_bltn(bltn_vm_finish));
  477. glo_define(intern("display:port"), mk_numb(2), mk_bltn(bltn_display_port));
  478. glo_define(intern("gensym"), mk_numb(1), mk_bltn(bltn_gensym));
  479. }