Add conversion builtins:
if (streq(name, "f64_from_i64")) {
pos += 1; skip();
const val: i64 = expression();
if (cur() == ')') { pos += 1; skip(); }
const f: f64 = @floatFromInt(val);
expr_is_float = true;
return @bitCast(f);
}
if (streq(name, "i64_from_f64")) {
pos += 1; skip();
const was_float: bool = expr_is_float;
expr_is_float = true;
const val: i64 = expression();
if (cur() == ')') { pos += 1; skip(); }
const f: f64 = @bitCast(val);
expr_is_float = was_float;
return @intFromFloat(f);
}
f64_from_i64(42) converts integer 42 to float 42.0 (as a bitcast i64). i64_from_f64(3.7) truncates to integer 3.
Test:
check_float("f64_from_i64(42)", 42.0);
check("i64_from_f64(3.7)", 3);
check("i64_from_f64(2.0 + 0.9)", 2); // truncates, not rounds
check_float("f64_from_i64(355) / f64_from_i64(113)", 3.14159);
The last test: 355/113 is a famous rational approximation of pi. With integer division it gives 3. With float division it gives 3.14159...
### Compiling floats
The compiler needs to emit the right WAT instructions based on types.