The VM
vm-scan-functions

Function calls. We need to pre-scan the WAT for (func $name ... lines to know where each function starts and ends, and what its parameters are.

var vm_fn_names: [32][]const u8 = undefined;
var vm_fn_start: [32]usize = undefined;
var vm_fn_end: [32]usize = undefined;
var vm_fn_params: [32][8][]const u8 = undefined;
var vm_fn_param_count: [32]usize = undefined;
var vm_fn_count: usize = 0;

Write vm_scan_functions() -- scan through vm_lines, find each (func $name, extract the name and parameter names, find the matching ) that closes the function.

fn vm_scan_functions() void {
    vm_fn_count = 0;
    var i: usize = 0;
    while (i < vm_line_count) {
        const line: []const u8 = vm_trim(vm_lines[i]);
        if (starts_with(line, "(func $")) {
            const name: []const u8 = parse_name(line, 0);
            vm_fn_names[vm_fn_count] = name;
            vm_fn_start[vm_fn_count] = i + 1; // first line of body

            // extract param names
            var pc: usize = 0;
            var j: usize = i;
            // params are on the same line or nearby
            // scan this line for (param $name
            var p: usize = 0;
            while (p < line.len) {
                if (p + 7 < line.len and starts_with(line[p..], "(param $")) {
                    const pname: []const u8 = parse_name(line, p);
                    vm_fn_params[vm_fn_count][pc] = pname;
                    pc += 1;
                }
                p += 1;
            }
            vm_fn_param_count[vm_fn_count] = pc;

            // find closing )  -- a line that is just ")"
            j = i + 1;
            while (j < vm_line_count) {
                const ln: []const u8 = vm_trim(vm_lines[j]);
                if (streq(ln, ")")) {
                    break;
                }
                j += 1;
            }
            vm_fn_end[vm_fn_count] = j;
            vm_fn_count += 1;
        }

        // Also handle (func (export "main") -- no $name
        if (starts_with(line, "(func (export")) {
            vm_fn_names[vm_fn_count] = "main";
            vm_fn_start[vm_fn_count] = i + 1;
            vm_fn_param_count[vm_fn_count] = 0;
            var j: usize = i + 1;
            while (j < vm_line_count) {
                if (streq(vm_trim(vm_lines[j]), ")")) { break; }
                j += 1;
            }
            vm_fn_end[vm_fn_count] = j;
            vm_fn_count += 1;
        }

        i += 1;
    }
}