My implementation of second part of Lox programming language from Crafting interpreters in C++. This implementation uses a bytecode VM to execute the programs.
Install meson
, ninja
and a C++ 20 capable compiler
$ meson setup builddir
$ cd builddir
$ ninja -j8
If you are on linux, run
$ ./src/cpplox
On windows, run
.\src\cpplox.exe
To run tests, you need to have Python 3
First install pytest
, a test automation library used to test programs.
Create a virtual environment
$ python -m venv .venv
Install dependencies
$ pip install -r requirements.txt
Run tests
$ meson setup builddir -Denable-tests=true
$ cd builddir
$ ninja -j8
$ meson test -v
Have Clang
installed along with asan
. You also need to follow the steps in the above section, pytest
must be installed and available on the PATH
Then run the following command,
$ ./development.sh
$ cpplox --help
Lox compiler and interpreter in C++
Usage:
cpplox [OPTION...] positional parameters
--print-tokens Show all tokens generated by the lexer along
with line position
--compile-only Compiles the source code to bytecode but does
not execute it
--dump-bytecode Dumps the bytecode generated by the compiler
before execution
--trace-execution Used for debugging: Prints the bytecode
instruction before executing it
--trace-eval-stack Used for debugginig: Prints the internal
evaluation stack before the instruction is
executed
--enable-step-mode Used for debugging: Enables step mode and
waits for input before an instruction is
executed
--eval-stack-size arg Maximum evaluation stack size allowed
(default: 1024)
-c, --command arg Execute the given command and exit
-h, --help Prints this help message
-v, --version Prints program version
-
The compiler de-duplicates both strings and integers (but not real numbers)
-
Supports 65k constants, and 65k global variables (accessed with 2 byte unsigned index)
-
const
variables
In global scope,
If a constant of the same name has already been declared, do not allow
redeclaration with var Example:
>> const x = 32;
>> var x = 50; // Not allowed
>> const x = 80;
>> const x = 90; // Not Allowed
>> var x = 95;
>> var x = 100; // Allowed
One difference is that redeclaration with const is not allowed since it helps make the vm simpler, otherwise an extra flag/byte needs to be maintained to identify if it's a const declaration or a var declaration.
switch
statement
Supports C-style switch statements with cases and default:
switch (value) {
case 1:
print "one";
break;
case 2:
var foo = "hello";
print foo;
break;
default:
print "other";
}
- Both the selector and the case value can be expressions
- Each arm of the switch statement defines a local scope, so variables can be declared within it
- There is no break statement, there is no fallthrough
- Cases cannot appear after the default statement
In local scope redeclaration of any form is disallowed
- Fix division by zero error
- Implement break statements