cf.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. // gcc -g -o cf cf.c && ./cf t1.w
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <stdint.h>
  5. #include <string.h>
  6. struct entry {
  7. char *name;
  8. void *code;
  9. void (*interpreter)(void *);
  10. struct entry *next;
  11. };
  12. struct entry *dictionary = NULL;
  13. void init_vm(void);
  14. struct entry *add_word(char *name, void *, void (*interpreter)(void *));
  15. struct entry *find_word(char *name);
  16. char *read_word(FILE *fptr);
  17. struct entry **load_code(FILE *fptr);
  18. void interpret(void *);
  19. #define STACK_SIZE 1000
  20. uint64_t stack[STACK_SIZE];
  21. uint64_t *stack_ptr;
  22. int main(int argc, char **argv) {
  23. FILE *fptr;
  24. if(argc != 2) {
  25. puts("./cf <filename>");
  26. return 1;
  27. }
  28. fptr = fopen(argv[1], "r");
  29. if(!fptr) {
  30. puts("open");
  31. return 2;
  32. }
  33. init_vm();
  34. interpret(load_code(fptr));
  35. return 0;
  36. }
  37. void bltn_one(void *code) {
  38. stack_ptr++;
  39. *stack_ptr = 1;
  40. }
  41. void bltn_dot(void *code) {
  42. printf("%lld\n", *stack_ptr);
  43. stack_ptr--;
  44. }
  45. void bltn_add(void *code) {
  46. uint64_t tmp;
  47. tmp = *stack_ptr;
  48. stack_ptr--;
  49. stack_ptr[0] += tmp;
  50. }
  51. void bltn_dup(void *code) {
  52. uint64_t tmp;
  53. tmp = *stack_ptr;
  54. stack_ptr++;
  55. *stack_ptr = tmp;
  56. }
  57. void init_vm(void) {
  58. stack_ptr = stack;
  59. add_word("one", NULL, bltn_one);
  60. add_word("dot", NULL, bltn_dot);
  61. add_word("add", NULL, bltn_add);
  62. add_word("dup", NULL, bltn_dup);
  63. }
  64. struct entry *add_word(char *name, void *code, void (*interpreter)(void *)) {
  65. struct entry *ent;
  66. ent = malloc(sizeof(struct entry));
  67. ent->name = name;
  68. ent->code = code;
  69. ent->interpreter = interpreter;
  70. ent->next = dictionary;
  71. dictionary = ent;
  72. return ent;
  73. }
  74. void bltn_lit(void *code) {
  75. uint64_t *n;
  76. n = code;
  77. stack_ptr++;
  78. *stack_ptr = n[0];
  79. }
  80. struct entry *find_word(char *name) {
  81. struct entry *ent;
  82. ent = dictionary;
  83. while(ent) {
  84. if(ent->name && !strcmp(ent->name, name)) {
  85. return ent;
  86. }
  87. ent = ent->next;
  88. }
  89. }
  90. char *read_word(FILE *fptr) {
  91. int c, i;
  92. static char *wbuf;
  93. static int wlen;
  94. if(feof(fptr)) {
  95. return NULL;
  96. }
  97. c = fgetc(fptr);
  98. if(c == EOF) {
  99. return NULL;
  100. }
  101. if(!wbuf) {
  102. wlen = 64;
  103. wbuf = malloc(wlen);
  104. }
  105. i = 0;
  106. do {
  107. wbuf[i++] = c;
  108. if(!c) break;
  109. if(i > wlen) {
  110. wlen *= 2;
  111. wbuf = realloc(wbuf, wlen);
  112. }
  113. } while((c = fgetc(fptr)) != EOF);
  114. return wbuf;
  115. }
  116. struct entry ** load_code(FILE *fptr) {
  117. char *word;
  118. struct entry *ent;
  119. struct entry **code;
  120. int code_len;
  121. char *sub_name;
  122. struct entry **sub_code;
  123. int i;
  124. uint64_t tmp, *tmp2;
  125. code_len = 1;
  126. code = malloc(code_len * sizeof(struct entry *));
  127. i = 0;
  128. while(word = read_word(fptr)) {
  129. //printf("read word <%s>\n", word);
  130. // IMMEDIATES are hard coded
  131. // in a proper forth you can define your own immediates
  132. if(!strcmp(";", word)) {
  133. code[i] = NULL;
  134. return code;
  135. }
  136. else if(!strcmp(":", word)) {
  137. sub_name = strdup(read_word(fptr));
  138. sub_code = load_code(fptr);
  139. add_word(sub_name, sub_code, interpret);
  140. continue;
  141. }
  142. else if(!strcmp("lit", word)) {
  143. word = read_word(fptr);
  144. if(1 != sscanf(word, "%lld", &tmp)) {
  145. printf("couldn't read a number from <%s>\n", word);
  146. exit(-1);
  147. }
  148. tmp2 = malloc(sizeof(uint64_t));
  149. tmp2[0] = tmp;
  150. ent = add_word(NULL, tmp2, bltn_lit);
  151. }
  152. else {
  153. ent = find_word(word);
  154. if(!ent) {
  155. printf("Could not find word <%s>\n", word);
  156. exit(-1);
  157. }
  158. }
  159. code[i++] = ent;
  160. if(i > code_len) {
  161. code_len *= 2;
  162. code = realloc(code, code_len * sizeof(struct entry*));
  163. }
  164. }
  165. code[i] = NULL;
  166. return code;
  167. }
  168. void interpret(void *code_v) {
  169. struct entry **code = code_v;
  170. struct entry *ent;
  171. while(ent = *code++) { ent->interpreter(ent->code); }
  172. }