A minimalistic programming language written in C89.
25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.

951 satır
22 KiB

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