Est. 1983 Intermediate

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

Paradigm Procedural, structured (imperative)
Typing Static, Strong, Manifest
First Appeared c. 1983 (the earliest dated document, the CP/M Draco Quick Reference Guide, is copyright 1983; the language grew out of earlier versions called MAC and Tiny Rigel)
Latest Version Amiga Draco 1.3 (compiler copyright 1991); CP/M-80 compiler 2.3 (copyright 1985)

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:

NameWhy it changed
MAC (“Microprocessor Algol Compiler”)Gray learned of MIT’s Project MAC
Tiny RigelNamed after a star, following Algol. “Tiny” because the type system was not yet complete. Another language called Rigel later appeared
DracoNamed 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 10 or downto.
  • 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 before corp, with no semicolon after it.
  • Pointer types are written with a prefix * and dereferenced with a postfix *, so a field access looks like t*.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) and long/ulong (32-bit), plus bool and char.
  • 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.
  • struct and union declarations in C style, enum types, 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.”
  • pretend is an explicit escape from the type system for systems code.

Systems features

  • Separate compilation with extern declarations, .g include files, and conditional compilation driven by constant folding.
  • Built-in new and free for dynamic storage, and built-in typed text and binary I/O (read, write, readln, writeln on channels).
  • Inline machine code through the code construct, and CPU-specific options such as nonrec procedures on CP/M. A vector procedure 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 _initialize and _terminate procedures automatically whenever that file is linked in.

The Toolchain

Draco was always more than a compiler. The CP/M distribution included:

ToolPurpose
DRACO.COMOne-pass compiler producing optimised relocatable object files
LINK.COMLinker 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.COMDraco’s own assembler and disassembler
DLIB.COM, XREF.COMLibrarian and object-file cross-referencer
CRT.LIB + CONFIGTerminal-independent screen library, similar to termcap/termlib, with a configuration program and a database of a few dozen terminal definitions
DEDGray’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.COM that 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, FDCompile for generating stubs to call Amiga shared libraries, and the DRLink linker as a replacement for BLink. Version 1.3 added the register keyword, 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

1983
The Draco Quick Reference Guide and the CRT library reference for CP/M carry a 1983 copyright notice from Chris Gray, the earliest dated Draco documents. Before this the language had been called MAC (Microprocessor Algol Compiler) and then Tiny Rigel. That earlier name survives in the run-time library names TRRUN.LIB and TRCPM.LIB
1985
CP/M Draco compiler version 2.3, whose banner reads 'Copyright (C) 1985 by Chris Gray', is a one-pass compiler written in Draco itself. It runs in a 64K address space, with a peephole optimiser and register-contents tracking
1986
On 13 November 1986 Gray uploads the complete CP/M-80 Draco suite to Keith Petersen (W8SDZ) for the public CP/M archives as 'copyrighted shareware': three archives holding the documentation, the compiler and tools, and games plus the Ded editor. The cover note says a conversion to generate MC68000 code for the Commodore Amiga is under way
1987
The Amiga version of Draco appears on Fred Fish's freely distributable disks. Wikipedia, citing John Foust's August 1987 'AMICUS Network' column in Amazing Computing, dates the Amiga release to 1987. The later 1.2 readme says the full documentation is on Fish disk 77
1988
Gray's articles 'About Draco' and 'Draco - The Language and Compiler' appear in Transactor for the Amiga (volume 1, issue 2, June 1988), as cited by Wikipedia
1989
Amiga Draco 1.2, dated 28 January 1989 in James Jacobs's Draco2C readme, becomes the last widely distributed version. From July to October 1989 the Amiga Transactor runs Gray's four-part series on writing a compiler, built around Toy, a Draco subset whose compiler is written in Draco
1991
Amiga Draco 1.3 is built with a 1991 copyright date. It adds the 'register' keyword, a larger peephole optimiser and forward-branch shortening. The 1.2 readme notes that 1.3 'has not been properly distributed'
2014
On 14 March 2014 James Jacobs uploads a complete Draco 1.3 package, with binaries and compiler source, to Aminet as dev/lang/Draco-m68k. Later that year, in November 2014 according to his website, Gray publishes most of his old CP/M and Amiga sources on graysage.com, including the Draco compiler, linker and libraries

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

Language Influence

Influenced By

Influenced

Toy AmigaMUD

Running Today

Run examples using the official Docker image:

docker pull
Last updated: