A minimalistic programming language written in C89.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2031 lines
53 KiB

6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
5 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
5 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
5 months ago
5 months ago
6 months ago
5 months ago
5 months ago
5 months ago
5 months ago
  1. #include "include/ink.h"
  2. #ifndef NOSTDLIB
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <ctype.h>
  7. #ifdef INSTRUMENTATION
  8. #include <time.h>
  9. #endif
  10. #endif
  11. #define INK_RESERVED (-1)
  12. #define INK_FUNCTION_KW (-2)
  13. #define INK_DO_KW (-3)
  14. #define INK_END_KW (-4)
  15. #define INK_LABEL (-5)
  16. #define INK_RETURN (-6)
  17. #define _KEYWORD_INK_FUNCTION "fn"
  18. #define _KEYWORD_INK_DO "do"
  19. #define _KEYWORD_INK_END "end"
  20. #define _KEYWORD_INK_RETURN "return"
  21. #define min(x, y) ((x) > (y) ? (y) : (x))
  22. #define max(x, y) ((x) < (y) ? (y) : (x))
  23. struct label {
  24. int active;
  25. int dest;
  26. char* name;
  27. };
  28. #ifdef NOSTDLIB
  29. static size_t strlen(const char* c) {
  30. size_t j;
  31. j = 0;
  32. while(*(c++)) {
  33. j++;
  34. }
  35. return j;
  36. }
  37. static void* memcpy(void* _dest, const void* _src, size_t sz) {
  38. char* dest;
  39. const char* src;
  40. dest = _dest;
  41. src = _src;
  42. while(sz--) {
  43. *(dest++) = *(src++);
  44. }
  45. return dest;
  46. }
  47. static int strcmp(const char* dest, const char* src) {
  48. while(*dest != 0 && *src != 0) {
  49. if(*(dest++) != *(src++)) {
  50. return 1;
  51. }
  52. }
  53. return 0;
  54. }
  55. static void* memmove(void* _dest, const void* _src, size_t sz) {
  56. char* dest;
  57. const char* src;
  58. dest = _dest;
  59. src = _src;
  60. if (src < dest) {
  61. src += sz;
  62. dest += sz;
  63. while (sz-- > 0) {
  64. *--dest = *--src;
  65. }
  66. } else {
  67. while (sz-- > 0) {
  68. *dest++ = *src++;
  69. }
  70. }
  71. return dest;
  72. }
  73. static void* memset(void* _dest, int src, size_t sz) {
  74. char* dest;
  75. dest = _dest;
  76. while(sz--) {
  77. *(dest++) = src++;
  78. }
  79. return dest;
  80. }
  81. static int isspace(int d) {
  82. return d == ' ' || d == '\t' || d == '\n';
  83. }
  84. static int isdigit(int d) {
  85. return '0' <= d && d <= '9';
  86. }
  87. static int atoi(const char* c) {
  88. int ret;
  89. ret = 0;
  90. while(*c) {
  91. ret *= 10;
  92. ret += *c - '0';
  93. ++c;
  94. }
  95. return ret;
  96. }
  97. #endif
  98. int ink_add_native(struct context* ctx, const char* name, void(*value)(struct context*)) {
  99. int len;
  100. char* copy;
  101. if(ctx->native_words == NULL) {
  102. ctx->native_words = ctx->inner_malloc(sizeof(struct native_fn) * 8);
  103. ctx->native_words_top = 0;
  104. ctx->native_words_capacity = 8;
  105. } else if(ctx->native_words_top == ctx->native_words_capacity) {
  106. int new_count;
  107. void* renewed;
  108. new_count = (ctx->native_words_capacity + ctx->native_words_capacity/2);
  109. renewed = ctx->inner_realloc(ctx->native_words, sizeof(struct native_fn) * new_count);
  110. if(renewed == NULL) {
  111. return -3;
  112. } else {
  113. ctx->native_words = renewed;
  114. ctx->native_words_capacity = new_count;
  115. }
  116. }
  117. len = strlen(name);
  118. copy = ctx->inner_malloc(len+1);
  119. if(copy == NULL) {
  120. return -4;
  121. }
  122. memcpy(copy, name, len);
  123. copy[len] = 0;
  124. ctx->native_words[ctx->native_words_top].value = value;
  125. ctx->native_words[ctx->native_words_top].name = copy;
  126. ctx->native_words_top++;
  127. return 0;
  128. }
  129. static int ink_add_indigenous(struct context* ctx, const char* name, struct elem* m, size_t count) {
  130. int len, i;
  131. char* copy;
  132. if(ctx->words == NULL) {
  133. ctx->words = ctx->malloc(sizeof(struct fn) * 8);
  134. ctx->words_top = 0;
  135. ctx->words_capacity = 8;
  136. } else if(ctx->words_top == ctx->words_capacity) {
  137. int new_count;
  138. void* renewed;
  139. new_count = (ctx->words_capacity + ctx->words_capacity/2);
  140. renewed = ctx->realloc(ctx->words, sizeof(struct fn) * new_count);
  141. if(renewed == NULL) {
  142. return -1;
  143. } else {
  144. ctx->words = renewed;
  145. ctx->words_capacity = new_count;
  146. }
  147. }
  148. for(i = 0; i < ctx->words_top; ++i) {
  149. if(strcmp(name, ctx->words[i].name) == 0) {
  150. ctx->free(ctx->words[i].things);
  151. ctx->words[i].things = ctx->malloc(sizeof(struct elem) * count);
  152. memcpy(ctx->words[i].things, m, sizeof(struct elem) * count);
  153. ctx->words[i].size = count;
  154. return i;
  155. }
  156. }
  157. len = strlen(name);
  158. copy = ctx->malloc(len+1);
  159. if(copy == NULL) {
  160. return -2;
  161. }
  162. memcpy(copy, name, len);
  163. copy[len] = 0;
  164. ctx->words[ctx->words_top].things = ctx->malloc(sizeof(struct elem) * count);
  165. memcpy(ctx->words[ctx->words_top].things, m, sizeof(struct elem) * count);
  166. ctx->words[ctx->words_top].size = count;
  167. ctx->words[ctx->words_top].name = copy;
  168. return ctx->words_top++;
  169. }
  170. /**
  171. *
  172. * @param ctx The context
  173. * @param name The name to add
  174. * @internal add a lexed string to the parser
  175. * @return the id of the string in the list
  176. */
  177. static int ink_add_lex_string(struct context* ctx, const char* name) {
  178. int i;
  179. int len;
  180. if(ctx->lex_reserved_words == NULL) {
  181. ctx->lex_reserved_words = ctx->inner_malloc(sizeof(char*) * 8);
  182. ctx->lex_reserved_words_top = 0;
  183. ctx->lex_reserved_words_capacity = 8;
  184. } else if(ctx->lex_reserved_words_top == ctx->lex_reserved_words_capacity) {
  185. int new_count;
  186. void* renewed;
  187. new_count = (ctx->lex_reserved_words_capacity + ctx->lex_reserved_words_capacity/2);
  188. renewed = ctx->inner_realloc(ctx->lex_reserved_words, sizeof(struct native_fn) * new_count);
  189. if(renewed == NULL) {
  190. return -5;
  191. } else {
  192. ctx->lex_reserved_words = renewed;
  193. ctx->lex_reserved_words_capacity = new_count;
  194. }
  195. }
  196. for(i = 0; i < ctx->lex_reserved_words_top; i++) {
  197. if(strcmp(ctx->lex_reserved_words[i], name) == 0) {
  198. return i;
  199. }
  200. }
  201. len = strlen(name);
  202. i = ctx->lex_reserved_words_top;
  203. ctx->lex_reserved_words[i] = ctx->malloc(len+1);
  204. memcpy(ctx->lex_reserved_words[i], name, len);
  205. ctx->lex_reserved_words[i][len] = 0;
  206. ctx->lex_reserved_words_top++;
  207. return i;
  208. }
  209. int ink_push(struct context* ctx, struct elem value) {
  210. struct ink_routine* current;
  211. if(ctx->routine_current >= ctx->routines_top) return -65;
  212. current = ctx->routines + ctx->routine_current;
  213. if(current->stack == NULL) {
  214. current->stack = ctx->malloc(sizeof(struct elem) * 8);
  215. current->top = 0;
  216. current->capacity = 8;
  217. } else if(current->top == current->capacity) {
  218. int new_count;
  219. void* renewed;
  220. new_count = (current->capacity + current->capacity/2);
  221. renewed = ctx->realloc(current->stack, sizeof(struct elem) * new_count);
  222. if(renewed == NULL) {
  223. return -18;
  224. } else {
  225. current->stack = renewed;
  226. current->capacity = new_count;
  227. }
  228. }
  229. current->stack[current->top] = value;
  230. current->top++;
  231. return 0;
  232. }
  233. int ink_push_fn(struct context* ctx, struct stack_frame value) {
  234. struct ink_routine* current;
  235. if(ctx->routine_current >= ctx->routines_top) return -55;
  236. current = ctx->routines + ctx->routine_current;
  237. if(current->panic) return -56;
  238. if(current->function_stack == NULL) {
  239. current->function_stack = ctx->malloc(sizeof(struct stack_frame) * 8);
  240. current->function_stack_top = 0;
  241. current->function_stack_capacity = 8;
  242. } else if(current->function_stack_top == current->function_stack_capacity) {
  243. int new_count;
  244. void* renewed;
  245. new_count = (current->function_stack_capacity + current->function_stack_capacity/2);
  246. renewed = ctx->realloc(current->function_stack, sizeof(struct stack_frame) * new_count);
  247. if(renewed == NULL) {
  248. return -9;
  249. } else {
  250. current->function_stack = renewed;
  251. current->function_stack_capacity = new_count;
  252. }
  253. }
  254. current->function_stack[current->function_stack_top] = value;
  255. current->function_stack_top++;
  256. return 0;
  257. }
  258. void ink_pop_fn(struct context* ctx) {
  259. if(ctx->routine_current >= ctx->routines_top) return;
  260. if(ctx->routines[ctx->routine_current].panic) return;
  261. if(ctx->routines[ctx->routine_current].function_stack == NULL) return;
  262. if(ctx->routines[ctx->routine_current].function_stack_top == 0) return;
  263. ctx->routines[ctx->routine_current].function_stack_top--;
  264. }
  265. void ink_pop(struct context* ctx) {
  266. if(ctx->routine_current >= ctx->routines_top) return;
  267. if(ctx->routines[ctx->routine_current].panic) return;
  268. if(ctx->routines[ctx->routine_current].stack == NULL) return;
  269. if(ctx->routines[ctx->routine_current].top == 0) return;
  270. ctx->routines[ctx->routine_current].top--;
  271. }
  272. struct context* ink_make_context(void*(*malloc)(size_t), void*(*realloc)(void*, size_t), void(*free)(void*), int(*putchar)(int)) {
  273. struct context* ctx;
  274. ctx = (struct context*)malloc(sizeof(struct context));
  275. ctx->malloc = malloc;
  276. ctx->realloc = realloc;
  277. ctx->free = free;
  278. ctx->inner_malloc = malloc;
  279. ctx->inner_realloc = realloc;
  280. ctx->inner_free = free;
  281. ctx->putchar = putchar;
  282. ctx->panic = 0;
  283. ctx->routines = NULL;
  284. ctx->routines_capacity = 0;
  285. ctx->routines_top = 0;
  286. ctx->types = NULL;
  287. ctx->types_capacity = 0;
  288. ctx->types_top = 0;
  289. ctx->native_words = NULL;
  290. ctx->native_words_capacity = 0;
  291. ctx->native_words_top = 0;
  292. ctx->words = NULL;
  293. ctx->words_capacity = 0;
  294. ctx->words_top = 0;
  295. ctx->lex_reserved_words = NULL;
  296. ctx->lex_reserved_words_capacity = 0;
  297. ctx->lex_reserved_words_top = 0;
  298. ctx->collections = 0;
  299. ctx->steps = 0;
  300. return ctx;
  301. }
  302. /**
  303. * Allocates a string that contains the integer
  304. * @param _ context (used to allocate)
  305. * @param cpy the value
  306. * @return the allocated string, needs to be freed by ctx->free
  307. * @internal this function is slightly cursed
  308. */
  309. static char* ink_itoa(struct context* _, int cpy) {
  310. char* n;
  311. char* it;
  312. n = _->malloc(16);
  313. n[15] = 0;
  314. it = n+15;
  315. do {
  316. it--;
  317. *it = (cpy % 10) + '0';
  318. cpy = cpy / 10;
  319. } while(cpy);
  320. memmove(n, it, 16 - (it-n));
  321. return n;
  322. }
  323. #ifndef NOSTDLIB
  324. struct context* ink_make_default_context(void) {
  325. struct context* ctx;
  326. ctx = ink_make_context(malloc, realloc, free, putchar);
  327. ink_std_library(ctx);
  328. return ctx;
  329. }
  330. #endif
  331. #ifndef NOSTRINGLITERALS
  332. static void new_protected_array(struct context* ctx);
  333. #endif
  334. static int ink_consume_one(int* end, struct context* pContext, char* r, int is_str) {
  335. int i;
  336. int done;
  337. struct elem value;
  338. int err;
  339. #ifndef NOSTRINGLITERALS
  340. if(is_str) {
  341. struct ink_routine* routine = pContext->routines + pContext->routine_current;
  342. struct ink_array* ary;
  343. int it = 0;
  344. new_protected_array(pContext);
  345. if(routine->top < 1) {
  346. pContext->panic = -1;
  347. return -8746;
  348. }
  349. value = routine->stack[routine->top - 1];
  350. ary = ink_get_value(pContext, value);
  351. if(ary == NULL) {
  352. pContext->panic = -1;
  353. return -8747;
  354. }
  355. for(;it != *end;++it) {
  356. struct elem character;
  357. character.type = INK_INTEGER;
  358. /* TODO: codepoint conversion and coalescence is required here */
  359. character.value = r[it];
  360. array_push(pContext, routine, ary, character);
  361. }
  362. *end = 0;
  363. return 0;
  364. }
  365. #endif
  366. is_str = is_str;
  367. if(*end == 0) {
  368. return 0;
  369. }
  370. r[*end] = 0;
  371. done = 0;
  372. if (strcmp(r, _KEYWORD_INK_FUNCTION) == 0) {
  373. value.value = 0;
  374. value.type = INK_FUNCTION_KW;
  375. done = 1;
  376. }
  377. if (!done && strcmp(r, _KEYWORD_INK_DO) == 0) {
  378. value.value = 0;
  379. value.type = INK_DO_KW;
  380. done = 1;
  381. }
  382. if (!done && strcmp(r, _KEYWORD_INK_END) == 0) {
  383. value.value = 0;
  384. value.type = INK_END_KW;
  385. done = 1;
  386. }
  387. if (!done && strcmp(r, _KEYWORD_INK_RETURN) == 0) {
  388. value.value = 0;
  389. value.type = INK_RETURN;
  390. done = 1;
  391. }
  392. if(done) {
  393. err = ink_push(pContext, value);
  394. if(err < 0) {
  395. return -19;
  396. }
  397. }
  398. if (!done) {
  399. for (i = 0; i < pContext->words_top; ++i) {
  400. if (strcmp(r, pContext->words[i].name) == 0) {
  401. value.value = i;
  402. value.type = INK_FUNCTION;
  403. err = ink_push(pContext, value);
  404. if(err < 0) {
  405. return -20;
  406. }
  407. done = 1;
  408. break;
  409. }
  410. }
  411. }
  412. if (!done) {
  413. for (i = 0; i < pContext->native_words_top; ++i) {
  414. if (strcmp(r, pContext->native_words[i].name) == 0) {
  415. value.value = i;
  416. value.type = INK_NATIVE_FUNCTION;
  417. err = ink_push(pContext, value);
  418. if(err < 0) {
  419. return -21;
  420. }
  421. done = 1;
  422. break;
  423. }
  424. }
  425. }
  426. if (!done) {
  427. for(i = (r[0] == '-'); i < *end; i++) {
  428. if(!isdigit(r[i])){
  429. goto not_an_int;
  430. }
  431. }
  432. value.value = atoi(r);
  433. value.type = INK_INTEGER;
  434. err = ink_push(pContext, value);
  435. if(err < 0) {
  436. return -22;
  437. }
  438. done = 1;
  439. }
  440. not_an_int:
  441. if (!done) {
  442. i = ink_add_lex_string(pContext, r);
  443. if(i < 0) {
  444. pContext->panic = 1;
  445. return -7;
  446. }
  447. value.value = i;
  448. if(r[strlen(r) - 1] == ':') {
  449. value.type = INK_LABEL;
  450. } else {
  451. value.type = INK_RESERVED;
  452. }
  453. err = ink_push(pContext, value);
  454. if(err < 0) {
  455. return -23;
  456. }
  457. }
  458. *end = 0;
  459. return 0;
  460. }
  461. static int ink_lex(struct context *pContext, const char* buffer) {
  462. /* Limits the token size to 127 chars */
  463. char r[128];
  464. int end;
  465. int err;
  466. #ifndef NOSTRINGLITERALS
  467. int parses_string;
  468. #endif
  469. end = 0;
  470. restart_after_comment:
  471. #ifndef NOSTRINGLITERALS
  472. parses_string = 0;
  473. #endif
  474. while(*buffer != 0) {
  475. #ifndef NOSTRINGLITERALS
  476. if(parses_string) {
  477. switch(*buffer) {
  478. case '"': {
  479. if(*(buffer+1) == 0 || isspace(*(buffer+1))) {
  480. err = ink_consume_one(&end, pContext, r, 1);
  481. if(err < 0) {
  482. pContext->panic = 1;
  483. return -995;
  484. }
  485. parses_string = 0;
  486. } else if(*(buffer+1) == '"') {
  487. r[end] = *buffer;
  488. ++end;
  489. ++buffer;
  490. } else if(*(buffer+1) == '/' && *(buffer+2) == '"') {
  491. r[end] = '\n';
  492. ++end;
  493. ++buffer;
  494. ++buffer;
  495. } else {
  496. pContext->panic = 1;
  497. return -994;
  498. }
  499. }break;
  500. default:
  501. r[end] = *buffer;
  502. ++end;
  503. }
  504. } else /* ... */
  505. #endif
  506. if(isspace(*buffer)) {
  507. if(end == 1 && r[0] == '#') {
  508. while(*buffer != '\n' && *buffer != 0) {
  509. ++buffer;
  510. }
  511. end = 0;
  512. goto restart_after_comment;
  513. }
  514. err = ink_consume_one(&end, pContext, r, 0);
  515. if(err < 0) {
  516. pContext->panic = 1;
  517. return -8;
  518. }
  519. } else /* ... */
  520. #ifndef NOSTRINGLITERALS
  521. if(end == 0 && *buffer == '"' && !parses_string) {
  522. parses_string = 1;
  523. } else /* ... */
  524. #endif
  525. {
  526. r[end] = *buffer;
  527. ++end;
  528. }
  529. ++buffer;
  530. }
  531. err = ink_consume_one(&end, pContext, r, 0);
  532. if(err < 0) {
  533. pContext->panic = 1;
  534. return -9;
  535. }
  536. return 0;
  537. }
  538. static int lblcmp(const char* label, const char* other, size_t label_sz) {
  539. while (label_sz != 1) {
  540. if(*other == 0) return 1;
  541. if(*label != *other) return 1;
  542. ++label;
  543. ++other;
  544. label_sz--;
  545. }
  546. return 0;
  547. }
  548. int ink_make_routine(struct context* ctx) {
  549. struct ink_routine* it;
  550. struct ink_routine* end;
  551. /* Allocate space if needed */
  552. if(ctx->routines == NULL) {
  553. ctx->routines = ctx->inner_malloc(sizeof(struct ink_routine) * 8);
  554. ctx->routines_top = 0;
  555. ctx->routines_capacity = 8;
  556. it = ctx->routines;
  557. end = ctx->routines + 8;
  558. for(;it != end;++it) {
  559. it->stack = NULL;
  560. it->function_stack = NULL;
  561. it->panic = INK_ROUTINE_CAN_REUSE;
  562. }
  563. } else if(ctx->routines_top == ctx->routines_capacity) {
  564. int new_count;
  565. void* renewed;
  566. new_count = (ctx->routines_capacity + ctx->routines_capacity/2);
  567. renewed = ctx->inner_realloc(ctx->routines, sizeof(struct ink_routine) * new_count);
  568. if(renewed == NULL) {
  569. return -99;
  570. } else {
  571. ctx->routines = renewed;
  572. it = ctx->routines + ctx->routines_capacity;
  573. end = ctx->routines + new_count;
  574. for(;it != end;++it) {
  575. it->panic = INK_ROUTINE_CAN_REUSE;
  576. }
  577. ctx->routines_capacity = new_count;
  578. }
  579. }
  580. it = ctx->routines;
  581. end = ctx->routines + ctx->routines_capacity;
  582. /* Looks for a reusable routine space then uses it */
  583. for(;it != end;++it) {
  584. if(it->panic == INK_ROUTINE_CAN_REUSE) {
  585. int idx;
  586. it->panic = 0;
  587. it->stack = NULL;
  588. it->top = 0;
  589. it->capacity = 0;
  590. it->function_stack = NULL;
  591. it->function_stack_top = 0;
  592. it->function_stack_capacity = 0;
  593. idx = it - ctx->routines;
  594. if(idx >= ctx->routines_top) {
  595. ctx->routines_top = idx + 1;
  596. }
  597. return idx;
  598. }
  599. }
  600. return -758;
  601. }
  602. int ink_kill_routine(struct context* ctx, int routine){
  603. struct ink_routine* curr;
  604. if(routine < 0 || routine >= ctx->routines_top) {
  605. return 0;
  606. }
  607. curr = ctx->routines + routine;
  608. if(curr->panic == INK_ROUTINE_CAN_REUSE) {
  609. return 0;
  610. }
  611. if(curr->stack != NULL) {
  612. ctx->free(curr->stack);
  613. curr->stack = NULL;
  614. }
  615. if(curr->function_stack != NULL) {
  616. ctx->free(curr->function_stack);
  617. curr->function_stack = NULL;
  618. }
  619. curr->panic = INK_ROUTINE_CAN_REUSE;
  620. return 1;
  621. }
  622. /**
  623. *
  624. * @param pContext
  625. * @param executable_buffer
  626. * @param executable_buffer_top
  627. * @internal Loop from hell
  628. */
  629. static int ink_parse(struct context* pContext, struct elem* executable_buffer, int* executable_buffer_top) {
  630. struct ink_routine* currentRoutine;
  631. int i, function_buffer_top, function_name, mode;
  632. int err;
  633. #define LABEL_BUFFER 128
  634. #define FUNCTION_BUFFER 256
  635. struct label labels[LABEL_BUFFER];
  636. struct elem function_buffer[FUNCTION_BUFFER];
  637. /* TODO: add checks for overflows in these arrays */
  638. currentRoutine = pContext->routines + pContext->routine_current;
  639. function_buffer_top = 0;
  640. function_name = -1;
  641. #define MODE_EXECUTABLE 0
  642. #define MODE_FUNCTION 1
  643. #define MODE_DO 2
  644. mode = MODE_EXECUTABLE;
  645. memset(labels, 0, sizeof(struct label)*LABEL_BUFFER);
  646. /* Loop from hell, good luck, pro-tip: leave the parser alone */
  647. for(i = 0; i < currentRoutine->top; ++i) {
  648. struct elem current;
  649. current = currentRoutine->stack[i];
  650. switch (mode) {
  651. case MODE_EXECUTABLE:
  652. switch(current.type) {
  653. case INK_FUNCTION_KW:
  654. mode = MODE_FUNCTION;
  655. function_name = -1;
  656. goto next_token;
  657. case INK_DO_KW:
  658. case INK_END_KW:
  659. return -26;
  660. default:
  661. executable_buffer[*executable_buffer_top] = current;
  662. *executable_buffer_top += 1;
  663. }
  664. break;
  665. case MODE_FUNCTION:
  666. if(current.type == INK_DO_KW) {
  667. if(function_name == -1) {
  668. return -27;
  669. } else {
  670. mode = MODE_DO;
  671. memset(labels, 0, sizeof(struct label)*128);
  672. goto next_token;
  673. }
  674. }
  675. if(function_name != -1) {
  676. return -28;
  677. }
  678. if(current.type != INK_RESERVED) {
  679. return -29;
  680. }
  681. function_name = current.value;
  682. break;
  683. case MODE_DO:
  684. if(current.type == INK_END_KW) {
  685. int j;
  686. for(j = 0; j < function_buffer_top; j++) {
  687. struct elem pt;
  688. pt = function_buffer[j];
  689. if(pt.type == INK_LABEL) {
  690. int k;
  691. for(k = 0; k < LABEL_BUFFER; k++) {
  692. if(labels[k].active) {
  693. if(strcmp(labels[k].name, pContext->lex_reserved_words[pt.value]) == 0) {
  694. labels[k].dest = j;
  695. return -30;
  696. break;
  697. }
  698. } else {
  699. labels[k].active = 1;
  700. labels[k].name = pContext->lex_reserved_words[pt.value];
  701. labels[k].dest = j;
  702. memcpy(function_buffer+j, function_buffer+j+1, sizeof(struct elem)*(function_buffer_top-j-1));
  703. function_buffer_top--;
  704. j--;
  705. break;
  706. }
  707. }
  708. }
  709. }
  710. for(j = 0; j < function_buffer_top; j++) {
  711. struct elem pt;
  712. pt = function_buffer[j];
  713. if(pt.type == INK_RESERVED) {
  714. int k;
  715. for(k = 0; k < LABEL_BUFFER; k++) {
  716. if(labels[k].active) {
  717. int label_sz;
  718. const char* lbl;
  719. lbl = labels[k].name;
  720. label_sz = strlen(lbl);
  721. if(lblcmp(labels[k].name, pContext->lex_reserved_words[pt.value], label_sz) == 0) {
  722. function_buffer[j].type = INK_INTEGER;
  723. function_buffer[j].value = labels[k].dest - j;
  724. break;
  725. }
  726. } else break;
  727. }
  728. }
  729. }
  730. err = ink_add_indigenous(pContext, pContext->lex_reserved_words[function_name], function_buffer, function_buffer_top);
  731. if(err < 0) {
  732. pContext->panic = 1;
  733. return -33;
  734. }
  735. function_buffer_top = 0;
  736. mode = MODE_EXECUTABLE;
  737. goto next_token;
  738. }
  739. function_buffer[function_buffer_top] = current;
  740. function_buffer_top += 1;
  741. break;
  742. }
  743. next_token: i=i;
  744. }
  745. if(mode == MODE_FUNCTION || mode == MODE_DO) {
  746. return -32;
  747. }
  748. return 0;
  749. #undef MODE_EXECUTABLE
  750. #undef MODE_FUNCTION
  751. #undef MODE_DO
  752. #undef LABEL_BUFFER
  753. #undef FUNCTION_BUFFER
  754. }
  755. int ink_step(struct context *pContext) {
  756. struct ink_routine* currentRoutine;
  757. struct stack_frame frame;
  758. struct stack_frame* top;
  759. struct elem next;
  760. int t;
  761. currentRoutine = pContext->routines + pContext->routine_current;
  762. pContext->steps++;
  763. if(currentRoutine->function_stack_top == 0) return 0;
  764. if(pContext->panic) {
  765. return -1;
  766. }
  767. top = &currentRoutine->function_stack[currentRoutine->function_stack_top-1];
  768. t = top->executing.type;
  769. switch(t) {
  770. case INK_NATIVE_FUNCTION:
  771. if(top->index != 0) {
  772. ink_pop_fn(pContext);
  773. } else {
  774. top->index++;
  775. if(pContext->native_words_top <= top->executing.value) {
  776. pContext->panic = 1;
  777. return -1;
  778. }
  779. pContext->native_words[top->executing.value].value(pContext);
  780. }
  781. break;
  782. case INK_FUNCTION:
  783. if(pContext->words_top <= top->executing.value) {
  784. pContext->panic = 1;
  785. return -1;
  786. }
  787. if(top->index >= pContext->words[top->executing.value].size) {
  788. ink_pop_fn(pContext);
  789. } else {
  790. next = pContext->words[top->executing.value].things[top->index];
  791. if(next.type == INK_RETURN) {
  792. ink_pop_fn(pContext);
  793. return 1;
  794. }
  795. frame.executing = next;
  796. frame.index = 0;
  797. t = ink_push_fn(pContext, frame);
  798. if(t < 0) {
  799. pContext->panic = 1;
  800. return -11;
  801. }
  802. top->index++;
  803. }
  804. break;
  805. default:
  806. t = ink_push(pContext, top->executing);
  807. if(t < 0) {
  808. pContext->panic = 1;
  809. return -25;
  810. }
  811. ink_pop_fn(pContext);
  812. break;
  813. }
  814. return 1;
  815. }
  816. int ink_compile(struct context *pContext, const char* buffer) {
  817. int routine, saved, executable_buffer_top;
  818. /* Main function has a size limit of 256 (need to know that for REPL */
  819. struct elem executable_buffer[256];
  820. struct ink_routine* currentRoutine;
  821. int err;
  822. struct stack_frame frame;
  823. char* integer;
  824. size_t integer_size;
  825. char main_fn[32] = "__-MAIN-__";
  826. routine = ink_make_routine(pContext);
  827. saved = pContext->routine_current;
  828. pContext->routine_current = routine;
  829. currentRoutine = pContext->routines + routine;
  830. currentRoutine->stack = NULL;
  831. currentRoutine->top = 0;
  832. currentRoutine->capacity = 0;
  833. err = ink_lex(pContext, buffer);
  834. if(err < 0) {
  835. pContext->panic = 1;
  836. return -1;
  837. }
  838. executable_buffer_top = 0;
  839. err = ink_parse(pContext, executable_buffer, &executable_buffer_top);
  840. if(err < 0) {
  841. pContext->panic = 1;
  842. return -1;
  843. }
  844. if(executable_buffer_top != 0) {
  845. integer = ink_itoa(pContext, routine);
  846. integer_size = strlen(integer);
  847. memcpy(main_fn + 10, integer, integer_size);
  848. pContext->free(integer);
  849. main_fn[10 + integer_size] = 0;
  850. frame.executing.value = ink_add_indigenous(pContext, main_fn, executable_buffer, executable_buffer_top);
  851. if (frame.executing.value < 0) {
  852. pContext->panic = 1;
  853. return -1;
  854. }
  855. frame.executing.type = INK_FUNCTION;
  856. frame.index = 0;
  857. err = ink_push_fn(pContext, frame);
  858. pContext->routines[pContext->routine_current].top = 0;
  859. if (err < 0) {
  860. pContext->panic = 1;
  861. return -1;
  862. }
  863. } else {
  864. pContext->routines[pContext->routine_current].panic = INK_ROUTINE_SUCCESS;
  865. }
  866. pContext->routine_current = saved;
  867. return routine;
  868. }
  869. int ink_can_run(struct context* pContext) {
  870. int it;
  871. if(pContext->panic) return 0;
  872. if(pContext->routines_top == 0) return 0;
  873. for(it = 0; it < pContext->routines_top; ++it) {
  874. if(pContext->routines[it].panic == 0) {
  875. return 1;
  876. }
  877. }
  878. return 0;
  879. }
  880. int ink_step_everyone(struct context* pContext) {
  881. int out;
  882. pContext->routine_current = -1;
  883. for(;;) {
  884. /* Increment to next runnable routine */
  885. do{
  886. ++(pContext->routine_current);
  887. } while(pContext->routine_current < pContext->routines_top && pContext->routines[pContext->routine_current].panic != 0);
  888. /* Exit condition */
  889. if(pContext->routine_current >= pContext->routines_top) break;
  890. /* Kill? */
  891. if(pContext->routines[pContext->routine_current].panic == INK_ROUTINE_SUCCESS) {
  892. ink_kill_routine(pContext, pContext->routine_current);
  893. }
  894. /* Step! */
  895. out = ink_step(pContext);
  896. if(out == 0) {
  897. pContext->routines[pContext->routine_current].panic = INK_ROUTINE_SUCCESS;
  898. } else if(out < 0) {
  899. pContext->routines[pContext->routine_current].panic = out;
  900. }
  901. }
  902. return 0;
  903. }
  904. int ink_new_type(
  905. struct context* ctx,
  906. const char* type_name,
  907. int size,
  908. void (*collect)(struct context*,void*),
  909. struct ink_collection_list (*gc)(struct context*,void*)
  910. ) {
  911. if(ctx->panic) return -128;
  912. /* Resize for push */
  913. if(ctx->types == NULL) {
  914. ctx->types = ctx->inner_malloc(sizeof(struct ink_type) * 8);
  915. ctx->types_top = 0;
  916. ctx->types_capacity = 8;
  917. } else if(ctx->types_top == ctx->types_capacity) {
  918. int new_count;
  919. void* renewed;
  920. new_count = (ctx->types_capacity + ctx->types_capacity/2);
  921. renewed = ctx->inner_realloc(ctx->types, sizeof(struct ink_type) * new_count);
  922. if(renewed == NULL) {
  923. return -129;
  924. } else {
  925. ctx->types = renewed;
  926. ctx->types_capacity = new_count;
  927. }
  928. }
  929. /* Push */
  930. ctx->types[ctx->types_top].name = type_name;
  931. ctx->types[ctx->types_top].element_size = size;
  932. ctx->types[ctx->types_top].elements = NULL;
  933. ctx->types[ctx->types_top].elements_top = 0;
  934. ctx->types[ctx->types_top].elements_capacity = 0;
  935. ctx->types[ctx->types_top].collect = collect;
  936. ctx->types[ctx->types_top].gc = gc;
  937. ctx->types_top++;
  938. /* Satisfying the minimal value requirement */
  939. return ctx->types_top - 1 + 16;
  940. }
  941. static struct element_slab* ink_get_value_link(struct context* ctx, struct elem ref) {
  942. int type_id;
  943. if(ref.type < 16) return NULL;
  944. type_id = ref.type - 16;
  945. if(type_id >= ctx->types_top) return NULL;
  946. if(ctx->types[type_id].element_size == 0) return NULL;
  947. if(ref.value < 0) return NULL;
  948. if(ref.value >= ctx->types[type_id].elements_top) return NULL;
  949. if(! ctx->types[type_id].elements[ref.value].in_use) return NULL;
  950. return ctx->types[type_id].elements + ref.value;
  951. }
  952. void* ink_get_value(struct context* ctx, struct elem ref) {
  953. struct element_slab* s;
  954. s = ink_get_value_link(ctx, ref);
  955. if(s == NULL) return NULL;
  956. return s->data;
  957. }
  958. struct elem ink_make_native_unsafe(struct context* ctx, int type, void* ptr, int is_protected) {
  959. int type_id;
  960. struct elem ret;
  961. int g, i;
  962. if(type < 16) {
  963. ret.type = 0;
  964. ret.value = -130;
  965. return ret;
  966. }
  967. /* Apply invariant of the user defined types */
  968. type_id = type - 16;
  969. if(type_id >= ctx->types_top) {
  970. ret.type = 0;
  971. ret.value = -129;
  972. return ret;
  973. }
  974. if(ctx->panic) {
  975. ret.type = 0;
  976. ret.value = -135;
  977. return ret;
  978. }
  979. /* Resize for push of value in store */
  980. if(ctx->types[type_id].elements == NULL) {
  981. ctx->types[type_id].elements = ctx->inner_malloc(sizeof(struct element_slab) * 8);
  982. ctx->types[type_id].elements_top = 0;
  983. ctx->types[type_id].elements_capacity = 8;
  984. memset(ctx->types[type_id].elements + ctx->types[type_id].elements_top, 0, sizeof(struct element_slab)*(ctx->types[type_id].elements_capacity - ctx->types[type_id].elements_top));
  985. } else if(ctx->types[type_id].elements_top == ctx->types[type_id].elements_capacity) {
  986. int new_count;
  987. void* renewed;
  988. new_count = (ctx->types[type_id].elements_capacity + ctx->types[type_id].elements_capacity/2);
  989. renewed = ctx->inner_realloc(ctx->types[type_id].elements, sizeof(struct element_slab) * new_count);
  990. if(renewed == NULL) {
  991. ret.type = 0;
  992. ret.value = -129;
  993. return ret;
  994. } else {
  995. ctx->types[type_id].elements = renewed;
  996. ctx->types[type_id].elements_capacity = new_count;
  997. memset(ctx->types[type_id].elements + ctx->types[type_id].elements_top, 0, sizeof(struct element_slab)*(ctx->types[type_id].elements_capacity - ctx->types[type_id].elements_top));
  998. }
  999. }
  1000. /* Push value in store */
  1001. g = ctx->types[type_id].elements_capacity;
  1002. for(i = 0; i < g; ++i) {
  1003. if(! ctx->types[type_id].elements[i].in_use) {
  1004. ctx->types[type_id].elements[i].in_use = 1;
  1005. ctx->types[type_id].elements[i].uses = 1;
  1006. ctx->types[type_id].elements[i].is_protected = is_protected;
  1007. if(ctx->types[type_id].element_size < 0) {
  1008. ctx->types[type_id].elements[i].data = ptr;
  1009. } else {
  1010. void* new_ptr = ctx->malloc(ctx->types[type_id].element_size);
  1011. if(new_ptr == NULL) {
  1012. ret.type = 0;
  1013. ret.value = -139;
  1014. return ret;
  1015. }
  1016. memcpy(new_ptr, ptr, ctx->types[type_id].element_size);
  1017. ctx->types[type_id].elements[i].data = new_ptr;
  1018. }
  1019. ctx->types[type_id].elements_top = max(ctx->types[type_id].elements_top, i+1);
  1020. ret.type = type;
  1021. ret.value = i;
  1022. return ret;
  1023. }
  1024. }
  1025. ret.type = 0;
  1026. ret.value = -140;
  1027. return ret;
  1028. }
  1029. struct elem ink_make_native(struct context* ctx, int type, void* ptr) {
  1030. return ink_make_native_unsafe(ctx, type, ptr, 0);
  1031. }
  1032. void ink_gc(struct context* ctx) {
  1033. int i, j, k;
  1034. int marked;
  1035. struct element_slab* v;
  1036. for(i = 0; i < ctx->types_top; ++i) {
  1037. for(j = 0; j < ctx->types[i].elements_top; ++j) {
  1038. ctx->types[i].elements[j].uses = 0;
  1039. }
  1040. }
  1041. /* Start by marking the roots of the routines, Clear the routines if possible */
  1042. for(i = 0; i < ctx->routines_top; ++i) {
  1043. if(ctx->routines[i].panic == INK_ROUTINE_SUCCESS) {
  1044. ctx->free(ctx->routines[i].stack);
  1045. ctx->free(ctx->routines[i].function_stack);
  1046. ctx->routines[i].panic = INK_ROUTINE_CAN_REUSE;
  1047. }
  1048. if(ctx->routines[i].panic == INK_ROUTINE_CAN_REUSE) {
  1049. continue;
  1050. }
  1051. for(j = 0; j < ctx->routines[i].top; ++j) {
  1052. v = ink_get_value_link(ctx, ctx->routines[i].stack[j]);
  1053. if(v != NULL) ++v->uses;
  1054. }
  1055. }
  1056. /* TODO: Mark objects contained within function code */
  1057. /* Mark the rest of the data */
  1058. do {
  1059. marked = 0;
  1060. for (i = 0; i < ctx->types_top; ++i) {
  1061. for (j = 0; j < ctx->types[i].elements_top; ++j) {
  1062. /* Only mark from things that are active and detected as in use */
  1063. if (ctx->types[i].elements[j].in_use && ctx->types[i].elements[j].is_protected && ctx->types[i].elements[j].uses) {
  1064. struct ink_collection_list c;
  1065. c = ctx->types[i].gc(ctx, ctx->types[i].elements[j].data);
  1066. for (k = 0; k < c.count; ++k) {
  1067. v = ink_get_value_link(ctx, c.elements[k]);
  1068. /* Never mark twice to avoid infinite loops with e.g. arrays that contain themselves */
  1069. if (v != NULL && !v->uses) {
  1070. ++v->uses;
  1071. marked = 1;
  1072. }
  1073. }
  1074. if (c.elements != NULL) ctx->inner_free(c.elements);
  1075. }
  1076. }
  1077. }
  1078. } while(marked);
  1079. /* Sweep phase: explore any allocated data and sweep the unused away */
  1080. for(i = 0; i < ctx->types_top; ++i) {
  1081. for(j = 0; j < ctx->types[i].elements_top; ++j) {
  1082. if(ctx->types[i].elements[j].uses == 0 && ctx->types[i].elements[j].in_use && ctx->types[i].elements[j].is_protected == 0) {
  1083. ctx->collections++;
  1084. ctx->types[i].collect(ctx, ctx->types[i].elements[j].data);
  1085. if(ctx->types[i].element_size > 0) {
  1086. ctx->free(ctx->types[i].elements[j].data);
  1087. }
  1088. ctx->types[i].elements[j].data = NULL;
  1089. ctx->types[i].elements[j].uses = 0;
  1090. ctx->types[i].elements[j].in_use = 0;
  1091. }
  1092. }
  1093. }
  1094. }
  1095. /**********************************************************************************************************************/
  1096. static void print_stacktrace(struct context* _) {
  1097. int i;
  1098. struct ink_routine* currentRoutine;
  1099. currentRoutine = _->routines + _->routine_current;
  1100. for(i = 0; i < currentRoutine->function_stack_top; ++i) {
  1101. struct elem thing;
  1102. char *n;
  1103. thing = currentRoutine->function_stack[i].executing;
  1104. switch(thing.type) {
  1105. case INK_NATIVE_FUNCTION: {
  1106. n = _->native_words[thing.value].name;
  1107. while (*n) {
  1108. _->putchar(*n);
  1109. ++n;
  1110. }
  1111. _->putchar(10);
  1112. break;
  1113. }
  1114. case INK_FUNCTION:{
  1115. n = _->words[thing.value].name;
  1116. while (*n) {
  1117. _->putchar(*n);
  1118. ++n;
  1119. }
  1120. _->putchar(':');
  1121. n = ink_itoa(_, currentRoutine->function_stack[i].index);
  1122. while (*n) {
  1123. _->putchar(*n);
  1124. ++n;
  1125. }
  1126. _->putchar(10);
  1127. break;
  1128. }
  1129. default:
  1130. break;
  1131. }
  1132. }
  1133. }
  1134. static void add_int(struct context* ctx) {
  1135. struct ink_routine* currentRoutine;
  1136. struct elem a;
  1137. struct elem b;
  1138. currentRoutine = ctx->routines + ctx->routine_current;
  1139. if(currentRoutine->top < 2) {
  1140. currentRoutine->panic = -1;
  1141. return;
  1142. }
  1143. a = currentRoutine->stack[currentRoutine->top-1];
  1144. b = currentRoutine->stack[currentRoutine->top-2];
  1145. if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) {
  1146. ctx->panic = 1;
  1147. return;
  1148. }
  1149. ink_pop(ctx);
  1150. currentRoutine->stack[currentRoutine->top-1].value = a.value + b.value;
  1151. }
  1152. static void sub_int(struct context* ctx) {
  1153. struct ink_routine* currentRoutine;
  1154. struct elem a;
  1155. struct elem b;
  1156. currentRoutine = ctx->routines + ctx->routine_current;
  1157. if(currentRoutine->top < 2) {
  1158. currentRoutine->panic = -1;
  1159. return;
  1160. }
  1161. a = currentRoutine->stack[currentRoutine->top-1];
  1162. b = currentRoutine->stack[currentRoutine->top-2];
  1163. if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) {
  1164. currentRoutine->panic = -1;
  1165. return;
  1166. }
  1167. ink_pop(ctx);
  1168. currentRoutine->stack[currentRoutine->top-1].value = b.value - a.value;
  1169. }
  1170. static void mult_int(struct context* ctx) {
  1171. struct ink_routine* currentRoutine;
  1172. struct elem a;
  1173. struct elem b;
  1174. currentRoutine = ctx->routines + ctx->routine_current;
  1175. if(currentRoutine->top < 2) {
  1176. currentRoutine->panic = -1;
  1177. return;
  1178. }
  1179. a = currentRoutine->stack[currentRoutine->top-1];
  1180. b = currentRoutine->stack[currentRoutine->top-2];
  1181. if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) {
  1182. currentRoutine->panic = -1;
  1183. return;
  1184. }
  1185. ink_pop(ctx);
  1186. currentRoutine->stack[currentRoutine->top-1].value = b.value * a.value;
  1187. }
  1188. static void div_int(struct context* ctx) {
  1189. struct ink_routine* currentRoutine;
  1190. struct elem a;
  1191. struct elem b;
  1192. currentRoutine = ctx->routines + ctx->routine_current;
  1193. if(currentRoutine->top < 2) {
  1194. currentRoutine->panic = -1;
  1195. return;
  1196. }
  1197. a = currentRoutine->stack[currentRoutine->top-1];
  1198. b = currentRoutine->stack[currentRoutine->top-2];
  1199. if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) {
  1200. currentRoutine->panic = -1;
  1201. return;
  1202. }
  1203. ink_pop(ctx);
  1204. currentRoutine->stack[currentRoutine->top-1].value = b.value / a.value;
  1205. }
  1206. static void is_equal(struct context* ctx) {
  1207. struct ink_routine* currentRoutine;
  1208. struct elem a;
  1209. struct elem b;
  1210. struct elem ret;
  1211. currentRoutine = ctx->routines + ctx->routine_current;
  1212. if(currentRoutine->top < 2) {
  1213. currentRoutine->panic = -1;
  1214. return;
  1215. }
  1216. a = currentRoutine->stack[currentRoutine->top-1];
  1217. b = currentRoutine->stack[currentRoutine->top-2];
  1218. ink_pop(ctx);
  1219. ink_pop(ctx);
  1220. ret.type = INK_INTEGER;
  1221. ret.value = a.value == b.value && a.type == b.type;
  1222. ink_push(ctx, ret);
  1223. }
  1224. static void is_different(struct context* ctx) {
  1225. struct ink_routine* currentRoutine;
  1226. struct elem a;
  1227. struct elem b;
  1228. struct elem ret;
  1229. currentRoutine = ctx->routines + ctx->routine_current;
  1230. if(currentRoutine->top < 2) {
  1231. currentRoutine->panic = -1;
  1232. return;
  1233. }
  1234. a = currentRoutine->stack[currentRoutine->top-1];
  1235. b = currentRoutine->stack[currentRoutine->top-2];
  1236. ink_pop(ctx);
  1237. ink_pop(ctx);
  1238. ret.type = INK_INTEGER;
  1239. ret.value = !(a.value == b.value && a.type == b.type);
  1240. ink_push(ctx, ret);
  1241. }
  1242. #ifndef NOEXTRAARITHMETIC
  1243. static void rem_int(struct context* ctx) {
  1244. struct ink_routine* currentRoutine;
  1245. struct elem a;
  1246. struct elem b;
  1247. currentRoutine = ctx->routines + ctx->routine_current;
  1248. if(currentRoutine->top < 2) {
  1249. currentRoutine->panic = -1;
  1250. return;
  1251. }
  1252. a = currentRoutine->stack[currentRoutine->top-1];
  1253. b = currentRoutine->stack[currentRoutine->top-2];
  1254. if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) {
  1255. currentRoutine->panic = -1;
  1256. return;
  1257. }
  1258. ink_pop(ctx);
  1259. currentRoutine->stack[currentRoutine->top-1].value = b.value % a.value;
  1260. }
  1261. static void xor_int(struct context* ctx) {
  1262. struct ink_routine* currentRoutine;
  1263. struct elem a;
  1264. struct elem b;
  1265. currentRoutine = ctx->routines + ctx->routine_current;
  1266. if(currentRoutine->top < 2) {
  1267. currentRoutine->panic = -1;
  1268. return;
  1269. }
  1270. a = currentRoutine->stack[currentRoutine->top-1];
  1271. b = currentRoutine->stack[currentRoutine->top-2];
  1272. if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) {
  1273. currentRoutine->panic = -1;
  1274. return;
  1275. }
  1276. ink_pop(ctx);
  1277. currentRoutine->stack[currentRoutine->top-1].value = b.value ^ a.value;
  1278. }
  1279. static void gt_int(struct context* ctx) {
  1280. struct ink_routine* currentRoutine;
  1281. struct elem a;
  1282. struct elem b;
  1283. currentRoutine = ctx->routines + ctx->routine_current;
  1284. if(currentRoutine->top < 2) {
  1285. currentRoutine->panic = -1;
  1286. return;
  1287. }
  1288. a = currentRoutine->stack[currentRoutine->top-1];
  1289. b = currentRoutine->stack[currentRoutine->top-2];
  1290. if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) {
  1291. currentRoutine->panic = -1;
  1292. return;
  1293. }
  1294. ink_pop(ctx);
  1295. currentRoutine->stack[currentRoutine->top-1].value = b.value > a.value;
  1296. }
  1297. static void gte_int(struct context* ctx) {
  1298. struct ink_routine* currentRoutine;
  1299. struct elem a;
  1300. struct elem b;
  1301. currentRoutine = ctx->routines + ctx->routine_current;
  1302. if(currentRoutine->top < 2) {
  1303. currentRoutine->panic = -1;
  1304. return;
  1305. }
  1306. a = currentRoutine->stack[currentRoutine->top-1];
  1307. b = currentRoutine->stack[currentRoutine->top-2];
  1308. if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) {
  1309. currentRoutine->panic = -1;
  1310. return;
  1311. }
  1312. ink_pop(ctx);
  1313. currentRoutine->stack[currentRoutine->top-1].value = b.value >= a.value;
  1314. }
  1315. static void lte_int(struct context* ctx) {
  1316. struct ink_routine* currentRoutine;
  1317. struct elem a;
  1318. struct elem b;
  1319. currentRoutine = ctx->routines + ctx->routine_current;
  1320. if(currentRoutine->top < 2) {
  1321. currentRoutine->panic = -1;
  1322. return;
  1323. }
  1324. a = currentRoutine->stack[currentRoutine->top-1];
  1325. b = currentRoutine->stack[currentRoutine->top-2];
  1326. if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) {
  1327. currentRoutine->panic = -1;
  1328. return;
  1329. }
  1330. ink_pop(ctx);
  1331. currentRoutine->stack[currentRoutine->top-1].value = b.value <= a.value;
  1332. }
  1333. #endif /* NOEXTRAARITHMETIC */
  1334. static void lt_int(struct context* ctx) {
  1335. struct ink_routine* currentRoutine;
  1336. struct elem a;
  1337. struct elem b;
  1338. currentRoutine = ctx->routines + ctx->routine_current;
  1339. if(currentRoutine->top < 2) {
  1340. currentRoutine->panic = -1;
  1341. return;
  1342. }
  1343. a = currentRoutine->stack[currentRoutine->top-1];
  1344. b = currentRoutine->stack[currentRoutine->top-2];
  1345. if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) {
  1346. currentRoutine->panic = -1;
  1347. return;
  1348. }
  1349. ink_pop(ctx);
  1350. currentRoutine->stack[currentRoutine->top-1].value = b.value < a.value;
  1351. }
  1352. static void dupe_elem(struct context* ctx) {
  1353. struct ink_routine* currentRoutine;
  1354. struct elem a;
  1355. int err;
  1356. currentRoutine = ctx->routines + ctx->routine_current;
  1357. if(currentRoutine->top < 1) {
  1358. ctx->panic = 1;
  1359. return;
  1360. }
  1361. a = currentRoutine->stack[currentRoutine->top-1];
  1362. err = ink_push(ctx, a);
  1363. if(err < 0) ctx->panic = 1;
  1364. }
  1365. static void drop_elem(struct context* ctx) {
  1366. struct ink_routine* currentRoutine;
  1367. currentRoutine = ctx->routines + ctx->routine_current;
  1368. if(currentRoutine->top < 1) {
  1369. ctx->panic = 1;
  1370. return;
  1371. }
  1372. ink_pop(ctx);
  1373. }
  1374. static void pluck_elem(struct context* ctx) {
  1375. struct ink_routine* currentRoutine;
  1376. struct elem a;
  1377. int position, err;
  1378. currentRoutine = ctx->routines + ctx->routine_current;
  1379. if(currentRoutine->top < 1) {
  1380. currentRoutine->panic = -1;
  1381. return;
  1382. }
  1383. a = currentRoutine->stack[currentRoutine->top-1];
  1384. if(a.type != INK_INTEGER) {
  1385. ctx->panic = 1;
  1386. return;
  1387. }
  1388. position = currentRoutine->top - (a.value + 1);
  1389. if(position >= currentRoutine->top || position < 0) {
  1390. ctx->panic = 1;
  1391. return;
  1392. }
  1393. ink_pop(ctx);
  1394. err = ink_push(ctx, currentRoutine->stack[position]);
  1395. if(err < 0) ctx->panic = 1;
  1396. }
  1397. static void swap_elem(struct context* ctx) {
  1398. struct ink_routine* currentRoutine;
  1399. struct elem a;
  1400. struct elem b;
  1401. currentRoutine = ctx->routines + ctx->routine_current;
  1402. if(currentRoutine->top < 2) {
  1403. currentRoutine->panic = -1;
  1404. return;
  1405. }
  1406. a = currentRoutine->stack[currentRoutine->top-1];
  1407. b = currentRoutine->stack[currentRoutine->top-2];
  1408. currentRoutine->stack[currentRoutine->top-2] = a;
  1409. currentRoutine->stack[currentRoutine->top-1] = b;
  1410. }
  1411. static void return_if(struct context* ctx) {
  1412. struct ink_routine* currentRoutine;
  1413. struct elem a;
  1414. currentRoutine = ctx->routines + ctx->routine_current;
  1415. if(currentRoutine->top < 1) {
  1416. ctx->panic = -1;
  1417. return;
  1418. }
  1419. a = currentRoutine->stack[currentRoutine->top-1];
  1420. if(a.type != INK_INTEGER) {
  1421. ctx->panic = 1;
  1422. return;
  1423. }
  1424. if(a.value) {
  1425. ink_pop_fn(ctx);
  1426. ink_pop_fn(ctx);
  1427. }
  1428. ink_pop(ctx);
  1429. return;
  1430. }
  1431. static void jump_if(struct context* ctx) {
  1432. struct ink_routine* currentRoutine;
  1433. struct elem label;
  1434. struct elem condition;
  1435. currentRoutine = ctx->routines + ctx->routine_current;
  1436. if(currentRoutine->top < 2) {
  1437. ctx->panic = -1;
  1438. return;
  1439. }
  1440. label = currentRoutine->stack[currentRoutine->top-1];
  1441. condition = currentRoutine->stack[currentRoutine->top-2];
  1442. if(label.type != INK_INTEGER || condition.type != INK_INTEGER) {
  1443. ctx->panic = -1;
  1444. return;
  1445. }
  1446. ink_pop(ctx);
  1447. ink_pop(ctx);
  1448. ink_pop_fn(ctx);
  1449. if(condition.value) {
  1450. currentRoutine->function_stack[currentRoutine->function_stack_top - 1].index += label.value - 2;
  1451. }
  1452. return;
  1453. }
  1454. static void print_int(struct context* ctx) {
  1455. struct ink_routine* currentRoutine;
  1456. struct elem a;
  1457. char* n;
  1458. char* str;
  1459. currentRoutine = ctx->routines + ctx->routine_current;
  1460. if(currentRoutine->top < 1 || currentRoutine->stack[currentRoutine->top-1].type != INK_INTEGER) {
  1461. currentRoutine->panic = -1;
  1462. return;
  1463. }
  1464. a = currentRoutine->stack[currentRoutine->top-1];
  1465. ink_pop(ctx);
  1466. n = ink_itoa(ctx, a.value);
  1467. str = n;
  1468. while (*str) {
  1469. ctx->putchar(*str);
  1470. ++str;
  1471. }
  1472. ctx->free(n);
  1473. }
  1474. static void print_as_utf8(struct context* ctx) {
  1475. struct ink_routine* currentRoutine;
  1476. struct elem a;
  1477. currentRoutine = ctx->routines + ctx->routine_current;
  1478. if(currentRoutine->top < 1 || currentRoutine->stack[currentRoutine->top-1].type != INK_INTEGER) {
  1479. ctx->panic = -1;
  1480. return;
  1481. }
  1482. a = currentRoutine->stack[currentRoutine->top-1];
  1483. if(a.value <= 0x7F) {
  1484. ctx->putchar(a.value);
  1485. } else if(a.value <= 0x7FF) {
  1486. ctx->putchar(((a.value & 0xFC0) >> 6) | 192);
  1487. ctx->putchar((a.value & 0x3F) | 128);
  1488. } else if(a.value <= 0xFFFF) {
  1489. ctx->putchar(((a.value & 0x3F000) >> 12) | 224);
  1490. ctx->putchar(((a.value & 0xFC0) >> 6) | 128);
  1491. ctx->putchar((a.value & 0x3F) | 128);
  1492. } else if(a.value <= 0x10FFFF) {
  1493. ctx->putchar(((a.value & 0x3C0000) >> 18) | 240);
  1494. ctx->putchar(((a.value & 0x3F000) >> 12) | 128);
  1495. ctx->putchar(((a.value & 0xFC0) >> 6) | 128);
  1496. ctx->putchar((a.value & 0x3F) | 128);
  1497. } else {
  1498. ctx->panic = -1;
  1499. return;
  1500. }
  1501. ink_pop(ctx);
  1502. }
  1503. int get_type_by_name(struct context* ctx, const char* name) {
  1504. int i;
  1505. for(i = 0; i < ctx->types_top; ++i) {
  1506. if(strcmp(ctx->types[i].name, name) == 0) {
  1507. return i + 16;
  1508. }
  1509. }
  1510. return -1;
  1511. }
  1512. static void run_gc(struct context* ctx) {
  1513. ink_gc(ctx);
  1514. }
  1515. static void clear_stack(struct context* ctx) {
  1516. struct ink_routine* currentRoutine;
  1517. currentRoutine = ctx->routines + ctx->routine_current;
  1518. while (currentRoutine->top >= 1) {
  1519. ink_pop(ctx);
  1520. }
  1521. return;
  1522. }
  1523. static void dump_stack(struct context* ctx) {
  1524. struct ink_routine* currentRoutine;
  1525. int index;
  1526. char* idx;
  1527. char* type;
  1528. char* value;
  1529. char* it;
  1530. currentRoutine = ctx->routines + ctx->routine_current;
  1531. index = currentRoutine->top;
  1532. while (index) {
  1533. --index;
  1534. idx = ink_itoa(ctx,index);
  1535. type = ink_itoa(ctx, currentRoutine->stack[index].type);
  1536. value = ink_itoa(ctx,currentRoutine->stack[index].value);
  1537. for(it = idx; *it; ++it) ctx->putchar(*it);
  1538. ctx->putchar(' ');ctx->putchar('|');ctx->putchar(' ');
  1539. for(it = type; *it; ++it) ctx->putchar(*it);
  1540. ctx->putchar(' ');ctx->putchar('|');ctx->putchar(' ');
  1541. for(it = value; *it; ++it) ctx->putchar(*it);
  1542. ctx->putchar('\n');
  1543. ctx->free(value);
  1544. ctx->free(type);
  1545. ctx->free(idx);
  1546. }
  1547. return;
  1548. }
  1549. static void collect_noop() {}
  1550. static struct ink_collection_list gc_noop() {
  1551. struct ink_collection_list c;
  1552. c.elements = NULL;
  1553. c.count = 0;
  1554. return c;
  1555. }
  1556. #ifndef NOARRAYLIB
  1557. static void collect_array(struct context* ctx, void* array) {
  1558. struct ink_array* ary;
  1559. ary = array;
  1560. if(ary->elements != NULL) ctx->free(ary->elements);
  1561. }
  1562. static struct ink_collection_list gc_array(struct context* ctx, void* array) {
  1563. struct ink_array* ary;
  1564. struct ink_collection_list c;
  1565. ary = array;
  1566. c.elements = ctx->inner_malloc(sizeof(struct elem)*ary->top);
  1567. c.count = ary->top;
  1568. memcpy(c.elements, ary->elements, sizeof(struct elem)*ary->top);
  1569. return c;
  1570. }
  1571. static void new_array(struct context* ctx) {
  1572. int tid;
  1573. struct elem e;
  1574. struct ink_array ary;
  1575. tid = get_type_by_name(ctx, "array");
  1576. ary.elements = NULL;
  1577. ary.top = 0;
  1578. ary.capacity = 0;
  1579. e = ink_make_native(ctx, tid, &ary);
  1580. ink_push(ctx, e);
  1581. }
  1582. #ifndef NOSTRINGLITERALS
  1583. static void new_protected_array(struct context* ctx) {
  1584. int tid;
  1585. struct elem e;
  1586. struct ink_array ary;
  1587. tid = get_type_by_name(ctx, "array");
  1588. ary.elements = NULL;
  1589. ary.top = 0;
  1590. ary.capacity = 0;
  1591. e = ink_make_native_unsafe(ctx, tid, &ary, 1);
  1592. ink_push(ctx, e);
  1593. }
  1594. #endif
  1595. static void push_array_stack_delim(struct context* ctx) {
  1596. int tid;
  1597. struct elem e;
  1598. tid = get_type_by_name(ctx, "array_marker");
  1599. e.type = tid;
  1600. e.value = 0;
  1601. ink_push(ctx, e);
  1602. }
  1603. void array_push(struct context* ctx, struct ink_routine* currentRoutine, struct ink_array* ary, struct elem value) {
  1604. if(ary->elements == NULL) {
  1605. ary->elements = ctx->malloc(sizeof(struct elem) * 8);
  1606. ary->top = 0;
  1607. ary->capacity = 8;
  1608. } else if(ary->top == ary->capacity) {
  1609. int new_count;
  1610. void* renewed;
  1611. new_count = (ary->capacity + ary->capacity/2);
  1612. renewed = ctx->realloc(ary->elements, sizeof(struct elem) * new_count);
  1613. if(renewed == NULL) {
  1614. currentRoutine->panic = -1;
  1615. return;
  1616. } else {
  1617. ary->elements = renewed;
  1618. ary->capacity = new_count;
  1619. }
  1620. }
  1621. ary->elements[ary->top] = value;
  1622. ary->top++;
  1623. }
  1624. static void push_array(struct context* ctx) {
  1625. int tid;
  1626. struct elem a;
  1627. struct ink_routine* currentRoutine;
  1628. struct ink_array* ary;
  1629. tid = get_type_by_name(ctx, "array");
  1630. currentRoutine = ctx->routines + ctx->routine_current;
  1631. if(currentRoutine->top < 2 || currentRoutine->stack[currentRoutine->top-1].type != tid) {
  1632. currentRoutine->panic = -1;
  1633. return;
  1634. }
  1635. a = currentRoutine->stack[currentRoutine->top-1];
  1636. ary= ink_get_value(ctx, a);
  1637. if(ary == NULL) {
  1638. currentRoutine->panic = -1;
  1639. return;
  1640. }
  1641. ink_pop(ctx);
  1642. array_push(ctx, currentRoutine, ary, currentRoutine->stack[currentRoutine->top-1]);
  1643. ink_pop(ctx);
  1644. }
  1645. static void push_delimited_array(struct context* ctx) {
  1646. int tid, idx, counter, i;
  1647. struct elem a;
  1648. struct ink_routine* currentRoutine;
  1649. struct ink_array* ary;
  1650. tid = get_type_by_name(ctx, "array_marker");
  1651. currentRoutine = ctx->routines + ctx->routine_current;
  1652. if(currentRoutine->top < 1) {
  1653. currentRoutine->panic = -1;
  1654. return;
  1655. }
  1656. new_array(ctx);
  1657. a = currentRoutine->stack[currentRoutine->top-1];
  1658. ink_pop(ctx);
  1659. ary= ink_get_value(ctx, a);
  1660. for(idx = 1; idx <= currentRoutine->top; ++idx) {
  1661. if(currentRoutine->stack[currentRoutine->top-idx].type == tid) {
  1662. break;
  1663. }
  1664. }
  1665. /* Save for cleanup */
  1666. counter = idx;
  1667. /* Don't copy the delimiter */
  1668. idx -= 1;
  1669. ary->elements = malloc(sizeof(struct elem) * idx);
  1670. if(ary->elements == NULL) {
  1671. currentRoutine->panic = -541;
  1672. return;
  1673. }
  1674. ary->capacity = idx;
  1675. ary->top = 0;
  1676. /* Copy the data */
  1677. for(i = currentRoutine->top - idx; i < currentRoutine->top; ++i) {
  1678. ary->elements[ary->top] = currentRoutine->stack[i];
  1679. ++(ary->top);
  1680. }
  1681. /* Cleanup */
  1682. while(counter--) {
  1683. ink_pop(ctx);
  1684. }
  1685. /* Put value in place */
  1686. ink_push(ctx, a);
  1687. }
  1688. static void index_array(struct context* ctx) {
  1689. int tid;
  1690. struct ink_routine *currentRoutine;
  1691. struct elem a;
  1692. struct ink_array *ary;
  1693. struct elem idx;
  1694. tid = get_type_by_name(ctx, "array");
  1695. currentRoutine = ctx->routines + ctx->routine_current;
  1696. if (currentRoutine->top < 2 || currentRoutine->stack[currentRoutine->top - 1].type != tid || currentRoutine->stack[currentRoutine->top - 2].type != INK_INTEGER) {
  1697. currentRoutine->panic = -1;
  1698. return;
  1699. }
  1700. a = currentRoutine->stack[currentRoutine->top - 1];
  1701. ary = ink_get_value(ctx, a);
  1702. if (ary == NULL) {
  1703. currentRoutine->panic = -1;
  1704. return;
  1705. }
  1706. ink_pop(ctx);
  1707. idx = currentRoutine->stack[currentRoutine->top - 1];
  1708. ink_pop(ctx);
  1709. if(ary->top <= idx.value) {
  1710. currentRoutine->panic = -1;
  1711. return;
  1712. }
  1713. ink_push(ctx, ary->elements[idx.value]);
  1714. }
  1715. static void set_array(struct context* ctx) {
  1716. int tid;
  1717. struct ink_routine *currentRoutine;
  1718. struct elem a;
  1719. struct ink_array *ary;
  1720. struct elem idx;
  1721. struct elem value;
  1722. tid = get_type_by_name(ctx, "array");
  1723. currentRoutine = ctx->routines + ctx->routine_current;
  1724. if (currentRoutine->top < 3 || currentRoutine->stack[currentRoutine->top - 1].type != tid || currentRoutine->stack[currentRoutine->top - 2].type != INK_INTEGER) {
  1725. currentRoutine->panic = -1;
  1726. return;
  1727. }
  1728. a = currentRoutine->stack[currentRoutine->top - 1];
  1729. ary = ink_get_value(ctx, a);
  1730. if (ary == NULL) {
  1731. currentRoutine->panic = -1;
  1732. return;
  1733. }
  1734. idx = currentRoutine->stack[currentRoutine->top - 2];
  1735. value = currentRoutine->stack[currentRoutine->top - 3];
  1736. if(ary->top <= idx.value) {
  1737. currentRoutine->panic = -1;
  1738. return;
  1739. }
  1740. ink_pop(ctx);
  1741. ink_pop(ctx);
  1742. ink_pop(ctx);
  1743. ary->elements[idx.value] = value;
  1744. }
  1745. static void get_size_array(struct context* ctx) {
  1746. int tid;
  1747. struct ink_routine *currentRoutine;
  1748. struct elem a;
  1749. struct ink_array *ary;
  1750. struct elem sz;
  1751. tid = get_type_by_name(ctx, "array");
  1752. currentRoutine = ctx->routines + ctx->routine_current;
  1753. if (currentRoutine->top < 1 || currentRoutine->stack[currentRoutine->top - 1].type != tid) {
  1754. currentRoutine->panic = -1;
  1755. return;
  1756. }
  1757. a = currentRoutine->stack[currentRoutine->top - 1];
  1758. ary = ink_get_value(ctx, a);
  1759. if (ary == NULL) {
  1760. currentRoutine->panic = -1;
  1761. return;
  1762. }
  1763. ink_pop(ctx);
  1764. sz.type = INK_INTEGER;
  1765. sz.value = ary->top;
  1766. ink_push(ctx, sz);
  1767. }
  1768. static void is_array(struct context* ctx) {
  1769. int tid;
  1770. struct ink_routine *currentRoutine;
  1771. struct elem a;
  1772. tid = get_type_by_name(ctx, "array");
  1773. currentRoutine = ctx->routines + ctx->routine_current;
  1774. if (currentRoutine->top < 1) {
  1775. currentRoutine->panic = -1;
  1776. return;
  1777. }
  1778. a.type = INK_INTEGER;
  1779. a.value = currentRoutine->stack[currentRoutine->top - 1].type == tid;
  1780. ink_pop(ctx);
  1781. ink_push(ctx, a);
  1782. }
  1783. static void is_int(struct context* ctx) {
  1784. struct ink_routine *currentRoutine;
  1785. struct elem a;
  1786. currentRoutine = ctx->routines + ctx->routine_current;
  1787. if (currentRoutine->top < 1) {
  1788. currentRoutine->panic = -1;
  1789. return;
  1790. }
  1791. a.type = INK_INTEGER;
  1792. a.value = currentRoutine->stack[currentRoutine->top - 1].type == INK_INTEGER;
  1793. ink_pop(ctx);
  1794. ink_push(ctx, a);
  1795. }
  1796. static void print_array_of_codepoints(struct context* ctx) {
  1797. int tid, i;
  1798. struct ink_routine *currentRoutine;
  1799. struct elem a;
  1800. struct ink_array *ary;
  1801. tid = get_type_by_name(ctx, "array");
  1802. currentRoutine = ctx->routines + ctx->routine_current;
  1803. if (currentRoutine->top < 1 || currentRoutine->stack[currentRoutine->top - 1].type != tid) {
  1804. currentRoutine->panic = -1;
  1805. return;
  1806. }
  1807. a = currentRoutine->stack[currentRoutine->top - 1];
  1808. ary = ink_get_value(ctx, a);
  1809. for(i = 0; i < ary->top; ++i) {
  1810. if(ary->elements[i].type != INK_INTEGER) {
  1811. currentRoutine->panic = -1;
  1812. return;
  1813. }
  1814. }
  1815. ink_pop(ctx);
  1816. for(i = 0; i < ary->top; ++i) {
  1817. ink_push(ctx, ary->elements[i]);
  1818. print_as_utf8(ctx);
  1819. }
  1820. }
  1821. static void arrayify_stack(struct context* ctx) {
  1822. struct ink_routine* currentRoutine;
  1823. struct elem array_ref;
  1824. struct ink_array* ary;
  1825. int idx;
  1826. currentRoutine = ctx->routines + ctx->routine_current;
  1827. new_array(ctx);
  1828. if(currentRoutine->panic < 0) return;
  1829. array_ref = currentRoutine->stack[currentRoutine->top - 1];
  1830. ary = ink_get_value(ctx, array_ref);
  1831. if(ary == NULL) {
  1832. currentRoutine->panic = -717;
  1833. return;
  1834. }
  1835. ink_pop(ctx);
  1836. for(idx = 0; idx < currentRoutine->top; ++idx) {
  1837. array_push(ctx, currentRoutine, ary, currentRoutine->stack[idx]);
  1838. }
  1839. while (currentRoutine->top > 0) {
  1840. ink_pop(ctx);
  1841. }
  1842. ink_push(ctx, array_ref);
  1843. return;
  1844. }
  1845. #endif /* NOARRAYLIB */
  1846. int ink_std_library(struct context* ctx) {
  1847. int v;
  1848. v = 0;
  1849. v += ink_add_native(ctx, "sys.trace", print_stacktrace);
  1850. v += ink_add_native(ctx, "sys.gc", run_gc);
  1851. v += ink_add_native(ctx, "print_int", print_int);
  1852. v += ink_add_native(ctx, "print_utf8", print_as_utf8);
  1853. v += ink_add_native(ctx, "+", add_int);
  1854. v += ink_add_native(ctx, "-", sub_int);
  1855. v += ink_add_native(ctx, "*", mult_int);
  1856. v += ink_add_native(ctx, "/", div_int);
  1857. v += ink_add_native(ctx, "==", is_equal);
  1858. v += ink_add_native(ctx, "!=", is_different);
  1859. v += ink_add_native(ctx, "<", lt_int);
  1860. v += ink_add_native(ctx, "swap", swap_elem);
  1861. v += ink_add_native(ctx, "dup", dupe_elem);
  1862. v += ink_add_native(ctx, "drop", drop_elem);
  1863. v += ink_add_native(ctx, "stack.clear", clear_stack);
  1864. v += ink_add_native(ctx, "stack.dump", dump_stack);
  1865. v += ink_add_native(ctx, "pluck", pluck_elem);
  1866. v += ink_add_native(ctx, "return_if", return_if);
  1867. v += ink_add_native(ctx, "jump_if", jump_if);
  1868. v += ink_add_native(ctx, "is.int", is_int);
  1869. #ifndef NOEXTRAARITHMETIC
  1870. v += ink_add_native(ctx, ">", gt_int);
  1871. v += ink_add_native(ctx, ">=", gte_int);
  1872. v += ink_add_native(ctx, "=<", lte_int);
  1873. v += ink_add_native(ctx, "%", rem_int);
  1874. v += ink_add_native(ctx, "int.xor", xor_int);
  1875. #endif /* NOEXTRAARITHMETIC */
  1876. #ifndef NOARRAYLIB
  1877. ink_new_type(ctx, "array", sizeof(struct ink_array), collect_array, gc_array);
  1878. ink_new_type(ctx, "array_marker", 0, collect_noop, gc_noop);
  1879. v += ink_add_native(ctx, "[", push_array_stack_delim);
  1880. v += ink_add_native(ctx, "]", push_delimited_array);
  1881. v += ink_add_native(ctx, "array.new", new_array);
  1882. v += ink_add_native(ctx, "array.push", push_array);
  1883. v += ink_add_native(ctx, "array.index", index_array);
  1884. v += ink_add_native(ctx, "array.set", set_array);
  1885. v += ink_add_native(ctx, "array.size", get_size_array);
  1886. v += ink_add_native(ctx, "array.print_utf8", print_array_of_codepoints);
  1887. v += ink_add_native(ctx, "is.array", is_array);
  1888. v += ink_add_native(ctx, "stack.to_array", arrayify_stack);
  1889. #endif /* NOARRAYLIB */
  1890. return v;
  1891. }