commit cd8f5c8841d67357f4c6b91c74b14aac0a1d89e6
parent c6fb28d0a7df1c5ea9b68f2b51a26f2e3cf44a76
Author: Virgil Dupras <hsoft@hardcoded.net>
Date: Wed, 1 Jun 2022 13:51:40 -0400
Add word definitions and jumps
Diffstat:
6 files changed, 54 insertions(+), 18 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -1 +1,2 @@
/dusk
+/forth.bin
diff --git a/Makefile b/Makefile
@@ -5,7 +5,7 @@ all: $(TARGETS)
forth.bin: forth.txt asm.py
./asm.py forth.txt > $@
-dusk: dusk.c forth.bin
+dusk: dusk.c forth.bin ops.txt
$(CC) $(CFLAGS) dusk.c $(LDFLAGS) -o $@
.PHONY: clean
diff --git a/asm.py b/asm.py
@@ -4,25 +4,58 @@
import sys
import struct
-out = sys.stdout.buffer.write
+ops = open('ops.txt', 'rb').read().split(b',')
+ops = [s.strip() for s in ops]
+ops = {name:i for i, name in enumerate(ops)}
+tokens = open(sys.argv[1], 'rb').read().split()
+tokens = [s.strip() for s in reversed(tokens)]
+outbuf = bytearray()
+prevword = 0
+words = {} # name:pc
+labels = {} # name:pc
+
+def out(fmt, *args):
+ outbuf.extend(struct.pack(fmt, *args))
+
+def pc():
+ return len(outbuf)
+
def lit(s): # parse a literal
- if len(s) == 3 and s[0] == "'" and s[2] == "'":
- return ord(s[1])
+ if len(s) == 3 and s[0] == ord("'") and s[2] == ord("'"):
+ return s[1]
+ elif s.isdigit():
+ return int(s)
return None
-ops = open('ops.txt', 'r').read().split(',')
-ops = [s.strip() for s in ops]
-ops = {name:i for i, name in enumerate(ops)}
-tokens = open(sys.argv[1], 'r').read().split()
-tokens = [s.strip() for s in tokens]
-for t in tokens:
+def nextt():
+ return tokens.pop()
+
+def newword():
+ global prevword
+ name = nextt()
+ count = len(name)
+ out(f'<{count}sib', name, prevword, count)
+ prevword = pc()
+ words[name] = prevword
+
+while tokens:
+ t = nextt()
if t in ops:
- out(struct.pack('b', ops[t]))
+ out('b', ops[t])
+ elif t == b':':
+ newword()
+ elif t.startswith(b'lbl'):
+ labels[t] = pc()
+ out('<i', 0)
else:
n = lit(t)
if n is None:
+ t = t.decode()
print(f"invalid token {t}", file=sys.stderr)
- break
+ sys.exit(1)
else:
- out(struct.pack('<i', n))
+ out('<bi', ops[b'PUSHi'], n)
+n = labels[b'lblboot']
+outbuf[n:n+4] = struct.pack('<i', words[b'BOOT'])
+sys.stdout.buffer.write(outbuf)
diff --git a/dusk.c b/dusk.c
@@ -52,13 +52,14 @@ static void lblxt() { pushRS(ip); ip = pop(); lblnext(); }
static void PUSHi() { push(pc32()); }
/* flow - idx 3 */
-static void BYE() { running = 0; }
+static void JMPi() { pc = gc(pc); }
+static void bye() { running = 0; }
-/* I/O - idx 4 */
+/* I/O - idx 5 */
static void emit() { putchar(pop()); }
static void key() { push(getchar()); }
-static void (*ops[6])() = {
+static void (*ops[7])() = {
#include "ops.txt"
};
diff --git a/forth.txt b/forth.txt
@@ -1 +1,2 @@
-PUSHi 'f' emit PUSHi 'o' emit PUSHi 'o' emit BYE
+JMPi lblboot
+: BOOT 'f' emit 'o' emit 'o' emit bye
diff --git a/ops.txt b/ops.txt
@@ -1,4 +1,4 @@
lblnext, lblxt,
PUSHi,
-BYE,
+JMPi, bye,
emit, key