From b9fec53c09002bc72c6cc53e0b4d9d76b4d8325d Mon Sep 17 00:00:00 2001 From: Jeremy Penner Date: Wed, 30 Jan 2019 22:12:14 -0500 Subject: [PATCH] Initial Forth interpreter implementation (Forp) --- forp.c | 340 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ forp.exe | Bin 0 -> 34447 bytes game.prj | Bin 4651 -> 4755 bytes 3 files changed, 340 insertions(+) create mode 100755 forp.c create mode 100755 forp.exe diff --git a/forp.c b/forp.c new file mode 100755 index 0000000..4876719 --- /dev/null +++ b/forp.c @@ -0,0 +1,340 @@ +#include + +#define MEM_SIZE 16384 +#define STACK_SIZE 64 +#define RSTACK_SIZE 32 + +union cell_union; +typedef union cell_union cell; + +union cell_union { + int i; + unsigned int u; + cell *p; + char *s; + void (*f)(); +}; + +char mem[MEM_SIZE]; +cell *HERE = (cell*)mem; +cell *LATEST = NULL; +cell IP = NULL; +cell W = NULL; +cell STATE = 0; +cell rstack_mem[RSTACK_SIZE]; +cell *rstack = rstack_mem; +cell stack_mem[STACK_SIZE]; +cell *stack = stack_mem; + +char *INPUT = NULL; + +#define CELL_OFFSET(cp, b) ((cell*)(((char *)(cp)) + b)) +#define TOP() (*(stack - 1)) +#define ST1() (*(stack - 2)) +#define ST2() (*(stack - 3)) +#define DROP(n) (stack -= n) +void PUSHC(cell c) { *stack = c; stack++; } +void PUSHI(int i) { stack->i = i; stack++; } +void PUSHU(unsigned int u) { stack->u = u; stack++; } +void PUSHCP(cell *c) { stack->p = c; stack++; } +#define PUSHP(p) PUSHCP((cell*)p) +void PUSHS(char *s) { stack->s = s; stack++; } +void RPUSH(cell c) { *rstack = c; rstack++; } +#define RPOP() (--rstack) + +void f_add() { + cell r = TOP(); + DROP(1); + TOP().i += r.i; +} + +void f_sub() { + cell r = TOP(); + DROP(1); + TOP().i -= r.i; +} + +void f_get() { + TOP() = (*(TOP().p)); +} + +void f_set() { + cell *p = TOP().p; + DROP(1); + (*p) = TOP(); +} + +void f_drop() { + DROP(1); +} + +void f_dup() { + PUSHC(TOP()); +} + +void f_swap() { + cell top = ST1(); + cell st1 = TOP(); + ST1() = st1; + TOP() = top; +} + +void f_rot() { // a b c -- b c a + cell c = TOP(); + cell b = ST1(); + cell a = ST2(); + TOP() = a; + ST1() = c; + ST2() = b; +} + + +void f_key() { + if (INPUT) { + PUSHI(*INPUT); + INPUT++; + if (TOP().i == 0) { + INPUT = NULL; + } + } else { + PUSHI(0); + } +} + +void f_word() { + static char buf[32] = {0}; + int key = ' '; + int ibuf = 0; + + while (key == ' ' || key == '\n' || key == '\r') { + f_key(); + key = TOP().i; + DROP(1); + } + + while (key != ' ' && key != '\n' && key != '\r' && key != 0) { + buf[ibuf++] = key; + f_key(); + key = TOP().i; + DROP(1); + } + buf[ibuf] = 0; + PUSHS(buf); +} + +void f_emit() { + printf("%c", TOP().i); + DROP(1); +} + +void f_dot() { + printf("%d ", TOP().i); + DROP(1); +} + +void f_puts() { + printf("%s", TOP().s); + DROP(1); +} + +void f_cr() { + PUSHI('\n'); + f_emit(); +} + +void f_comma() { + *HERE++ = TOP(); + DROP(1); +} + +void f_create() { // name -- + int namelen; + HERE->p = LATEST; + LATEST = HERE; + HERE++; + namelen = strlen(TOP().s); + HERE->u = namelen; HERE ++; + memcpy(HERE, TOP().s, namelen + 1); + HERE = CELL_OFFSET(HERE, namelen + 1); + DROP(1); +} + +void f_cdef() { // func name -- + f_create(); + HERE->p = TOP().p; + HERE ++; + DROP(1); +} + + +int RET = 0; +void f_docolon() { + RPUSH(IP); + IP.p = W.p + 1; + + while (!RET) { + W = *IP.p; + IP.p++; + W.p->f(); + } + RET = 0; + IP = *RPOP(); +} + +void f_ret() { + RET = 1; +} + +void f_donumber() { + PUSHC(*IP.p); + IP.p++; +} + +void f_number() { // str -- num isnum + int num = 0, result; + result = sscanf(TOP().s, "%d", &num); + TOP().i = num; + PUSHI(result == 1); +} + +void f_streq() { + int result = strcmp(TOP().s, ST1().s); + DROP(1); + TOP().i = result == 0; +} + +void f_lookup() { // name -- code pointer + cell *entry = LATEST; + while (entry) { + f_dup(); + PUSHP(entry + 2); + f_streq(); + if (TOP().i) { + DROP(1); + TOP().p = CELL_OFFSET(entry + 2, entry[1].u + 1); + return; + } + DROP(1); + entry = entry->p; + } + TOP().p = NULL; +} + +void f_def() { + cell *herebefore = HERE; + cell *latestbefore = LATEST; + f_word(); + f_create(); + PUSHP(f_docolon); + f_comma(); + while(1) { + f_word(); // w + f_dup(); // w w + f_lookup(); // w code + if (TOP().p == NULL) { + DROP(1); // w + f_dup(); // w w + f_number(); // w n isnum + if (TOP().i) { + PUSHS("_DONUMBER"); + f_lookup(); // w n isnum _donumber + f_comma(); + PUSHI(ST1().i); // w n isnum n + f_comma(); // w n isnum + DROP(3); + } else { + DROP(2); // w + HERE = herebefore; + LATEST = latestbefore; + f_puts(); + PUSHS("?\n"); + f_puts(); + f_cr(); + return; + } + } else if (TOP().p->f == f_ret) { + f_comma(); + DROP(1); + return; + } else { + f_comma(); + DROP(1); + } + } +} + +void f_interpret(char *input) { + INPUT = input; + while(1) { + f_word(); // w + if (TOP().s[0] == '\0') { + PUSHS("ok\n"); + f_puts(); + DROP(1); + return; + } + f_dup(); // w w + f_lookup(); // w code + if (TOP().p == NULL) { + DROP(1); // w + f_dup(); // w w + f_number(); // w n isnum + if (TOP().i) { + f_rot(); // w n isnum -- n isnum w + DROP(2); // n isnum w -- n + continue; + } + DROP(2); // w + f_puts(); + PUSHS("?\n"); + f_puts(); + return; + } + W = TOP(); // w code + DROP(2); + W.p->f(); + if (stack < stack_mem) { + stack = stack_mem; + PUSHS("stack underflow!\n"); + f_puts(); + return; + } + } +} + +int DIE = 0; +void f_quit() { + DIE = 1; +} + +#define CDEF(name, def) PUSHP(def); PUSHS(name); f_cdef() +void f_init() { + CDEF(":", f_def); + CDEF(";", f_ret); + CDEF("+", f_add); + CDEF("-", f_sub); + CDEF("@", f_get); + CDEF("!", f_set); + CDEF("dup", f_dup); + CDEF("drop", f_drop); + CDEF("swap", f_drop); + CDEF("rot", f_rot); + CDEF("emit", f_emit); + CDEF("number", f_number); + CDEF("_DONUMBER", f_donumber); + CDEF(".", f_dot); + CDEF(".s", f_puts); + CDEF(",", f_comma); + CDEF("quit", f_quit); + f_interpret(": -rot rot rot ;"); +} + +int main() { + char inputbuf[256]; + f_init(); + + while (!DIE) { + f_interpret(gets(inputbuf)); + } + return 0; +} \ No newline at end of file diff --git a/forp.exe b/forp.exe new file mode 100755 index 0000000000000000000000000000000000000000..a57a2e90eb7b6029edaf3d954000f0e5ca447e93 GIT binary patch literal 34447 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 ZgtcnRy^)IYbBkHGSsljuHB0Bwe*zI~)O7#= literal 0 HcmV?d00001 diff --git a/game.prj b/game.prj index 3135e193e86cd819fdc19180794a5e2520c36e35..cfae4533964c6f0dcd4b576503e973476fc2ed3e 100755 GIT binary patch delta 181 zcmZ3jGFf#44?nX6gZgBC{;TyxOi~O$z_g1YjLDPfID{ue4?i;lgT`cj{;TF(Oi~OC3^N#m7~U~HWQ=Dx%(#RxhoOVv2E${99>!@5 e|NqxBE@7}^EMk1ez{U6<49pnJHa80hFaZEb@fkt@