Write c_fn_def() -- compile a function definition:
fn c_fn_def() void {
const fname: []const u8 = read_name();
if (cur() == '(') { pos += 1; skip(); }
var params: [8][]const u8 = undefined;
var ptypes: [8][]const u8 = undefined;
var pc: usize = 0;
while (cur() != ')' and cur() != 0) {
params[pc] = read_name();
if (cur() == ':') { pos += 1; skip(); ptypes[pc] = read_name(); } else { ptypes[pc] = "i64"; }
pc += 1;
if (cur() == ',') { pos += 1; skip(); }
}
if (cur() == ')') { pos += 1; skip(); }
var rtype: []const u8 = "i64";
if (is_letter(cur())) { rtype = read_name(); }
const body_start: usize = pos;
skip_block();
const body_end: usize = pos;
scan_for_locals(body_start, body_end);
emit_str("(func $");
emit_str(fname);
for (0..pc) |i| {
emit_str(" (param $");
emit_str(params[i]);
emit_str(" ");
emit_str(ptypes[i]);
emit_str(")");
}
emit_str(" (result ");
emit_str(rtype);
emit_str(")\n");
emit_locals();
pos = body_start;
c_block();
emit_op("drop"); // c_block always produces a value; function returns via 'return'
emit_const(0); // default return value if no 'return' hit
emit_str(")\n");
}
The function body goes through c_block which produces a value. We drop it and push 0 as a default return. Functions should use explicit return expr; -- the return instruction bypasses the default.