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.

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