A new Forth system, currently targeting bare metal x86, but which aims to minimize platform dependencies by being coded within Forth as much as possible. The Makefile provided can build the system with (make
) and spin up within a qemu emulator with (make run
). Project dependencies are currently just nasm
and qemu-system-x86
.
Quarter Forth is named for the not-quite Forth language (quarter) used while bootstrapping.
I've blogged about Forth and Quarter here
The Kernel provides the core primitive, and starts a bare key-dispatch-execute loop, so the bootstrapping process can begin.
The first stage of the bootstrap defines the word
and find
primitives
necessary for a basic Forth interpreter and compiler. At this point, we are coding in quarter where primitives are referenced by single character names, and accessed via a hard-coded dispatch table in the kernel. By the end of the first stage we have definitions for [
and :
. We enter the interpreter now and transition to Forth.
Bootstrapping continues in Forth, defining all the standard Forth words, and providing us support for numerics, resulting in implementations for [
and :
with the standard behaviour expected from a Forth system.
- Case sensitive; lowercase preferred.
- Null terminated strings.
- Interpreter "[" and colon compiler ":" are separate words -- looking for markers, respectively "]" and ";" -- instead of being a single state aware word.
- Numbers are unsigned. the
number?
parser and.
printer are base state aware, controlled byhex
/decimal
. - No support for floats or double arithmetic.
- We do have return stack operators.
- Recursion is possible/allowed. Enabled by words becoming visible in the dictionary from the moment the dictionary header is linked.
- Recursion is the preferred means of coding iteration, although there is now support for standard Forth loops using
do
..i
..loop
. But when you have recursion, who needs loops? - Tail recursion is supported via
tail
orrecurse
which seems to nicely complement the standard wordexit
. It allows easy coding of iterative processes which don't consume the return stack. You can do just about everything you want with if/then/exit/tail.
- 16 bit. cell = 2bytes
- Threading model: subroutine threaded
- x86. call instructions are 3 bytes. A 1 byte op-code + 2 bytes relative address.
- Dictionary header format: (null-terminated) string, link-cell, length/flag-byte, followed directly by the executable code. The address of the executable code is used as the representation for execution tokens. The link cell is 0 or points to the previous XT.
- Threaded Interpretive Languages, R. G. Loeliger, 1981
- Starting Forth, Leo Brodie
- Moving Forth, Brad Rodriguez
- buzzard.2 (1992 IOCCC entry), Sean Barrett
- Forth standard
- Jones Forth, Richard Jones
- Sector Forth, Cesar Blum
- Tumble Forth, Virgil Dupras
Particular thanks go to the tumble forth tutorial, which guided my first steps.