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

2359 lignes
71 KiB

il y a 5 mois
il y a 6 mois
il y a 6 mois
il y a 6 mois
il y a 6 mois
il y a 6 mois
il y a 6 mois
il y a 5 mois
il y a 6 mois
il y a 6 mois
il y a 6 mois
il y a 6 mois
il y a 6 mois
il y a 6 mois
il y a 6 mois
il y a 6 mois
il y a 6 mois
il y a 6 mois
il y a 6 mois
il y a 6 mois
il y a 6 mois
il y a 6 mois
il y a 6 mois
il y a 6 mois
  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. }