Missed writing an entry yesterday, didn't miss coding though. Already done with laying down the foundation of
clox, our Bytecode VM.
(I'm gonna be making this post very brief, because well, Bob already walks us through the entire code in the book -- https://craftinginterpreters.com/chunks-of-bytecode.html)
All we can do with
clox right now is make a chunk and write to it. There is no front-end to the compiler, no interpretation of the code. Heck, we don't even have the full list of opcodes (each opcode is a unique byte which corresponds to a special instruction of our language, e.g.,
OP_RETURN for returning from a function.) yet.
Consider a chunk as a sequence of codes, each a byte long. Now, these bytes might mean different things: either opcodes or pointers to the data those opcodes need. But, that's all a chunk is: A sequence of bytes.
How do we know which is which?
To interpret the meaning of these bytes, we need to iterate through the entire sequence, and match it against a list of values:
Say, the first value we encounter is
0x10. Let's assume that we had mapped it to
OP_RETURN. (It is very unlikely for the first opcode to be
OP_RETURN, but bear it for it makes the example easy).
Next byte in the chunk might correspond to
OP_CONSTANT. Whenever we store a
OP_CONSTANT, we also need to store the value this constant holds. By convention, the next byte holds the address of this value.
You can see a pattern here. Each opcode may have zero or more operands -- so our compiler can easily figure out which is which.
For now, all it does is exactly that. We hand-write a bunch of values in the chunk, like this, and let it "disassemble" it:
initChunk(&chunk); int constant = addConstant(&chunk, 1.2); // 122 is an arbitrary line number I passed. writeChunk(&chunk, OP_CONSTANT, 122); writeChunk(&chunk, constant, 122); int constant2 = addConstant(&chunk, 456); writeChunk(&chunk, OP_CONSTANT, 123); writeChunk(&chunk, constant2, 123); writeChunk(&chunk, OP_RETURN, 123); disassembleChunk(&chunk, "Test Chunk");
Our disassembler outputs this:
== Test Chunk == 0000 122 OP_CONSANT 0 '1.2' 0002 123 OP_CONSANT 1 '456' 0004 | OP_RETURN