The block/loop/br/br_if pattern for while loops.
Our compiler emits:
block ← outer (br target 1 = exit here)
loop ← inner (br target 0 = jump here)
;; condition
i64.eqz
br_if 1 ← exit the block (go past the outer end)
;; body
br 0 ← jump back to loop (go to inner start)
end ← inner end
end ← outer end
The VM needs a block stack to track where to jump. When we enter a block or loop, we push its line index and type. br 0 jumps to the innermost entry. br 1 jumps to the next one out.
For block: jumping means going to the end (forward -- exit the block).
For loop: jumping means going back to the loop line (backward -- repeat).
This distinction is crucial. br 0 on a loop goes backward. br 1 on a block goes forward.
const BlockKind = enum { block, loop, ift };
var vm_block_kind: [64]BlockKind = undefined;
var vm_block_target: [64]usize = undefined; // where to jump
var vm_block_depth: usize = 0;