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.

548 lines
14 KiB

6 months ago
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <ctype.h>
  5. #include "ink.h"
  6. #define INK_RESERVED (-1)
  7. #define INK_FUNCTION_KW (-2)
  8. #define INK_DO_KW (-3)
  9. #define INK_END_KW (-4)
  10. #define INK_LABEL (-5)
  11. #define INK_RETURN (-6)
  12. #define _KEYWORD_INK_FUNCTION "fn"
  13. #define _KEYWORD_INK_DO "do"
  14. #define _KEYWORD_INK_END "end"
  15. struct label {
  16. int active;
  17. int dest;
  18. char* name;
  19. };
  20. void ink_add_native(struct context* ctx, const char* name, void(*value)(struct context*)) {
  21. if(ctx->native_words == NULL) {
  22. ctx->native_words = ctx->malloc(sizeof(struct native_fn) * 8);
  23. ctx->native_words_top = 0;
  24. ctx->native_words_capacity = 8;
  25. } else if(ctx->native_words_top == ctx->native_words_capacity) {
  26. int new_count = (ctx->native_words_capacity + ctx->native_words_capacity/2);
  27. void* renewed = ctx->realloc(ctx->native_words, sizeof(struct native_fn) * new_count);
  28. if(renewed == NULL) {
  29. // TODO: error
  30. } else {
  31. ctx->native_words = renewed;
  32. ctx->native_words_capacity = new_count;
  33. }
  34. }
  35. int len = strlen(name);
  36. char* copy = ctx->malloc(len+1);
  37. if(copy == NULL) {
  38. // TODO: error
  39. }
  40. memcpy(copy, name, len);
  41. copy[len] = 0;
  42. ctx->native_words[ctx->native_words_top].value = value;
  43. ctx->native_words[ctx->native_words_top].name = copy;
  44. ctx->native_words_top++;
  45. }
  46. static int ink_add_indigenous(struct context* ctx, const char* name, struct elem* m, size_t count) {
  47. if(ctx->words == NULL) {
  48. ctx->words = ctx->malloc(sizeof(struct fn) * 8);
  49. ctx->words_top = 0;
  50. ctx->words_capacity = 8;
  51. } else if(ctx->words_top == ctx->words_capacity) {
  52. int new_count = (ctx->words_capacity + ctx->words_capacity/2);
  53. void* renewed = ctx->realloc(ctx->words, sizeof(struct native_fn) * new_count);
  54. if(renewed == NULL) {
  55. // TODO: error
  56. } else {
  57. ctx->words = renewed;
  58. ctx->words_capacity = new_count;
  59. }
  60. }
  61. int i;
  62. for(i = 0; i < ctx->words_top; ++i) {
  63. if(strcmp(name, ctx->words[i].name) == 0) {
  64. ctx->free(ctx->words[i].things);
  65. ctx->words[i].things = malloc(sizeof(struct elem) * count);
  66. memcpy(ctx->words[i].things, m, sizeof(struct elem) * count);
  67. ctx->words[i].size = count;
  68. return i;
  69. }
  70. }
  71. int len = strlen(name);
  72. char* copy = ctx->malloc(len+1);
  73. if(copy == NULL) {
  74. // TODO: error
  75. }
  76. memcpy(copy, name, len);
  77. copy[len] = 0;
  78. ctx->words[ctx->words_top].things = malloc(sizeof(struct elem) * count);
  79. memcpy(ctx->words[ctx->words_top].things, m, sizeof(struct elem) * count);
  80. ctx->words[ctx->words_top].size = count;
  81. ctx->words[ctx->words_top].name = copy;
  82. return ctx->words_top++;
  83. }
  84. static int ink_add_lex_string(struct context* ctx, const char* name) {
  85. int i;
  86. if(ctx->lex_reserved_words == NULL) {
  87. ctx->lex_reserved_words = ctx->malloc(sizeof(char*) * 8);
  88. ctx->lex_reserved_words_top = 0;
  89. ctx->lex_reserved_words_capacity = 8;
  90. } else if(ctx->lex_reserved_words_top == ctx->lex_reserved_words_capacity) {
  91. int new_count = (ctx->lex_reserved_words_capacity + ctx->lex_reserved_words_capacity/2);
  92. void* renewed = ctx->realloc(ctx->lex_reserved_words, sizeof(struct native_fn) * new_count);
  93. if(renewed == NULL) {
  94. // TODO: error
  95. } else {
  96. ctx->lex_reserved_words = renewed;
  97. ctx->lex_reserved_words_capacity = new_count;
  98. }
  99. }
  100. for(i = 0; i < ctx->lex_reserved_words_top; i++) {
  101. if(strcmp(ctx->lex_reserved_words[i], name) == 0) {
  102. return i;
  103. }
  104. }
  105. int len = strlen(name);
  106. i = ctx->lex_reserved_words_top;
  107. ctx->lex_reserved_words[i] = malloc(len+1);
  108. memcpy(ctx->lex_reserved_words[i], name, len);
  109. ctx->lex_reserved_words[i][len] = 0;
  110. ctx->lex_reserved_words_top++;
  111. return i;
  112. }
  113. void ink_push(struct context* ctx, struct elem value) {
  114. if(ctx->stack == NULL) {
  115. ctx->stack = ctx->malloc(sizeof(struct elem) * 8);
  116. ctx->top = 0;
  117. ctx->capacity = 8;
  118. } else if(ctx->top == ctx->capacity) {
  119. int new_count = (ctx->capacity + ctx->capacity/2);
  120. void* renewed = ctx->realloc(ctx->stack, sizeof(struct elem) * new_count);
  121. if(renewed == NULL) {
  122. // TODO: error
  123. } else {
  124. ctx->stack = renewed;
  125. ctx->capacity = new_count;
  126. }
  127. }
  128. ctx->stack[ctx->top] = value;
  129. ctx->top++;
  130. }
  131. void ink_push_fn(struct context* ctx, struct stack_frame value) {
  132. if(ctx->function_stack == NULL) {
  133. ctx->function_stack = ctx->malloc(sizeof(struct stack_frame) * 8);
  134. ctx->function_stack_top = 0;
  135. ctx->function_stack_capacity = 8;
  136. } else if(ctx->function_stack_top == ctx->function_stack_capacity) {
  137. int new_count = (ctx->function_stack_capacity + ctx->function_stack_capacity/2);
  138. void* renewed = ctx->realloc(ctx->function_stack, sizeof(struct stack_frame) * new_count);
  139. if(renewed == NULL) {
  140. // TODO: error
  141. } else {
  142. ctx->function_stack = renewed;
  143. ctx->function_stack_capacity = new_count;
  144. }
  145. }
  146. ctx->function_stack[ctx->function_stack_top] = value;
  147. ctx->function_stack_top++;
  148. }
  149. static void ink_pop_fn(struct context* ctx) {
  150. if(ctx->function_stack == NULL) return;
  151. if(ctx->function_stack_top == 0) return;
  152. ctx->function_stack_top--;
  153. }
  154. static void ink_pop(struct context* ctx) {
  155. if(ctx->stack == NULL) return;
  156. if(ctx->top == 0) return;
  157. ctx->top--;
  158. }
  159. struct context* ink_make_context(void*(*malloc)(size_t), void*(*realloc)(void*, size_t), void(*free)(void*)) {
  160. struct context* ctx = (struct context*)malloc(sizeof(struct context));
  161. ctx->malloc = malloc;
  162. ctx->realloc = realloc;
  163. ctx->free = free;
  164. ctx->panic = 0;
  165. ctx->stack = NULL;
  166. ctx->capacity = 0;
  167. ctx->top = 0;
  168. ctx->function_stack = NULL;
  169. ctx->function_stack_capacity = 0;
  170. ctx->function_stack_top = 0;
  171. ctx->native_words = NULL;
  172. ctx->native_words_capacity = 0;
  173. ctx->native_words_top = 0;
  174. ctx->words = NULL;
  175. ctx->words_capacity = 0;
  176. ctx->words_top = 0;
  177. ctx->lex_reserved_words = NULL;
  178. ctx->lex_reserved_words_capacity = 0;
  179. ctx->lex_reserved_words_top = 0;
  180. return ctx;
  181. }
  182. static void print_stacktrace(struct context* _) {
  183. int i = 0;
  184. for(; i < _->function_stack_top; ++i) {
  185. struct elem thing = _->function_stack[i].executing;
  186. switch(thing.type) {
  187. case INK_NATIVE_FUNCTION:
  188. printf("%s\n", _->native_words[thing.value].name);
  189. break;
  190. case INK_FUNCTION:
  191. printf("%s:%d\n", _->words[thing.value].name, _->function_stack[i].index);
  192. break;
  193. default:
  194. break;
  195. }
  196. }
  197. }
  198. static void add_int(struct context* ctx) {
  199. if(ctx->top < 2) {
  200. ctx->panic = 1;
  201. return;
  202. }
  203. struct elem a = ctx->stack[ctx->top-1];
  204. struct elem b = ctx->stack[ctx->top-2];
  205. if(!(a.type == INK_INTEGER && b.type == INK_INTEGER)) {
  206. ctx->panic = 1;
  207. return;
  208. }
  209. ink_pop(ctx);
  210. ctx->stack[ctx->top-1].value = a.value + b.value;
  211. }
  212. static void print_int(struct context* ctx) {
  213. if(ctx->top < 1 || ctx->stack[ctx->top-1].type != INK_INTEGER) {
  214. ctx->panic = 1;
  215. return;
  216. }
  217. struct elem a = ctx->stack[ctx->top-1];
  218. ink_pop(ctx);
  219. printf("%d", a.value);
  220. }
  221. static void print_as_utf8(struct context* ctx) {
  222. if(ctx->top < 1 || ctx->stack[ctx->top-1].type != INK_INTEGER) {
  223. ctx->panic = 1;
  224. return;
  225. }
  226. struct elem a = ctx->stack[ctx->top-1];
  227. if(a.value <= 0x7F) {
  228. putc(a.value, stdout);
  229. } else if(a.value <= 0x7FF) {
  230. putc(((a.value & 0xFC0) >> 6) | 192, stdout);
  231. putc((a.value & 0x3F) | 128, stdout);
  232. } else if(a.value <= 0xFFFF) {
  233. putc(((a.value & 0x3F000) >> 12) | 224, stdout);
  234. putc(((a.value & 0xFC0) >> 6) | 128, stdout);
  235. putc((a.value & 0x3F) | 128, stdout);
  236. } else if(a.value <= 0x10FFFF) {
  237. putc(((a.value & 0x3C0000) >> 18) | 240, stdout);
  238. putc(((a.value & 0x3F000) >> 12) | 128, stdout);
  239. putc(((a.value & 0xFC0) >> 6) | 128, stdout);
  240. putc((a.value & 0x3F) | 128, stdout);
  241. } else {
  242. ctx->panic = 1;
  243. return;
  244. }
  245. ink_pop(ctx);
  246. }
  247. struct context* ink_make_default_context() {
  248. struct context* ctx = ink_make_context(malloc, realloc, free);
  249. ink_add_native(ctx, "trace", print_stacktrace);
  250. ink_add_native(ctx, "print_int", print_int);
  251. ink_add_native(ctx, "print_utf8", print_as_utf8);
  252. ink_add_native(ctx, "+", add_int);
  253. return ctx;
  254. }
  255. static void ink_consume_one(int* end, struct context* pContext, char** buffer, char* r) {
  256. int i;
  257. if(*end == 0) {
  258. return;
  259. }
  260. r[*end] = 0;
  261. int done = 0;
  262. if (strcmp(r, _KEYWORD_INK_FUNCTION) == 0) {
  263. struct elem value;
  264. value.value = 0;
  265. value.type = INK_FUNCTION_KW;
  266. ink_push(pContext, value);
  267. done = 1;
  268. }
  269. if (!done && strcmp(r, _KEYWORD_INK_DO) == 0) {
  270. struct elem value;
  271. value.value = 0;
  272. value.type = INK_DO_KW;
  273. ink_push(pContext, value);
  274. done = 1;
  275. }
  276. if (!done && strcmp(r, _KEYWORD_INK_END) == 0) {
  277. struct elem value;
  278. value.value = 0;
  279. value.type = INK_END_KW;
  280. ink_push(pContext, value);
  281. done = 1;
  282. }
  283. if (!done) {
  284. for (i = 0; i < pContext->words_top; ++i) {
  285. if (strcmp(r, pContext->words[i].name) == 0) {
  286. struct elem value;
  287. value.value = i;
  288. value.type = INK_FUNCTION;
  289. ink_push(pContext, value);
  290. done = 1;
  291. break;
  292. }
  293. }
  294. }
  295. if (!done) {
  296. for (i = 0; i < pContext->native_words_top; ++i) {
  297. if (strcmp(r, pContext->native_words[i].name) == 0) {
  298. struct elem value;
  299. value.value = i;
  300. value.type = INK_NATIVE_FUNCTION;
  301. ink_push(pContext, value);
  302. done = 1;
  303. break;
  304. }
  305. }
  306. }
  307. if (!done) {
  308. for(i = (r[0] == '-'); i < *end; i++) {
  309. if(!isdigit(r[i])){
  310. goto not_an_int;
  311. }
  312. }
  313. struct elem value;
  314. value.value = atoi(r);
  315. value.type = INK_INTEGER;
  316. ink_push(pContext, value);
  317. done = 1;
  318. }
  319. not_an_int: if (!done) {
  320. i = ink_add_lex_string(pContext, r);
  321. struct elem value;
  322. value.value = i;
  323. if(r[strlen(r) - 1] == ':') {
  324. value.type = INK_LABEL;
  325. } else {
  326. value.type = INK_RESERVED;
  327. }
  328. ink_push(pContext, value);
  329. }
  330. *end = 0;
  331. }
  332. static void ink_lex(struct context *pContext, char* buffer) {
  333. int i;
  334. char r[128];
  335. int end = 0;
  336. while(*buffer != 0) {
  337. if(isspace(*buffer)) {
  338. ink_consume_one(&end, pContext, &buffer, r);
  339. } else {
  340. r[end] = *buffer;
  341. ++end;
  342. }
  343. ++buffer;
  344. }
  345. ink_consume_one(&end, pContext, &buffer, r);
  346. }
  347. static int lblcmp(const char* label, const char* other, size_t label_sz) {
  348. while (label_sz != 1) {
  349. if(*other == 0) return 1;
  350. if(*label != *other) return 1;
  351. ++label;
  352. ++other;
  353. label_sz--;
  354. }
  355. return 0;
  356. }
  357. static void ink_parse(struct context* pContext, struct elem* executable_buffer, int* executable_buffer_top) {
  358. int i;
  359. struct label labels[128];
  360. struct elem function_buffer[256];
  361. int function_buffer_top = 0;
  362. int function_name = -1;
  363. #define MODE_EXECUTABLE 0
  364. #define MODE_FUNCTION 1
  365. #define MODE_DO 2
  366. int mode = 0;
  367. memset(labels, 0, sizeof(struct label)*128);
  368. for(i = 0; i < pContext->top; ++i) {
  369. struct elem current = pContext->stack[i];
  370. switch (mode) {
  371. case MODE_EXECUTABLE:
  372. switch(current.type) {
  373. case INK_FUNCTION_KW:
  374. mode = MODE_FUNCTION;
  375. goto next_token;
  376. case INK_DO_KW:
  377. case INK_END_KW:
  378. // TODO: error
  379. default:
  380. executable_buffer[*executable_buffer_top] = current;
  381. *executable_buffer_top += 1;
  382. }
  383. break;
  384. case MODE_FUNCTION:
  385. if(current.type == INK_DO_KW) {
  386. if(function_name == -1) {
  387. // TODO: error (function name was not supplied)
  388. } else {
  389. mode = MODE_DO;
  390. memset(labels, 0, sizeof(struct label)*128);
  391. goto next_token;
  392. }
  393. }
  394. if(function_name != -1) {
  395. // TODO: error (function name supplied already)
  396. }
  397. if(current.type != INK_RESERVED) {
  398. // TODO: error
  399. }
  400. function_name = current.value;
  401. break;
  402. case MODE_DO:
  403. if(current.type == INK_END_KW) {
  404. int j;
  405. for(j = 0; j < function_buffer_top; j++) {
  406. struct elem pt = function_buffer[j];
  407. if(pt.type == INK_LABEL) {
  408. int k;
  409. for(k = 0; k < 128; k++) {
  410. if(labels[k].active) {
  411. if(strcmp(labels[k].name, pContext->lex_reserved_words[pt.value]) == 0) {
  412. labels[k].dest = j;
  413. // TODO: error
  414. break;
  415. }
  416. } else {
  417. labels[k].active = 1;
  418. labels[k].name = pContext->lex_reserved_words[pt.value];
  419. labels[k].dest = j;
  420. memcpy(function_buffer+j, function_buffer+j+1, sizeof(struct elem)*(function_buffer_top-j-1));
  421. function_buffer_top--;
  422. j--;
  423. break;
  424. }
  425. }
  426. }
  427. }
  428. for(j = 0; j < function_buffer_top; j++) {
  429. struct elem pt = function_buffer[j];
  430. if(pt.type == INK_RESERVED) {
  431. const char* str = pContext->lex_reserved_words[pt.value];
  432. int k;
  433. for(k = 0; k < 128; k++) {
  434. if(labels[k].active) {
  435. const char* lbl = labels[k].name;
  436. int label_sz = strlen(lbl);
  437. if(lblcmp(labels[k].name, pContext->lex_reserved_words[pt.value], label_sz) == 0) {
  438. function_buffer[j].type = INK_INTEGER;
  439. function_buffer[j].value = labels[k].dest - j;
  440. break;
  441. }
  442. } else break;
  443. }
  444. }
  445. }
  446. ink_add_indigenous(pContext, pContext->lex_reserved_words[function_name], function_buffer, function_buffer_top);
  447. function_buffer_top = 0;
  448. mode = MODE_EXECUTABLE;
  449. goto next_token;
  450. }
  451. function_buffer[function_buffer_top] = current;
  452. function_buffer_top += 1;
  453. break;
  454. }
  455. next_token: i=i;
  456. }
  457. if(mode == MODE_FUNCTION || mode == MODE_DO) {
  458. // error, missing an end
  459. }
  460. #undef MODE_EXECUTABLE
  461. #undef MODE_FUNCTION
  462. #undef MODE_DO
  463. }
  464. int ink_step(struct context *pContext) {
  465. if(pContext->function_stack_top == 0) return 0;
  466. if(pContext->panic) {
  467. perror("PANIC!!!\n");
  468. return -1;
  469. }
  470. struct stack_frame* top = &pContext->function_stack[pContext->function_stack_top-1];
  471. switch(top->executing.type) {
  472. case INK_NATIVE_FUNCTION:
  473. if(top->index != 0) {
  474. ink_pop_fn(pContext);
  475. } else {
  476. top->index++;
  477. if(pContext->native_words_top <= top->executing.value) {
  478. pContext->panic = 1;
  479. return -1;
  480. }
  481. pContext->native_words[top->executing.value].value(pContext);
  482. }
  483. break;
  484. case INK_FUNCTION:
  485. if(pContext->words_top <= top->executing.value) {
  486. pContext->panic = 1;
  487. return -1;
  488. }
  489. if(top->index >= pContext->words[top->executing.value].size) {
  490. ink_pop_fn(pContext);
  491. } else {
  492. struct stack_frame frame;
  493. frame.executing = pContext->words[top->executing.value].things[top->index];
  494. frame.index = 0;
  495. ink_push_fn(pContext, frame);
  496. top->index++;
  497. }
  498. break;
  499. default:
  500. ink_push(pContext, top->executing);
  501. ink_pop_fn(pContext);
  502. break;
  503. }
  504. return 1;
  505. }
  506. void ink_run(struct context *pContext, char* buffer) {
  507. pContext->free(pContext->stack);
  508. pContext->stack = NULL;
  509. pContext->top = 0;
  510. pContext->capacity = 0;
  511. ink_lex(pContext, buffer);
  512. int i = 0;
  513. struct elem executable_buffer[256];
  514. int executable_buffer_top = 0;
  515. ink_parse(pContext, executable_buffer, &executable_buffer_top);
  516. struct stack_frame frame;
  517. frame.executing.value = ink_add_indigenous(pContext, "__-MAIN-__", executable_buffer, executable_buffer_top);
  518. frame.executing.type = INK_FUNCTION;
  519. frame.index = 0;
  520. ink_push_fn(pContext, frame);
  521. int out;
  522. do {
  523. out = ink_step(pContext);
  524. } while(out > 0);
  525. }