DEV Community

loading...

Laying down ground work for a Bytecode Virtual Machine

rj722 profile image Rahul Jha ・2 min read

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.

Chunk. What chunk?

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:

  1. 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).

  2. 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");
Enter fullscreen mode Exit fullscreen mode

Our disassembler outputs this:

== Test Chunk ==
0000  122 OP_CONSANT          0 '1.2'
0002  123 OP_CONSANT          1 '456'
0004    | OP_RETURN
Enter fullscreen mode Exit fullscreen mode

Discussion (1)

pic
Editor guide
Collapse
rj722 profile image
Rahul Jha Author

Here's the repository on GitHub: github.com/RJ722/clox if someone wants to follow along. The results in the post are from commit 03313fd.