A minimalistic programming language written in C89.
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

2398 行
62 KiB

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