A Lox interpreter written in Lox which passes the tests in the Lox test suite.
The following native functions are required to run Lox.lox:
- read(): number
Returns 1 byte read from standard in.
Returns
nil
if the end of the stream is reached. - utf(number, number, number, number): string
Takes 1, 2, 3, or 4 bytes and returns a corresponding UTF character.
The Lox function
ascii
is a short-hand for utf(b1, nil, nil, nil). Lox supports UTF characters in strings but not other tokens. - exit(number) Exits with the given exit code; used to exit with 65 (error) or 70 (runtime error).
- printerr(string) Prints the string to standard error.
These are implemented in a patch for the original jlox interpreter, in the jlox compiler and in my implementation of clox.
Lox.lox has been tested with the original jlox interpreter, the jlox compiler and clox which are provided as a git submodules, which should be checked out:
$ git submodule update --init --recursive
You'll need Java 20, Dart 2.19 and GCC to build. A build script is provided to patch and build the original jlox interpreter and compile the Lox.lox to a jar with the jlox compiler:
$ ./build.sh
A Lox script can be run with the bin/loxlox
script which will
pipe the contents of the specified file to the compiled Lox.lox.
$ echo "print \"Hello World\";" > hello.lox
$ bin/loxlox hello.lox
Hello World
The Lox tests can be run by running the test.sh
script.
$ ./test.sh
As a quick performance test, running the below fibonacci example, gives the following run times (on my laptop, approximate average over several runs):
jlox interpreter | jlox compiler | clox | |
Directly | 1 second | 0.10 seconds | 0.19 seconds |
Lox.lox | 280 seconds | 18 seconds | 24 seconds |
fun fib(n) {
if (n < 2) return n;
return fib(n - 2) + fib(n - 1);
}
var start = clock();
print fib(30);
var end = clock();
print end - start;