Add for to the compiler. Emit block/loop/br_if/br with auto-init and auto-increment. Store the end bound in $__for_end:
if (streq(word, "for")) {
if (cur() == '(') { pos += 1; skip(); }
c_expression(); // start
if (cur() == '.') { pos += 1; }
if (cur() == '.') { pos += 1; }
skip();
c_expression(); // end
emit_str(" local.set $__for_end\n");
if (cur() == ')') { pos += 1; skip(); }
if (cur() == '|') { pos += 1; skip(); }
const loop_var: []const u8 = read_name();
if (cur() == '|') { pos += 1; skip(); }
// init
emit_str(" local.set $"); emit_str(loop_var); emit_byte('\n');
emit_op("block");
emit_op("loop");
// condition: i >= end -> exit
emit_str(" local.get $"); emit_str(loop_var); emit_byte('\n');
emit_str(" local.get $__for_end\n");
emit_op("i64.ge_s");
emit_op("br_if 1");
c_block();
emit_op("drop");
// increment
emit_str(" local.get $"); emit_str(loop_var); emit_byte('\n');
emit_op("i64.const 1");
emit_op("i64.add");
emit_str(" local.set $"); emit_str(loop_var); emit_byte('\n');
emit_op("br 0");
emit_op("end");
emit_op("end");
return false;
}
Add (local $__for_end i64) to emit_locals(). Update scan_for_locals to detect |name| in for statements and register the capture as a local.
Agreement tests:
check_both("var s: i64 = 0; for (0..5) |i| { s += i; } s", 10);
check_both("var s: i64 = 0; for (0..3) |i| { for (0..4) |j| { s += 1; } } s", 12);
### true and false