A minimalistic programming language written in C89.
25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.

1420 satır
38 KiB

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