This is an implementation of a BASIC interpreter providing a BASICODE runtime environment independent of any emulator (unless you count the Java VM as one). The point of this project is to have such a thing, rather than providing a highly optimised BASICODE run-time environment. Frankly, the JVM, off the shelf, will do a good enough job at delivering run-time performance. This is also why the BASICODE implementation does not sport any translation to Java bytecodes. The whole thing should be simple, first and foremost.
If you're not interested in building the project before trying it, you can
download an executable JAR file (basicode.jar
) from the
release page.
The project was built using Java 21 and Maven. Once those are installed, just
running mvn package
on the command line should be enough to build
everything and run the tests.
The mvn package
run will generate an executable JAR file named
basicode.jar
in the project root. This file includes all relevant
dependencies, so it can be used as a standalone "executable" for BASICODE as
long as you still have Java 21 installed.
To run a BASIC file from the command line at the project root, run this (the
-hold
argument will make the BASICODE window stay after the program has
run, until you press a key):
$ java -jar basicode.jar -hold examples/hello.bas
This works for other BASICODE programs, as long as you point to the right
basicode.jar
and BASIC source file. If no BASIC source file is given, a
dialogue will open that lets you choose one.
The BASICODE implementation is meant to be simple, and to be as "standalone" as possible. Therefore, the implementation relies on out-of-the box components of the JDK as much as possible. The only exception is the parser generator: for the grammar to be more easily writeable and maintainable, the implementation uses JavaCC. For the GUI, the standard AWT and Swing packages are used.
The BASIC grammar is located in the file basic.jj
in the de.haupz. basicode.parser
package. All other files in that package are generated
and should not be modified. The best way to modify the grammar is to modify
basic.jj
and rebuild the project using mvn compile
.
The grammar is straightforward. While there are numerous BASIC dialects that do not use line numbers (or make them optional), the BASICODE implementation here is meant to be compatible with the BASICODE sources "out there". Therefore, the grammar here enforces the use of line numbers.
Several other restrictions the BASICODE conventions impose - e.g., the maximum length of a source code line being 60 characters - are not enforced.
The grammar, during parsing, generates an abstract syntax tree (AST) of the program. The nodes of this AST are directly used by the interpreter (see below).
The AST nodes generated by the parser contain all the logic that is needed to run the program they represent. The BASIC interpreter used here thus embodies an AST interpreter design.
The main interpreter loop is contained in the ProgramNode
class, which can
be found in the de.haupz.basicode.ast
package. Many of the AST node
come with a piece of JavaDoc commentary that describes how they work, so
I'll refer to those for further details.
BASICODE supports reading from and writing to files on different kinds of media that were in use at the time when it was invented. These include cassette tapes, floppy disks, and microdrives. Since this BASICODE implementation would typically not have access to such media, it defaults to always opening files on the file system the implementation is running on.
If file names are given without any directory prefix (which would be unusual
in BASICODE to begin with), files will be expected to be located, and can be
expected to be created, in the directory the java
command to start
BASICODE was issued.
Similarly to file I/O, printer output is also emulated. The BASICODE
implementation will open a file named BASICODE-printer.txt
that will
contain any output sent to the printer.
The grammar and basic functionality of the BASICODE implementation are
covered in a decent amount of unit tests, which can be found in the test
directory. The mvn test
command will run them after building the project,
and building the standalone JAR using mvn package
will run the tests as
well.
Some BASICODE example programs can be found in the examples
directory.
They are mostly simple, and serve to test particular aspects of the BASICODE
conventions.
A vast set of examples can be found on Rob Hagemans' BASICODE in the browser page, or in his GitHub repository dedicated to BASICODE examples.
If you're interested in contributing to this project, please find details in
CONTRIBUTING.md
.
This project is under the MIT Licence, non-contagious, well-intentioned, and harmless.
The font used in the emulated console is "Amstrad CPC464 Regular" by Wesley Clarke. It's included here thanks to being licenced with CC BY-SA 3.0.
I'm immensely grateful to Thomas Rademacher of basicode.de for introducing me to BASICODE. Many thanks to Bernd Bock and other members of Joyce-User-AG for encouragement and bug reports.