Draco
Chris Gray's one-person systems programming language: a strongly typed, keyword-heavy blend of Pascal, C and ALGOL 68 with a self-hosting one-pass compiler. It ran on CP/M-80 in 64K of memory and was later ported to the Commodore Amiga.
Created by Chris Gray
Draco is a strongly typed systems programming language designed and implemented single-handedly by Canadian programmer Chris Gray. He wrote it first for 8080/Z80 machines running CP/M and later ported it to the Commodore Amiga. Gray described it as a language for “writing operating systems, compilers, editors, databases”. It was meant to keep C’s low-level facilities, like pointers, bit operators, separate compilation and conditional compilation, while adding Pascal’s strict typing. Its syntax uses ALGOL 68-style reversed keywords (if ... fi, do ... od, case ... esac, proc ... corp). Draco never had a large user base. Gray estimated it brought in “something like $1000” in shareware payments. Even so, it is a good example of the hobbyist compiler craft of the early microcomputer era: a self-hosting, optimising, one-pass compiler that ran in 64K of memory.
History and Origins
From the mainframe to the microcomputer
Gray tells the story on his own website. As a graduate student he designed a large AI language called ALAI. Its syntax took reversed keywords from ALGOL 68, a language some professors in his department worked on. To build ALAI he first wrote two smaller languages for the IBM 360/370, QD (“Quick and Dirty”) and QC (“Quick and Clean”). He also wrote Six, a compiler for a text-adventure system.
Then he bought an Exidy Sorcerer running CP/M. He found that it had no compiler, only interpreted BASIC and assembler, so he wrote one. He wrote the compiler in its own new language first, by hand with pen and paper. Then he typed it into a UNIX PDP-11, translating it to C as he went, and had it generate PDP-11 code until it could compile itself. After that he retargeted it to emit Intel 8080 code. He carried the output upstairs on 8-inch floppy disks to the Sorcerer in his office. Eventually the compiler compiled itself under CP/M, and from then on, in his words, “I was independent of any other computer for my work.”
Three names
The language changed names twice:
| Name | Why it changed |
|---|---|
| MAC (“Microprocessor Algol Compiler”) | Gray learned of MIT’s Project MAC |
| Tiny Rigel | Named after a star, following Algol. “Tiny” because the type system was not yet complete. Another language called Rigel later appeared |
| Draco | Named after the large northern constellation. Gray notes that “it has been called ‘Draconian’ by some of its users” because it is so strict about types |
The Tiny Rigel name stayed in the toolchain. The CP/M reference manual explains that the TR prefix on the standard libraries TRRUN.LIB and TRCPM.LIB “is from a previous name of the language.”
Dating Draco
The encyclopedia index lists Draco under 1980. No primary source found for this page confirms that year. Gray’s own account does not date the MAC and Tiny Rigel stages. The earliest dated Draco documents are the CP/M Draco Quick Reference Guide and CRT library reference, both marked “Copyright 1983 by Chris Gray”. This page therefore uses c. 1983 for Draco under that name and treats the predecessor languages as earlier. Secondary sources disagree. Wikipedia says “early 1980s”, Rosetta Code says “mid-1980s”, and FOLDOC says 1987, which is really the date of the Amiga release.
Shareware on CP/M
Gray says he first wrote the CP/M system with commercial sale in mind. The 1986 distribution says this directly: “This software was originally intended as commercial software… Due to the lack of a viable market for CP/M-80, character based software, this software is now being distributed as ‘shareware’.” On 13 November 1986 he sent the complete three-archive suite to Keith Petersen for the public CP/M archives. The suite is still mirrored today in collections of the old Simtel CP/M archives. Gray also says his documentation was later reprinted, without his permission, in the McGraw-Hill book Online Programming Languages and Assemblers, edited by William J. Birnes (1989).
The Amiga port
Gray was an early Amiga owner. He cross-developed the 68000 version over a serial link between his CP/M machine and an Amiga 1000, and got it running on the Amiga itself. The first Amiga-hosted version ran on an A1000 with two floppy drives and 512K of RAM. On the Amiga he added IEEE floating point and greatly improved the generated code. The compiler, he says, is “still basically the same compiler, however.” Amiga Draco was distributed on Fred Fish’s freely distributable disks. Version 1.2 (January 1989) was the last widely available release. Its readme says the compiler generates code “optimized to about the level of the late 1980’s commercial compilers” and ships with Draco include files for all Amiga 1.3 system functions.
Gray also wrote about the language in print. Wikipedia cites two of his articles in Transactor for the Amiga (June 1988). From July to October 1989 he wrote a four-part series in the Amiga Transactor on how to build a compiler. It used Toy, a Draco subset whose compiler was itself written in Draco. Gray says the magazine closed after the October issue and he was never paid for the articles.
Design Philosophy
The introduction to the 1986 CP/M distribution, “What is Draco, Why Did I Write It and Why Is It Like It Is?”, sets out Gray’s reasoning as a list of complaints about both of the main micro languages of the day.
About Pascal, his complaints included: no standard separate compilation, no conditional compilation, no general string mechanism, no pointer or bit manipulation, no signed/unsigned types, procedure calls that “look like variables”, and “I HATE BEGIN and END!”
About C, they included: “too many bloody brackets”, a “horrible declaration syntax (just what is char *(*p[])()?)”, the = versus == trap, little type checking, passing everything as 16 bits on an 8-bit CPU, and “stupid linkers” that load code that is never called.
His answer was a language that “has all of the facilities of C, except for bitfields and the macro preprocessor” but is strongly typed like Pascal. It is not an expression language either: Draco keeps statements such as a := 27 strictly separate from expressions such as a + 27. Gray preferred keywords to brackets, and he chose a different closing keyword for each construct rather than one shared BEGIN/END or {/}. Unlike most Pascals of the time, Draco is case-sensitive.
Key Features
The example Gray used to compare Draco with Pascal and C:
proc main()void:
int i, j;
for i from 0 upto 10 do
for j from 0 upto i do
write(j : 2, ' ');
od;
writeln();
od;
writeln("All done.");
corp;
Syntax
:=for assignment and=for comparison. Inequality is~=.- Every block has its own closing keyword:
if/elif/else/fi,while/do/od,case/incase/default/esac,proc/corp. - Counting loops state their direction:
for i from 0 upto 10ordownto. - Procedures declare their result type after the parameter list (
proc hanoi(...)void:). A result is returned by placing it at the end of the procedure body, just beforecorp, with no semicolon after it. - Pointer types are written with a prefix
*and dereferenced with a postfix*, so a field access looks liket*.t_left. Arrays are declared with a prefix size, for example[100] *Tree_t B_Index;.
proc hanoi(*char fromPeg, usingPeg, toPeg; int n)void:
if n ~= 0 then
hanoi(fromPeg, toPeg, usingPeg, n - 1);
writeln("Move disk ", n, " from ", fromPeg, " peg to ", toPeg, " peg.");
hanoi(usingPeg, fromPeg, toPeg, n - 1);
fi;
corp;
(Simplified from hanoi.drc on the CP/M documentation disk.)
Types
- Built-in numeric types on CP/M:
byte,short/ushort(the manual says “often 8 bit”),int/word(16-bit) andlong/ulong(32-bit), plusboolandchar. - Range-bounded types:
unsigned INDEX_RANGE - 1 i;declares a variable whose range is known at compile time, so the compiler can choose the smallest suitable machine type. structanduniondeclarations in C style,enumtypes, named and typed constants, and array and struct constants.- Procedure types that can be assigned, compared and called, for example
proc (int a, b)int. - Operator types, which the manual calls Draco’s “(somewhat limited) way of being an extensible language”. An operator type names a base representation and a procedure-name prefix. The compiler then turns operators on values of that type into calls to user-written procedures.
- Type equivalence is structural: two types are equivalent “if they are equivalently constructed from equivalent component types.”
pretendis an explicit escape from the type system for systems code.
Systems features
- Separate compilation with
externdeclarations,.ginclude files, and conditional compilation driven by constant folding. - Built-in
newandfreefor dynamic storage, and built-in typed text and binary I/O (read,write,readln,writelnon channels). - Inline machine code through the
codeconstruct, and CPU-specific options such asnonrecprocedures on CP/M. Avectorprocedure on CP/M ends with a return-from-interrupt and saves all registers, so interrupt handlers can be written in Draco. - A simple module convention: the linker calls a library file’s
_initializeand_terminateprocedures automatically whenever that file is linked in.
The Toolchain
Draco was always more than a compiler. The CP/M distribution included:
| Tool | Purpose |
|---|---|
DRACO.COM | One-pass compiler producing optimised relocatable object files |
LINK.COM | Linker that loads only referenced code and searches libraries repeatedly in a defined order. It runs in one pass when the program fits in memory, otherwise two |
DAS.COM / DDIS.COM | Draco’s own assembler and disassembler |
DLIB.COM, XREF.COM | Librarian and object-file cross-referencer |
CRT.LIB + CONFIG | Terminal-independent screen library, similar to termcap/termlib, with a configuration program and a database of a few dozen terminal definitions |
DED | Gray’s multi-buffer screen editor |
Gray’s own list of the CP/M compiler’s features includes register-value tracking to avoid redundant loads, “near-optimal branch networks” for conditions and loops, and either a jump table or a binary search for case, depending on the values. It also does compile-time evaluation of some array indexing, and the whole compiler fits in the 64K address space without overlays.
Speed and size, as reported by the author
The 1986 CP/M introduction gives these figures. They come from Gray himself, not from independent benchmarks. The compiler goes “from source code to relocatable, optimized machine code at a rate of about 2000 lines per minute on a 5 MHz 8085”. The whole compiler, about 10,000 lines, can be rebuilt “in under 10 minutes” working from one 8-inch floppy disk. A simple “hello there world” program links to “under 1000 bytes”. No comparison with other CP/M compilers on the same hardware has been found.
Evolution
- CP/M-80 (1983-1986): Compiler 2.3 is the version whose source Gray later published. The distributed binary lacked long and floating-point constants so that it could run in a 56K TPA. A separate
BIGDRACO.COMthat understood those constants, but needed a 60K TPA, was also supplied. Gray’s own list of shortcomings in the 1986 release included “essentially non-existant floating point support” and “no proper modules”. - Amiga 1.x (1987-1991): Retargeted to the MC68000. This version added IEEE floating point, much better code generation,
FDCompilefor generating stubs to call Amiga shared libraries, and the DRLink linker as a replacement for BLink. Version 1.3 added theregisterkeyword, a larger peephole optimiser, forward-branch shortening and smaller procedure entry and exit code. - After Draco: Gray’s later projects kept the Draco style. He says that “any MUD system I wrote was of course going to have a Draco-like language in it”. That system was AmigaMUD (started 1990), whose server he later translated to C and ported to Linux as CGMud. His next language, Zed, was in progress by 2014.
Current Relevance
Draco is a historical language with no active development. The Draco2C readme puts it simply: “development of Draco has ceased”. The surviving material is better than for most one-person languages of the period:
- The CP/M suite is still on the CP/M archive mirrors, and Gray’s site has ZIP archives of the CP/M compiler 2.3 source, documentation and programs.
- Gray’s site also has the Amiga compiler source, binaries, includes and the DRLink source. Gray says he runs these under the UAE Amiga emulator on Linux.
- Aminet has Draco 1.2 (
dev/lang/Draco), the full Draco 1.3 package with source (dev/lang/Draco-m68k, uploaded by James Jacobs in March 2014), and Jacobs’s Draco2C (2005), which converts Draco source into ANSI C. - Rosetta Code has a Draco category with solutions to modern tasks.
No official or community Docker image exists. Running Draco today means using a CP/M emulator such as yaze (Gray suggests the VT100 terminal setting) or an Amiga emulator with Kickstart and Workbench images.
Why It Matters
Draco shows what one determined programmer could build for the 8-bit micros of the early 1980s. It was a strongly typed, ALGOL-flavoured systems language with a self-hosting, optimising compiler, written at a time when Gray found nothing on CP/M but BASIC and assembler. Many of his complaints about C and Pascal, such as declaration syntax, = versus ==, weak type checking, and the lack of named typed constants and separate compilation, were common ones at the time. Later languages added fixes for some of the same problems. Draco also had a small part in Amiga history. It was among the compilers circulating on the early Fred Fish disks, Amiga Empire was written in it, and its Toy series in the Amiga Transactor walked readers through building a compiler, although the magazine closed after only four instalments.
Timeline
Notable Uses & Legacy
The Draco toolchain itself
The CP/M compiler (about 10,000 lines), the Amiga compiler and the DRLink linker are all written in Draco, and so are the CP/M cross-referencer, hex editor and Ded screen editor. Gray says Ded was the editor he used to type the introduction distributed with the CP/M release
Amiga Empire
Gray's Amiga port of Peter Langston's multi-player economics and war game Empire is written in Draco and was reportedly distributed as shareware. Executables of Dave Wright's version of Amiga Empire are on Fred Fish disk 357
Toy compiler (Amiga Transactor, 1989)
The teaching compiler for Gray's four-part 'how to write a compiler' series is written in Draco and compiles a Draco subset straight to AmigaDOS executables, without needing a linker
Quest and Explore
Quest is an adventure-game system whose complete Draco source was shipped on the CP/M documentation disk. Explore is Gray's Ultima-style role-playing system, written for CP/M with a CompuPro graphics board and later ported to the Amiga. It was never released, but according to Gray its source and the Amelon scenario are now on his website