First working code generation for simple arithmetic

I've got my first bytecode output by the compiler. The runtime now takes a string, parses it into S-expressions, and passes them to the compilation phase. The compilation phase is more or less one-pass and emits an unoptimized bytecode for a "register machine". At the moment, the register machine is not there, so no execution yet. But I already know how to make it because the previous version of Valeri had it.

This is what the entry point in Valeri looks like now:


auto code_str = TRY(String::create("(* (+ 1 2 3) 4)"));
auto reader = Reader(code_str);

auto parsed = TRY(reader.read_one());
auto code_str_written = TRY(write_one(parsed));

// Print the s-expression back, to make sure that
// we've parsed it correctly
TRY(debug_print(code_str_written));

auto compiled = TRY(compile(parsed));
Function& fun = *compiled.to<Function>();

TRY(debug_print(TRY(fun.constants())));
TRY(debug_print(TRY(fun.code())));

And this is what it outputs to the console:


(* (+ 1 2 3) 4)

[1 2 3 4]

[
  #<opcode mov r0 c0>
  #<opcode mov r1 c1>
  #<opcode add r2 r0 r1>
  #<opcode mov r3 c2>
  #<opcode add r0 r2 r3>
  #<opcode mov r1 c3>
  #<opcode mul r0 r0 r1>
  #<opcode ret r0>
]

In this example, a few things can potentially be eliminated. If I were writing the bytecode by hand, I could've removed the pointless assignments of constants to registers and instead referred to constants directly in subsequent instructions. But at this point it will make the compiler a lot more complex than needed for the prototype.

Next steps will be:

Stay tuned.