Est. 1997 Beginner

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

Paradigm Procedural (unstructured, line-numbered BASIC)
Typing Dynamic, two types (numeric and string) fixed by the $ name suffix
First Appeared 1997
Latest Version Column source release of April-June 1997 (Program.java marked version 1.1)

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, PRINTStatement and 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 Expression with a value() 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:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
100 REM This is probably the canonical BASIC example
110 REM Program. Note that REM statements are ignored.
120 PRINT "This is a test program."
130 PRINT "Summing the values between 1 and 100"
140 LET total = 0
150 FOR I = 1 TO 100
160     LET total = total + i
170 NEXT I
180 PRINT "The total of all digits between 1 and 100 is " total
190 END

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:

GroupStatements
Assignment and dataLET, DATA, READ, RESTORE, DIM
Control flowGOTO, GOSUB, RETURN, IF ... THEN, ON ... GOTO, ON ... GOSUB, FOR ... TO ... STEP, NEXT, STOP, END
I/OPRINT, INPUT
MiscellaneousREM, 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:

1
100 IF (A > 0) .AND. (B$ = "YES") THEN PRINT A ** 2

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.

1
for b=99 to 1 step -1:print b;" bottle(s) of beer on the wall,":print b;" bottle(s) of beer.":print "Take one down, pass it around,":print (b-1);" bottle(s) of beer on the wall.":print " ":next b

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

1997
In February, McManis's "Java In Depth" column in JavaWorld uses StreamTokenizer to build a bc-style calculator. Looking back, McManis wrote that the reader discussion it started was "where the whole idea of doing a BASIC interpreter came up"
1997
On 1 May, JavaWorld publishes "How to build an interpreter in Java, Part 1: The BASICs". It describes the design of a BASIC-80 dialect and links to "COCOA, a BASIC interpreter written in Java" on McManis's site. The 41 interpreter source files in the column's code bundle are dated 29 April 1997
1997
In June, "Part 2: The structure" names the dialect Cocoa, goes through the lexer and statement parser, and links to the full source and to the COCOA programming documentation
1997
In July, "Build an interpreter in Java -- Implement the execution engine" finishes the series. It covers expression evaluation, strings, multidimensional arrays and the run loop
1998
McManis's August 1998 column is the last one listed in his own index of JavaWorld columns. His COCOA pages stay online, first at professionals.com and later at mcmanis.com
2004
By about October 2004 (the date his index page gives as "today"), McManis has rebuilt his JavaWorld source pages at mcmanis.com/chuck/java/, COCOA included, from the Wayback Machine and old Zip disks. The building that housed his web server had caught fire and there was no usable backup
2005
On 20 April, Philipp Winterberg adds a COCOA version of "99 Bottles of Beer" to the 99-bottles-of-beer.net collection. It is a single line meant to be pasted into the interpreter window
2009
On 8 November, Robert Tolksdorf lists COCOA in his catalogue of programming languages for the Java Virtual Machine

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

Language Influence

Influenced By

BASIC-80

Running Today

Run examples using the official Docker image:

docker pull
Last updated: