Skip to content

mrjameshamilton/loxlox

Repository files navigation

Lox.lox

A Lox interpreter written in Lox which passes the tests in the Lox test suite.

Native functions

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.

Building

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

Performance

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;