A minimalistic programming language written in C89.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

1306 lignes
35 KiB

il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
il y a 4 mois
  1. #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 = 0;
  31. while(*(c++)) {
  32. j++;
  33. }
  34. return j;
  35. }
  36. static void* memcpy(void* _dest, const void* _src, size_t sz) {
  37. char* dest = _dest;
  38. const char* src = _src;
  39. while(sz--) {
  40. *(dest++) = *(src++);
  41. }
  42. return dest;
  43. }
  44. static int strcmp(const char* dest, const char* src) {
  45. while(*dest != 0 && *src != 0) {
  46. if(*(dest++) != *(src++)) {
  47. return 1;
  48. }
  49. }
  50. return 0;
  51. }
  52. static void* memmove(void* _dest, const void* _src, size_t sz) {
  53. char* dest = _dest;
  54. const char* src = _src;
  55. if (src < dest) {
  56. src += sz;
  57. dest += sz;
  58. while (sz-- > 0) {
  59. *--dest = *--src;
  60. }
  61. } else {
  62. while (sz-- > 0) {
  63. *dest++ = *src++;
  64. }
  65. }
  66. return dest;
  67. }
  68. static void* memset(void* _dest, int src, size_t sz) {
  69. char* dest = _dest;
  70. while(sz--) {
  71. *(dest++) = src++;
  72. }
  73. return dest;
  74. }
  75. static int isspace(int d) {
  76. return d == ' ' || d == '\t' || d == '\n';
  77. }
  78. static int isdigit(int d) {
  79. return '0' <= d && d <= '9';
  80. }
  81. static int atoi(const char* c) {
  82. int ret = 0;
  83. while(*c) {
  84. ret *= 10;
  85. ret += *c - '0';
  86. ++c;
  87. }
  88. return ret;
  89. }
  90. #endif
  91. int ink_add_native(struct context* ctx, const char* name, void(*value)(struct context*)) {
  92. if(ctx->native_words == NULL) {
  93. ctx->native_words = ctx->inner_malloc(sizeof(struct native_fn) * 8);
  94. ctx->native_words_top = 0;
  95. ctx->native_words_capacity = 8;
  96. } else if(ctx->native_words_top == ctx->native_words_capacity) {
  97. int new_count = (ctx->native_words_capacity + ctx->native_words_capacity/2);
  98. void* renewed = ctx->inner_realloc(ctx->native_words, sizeof(struct native_fn) * new_count);
  99. if(renewed == NULL) {
  100. return -3;
  101. } else {
  102. ctx->native_words = renewed;
  103. ctx->native_words_capacity = new_count;
  104. }
  105. }
  106. int len = strlen(name);
  107. char* copy = ctx->inner_malloc(len+1);
  108. if(copy == NULL) {
  109. return -4;
  110. }
  111. memcpy(copy, name, len);
  112. copy[len] = 0;
  113. ctx->native_words[ctx->native_words_top].value = value;
  114. ctx->native_words[ctx->native_words_top].name = copy;
  115. ctx->native_words_top++;
  116. return 0;
  117. }
  118. static int ink_add_indigenous(struct context* ctx, const char* name, struct elem* m, size_t count) {
  119. if(ctx->words == NULL) {
  120. ctx->words = ctx->malloc(sizeof(struct fn) * 8);
  121. ctx->words_top = 0;
  122. ctx->words_capacity = 8;
  123. } else if(ctx->words_top == ctx->words_capacity) {
  124. int new_count = (ctx->words_capacity + ctx->words_capacity/2);
  125. void* renewed = ctx->realloc(ctx->words, sizeof(struct native_fn) * new_count);
  126. if(renewed == NULL) {
  127. return -1;
  128. } else {
  129. ctx->words = renewed;
  130. ctx->words_capacity = new_count;
  131. }
  132. }
  133. int i;
  134. for(i = 0; i < ctx->words_top; ++i) {
  135. if(strcmp(name, ctx->words[i].name) == 0) {
  136. ctx->free(ctx->words[i].things);
  137. ctx->words[i].things = ctx->malloc(sizeof(struct elem) * count);
  138. memcpy(ctx->words[i].things, m, sizeof(struct elem) * count);
  139. ctx->words[i].size = count;
  140. return i;
  141. }
  142. }
  143. int len = strlen(name);
  144. char* copy = ctx->malloc(len+1);
  145. if(copy == NULL) {
  146. return -2;
  147. }
  148. memcpy(copy, name, len);
  149. copy[len] = 0;
  150. ctx->words[ctx->words_top].things = ctx->malloc(sizeof(struct elem) * count);
  151. memcpy(ctx->words[ctx->words_top].things, m, sizeof(struct elem) * count);
  152. ctx->words[ctx->words_top].size = count;
  153. ctx->words[ctx->words_top].name = copy;
  154. return ctx->words_top++;
  155. }
  156. static int ink_add_lex_string(struct context* ctx, const char* name) {
  157. int i;
  158. if(ctx->lex_reserved_words == NULL) {
  159. ctx->lex_reserved_words = ctx->inner_malloc(sizeof(char*) * 8);
  160. ctx->lex_reserved_words_top = 0;
  161. ctx->lex_reserved_words_capacity = 8;
  162. } else if(ctx->lex_reserved_words_top == ctx->lex_reserved_words_capacity) {
  163. int new_count = (ctx->lex_reserved_words_capacity + ctx->lex_reserved_words_capacity/2);
  164. void* renewed = ctx->inner_realloc(ctx->lex_reserved_words, sizeof(struct native_fn) * new_count);
  165. if(renewed == NULL) {
  166. return -5;
  167. } else {
  168. ctx->lex_reserved_words = renewed;
  169. ctx->lex_reserved_words_capacity = new_count;
  170. }
  171. }
  172. for(i = 0; i < ctx->lex_reserved_words_top; i++) {
  173. if(strcmp(ctx->lex_reserved_words[i], name) == 0) {
  174. return i;
  175. }
  176. }
  177. int len = strlen(name);
  178. i = ctx->lex_reserved_words_top;
  179. ctx->lex_reserved_words[i] = ctx->malloc(len+1);
  180. memcpy(ctx->lex_reserved_words[i], name, len);
  181. ctx->lex_reserved_words[i][len] = 0;
  182. ctx->lex_reserved_words_top++;
  183. return i;
  184. }
  185. int ink_push(struct context* ctx, struct elem value) {
  186. if(ctx->routine_current >= ctx->routines_top) return -65;
  187. struct ink_routine* current = ctx->routines + ctx->routine_current;
  188. if(current->stack == NULL) {
  189. current->stack = ctx->malloc(sizeof(struct elem) * 8);
  190. current->top = 0;
  191. current->capacity = 8;
  192. } else if(current->top == current->capacity) {
  193. int new_count = (current->capacity + current->capacity/2);
  194. void* renewed = ctx->realloc(current->stack, sizeof(struct elem) * new_count);
  195. if(renewed == NULL) {
  196. return -18;
  197. } else {
  198. current->stack = renewed;
  199. current->capacity = new_count;
  200. }
  201. }
  202. current->stack[current->top] = value;
  203. current->top++;
  204. return 0;
  205. }
  206. int ink_push_fn(struct context* ctx, struct stack_frame value) {
  207. if(ctx->routine_current >= ctx->routines_top) return -55;
  208. struct ink_routine* current = ctx->routines + ctx->routine_current;
  209. if(current->panic) return -56;
  210. if(current->function_stack == NULL) {
  211. current->function_stack = ctx->malloc(sizeof(struct stack_frame) * 8);
  212. current->function_stack_top = 0;
  213. current->function_stack_capacity = 8;
  214. } else if(current->function_stack_top == current->function_stack_capacity) {
  215. int new_count = (current->function_stack_capacity + current->function_stack_capacity/2);
  216. void* renewed = ctx->realloc(current->function_stack, sizeof(struct stack_frame) * new_count);
  217. if(renewed == NULL) {
  218. return -9;
  219. } else {
  220. current->function_stack = renewed;
  221. current->function_stack_capacity = new_count;
  222. }
  223. }
  224. current->function_stack[current->function_stack_top] = value;
  225. current->function_stack_top++;
  226. return 0;
  227. }
  228. void ink_pop_fn(struct context* ctx) {
  229. if(ctx->routine_current >= ctx->routines_top) return;
  230. if(ctx->routines[ctx->routine_current].panic) return;
  231. if(ctx->routines[ctx->routine_current].function_stack == NULL) return;
  232. if(ctx->routines[ctx->routine_current].function_stack_top == 0) return;
  233. ctx->routines[ctx->routine_current].function_stack_top--;
  234. }
  235. void ink_pop(struct context* ctx) {
  236. if(ctx->routine_current >= ctx->routines_top) return;
  237. if(ctx->routines[ctx->routine_current].panic) return;
  238. if(ctx->routines[ctx->routine_current].stack == NULL) return;
  239. if(ctx->routines[ctx->routine_current].top == 0) return;
  240. ctx->routines[ctx->routine_current].top--;
  241. }
  242. struct context* ink_make_context(void*(*malloc)(size_t), void*(*realloc)(void*, size_t), void(*free)(void*), int(*putchar)(int)) {
  243. struct context* ctx = (struct context*)malloc(sizeof(struct context));
  244. ctx->malloc = malloc;
  245. ctx->realloc = realloc;
  246. ctx->free = free;
  247. ctx->inner_malloc = malloc;
  248. ctx->inner_realloc = realloc;
  249. ctx->inner_free = free;
  250. ctx->putchar = putchar;
  251. ctx->panic = 0;
  252. ctx->routines = NULL;
  253. ctx->routines_capacity = 0;
  254. ctx->routines_top = 0;
  255. ctx->types = NULL;
  256. ctx->types_capacity = 0;
  257. ctx->types_top = 0;
  258. ctx->native_words = NULL;
  259. ctx->native_words_capacity = 0;
  260. ctx->native_words_top = 0;
  261. ctx->words = NULL;
  262. ctx->words_capacity = 0;
  263. ctx->words_top = 0;
  264. ctx->lex_reserved_words = NULL;
  265. ctx->lex_reserved_words_capacity = 0;
  266. ctx->lex_reserved_words_top = 0;
  267. ctx->collections = 0;
  268. ctx->steps = 0;
  269. return ctx;
  270. }
  271. /**
  272. * Allocates a string that contains the integer
  273. * @param _ context (used to allocate)
  274. * @param cpy the value
  275. * @return the allocated string, needs to be freed by ctx->free
  276. * @internal this function is slightly cursed
  277. */
  278. static char* ink_itoa(struct context* _, int cpy) {
  279. char* n = _->malloc(16);
  280. n[15] = 0;
  281. char* it = n+15;
  282. do {
  283. it--;
  284. *it = (cpy % 10) + '0';
  285. cpy = cpy / 10;
  286. } while(cpy);
  287. memmove(n, it, 16 - (it-n));
  288. return n;
  289. }
  290. #ifndef NOSTDLIB
  291. struct context* ink_make_default_context() {
  292. struct context* ctx = ink_make_context(malloc, realloc, free, putchar);
  293. ink_std_library(ctx);
  294. return ctx;
  295. }
  296. #endif
  297. static int ink_consume_one(int* end, struct context* pContext, char** buffer, char* r) {
  298. int i;
  299. if(*end == 0) {
  300. return 0;
  301. }
  302. r[*end] = 0;
  303. int done = 0;
  304. struct elem value;
  305. if (strcmp(r, _KEYWORD_INK_FUNCTION) == 0) {
  306. value.value = 0;
  307. value.type = INK_FUNCTION_KW;
  308. done = 1;
  309. }
  310. if (!done && strcmp(r, _KEYWORD_INK_DO) == 0) {
  311. value.value = 0;
  312. value.type = INK_DO_KW;
  313. done = 1;
  314. }
  315. if (!done && strcmp(r, _KEYWORD_INK_END) == 0) {
  316. value.value = 0;
  317. value.type = INK_END_KW;
  318. done = 1;
  319. }
  320. if (!done && strcmp(r, _KEYWORD_INK_RETURN) == 0) {
  321. value.value = 0;
  322. value.type = INK_RETURN;
  323. done = 1;
  324. }
  325. if(done) {
  326. int err;
  327. err = ink_push(pContext, value);
  328. if(err < 0) {
  329. return -19;
  330. }
  331. }
  332. if (!done) {
  333. for (i = 0; i < pContext->words_top; ++i) {
  334. if (strcmp(r, pContext->words[i].name) == 0) {
  335. value.value = i;
  336. value.type = INK_FUNCTION;
  337. int err;
  338. err = ink_push(pContext, value);
  339. if(err < 0) {
  340. return -20;
  341. }
  342. done = 1;
  343. break;
  344. }
  345. }
  346. }
  347. if (!done) {
  348. for (i = 0; i < pContext->native_words_top; ++i) {
  349. if (strcmp(r, pContext->native_words[i].name) == 0) {
  350. value.value = i;
  351. value.type = INK_NATIVE_FUNCTION;
  352. int err;
  353. err = ink_push(pContext, value);
  354. if(err < 0) {
  355. return -21;
  356. }
  357. done = 1;
  358. break;
  359. }
  360. }
  361. }
  362. if (!done) {
  363. for(i = (r[0] == '-'); i < *end; i++) {
  364. if(!isdigit(r[i])){
  365. goto not_an_int;
  366. }
  367. }
  368. value.value = atoi(r);
  369. value.type = INK_INTEGER;
  370. int err;
  371. err = ink_push(pContext, value);
  372. if(err < 0) {
  373. return -22;
  374. }
  375. done = 1;
  376. }
  377. not_an_int:
  378. if (!done) {
  379. i = ink_add_lex_string(pContext, r);
  380. if(i < 0) {
  381. pContext->panic = 1;
  382. return -7;
  383. }
  384. value.value = i;
  385. if(r[strlen(r) - 1] == ':') {
  386. value.type = INK_LABEL;
  387. } else {
  388. value.type = INK_RESERVED;
  389. }
  390. int err;
  391. err = ink_push(pContext, value);
  392. if(err < 0) {
  393. return -23;
  394. }
  395. }
  396. *end = 0;
  397. return 0;
  398. }
  399. static int ink_lex(struct context *pContext, char* buffer) {
  400. int i;
  401. char r[128];
  402. int end = 0;
  403. int err;
  404. while(*buffer != 0) {
  405. if(isspace(*buffer)) {
  406. err = ink_consume_one(&end, pContext, &buffer, r);
  407. if(err < 0) {
  408. pContext->panic = 1;
  409. return -8;
  410. }
  411. } else {
  412. r[end] = *buffer;
  413. ++end;
  414. }
  415. ++buffer;
  416. }
  417. err = ink_consume_one(&end, pContext, &buffer, r);
  418. if(err < 0) {
  419. pContext->panic = 1;
  420. return -9;
  421. }
  422. return 0;
  423. }
  424. static int lblcmp(const char* label, const char* other, size_t label_sz) {
  425. while (label_sz != 1) {
  426. if(*other == 0) return 1;
  427. if(*label != *other) return 1;
  428. ++label;
  429. ++other;
  430. label_sz--;
  431. }
  432. return 0;
  433. }
  434. int ink_make_routine(struct context* ctx) {
  435. if(ctx->routines == NULL) {
  436. ctx->routines = ctx->inner_malloc(sizeof(struct ink_routine) * 8);
  437. ctx->routines_top = 0;
  438. ctx->routines_capacity = 8;
  439. struct ink_routine* it = ctx->routines;
  440. struct ink_routine* end = ctx->routines + 8;
  441. for(;it != end;++it) {
  442. it->stack = NULL;
  443. it->function_stack = NULL;
  444. it->panic = INK_ROUTINE_CAN_REUSE;
  445. }
  446. } else if(ctx->routines_top == ctx->routines_capacity) {
  447. int new_count = (ctx->routines_capacity + ctx->routines_capacity/2);
  448. void* renewed = ctx->inner_realloc(ctx->routines, sizeof(struct stack_frame) * new_count);
  449. if(renewed == NULL) {
  450. return -99;
  451. } else {
  452. ctx->routines = renewed;
  453. struct ink_routine* it = ctx->routines + ctx->routines_capacity;
  454. struct ink_routine* end = ctx->routines + new_count;
  455. for(;it != end;++it) {
  456. it->panic = INK_ROUTINE_CAN_REUSE;
  457. }
  458. ctx->routines_capacity = new_count;
  459. }
  460. }
  461. struct ink_routine* it = ctx->routines;
  462. struct ink_routine* end = ctx->routines + ctx->routines_capacity;
  463. for(;it != end;++it) {
  464. if(it->panic == INK_ROUTINE_CAN_REUSE) {
  465. it->panic = 0;
  466. it->stack = NULL;
  467. it->top = 0;
  468. it->capacity = 0;
  469. it->function_stack = NULL;
  470. it->function_stack_top = 0;
  471. it->function_stack_capacity = 0;
  472. int idx = it - ctx->routines;
  473. if(idx >= ctx->routines_top) {
  474. ctx->routines_top = idx + 1;
  475. }
  476. return idx;
  477. }
  478. }
  479. }
  480. int ink_kill_routine(struct context* ctx, int routine){
  481. if(routine < 0 || routine >= ctx->routines_top) {
  482. return 0;
  483. }
  484. struct ink_routine* curr = ctx->routines + routine;
  485. if(curr->panic == INK_ROUTINE_CAN_REUSE) {
  486. return 0;
  487. }
  488. if(curr->stack != NULL) {
  489. ctx->free(curr->stack);
  490. curr->stack = NULL;
  491. }
  492. if(curr->function_stack != NULL) {
  493. ctx->free(curr->function_stack);
  494. curr->function_stack = NULL;
  495. }
  496. curr->panic = INK_ROUTINE_CAN_REUSE;
  497. return 1;
  498. }
  499. /**
  500. *
  501. * @param pContext
  502. * @param executable_buffer
  503. * @param executable_buffer_top
  504. * @internal Loop from hell
  505. */
  506. static int ink_parse(struct context* pContext, struct elem* executable_buffer, int* executable_buffer_top) {
  507. struct ink_routine* currentRoutine = pContext->routines + pContext->routine_current;
  508. int i;
  509. #define LABEL_BUFFER 128
  510. #define FUNCTION_BUFFER 256
  511. struct label labels[LABEL_BUFFER];
  512. struct elem function_buffer[FUNCTION_BUFFER];
  513. int function_buffer_top = 0;
  514. int function_name = -1;
  515. #define MODE_EXECUTABLE 0
  516. #define MODE_FUNCTION 1
  517. #define MODE_DO 2
  518. int mode = 0;
  519. memset(labels, 0, sizeof(struct label)*LABEL_BUFFER);
  520. for(i = 0; i < currentRoutine->top; ++i) {
  521. struct elem current;
  522. current = currentRoutine->stack[i];
  523. switch (mode) {
  524. case MODE_EXECUTABLE:
  525. switch(current.type) {
  526. case INK_FUNCTION_KW:
  527. mode = MODE_FUNCTION;
  528. function_name = -1;
  529. goto next_token;
  530. case INK_DO_KW:
  531. case INK_END_KW:
  532. return -26;
  533. default:
  534. executable_buffer[*executable_buffer_top] = current;
  535. *executable_buffer_top += 1;
  536. }
  537. break;
  538. case MODE_FUNCTION:
  539. if(current.type == INK_DO_KW) {
  540. if(function_name == -1) {
  541. return -27;
  542. } else {
  543. mode = MODE_DO;
  544. memset(labels, 0, sizeof(struct label)*128);
  545. goto next_token;
  546. }
  547. }
  548. if(function_name != -1) {
  549. return -28;
  550. }
  551. if(current.type != INK_RESERVED) {
  552. return -29;
  553. }
  554. function_name = current.value;
  555. break;
  556. case MODE_DO:
  557. if(current.type == INK_END_KW) {
  558. int j;
  559. for(j = 0; j < function_buffer_top; j++) {
  560. struct elem pt;
  561. pt = function_buffer[j];
  562. if(pt.type == INK_LABEL) {
  563. int k;
  564. for(k = 0; k < LABEL_BUFFER; k++) {
  565. if(labels[k].active) {
  566. if(strcmp(labels[k].name, pContext->lex_reserved_words[pt.value]) == 0) {
  567. labels[k].dest = j;
  568. return -30;
  569. break;
  570. }
  571. } else {
  572. labels[k].active = 1;
  573. labels[k].name = pContext->lex_reserved_words[pt.value];
  574. labels[k].dest = j;
  575. memcpy(function_buffer+j, function_buffer+j+1, sizeof(struct elem)*(function_buffer_top-j-1));
  576. function_buffer_top--;
  577. j--;
  578. break;
  579. }
  580. }
  581. }
  582. }
  583. for(j = 0; j < function_buffer_top; j++) {
  584. struct elem pt;
  585. pt = function_buffer[j];
  586. if(pt.type == INK_RESERVED) {
  587. const char* str = pContext->lex_reserved_words[pt.value];
  588. int k;
  589. for(k = 0; k < LABEL_BUFFER; k++) {
  590. if(labels[k].active) {
  591. const char* lbl = labels[k].name;
  592. int label_sz = strlen(lbl);
  593. if(lblcmp(labels[k].name, pContext->lex_reserved_words[pt.value], label_sz) == 0) {
  594. function_buffer[j].type = INK_INTEGER;
  595. function_buffer[j].value = labels[k].dest - j;
  596. break;
  597. }
  598. } else break;
  599. }
  600. }
  601. }
  602. int err;
  603. err = ink_add_indigenous(pContext, pContext->lex_reserved_words[function_name], function_buffer, function_buffer_top);
  604. if(err < 0) {
  605. pContext->panic = 1;
  606. return -33;
  607. }
  608. function_buffer_top = 0;
  609. mode = MODE_EXECUTABLE;
  610. goto next_token;
  611. }
  612. function_buffer[function_buffer_top] = current;
  613. function_buffer_top += 1;
  614. break;
  615. }
  616. next_token: i=i;
  617. }
  618. if(mode == MODE_FUNCTION || mode == MODE_DO) {
  619. return -32;
  620. }
  621. return 0;
  622. #undef MODE_EXECUTABLE
  623. #undef MODE_FUNCTION
  624. #undef MODE_DO
  625. #undef LABEL_BUFFER
  626. #undef FUNCTION_BUFFER
  627. }
  628. int ink_step(struct context *pContext) {
  629. struct ink_routine* currentRoutine = pContext->routines + pContext->routine_current;
  630. pContext->steps++;
  631. if(currentRoutine->function_stack_top == 0) return 0;
  632. if(pContext->panic) {
  633. return -1;
  634. }
  635. struct stack_frame frame;
  636. struct stack_frame* top;
  637. struct elem next;
  638. int t;
  639. top = &currentRoutine->function_stack[currentRoutine->function_stack_top-1];
  640. t = top->executing.type;
  641. switch(t) {
  642. case INK_NATIVE_FUNCTION:
  643. if(top->index != 0) {
  644. ink_pop_fn(pContext);
  645. } else {
  646. top->index++;
  647. if(pContext->native_words_top <= top->executing.value) {
  648. pContext->panic = 1;
  649. return -1;
  650. }
  651. pContext->native_words[top->executing.value].value(pContext);
  652. }
  653. break;
  654. case INK_FUNCTION:
  655. if(pContext->words_top <= top->executing.value) {
  656. pContext->panic = 1;
  657. return -1;
  658. }
  659. if(top->index >= pContext->words[top->executing.value].size) {
  660. ink_pop_fn(pContext);
  661. } else {
  662. next = pContext->words[top->executing.value].things[top->index];
  663. if(next.type == INK_RETURN) {
  664. ink_pop_fn(pContext);
  665. return 1;
  666. }
  667. frame.executing = next;
  668. frame.index = 0;
  669. t = ink_push_fn(pContext, frame);
  670. if(t < 0) {
  671. pContext->panic = 1;
  672. return -11;
  673. }
  674. top->index++;
  675. }
  676. break;
  677. default:
  678. t = ink_push(pContext, top->executing);
  679. if(t < 0) {
  680. pContext->panic = 1;
  681. return -25;
  682. }
  683. ink_pop_fn(pContext);
  684. break;
  685. }
  686. return 1;
  687. }
  688. void ink_compile(struct context *pContext, char* buffer) {
  689. int routine = ink_make_routine(pContext);
  690. int saved = pContext->routine_current;
  691. pContext->routine_current = routine;
  692. struct ink_routine* currentRoutine = pContext->routines + routine;
  693. currentRoutine->stack = NULL;
  694. currentRoutine->top = 0;
  695. currentRoutine->capacity = 0;
  696. int err;
  697. err = ink_lex(pContext, buffer);
  698. if(err < 0) {
  699. pContext->panic = 1;
  700. return;
  701. }
  702. int i = 0;
  703. struct elem executable_buffer[256];
  704. int executable_buffer_top = 0;
  705. err = ink_parse(pContext, executable_buffer, &executable_buffer_top);
  706. if(err < 0) {
  707. pContext->panic = 1;
  708. return;
  709. }
  710. struct stack_frame frame;
  711. char main_fn[32] = "__-MAIN-__";
  712. char* integer = ink_itoa(pContext, routine);
  713. size_t integer_size = strlen(integer);
  714. memcpy(main_fn+10, integer, integer_size);
  715. pContext->free(integer);
  716. main_fn[10+integer_size] = 0;
  717. frame.executing.value = ink_add_indigenous(pContext, main_fn, executable_buffer, executable_buffer_top);
  718. if(frame.executing.value < 0) {
  719. pContext->panic = 1;
  720. return;
  721. }
  722. frame.executing.type = INK_FUNCTION;
  723. frame.index = 0;
  724. err = ink_push_fn(pContext, frame);
  725. if(err < 0) {
  726. pContext->panic = 1;
  727. return;
  728. }
  729. pContext->routine_current = saved;
  730. return;
  731. }
  732. int ink_can_run(struct context* pContext) {
  733. int it = 0;
  734. for(;it < pContext->routines_top; ++it) {
  735. if(pContext->routines[it].panic == 0) {
  736. return 1;
  737. }
  738. }
  739. return 0;
  740. }
  741. int ink_step_everyone(struct context* pContext) {
  742. int out;
  743. pContext->routine_current = -1;
  744. for(;;) {
  745. do{
  746. ++(pContext->routine_current);
  747. } while(pContext->routine_current < pContext->routines_top && pContext->routines[pContext->routine_current].panic != 0);
  748. if(pContext->routine_current >= pContext->routines_top) break;
  749. if(pContext->routines[pContext->routine_current].panic == INK_ROUTINE_SUCCESS) {
  750. ink_kill_routine(pContext, pContext->routine_current);
  751. }
  752. out = ink_step(pContext);
  753. if(out == 0) {
  754. pContext->routines[pContext->routine_current].panic = INK_ROUTINE_SUCCESS;
  755. } else if(out < 0) {
  756. pContext->routines[pContext->routine_current].panic = out;
  757. }
  758. }
  759. return 0;
  760. }
  761. int ink_new_type(
  762. struct context* ctx,
  763. const char* type_name,
  764. int size,
  765. void (*collect)(struct context*,void*),
  766. struct ink_collection_list (*gc)(struct context*,void*)
  767. ) {
  768. if(ctx->panic) return -128;
  769. if(ctx->types == NULL) {
  770. ctx->types = ctx->inner_malloc(sizeof(struct ink_type) * 8);
  771. ctx->types_top = 0;
  772. ctx->types_capacity = 8;
  773. } else if(ctx->types_top == ctx->types_capacity) {
  774. int new_count = (ctx->types_capacity + ctx->types_capacity/2);
  775. void* renewed = ctx->inner_realloc(ctx->types, sizeof(struct ink_type) * new_count);
  776. if(renewed == NULL) {
  777. return -129;
  778. } else {
  779. ctx->types = renewed;
  780. ctx->types_capacity = new_count;
  781. }
  782. }
  783. ctx->types[ctx->types_top].name = type_name;
  784. ctx->types[ctx->types_top].element_size = size;
  785. ctx->types[ctx->types_top].elements = NULL;
  786. ctx->types[ctx->types_top].elements_top = 0;
  787. ctx->types[ctx->types_top].elements_capacity = 0;
  788. ctx->types[ctx->types_top].collect = collect;
  789. ctx->types[ctx->types_top].gc = gc;
  790. ctx->types_top++;
  791. // Satisfying the minimal value requirement
  792. return ctx->types_top - 1 + 16;
  793. }
  794. static struct element_slab* ink_get_value_link(struct context* ctx, struct elem ref) {
  795. if(ref.type < 16) return NULL;
  796. int type_id = ref.type - 16;
  797. if(type_id >= ctx->types_top) return NULL;
  798. if(ctx->types[type_id].element_size == 0) return NULL;
  799. if(ref.value < 0) return NULL;
  800. if(ref.value >= ctx->types[type_id].elements_top) return NULL;
  801. if(! ctx->types[type_id].elements[ref.value].in_use) return NULL;
  802. return ctx->types[type_id].elements + ref.value;
  803. }
  804. void* ink_get_value(struct context* ctx, struct elem ref) {
  805. struct element_slab* s;
  806. s = ink_get_value_link(ctx, ref);
  807. if(s == NULL) return NULL;
  808. return s->data;
  809. }
  810. struct elem ink_make_native(struct context* ctx, int type, void* ptr) {
  811. if(type < 16) {
  812. struct elem ret;
  813. ret.type = 0;
  814. ret.value = -130;
  815. return ret;
  816. }
  817. int type_id = type - 16;
  818. if(type_id >= ctx->types_top) {
  819. struct elem ret;
  820. ret.type = 0;
  821. ret.value = -129;
  822. return ret;
  823. }
  824. if(ctx->panic) {
  825. struct elem ret;
  826. ret.type = 0;
  827. ret.value = -135;
  828. return ret;
  829. }
  830. if(ctx->types[type_id].elements == NULL) {
  831. ctx->types[type_id].elements = ctx->inner_malloc(sizeof(struct element_slab) * 8);
  832. ctx->types[type_id].elements_top = 0;
  833. ctx->types[type_id].elements_capacity = 8;
  834. memset(ctx->types[type_id].elements + ctx->types[type_id].elements_top, 0, ctx->types[type_id].elements_capacity - ctx->types[type_id].elements_top);
  835. } else if(ctx->types[type_id].elements_top == ctx->types[type_id].elements_capacity) {
  836. int new_count = (ctx->types[type_id].elements_capacity + ctx->types[type_id].elements_capacity/2);
  837. void* renewed = ctx->inner_realloc(ctx->types[type_id].elements, sizeof(struct element_slab) * new_count);
  838. if(renewed == NULL) {
  839. struct elem ret;
  840. ret.type = 0;
  841. ret.value = -129;
  842. return ret;
  843. } else {
  844. ctx->types[type_id].elements = renewed;
  845. ctx->types[type_id].elements_capacity = new_count;
  846. memset(ctx->types[type_id].elements + ctx->types[type_id].elements_top, 0, ctx->types[type_id].elements_capacity - ctx->types[type_id].elements_top);
  847. }
  848. }
  849. int g = ctx->types[type_id].elements_capacity;
  850. int i;
  851. for(i = 0; i < g; ++i) {
  852. if(! ctx->types[type_id].elements[i].in_use) {
  853. ctx->types[type_id].elements[i].in_use = 1;
  854. ctx->types[type_id].elements[i].uses = 1;
  855. if(ctx->types[type_id].element_size < 0) {
  856. ctx->types[type_id].elements[i].data = ptr;
  857. } else {
  858. void* new_ptr = ctx->malloc(ctx->types[type_id].element_size);
  859. if(new_ptr == NULL) {
  860. struct elem ret;
  861. ret.type = 0;
  862. ret.value = -139;
  863. return ret;
  864. }
  865. memcpy(new_ptr, ptr, ctx->types[type_id].element_size);
  866. ctx->types[type_id].elements[i].data = ptr;
  867. }
  868. ctx->types[type_id].elements_top = max(ctx->types[type_id].elements_top+1, i+1);
  869. struct elem ret;
  870. ret.type = type;
  871. ret.value = i;
  872. return ret;
  873. }
  874. }
  875. struct elem ret;
  876. ret.type = 0;
  877. ret.value = -140;
  878. return ret;
  879. }
  880. void ink_gc(struct context* ctx) {
  881. int i, j, k;
  882. for(i = 0; i < ctx->types_top; ++i) {
  883. for(j = 0; j < ctx->types[i].elements_top; ++j) {
  884. ctx->types[i].elements[j].uses = 0;
  885. }
  886. }
  887. for(i = 0; i < ctx->types_top; ++i) {
  888. for(j = 0; j < ctx->types[i].elements_top; ++j) {
  889. struct ink_collection_list c = ctx->types[i].gc(ctx, ctx->types[i].elements[j].data);
  890. for(k = 0; k < c.count; ++k) {
  891. struct element_slab* v = ink_get_value_link(ctx, c.elements[k]);
  892. if(v != NULL) ++v->uses;
  893. }
  894. if(c.elements != NULL) ctx->inner_free(c.elements);
  895. }
  896. }
  897. for(i = 0; i < ctx->routines_top; ++i) {
  898. for(j = 0; j < ctx->routines[i].top; ++j) {
  899. struct element_slab* v = ink_get_value_link(ctx, ctx->routines[i].stack[j]);
  900. if(v != NULL) ++v->uses;
  901. }
  902. }
  903. for(i = 0; i < ctx->types_top; ++i) {
  904. for(j = 0; j < ctx->types[i].elements_top; ++j) {
  905. if(ctx->types[i].elements[j].uses == 0) {
  906. ctx->collections++;
  907. ctx->types[i].collect(ctx, ctx->types[i].elements[j].data);
  908. if(ctx->types[i].element_size > 0) {
  909. ctx->free(ctx->types[i].elements[j].data);
  910. }
  911. ctx->types[i].elements[j].data = NULL;
  912. ctx->types[i].elements[j].uses = 0;
  913. ctx->types[i].elements[j].in_use = 0;
  914. }
  915. }
  916. }
  917. }
  918. /**********************************************************************************************************************/
  919. static void print_stacktrace(struct context* _) {
  920. int i = 0;
  921. struct ink_routine* currentRoutine = _->routines + _->routine_current;
  922. for(; i < currentRoutine->function_stack_top; ++i) {
  923. struct elem thing;
  924. thing = currentRoutine->function_stack[i].executing;
  925. switch(thing.type) {
  926. case INK_NATIVE_FUNCTION: {
  927. char *n = _->native_words[thing.value].name;
  928. while (*n) {
  929. _->putchar(*n);
  930. ++n;
  931. }
  932. _->putchar(10);
  933. break;
  934. }
  935. case INK_FUNCTION:{
  936. char *n = _->native_words[thing.value].name;
  937. while (*n) {
  938. _->putchar(*n);
  939. ++n;
  940. }
  941. _->putchar(':');
  942. n = ink_itoa(_, currentRoutine->function_stack[i].index);
  943. while (*n) {
  944. _->putchar(*n);
  945. ++n;
  946. }
  947. _->free(n);
  948. _->putchar(10);
  949. break;
  950. }
  951. default:
  952. break;
  953. }
  954. }
  955. }
  956. static void add_int(struct context* ctx) {
  957. struct ink_routine* currentRoutine = ctx->routines + ctx->routine_current;
  958. if(currentRoutine->top < 2) {
  959. currentRoutine->panic = 1;
  960. return;
  961. }
  962. struct elem a;
  963. struct elem b;
  964. a = currentRoutine->stack[currentRoutine->top-1];
  965. b = currentRoutine->stack[currentRoutine->top-2];
  966. if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) {
  967. ctx->panic = 1;
  968. return;
  969. }
  970. ink_pop(ctx);
  971. currentRoutine->stack[currentRoutine->top-1].value = a.value + b.value;
  972. }
  973. static void sub_int(struct context* ctx) {
  974. struct ink_routine* currentRoutine = ctx->routines + ctx->routine_current;
  975. if(currentRoutine->top < 2) {
  976. currentRoutine->panic = 1;
  977. return;
  978. }
  979. struct elem a;
  980. struct elem b;
  981. a = currentRoutine->stack[currentRoutine->top-1];
  982. b = currentRoutine->stack[currentRoutine->top-2];
  983. if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) {
  984. currentRoutine->panic = 1;
  985. return;
  986. }
  987. ink_pop(ctx);
  988. currentRoutine->stack[currentRoutine->top-1].value = b.value - a.value;
  989. }
  990. static void mult_int(struct context* ctx) {
  991. struct ink_routine* currentRoutine = ctx->routines + ctx->routine_current;
  992. if(currentRoutine->top < 2) {
  993. currentRoutine->panic = 1;
  994. return;
  995. }
  996. struct elem a;
  997. struct elem b;
  998. a = currentRoutine->stack[currentRoutine->top-1];
  999. b = currentRoutine->stack[currentRoutine->top-2];
  1000. if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) {
  1001. currentRoutine->panic = 1;
  1002. return;
  1003. }
  1004. ink_pop(ctx);
  1005. currentRoutine->stack[currentRoutine->top-1].value = b.value * a.value;
  1006. }
  1007. static void div_int(struct context* ctx) {
  1008. struct ink_routine* currentRoutine = ctx->routines + ctx->routine_current;
  1009. if(currentRoutine->top < 2) {
  1010. currentRoutine->panic = 1;
  1011. return;
  1012. }
  1013. struct elem a;
  1014. struct elem b;
  1015. a = currentRoutine->stack[currentRoutine->top-1];
  1016. b = currentRoutine->stack[currentRoutine->top-2];
  1017. if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) {
  1018. currentRoutine->panic = 1;
  1019. return;
  1020. }
  1021. ink_pop(ctx);
  1022. currentRoutine->stack[currentRoutine->top-1].value = b.value / a.value;
  1023. }
  1024. static void rem_int(struct context* ctx) {
  1025. struct ink_routine* currentRoutine = ctx->routines + ctx->routine_current;
  1026. if(currentRoutine->top < 2) {
  1027. currentRoutine->panic = 1;
  1028. return;
  1029. }
  1030. struct elem a;
  1031. struct elem b;
  1032. a = currentRoutine->stack[currentRoutine->top-1];
  1033. b = currentRoutine->stack[currentRoutine->top-2];
  1034. if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) {
  1035. currentRoutine->panic = 1;
  1036. return;
  1037. }
  1038. ink_pop(ctx);
  1039. currentRoutine->stack[currentRoutine->top-1].value = b.value % a.value;
  1040. }
  1041. static void dupe_elem(struct context* ctx) {
  1042. struct ink_routine* currentRoutine = ctx->routines + ctx->routine_current;
  1043. if(currentRoutine->top < 1) {
  1044. ctx->panic = 1;
  1045. return;
  1046. }
  1047. struct elem a;
  1048. a = currentRoutine->stack[currentRoutine->top-1];
  1049. int err;
  1050. err = ink_push(ctx, a);
  1051. if(err < 0) ctx->panic;
  1052. }
  1053. static void drop_elem(struct context* ctx) {
  1054. struct ink_routine* currentRoutine = ctx->routines + ctx->routine_current;
  1055. if(currentRoutine->top < 1) {
  1056. ctx->panic = 1;
  1057. return;
  1058. }
  1059. ink_pop(ctx);
  1060. }
  1061. static void pluck_elem(struct context* ctx) {
  1062. struct ink_routine* currentRoutine = ctx->routines + ctx->routine_current;
  1063. if(currentRoutine->top < 1) {
  1064. currentRoutine->panic = 1;
  1065. return;
  1066. }
  1067. struct elem a;
  1068. a = currentRoutine->stack[currentRoutine->top-1];
  1069. if(a.type != INK_INTEGER) {
  1070. ctx->panic = 1;
  1071. return;
  1072. }
  1073. int position = currentRoutine->top - (a.value + 1);
  1074. if(position >= currentRoutine->top || position < 0) {
  1075. ctx->panic = 1;
  1076. return;
  1077. }
  1078. ink_pop(ctx);
  1079. int err;
  1080. err = ink_push(ctx, currentRoutine->stack[position]);
  1081. if(err < 0) ctx->panic;
  1082. }
  1083. static void swap_elem(struct context* ctx) {
  1084. struct ink_routine* currentRoutine = ctx->routines + ctx->routine_current;
  1085. if(currentRoutine->top < 2) {
  1086. currentRoutine->panic = 1;
  1087. return;
  1088. }
  1089. struct elem a;
  1090. struct elem b;
  1091. a = currentRoutine->stack[currentRoutine->top-1];
  1092. b = currentRoutine->stack[currentRoutine->top-2];
  1093. currentRoutine->stack[currentRoutine->top-2] = a;
  1094. currentRoutine->stack[currentRoutine->top-1] = b;
  1095. }
  1096. static void return_if(struct context* ctx) {
  1097. struct ink_routine* currentRoutine = ctx->routines + ctx->routine_current;
  1098. if(currentRoutine->top < 1) {
  1099. ctx->panic = 1;
  1100. return;
  1101. }
  1102. struct elem a;
  1103. a = currentRoutine->stack[currentRoutine->top-1];
  1104. if(a.type != INK_INTEGER) {
  1105. ctx->panic = 1;
  1106. return;
  1107. }
  1108. if(a.value) {
  1109. ink_pop_fn(ctx);
  1110. ink_pop_fn(ctx);
  1111. }
  1112. ink_pop(ctx);
  1113. return;
  1114. }
  1115. static void jump_if(struct context* ctx) {
  1116. struct ink_routine* currentRoutine = ctx->routines + ctx->routine_current;
  1117. if(currentRoutine->top < 1) {
  1118. ctx->panic = 1;
  1119. return;
  1120. }
  1121. struct elem a;
  1122. a = currentRoutine->stack[currentRoutine->top-1];
  1123. if(a.type != INK_INTEGER) {
  1124. ctx->panic = 1;
  1125. return;
  1126. }
  1127. ink_pop(ctx);
  1128. if(a.value) {
  1129. ink_pop_fn(ctx);
  1130. a = currentRoutine->stack[currentRoutine->top-1];
  1131. currentRoutine->function_stack[currentRoutine->function_stack_top - 1].index += a.value - 3;
  1132. }
  1133. ink_pop(ctx);
  1134. return;
  1135. }
  1136. static void print_int(struct context* ctx) {
  1137. struct ink_routine* currentRoutine = ctx->routines + ctx->routine_current;
  1138. if(currentRoutine->top < 1 || currentRoutine->stack[currentRoutine->top-1].type != INK_INTEGER) {
  1139. currentRoutine->panic = 1;
  1140. return;
  1141. }
  1142. struct elem a;
  1143. a = currentRoutine->stack[currentRoutine->top-1];
  1144. ink_pop(ctx);
  1145. char* n = ink_itoa(ctx, a.value);
  1146. char* str = n;
  1147. while (*str) {
  1148. ctx->putchar(*str);
  1149. ++str;
  1150. }
  1151. ctx->free(n);
  1152. }
  1153. static void print_as_utf8(struct context* ctx) {
  1154. struct ink_routine* currentRoutine = ctx->routines + ctx->routine_current;
  1155. if(currentRoutine->top < 1 || currentRoutine->stack[currentRoutine->top-1].type != INK_INTEGER) {
  1156. ctx->panic = 1;
  1157. return;
  1158. }
  1159. struct elem a;
  1160. a = currentRoutine->stack[currentRoutine->top-1];
  1161. if(a.value <= 0x7F) {
  1162. ctx->putchar(a.value);
  1163. } else if(a.value <= 0x7FF) {
  1164. ctx->putchar(((a.value & 0xFC0) >> 6) | 192);
  1165. ctx->putchar((a.value & 0x3F) | 128);
  1166. } else if(a.value <= 0xFFFF) {
  1167. ctx->putchar(((a.value & 0x3F000) >> 12) | 224);
  1168. ctx->putchar(((a.value & 0xFC0) >> 6) | 128);
  1169. ctx->putchar((a.value & 0x3F) | 128);
  1170. } else if(a.value <= 0x10FFFF) {
  1171. ctx->putchar(((a.value & 0x3C0000) >> 18) | 240);
  1172. ctx->putchar(((a.value & 0x3F000) >> 12) | 128);
  1173. ctx->putchar(((a.value & 0xFC0) >> 6) | 128);
  1174. ctx->putchar((a.value & 0x3F) | 128);
  1175. } else {
  1176. ctx->panic = 1;
  1177. return;
  1178. }
  1179. ink_pop(ctx);
  1180. }
  1181. struct ink_array {
  1182. int top;
  1183. int capacity;
  1184. struct elem* elements;
  1185. };
  1186. static int get_type_by_name(struct context* ctx, const char* name) {
  1187. int i;
  1188. for(i = 0; i < ctx->types_top; ++i) {
  1189. if(strcmp(ctx->types[i].name, name) == 0) {
  1190. return i + 16;
  1191. }
  1192. }
  1193. return -1;
  1194. }
  1195. static void collect_array(struct context* ctx, void* array) {
  1196. struct ink_array* ary = array;
  1197. ctx->free(ary->elements);
  1198. }
  1199. static struct ink_collection_list gc_array(struct context* ctx, void* array) {
  1200. struct ink_array* ary = array;
  1201. struct ink_collection_list c;
  1202. c.elements = ctx->inner_malloc(sizeof(struct elem)*ary->top);
  1203. c.count = ary->top;
  1204. memcpy(c.elements, ary->elements, sizeof(struct elem)*ary->top);
  1205. return c;
  1206. }
  1207. static void new_array(struct context* ctx) {
  1208. int tid = get_type_by_name(ctx, "array");
  1209. struct ink_array ary;
  1210. ary.elements = NULL;
  1211. ary.top = 0;
  1212. ary.capacity = 0;
  1213. struct elem e = ink_make_native(ctx, tid, &ary);
  1214. ink_push(ctx, e);
  1215. }
  1216. int ink_std_library(struct context* ctx) {
  1217. int v;
  1218. v = 0;
  1219. int array_t = ink_new_type(ctx, "array", sizeof(struct ink_array), collect_array, gc_array);
  1220. v += ink_add_native(ctx, "array", new_array);
  1221. v += ink_add_native(ctx, "trace", print_stacktrace);
  1222. v += ink_add_native(ctx, "print_int", print_int);
  1223. v += ink_add_native(ctx, "print_utf8", print_as_utf8);
  1224. v += ink_add_native(ctx, "+", add_int);
  1225. v += ink_add_native(ctx, "-", sub_int);
  1226. v += ink_add_native(ctx, "*", mult_int);
  1227. v += ink_add_native(ctx, "/", div_int);
  1228. v += ink_add_native(ctx, "%", rem_int);
  1229. v += ink_add_native(ctx, "swap", swap_elem);
  1230. v += ink_add_native(ctx, "dup", dupe_elem);
  1231. v += ink_add_native(ctx, "drop", drop_elem);
  1232. v += ink_add_native(ctx, "pluck", pluck_elem);
  1233. v += ink_add_native(ctx, "return_if", return_if);
  1234. v += ink_add_native(ctx, "jump_if", jump_if);
  1235. return v;
  1236. }