A minimalistic programming language written in C89.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2103 lines
57 KiB

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