A minimalistic programming language written in C89.
Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

1388 Zeilen
37 KiB

vor 5 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
vor 6 Monaten
  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 = 0;
  31. while(*(c++)) {
  32. j++;
  33. }
  34. return j;
  35. }
  36. static void* memcpy(void* _dest, const void* _src, size_t sz) {
  37. char* dest = _dest;
  38. const char* src = _src;
  39. while(sz--) {
  40. *(dest++) = *(src++);
  41. }
  42. return dest;
  43. }
  44. static int strcmp(const char* dest, const char* src) {
  45. while(*dest != 0 && *src != 0) {
  46. if(*(dest++) != *(src++)) {
  47. return 1;
  48. }
  49. }
  50. return 0;
  51. }
  52. static void* memmove(void* _dest, const void* _src, size_t sz) {
  53. char* dest = _dest;
  54. const char* src = _src;
  55. if (src < dest) {
  56. src += sz;
  57. dest += sz;
  58. while (sz-- > 0) {
  59. *--dest = *--src;
  60. }
  61. } else {
  62. while (sz-- > 0) {
  63. *dest++ = *src++;
  64. }
  65. }
  66. return dest;
  67. }
  68. static void* memset(void* _dest, int src, size_t sz) {
  69. char* dest = _dest;
  70. while(sz--) {
  71. *(dest++) = src++;
  72. }
  73. return dest;
  74. }
  75. static int isspace(int d) {
  76. return d == ' ' || d == '\t' || d == '\n';
  77. }
  78. static int isdigit(int d) {
  79. return '0' <= d && d <= '9';
  80. }
  81. static int atoi(const char* c) {
  82. int ret = 0;
  83. while(*c) {
  84. ret *= 10;
  85. ret += *c - '0';
  86. ++c;
  87. }
  88. return ret;
  89. }
  90. #endif
  91. int ink_add_native(struct context* ctx, const char* name, void(*value)(struct context*)) {
  92. if(ctx->native_words == NULL) {
  93. ctx->native_words = ctx->inner_malloc(sizeof(struct native_fn) * 8);
  94. ctx->native_words_top = 0;
  95. ctx->native_words_capacity = 8;
  96. } else if(ctx->native_words_top == ctx->native_words_capacity) {
  97. int new_count = (ctx->native_words_capacity + ctx->native_words_capacity/2);
  98. void* renewed = ctx->inner_realloc(ctx->native_words, sizeof(struct native_fn) * new_count);
  99. if(renewed == NULL) {
  100. return -3;
  101. } else {
  102. ctx->native_words = renewed;
  103. ctx->native_words_capacity = new_count;
  104. }
  105. }
  106. int len = strlen(name);
  107. char* copy = ctx->inner_malloc(len+1);
  108. if(copy == NULL) {
  109. return -4;
  110. }
  111. memcpy(copy, name, len);
  112. copy[len] = 0;
  113. ctx->native_words[ctx->native_words_top].value = value;
  114. ctx->native_words[ctx->native_words_top].name = copy;
  115. ctx->native_words_top++;
  116. return 0;
  117. }
  118. static int ink_add_indigenous(struct context* ctx, const char* name, struct elem* m, size_t count) {
  119. if(ctx->words == NULL) {
  120. ctx->words = ctx->malloc(sizeof(struct fn) * 8);
  121. ctx->words_top = 0;
  122. ctx->words_capacity = 8;
  123. } else if(ctx->words_top == ctx->words_capacity) {
  124. int new_count = (ctx->words_capacity + ctx->words_capacity/2);
  125. void* renewed = ctx->realloc(ctx->words, sizeof(struct native_fn) * new_count);
  126. if(renewed == NULL) {
  127. return -1;
  128. } else {
  129. ctx->words = renewed;
  130. ctx->words_capacity = new_count;
  131. }
  132. }
  133. int i;
  134. for(i = 0; i < ctx->words_top; ++i) {
  135. if(strcmp(name, ctx->words[i].name) == 0) {
  136. ctx->free(ctx->words[i].things);
  137. ctx->words[i].things = ctx->malloc(sizeof(struct elem) * count);
  138. memcpy(ctx->words[i].things, m, sizeof(struct elem) * count);
  139. ctx->words[i].size = count;
  140. return i;
  141. }
  142. }
  143. int len = strlen(name);
  144. char* copy = ctx->malloc(len+1);
  145. if(copy == NULL) {
  146. return -2;
  147. }
  148. memcpy(copy, name, len);
  149. copy[len] = 0;
  150. ctx->words[ctx->words_top].things = ctx->malloc(sizeof(struct elem) * count);
  151. memcpy(ctx->words[ctx->words_top].things, m, sizeof(struct elem) * count);
  152. ctx->words[ctx->words_top].size = count;
  153. ctx->words[ctx->words_top].name = copy;
  154. return ctx->words_top++;
  155. }
  156. static int ink_add_lex_string(struct context* ctx, const char* name) {
  157. int i;
  158. if(ctx->lex_reserved_words == NULL) {
  159. ctx->lex_reserved_words = ctx->inner_malloc(sizeof(char*) * 8);
  160. ctx->lex_reserved_words_top = 0;
  161. ctx->lex_reserved_words_capacity = 8;
  162. } else if(ctx->lex_reserved_words_top == ctx->lex_reserved_words_capacity) {
  163. int new_count = (ctx->lex_reserved_words_capacity + ctx->lex_reserved_words_capacity/2);
  164. void* renewed = ctx->inner_realloc(ctx->lex_reserved_words, sizeof(struct native_fn) * new_count);
  165. if(renewed == NULL) {
  166. return -5;
  167. } else {
  168. ctx->lex_reserved_words = renewed;
  169. ctx->lex_reserved_words_capacity = new_count;
  170. }
  171. }
  172. for(i = 0; i < ctx->lex_reserved_words_top; i++) {
  173. if(strcmp(ctx->lex_reserved_words[i], name) == 0) {
  174. return i;
  175. }
  176. }
  177. int len = strlen(name);
  178. i = ctx->lex_reserved_words_top;
  179. ctx->lex_reserved_words[i] = ctx->malloc(len+1);
  180. memcpy(ctx->lex_reserved_words[i], name, len);
  181. ctx->lex_reserved_words[i][len] = 0;
  182. ctx->lex_reserved_words_top++;
  183. return i;
  184. }
  185. int ink_push(struct context* ctx, struct elem value) {
  186. if(ctx->routine_current >= ctx->routines_top) return -65;
  187. struct ink_routine* current = ctx->routines + ctx->routine_current;
  188. if(current->stack == NULL) {
  189. current->stack = ctx->malloc(sizeof(struct elem) * 8);
  190. current->top = 0;
  191. current->capacity = 8;
  192. } else if(current->top == current->capacity) {
  193. int new_count = (current->capacity + current->capacity/2);
  194. void* renewed = ctx->realloc(current->stack, sizeof(struct elem) * new_count);
  195. if(renewed == NULL) {
  196. return -18;
  197. } else {
  198. current->stack = renewed;
  199. current->capacity = new_count;
  200. }
  201. }
  202. current->stack[current->top] = value;
  203. current->top++;
  204. return 0;
  205. }
  206. int ink_push_fn(struct context* ctx, struct stack_frame value) {
  207. if(ctx->routine_current >= ctx->routines_top) return -55;
  208. struct ink_routine* current = ctx->routines + ctx->routine_current;
  209. if(current->panic) return -56;
  210. if(current->function_stack == NULL) {
  211. current->function_stack = ctx->malloc(sizeof(struct stack_frame) * 8);
  212. current->function_stack_top = 0;
  213. current->function_stack_capacity = 8;
  214. } else if(current->function_stack_top == current->function_stack_capacity) {
  215. int new_count = (current->function_stack_capacity + current->function_stack_capacity/2);
  216. void* renewed = ctx->realloc(current->function_stack, sizeof(struct stack_frame) * new_count);
  217. if(renewed == NULL) {
  218. return -9;
  219. } else {
  220. current->function_stack = renewed;
  221. current->function_stack_capacity = new_count;
  222. }
  223. }
  224. current->function_stack[current->function_stack_top] = value;
  225. current->function_stack_top++;
  226. return 0;
  227. }
  228. void ink_pop_fn(struct context* ctx) {
  229. if(ctx->routine_current >= ctx->routines_top) return;
  230. if(ctx->routines[ctx->routine_current].panic) return;
  231. if(ctx->routines[ctx->routine_current].function_stack == NULL) return;
  232. if(ctx->routines[ctx->routine_current].function_stack_top == 0) return;
  233. ctx->routines[ctx->routine_current].function_stack_top--;
  234. }
  235. void ink_pop(struct context* ctx) {
  236. if(ctx->routine_current >= ctx->routines_top) return;
  237. if(ctx->routines[ctx->routine_current].panic) return;
  238. if(ctx->routines[ctx->routine_current].stack == NULL) return;
  239. if(ctx->routines[ctx->routine_current].top == 0) return;
  240. ctx->routines[ctx->routine_current].top--;
  241. }
  242. struct context* ink_make_context(void*(*malloc)(size_t), void*(*realloc)(void*, size_t), void(*free)(void*), int(*putchar)(int)) {
  243. struct context* ctx = (struct context*)malloc(sizeof(struct context));
  244. ctx->malloc = malloc;
  245. ctx->realloc = realloc;
  246. ctx->free = free;
  247. ctx->inner_malloc = malloc;
  248. ctx->inner_realloc = realloc;
  249. ctx->inner_free = free;
  250. ctx->putchar = putchar;
  251. ctx->panic = 0;
  252. ctx->routines = NULL;
  253. ctx->routines_capacity = 0;
  254. ctx->routines_top = 0;
  255. ctx->types = NULL;
  256. ctx->types_capacity = 0;
  257. ctx->types_top = 0;
  258. ctx->native_words = NULL;
  259. ctx->native_words_capacity = 0;
  260. ctx->native_words_top = 0;
  261. ctx->words = NULL;
  262. ctx->words_capacity = 0;
  263. ctx->words_top = 0;
  264. ctx->lex_reserved_words = NULL;
  265. ctx->lex_reserved_words_capacity = 0;
  266. ctx->lex_reserved_words_top = 0;
  267. ctx->collections = 0;
  268. ctx->steps = 0;
  269. return ctx;
  270. }
  271. /**
  272. * Allocates a string that contains the integer
  273. * @param _ context (used to allocate)
  274. * @param cpy the value
  275. * @return the allocated string, needs to be freed by ctx->free
  276. * @internal this function is slightly cursed
  277. */
  278. static char* ink_itoa(struct context* _, int cpy) {
  279. char* n = _->malloc(16);
  280. n[15] = 0;
  281. char* it = n+15;
  282. do {
  283. it--;
  284. *it = (cpy % 10) + '0';
  285. cpy = cpy / 10;
  286. } while(cpy);
  287. memmove(n, it, 16 - (it-n));
  288. return n;
  289. }
  290. #ifndef NOSTDLIB
  291. struct context* ink_make_default_context() {
  292. struct context* ctx = ink_make_context(malloc, realloc, free, putchar);
  293. ink_std_library(ctx);
  294. return ctx;
  295. }
  296. #endif
  297. static int ink_consume_one(int* end, struct context* pContext, char** buffer, char* r) {
  298. int i;
  299. if(*end == 0) {
  300. return 0;
  301. }
  302. r[*end] = 0;
  303. int done = 0;
  304. struct elem value;
  305. if (strcmp(r, _KEYWORD_INK_FUNCTION) == 0) {
  306. value.value = 0;
  307. value.type = INK_FUNCTION_KW;
  308. done = 1;
  309. }
  310. if (!done && strcmp(r, _KEYWORD_INK_DO) == 0) {
  311. value.value = 0;
  312. value.type = INK_DO_KW;
  313. done = 1;
  314. }
  315. if (!done && strcmp(r, _KEYWORD_INK_END) == 0) {
  316. value.value = 0;
  317. value.type = INK_END_KW;
  318. done = 1;
  319. }
  320. if (!done && strcmp(r, _KEYWORD_INK_RETURN) == 0) {
  321. value.value = 0;
  322. value.type = INK_RETURN;
  323. done = 1;
  324. }
  325. if(done) {
  326. int err;
  327. err = ink_push(pContext, value);
  328. if(err < 0) {
  329. return -19;
  330. }
  331. }
  332. if (!done) {
  333. for (i = 0; i < pContext->words_top; ++i) {
  334. if (strcmp(r, pContext->words[i].name) == 0) {
  335. value.value = i;
  336. value.type = INK_FUNCTION;
  337. int err;
  338. err = ink_push(pContext, value);
  339. if(err < 0) {
  340. return -20;
  341. }
  342. done = 1;
  343. break;
  344. }
  345. }
  346. }
  347. if (!done) {
  348. for (i = 0; i < pContext->native_words_top; ++i) {
  349. if (strcmp(r, pContext->native_words[i].name) == 0) {
  350. value.value = i;
  351. value.type = INK_NATIVE_FUNCTION;
  352. int err;
  353. err = ink_push(pContext, value);
  354. if(err < 0) {
  355. return -21;
  356. }
  357. done = 1;
  358. break;
  359. }
  360. }
  361. }
  362. if (!done) {
  363. for(i = (r[0] == '-'); i < *end; i++) {
  364. if(!isdigit(r[i])){
  365. goto not_an_int;
  366. }
  367. }
  368. value.value = atoi(r);
  369. value.type = INK_INTEGER;
  370. int err;
  371. err = ink_push(pContext, value);
  372. if(err < 0) {
  373. return -22;
  374. }
  375. done = 1;
  376. }
  377. not_an_int:
  378. if (!done) {
  379. i = ink_add_lex_string(pContext, r);
  380. if(i < 0) {
  381. pContext->panic = 1;
  382. return -7;
  383. }
  384. value.value = i;
  385. if(r[strlen(r) - 1] == ':') {
  386. value.type = INK_LABEL;
  387. } else {
  388. value.type = INK_RESERVED;
  389. }
  390. int err;
  391. err = ink_push(pContext, value);
  392. if(err < 0) {
  393. return -23;
  394. }
  395. }
  396. *end = 0;
  397. return 0;
  398. }
  399. static int ink_lex(struct context *pContext, char* buffer) {
  400. int i;
  401. char r[128];
  402. int end = 0;
  403. int err;
  404. while(*buffer != 0) {
  405. if(isspace(*buffer)) {
  406. err = ink_consume_one(&end, pContext, &buffer, r);
  407. if(err < 0) {
  408. pContext->panic = 1;
  409. return -8;
  410. }
  411. } else {
  412. r[end] = *buffer;
  413. ++end;
  414. }
  415. ++buffer;
  416. }
  417. err = ink_consume_one(&end, pContext, &buffer, r);
  418. if(err < 0) {
  419. pContext->panic = 1;
  420. return -9;
  421. }
  422. return 0;
  423. }
  424. static int lblcmp(const char* label, const char* other, size_t label_sz) {
  425. while (label_sz != 1) {
  426. if(*other == 0) return 1;
  427. if(*label != *other) return 1;
  428. ++label;
  429. ++other;
  430. label_sz--;
  431. }
  432. return 0;
  433. }
  434. int ink_make_routine(struct context* ctx) {
  435. if(ctx->routines == NULL) {
  436. ctx->routines = ctx->inner_malloc(sizeof(struct ink_routine) * 8);
  437. ctx->routines_top = 0;
  438. ctx->routines_capacity = 8;
  439. struct ink_routine* it = ctx->routines;
  440. struct ink_routine* end = ctx->routines + 8;
  441. for(;it != end;++it) {
  442. it->stack = NULL;
  443. it->function_stack = NULL;
  444. it->panic = INK_ROUTINE_CAN_REUSE;
  445. }
  446. } else if(ctx->routines_top == ctx->routines_capacity) {
  447. int new_count = (ctx->routines_capacity + ctx->routines_capacity/2);
  448. void* renewed = ctx->inner_realloc(ctx->routines, sizeof(struct stack_frame) * new_count);
  449. if(renewed == NULL) {
  450. return -99;
  451. } else {
  452. ctx->routines = renewed;
  453. struct ink_routine* it = ctx->routines + ctx->routines_capacity;
  454. struct ink_routine* end = ctx->routines + new_count;
  455. for(;it != end;++it) {
  456. it->panic = INK_ROUTINE_CAN_REUSE;
  457. }
  458. ctx->routines_capacity = new_count;
  459. }
  460. }
  461. struct ink_routine* it = ctx->routines;
  462. struct ink_routine* end = ctx->routines + ctx->routines_capacity;
  463. for(;it != end;++it) {
  464. if(it->panic == INK_ROUTINE_CAN_REUSE) {
  465. it->panic = 0;
  466. it->stack = NULL;
  467. it->top = 0;
  468. it->capacity = 0;
  469. it->function_stack = NULL;
  470. it->function_stack_top = 0;
  471. it->function_stack_capacity = 0;
  472. int idx = it - ctx->routines;
  473. if(idx >= ctx->routines_top) {
  474. ctx->routines_top = idx + 1;
  475. }
  476. return idx;
  477. }
  478. }
  479. }
  480. int ink_kill_routine(struct context* ctx, int routine){
  481. if(routine < 0 || routine >= ctx->routines_top) {
  482. return 0;
  483. }
  484. struct ink_routine* curr = ctx->routines + routine;
  485. if(curr->panic == INK_ROUTINE_CAN_REUSE) {
  486. return 0;
  487. }
  488. if(curr->stack != NULL) {
  489. ctx->free(curr->stack);
  490. curr->stack = NULL;
  491. }
  492. if(curr->function_stack != NULL) {
  493. ctx->free(curr->function_stack);
  494. curr->function_stack = NULL;
  495. }
  496. curr->panic = INK_ROUTINE_CAN_REUSE;
  497. return 1;
  498. }
  499. /**
  500. *
  501. * @param pContext
  502. * @param executable_buffer
  503. * @param executable_buffer_top
  504. * @internal Loop from hell
  505. */
  506. static int ink_parse(struct context* pContext, struct elem* executable_buffer, int* executable_buffer_top) {
  507. struct ink_routine* currentRoutine = pContext->routines + pContext->routine_current;
  508. int i;
  509. #define LABEL_BUFFER 128
  510. #define FUNCTION_BUFFER 256
  511. struct label labels[LABEL_BUFFER];
  512. struct elem function_buffer[FUNCTION_BUFFER];
  513. int function_buffer_top = 0;
  514. int function_name = -1;
  515. #define MODE_EXECUTABLE 0
  516. #define MODE_FUNCTION 1
  517. #define MODE_DO 2
  518. int mode = 0;
  519. memset(labels, 0, sizeof(struct label)*LABEL_BUFFER);
  520. for(i = 0; i < currentRoutine->top; ++i) {
  521. struct elem current;
  522. current = currentRoutine->stack[i];
  523. switch (mode) {
  524. case MODE_EXECUTABLE:
  525. switch(current.type) {
  526. case INK_FUNCTION_KW:
  527. mode = MODE_FUNCTION;
  528. function_name = -1;
  529. goto next_token;
  530. case INK_DO_KW:
  531. case INK_END_KW:
  532. return -26;
  533. default:
  534. executable_buffer[*executable_buffer_top] = current;
  535. *executable_buffer_top += 1;
  536. }
  537. break;
  538. case MODE_FUNCTION:
  539. if(current.type == INK_DO_KW) {
  540. if(function_name == -1) {
  541. return -27;
  542. } else {
  543. mode = MODE_DO;
  544. memset(labels, 0, sizeof(struct label)*128);
  545. goto next_token;
  546. }
  547. }
  548. if(function_name != -1) {
  549. return -28;
  550. }
  551. if(current.type != INK_RESERVED) {
  552. return -29;
  553. }
  554. function_name = current.value;
  555. break;
  556. case MODE_DO:
  557. if(current.type == INK_END_KW) {
  558. int j;
  559. for(j = 0; j < function_buffer_top; j++) {
  560. struct elem pt;
  561. pt = function_buffer[j];
  562. if(pt.type == INK_LABEL) {
  563. int k;
  564. for(k = 0; k < LABEL_BUFFER; k++) {
  565. if(labels[k].active) {
  566. if(strcmp(labels[k].name, pContext->lex_reserved_words[pt.value]) == 0) {
  567. labels[k].dest = j;
  568. return -30;
  569. break;
  570. }
  571. } else {
  572. labels[k].active = 1;
  573. labels[k].name = pContext->lex_reserved_words[pt.value];
  574. labels[k].dest = j;
  575. memcpy(function_buffer+j, function_buffer+j+1, sizeof(struct elem)*(function_buffer_top-j-1));
  576. function_buffer_top--;
  577. j--;
  578. break;
  579. }
  580. }
  581. }
  582. }
  583. for(j = 0; j < function_buffer_top; j++) {
  584. struct elem pt;
  585. pt = function_buffer[j];
  586. if(pt.type == INK_RESERVED) {
  587. const char* str = pContext->lex_reserved_words[pt.value];
  588. int k;
  589. for(k = 0; k < LABEL_BUFFER; k++) {
  590. if(labels[k].active) {
  591. const char* lbl = labels[k].name;
  592. int label_sz = strlen(lbl);
  593. if(lblcmp(labels[k].name, pContext->lex_reserved_words[pt.value], label_sz) == 0) {
  594. function_buffer[j].type = INK_INTEGER;
  595. function_buffer[j].value = labels[k].dest - j;
  596. break;
  597. }
  598. } else break;
  599. }
  600. }
  601. }
  602. int err;
  603. err = ink_add_indigenous(pContext, pContext->lex_reserved_words[function_name], function_buffer, function_buffer_top);
  604. if(err < 0) {
  605. pContext->panic = 1;
  606. return -33;
  607. }
  608. function_buffer_top = 0;
  609. mode = MODE_EXECUTABLE;
  610. goto next_token;
  611. }
  612. function_buffer[function_buffer_top] = current;
  613. function_buffer_top += 1;
  614. break;
  615. }
  616. next_token: i=i;
  617. }
  618. if(mode == MODE_FUNCTION || mode == MODE_DO) {
  619. return -32;
  620. }
  621. return 0;
  622. #undef MODE_EXECUTABLE
  623. #undef MODE_FUNCTION
  624. #undef MODE_DO
  625. #undef LABEL_BUFFER
  626. #undef FUNCTION_BUFFER
  627. }
  628. int ink_step(struct context *pContext) {
  629. struct ink_routine* currentRoutine = pContext->routines + pContext->routine_current;
  630. pContext->steps++;
  631. if(currentRoutine->function_stack_top == 0) return 0;
  632. if(pContext->panic) {
  633. return -1;
  634. }
  635. struct stack_frame frame;
  636. struct stack_frame* top;
  637. struct elem next;
  638. int t;
  639. top = &currentRoutine->function_stack[currentRoutine->function_stack_top-1];
  640. t = top->executing.type;
  641. switch(t) {
  642. case INK_NATIVE_FUNCTION:
  643. if(top->index != 0) {
  644. ink_pop_fn(pContext);
  645. } else {
  646. top->index++;
  647. if(pContext->native_words_top <= top->executing.value) {
  648. pContext->panic = 1;
  649. return -1;
  650. }
  651. pContext->native_words[top->executing.value].value(pContext);
  652. }
  653. break;
  654. case INK_FUNCTION:
  655. if(pContext->words_top <= top->executing.value) {
  656. pContext->panic = 1;
  657. return -1;
  658. }
  659. if(top->index >= pContext->words[top->executing.value].size) {
  660. ink_pop_fn(pContext);
  661. } else {
  662. next = pContext->words[top->executing.value].things[top->index];
  663. if(next.type == INK_RETURN) {
  664. ink_pop_fn(pContext);
  665. return 1;
  666. }
  667. frame.executing = next;
  668. frame.index = 0;
  669. t = ink_push_fn(pContext, frame);
  670. if(t < 0) {
  671. pContext->panic = 1;
  672. return -11;
  673. }
  674. top->index++;
  675. }
  676. break;
  677. default:
  678. t = ink_push(pContext, top->executing);
  679. if(t < 0) {
  680. pContext->panic = 1;
  681. return -25;
  682. }
  683. ink_pop_fn(pContext);
  684. break;
  685. }
  686. return 1;
  687. }
  688. void ink_compile(struct context *pContext, char* buffer) {
  689. int routine = ink_make_routine(pContext);
  690. int saved = pContext->routine_current;
  691. pContext->routine_current = routine;
  692. struct ink_routine* currentRoutine = pContext->routines + routine;
  693. currentRoutine->stack = NULL;
  694. currentRoutine->top = 0;
  695. currentRoutine->capacity = 0;
  696. int err;
  697. err = ink_lex(pContext, buffer);
  698. if(err < 0) {
  699. pContext->panic = 1;
  700. return;
  701. }
  702. int i = 0;
  703. struct elem executable_buffer[256];
  704. int executable_buffer_top = 0;
  705. err = ink_parse(pContext, executable_buffer, &executable_buffer_top);
  706. if(err < 0) {
  707. pContext->panic = 1;
  708. return;
  709. }
  710. struct stack_frame frame;
  711. char main_fn[32] = "__-MAIN-__";
  712. char* integer = ink_itoa(pContext, routine);
  713. size_t integer_size = strlen(integer);
  714. memcpy(main_fn+10, integer, integer_size);
  715. pContext->free(integer);
  716. main_fn[10+integer_size] = 0;
  717. frame.executing.value = ink_add_indigenous(pContext, main_fn, executable_buffer, executable_buffer_top);
  718. if(frame.executing.value < 0) {
  719. pContext->panic = 1;
  720. return;
  721. }
  722. frame.executing.type = INK_FUNCTION;
  723. frame.index = 0;
  724. err = ink_push_fn(pContext, frame);
  725. if(err < 0) {
  726. pContext->panic = 1;
  727. return;
  728. }
  729. pContext->routine_current = saved;
  730. return;
  731. }
  732. int ink_can_run(struct context* pContext) {
  733. int it = 0;
  734. for(;it < pContext->routines_top; ++it) {
  735. if(pContext->routines[it].panic == 0) {
  736. return 1;
  737. }
  738. }
  739. return 0;
  740. }
  741. int ink_step_everyone(struct context* pContext) {
  742. int out;
  743. pContext->routine_current = -1;
  744. for(;;) {
  745. do{
  746. ++(pContext->routine_current);
  747. } while(pContext->routine_current < pContext->routines_top && pContext->routines[pContext->routine_current].panic != 0);
  748. if(pContext->routine_current >= pContext->routines_top) break;
  749. if(pContext->routines[pContext->routine_current].panic == INK_ROUTINE_SUCCESS) {
  750. ink_kill_routine(pContext, pContext->routine_current);
  751. }
  752. out = ink_step(pContext);
  753. if(out == 0) {
  754. pContext->routines[pContext->routine_current].panic = INK_ROUTINE_SUCCESS;
  755. } else if(out < 0) {
  756. pContext->routines[pContext->routine_current].panic = out;
  757. }
  758. }
  759. return 0;
  760. }
  761. int ink_new_type(
  762. struct context* ctx,
  763. const char* type_name,
  764. int size,
  765. void (*collect)(struct context*,void*),
  766. struct ink_collection_list (*gc)(struct context*,void*)
  767. ) {
  768. if(ctx->panic) return -128;
  769. if(ctx->types == NULL) {
  770. ctx->types = ctx->inner_malloc(sizeof(struct ink_type) * 8);
  771. ctx->types_top = 0;
  772. ctx->types_capacity = 8;
  773. } else if(ctx->types_top == ctx->types_capacity) {
  774. int new_count = (ctx->types_capacity + ctx->types_capacity/2);
  775. void* renewed = ctx->inner_realloc(ctx->types, sizeof(struct ink_type) * new_count);
  776. if(renewed == NULL) {
  777. return -129;
  778. } else {
  779. ctx->types = renewed;
  780. ctx->types_capacity = new_count;
  781. }
  782. }
  783. ctx->types[ctx->types_top].name = type_name;
  784. ctx->types[ctx->types_top].element_size = size;
  785. ctx->types[ctx->types_top].elements = NULL;
  786. ctx->types[ctx->types_top].elements_top = 0;
  787. ctx->types[ctx->types_top].elements_capacity = 0;
  788. ctx->types[ctx->types_top].collect = collect;
  789. ctx->types[ctx->types_top].gc = gc;
  790. ctx->types_top++;
  791. // Satisfying the minimal value requirement
  792. return ctx->types_top - 1 + 16;
  793. }
  794. static struct element_slab* ink_get_value_link(struct context* ctx, struct elem ref) {
  795. if(ref.type < 16) return NULL;
  796. int type_id = ref.type - 16;
  797. if(type_id >= ctx->types_top) return NULL;
  798. if(ctx->types[type_id].element_size == 0) return NULL;
  799. if(ref.value < 0) return NULL;
  800. if(ref.value >= ctx->types[type_id].elements_top) return NULL;
  801. if(! ctx->types[type_id].elements[ref.value].in_use) return NULL;
  802. return ctx->types[type_id].elements + ref.value;
  803. }
  804. void* ink_get_value(struct context* ctx, struct elem ref) {
  805. struct element_slab* s;
  806. s = ink_get_value_link(ctx, ref);
  807. if(s == NULL) return NULL;
  808. return s->data;
  809. }
  810. struct elem ink_make_native(struct context* ctx, int type, void* ptr) {
  811. if(type < 16) {
  812. struct elem ret;
  813. ret.type = 0;
  814. ret.value = -130;
  815. return ret;
  816. }
  817. int type_id = type - 16;
  818. if(type_id >= ctx->types_top) {
  819. struct elem ret;
  820. ret.type = 0;
  821. ret.value = -129;
  822. return ret;
  823. }
  824. if(ctx->panic) {
  825. struct elem ret;
  826. ret.type = 0;
  827. ret.value = -135;
  828. return ret;
  829. }
  830. if(ctx->types[type_id].elements == NULL) {
  831. ctx->types[type_id].elements = ctx->inner_malloc(sizeof(struct element_slab) * 8);
  832. ctx->types[type_id].elements_top = 0;
  833. ctx->types[type_id].elements_capacity = 8;
  834. 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));
  835. } else if(ctx->types[type_id].elements_top == ctx->types[type_id].elements_capacity) {
  836. int new_count = (ctx->types[type_id].elements_capacity + ctx->types[type_id].elements_capacity/2);
  837. void* renewed = ctx->inner_realloc(ctx->types[type_id].elements, sizeof(struct element_slab) * new_count);
  838. if(renewed == NULL) {
  839. struct elem ret;
  840. ret.type = 0;
  841. ret.value = -129;
  842. return ret;
  843. } else {
  844. ctx->types[type_id].elements = renewed;
  845. ctx->types[type_id].elements_capacity = new_count;
  846. 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));
  847. }
  848. }
  849. int g = ctx->types[type_id].elements_capacity;
  850. int i;
  851. for(i = 0; i < g; ++i) {
  852. if(! ctx->types[type_id].elements[i].in_use) {
  853. ctx->types[type_id].elements[i].in_use = 1;
  854. ctx->types[type_id].elements[i].uses = 1;
  855. if(ctx->types[type_id].element_size < 0) {
  856. ctx->types[type_id].elements[i].data = ptr;
  857. } else {
  858. void* new_ptr = ctx->malloc(ctx->types[type_id].element_size);
  859. if(new_ptr == NULL) {
  860. struct elem ret;
  861. ret.type = 0;
  862. ret.value = -139;
  863. return ret;
  864. }
  865. memcpy(new_ptr, ptr, ctx->types[type_id].element_size);
  866. ctx->types[type_id].elements[i].data = new_ptr;
  867. }
  868. ctx->types[type_id].elements_top = max(ctx->types[type_id].elements_top, i+1);
  869. struct elem ret;
  870. ret.type = type;
  871. ret.value = i;
  872. return ret;
  873. }
  874. }
  875. struct elem ret;
  876. ret.type = 0;
  877. ret.value = -140;
  878. return ret;
  879. }
  880. void ink_gc(struct context* ctx) {
  881. int i, j, k;
  882. for(i = 0; i < ctx->types_top; ++i) {
  883. for(j = 0; j < ctx->types[i].elements_top; ++j) {
  884. ctx->types[i].elements[j].uses = 0;
  885. }
  886. }
  887. for(i = 0; i < ctx->routines_top; ++i) {
  888. for(j = 0; j < ctx->routines[i].top; ++j) {
  889. struct element_slab* v = ink_get_value_link(ctx, ctx->routines[i].stack[j]);
  890. if(v != NULL) ++v->uses;
  891. }
  892. }
  893. int marked;
  894. do {
  895. marked = 0;
  896. for (i = 0; i < ctx->types_top; ++i) {
  897. for (j = 0; j < ctx->types[i].elements_top; ++j) {
  898. if (ctx->types[i].elements[j].in_use && ctx->types[i].elements[j].uses) {
  899. struct ink_collection_list c = ctx->types[i].gc(ctx, ctx->types[i].elements[j].data);
  900. for (k = 0; k < c.count; ++k) {
  901. struct element_slab *v = ink_get_value_link(ctx, c.elements[k]);
  902. if (v != NULL && !v->uses) {
  903. ++v->uses;
  904. marked = 1;
  905. }
  906. }
  907. if (c.elements != NULL) ctx->inner_free(c.elements);
  908. }
  909. }
  910. }
  911. } while(marked);
  912. for(i = 0; i < ctx->types_top; ++i) {
  913. for(j = 0; j < ctx->types[i].elements_top; ++j) {
  914. if(ctx->types[i].elements[j].uses == 0 && ctx->types[i].elements[j].in_use) {
  915. ctx->collections++;
  916. ctx->types[i].collect(ctx, ctx->types[i].elements[j].data);
  917. if(ctx->types[i].element_size > 0) {
  918. ctx->free(ctx->types[i].elements[j].data);
  919. }
  920. ctx->types[i].elements[j].data = NULL;
  921. ctx->types[i].elements[j].uses = 0;
  922. ctx->types[i].elements[j].in_use = 0;
  923. }
  924. }
  925. }
  926. }
  927. /**********************************************************************************************************************/
  928. static void print_stacktrace(struct context* _) {
  929. int i = 0;
  930. struct ink_routine* currentRoutine = _->routines + _->routine_current;
  931. for(; i < currentRoutine->function_stack_top; ++i) {
  932. struct elem thing;
  933. thing = currentRoutine->function_stack[i].executing;
  934. switch(thing.type) {
  935. case INK_NATIVE_FUNCTION: {
  936. char *n = _->native_words[thing.value].name;
  937. while (*n) {
  938. _->putchar(*n);
  939. ++n;
  940. }
  941. _->putchar(10);
  942. break;
  943. }
  944. case INK_FUNCTION:{
  945. char *n = _->native_words[thing.value].name;
  946. while (*n) {
  947. _->putchar(*n);
  948. ++n;
  949. }
  950. _->putchar(':');
  951. n = ink_itoa(_, currentRoutine->function_stack[i].index);
  952. while (*n) {
  953. _->putchar(*n);
  954. ++n;
  955. }
  956. _->free(n);
  957. _->putchar(10);
  958. break;
  959. }
  960. default:
  961. break;
  962. }
  963. }
  964. }
  965. static void add_int(struct context* ctx) {
  966. struct ink_routine* currentRoutine = ctx->routines + ctx->routine_current;
  967. if(currentRoutine->top < 2) {
  968. currentRoutine->panic = 1;
  969. return;
  970. }
  971. struct elem a;
  972. struct elem b;
  973. a = currentRoutine->stack[currentRoutine->top-1];
  974. b = currentRoutine->stack[currentRoutine->top-2];
  975. if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) {
  976. ctx->panic = 1;
  977. return;
  978. }
  979. ink_pop(ctx);
  980. currentRoutine->stack[currentRoutine->top-1].value = a.value + b.value;
  981. }
  982. static void sub_int(struct context* ctx) {
  983. struct ink_routine* currentRoutine = ctx->routines + ctx->routine_current;
  984. if(currentRoutine->top < 2) {
  985. currentRoutine->panic = 1;
  986. return;
  987. }
  988. struct elem a;
  989. struct elem b;
  990. a = currentRoutine->stack[currentRoutine->top-1];
  991. b = currentRoutine->stack[currentRoutine->top-2];
  992. if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) {
  993. currentRoutine->panic = 1;
  994. return;
  995. }
  996. ink_pop(ctx);
  997. currentRoutine->stack[currentRoutine->top-1].value = b.value - a.value;
  998. }
  999. static void mult_int(struct context* ctx) {
  1000. struct ink_routine* currentRoutine = ctx->routines + ctx->routine_current;
  1001. if(currentRoutine->top < 2) {
  1002. currentRoutine->panic = 1;
  1003. return;
  1004. }
  1005. struct elem a;
  1006. struct elem b;
  1007. a = currentRoutine->stack[currentRoutine->top-1];
  1008. b = currentRoutine->stack[currentRoutine->top-2];
  1009. if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) {
  1010. currentRoutine->panic = 1;
  1011. return;
  1012. }
  1013. ink_pop(ctx);
  1014. currentRoutine->stack[currentRoutine->top-1].value = b.value * a.value;
  1015. }
  1016. static void div_int(struct context* ctx) {
  1017. struct ink_routine* currentRoutine = ctx->routines + ctx->routine_current;
  1018. if(currentRoutine->top < 2) {
  1019. currentRoutine->panic = 1;
  1020. return;
  1021. }
  1022. struct elem a;
  1023. struct elem b;
  1024. a = currentRoutine->stack[currentRoutine->top-1];
  1025. b = currentRoutine->stack[currentRoutine->top-2];
  1026. if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) {
  1027. currentRoutine->panic = 1;
  1028. return;
  1029. }
  1030. ink_pop(ctx);
  1031. currentRoutine->stack[currentRoutine->top-1].value = b.value / a.value;
  1032. }
  1033. static void rem_int(struct context* ctx) {
  1034. struct ink_routine* currentRoutine = ctx->routines + ctx->routine_current;
  1035. if(currentRoutine->top < 2) {
  1036. currentRoutine->panic = 1;
  1037. return;
  1038. }
  1039. struct elem a;
  1040. struct elem b;
  1041. a = currentRoutine->stack[currentRoutine->top-1];
  1042. b = currentRoutine->stack[currentRoutine->top-2];
  1043. if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) {
  1044. currentRoutine->panic = 1;
  1045. return;
  1046. }
  1047. ink_pop(ctx);
  1048. currentRoutine->stack[currentRoutine->top-1].value = b.value % a.value;
  1049. }
  1050. static void dupe_elem(struct context* ctx) {
  1051. struct ink_routine* currentRoutine = ctx->routines + ctx->routine_current;
  1052. if(currentRoutine->top < 1) {
  1053. ctx->panic = 1;
  1054. return;
  1055. }
  1056. struct elem a;
  1057. a = currentRoutine->stack[currentRoutine->top-1];
  1058. int err;
  1059. err = ink_push(ctx, a);
  1060. if(err < 0) ctx->panic;
  1061. }
  1062. static void drop_elem(struct context* ctx) {
  1063. struct ink_routine* currentRoutine = ctx->routines + ctx->routine_current;
  1064. if(currentRoutine->top < 1) {
  1065. ctx->panic = 1;
  1066. return;
  1067. }
  1068. ink_pop(ctx);
  1069. }
  1070. static void pluck_elem(struct context* ctx) {
  1071. struct ink_routine* currentRoutine = ctx->routines + ctx->routine_current;
  1072. if(currentRoutine->top < 1) {
  1073. currentRoutine->panic = 1;
  1074. return;
  1075. }
  1076. struct elem a;
  1077. a = currentRoutine->stack[currentRoutine->top-1];
  1078. if(a.type != INK_INTEGER) {
  1079. ctx->panic = 1;
  1080. return;
  1081. }
  1082. int position = currentRoutine->top - (a.value + 1);
  1083. if(position >= currentRoutine->top || position < 0) {
  1084. ctx->panic = 1;
  1085. return;
  1086. }
  1087. ink_pop(ctx);
  1088. int err;
  1089. err = ink_push(ctx, currentRoutine->stack[position]);
  1090. if(err < 0) ctx->panic;
  1091. }
  1092. static void swap_elem(struct context* ctx) {
  1093. struct ink_routine* currentRoutine = ctx->routines + ctx->routine_current;
  1094. if(currentRoutine->top < 2) {
  1095. currentRoutine->panic = 1;
  1096. return;
  1097. }
  1098. struct elem a;
  1099. struct elem b;
  1100. a = currentRoutine->stack[currentRoutine->top-1];
  1101. b = currentRoutine->stack[currentRoutine->top-2];
  1102. currentRoutine->stack[currentRoutine->top-2] = a;
  1103. currentRoutine->stack[currentRoutine->top-1] = b;
  1104. }
  1105. static void return_if(struct context* ctx) {
  1106. struct ink_routine* currentRoutine = ctx->routines + ctx->routine_current;
  1107. if(currentRoutine->top < 1) {
  1108. ctx->panic = 1;
  1109. return;
  1110. }
  1111. struct elem a;
  1112. a = currentRoutine->stack[currentRoutine->top-1];
  1113. if(a.type != INK_INTEGER) {
  1114. ctx->panic = 1;
  1115. return;
  1116. }
  1117. if(a.value) {
  1118. ink_pop_fn(ctx);
  1119. ink_pop_fn(ctx);
  1120. }
  1121. ink_pop(ctx);
  1122. return;
  1123. }
  1124. static void jump_if(struct context* ctx) {
  1125. struct ink_routine* currentRoutine = ctx->routines + ctx->routine_current;
  1126. if(currentRoutine->top < 1) {
  1127. ctx->panic = 1;
  1128. return;
  1129. }
  1130. struct elem a;
  1131. a = currentRoutine->stack[currentRoutine->top-1];
  1132. if(a.type != INK_INTEGER) {
  1133. ctx->panic = 1;
  1134. return;
  1135. }
  1136. ink_pop(ctx);
  1137. if(a.value) {
  1138. ink_pop_fn(ctx);
  1139. a = currentRoutine->stack[currentRoutine->top-1];
  1140. currentRoutine->function_stack[currentRoutine->function_stack_top - 1].index += a.value - 3;
  1141. }
  1142. ink_pop(ctx);
  1143. return;
  1144. }
  1145. static void print_int(struct context* ctx) {
  1146. struct ink_routine* currentRoutine = ctx->routines + ctx->routine_current;
  1147. if(currentRoutine->top < 1 || currentRoutine->stack[currentRoutine->top-1].type != INK_INTEGER) {
  1148. currentRoutine->panic = 1;
  1149. return;
  1150. }
  1151. struct elem a;
  1152. a = currentRoutine->stack[currentRoutine->top-1];
  1153. ink_pop(ctx);
  1154. char* n = ink_itoa(ctx, a.value);
  1155. char* str = n;
  1156. while (*str) {
  1157. ctx->putchar(*str);
  1158. ++str;
  1159. }
  1160. ctx->free(n);
  1161. }
  1162. static void print_as_utf8(struct context* ctx) {
  1163. struct ink_routine* currentRoutine = ctx->routines + ctx->routine_current;
  1164. if(currentRoutine->top < 1 || currentRoutine->stack[currentRoutine->top-1].type != INK_INTEGER) {
  1165. ctx->panic = 1;
  1166. return;
  1167. }
  1168. struct elem a;
  1169. a = currentRoutine->stack[currentRoutine->top-1];
  1170. if(a.value <= 0x7F) {
  1171. ctx->putchar(a.value);
  1172. } else if(a.value <= 0x7FF) {
  1173. ctx->putchar(((a.value & 0xFC0) >> 6) | 192);
  1174. ctx->putchar((a.value & 0x3F) | 128);
  1175. } else if(a.value <= 0xFFFF) {
  1176. ctx->putchar(((a.value & 0x3F000) >> 12) | 224);
  1177. ctx->putchar(((a.value & 0xFC0) >> 6) | 128);
  1178. ctx->putchar((a.value & 0x3F) | 128);
  1179. } else if(a.value <= 0x10FFFF) {
  1180. ctx->putchar(((a.value & 0x3C0000) >> 18) | 240);
  1181. ctx->putchar(((a.value & 0x3F000) >> 12) | 128);
  1182. ctx->putchar(((a.value & 0xFC0) >> 6) | 128);
  1183. ctx->putchar((a.value & 0x3F) | 128);
  1184. } else {
  1185. ctx->panic = 1;
  1186. return;
  1187. }
  1188. ink_pop(ctx);
  1189. }
  1190. struct ink_array {
  1191. int top;
  1192. int capacity;
  1193. struct elem* elements;
  1194. };
  1195. static int get_type_by_name(struct context* ctx, const char* name) {
  1196. int i;
  1197. for(i = 0; i < ctx->types_top; ++i) {
  1198. if(strcmp(ctx->types[i].name, name) == 0) {
  1199. return i + 16;
  1200. }
  1201. }
  1202. return -1;
  1203. }
  1204. static void collect_array(struct context* ctx, void* array) {
  1205. struct ink_array* ary = array;
  1206. if(ary->elements != NULL) ctx->free(ary->elements);
  1207. }
  1208. static struct ink_collection_list gc_array(struct context* ctx, void* array) {
  1209. struct ink_array* ary = array;
  1210. struct ink_collection_list c;
  1211. c.elements = ctx->inner_malloc(sizeof(struct elem)*ary->top);
  1212. c.count = ary->top;
  1213. memcpy(c.elements, ary->elements, sizeof(struct elem)*ary->top);
  1214. return c;
  1215. }
  1216. static void new_array(struct context* ctx) {
  1217. int tid = get_type_by_name(ctx, "array");
  1218. struct ink_array ary;
  1219. ary.elements = NULL;
  1220. ary.top = 0;
  1221. ary.capacity = 0;
  1222. struct elem e = ink_make_native(ctx, tid, &ary);
  1223. ink_push(ctx, e);
  1224. }
  1225. static void push_array(struct context* ctx) {
  1226. int tid = get_type_by_name(ctx, "array");
  1227. struct ink_routine* currentRoutine = ctx->routines + ctx->routine_current;
  1228. if(currentRoutine->top < 2 || currentRoutine->stack[currentRoutine->top-1].type != tid) {
  1229. currentRoutine->panic = 1;
  1230. return;
  1231. }
  1232. struct elem a;
  1233. a = currentRoutine->stack[currentRoutine->top-1];
  1234. struct ink_array* ary= ink_get_value(ctx, a);
  1235. if(ary == NULL) {
  1236. currentRoutine->panic = 1;
  1237. return;
  1238. }
  1239. ink_pop(ctx);
  1240. if(ary->elements == NULL) {
  1241. ary->elements = ctx->malloc(sizeof(struct elem) * 8);
  1242. ary->top = 0;
  1243. ary->capacity = 8;
  1244. } else if(ary->top == ary->capacity) {
  1245. int new_count = (ary->capacity + ary->capacity/2);
  1246. void* renewed = ctx->realloc(ary->elements, sizeof(struct elem) * new_count);
  1247. if(renewed == NULL) {
  1248. currentRoutine->panic = 1;
  1249. return;
  1250. } else {
  1251. ary->elements = renewed;
  1252. ary->capacity = new_count;
  1253. }
  1254. }
  1255. ary->elements[ary->top] = currentRoutine->stack[currentRoutine->top-1];
  1256. ary->top++;
  1257. ink_pop(ctx);
  1258. }
  1259. static void index_array(struct context* ctx) {
  1260. int tid = get_type_by_name(ctx, "array");
  1261. struct ink_routine *currentRoutine = ctx->routines + ctx->routine_current;
  1262. if (currentRoutine->top < 2 || currentRoutine->stack[currentRoutine->top - 1].type != tid || currentRoutine->stack[currentRoutine->top - 2].type != INK_INTEGER) {
  1263. currentRoutine->panic = 1;
  1264. return;
  1265. }
  1266. struct elem a;
  1267. a = currentRoutine->stack[currentRoutine->top - 1];
  1268. struct ink_array *ary = ink_get_value(ctx, a);
  1269. if (ary == NULL) {
  1270. currentRoutine->panic = 1;
  1271. return;
  1272. }
  1273. ink_pop(ctx);
  1274. struct elem idx;
  1275. idx = currentRoutine->stack[currentRoutine->top - 1];
  1276. ink_pop(ctx);
  1277. if(ary->top <= idx.value) {
  1278. currentRoutine->panic = 1;
  1279. return;
  1280. }
  1281. ink_push(ctx, ary->elements[idx.value]);
  1282. }
  1283. static void run_gc(struct context* ctx) {
  1284. ink_gc(ctx);
  1285. }
  1286. int ink_std_library(struct context* ctx) {
  1287. int v;
  1288. v = 0;
  1289. int array_t = ink_new_type(ctx, "array", sizeof(struct ink_array), collect_array, gc_array);
  1290. v += ink_add_native(ctx, "array.new", new_array);
  1291. v += ink_add_native(ctx, "array.push", push_array);
  1292. v += ink_add_native(ctx, "array.index", index_array);
  1293. v += ink_add_native(ctx, "sys.trace", print_stacktrace);
  1294. v += ink_add_native(ctx, "sys.gc", run_gc);
  1295. v += ink_add_native(ctx, "print_int", print_int);
  1296. v += ink_add_native(ctx, "print_utf8", print_as_utf8);
  1297. v += ink_add_native(ctx, "+", add_int);
  1298. v += ink_add_native(ctx, "-", sub_int);
  1299. v += ink_add_native(ctx, "*", mult_int);
  1300. v += ink_add_native(ctx, "/", div_int);
  1301. v += ink_add_native(ctx, "%", rem_int);
  1302. v += ink_add_native(ctx, "swap", swap_elem);
  1303. v += ink_add_native(ctx, "dup", dupe_elem);
  1304. v += ink_add_native(ctx, "drop", drop_elem);
  1305. v += ink_add_native(ctx, "pluck", pluck_elem);
  1306. v += ink_add_native(ctx, "return_if", return_if);
  1307. v += ink_add_native(ctx, "jump_if", jump_if);
  1308. return v;
  1309. }