COCOA
Chuck McManis's line-numbered BASIC-80-style dialect, implemented as a BASIC interpreter written entirely in Java and taught step by step in his 1997 JavaWorld "Java In Depth" series on building interpreters.
Created by Chuck McManis
COCOA is a small, line-numbered dialect of BASIC. It is also the name of the interpreter, written entirely in Java, that runs it. Chuck McManis, a former member of Sun’s Java group, wrote it as the running example for a three-part series in his JavaWorld column “Java In Depth” in May, June and July 1997. In his own words it is “a primitive BASIC, uses line numbers, implements most of BASIC-80.” COCOA was never meant to compete with commercial BASICs. It was meant to show, in about 40 small classes, how to build and embed a scripting language inside a Java program. That makes it an unusually well-documented piece of early Java history: every class in the interpreter was published and explained in print.
COCOA has nothing to do with Apple’s Cocoa application framework, or with Apple’s earlier children’s simulation tool of the same name (later Stagecast Creator). Some catalogues list this COCOA as a 1969 simulation language. No evidence supports that date or category: every source traces the name to McManis’s 1997 interpreter.
History & Origins
A Java insider writing about interpreters
McManis joined the group that became Java just after FirstPerson Inc. was formed, and stayed through Java’s alpha and beta releases. According to the biography in his JavaWorld articles, he programmed the Java version of Sun’s home page in May 1995. After leaving Sun, McManis wrote the “Java In Depth” column for JavaWorld from April 1996 to August 1998, most months but not all (his own index lists no column for several months in late 1997 and 1998). Each column went deep on one topic: threads, class loaders, containers, and, in early 1997, lexical analysis.
The January and February 1997 columns covered Java’s StringTokenizer and StreamTokenizer, and the February one built an interactive calculator like the Unix bc(1) command. On the page where McManis later collected his column sources, he wrote that the February column “triggered a discussion about what other sort of interpreted things one might do in Java and it was where the whole idea of doing a BASIC interpreter came up.”
Why BASIC?
Part 1 of the interpreter series opens with a friend laughing at the idea and asking, “Why in the world would you build a BASIC interpreter in Java?” McManis gave two reasons. The simple one was that it was fun, and that BASIC was a language he had “fond memories” of from early personal computing. The serious one was that Java applications were growing up. Developers were moving past “tumbling Duke applets” to serious applications that needed user-programmable macro or configuration languages. He pointed to Emacs Lisp, to REXX (which he met on the Amiga through ARexx ports), and to Mike Cowlishaw’s then-new NetRexx as examples. A BASIC in Java, he wrote, would be a fun way to show how scripting languages “can be written in Java and, through their integration with Java, show how they can enhance the capabilities of your Java applications.”
For the dialect he chose BASIC-80, which he described as “popular on the CP/M operating system in the late seventies” and “only moderately more complex than the simplest dialects.”
Dating COCOA
The public debut is well documented. Part 1 appeared in the May 1997 JavaWorld (dated 1 May 1997 in the magazine’s archive), and its resources section links to “COCOA, a BASIC interpreter written in Java.” Part 2 followed in June and Part 3 in July. The interpreter source files in the column’s code bundle carry file dates of 29 April 1997.
There is one wrinkle. The source headers and the interpreter’s startup banner say “Copyright (c) 1996 Chuck McManis,” and the COCOA applet page also carries a 1996 copyright. McManis’s later recollection puts the idea after the February 1997 column. So some of the work may have started in late 1996, or the 1996 notice may simply have been carried over from his earlier column code. This page uses 1997, the year COCOA was first published.
Design Philosophy
COCOA was designed as a teaching artifact as much as a language, and the three articles are explicit about the design goals.
- Parse once, then execute a tree. McManis weighed the classic read-parse-execute loop against parsing into a tree and executing it “in place”. He chose the tree because “tokenizing interpreters also are faster as they don’t need to re-scan the input every time they execute a statement.” The series makes that claim in general terms and gives no benchmark for COCOA.
- A small public interface. The embeddable API is a factory method,
Program.load(InputStream, PrintStream), which returns a parsed program, and an instance method,run(InputStream, OutputStream), which executes it against any pair of streams. That split between loading and executing was, as McManis put it, “the two halves of any interpreter.” - One class per statement. Each BASIC keyword is its own subclass of
Statement(GOTOStatement,FORStatement,PRINTStatementand so on), and each parses its own arguments in its constructor. New statements can be added “with a minimum impact on the classes that were already in place.” - Everything computable is an Expression. Constants, variables, operators and built-in functions are all subclasses of
Expressionwith avalue()method. McManis called this idea “stolen shamelessly from Lisp.” - Hand-written, not generated. McManis had written about the JavaCC parser generator (then called Jack) for JavaWorld in December 1996. He still wrote COCOA’s lexer and parser by hand, judging that a generator was overkill for a grammar this size. He later said he might redo COCOA with such a tool “to make it more maintainable.”
Key Features
Program structure
A COCOA program is a set of numbered statements. Lines entered with a number are stored for later execution, and lines without one run immediately. Several statements can share a line if separated by colons. McManis’s canonical example from Part 1:
| |
LET is optional, and any statement that begins with a variable name is treated as an assignment. Following old BASICs that saved memory, ? is shorthand for PRINT and a leading ' for REM.
Statements
The COCOA programming documentation lists these statements:
| Group | Statements |
|---|---|
| Assignment and data | LET, DATA, READ, RESTORE, DIM |
| Control flow | GOTO, GOSUB, RETURN, IF ... THEN, ON ... GOTO, ON ... GOSUB, FOR ... TO ... STEP, NEXT, STOP, END |
| I/O | PRINT, INPUT |
| Miscellaneous | REM, RANDOMIZE, TRON, TROFF |
TRON turns on statement tracing and can take a file name to send the trace to a file. DATA statements can appear anywhere in the program: before running, the interpreter executes every DATA statement to fill its data store, then skips them during normal execution.
Types, variables and arrays
COCOA has two data types for variables: numbers, stored internally as Java double, and strings, marked by a trailing $. Boolean values exist only inside IF conditions. Arrays must be declared with DIM before use, can have up to four dimensions, and share a namespace with scalar variables. Unlike some BASICs, undeclared arrays do not default to ten elements.
The sources disagree on variable names. The programming documentation limits them to A-Z and A0-Z9 (and A$-Z$ for strings). But Part 1 of the series says longer names such as FOO and FOO2 are valid and case-insensitive, and the published lexer does accept multi-character letter-and-digit names, lowercasing them as it reads.
Operators and functions
The expression grammar has arithmetic, comparison, bitwise and Boolean operators. Two quirks stand out for BASIC programmers: exponentiation is written **, and ^ means bitwise exclusive OR. The Boolean operators use Fortran-style dotted names:
| |
The built-in function library covers RND, INT, SIN, COS, TAN, ATN, SQR, MAX, MIN, ABS, LOG, SGN, LEN, VAL, STR$, CHR$, LEFT$, RIGHT$, MID$, SPC$ and TAB (spelled TAB$ in the programming documentation, but registered as tab in the published source). For “legacy programs”, FRE always returns 8192. McManis put argument parsing inside FunctionExpression itself so that extra function libraries could be plugged in as subclasses.
The interactive environment
Wrapped in a CommandInterpreter, COCOA acts like a home-computer BASIC prompt. It accepts the commands NEW, RUN, LIST, CAT, DEL, RESUME, CONT, SAVE, LOAD, DUMP and BYE. On McManis’s web page the interpreter ran as an applet in a pop-up console window, with a console class reportedly credited to Dave Dyer. Typing while a program runs interrupts it at the current statement.
Winterberg’s 99 Bottles of Beer entry shows the style well: the whole song is one line pasted into that window.
| |
Implementation
The interpreter is a single Java package, basic, of roughly 40 classes, plus a few utility classes from McManis’s own libraries. Program lines are stored in a modified red-black tree keyed by line number, which he had built in an earlier column on containers. Variables are kept in a second red-black tree that acts as the symbol table. Multidimensional arrays are flattened into one Java array, with the offset computed from per-dimension multipliers. GOSUB return addresses go on a java.util.Stack.
Because the interpreter was designed to run as a thread, several COCOA programs could run at once in one Java program. McManis suggested this could support something like the programmable robot-battle games he remembered from the Apple II and PC. He also noted the practical payoff of Java’s portability: “COCOA ran on Unix systems and Macintoshes the same day I got working on a Windows 95 based PC.”
Licensing
COCOA was never open source. The source headers allow use, copying and modification for non-commercial purposes only, and McManis stressed repeatedly that the code was copyrighted: “use it to learn about writing interpreters but don’t redistribute my code.” The COCOA home page offers commercial licences, which he said had been sold before and cost “in the low four figures.”
Evolution
COCOA did not really evolve after 1997. It was finished as a column example. His own index lists no JavaWorld column after August 1998, and no later release of COCOA is documented. After a fire destroyed his web server and he found he had no usable backup, McManis rebuilt his column pages from the Wayback Machine and Zip disks at mcmanis.com, where, by his own account, they had been restored by about October 2004. The COCOA home page, programming documentation and source zip are still served there over plain HTTP.
The 1997 applet used the Java 1.0-era AWT and applet model, which modern browsers no longer support. Running it today means compiling the published sources with a JDK, and old APIs such as DataInputStream.readLine() will produce deprecation warnings.
Current Relevance
COCOA is historical. It has no community, no maintained implementation and no Docker image. It survives in three places: McManis’s own site, InfoWorld’s re-hosted copies of the old JavaWorld articles, and entries in language catalogues such as the 99 Bottles of Beer collection and Robert Tolksdorf’s list of JVM languages.
Why It Matters
COCOA is a snapshot of the moment, barely two years after Java’s public release, when developers began to treat the JVM as a host for other languages rather than just a runtime for Java. McManis’s series sat alongside early JVM-hosted languages such as NetRexx, the Jacl Tcl interpreter and small Lisps, which he cited as references. It showed, with complete source code, how an object-oriented design (one class per statement, expressions as a tree of polymorphic nodes, a narrow load/run API) turns a toy language into something that can be embedded in another application. Those ideas became standard in later JVM scripting work. The COCOA series itself remains a clear, readable introduction to how a tree-walking interpreter is put together.
Timeline
Notable Uses & Legacy
JavaWorld "Java In Depth" interpreter series
COCOA was the worked example for McManis's three-part 1997 series on building interpreters in Java. It showed how to write a hand-built lexer, a recursive-descent parser, a parse tree of Statement and Expression subclasses, and an embeddable execution engine. McManis wrote that his class loader column and the BASIC interpreter series "probably brought me the most correspondence" of all his columns
Commercial licensees
McManis wrote that "a couple of people have licensed the code and are using it in their products", with licences "in the low four figures". The licensees and products are not named in any source found
99 Bottles of Beer collection
Philipp Winterberg's 2005 entry fits the whole song into one FOR/NEXT line, meant to be pasted into the COCOA applet window
JVM language catalogues
Robert Tolksdorf's long-running list of languages for the Java Virtual Machine includes COCOA as an early example of a language hosted on the JVM