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.

1854 lines
48 KiB

преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 3 месеца
преди 3 месеца
преди 3 месеца
преди 3 месеца
преди 3 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
преди 4 месеца
  1. #include "ink.h"
  2. #ifndef NOSTDLIB
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <ctype.h>
  7. #ifdef INSTRUMENTATION
  8. #include <time.h>
  9. #endif
  10. #endif
  11. #define INK_RESERVED (-1)
  12. #define INK_FUNCTION_KW (-2)
  13. #define INK_DO_KW (-3)
  14. #define INK_END_KW (-4)
  15. #define INK_LABEL (-5)
  16. #define INK_RETURN (-6)
  17. #define _KEYWORD_INK_FUNCTION "fn"
  18. #define _KEYWORD_INK_DO "do"
  19. #define _KEYWORD_INK_END "end"
  20. #define _KEYWORD_INK_RETURN "return"
  21. #define min(x, y) ((x) > (y) ? (y) : (x))
  22. #define max(x, y) ((x) < (y) ? (y) : (x))
  23. struct label {
  24. int active;
  25. int dest;
  26. char* name;
  27. };
  28. #ifdef NOSTDLIB
  29. static size_t strlen(const char* c) {
  30. size_t j;
  31. j = 0;
  32. while(*(c++)) {
  33. j++;
  34. }
  35. return j;
  36. }
  37. static void* memcpy(void* _dest, const void* _src, size_t sz) {
  38. char* dest;
  39. const char* src;
  40. dest = _dest;
  41. src = _src;
  42. while(sz--) {
  43. *(dest++) = *(src++);
  44. }
  45. return dest;
  46. }
  47. static int strcmp(const char* dest, const char* src) {
  48. while(*dest != 0 && *src != 0) {
  49. if(*(dest++) != *(src++)) {
  50. return 1;
  51. }
  52. }
  53. return 0;
  54. }
  55. static void* memmove(void* _dest, const void* _src, size_t sz) {
  56. char* dest;
  57. const char* src;
  58. dest = _dest;
  59. src = _src;
  60. if (src < dest) {
  61. src += sz;
  62. dest += sz;
  63. while (sz-- > 0) {
  64. *--dest = *--src;
  65. }
  66. } else {
  67. while (sz-- > 0) {
  68. *dest++ = *src++;
  69. }
  70. }
  71. return dest;
  72. }
  73. static void* memset(void* _dest, int src, size_t sz) {
  74. char* dest;
  75. dest = _dest;
  76. while(sz--) {
  77. *(dest++) = src++;
  78. }
  79. return dest;
  80. }
  81. static int isspace(int d) {
  82. return d == ' ' || d == '\t' || d == '\n';
  83. }
  84. static int isdigit(int d) {
  85. return '0' <= d && d <= '9';
  86. }
  87. static int atoi(const char* c) {
  88. int ret;
  89. ret = 0;
  90. while(*c) {
  91. ret *= 10;
  92. ret += *c - '0';
  93. ++c;
  94. }
  95. return ret;
  96. }
  97. #endif
  98. int ink_add_native(struct context* ctx, const char* name, void(*value)(struct context*)) {
  99. int len;
  100. char* copy;
  101. if(ctx->native_words == NULL) {
  102. ctx->native_words = ctx->inner_malloc(sizeof(struct native_fn) * 8);
  103. ctx->native_words_top = 0;
  104. ctx->native_words_capacity = 8;
  105. } else if(ctx->native_words_top == ctx->native_words_capacity) {
  106. int new_count;
  107. void* renewed;
  108. new_count = (ctx->native_words_capacity + ctx->native_words_capacity/2);
  109. renewed = ctx->inner_realloc(ctx->native_words, sizeof(struct native_fn) * new_count);
  110. if(renewed == NULL) {
  111. return -3;
  112. } else {
  113. ctx->native_words = renewed;
  114. ctx->native_words_capacity = new_count;
  115. }
  116. }
  117. len = strlen(name);
  118. copy = ctx->inner_malloc(len+1);
  119. if(copy == NULL) {
  120. return -4;
  121. }
  122. memcpy(copy, name, len);
  123. copy[len] = 0;
  124. ctx->native_words[ctx->native_words_top].value = value;
  125. ctx->native_words[ctx->native_words_top].name = copy;
  126. ctx->native_words_top++;
  127. return 0;
  128. }
  129. static int ink_add_indigenous(struct context* ctx, const char* name, struct elem* m, size_t count) {
  130. int len, i;
  131. char* copy;
  132. if(ctx->words == NULL) {
  133. ctx->words = ctx->malloc(sizeof(struct fn) * 8);
  134. ctx->words_top = 0;
  135. ctx->words_capacity = 8;
  136. } else if(ctx->words_top == ctx->words_capacity) {
  137. int new_count;
  138. void* renewed;
  139. new_count = (ctx->words_capacity + ctx->words_capacity/2);
  140. renewed = ctx->realloc(ctx->words, sizeof(struct fn) * new_count);
  141. if(renewed == NULL) {
  142. return -1;
  143. } else {
  144. ctx->words = renewed;
  145. ctx->words_capacity = new_count;
  146. }
  147. }
  148. for(i = 0; i < ctx->words_top; ++i) {
  149. if(strcmp(name, ctx->words[i].name) == 0) {
  150. ctx->free(ctx->words[i].things);
  151. ctx->words[i].things = ctx->malloc(sizeof(struct elem) * count);
  152. memcpy(ctx->words[i].things, m, sizeof(struct elem) * count);
  153. ctx->words[i].size = count;
  154. return i;
  155. }
  156. }
  157. len = strlen(name);
  158. copy = ctx->malloc(len+1);
  159. if(copy == NULL) {
  160. return -2;
  161. }
  162. memcpy(copy, name, len);
  163. copy[len] = 0;
  164. ctx->words[ctx->words_top].things = ctx->malloc(sizeof(struct elem) * count);
  165. memcpy(ctx->words[ctx->words_top].things, m, sizeof(struct elem) * count);
  166. ctx->words[ctx->words_top].size = count;
  167. ctx->words[ctx->words_top].name = copy;
  168. return ctx->words_top++;
  169. }
  170. /**
  171. *
  172. * @param ctx The context
  173. * @param name The name to add
  174. * @internal add a lexed string to the parser
  175. * @return the id of the string in the list
  176. */
  177. static int ink_add_lex_string(struct context* ctx, const char* name) {
  178. int i;
  179. int len;
  180. if(ctx->lex_reserved_words == NULL) {
  181. ctx->lex_reserved_words = ctx->inner_malloc(sizeof(char*) * 8);
  182. ctx->lex_reserved_words_top = 0;
  183. ctx->lex_reserved_words_capacity = 8;
  184. } else if(ctx->lex_reserved_words_top == ctx->lex_reserved_words_capacity) {
  185. int new_count;
  186. void* renewed;
  187. new_count = (ctx->lex_reserved_words_capacity + ctx->lex_reserved_words_capacity/2);
  188. renewed = ctx->inner_realloc(ctx->lex_reserved_words, sizeof(struct native_fn) * new_count);
  189. if(renewed == NULL) {
  190. return -5;
  191. } else {
  192. ctx->lex_reserved_words = renewed;
  193. ctx->lex_reserved_words_capacity = new_count;
  194. }
  195. }
  196. for(i = 0; i < ctx->lex_reserved_words_top; i++) {
  197. if(strcmp(ctx->lex_reserved_words[i], name) == 0) {
  198. return i;
  199. }
  200. }
  201. len = strlen(name);
  202. i = ctx->lex_reserved_words_top;
  203. ctx->lex_reserved_words[i] = ctx->malloc(len+1);
  204. memcpy(ctx->lex_reserved_words[i], name, len);
  205. ctx->lex_reserved_words[i][len] = 0;
  206. ctx->lex_reserved_words_top++;
  207. return i;
  208. }
  209. int ink_push(struct context* ctx, struct elem value) {
  210. struct ink_routine* current;
  211. if(ctx->routine_current >= ctx->routines_top) return -65;
  212. current = ctx->routines + ctx->routine_current;
  213. if(current->stack == NULL) {
  214. current->stack = ctx->malloc(sizeof(struct elem) * 8);
  215. current->top = 0;
  216. current->capacity = 8;
  217. } else if(current->top == current->capacity) {
  218. int new_count;
  219. void* renewed;
  220. new_count = (current->capacity + current->capacity/2);
  221. renewed = ctx->realloc(current->stack, sizeof(struct elem) * new_count);
  222. if(renewed == NULL) {
  223. return -18;
  224. } else {
  225. current->stack = renewed;
  226. current->capacity = new_count;
  227. }
  228. }
  229. current->stack[current->top] = value;
  230. current->top++;
  231. return 0;
  232. }
  233. int ink_push_fn(struct context* ctx, struct stack_frame value) {
  234. struct ink_routine* current;
  235. if(ctx->routine_current >= ctx->routines_top) return -55;
  236. current = ctx->routines + ctx->routine_current;
  237. if(current->panic) return -56;
  238. if(current->function_stack == NULL) {
  239. current->function_stack = ctx->malloc(sizeof(struct stack_frame) * 8);
  240. current->function_stack_top = 0;
  241. current->function_stack_capacity = 8;
  242. } else if(current->function_stack_top == current->function_stack_capacity) {
  243. int new_count;
  244. void* renewed;
  245. new_count = (current->function_stack_capacity + current->function_stack_capacity/2);
  246. renewed = ctx->realloc(current->function_stack, sizeof(struct stack_frame) * new_count);
  247. if(renewed == NULL) {
  248. return -9;
  249. } else {
  250. current->function_stack = renewed;
  251. current->function_stack_capacity = new_count;
  252. }
  253. }
  254. current->function_stack[current->function_stack_top] = value;
  255. current->function_stack_top++;
  256. return 0;
  257. }
  258. void ink_pop_fn(struct context* ctx) {
  259. if(ctx->routine_current >= ctx->routines_top) return;
  260. if(ctx->routines[ctx->routine_current].panic) return;
  261. if(ctx->routines[ctx->routine_current].function_stack == NULL) return;
  262. if(ctx->routines[ctx->routine_current].function_stack_top == 0) return;
  263. ctx->routines[ctx->routine_current].function_stack_top--;
  264. }
  265. void ink_pop(struct context* ctx) {
  266. if(ctx->routine_current >= ctx->routines_top) return;
  267. if(ctx->routines[ctx->routine_current].panic) return;
  268. if(ctx->routines[ctx->routine_current].stack == NULL) return;
  269. if(ctx->routines[ctx->routine_current].top == 0) return;
  270. ctx->routines[ctx->routine_current].top--;
  271. }
  272. struct context* ink_make_context(void*(*malloc)(size_t), void*(*realloc)(void*, size_t), void(*free)(void*), int(*putchar)(int)) {
  273. struct context* ctx;
  274. ctx = (struct context*)malloc(sizeof(struct context));
  275. ctx->malloc = malloc;
  276. ctx->realloc = realloc;
  277. ctx->free = free;
  278. ctx->inner_malloc = malloc;
  279. ctx->inner_realloc = realloc;
  280. ctx->inner_free = free;
  281. ctx->putchar = putchar;
  282. ctx->panic = 0;
  283. ctx->routines = NULL;
  284. ctx->routines_capacity = 0;
  285. ctx->routines_top = 0;
  286. ctx->types = NULL;
  287. ctx->types_capacity = 0;
  288. ctx->types_top = 0;
  289. ctx->native_words = NULL;
  290. ctx->native_words_capacity = 0;
  291. ctx->native_words_top = 0;
  292. ctx->words = NULL;
  293. ctx->words_capacity = 0;
  294. ctx->words_top = 0;
  295. ctx->lex_reserved_words = NULL;
  296. ctx->lex_reserved_words_capacity = 0;
  297. ctx->lex_reserved_words_top = 0;
  298. ctx->collections = 0;
  299. ctx->steps = 0;
  300. return ctx;
  301. }
  302. /**
  303. * Allocates a string that contains the integer
  304. * @param _ context (used to allocate)
  305. * @param cpy the value
  306. * @return the allocated string, needs to be freed by ctx->free
  307. * @internal this function is slightly cursed
  308. */
  309. static char* ink_itoa(struct context* _, int cpy) {
  310. char* n;
  311. char* it;
  312. n = _->malloc(16);
  313. n[15] = 0;
  314. it = n+15;
  315. do {
  316. it--;
  317. *it = (cpy % 10) + '0';
  318. cpy = cpy / 10;
  319. } while(cpy);
  320. memmove(n, it, 16 - (it-n));
  321. return n;
  322. }
  323. #ifndef NOSTDLIB
  324. struct context* ink_make_default_context(void) {
  325. struct context* ctx;
  326. ctx = ink_make_context(malloc, realloc, free, putchar);
  327. ink_std_library(ctx);
  328. return ctx;
  329. }
  330. #endif
  331. static int ink_consume_one(int* end, struct context* pContext, char** buffer, char* r) {
  332. int i;
  333. int done;
  334. struct elem value;
  335. int err;
  336. if(*end == 0) {
  337. return 0;
  338. }
  339. r[*end] = 0;
  340. done = 0;
  341. if (strcmp(r, _KEYWORD_INK_FUNCTION) == 0) {
  342. value.value = 0;
  343. value.type = INK_FUNCTION_KW;
  344. done = 1;
  345. }
  346. if (!done && strcmp(r, _KEYWORD_INK_DO) == 0) {
  347. value.value = 0;
  348. value.type = INK_DO_KW;
  349. done = 1;
  350. }
  351. if (!done && strcmp(r, _KEYWORD_INK_END) == 0) {
  352. value.value = 0;
  353. value.type = INK_END_KW;
  354. done = 1;
  355. }
  356. if (!done && strcmp(r, _KEYWORD_INK_RETURN) == 0) {
  357. value.value = 0;
  358. value.type = INK_RETURN;
  359. done = 1;
  360. }
  361. if(done) {
  362. err = ink_push(pContext, value);
  363. if(err < 0) {
  364. return -19;
  365. }
  366. }
  367. if (!done) {
  368. for (i = 0; i < pContext->words_top; ++i) {
  369. if (strcmp(r, pContext->words[i].name) == 0) {
  370. value.value = i;
  371. value.type = INK_FUNCTION;
  372. err = ink_push(pContext, value);
  373. if(err < 0) {
  374. return -20;
  375. }
  376. done = 1;
  377. break;
  378. }
  379. }
  380. }
  381. if (!done) {
  382. for (i = 0; i < pContext->native_words_top; ++i) {
  383. if (strcmp(r, pContext->native_words[i].name) == 0) {
  384. value.value = i;
  385. value.type = INK_NATIVE_FUNCTION;
  386. err = ink_push(pContext, value);
  387. if(err < 0) {
  388. return -21;
  389. }
  390. done = 1;
  391. break;
  392. }
  393. }
  394. }
  395. if (!done) {
  396. for(i = (r[0] == '-'); i < *end; i++) {
  397. if(!isdigit(r[i])){
  398. goto not_an_int;
  399. }
  400. }
  401. value.value = atoi(r);
  402. value.type = INK_INTEGER;
  403. err = ink_push(pContext, value);
  404. if(err < 0) {
  405. return -22;
  406. }
  407. done = 1;
  408. }
  409. not_an_int:
  410. if (!done) {
  411. i = ink_add_lex_string(pContext, r);
  412. if(i < 0) {
  413. pContext->panic = 1;
  414. return -7;
  415. }
  416. value.value = i;
  417. if(r[strlen(r) - 1] == ':') {
  418. value.type = INK_LABEL;
  419. } else {
  420. value.type = INK_RESERVED;
  421. }
  422. err = ink_push(pContext, value);
  423. if(err < 0) {
  424. return -23;
  425. }
  426. }
  427. *end = 0;
  428. return 0;
  429. }
  430. static int ink_lex(struct context *pContext, char* buffer) {
  431. /* Limits the token size to 127 chars */
  432. char r[128];
  433. int end;
  434. int err;
  435. end = 0;
  436. restart_after_comment:
  437. while(*buffer != 0) {
  438. if(isspace(*buffer)) {
  439. if(end == 1 && r[0] == '#') {
  440. while(*buffer != '\n' && *buffer != 0) {
  441. ++buffer;
  442. }
  443. end = 0;
  444. goto restart_after_comment;
  445. }
  446. err = ink_consume_one(&end, pContext, &buffer, r);
  447. if(err < 0) {
  448. pContext->panic = 1;
  449. return -8;
  450. }
  451. } else {
  452. r[end] = *buffer;
  453. ++end;
  454. }
  455. ++buffer;
  456. }
  457. err = ink_consume_one(&end, pContext, &buffer, r);
  458. if(err < 0) {
  459. pContext->panic = 1;
  460. return -9;
  461. }
  462. return 0;
  463. }
  464. static int lblcmp(const char* label, const char* other, size_t label_sz) {
  465. while (label_sz != 1) {
  466. if(*other == 0) return 1;
  467. if(*label != *other) return 1;
  468. ++label;
  469. ++other;
  470. label_sz--;
  471. }
  472. return 0;
  473. }
  474. int ink_make_routine(struct context* ctx) {
  475. struct ink_routine* it;
  476. struct ink_routine* end;
  477. /* Allocate space if needed */
  478. if(ctx->routines == NULL) {
  479. ctx->routines = ctx->inner_malloc(sizeof(struct ink_routine) * 8);
  480. ctx->routines_top = 0;
  481. ctx->routines_capacity = 8;
  482. it = ctx->routines;
  483. end = ctx->routines + 8;
  484. for(;it != end;++it) {
  485. it->stack = NULL;
  486. it->function_stack = NULL;
  487. it->panic = INK_ROUTINE_CAN_REUSE;
  488. }
  489. } else if(ctx->routines_top == ctx->routines_capacity) {
  490. int new_count;
  491. void* renewed;
  492. new_count = (ctx->routines_capacity + ctx->routines_capacity/2);
  493. renewed = ctx->inner_realloc(ctx->routines, sizeof(struct ink_routine) * new_count);
  494. if(renewed == NULL) {
  495. return -99;
  496. } else {
  497. ctx->routines = renewed;
  498. it = ctx->routines + ctx->routines_capacity;
  499. end = ctx->routines + new_count;
  500. for(;it != end;++it) {
  501. it->panic = INK_ROUTINE_CAN_REUSE;
  502. }
  503. ctx->routines_capacity = new_count;
  504. }
  505. }
  506. it = ctx->routines;
  507. end = ctx->routines + ctx->routines_capacity;
  508. /* Looks for a reusable routine space then uses it */
  509. for(;it != end;++it) {
  510. if(it->panic == INK_ROUTINE_CAN_REUSE) {
  511. int idx;
  512. it->panic = 0;
  513. it->stack = NULL;
  514. it->top = 0;
  515. it->capacity = 0;
  516. it->function_stack = NULL;
  517. it->function_stack_top = 0;
  518. it->function_stack_capacity = 0;
  519. idx = it - ctx->routines;
  520. if(idx >= ctx->routines_top) {
  521. ctx->routines_top = idx + 1;
  522. }
  523. return idx;
  524. }
  525. }
  526. return -758;
  527. }
  528. int ink_kill_routine(struct context* ctx, int routine){
  529. struct ink_routine* curr;
  530. if(routine < 0 || routine >= ctx->routines_top) {
  531. return 0;
  532. }
  533. curr = ctx->routines + routine;
  534. if(curr->panic == INK_ROUTINE_CAN_REUSE) {
  535. return 0;
  536. }
  537. if(curr->stack != NULL) {
  538. ctx->free(curr->stack);
  539. curr->stack = NULL;
  540. }
  541. if(curr->function_stack != NULL) {
  542. ctx->free(curr->function_stack);
  543. curr->function_stack = NULL;
  544. }
  545. curr->panic = INK_ROUTINE_CAN_REUSE;
  546. return 1;
  547. }
  548. /**
  549. *
  550. * @param pContext
  551. * @param executable_buffer
  552. * @param executable_buffer_top
  553. * @internal Loop from hell
  554. */
  555. static int ink_parse(struct context* pContext, struct elem* executable_buffer, int* executable_buffer_top) {
  556. struct ink_routine* currentRoutine;
  557. int i, function_buffer_top, function_name, mode;
  558. int err;
  559. #define LABEL_BUFFER 128
  560. #define FUNCTION_BUFFER 256
  561. struct label labels[LABEL_BUFFER];
  562. struct elem function_buffer[FUNCTION_BUFFER];
  563. currentRoutine = pContext->routines + pContext->routine_current;
  564. function_buffer_top = 0;
  565. function_name = -1;
  566. #define MODE_EXECUTABLE 0
  567. #define MODE_FUNCTION 1
  568. #define MODE_DO 2
  569. mode = MODE_EXECUTABLE;
  570. memset(labels, 0, sizeof(struct label)*LABEL_BUFFER);
  571. /* Loop from hell, good luck, pro-tip: leave the parser alone */
  572. for(i = 0; i < currentRoutine->top; ++i) {
  573. struct elem current;
  574. current = currentRoutine->stack[i];
  575. switch (mode) {
  576. case MODE_EXECUTABLE:
  577. switch(current.type) {
  578. case INK_FUNCTION_KW:
  579. mode = MODE_FUNCTION;
  580. function_name = -1;
  581. goto next_token;
  582. case INK_DO_KW:
  583. case INK_END_KW:
  584. return -26;
  585. default:
  586. executable_buffer[*executable_buffer_top] = current;
  587. *executable_buffer_top += 1;
  588. }
  589. break;
  590. case MODE_FUNCTION:
  591. if(current.type == INK_DO_KW) {
  592. if(function_name == -1) {
  593. return -27;
  594. } else {
  595. mode = MODE_DO;
  596. memset(labels, 0, sizeof(struct label)*128);
  597. goto next_token;
  598. }
  599. }
  600. if(function_name != -1) {
  601. return -28;
  602. }
  603. if(current.type != INK_RESERVED) {
  604. return -29;
  605. }
  606. function_name = current.value;
  607. break;
  608. case MODE_DO:
  609. if(current.type == INK_END_KW) {
  610. int j;
  611. for(j = 0; j < function_buffer_top; j++) {
  612. struct elem pt;
  613. pt = function_buffer[j];
  614. if(pt.type == INK_LABEL) {
  615. int k;
  616. for(k = 0; k < LABEL_BUFFER; k++) {
  617. if(labels[k].active) {
  618. if(strcmp(labels[k].name, pContext->lex_reserved_words[pt.value]) == 0) {
  619. labels[k].dest = j;
  620. return -30;
  621. break;
  622. }
  623. } else {
  624. labels[k].active = 1;
  625. labels[k].name = pContext->lex_reserved_words[pt.value];
  626. labels[k].dest = j;
  627. memcpy(function_buffer+j, function_buffer+j+1, sizeof(struct elem)*(function_buffer_top-j-1));
  628. function_buffer_top--;
  629. j--;
  630. break;
  631. }
  632. }
  633. }
  634. }
  635. for(j = 0; j < function_buffer_top; j++) {
  636. struct elem pt;
  637. pt = function_buffer[j];
  638. if(pt.type == INK_RESERVED) {
  639. int k;
  640. for(k = 0; k < LABEL_BUFFER; k++) {
  641. if(labels[k].active) {
  642. int label_sz;
  643. const char* lbl;
  644. lbl = labels[k].name;
  645. label_sz = strlen(lbl);
  646. if(lblcmp(labels[k].name, pContext->lex_reserved_words[pt.value], label_sz) == 0) {
  647. function_buffer[j].type = INK_INTEGER;
  648. function_buffer[j].value = labels[k].dest - j;
  649. break;
  650. }
  651. } else break;
  652. }
  653. }
  654. }
  655. err = ink_add_indigenous(pContext, pContext->lex_reserved_words[function_name], function_buffer, function_buffer_top);
  656. if(err < 0) {
  657. pContext->panic = 1;
  658. return -33;
  659. }
  660. function_buffer_top = 0;
  661. mode = MODE_EXECUTABLE;
  662. goto next_token;
  663. }
  664. function_buffer[function_buffer_top] = current;
  665. function_buffer_top += 1;
  666. break;
  667. }
  668. next_token: i=i;
  669. }
  670. if(mode == MODE_FUNCTION || mode == MODE_DO) {
  671. return -32;
  672. }
  673. return 0;
  674. #undef MODE_EXECUTABLE
  675. #undef MODE_FUNCTION
  676. #undef MODE_DO
  677. #undef LABEL_BUFFER
  678. #undef FUNCTION_BUFFER
  679. }
  680. int ink_step(struct context *pContext) {
  681. struct ink_routine* currentRoutine;
  682. struct stack_frame frame;
  683. struct stack_frame* top;
  684. struct elem next;
  685. int t;
  686. currentRoutine = pContext->routines + pContext->routine_current;
  687. pContext->steps++;
  688. if(currentRoutine->function_stack_top == 0) return 0;
  689. if(pContext->panic) {
  690. return -1;
  691. }
  692. top = &currentRoutine->function_stack[currentRoutine->function_stack_top-1];
  693. t = top->executing.type;
  694. switch(t) {
  695. case INK_NATIVE_FUNCTION:
  696. if(top->index != 0) {
  697. ink_pop_fn(pContext);
  698. } else {
  699. top->index++;
  700. if(pContext->native_words_top <= top->executing.value) {
  701. pContext->panic = 1;
  702. return -1;
  703. }
  704. pContext->native_words[top->executing.value].value(pContext);
  705. }
  706. break;
  707. case INK_FUNCTION:
  708. if(pContext->words_top <= top->executing.value) {
  709. pContext->panic = 1;
  710. return -1;
  711. }
  712. if(top->index >= pContext->words[top->executing.value].size) {
  713. ink_pop_fn(pContext);
  714. } else {
  715. next = pContext->words[top->executing.value].things[top->index];
  716. if(next.type == INK_RETURN) {
  717. ink_pop_fn(pContext);
  718. return 1;
  719. }
  720. frame.executing = next;
  721. frame.index = 0;
  722. t = ink_push_fn(pContext, frame);
  723. if(t < 0) {
  724. pContext->panic = 1;
  725. return -11;
  726. }
  727. top->index++;
  728. }
  729. break;
  730. default:
  731. t = ink_push(pContext, top->executing);
  732. if(t < 0) {
  733. pContext->panic = 1;
  734. return -25;
  735. }
  736. ink_pop_fn(pContext);
  737. break;
  738. }
  739. return 1;
  740. }
  741. void ink_compile(struct context *pContext, const char* buffer) {
  742. int routine, saved, executable_buffer_top;
  743. /* Main function has a size limit of 256 (need to know that for REPL */
  744. struct elem executable_buffer[256];
  745. struct ink_routine* currentRoutine;
  746. int err;
  747. struct stack_frame frame;
  748. char* integer;
  749. size_t integer_size;
  750. char main_fn[32] = "__-MAIN-__";
  751. routine = ink_make_routine(pContext);
  752. saved = pContext->routine_current;
  753. pContext->routine_current = routine;
  754. currentRoutine = pContext->routines + routine;
  755. currentRoutine->stack = NULL;
  756. currentRoutine->top = 0;
  757. currentRoutine->capacity = 0;
  758. err = ink_lex(pContext, buffer);
  759. if(err < 0) {
  760. pContext->panic = 1;
  761. return;
  762. }
  763. executable_buffer_top = 0;
  764. err = ink_parse(pContext, executable_buffer, &executable_buffer_top);
  765. if(err < 0) {
  766. pContext->panic = 1;
  767. return;
  768. }
  769. integer = ink_itoa(pContext, routine);
  770. integer_size = strlen(integer);
  771. memcpy(main_fn+10, integer, integer_size);
  772. pContext->free(integer);
  773. main_fn[10+integer_size] = 0;
  774. frame.executing.value = ink_add_indigenous(pContext, main_fn, executable_buffer, executable_buffer_top);
  775. if(frame.executing.value < 0) {
  776. pContext->panic = 1;
  777. return;
  778. }
  779. frame.executing.type = INK_FUNCTION;
  780. frame.index = 0;
  781. err = ink_push_fn(pContext, frame);
  782. if(err < 0) {
  783. pContext->panic = 1;
  784. return;
  785. }
  786. pContext->routine_current = saved;
  787. return;
  788. }
  789. int ink_can_run(struct context* pContext) {
  790. int it;
  791. for(it = 0; it < pContext->routines_top; ++it) {
  792. if(pContext->routines[it].panic == 0) {
  793. return 1;
  794. }
  795. }
  796. return 0;
  797. }
  798. int ink_step_everyone(struct context* pContext) {
  799. int out;
  800. pContext->routine_current = -1;
  801. for(;;) {
  802. /* Increment to next runnable routine */
  803. do{
  804. ++(pContext->routine_current);
  805. } while(pContext->routine_current < pContext->routines_top && pContext->routines[pContext->routine_current].panic != 0);
  806. /* Exit condition */
  807. if(pContext->routine_current >= pContext->routines_top) break;
  808. /* Kill? */
  809. if(pContext->routines[pContext->routine_current].panic == INK_ROUTINE_SUCCESS) {
  810. ink_kill_routine(pContext, pContext->routine_current);
  811. }
  812. /* Step! */
  813. out = ink_step(pContext);
  814. if(out == 0) {
  815. pContext->routines[pContext->routine_current].panic = INK_ROUTINE_SUCCESS;
  816. } else if(out < 0) {
  817. pContext->routines[pContext->routine_current].panic = out;
  818. }
  819. }
  820. return 0;
  821. }
  822. int ink_new_type(
  823. struct context* ctx,
  824. const char* type_name,
  825. int size,
  826. void (*collect)(struct context*,void*),
  827. struct ink_collection_list (*gc)(struct context*,void*)
  828. ) {
  829. if(ctx->panic) return -128;
  830. /* Resize for push */
  831. if(ctx->types == NULL) {
  832. ctx->types = ctx->inner_malloc(sizeof(struct ink_type) * 8);
  833. ctx->types_top = 0;
  834. ctx->types_capacity = 8;
  835. } else if(ctx->types_top == ctx->types_capacity) {
  836. int new_count;
  837. void* renewed;
  838. new_count = (ctx->types_capacity + ctx->types_capacity/2);
  839. renewed = ctx->inner_realloc(ctx->types, sizeof(struct ink_type) * new_count);
  840. if(renewed == NULL) {
  841. return -129;
  842. } else {
  843. ctx->types = renewed;
  844. ctx->types_capacity = new_count;
  845. }
  846. }
  847. /* Push */
  848. ctx->types[ctx->types_top].name = type_name;
  849. ctx->types[ctx->types_top].element_size = size;
  850. ctx->types[ctx->types_top].elements = NULL;
  851. ctx->types[ctx->types_top].elements_top = 0;
  852. ctx->types[ctx->types_top].elements_capacity = 0;
  853. ctx->types[ctx->types_top].collect = collect;
  854. ctx->types[ctx->types_top].gc = gc;
  855. ctx->types_top++;
  856. /* Satisfying the minimal value requirement */
  857. return ctx->types_top - 1 + 16;
  858. }
  859. static struct element_slab* ink_get_value_link(struct context* ctx, struct elem ref) {
  860. int type_id;
  861. if(ref.type < 16) return NULL;
  862. type_id = ref.type - 16;
  863. if(type_id >= ctx->types_top) return NULL;
  864. if(ctx->types[type_id].element_size == 0) return NULL;
  865. if(ref.value < 0) return NULL;
  866. if(ref.value >= ctx->types[type_id].elements_top) return NULL;
  867. if(! ctx->types[type_id].elements[ref.value].in_use) return NULL;
  868. return ctx->types[type_id].elements + ref.value;
  869. }
  870. void* ink_get_value(struct context* ctx, struct elem ref) {
  871. struct element_slab* s;
  872. s = ink_get_value_link(ctx, ref);
  873. if(s == NULL) return NULL;
  874. return s->data;
  875. }
  876. struct elem ink_make_native(struct context* ctx, int type, void* ptr) {
  877. int type_id;
  878. struct elem ret;
  879. int g, i;
  880. if(type < 16) {
  881. ret.type = 0;
  882. ret.value = -130;
  883. return ret;
  884. }
  885. /* Apply invariant of the user defined types */
  886. type_id = type - 16;
  887. if(type_id >= ctx->types_top) {
  888. ret.type = 0;
  889. ret.value = -129;
  890. return ret;
  891. }
  892. if(ctx->panic) {
  893. ret.type = 0;
  894. ret.value = -135;
  895. return ret;
  896. }
  897. /* Resize for push of value in store */
  898. if(ctx->types[type_id].elements == NULL) {
  899. ctx->types[type_id].elements = ctx->inner_malloc(sizeof(struct element_slab) * 8);
  900. ctx->types[type_id].elements_top = 0;
  901. ctx->types[type_id].elements_capacity = 8;
  902. 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));
  903. } else if(ctx->types[type_id].elements_top == ctx->types[type_id].elements_capacity) {
  904. int new_count;
  905. void* renewed;
  906. new_count = (ctx->types[type_id].elements_capacity + ctx->types[type_id].elements_capacity/2);
  907. renewed = ctx->inner_realloc(ctx->types[type_id].elements, sizeof(struct element_slab) * new_count);
  908. if(renewed == NULL) {
  909. ret.type = 0;
  910. ret.value = -129;
  911. return ret;
  912. } else {
  913. ctx->types[type_id].elements = renewed;
  914. ctx->types[type_id].elements_capacity = new_count;
  915. 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));
  916. }
  917. }
  918. /* Push value in store */
  919. g = ctx->types[type_id].elements_capacity;
  920. for(i = 0; i < g; ++i) {
  921. if(! ctx->types[type_id].elements[i].in_use) {
  922. ctx->types[type_id].elements[i].in_use = 1;
  923. ctx->types[type_id].elements[i].uses = 1;
  924. if(ctx->types[type_id].element_size < 0) {
  925. ctx->types[type_id].elements[i].data = ptr;
  926. } else {
  927. void* new_ptr = ctx->malloc(ctx->types[type_id].element_size);
  928. if(new_ptr == NULL) {
  929. ret.type = 0;
  930. ret.value = -139;
  931. return ret;
  932. }
  933. memcpy(new_ptr, ptr, ctx->types[type_id].element_size);
  934. ctx->types[type_id].elements[i].data = new_ptr;
  935. }
  936. ctx->types[type_id].elements_top = max(ctx->types[type_id].elements_top, i+1);
  937. ret.type = type;
  938. ret.value = i;
  939. return ret;
  940. }
  941. }
  942. ret.type = 0;
  943. ret.value = -140;
  944. return ret;
  945. }
  946. void ink_gc(struct context* ctx) {
  947. int i, j, k;
  948. int marked;
  949. struct element_slab* v;
  950. for(i = 0; i < ctx->types_top; ++i) {
  951. for(j = 0; j < ctx->types[i].elements_top; ++j) {
  952. ctx->types[i].elements[j].uses = 0;
  953. }
  954. }
  955. /* Start by marking the roots of the routines, Clear the routines if possible */
  956. for(i = 0; i < ctx->routines_top; ++i) {
  957. if(ctx->routines[i].panic == INK_ROUTINE_SUCCESS) {
  958. ctx->free(ctx->routines[i].stack);
  959. ctx->free(ctx->routines[i].function_stack);
  960. ctx->routines[i].panic = INK_ROUTINE_CAN_REUSE;
  961. }
  962. if(ctx->routines[i].panic == INK_ROUTINE_CAN_REUSE) {
  963. continue;
  964. }
  965. for(j = 0; j < ctx->routines[i].top; ++j) {
  966. v = ink_get_value_link(ctx, ctx->routines[i].stack[j]);
  967. if(v != NULL) ++v->uses;
  968. }
  969. }
  970. /* TODO: Mark objects contained within function code */
  971. /* Mark the rest of the data */
  972. do {
  973. marked = 0;
  974. for (i = 0; i < ctx->types_top; ++i) {
  975. for (j = 0; j < ctx->types[i].elements_top; ++j) {
  976. /* Only mark from things that are active and detected as in use */
  977. if (ctx->types[i].elements[j].in_use && ctx->types[i].elements[j].uses) {
  978. struct ink_collection_list c;
  979. c = ctx->types[i].gc(ctx, ctx->types[i].elements[j].data);
  980. for (k = 0; k < c.count; ++k) {
  981. v = ink_get_value_link(ctx, c.elements[k]);
  982. /* Never mark twice to avoid infinite loops with e.g. arrays that contain themselves */
  983. if (v != NULL && !v->uses) {
  984. ++v->uses;
  985. marked = 1;
  986. }
  987. }
  988. if (c.elements != NULL) ctx->inner_free(c.elements);
  989. }
  990. }
  991. }
  992. } while(marked);
  993. /* Sweep phase: explore any allocated data and sweep the unused away */
  994. for(i = 0; i < ctx->types_top; ++i) {
  995. for(j = 0; j < ctx->types[i].elements_top; ++j) {
  996. if(ctx->types[i].elements[j].uses == 0 && ctx->types[i].elements[j].in_use) {
  997. ctx->collections++;
  998. ctx->types[i].collect(ctx, ctx->types[i].elements[j].data);
  999. if(ctx->types[i].element_size > 0) {
  1000. ctx->free(ctx->types[i].elements[j].data);
  1001. }
  1002. ctx->types[i].elements[j].data = NULL;
  1003. ctx->types[i].elements[j].uses = 0;
  1004. ctx->types[i].elements[j].in_use = 0;
  1005. }
  1006. }
  1007. }
  1008. }
  1009. /**********************************************************************************************************************/
  1010. static void print_stacktrace(struct context* _) {
  1011. int i;
  1012. struct ink_routine* currentRoutine;
  1013. currentRoutine = _->routines + _->routine_current;
  1014. for(i = 0; i < currentRoutine->function_stack_top; ++i) {
  1015. struct elem thing;
  1016. char *n;
  1017. thing = currentRoutine->function_stack[i].executing;
  1018. switch(thing.type) {
  1019. case INK_NATIVE_FUNCTION: {
  1020. n = _->native_words[thing.value].name;
  1021. while (*n) {
  1022. _->putchar(*n);
  1023. ++n;
  1024. }
  1025. _->putchar(10);
  1026. break;
  1027. }
  1028. case INK_FUNCTION:{
  1029. n = _->words[thing.value].name;
  1030. while (*n) {
  1031. _->putchar(*n);
  1032. ++n;
  1033. }
  1034. _->putchar(':');
  1035. n = ink_itoa(_, currentRoutine->function_stack[i].index);
  1036. while (*n) {
  1037. _->putchar(*n);
  1038. ++n;
  1039. }
  1040. _->putchar(10);
  1041. break;
  1042. }
  1043. default:
  1044. break;
  1045. }
  1046. }
  1047. }
  1048. static void add_int(struct context* ctx) {
  1049. struct ink_routine* currentRoutine;
  1050. struct elem a;
  1051. struct elem b;
  1052. currentRoutine = ctx->routines + ctx->routine_current;
  1053. if(currentRoutine->top < 2) {
  1054. currentRoutine->panic = -1;
  1055. return;
  1056. }
  1057. a = currentRoutine->stack[currentRoutine->top-1];
  1058. b = currentRoutine->stack[currentRoutine->top-2];
  1059. if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) {
  1060. ctx->panic = 1;
  1061. return;
  1062. }
  1063. ink_pop(ctx);
  1064. currentRoutine->stack[currentRoutine->top-1].value = a.value + b.value;
  1065. }
  1066. static void sub_int(struct context* ctx) {
  1067. struct ink_routine* currentRoutine;
  1068. struct elem a;
  1069. struct elem b;
  1070. currentRoutine = ctx->routines + ctx->routine_current;
  1071. if(currentRoutine->top < 2) {
  1072. currentRoutine->panic = -1;
  1073. return;
  1074. }
  1075. a = currentRoutine->stack[currentRoutine->top-1];
  1076. b = currentRoutine->stack[currentRoutine->top-2];
  1077. if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) {
  1078. currentRoutine->panic = -1;
  1079. return;
  1080. }
  1081. ink_pop(ctx);
  1082. currentRoutine->stack[currentRoutine->top-1].value = b.value - a.value;
  1083. }
  1084. static void mult_int(struct context* ctx) {
  1085. struct ink_routine* currentRoutine;
  1086. struct elem a;
  1087. struct elem b;
  1088. currentRoutine = ctx->routines + ctx->routine_current;
  1089. if(currentRoutine->top < 2) {
  1090. currentRoutine->panic = -1;
  1091. return;
  1092. }
  1093. a = currentRoutine->stack[currentRoutine->top-1];
  1094. b = currentRoutine->stack[currentRoutine->top-2];
  1095. if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) {
  1096. currentRoutine->panic = -1;
  1097. return;
  1098. }
  1099. ink_pop(ctx);
  1100. currentRoutine->stack[currentRoutine->top-1].value = b.value * a.value;
  1101. }
  1102. static void div_int(struct context* ctx) {
  1103. struct ink_routine* currentRoutine;
  1104. struct elem a;
  1105. struct elem b;
  1106. currentRoutine = ctx->routines + ctx->routine_current;
  1107. if(currentRoutine->top < 2) {
  1108. currentRoutine->panic = -1;
  1109. return;
  1110. }
  1111. a = currentRoutine->stack[currentRoutine->top-1];
  1112. b = currentRoutine->stack[currentRoutine->top-2];
  1113. if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) {
  1114. currentRoutine->panic = -1;
  1115. return;
  1116. }
  1117. ink_pop(ctx);
  1118. currentRoutine->stack[currentRoutine->top-1].value = b.value / a.value;
  1119. }
  1120. static void is_equal(struct context* ctx) {
  1121. struct ink_routine* currentRoutine;
  1122. struct elem a;
  1123. struct elem b;
  1124. struct elem ret;
  1125. currentRoutine = ctx->routines + ctx->routine_current;
  1126. if(currentRoutine->top < 2) {
  1127. currentRoutine->panic = -1;
  1128. return;
  1129. }
  1130. a = currentRoutine->stack[currentRoutine->top-1];
  1131. b = currentRoutine->stack[currentRoutine->top-2];
  1132. ink_pop(ctx);
  1133. ink_pop(ctx);
  1134. ret.type = INK_INTEGER;
  1135. ret.value = a.value == b.value && a.type == b.type;
  1136. ink_push(ctx, ret);
  1137. }
  1138. static void is_different(struct context* ctx) {
  1139. struct ink_routine* currentRoutine;
  1140. struct elem a;
  1141. struct elem b;
  1142. struct elem ret;
  1143. currentRoutine = ctx->routines + ctx->routine_current;
  1144. if(currentRoutine->top < 2) {
  1145. currentRoutine->panic = -1;
  1146. return;
  1147. }
  1148. a = currentRoutine->stack[currentRoutine->top-1];
  1149. b = currentRoutine->stack[currentRoutine->top-2];
  1150. ink_pop(ctx);
  1151. ink_pop(ctx);
  1152. ret.type = INK_INTEGER;
  1153. ret.value = !(a.value == b.value && a.type == b.type);
  1154. ink_push(ctx, ret);
  1155. }
  1156. #ifndef NOEXTRAARITHMETIC
  1157. static void rem_int(struct context* ctx) {
  1158. struct ink_routine* currentRoutine;
  1159. struct elem a;
  1160. struct elem b;
  1161. currentRoutine = ctx->routines + ctx->routine_current;
  1162. if(currentRoutine->top < 2) {
  1163. currentRoutine->panic = -1;
  1164. return;
  1165. }
  1166. a = currentRoutine->stack[currentRoutine->top-1];
  1167. b = currentRoutine->stack[currentRoutine->top-2];
  1168. if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) {
  1169. currentRoutine->panic = -1;
  1170. return;
  1171. }
  1172. ink_pop(ctx);
  1173. currentRoutine->stack[currentRoutine->top-1].value = b.value % a.value;
  1174. }
  1175. static void gt_int(struct context* ctx) {
  1176. struct ink_routine* currentRoutine;
  1177. struct elem a;
  1178. struct elem b;
  1179. currentRoutine = ctx->routines + ctx->routine_current;
  1180. if(currentRoutine->top < 2) {
  1181. currentRoutine->panic = -1;
  1182. return;
  1183. }
  1184. a = currentRoutine->stack[currentRoutine->top-1];
  1185. b = currentRoutine->stack[currentRoutine->top-2];
  1186. if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) {
  1187. currentRoutine->panic = -1;
  1188. return;
  1189. }
  1190. ink_pop(ctx);
  1191. currentRoutine->stack[currentRoutine->top-1].value = b.value > a.value;
  1192. }
  1193. static void gte_int(struct context* ctx) {
  1194. struct ink_routine* currentRoutine;
  1195. struct elem a;
  1196. struct elem b;
  1197. currentRoutine = ctx->routines + ctx->routine_current;
  1198. if(currentRoutine->top < 2) {
  1199. currentRoutine->panic = -1;
  1200. return;
  1201. }
  1202. a = currentRoutine->stack[currentRoutine->top-1];
  1203. b = currentRoutine->stack[currentRoutine->top-2];
  1204. if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) {
  1205. currentRoutine->panic = -1;
  1206. return;
  1207. }
  1208. ink_pop(ctx);
  1209. currentRoutine->stack[currentRoutine->top-1].value = b.value >= a.value;
  1210. }
  1211. static void lte_int(struct context* ctx) {
  1212. struct ink_routine* currentRoutine;
  1213. struct elem a;
  1214. struct elem b;
  1215. currentRoutine = ctx->routines + ctx->routine_current;
  1216. if(currentRoutine->top < 2) {
  1217. currentRoutine->panic = -1;
  1218. return;
  1219. }
  1220. a = currentRoutine->stack[currentRoutine->top-1];
  1221. b = currentRoutine->stack[currentRoutine->top-2];
  1222. if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) {
  1223. currentRoutine->panic = -1;
  1224. return;
  1225. }
  1226. ink_pop(ctx);
  1227. currentRoutine->stack[currentRoutine->top-1].value = b.value <= a.value;
  1228. }
  1229. #endif // NOEXTRAARITHMETIC
  1230. static void lt_int(struct context* ctx) {
  1231. struct ink_routine* currentRoutine;
  1232. struct elem a;
  1233. struct elem b;
  1234. currentRoutine = ctx->routines + ctx->routine_current;
  1235. if(currentRoutine->top < 2) {
  1236. currentRoutine->panic = -1;
  1237. return;
  1238. }
  1239. a = currentRoutine->stack[currentRoutine->top-1];
  1240. b = currentRoutine->stack[currentRoutine->top-2];
  1241. if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) {
  1242. currentRoutine->panic = -1;
  1243. return;
  1244. }
  1245. ink_pop(ctx);
  1246. currentRoutine->stack[currentRoutine->top-1].value = b.value < a.value;
  1247. }
  1248. static void dupe_elem(struct context* ctx) {
  1249. struct ink_routine* currentRoutine;
  1250. struct elem a;
  1251. int err;
  1252. currentRoutine = ctx->routines + ctx->routine_current;
  1253. if(currentRoutine->top < 1) {
  1254. ctx->panic = 1;
  1255. return;
  1256. }
  1257. a = currentRoutine->stack[currentRoutine->top-1];
  1258. err = ink_push(ctx, a);
  1259. if(err < 0) ctx->panic = 1;
  1260. }
  1261. static void drop_elem(struct context* ctx) {
  1262. struct ink_routine* currentRoutine;
  1263. currentRoutine = ctx->routines + ctx->routine_current;
  1264. if(currentRoutine->top < 1) {
  1265. ctx->panic = 1;
  1266. return;
  1267. }
  1268. ink_pop(ctx);
  1269. }
  1270. static void pluck_elem(struct context* ctx) {
  1271. struct ink_routine* currentRoutine;
  1272. struct elem a;
  1273. int position, err;
  1274. currentRoutine = ctx->routines + ctx->routine_current;
  1275. if(currentRoutine->top < 1) {
  1276. currentRoutine->panic = -1;
  1277. return;
  1278. }
  1279. a = currentRoutine->stack[currentRoutine->top-1];
  1280. if(a.type != INK_INTEGER) {
  1281. ctx->panic = 1;
  1282. return;
  1283. }
  1284. position = currentRoutine->top - (a.value + 1);
  1285. if(position >= currentRoutine->top || position < 0) {
  1286. ctx->panic = 1;
  1287. return;
  1288. }
  1289. ink_pop(ctx);
  1290. err = ink_push(ctx, currentRoutine->stack[position]);
  1291. if(err < 0) ctx->panic = 1;
  1292. }
  1293. static void swap_elem(struct context* ctx) {
  1294. struct ink_routine* currentRoutine;
  1295. struct elem a;
  1296. struct elem b;
  1297. currentRoutine = ctx->routines + ctx->routine_current;
  1298. if(currentRoutine->top < 2) {
  1299. currentRoutine->panic = -1;
  1300. return;
  1301. }
  1302. a = currentRoutine->stack[currentRoutine->top-1];
  1303. b = currentRoutine->stack[currentRoutine->top-2];
  1304. currentRoutine->stack[currentRoutine->top-2] = a;
  1305. currentRoutine->stack[currentRoutine->top-1] = b;
  1306. }
  1307. static void return_if(struct context* ctx) {
  1308. struct ink_routine* currentRoutine;
  1309. struct elem a;
  1310. currentRoutine = ctx->routines + ctx->routine_current;
  1311. if(currentRoutine->top < 1) {
  1312. ctx->panic = -1;
  1313. return;
  1314. }
  1315. a = currentRoutine->stack[currentRoutine->top-1];
  1316. if(a.type != INK_INTEGER) {
  1317. ctx->panic = 1;
  1318. return;
  1319. }
  1320. if(a.value) {
  1321. ink_pop_fn(ctx);
  1322. ink_pop_fn(ctx);
  1323. }
  1324. ink_pop(ctx);
  1325. return;
  1326. }
  1327. static void jump_if(struct context* ctx) {
  1328. struct ink_routine* currentRoutine;
  1329. struct elem label;
  1330. struct elem condition;
  1331. currentRoutine = ctx->routines + ctx->routine_current;
  1332. if(currentRoutine->top < 2) {
  1333. ctx->panic = -1;
  1334. return;
  1335. }
  1336. label = currentRoutine->stack[currentRoutine->top-1];
  1337. condition = currentRoutine->stack[currentRoutine->top-2];
  1338. if(label.type != INK_INTEGER || condition.type != INK_INTEGER) {
  1339. ctx->panic = -1;
  1340. return;
  1341. }
  1342. ink_pop(ctx);
  1343. ink_pop(ctx);
  1344. ink_pop_fn(ctx);
  1345. if(condition.value) {
  1346. currentRoutine->function_stack[currentRoutine->function_stack_top - 1].index += label.value - 2;
  1347. }
  1348. return;
  1349. }
  1350. static void print_int(struct context* ctx) {
  1351. struct ink_routine* currentRoutine;
  1352. struct elem a;
  1353. char* n;
  1354. char* str;
  1355. currentRoutine = ctx->routines + ctx->routine_current;
  1356. if(currentRoutine->top < 1 || currentRoutine->stack[currentRoutine->top-1].type != INK_INTEGER) {
  1357. currentRoutine->panic = -1;
  1358. return;
  1359. }
  1360. a = currentRoutine->stack[currentRoutine->top-1];
  1361. ink_pop(ctx);
  1362. n = ink_itoa(ctx, a.value);
  1363. str = n;
  1364. while (*str) {
  1365. ctx->putchar(*str);
  1366. ++str;
  1367. }
  1368. ctx->free(n);
  1369. }
  1370. static void print_as_utf8(struct context* ctx) {
  1371. struct ink_routine* currentRoutine;
  1372. struct elem a;
  1373. currentRoutine = ctx->routines + ctx->routine_current;
  1374. if(currentRoutine->top < 1 || currentRoutine->stack[currentRoutine->top-1].type != INK_INTEGER) {
  1375. ctx->panic = -1;
  1376. return;
  1377. }
  1378. a = currentRoutine->stack[currentRoutine->top-1];
  1379. if(a.value <= 0x7F) {
  1380. ctx->putchar(a.value);
  1381. } else if(a.value <= 0x7FF) {
  1382. ctx->putchar(((a.value & 0xFC0) >> 6) | 192);
  1383. ctx->putchar((a.value & 0x3F) | 128);
  1384. } else if(a.value <= 0xFFFF) {
  1385. ctx->putchar(((a.value & 0x3F000) >> 12) | 224);
  1386. ctx->putchar(((a.value & 0xFC0) >> 6) | 128);
  1387. ctx->putchar((a.value & 0x3F) | 128);
  1388. } else if(a.value <= 0x10FFFF) {
  1389. ctx->putchar(((a.value & 0x3C0000) >> 18) | 240);
  1390. ctx->putchar(((a.value & 0x3F000) >> 12) | 128);
  1391. ctx->putchar(((a.value & 0xFC0) >> 6) | 128);
  1392. ctx->putchar((a.value & 0x3F) | 128);
  1393. } else {
  1394. ctx->panic = -1;
  1395. return;
  1396. }
  1397. ink_pop(ctx);
  1398. }
  1399. static int get_type_by_name(struct context* ctx, const char* name) {
  1400. int i;
  1401. for(i = 0; i < ctx->types_top; ++i) {
  1402. if(strcmp(ctx->types[i].name, name) == 0) {
  1403. return i + 16;
  1404. }
  1405. }
  1406. return -1;
  1407. }
  1408. static void run_gc(struct context* ctx) {
  1409. ink_gc(ctx);
  1410. }
  1411. static void clear_stack(struct context* ctx) {
  1412. struct ink_routine* currentRoutine;
  1413. currentRoutine = ctx->routines + ctx->routine_current;
  1414. while (currentRoutine->top >= 1) {
  1415. ink_pop(ctx);
  1416. }
  1417. return;
  1418. }
  1419. static void collect_noop(struct context* _1, void* _2) {}
  1420. static struct ink_collection_list gc_noop(struct context* _1, void* _2) {
  1421. struct ink_collection_list c;
  1422. c.elements = NULL;
  1423. c.count = 0;
  1424. return c;
  1425. }
  1426. #ifndef NOARRAYLIB
  1427. struct ink_array {
  1428. int top;
  1429. int capacity;
  1430. struct elem* elements;
  1431. };
  1432. static void collect_array(struct context* ctx, void* array) {
  1433. struct ink_array* ary;
  1434. ary = array;
  1435. if(ary->elements != NULL) ctx->free(ary->elements);
  1436. }
  1437. static struct ink_collection_list gc_array(struct context* ctx, void* array) {
  1438. struct ink_array* ary;
  1439. struct ink_collection_list c;
  1440. ary = array;
  1441. c.elements = ctx->inner_malloc(sizeof(struct elem)*ary->top);
  1442. c.count = ary->top;
  1443. memcpy(c.elements, ary->elements, sizeof(struct elem)*ary->top);
  1444. return c;
  1445. }
  1446. static void new_array(struct context* ctx) {
  1447. int tid;
  1448. struct elem e;
  1449. struct ink_array ary;
  1450. tid = get_type_by_name(ctx, "array");
  1451. ary.elements = NULL;
  1452. ary.top = 0;
  1453. ary.capacity = 0;
  1454. e = ink_make_native(ctx, tid, &ary);
  1455. ink_push(ctx, e);
  1456. }
  1457. static void push_array_stack_delim(struct context* ctx) {
  1458. int tid;
  1459. struct elem e;
  1460. tid = get_type_by_name(ctx, "array_marker");
  1461. e.type = tid;
  1462. e.value = 0;
  1463. ink_push(ctx, e);
  1464. }
  1465. static void array_push(struct context* ctx, struct ink_routine* currentRoutine, struct ink_array* ary, struct elem value) {
  1466. if(ary->elements == NULL) {
  1467. ary->elements = ctx->malloc(sizeof(struct elem) * 8);
  1468. ary->top = 0;
  1469. ary->capacity = 8;
  1470. } else if(ary->top == ary->capacity) {
  1471. int new_count;
  1472. void* renewed;
  1473. new_count = (ary->capacity + ary->capacity/2);
  1474. renewed = ctx->realloc(ary->elements, sizeof(struct elem) * new_count);
  1475. if(renewed == NULL) {
  1476. currentRoutine->panic = -1;
  1477. return;
  1478. } else {
  1479. ary->elements = renewed;
  1480. ary->capacity = new_count;
  1481. }
  1482. }
  1483. ary->elements[ary->top] = value;
  1484. ary->top++;
  1485. }
  1486. static void push_array(struct context* ctx) {
  1487. int tid;
  1488. struct elem a;
  1489. struct ink_routine* currentRoutine;
  1490. struct ink_array* ary;
  1491. tid = get_type_by_name(ctx, "array");
  1492. currentRoutine = ctx->routines + ctx->routine_current;
  1493. if(currentRoutine->top < 2 || currentRoutine->stack[currentRoutine->top-1].type != tid) {
  1494. currentRoutine->panic = -1;
  1495. return;
  1496. }
  1497. a = currentRoutine->stack[currentRoutine->top-1];
  1498. ary= ink_get_value(ctx, a);
  1499. if(ary == NULL) {
  1500. currentRoutine->panic = -1;
  1501. return;
  1502. }
  1503. ink_pop(ctx);
  1504. array_push(ctx, currentRoutine, ary, currentRoutine->stack[currentRoutine->top-1]);
  1505. ink_pop(ctx);
  1506. }
  1507. static void push_delimited_array(struct context* ctx) {
  1508. int tid, idx, counter, i;
  1509. struct elem a;
  1510. struct ink_routine* currentRoutine;
  1511. struct ink_array* ary;
  1512. tid = get_type_by_name(ctx, "array_marker");
  1513. currentRoutine = ctx->routines + ctx->routine_current;
  1514. if(currentRoutine->top < 1) {
  1515. currentRoutine->panic = -1;
  1516. return;
  1517. }
  1518. new_array(ctx);
  1519. a = currentRoutine->stack[currentRoutine->top-1];
  1520. ink_pop(ctx);
  1521. ary= ink_get_value(ctx, a);
  1522. for(idx = 1; idx <= currentRoutine->top; ++idx) {
  1523. struct elem maybe_delim;
  1524. if(currentRoutine->stack[currentRoutine->top-idx].type == tid) {
  1525. break;
  1526. }
  1527. }
  1528. /* Save for cleanup */
  1529. counter = idx;
  1530. /* Don't copy the delimiter */
  1531. idx -= 1;
  1532. ary->elements = malloc(sizeof(struct elem) * idx);
  1533. if(ary->elements == NULL) {
  1534. currentRoutine->panic = -541;
  1535. return;
  1536. }
  1537. ary->capacity = idx;
  1538. ary->top = 0;
  1539. /* Copy the data */
  1540. for(i = currentRoutine->top - idx; i < currentRoutine->top; ++i) {
  1541. ary->elements[ary->top] = currentRoutine->stack[i];
  1542. ++(ary->top);
  1543. }
  1544. /* Cleanup */
  1545. while(counter--) {
  1546. ink_pop(ctx);
  1547. }
  1548. /* Pop the marker too */
  1549. ink_pop(ctx);
  1550. /* Put value in place */
  1551. ink_push(ctx, a);
  1552. }
  1553. static void index_array(struct context* ctx) {
  1554. int tid;
  1555. struct ink_routine *currentRoutine;
  1556. struct elem a;
  1557. struct ink_array *ary;
  1558. struct elem idx;
  1559. tid = get_type_by_name(ctx, "array");
  1560. currentRoutine = ctx->routines + ctx->routine_current;
  1561. if (currentRoutine->top < 2 || currentRoutine->stack[currentRoutine->top - 1].type != tid || currentRoutine->stack[currentRoutine->top - 2].type != INK_INTEGER) {
  1562. currentRoutine->panic = -1;
  1563. return;
  1564. }
  1565. a = currentRoutine->stack[currentRoutine->top - 1];
  1566. ary = ink_get_value(ctx, a);
  1567. if (ary == NULL) {
  1568. currentRoutine->panic = -1;
  1569. return;
  1570. }
  1571. ink_pop(ctx);
  1572. idx = currentRoutine->stack[currentRoutine->top - 1];
  1573. ink_pop(ctx);
  1574. if(ary->top <= idx.value) {
  1575. currentRoutine->panic = -1;
  1576. return;
  1577. }
  1578. ink_push(ctx, ary->elements[idx.value]);
  1579. }
  1580. static void set_array(struct context* ctx) {
  1581. int tid;
  1582. struct ink_routine *currentRoutine;
  1583. struct elem a;
  1584. struct ink_array *ary;
  1585. struct elem idx;
  1586. struct elem value;
  1587. tid = get_type_by_name(ctx, "array");
  1588. currentRoutine = ctx->routines + ctx->routine_current;
  1589. if (currentRoutine->top < 3 || currentRoutine->stack[currentRoutine->top - 1].type != tid || currentRoutine->stack[currentRoutine->top - 2].type != INK_INTEGER) {
  1590. currentRoutine->panic = -1;
  1591. return;
  1592. }
  1593. a = currentRoutine->stack[currentRoutine->top - 1];
  1594. ary = ink_get_value(ctx, a);
  1595. if (ary == NULL) {
  1596. currentRoutine->panic = -1;
  1597. return;
  1598. }
  1599. idx = currentRoutine->stack[currentRoutine->top - 2];
  1600. value = currentRoutine->stack[currentRoutine->top - 3];
  1601. if(ary->top <= idx.value) {
  1602. currentRoutine->panic = -1;
  1603. return;
  1604. }
  1605. ink_pop(ctx);
  1606. ink_pop(ctx);
  1607. ink_pop(ctx);
  1608. ary->elements[idx.value] = value;
  1609. }
  1610. static void get_size_array(struct context* ctx) {
  1611. int tid;
  1612. struct ink_routine *currentRoutine;
  1613. struct elem a;
  1614. struct ink_array *ary;
  1615. struct elem sz;
  1616. tid = get_type_by_name(ctx, "array");
  1617. currentRoutine = ctx->routines + ctx->routine_current;
  1618. if (currentRoutine->top < 1 || currentRoutine->stack[currentRoutine->top - 1].type != tid) {
  1619. currentRoutine->panic = -1;
  1620. return;
  1621. }
  1622. a = currentRoutine->stack[currentRoutine->top - 1];
  1623. ary = ink_get_value(ctx, a);
  1624. if (ary == NULL) {
  1625. currentRoutine->panic = -1;
  1626. return;
  1627. }
  1628. ink_pop(ctx);
  1629. sz.type = INK_INTEGER;
  1630. sz.value = ary->top;
  1631. ink_push(ctx, sz);
  1632. }
  1633. static void print_array_of_codepoints(struct context* ctx) {
  1634. int tid, i;
  1635. struct ink_routine *currentRoutine;
  1636. struct elem a;
  1637. struct ink_array *ary;
  1638. struct elem idx;
  1639. tid = get_type_by_name(ctx, "array");
  1640. currentRoutine = ctx->routines + ctx->routine_current;
  1641. if (currentRoutine->top < 1 || currentRoutine->stack[currentRoutine->top - 1].type != tid) {
  1642. currentRoutine->panic = -1;
  1643. return;
  1644. }
  1645. a = currentRoutine->stack[currentRoutine->top - 1];
  1646. ary = ink_get_value(ctx, a);
  1647. for(i = 0; i < ary->top; ++i) {
  1648. if(ary->elements[i].type != INK_INTEGER) {
  1649. currentRoutine->panic = -1;
  1650. return;
  1651. }
  1652. }
  1653. ink_pop(ctx);
  1654. for(i = 0; i < ary->top; ++i) {
  1655. ink_push(ctx, ary->elements[i]);
  1656. print_as_utf8(ctx);
  1657. }
  1658. }
  1659. static void arrayify_stack(struct context* ctx) {
  1660. struct ink_routine* currentRoutine;
  1661. struct elem array_ref;
  1662. struct ink_array* ary;
  1663. int idx;
  1664. currentRoutine = ctx->routines + ctx->routine_current;
  1665. new_array(ctx);
  1666. if(currentRoutine->panic < 0) return;
  1667. array_ref = currentRoutine->stack[currentRoutine->top - 1];
  1668. ary = ink_get_value(ctx, array_ref);
  1669. if(ary == NULL) {
  1670. currentRoutine->panic = -717;
  1671. return;
  1672. }
  1673. ink_pop(ctx);
  1674. for(idx = 0; idx < currentRoutine->top; ++idx) {
  1675. array_push(ctx, currentRoutine, ary, currentRoutine->stack[idx]);
  1676. }
  1677. while (currentRoutine->top > 0) {
  1678. ink_pop(ctx);
  1679. }
  1680. ink_push(ctx, array_ref);
  1681. return;
  1682. }
  1683. #endif // NOARRAYLIB
  1684. int ink_std_library(struct context* ctx) {
  1685. int v;
  1686. v = 0;
  1687. v += ink_add_native(ctx, "sys.trace", print_stacktrace);
  1688. v += ink_add_native(ctx, "sys.gc", run_gc);
  1689. v += ink_add_native(ctx, "print_int", print_int);
  1690. v += ink_add_native(ctx, "print_utf8", print_as_utf8);
  1691. v += ink_add_native(ctx, "+", add_int);
  1692. v += ink_add_native(ctx, "-", sub_int);
  1693. v += ink_add_native(ctx, "*", mult_int);
  1694. v += ink_add_native(ctx, "/", div_int);
  1695. v += ink_add_native(ctx, "==", is_equal);
  1696. v += ink_add_native(ctx, "!=", is_different);
  1697. v += ink_add_native(ctx, "<", lt_int);
  1698. v += ink_add_native(ctx, "swap", swap_elem);
  1699. v += ink_add_native(ctx, "dup", dupe_elem);
  1700. v += ink_add_native(ctx, "drop", drop_elem);
  1701. v += ink_add_native(ctx, "stack.clear", clear_stack);
  1702. v += ink_add_native(ctx, "pluck", pluck_elem);
  1703. v += ink_add_native(ctx, "return_if", return_if);
  1704. v += ink_add_native(ctx, "jump_if", jump_if);
  1705. #ifndef NOEXTRAARITHMETIC
  1706. v += ink_add_native(ctx, ">", gt_int);
  1707. v += ink_add_native(ctx, ">=", gte_int);
  1708. v += ink_add_native(ctx, "=<", lte_int);
  1709. v += ink_add_native(ctx, "%", rem_int);
  1710. #endif // NOEXTRAARITHMETIC
  1711. #ifndef NOARRAYLIB
  1712. ink_new_type(ctx, "array", sizeof(struct ink_array), collect_array, gc_array);
  1713. ink_new_type(ctx, "array_marker", 0, collect_noop, gc_noop);
  1714. v += ink_add_native(ctx, "[", push_array_stack_delim);
  1715. v += ink_add_native(ctx, "]", push_delimited_array);
  1716. v += ink_add_native(ctx, "array.new", new_array);
  1717. v += ink_add_native(ctx, "array.push", push_array);
  1718. v += ink_add_native(ctx, "array.index", index_array);
  1719. v += ink_add_native(ctx, "array.set", set_array);
  1720. v += ink_add_native(ctx, "array.size", get_size_array);
  1721. v += ink_add_native(ctx, "array.print_utf8", print_array_of_codepoints);
  1722. v += ink_add_native(ctx, "stack.to_array", arrayify_stack);
  1723. #endif // NOARRAYLIB
  1724. return v;
  1725. }