A minimalistic programming language written in C89.
25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2359 lines
71 KiB

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