On Chuck Moore's colorForth


Nov. 11, 2002



Real programmers write Forth kernels in assembler and CAD packages in Forth. The former in 6600 bytes of object code and the latter in about 4000 32-bit words of object code.



How does he do that?



First some basic metrics. The word interpreter is 24 bytes and 'find' loop is 35 bytes. colorForth has a kernel that takes up 11kb but is only comprised of 6600 bytes of object code. This includes the colorForth kernel, user and graphics interface. The rest is dictionary expansion room for approx. 640 new definitions (128 for MACRO, 512 for FORTH). That leaves about 1000 bytes for kernel extensions (MACROs for basic operations). Application code will need to point 'here' after block 162 decimal or address A200h.



Blocks are 256 bytes long and start at block 24 (address 3000h, 12298 decimal) where the default warm start loads from. Code/dictionary go below that. Stacks are at 0A0000h.



colorForth is a simple multi-tasker that uses two tasks: 'god' (graphic ouput display) and 'main' (usually 'keyboard').'main' switches to 'god' while waiting for 'key' input. 'god' updates the video display every time that it is switched to. 'switch' (called within god) copies the output image at 'frame' to the AGP video memory at 'displ'.



According to Chuck's web site, OKAD is written in about 500 lines of code. c.f.: http://colorforth.com/vlsi.html



Examining his other colorForth code on display at: http://www.merlintec.com/download/color.html
a nominal length for a line of code is about 8 words. So OKAD is nominally 4000 words or 16kb of source code. Compiled object code will be about the same order of size including dictionary overhead (data arrays not included).




And I do mean 'words'. colorForth is written around the concept of a 'word', i.e. a 32 bit word. Numbers and strings are all multiples of 32 bit words.



Numbers are retained in a binary format with four bits of color type and a hex/decimal bit flag, single precision number 'words' are retained as signed 27 bit binary values.



Alpha-numeric strings are comprised of 4 bits of color information with the remaining 28 bits available for packed Huffman character encoded strings.



Input is a word at a time, either an alpha-numeric string or a number. Color is intrinsic to the individual 32-bit words. colorForth is not line oriented, it is _word_ oriented.



The Huffman coding was chosen to optimally encode the strings used in the dictionary names peculiar to colorForth and OKAD into the most compact form. (Write a different app with different names and you may want to re-cast the Huffman encoding for your apps character frequencies.)



Numeric variables are maintained in their block location. see:
http://colorforth.com/parsed.html



Looking at the colorForth user interface, it is evident that it was designed by and for Chuck's specific way of thinking and coding. It enforces a word model as the basic unit of colorForth syntax.



The user interface first selects a color, which then specifies an input method. For basic input, each word is executed/enstacked at the inception of the next command.



The block editor changes from execute/enstack to insert/delete, otherwise the input methods remain the same.



Back to the original question: How does he do that?



First, learn _all_ the CPU opcodes, not just the commonly used ones. Chuck's code uses opcodes that don't appear in dis-assembly of compiler output.



Secondly, learn the characteristics of the hardware platform. Do prototyping to figure out how to do straigtforward operations. Other peoples code (OPC) will have a bias for their goals, not yours. OPC will also usually have irrelevant generalities. Map your required functions to the hardware.



Third, keep the user interface to the bare minimum. This is the most expensive part of code. (I recently did a vertical scrollbar in C. The basic functionality took 644 bytes of object code. The finished version that _looked_ good with 3D outlines, but provided no extra functionality, took over 1300 bytes of code.) colorForth uses about 600 bytes for the basic input, number conversion and Huffman word packing. Chuck mentions that the basic kernel is less than 2k, so the rest (4.5k) goes into the user interface and CAD capable graphics.



Finally, Chuck talks about moving everything closer to the front of the development effort: run-time to compile-time, compile-time to edit-time, edit-time to design time. Do the design up front and code entry/debugging is only 10% of the development effort.



To sum it up:



1. Know your tools, hardware and software, inside out.

2. Keep the user interface as simple as possible.

3. Prototype first, design second and code last.



Chuck has been designing colorForth for 20 years. It has been a process of elimination as well as invention. The whole point of colorForth is to implement OKAD in a manner usable to Chuck for the purpose of designing the X18 stack processor and similar designs. colorForth was designed as a specific purpose programming language rather than general purpose. This goes a long way towards explaining why colorForth seems so hostile to collaborative programming. It was explicitly created as the requisite base for OKAD.



The rigor with which colorForth and OKAD were created are on the same order as that of G. Spencer Brown's "The Laws of Form" or Whitehead and Russel's "Principia Mathematica". Consider it a logical proof of fitting a VLSI CAD design package into about 25kb along with an open-ended programming language.



Comparing anyone elses code to colorForth/OKAD without taking the years of design refinement into consideration is unjust. And expecting to be able to create new colorForth software platforms that are as elegant is just plain silly. The ruthless, brutal design methodology that is colorForth is a true 'Zen of Computing' and can take years to acquire. YMMV.



Return to colorForth index