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.

857 lines
20 KiB

6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
  1. #ifndef NOSTDLIB
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <ctype.h>
  6. #endif
  7. #include "ink.h"
  8. #define INK_RESERVED (-1)
  9. #define INK_FUNCTION_KW (-2)
  10. #define INK_DO_KW (-3)
  11. #define INK_END_KW (-4)
  12. #define INK_LABEL (-5)
  13. #define INK_RETURN (-6)
  14. #define _KEYWORD_INK_FUNCTION "fn"
  15. #define _KEYWORD_INK_DO "do"
  16. #define _KEYWORD_INK_END "end"
  17. #define _KEYWORD_INK_RETURN "return"
  18. struct label {
  19. int active;
  20. int dest;
  21. char* name;
  22. };
  23. #ifdef NOSTDLIB
  24. static size_t strlen(const char* c) {
  25. size_t j = 0;
  26. while(*(c++)) {
  27. j++;
  28. }
  29. return j;
  30. }
  31. static void* memcpy(void* _dest, const void* _src, size_t sz) {
  32. char* dest = _dest;
  33. const char* src = _src;
  34. while(sz--) {
  35. *(dest++) = *(src++);
  36. }
  37. return dest;
  38. }
  39. static int strcmp(const char* dest, const char* src) {
  40. while(*dest != 0 && *src != 0) {
  41. if(*(dest++) != *(src++)) {
  42. return 1;
  43. }
  44. }
  45. return 0;
  46. }
  47. static void* memmove(void* _dest, const void* _src, size_t sz) {
  48. char* dest = _dest;
  49. const char* src = _src;
  50. if (src < dest) {
  51. src += sz;
  52. dest += sz;
  53. while (sz-- > 0) {
  54. *--dest = *--src;
  55. }
  56. } else {
  57. while (sz-- > 0) {
  58. *dest++ = *src++;
  59. }
  60. }
  61. return dest;
  62. }
  63. static void* memset(void* _dest, int src, size_t sz) {
  64. char* dest = _dest;
  65. while(sz--) {
  66. *(dest++) = src++;
  67. }
  68. return dest;
  69. }
  70. static int isspace(int d) {
  71. return d == ' ' || d == '\t' || d == '\n';
  72. }
  73. static int isdigit(int d) {
  74. return '0' <= d && d <= '9';
  75. }
  76. static int atoi(const char* c) {
  77. int ret = 0;
  78. while(*c) {
  79. ret *= 10;
  80. ret += *c - '0';
  81. ++c;
  82. }
  83. return ret;
  84. }
  85. #endif
  86. void ink_add_native(struct context* ctx, const char* name, void(*value)(struct context*)) {
  87. if(ctx->native_words == NULL) {
  88. ctx->native_words = ctx->malloc(sizeof(struct native_fn) * 8);
  89. ctx->native_words_top = 0;
  90. ctx->native_words_capacity = 8;
  91. } else if(ctx->native_words_top == ctx->native_words_capacity) {
  92. int new_count = (ctx->native_words_capacity + ctx->native_words_capacity/2);
  93. void* renewed = ctx->realloc(ctx->native_words, sizeof(struct native_fn) * new_count);
  94. if(renewed == NULL) {
  95. // TODO: error
  96. } else {
  97. ctx->native_words = renewed;
  98. ctx->native_words_capacity = new_count;
  99. }
  100. }
  101. int len = strlen(name);
  102. char* copy = ctx->malloc(len+1);
  103. if(copy == NULL) {
  104. // TODO: error
  105. }
  106. memcpy(copy, name, len);
  107. copy[len] = 0;
  108. ctx->native_words[ctx->native_words_top].value = value;
  109. ctx->native_words[ctx->native_words_top].name = copy;
  110. ctx->native_words_top++;
  111. }
  112. static int ink_add_indigenous(struct context* ctx, const char* name, struct elem* m, size_t count) {
  113. if(ctx->words == NULL) {
  114. ctx->words = ctx->malloc(sizeof(struct fn) * 8);
  115. ctx->words_top = 0;
  116. ctx->words_capacity = 8;
  117. } else if(ctx->words_top == ctx->words_capacity) {
  118. int new_count = (ctx->words_capacity + ctx->words_capacity/2);
  119. void* renewed = ctx->realloc(ctx->words, sizeof(struct native_fn) * new_count);
  120. if(renewed == NULL) {
  121. // TODO: error
  122. } else {
  123. ctx->words = renewed;
  124. ctx->words_capacity = new_count;
  125. }
  126. }
  127. int i;
  128. for(i = 0; i < ctx->words_top; ++i) {
  129. if(strcmp(name, ctx->words[i].name) == 0) {
  130. ctx->free(ctx->words[i].things);
  131. ctx->words[i].things = ctx->malloc(sizeof(struct elem) * count);
  132. memcpy(ctx->words[i].things, m, sizeof(struct elem) * count);
  133. ctx->words[i].size = count;
  134. return i;
  135. }
  136. }
  137. int len = strlen(name);
  138. char* copy = ctx->malloc(len+1);
  139. if(copy == NULL) {
  140. // TODO: error
  141. }
  142. memcpy(copy, name, len);
  143. copy[len] = 0;
  144. ctx->words[ctx->words_top].things = ctx->malloc(sizeof(struct elem) * count);
  145. memcpy(ctx->words[ctx->words_top].things, m, sizeof(struct elem) * count);
  146. ctx->words[ctx->words_top].size = count;
  147. ctx->words[ctx->words_top].name = copy;
  148. return ctx->words_top++;
  149. }
  150. static int ink_add_lex_string(struct context* ctx, const char* name) {
  151. int i;
  152. if(ctx->lex_reserved_words == NULL) {
  153. ctx->lex_reserved_words = ctx->malloc(sizeof(char*) * 8);
  154. ctx->lex_reserved_words_top = 0;
  155. ctx->lex_reserved_words_capacity = 8;
  156. } else if(ctx->lex_reserved_words_top == ctx->lex_reserved_words_capacity) {
  157. int new_count = (ctx->lex_reserved_words_capacity + ctx->lex_reserved_words_capacity/2);
  158. void* renewed = ctx->realloc(ctx->lex_reserved_words, sizeof(struct native_fn) * new_count);
  159. if(renewed == NULL) {
  160. // TODO: error
  161. } else {
  162. ctx->lex_reserved_words = renewed;
  163. ctx->lex_reserved_words_capacity = new_count;
  164. }
  165. }
  166. for(i = 0; i < ctx->lex_reserved_words_top; i++) {
  167. if(strcmp(ctx->lex_reserved_words[i], name) == 0) {
  168. return i;
  169. }
  170. }
  171. int len = strlen(name);
  172. i = ctx->lex_reserved_words_top;
  173. ctx->lex_reserved_words[i] = ctx->malloc(len+1);
  174. memcpy(ctx->lex_reserved_words[i], name, len);
  175. ctx->lex_reserved_words[i][len] = 0;
  176. ctx->lex_reserved_words_top++;
  177. return i;
  178. }
  179. void ink_push(struct context* ctx, struct elem value) {
  180. if(ctx->stack == NULL) {
  181. ctx->stack = ctx->malloc(sizeof(struct elem) * 8);
  182. ctx->top = 0;
  183. ctx->capacity = 8;
  184. } else if(ctx->top == ctx->capacity) {
  185. int new_count = (ctx->capacity + ctx->capacity/2);
  186. void* renewed = ctx->realloc(ctx->stack, sizeof(struct elem) * new_count);
  187. if(renewed == NULL) {
  188. // TODO: error
  189. } else {
  190. ctx->stack = renewed;
  191. ctx->capacity = new_count;
  192. }
  193. }
  194. ctx->stack[ctx->top] = value;
  195. ctx->top++;
  196. }
  197. void ink_push_fn(struct context* ctx, struct stack_frame value) {
  198. if(ctx->function_stack == NULL) {
  199. ctx->function_stack = ctx->malloc(sizeof(struct stack_frame) * 8);
  200. ctx->function_stack_top = 0;
  201. ctx->function_stack_capacity = 8;
  202. } else if(ctx->function_stack_top == ctx->function_stack_capacity) {
  203. int new_count = (ctx->function_stack_capacity + ctx->function_stack_capacity/2);
  204. void* renewed = ctx->realloc(ctx->function_stack, sizeof(struct stack_frame) * new_count);
  205. if(renewed == NULL) {
  206. // TODO: error
  207. } else {
  208. ctx->function_stack = renewed;
  209. ctx->function_stack_capacity = new_count;
  210. }
  211. }
  212. ctx->function_stack[ctx->function_stack_top] = value;
  213. ctx->function_stack_top++;
  214. }
  215. static void ink_pop_fn(struct context* ctx) {
  216. if(ctx->function_stack == NULL) return;
  217. if(ctx->function_stack_top == 0) return;
  218. ctx->function_stack_top--;
  219. }
  220. static void ink_pop(struct context* ctx) {
  221. if(ctx->stack == NULL) return;
  222. if(ctx->top == 0) return;
  223. ctx->top--;
  224. }
  225. struct context* ink_make_context(void*(*malloc)(size_t), void*(*realloc)(void*, size_t), void(*free)(void*), int(*putchar)(int)) {
  226. struct context* ctx = (struct context*)malloc(sizeof(struct context));
  227. ctx->malloc = malloc;
  228. ctx->realloc = realloc;
  229. ctx->free = free;
  230. ctx->putchar = putchar;
  231. ctx->panic = 0;
  232. ctx->stack = NULL;
  233. ctx->capacity = 0;
  234. ctx->top = 0;
  235. ctx->function_stack = NULL;
  236. ctx->function_stack_capacity = 0;
  237. ctx->function_stack_top = 0;
  238. ctx->native_words = NULL;
  239. ctx->native_words_capacity = 0;
  240. ctx->native_words_top = 0;
  241. ctx->words = NULL;
  242. ctx->words_capacity = 0;
  243. ctx->words_top = 0;
  244. ctx->lex_reserved_words = NULL;
  245. ctx->lex_reserved_words_capacity = 0;
  246. ctx->lex_reserved_words_top = 0;
  247. return ctx;
  248. }
  249. /**
  250. * Allocates a string that contains the integer
  251. * @param _ context (used to allocate)
  252. * @param cpy the value
  253. * @return the allocated string, needs to be freed by ctx->free
  254. */
  255. static char* ink_itoa(struct context* _, int cpy) {
  256. char* n = _->malloc(16);
  257. n[15] = 0;
  258. char* it = n+15;
  259. do {
  260. it--;
  261. *it = (cpy % 10) + '0';
  262. cpy = cpy / 10;
  263. } while(cpy);
  264. memmove(n, it, 16 - (it-n));
  265. return n;
  266. }
  267. #ifndef NOSTDLIB
  268. struct context* ink_make_default_context() {
  269. struct context* ctx = ink_make_context(malloc, realloc, free, putchar);
  270. ink_std_library(ctx);
  271. return ctx;
  272. }
  273. #endif
  274. static void ink_consume_one(int* end, struct context* pContext, char** buffer, char* r) {
  275. int i;
  276. if(*end == 0) {
  277. return;
  278. }
  279. r[*end] = 0;
  280. int done = 0;
  281. if (strcmp(r, _KEYWORD_INK_FUNCTION) == 0) {
  282. struct elem value;
  283. value.value = 0;
  284. value.type = INK_FUNCTION_KW;
  285. ink_push(pContext, value);
  286. done = 1;
  287. }
  288. if (!done && strcmp(r, _KEYWORD_INK_DO) == 0) {
  289. struct elem value;
  290. value.value = 0;
  291. value.type = INK_DO_KW;
  292. ink_push(pContext, value);
  293. done = 1;
  294. }
  295. if (!done && strcmp(r, _KEYWORD_INK_END) == 0) {
  296. struct elem value;
  297. value.value = 0;
  298. value.type = INK_END_KW;
  299. ink_push(pContext, value);
  300. done = 1;
  301. }
  302. if (!done && strcmp(r, _KEYWORD_INK_RETURN) == 0) {
  303. struct elem value;
  304. value.value = 0;
  305. value.type = INK_RETURN;
  306. ink_push(pContext, value);
  307. done = 1;
  308. }
  309. if (!done) {
  310. for (i = 0; i < pContext->words_top; ++i) {
  311. if (strcmp(r, pContext->words[i].name) == 0) {
  312. struct elem value;
  313. value.value = i;
  314. value.type = INK_FUNCTION;
  315. ink_push(pContext, value);
  316. done = 1;
  317. break;
  318. }
  319. }
  320. }
  321. if (!done) {
  322. for (i = 0; i < pContext->native_words_top; ++i) {
  323. if (strcmp(r, pContext->native_words[i].name) == 0) {
  324. struct elem value;
  325. value.value = i;
  326. value.type = INK_NATIVE_FUNCTION;
  327. ink_push(pContext, value);
  328. done = 1;
  329. break;
  330. }
  331. }
  332. }
  333. if (!done) {
  334. for(i = (r[0] == '-'); i < *end; i++) {
  335. if(!isdigit(r[i])){
  336. goto not_an_int;
  337. }
  338. }
  339. struct elem value;
  340. value.value = atoi(r);
  341. value.type = INK_INTEGER;
  342. ink_push(pContext, value);
  343. done = 1;
  344. }
  345. not_an_int: if (!done) {
  346. i = ink_add_lex_string(pContext, r);
  347. struct elem value;
  348. value.value = i;
  349. if(r[strlen(r) - 1] == ':') {
  350. value.type = INK_LABEL;
  351. } else {
  352. value.type = INK_RESERVED;
  353. }
  354. ink_push(pContext, value);
  355. }
  356. *end = 0;
  357. }
  358. static void ink_lex(struct context *pContext, char* buffer) {
  359. int i;
  360. char r[128];
  361. int end = 0;
  362. while(*buffer != 0) {
  363. if(isspace(*buffer)) {
  364. ink_consume_one(&end, pContext, &buffer, r);
  365. } else {
  366. r[end] = *buffer;
  367. ++end;
  368. }
  369. ++buffer;
  370. }
  371. ink_consume_one(&end, pContext, &buffer, r);
  372. }
  373. static int lblcmp(const char* label, const char* other, size_t label_sz) {
  374. while (label_sz != 1) {
  375. if(*other == 0) return 1;
  376. if(*label != *other) return 1;
  377. ++label;
  378. ++other;
  379. label_sz--;
  380. }
  381. return 0;
  382. }
  383. /**
  384. *
  385. * @param pContext
  386. * @param executable_buffer
  387. * @param executable_buffer_top
  388. * @internal Loop from hell
  389. */
  390. static void ink_parse(struct context* pContext, struct elem* executable_buffer, int* executable_buffer_top) {
  391. int i;
  392. #define LABEL_BUFFER 128
  393. #define FUNCTION_BUFFER 256
  394. struct label labels[LABEL_BUFFER];
  395. struct elem function_buffer[FUNCTION_BUFFER];
  396. int function_buffer_top = 0;
  397. int function_name = -1;
  398. #define MODE_EXECUTABLE 0
  399. #define MODE_FUNCTION 1
  400. #define MODE_DO 2
  401. int mode = 0;
  402. memset(labels, 0, sizeof(struct label)*LABEL_BUFFER);
  403. for(i = 0; i < pContext->top; ++i) {
  404. struct elem current = pContext->stack[i];
  405. switch (mode) {
  406. case MODE_EXECUTABLE:
  407. switch(current.type) {
  408. case INK_FUNCTION_KW:
  409. mode = MODE_FUNCTION;
  410. goto next_token;
  411. case INK_DO_KW:
  412. case INK_END_KW:
  413. // TODO: error
  414. default:
  415. executable_buffer[*executable_buffer_top] = current;
  416. *executable_buffer_top += 1;
  417. }
  418. break;
  419. case MODE_FUNCTION:
  420. if(current.type == INK_DO_KW) {
  421. if(function_name == -1) {
  422. // TODO: error (function name was not supplied)
  423. } else {
  424. mode = MODE_DO;
  425. memset(labels, 0, sizeof(struct label)*128);
  426. goto next_token;
  427. }
  428. }
  429. if(function_name != -1) {
  430. // TODO: error (function name supplied already)
  431. }
  432. if(current.type != INK_RESERVED) {
  433. // TODO: error
  434. }
  435. function_name = current.value;
  436. break;
  437. case MODE_DO:
  438. if(current.type == INK_END_KW) {
  439. int j;
  440. for(j = 0; j < function_buffer_top; j++) {
  441. struct elem pt = function_buffer[j];
  442. if(pt.type == INK_LABEL) {
  443. int k;
  444. for(k = 0; k < LABEL_BUFFER; k++) {
  445. if(labels[k].active) {
  446. if(strcmp(labels[k].name, pContext->lex_reserved_words[pt.value]) == 0) {
  447. labels[k].dest = j;
  448. // TODO: error
  449. break;
  450. }
  451. } else {
  452. labels[k].active = 1;
  453. labels[k].name = pContext->lex_reserved_words[pt.value];
  454. labels[k].dest = j;
  455. memcpy(function_buffer+j, function_buffer+j+1, sizeof(struct elem)*(function_buffer_top-j-1));
  456. function_buffer_top--;
  457. j--;
  458. break;
  459. }
  460. }
  461. }
  462. }
  463. for(j = 0; j < function_buffer_top; j++) {
  464. struct elem pt = function_buffer[j];
  465. if(pt.type == INK_RESERVED) {
  466. const char* str = pContext->lex_reserved_words[pt.value];
  467. int k;
  468. for(k = 0; k < LABEL_BUFFER; k++) {
  469. if(labels[k].active) {
  470. const char* lbl = labels[k].name;
  471. int label_sz = strlen(lbl);
  472. if(lblcmp(labels[k].name, pContext->lex_reserved_words[pt.value], label_sz) == 0) {
  473. function_buffer[j].type = INK_INTEGER;
  474. function_buffer[j].value = labels[k].dest - j;
  475. break;
  476. }
  477. } else break;
  478. }
  479. }
  480. }
  481. ink_add_indigenous(pContext, pContext->lex_reserved_words[function_name], function_buffer, function_buffer_top);
  482. function_buffer_top = 0;
  483. mode = MODE_EXECUTABLE;
  484. goto next_token;
  485. }
  486. function_buffer[function_buffer_top] = current;
  487. function_buffer_top += 1;
  488. break;
  489. }
  490. next_token: i=i;
  491. }
  492. if(mode == MODE_FUNCTION || mode == MODE_DO) {
  493. // error, missing an end
  494. }
  495. #undef MODE_EXECUTABLE
  496. #undef MODE_FUNCTION
  497. #undef MODE_DO
  498. #undef LABEL_BUFFER
  499. #undef FUNCTION_BUFFER
  500. }
  501. int ink_step(struct context *pContext) {
  502. if(pContext->function_stack_top == 0) return 0;
  503. if(pContext->panic) {
  504. return -1;
  505. }
  506. struct stack_frame* top = &pContext->function_stack[pContext->function_stack_top-1];
  507. switch(top->executing.type) {
  508. case INK_NATIVE_FUNCTION:
  509. if(top->index != 0) {
  510. ink_pop_fn(pContext);
  511. } else {
  512. top->index++;
  513. if(pContext->native_words_top <= top->executing.value) {
  514. pContext->panic = 1;
  515. return -1;
  516. }
  517. pContext->native_words[top->executing.value].value(pContext);
  518. }
  519. break;
  520. case INK_FUNCTION:
  521. if(pContext->words_top <= top->executing.value) {
  522. pContext->panic = 1;
  523. return -1;
  524. }
  525. if(top->index >= pContext->words[top->executing.value].size) {
  526. ink_pop_fn(pContext);
  527. } else {
  528. struct elem next = pContext->words[top->executing.value].things[top->index];
  529. if(next.type == INK_RETURN) {
  530. ink_pop_fn(pContext);
  531. return 1;
  532. }
  533. struct stack_frame frame;
  534. frame.executing = next;
  535. frame.index = 0;
  536. ink_push_fn(pContext, frame);
  537. top->index++;
  538. }
  539. break;
  540. default:
  541. ink_push(pContext, top->executing);
  542. ink_pop_fn(pContext);
  543. break;
  544. }
  545. return 1;
  546. }
  547. void ink_run(struct context *pContext, char* buffer) {
  548. pContext->free(pContext->stack);
  549. pContext->stack = NULL;
  550. pContext->top = 0;
  551. pContext->capacity = 0;
  552. ink_lex(pContext, buffer);
  553. int i = 0;
  554. struct elem executable_buffer[256];
  555. int executable_buffer_top = 0;
  556. ink_parse(pContext, executable_buffer, &executable_buffer_top);
  557. struct stack_frame frame;
  558. frame.executing.value = ink_add_indigenous(pContext, "__-MAIN-__", executable_buffer, executable_buffer_top);
  559. frame.executing.type = INK_FUNCTION;
  560. frame.index = 0;
  561. ink_push_fn(pContext, frame);
  562. int out;
  563. do {
  564. out = ink_step(pContext);
  565. } while(out > 0);
  566. }
  567. /**********************************************************************************************************************/
  568. static void print_stacktrace(struct context* _) {
  569. int i = 0;
  570. for(; i < _->function_stack_top; ++i) {
  571. struct elem thing = _->function_stack[i].executing;
  572. switch(thing.type) {
  573. case INK_NATIVE_FUNCTION: {
  574. char *n = _->native_words[thing.value].name;
  575. while (*n) {
  576. _->putchar(*n);
  577. ++n;
  578. }
  579. _->putchar(10);
  580. break;
  581. }
  582. case INK_FUNCTION:{
  583. char *n = _->native_words[thing.value].name;
  584. while (*n) {
  585. _->putchar(*n);
  586. ++n;
  587. }
  588. _->putchar(':');
  589. n = ink_itoa(_, _->function_stack[i].index);
  590. while (*n) {
  591. _->putchar(*n);
  592. ++n;
  593. }
  594. _->free(n);
  595. _->putchar(10);
  596. break;
  597. }
  598. default:
  599. break;
  600. }
  601. }
  602. }
  603. static void add_int(struct context* ctx) {
  604. if(ctx->top < 2) {
  605. ctx->panic = 1;
  606. return;
  607. }
  608. struct elem a = ctx->stack[ctx->top-1];
  609. struct elem b = ctx->stack[ctx->top-2];
  610. if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) {
  611. ctx->panic = 1;
  612. return;
  613. }
  614. ink_pop(ctx);
  615. ctx->stack[ctx->top-1].value = a.value + b.value;
  616. }
  617. static void sub_int(struct context* ctx) {
  618. if(ctx->top < 2) {
  619. ctx->panic = 1;
  620. return;
  621. }
  622. struct elem a = ctx->stack[ctx->top-1];
  623. struct elem b = ctx->stack[ctx->top-2];
  624. if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) {
  625. ctx->panic = 1;
  626. return;
  627. }
  628. ink_pop(ctx);
  629. ctx->stack[ctx->top-1].value = b.value - a.value;
  630. }
  631. static void mult_int(struct context* ctx) {
  632. if(ctx->top < 2) {
  633. ctx->panic = 1;
  634. return;
  635. }
  636. struct elem a = ctx->stack[ctx->top-1];
  637. struct elem b = ctx->stack[ctx->top-2];
  638. if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) {
  639. ctx->panic = 1;
  640. return;
  641. }
  642. ink_pop(ctx);
  643. ctx->stack[ctx->top-1].value = b.value * a.value;
  644. }
  645. static void div_int(struct context* ctx) {
  646. if(ctx->top < 2) {
  647. ctx->panic = 1;
  648. return;
  649. }
  650. struct elem a = ctx->stack[ctx->top-1];
  651. struct elem b = ctx->stack[ctx->top-2];
  652. if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) {
  653. ctx->panic = 1;
  654. return;
  655. }
  656. ink_pop(ctx);
  657. ctx->stack[ctx->top-1].value = b.value / a.value;
  658. }
  659. static void rem_int(struct context* ctx) {
  660. if(ctx->top < 2) {
  661. ctx->panic = 1;
  662. return;
  663. }
  664. struct elem a = ctx->stack[ctx->top-1];
  665. struct elem b = ctx->stack[ctx->top-2];
  666. if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) {
  667. ctx->panic = 1;
  668. return;
  669. }
  670. ink_pop(ctx);
  671. ctx->stack[ctx->top-1].value = b.value % a.value;
  672. }
  673. static void dupe_elem(struct context* ctx) {
  674. if(ctx->top < 1) {
  675. ctx->panic = 1;
  676. return;
  677. }
  678. struct elem a = ctx->stack[ctx->top-1];
  679. ink_push(ctx, a);
  680. }
  681. static void drop_elem(struct context* ctx) {
  682. if(ctx->top < 1) {
  683. ctx->panic = 1;
  684. return;
  685. }
  686. ink_pop(ctx);
  687. }
  688. static void pluck_elem(struct context* ctx) {
  689. if(ctx->top < 1) {
  690. ctx->panic = 1;
  691. return;
  692. }
  693. struct elem a = ctx->stack[ctx->top-1];
  694. if(a.type != INK_INTEGER) {
  695. ctx->panic = 1;
  696. return;
  697. }
  698. int position = ctx->top - (a.value + 1);
  699. if(position >= ctx->top || position < 0) {
  700. ctx->panic = 1;
  701. return;
  702. }
  703. ink_pop(ctx);
  704. ink_push(ctx, ctx->stack[position]);
  705. }
  706. static void swap_elem(struct context* ctx) {
  707. if(ctx->top < 2) {
  708. ctx->panic = 1;
  709. return;
  710. }
  711. struct elem a = ctx->stack[ctx->top-1];
  712. struct elem b = ctx->stack[ctx->top-2];
  713. ctx->stack[ctx->top-2] = a;
  714. ctx->stack[ctx->top-1] = b;
  715. }
  716. static void return_if(struct context* ctx) {
  717. if(ctx->top < 1) {
  718. ctx->panic = 1;
  719. return;
  720. }
  721. struct elem a = ctx->stack[ctx->top-1];
  722. if(a.type != INK_INTEGER) {
  723. ctx->panic = 1;
  724. return;
  725. }
  726. if(a.value) {
  727. ink_pop_fn(ctx);
  728. ink_pop_fn(ctx);
  729. }
  730. ink_pop(ctx);
  731. return;
  732. }
  733. static void jump_if(struct context* ctx) {
  734. if(ctx->top < 1) {
  735. ctx->panic = 1;
  736. return;
  737. }
  738. struct elem a = ctx->stack[ctx->top-1];
  739. if(a.type != INK_INTEGER) {
  740. ctx->panic = 1;
  741. return;
  742. }
  743. ink_pop(ctx);
  744. if(a.value) {
  745. ink_pop_fn(ctx);
  746. a = ctx->stack[ctx->top-1];
  747. ctx->function_stack[ctx->function_stack_top - 1].index += a.value - 3;
  748. ink_pop(ctx);
  749. //printf("\t*%d\n", ctx->function_stack[ctx->function_stack_top - 1].index);
  750. }
  751. return;
  752. }
  753. static void print_int(struct context* ctx) {
  754. if(ctx->top < 1 || ctx->stack[ctx->top-1].type != INK_INTEGER) {
  755. ctx->panic = 1;
  756. return;
  757. }
  758. struct elem a = ctx->stack[ctx->top-1];
  759. ink_pop(ctx);
  760. char* n = ink_itoa(ctx, a.value);
  761. char* str = n;
  762. while (*str) {
  763. ctx->putchar(*str);
  764. ++str;
  765. }
  766. ctx->free(n);
  767. }
  768. static void print_as_utf8(struct context* ctx) {
  769. if(ctx->top < 1 || ctx->stack[ctx->top-1].type != INK_INTEGER) {
  770. ctx->panic = 1;
  771. return;
  772. }
  773. struct elem a = ctx->stack[ctx->top-1];
  774. if(a.value <= 0x7F) {
  775. ctx->putchar(a.value);
  776. } else if(a.value <= 0x7FF) {
  777. ctx->putchar(((a.value & 0xFC0) >> 6) | 192);
  778. ctx->putchar((a.value & 0x3F) | 128);
  779. } else if(a.value <= 0xFFFF) {
  780. ctx->putchar(((a.value & 0x3F000) >> 12) | 224);
  781. ctx->putchar(((a.value & 0xFC0) >> 6) | 128);
  782. ctx->putchar((a.value & 0x3F) | 128);
  783. } else if(a.value <= 0x10FFFF) {
  784. ctx->putchar(((a.value & 0x3C0000) >> 18) | 240);
  785. ctx->putchar(((a.value & 0x3F000) >> 12) | 128);
  786. ctx->putchar(((a.value & 0xFC0) >> 6) | 128);
  787. ctx->putchar((a.value & 0x3F) | 128);
  788. } else {
  789. ctx->panic = 1;
  790. return;
  791. }
  792. ink_pop(ctx);
  793. }
  794. void ink_std_library(struct context* ctx) {
  795. ink_add_native(ctx, "trace", print_stacktrace);
  796. ink_add_native(ctx, "print_int", print_int);
  797. ink_add_native(ctx, "print_utf8", print_as_utf8);
  798. ink_add_native(ctx, "+", add_int);
  799. ink_add_native(ctx, "-", sub_int);
  800. ink_add_native(ctx, "*", mult_int);
  801. ink_add_native(ctx, "/", div_int);
  802. ink_add_native(ctx, "%", rem_int);
  803. ink_add_native(ctx, "swap", swap_elem);
  804. ink_add_native(ctx, "dup", dupe_elem);
  805. ink_add_native(ctx, "drop", drop_elem);
  806. ink_add_native(ctx, "pluck", pluck_elem);
  807. ink_add_native(ctx, "return_if", return_if);
  808. ink_add_native(ctx, "jump_if", jump_if);
  809. }