In the hopes of solving both these issues in one swell foop, I've started work on an ANS Forth for the Propeller — creatively titled PropellerForth. For folks who haven't used Forth, it is simultaneously the most bewildering and liberating programming environment you'll ever use — a computational boot-to-the-head of the same degree as Lisp or Smalltalk. Like these languages, Forth is generally written entirely in itself, and the user can modify even the fundamental operations at runtime in an interactive environment.
The main difference: even modern Forths tend to fit happily in 8K of RAM. (Mine's a little larger than this, now, because I've added in some luxurious libraries.)
Currently, my system image comes in at 8,372 bytes, including all buffers and stacks for the bootstrap task. It executes 1.7 million words (small words) per second at 80Mhz — not a speed demon, but I've still got a lot of room for optimization. It was at 1.4 milion wps yesterday.
The oddities of the Propeller architecture have made this a little interesting:
- It's an old-style, string-of-addresses indirect threaded Forth. This is necessary because the more modern styles such as direct or subroutine threading assume you can jump to instructions in the dictionary's data space; the Propeller can't.
- The Propeller has no hardware stacks, or indirect addressing of its fast (local) RAM. Thus, the stack is emulated with slow (shared) RAM, entirely in software. This has required a lot of careful tuning.
- The Propeller has no hardware peripherals, other than some counters. All I/O, including the serial console, is implemented by the Forth kernel.
- Forth was designed for multiuser multitasking on single-core machines, and later expanded to multiuser multitasking on SMP machines. As an embedded system, the Propeller needs single-user multitasking on an eight-core chip — eight cores sharing a dictionary and data space. This means things like semaphores all of a sudden appear in the standard library.
Forth is intoxicating. Once the system is bootstrapped (which required a couple kilobytes of assembler, most of which I generated with some scripts — as I am wont to do), development proceeds exponentially, by defining each layer in the system in terms of the previous.
I believe that every aspiring (or experienced) computer programmer should write a Forth at some point, as a sort of rite of passage. It's challenging, but not because it's hard: because it requires some pretty fundamental paradigm shifts. Writing a Forth will bring you many Aha! moments, and watching the language define itself is quite a trip.