Forth
Part of Programming Fundamentals
Forth is an extraordinarily compact stack-based programming language that can be implemented in under 1 KB of code, making it ideal for severely resource-constrained rebuilding scenarios.
Why This Matters
When memory is desperately scarce — a few kilobytes of ROM, a few hundred bytes of RAM — BASIC is too large and a full C compiler is out of the question. Forth fills this gap. The Forth language environment: interpreter, compiler, and standard library combined, can fit in less than 1 KB of machine code. It has been implemented on processors with as little as 2 KB of total memory.
Beyond extreme compactness, Forth has an unusual property: it erases the distinction between programming language and operating system. A Forth system running on bare hardware is immediately interactive, immediately extensible, and immediately capable of controlling hardware directly. You type words at a prompt; the system executes them; you define new words that combine old ones. There is no compilation step, no linking step, no separate build process.
For a civilization rebuilding computation, Forth represents a path to a complete, self-extending programming environment on minimal hardware. Many early embedded systems, scientific instruments, and even NASA spacecraft were programmed in Forth for exactly this reason.
How Forth Works
Forth is built around a stack. All computation uses a last-in-first-out stack of numbers. Operators take their arguments from the stack and push results back onto it. This is Reverse Polish Notation (RPN), the same notation used by HP scientific calculators.
Instead of writing 3 + 4, you write 3 4 +. This pushes 3, pushes 4, then + pops both and pushes 7.
3 4 + . \ stack: 3 then 7, then print 7
The dot (.) pops the top of stack and prints it. After this, the stack is empty.
A more complex expression: (3 + 4) * (10 - 2) becomes:
3 4 + 10 2 - * \ leaves 56 on stack
Trace: push 3, push 4, + gives 7, push 10, push 2, - gives 8, * gives 56.
This notation seems odd at first but eliminates the need for parentheses and precedence rules. The order of operations is explicit and unambiguous.
Words and the Dictionary
In Forth, every executable unit is called a word. The language comes with many built-in words and gives you simple syntax to define new ones:
: SQUARE DUP * ;
This defines a new word SQUARE: DUP duplicates the top of stack (so you have two copies of the number), then * multiplies them. After this definition, 5 SQUARE . prints 25.
: SQUARE ... ; is the word definition syntax — colon starts the definition, semicolon ends it. New words are added to the dictionary: the runtime lookup table that maps word names to their code addresses.
You can immediately use a new word to define more words:
: CUBE DUP SQUARE * ;
5 CUBE . \ prints 125
The dictionary grows incrementally. Each new word builds on previous ones. A complete application is assembled this way — small words defining bigger words, all the way up to the application’s top-level loop.
Essential Stack Operations
Forth provides words for manipulating the stack directly:
DUP— duplicate top of stack:(n -- n n)DROP— discard top of stack:(n -- )SWAP— exchange top two values:(a b -- b a)OVER— copy second value to top:(a b -- a b a)ROT— rotate third value to top:(a b c -- b c a)2DUP— duplicate top pair:(a b -- a b a b)
The stack effect notation (before -- after) is Forth’s standard way to document how a word affects the stack. Learn to read and write it for every word you define.
Control Structures
Forth has conditional and loop structures:
\ IF..THEN: execute if true (nonzero top of stack)
: ABS DUP 0 < IF NEGATE THEN ;
\ IF..ELSE..THEN
: MAX 2DUP > IF DROP ELSE NIP THEN ;
\ counted loop: DO..LOOP
: SQUARES 11 1 DO I DUP * . LOOP ;
\ prints squares 1 through 100
\ indefinite loop: BEGIN..UNTIL
: COUNTDOWN BEGIN DUP . 1 - DUP 0 = UNTIL DROP ;
These structures compile to conditional jumps in the dictionary. The Forth compiler, when it encounters IF, compiles a conditional jump and leaves a placeholder for the jump target; when it encounters THEN, it fills in the placeholder with the current address.
Memory Access
Forth provides direct memory access words:
@(fetch): address — value. Reads a 16-bit word from the given address.!(store): value address —. Writes a 16-bit word to the given address.C@(character fetch): reads a byte.C!(character store): writes a byte.
0x2000 @ \ read word from address 0x2000
42 0x2000 ! \ write 42 to address 0x2000
Combined with the ability to define words, this gives you complete control over hardware. Define a constant for a hardware register address, then define words that read and write it:
$8000 CONSTANT UART_STATUS
$8001 CONSTANT UART_DATA
: UART-READY? UART_STATUS C@ 1 AND ;
: SEND-CHAR BEGIN UART-READY? UNTIL UART_DATA C! ;
Implementing a Forth System
A minimal Forth system requires only a few hundred bytes of machine code:
The inner interpreter: Loops through the list of word addresses in a definition and executes each one. On most implementations, this is a tight loop of 5-10 machine instructions.
The outer interpreter: Reads a word from input, searches the dictionary for it, and either executes it (interpret mode) or compiles a call to it (compile mode).
The dictionary: A linked list of word headers (name, flags, link pointer) followed by the word’s code. New words are added at the end.
Primitive words: The built-in words that cannot be defined in Forth itself — arithmetic (+, -, *, /), stack operations, memory access, comparison, and I/O. Typically 30-60 words, each a few machine instructions.
Once the primitives are in place, the rest of the system — control structures, string handling, file I/O, even the compiler itself — can be written in Forth.
Historical Context
Forth was created by Charles Moore in the late 1960s, originally to control astronomical instruments. It was designed to run on the smallest possible hardware while remaining fully programmable. Moore’s original Forth ran on an 18-bit minicomputer with 4 KB of memory and bootstrapped itself from a handful of machine code primitives.
Throughout the 1970s and 1980s, Forth was used in embedded systems, scientific instruments, space missions, and industrial control — anywhere memory was scarce and performance mattered. The Voyager spacecraft used Forth. Early personal computers ran Forth systems as alternatives to BASIC.
The language’s influence extends beyond its direct users. Forth’s dual-stack model (data stack and return stack) influenced processor design; the threaded code interpretation technique influenced virtual machine design; the extensible dictionary model influenced LISP-family languages.
Practical Notes for Rebuilders
Forth is the right choice when: memory is extremely scarce (under 4 KB), immediate interactivity is important, and the people programming it are willing to invest a few days learning to think in stack terms.
The learning curve is real but short. A programmer who already understands assembly language can learn Forth in a few days. The stack discipline that seems alien at first becomes natural quickly and trains a valuable skill: thinking about data flow explicitly.
Start by implementing the primitive words in assembly, verify each works correctly, then build up the standard Forth vocabulary in Forth itself. The self-hosting capability — Forth defining most of itself — is both elegant and highly diagnostic: if the system can interpret new Forth definitions correctly, the core is working.