First real program compiled with Valeri

I've reached my first significant milestone with Valeri. It can now compile something useful to bytecode and then execute it in the virtual machine.

As an example, I've implemented a simple recursive factorial function:


(fn fact (n)
    (if (<= n 0)
        1
        (* n (fact (- n 1)))))

(fact 12)

If you save this code as factorial.vli, you can then run it with ./vli factorial.vli, and it will give you 479001600, as you would expect.

This may not seem impressive at a first glance, but to compile this example the compiler has to support:

Most importantly, this is not a recursive AST evaluator like how many people implement their first Lisp. This in fact compiles into a bytecode which is then executed on a virtual machine. It means that the performance is bad (due to lack of optimizations), but not completely abysmal.

The process of compilation is now 2-step:

To emit the bytecode, I'm following an approach that is close in spirit to the Incremental Approach to Compiler Construction paper. With the exception that the paper uses stack and an accumulator register, and my implementation is register-based like Lua, see Lua 5.0 paper for reference.

I'm very happy about the progress, but also am mindful of the fact that this is only the beginning. For this compiler to be really useful, it should give decent error reporting (both during the compilation phase and runtime phase). And this is where the real struggle will begin.