Helper functions:
fn skip_past_block() i64 {
while (cur() != '{') {
if (cur() == 0) { return 0; }
src_pos += 1;
}
src_pos += 1; skip();
var depth: i64 = 1;
while (depth > 0) {
if (cur() == 0) { return 0; }
if (cur() == '{') { depth += 1; }
if (cur() == '}') { depth -= 1; }
if (depth > 0) { src_pos += 1; }
}
if (cur() == '}') { src_pos += 1; skip(); }
return 0;
}
fn skip_stmt() i64 {
while (cur() != ';') {
if (cur() == 0) { return 0; }
if (cur() == '{') { skip_past_block(); return 0; }
src_pos += 1;
}
src_pos += 1; skip();
return 0;
}
fn scan_locals() i64 {
var save: i64 = src_pos;
if (cur() == '{') { src_pos += 1; skip(); }
var depth: i64 = 0;
while (cur() != 0) {
if (cur() == '{') { depth += 1; }
if (cur() == '}') {
if (depth == 0) {
emit_s(" (local $__tmp i64)\n");
emit_s(" (local $__for_end i64)\n");
src_pos = save;
return 0;
}
depth -= 1;
}
if (is_letter(cur()) == 1) {
var w: i64 = read_name();
if (streq_mem(w, "var") == 1 or streq_mem(w, "const") == 1) {
var vname: i64 = read_name();
if (cur() == ':') { src_pos += 1; skip(); read_name(); }
if (is_global(vname) == 0) {
emit_s(" (local $"); emit_s(vname); emit_s(" i64)\n");
}
}
if (streq_mem(w, "for") == 1) {
// skip to |name| and register the capture variable
while (cur() != '|' and cur() != 0) { src_pos += 1; }
if (cur() == '|') { src_pos += 1; skip(); }
var capname: i64 = read_name();
if (cur() == '|') { src_pos += 1; skip(); }
emit_s(" (local $"); emit_s(capname); emit_s(" i64)\n");
}
} else {
src_pos += 1;
}
}
emit_s(" (local $__tmp i64)\n");
emit_s(" (local $__for_end i64)\n");
src_pos = save;
return 0;
}
scan_locals now also detects for loops and registers their capture variables as locals. It emits $__tmp and $__for_end for every function.