123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229 |
- // gcc -g -o cf cf.c && ./cf t1.w
- #include <stdio.h>
- #include <stdlib.h>
- #include <stdint.h>
- #include <string.h>
- struct entry {
- char *name;
- void *code;
- void (*interpreter)(void *);
- struct entry *next;
- };
- struct entry *dictionary = NULL;
- void init_vm(void);
- struct entry *add_word(char *name, void *, void (*interpreter)(void *));
- struct entry *find_word(char *name);
- char *read_word(FILE *fptr);
- struct entry **load_code(FILE *fptr);
- void interpret(void *);
- #define STACK_SIZE 1000
- uint64_t stack[STACK_SIZE];
- uint64_t *stack_ptr;
- int main(int argc, char **argv) {
- FILE *fptr;
-
- if(argc != 2) {
- puts("./cf <filename>");
- return 1;
- }
-
- fptr = fopen(argv[1], "r");
- if(!fptr) {
- puts("open");
- return 2;
- }
- init_vm();
- interpret(load_code(fptr));
-
- return 0;
- }
- void bltn_one(void *code) {
- stack_ptr++;
- *stack_ptr = 1;
- }
- void bltn_dot(void *code) {
- printf("%lld\n", *stack_ptr);
- stack_ptr--;
- }
- void bltn_add(void *code) {
- uint64_t tmp;
- tmp = *stack_ptr;
- stack_ptr--;
- stack_ptr[0] += tmp;
- }
- void bltn_dup(void *code) {
- uint64_t tmp;
- tmp = *stack_ptr;
- stack_ptr++;
- *stack_ptr = tmp;
- }
- void init_vm(void) {
- stack_ptr = stack;
-
- add_word("one", NULL, bltn_one);
- add_word("dot", NULL, bltn_dot);
- add_word("add", NULL, bltn_add);
- add_word("dup", NULL, bltn_dup);
- }
- struct entry *add_word(char *name, void *code, void (*interpreter)(void *)) {
- struct entry *ent;
- ent = malloc(sizeof(struct entry));
- ent->name = name;
- ent->code = code;
- ent->interpreter = interpreter;
- ent->next = dictionary;
-
- dictionary = ent;
- return ent;
- }
- void bltn_lit(void *code) {
- uint64_t *n;
- n = code;
-
- stack_ptr++;
- *stack_ptr = n[0];
- }
- struct entry *find_word(char *name) {
- struct entry *ent;
- ent = dictionary;
- while(ent) {
- if(ent->name && !strcmp(ent->name, name)) {
- return ent;
- }
-
- ent = ent->next;
- }
- }
- char *read_word(FILE *fptr) {
- int c, i;
- static char *wbuf;
- static int wlen;
-
- if(feof(fptr)) {
- return NULL;
- }
- c = fgetc(fptr);
- if(c == EOF) {
- return NULL;
- }
- if(!wbuf) {
- wlen = 64;
- wbuf = malloc(wlen);
- }
-
- i = 0;
- do {
- wbuf[i++] = c;
-
- if(!c) break;
-
- if(i > wlen) {
- wlen *= 2;
- wbuf = realloc(wbuf, wlen);
- }
- } while((c = fgetc(fptr)) != EOF);
-
- return wbuf;
- }
- struct entry ** load_code(FILE *fptr) {
- char *word;
- struct entry *ent;
-
- struct entry **code;
- int code_len;
-
- char *sub_name;
- struct entry **sub_code;
-
- int i;
- uint64_t tmp, *tmp2;
- code_len = 1;
- code = malloc(code_len * sizeof(struct entry *));
- i = 0;
-
- while(word = read_word(fptr)) {
- //printf("read word <%s>\n", word);
- // IMMEDIATES are hard coded
- // in a proper forth you can define your own immediates
-
- if(!strcmp(";", word)) {
- code[i] = NULL;
- return code;
- }
- else if(!strcmp(":", word)) {
- sub_name = strdup(read_word(fptr));
- sub_code = load_code(fptr);
- add_word(sub_name, sub_code, interpret);
-
- continue;
- }
- else if(!strcmp("lit", word)) {
- word = read_word(fptr);
- if(1 != sscanf(word, "%lld", &tmp)) {
- printf("couldn't read a number from <%s>\n", word);
- exit(-1);
- }
-
- tmp2 = malloc(sizeof(uint64_t));
- tmp2[0] = tmp;
-
- ent = add_word(NULL, tmp2, bltn_lit);
- }
- else {
- ent = find_word(word);
-
- if(!ent) {
- printf("Could not find word <%s>\n", word);
- exit(-1);
- }
- }
-
- code[i++] = ent;
- if(i > code_len) {
- code_len *= 2;
- code = realloc(code, code_len * sizeof(struct entry*));
- }
- }
-
- code[i] = NULL;
- return code;
- }
- void interpret(void *code_v) {
- struct entry **code = code_v;
- struct entry *ent;
- while(ent = *code++) { ent->interpreter(ent->code); }
- }
|