duskos

dusk os fork
git clone git://git.alexwennerberg.com/duskos
Log | Files | Refs | README | LICENSE

commit 997f0e3e0aba1f2846dc01c3447058f887419411
parent fbc2832fa5316af243fffadaa57547ef91274f56
Author: Virgil Dupras <hsoft@hardcoded.net>
Date:   Wed,  1 Jun 2022 13:51:40 -0400

Add branches, stype and string literal

We have the "Dusk OS" prompt.

Diffstat:
MREADME.md | 1+
Masm.py | 100+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------
Mdusk.c | 28+++++++++++++++++++++++-----
Mforth.txt | 6++++--
Mops.txt | 6++++--
5 files changed, 117 insertions(+), 24 deletions(-)

diff --git a/README.md b/README.md @@ -10,6 +10,7 @@ has a widened scope: * Access, visualize and print images and PDFs. * Compress and decompress files. * Edit and compile C code. Possibly other languages too. +* No focus on binary size (unlike Collapse OS, we have plenty here). Additionally, it's worth mentioning that as a consequence of its laser sharp focus on simplicity, Dusk OS is also defined by what it *doesn't* do: diff --git a/asm.py b/asm.py @@ -7,20 +7,35 @@ import struct 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)] +fp = open(sys.argv[1], 'rb') outbuf = bytearray() prevword = 0 words = {} # name:pc labels = {} # name:pc +ps = [] # PS for immediate words def out(fmt, *args): outbuf.extend(struct.pack(fmt, *args)) +def opwr(name): + if isinstance(name, str): + name = name.encode() + out('<b', ops[name]) + +def intwr(n): + out('<i', n) + +def intset(offset, n): + outbuf[offset:offset+4] = struct.pack('<i', n) + +def litwr(n): + opwr('_i_') + intwr(n) + def pc(): return len(outbuf) -def lit(s): # parse a literal +def litparse(s): if len(s) == 3 and s[0] == ord("'") and s[2] == ord("'"): return s[1] elif s.isdigit(): @@ -28,7 +43,14 @@ def lit(s): # parse a literal return None def nextt(): - return tokens.pop() + r = bytearray() + c = fp.read(1) + while c and c[0] <= 0x20: + c = fp.read(1) + while c and c[0] > 0x20: + r.append(c[0]) + c = fp.read(1) + return bytes(r) def newword(): global prevword @@ -38,27 +60,75 @@ def newword(): prevword = pc() words[name] = prevword +def _if_(): + opwr('_br_') + ps.append(pc()) + intwr(0) -while tokens: - t = nextt() +def _then_(): + intset(ps.pop(), pc()) + +def _begin_(): + ps.append(pc()) + +def _again_(): + opwr('_br_') + intwr(ps.pop()) + +def _until_(): + opwr('_cbr_') + intwr(ps.pop()) + +def _next_(): + opwr('_next_') + intwr(ps.pop()) + +def slitwr(): + s = bytearray() + c = fp.read(1) + while c and c != b'"': + s.append(c[0]) + c = fp.read(1) + _if_() + spc = pc() + outbuf.extend(s) + _then_() + litwr(spc) + litwr(len(s)) + +special = { + b':': newword, + b'S"': slitwr, + b'if': _if_, + b'then': _then_, + b'begin': _begin_, + b'again': _again_, + b'until': _until_, + b'next': _next_, +} + +t = nextt() +while t: if t in ops: - out('b', ops[t]) + opwr(t) elif t in words: - out('<bi', ops[b'CALLi'], words[t]) - elif t == b':': - newword() + opwr('_call_') + intwr(words[t]) + elif t in special: + special[t]() elif t.startswith(b'lbl'): labels[t] = pc() - out('<i', 0) + intwr(0) else: - n = lit(t) + n = litparse(t) if n is None: t = t.decode() print(f"invalid token {t}", file=sys.stderr) sys.exit(1) else: - out('<bi', ops[b'PUSHi'], n) + litwr(n) + t = nextt() -n = labels[b'lblboot'] -outbuf[n:n+4] = struct.pack('<i', words[b'BOOT']) +fp.close() +intset(labels[b'lblboot'], words[b'BOOT']) sys.stdout.buffer.write(outbuf) diff --git a/dusk.c b/dusk.c @@ -1,6 +1,7 @@ #include <inttypes.h> #include <stdio.h> +#define CSIZE 4 #define MEMSIZE 0x10000 #define STACKSIZE 0x100 @@ -41,23 +42,40 @@ static cell pop() { return stack_pop(&ps); } static void push(cell x) { stack_push(&ps, x); } static cell popRS() { return stack_pop(&rs); } static void pushRS(cell x) { stack_push(&rs, x); } -static cell pc32() { cell n = gc(pc); pc+=4; return n; } +static cell pc32() { cell n = gc(pc); pc+=CSIZE; return n; } /* Native words */ /* stack */ -static void PUSHi() { push(pc32()); } +static void _i_() { push(pc32()); } +static void dup() { push(peek()); } +static void swap() { cell a = pop(); cell b = pop(); push(a); push(b); } +static void p2r() { pushRS(pop()); } +static void r2p() { push(popRS()); } /* flow */ -static void JMPi() { pc = gc(pc); } -static void CALLi() { pushRS(pc+4); JMPi(); } +static void _br_() { pc = gc(pc); } +static void _cbr_() { if (pop()) { pc+=CSIZE; } else { _br_(); } } +static void _next_() { + cell n = popRS()-1; + if (n) { pushRS(n); _br_(); } + else { pc+=CSIZE; } +} +static void _call_() { pushRS(pc+CSIZE); _br_(); } static void exit() { pc = popRS(); } static void bye() { running = 0; } +/* memory */ +static void cfetch() { cell a = pop(); push(mem[a]); } + +/* arithmetic */ +static void inc() { push(pop()+1); } +static void dec() { push(pop()-1); } + /* I/O */ static void emit() { putchar(pop()); } static void key() { push(getchar()); } -static void (*ops[7])() = { +static void (*ops[16])() = { #include "ops.txt" }; diff --git a/forth.txt b/forth.txt @@ -1,3 +1,5 @@ -JMPi lblboot -: foo 'f' emit 'o' emit 'o' emit exit +_br_ lblboot +: c@+ dup inc swap cfetch exit +: stype p2r begin c@+ emit next exit +: foo S" Dusk OS" stype exit : BOOT foo bye diff --git a/ops.txt b/ops.txt @@ -1,3 +1,5 @@ -PUSHi, -JMPi, CALLi, exit, bye, +_i_, dup, swap, p2r, r2p, +_br_, _cbr_, _next_, _call_, exit, bye, +cfetch, +inc, dec, emit, key