ReviewOS

also looking at this

home-lang/home

fix(interpreter): keep 2^63 as a float in floor, ceil and round

#932
Open mkantautas wants to merge fix/interpreter-floor-ceil-round-max into main
2 files +22 -3
packages/interpreter/src/interpreter.zigmodified+5-3
Changes to packages/interpreter/src/interpreter.zig
@@ -3464,8 +3464,10 @@ pub const Interpreter = struct {
34643464 if (val == .Float) {
34653465 const floored = @floor(val.Float);
34663466 // If the result fits in i64, return Int; otherwise Float.
3467 // maxInt(i64) rounds up to 2^63 as an f64, which does not fit,
3468 // so the upper bound is exclusive.
34673469 if (floored >= @as(f64, @floatFromInt(std.math.minInt(i64))) and
3468 floored <= @as(f64, @floatFromInt(std.math.maxInt(i64))))
3470 floored < @as(f64, @floatFromInt(std.math.maxInt(i64))))
34693471 {
34703472 return Value{ .Int = @intFromFloat(floored) };
34713473 }
@@ -3481,7 +3483,7 @@ pub const Interpreter = struct {
34813483 if (val == .Float) {
34823484 const ceiled = @ceil(val.Float);
34833485 if (ceiled >= @as(f64, @floatFromInt(std.math.minInt(i64))) and
3484 ceiled <= @as(f64, @floatFromInt(std.math.maxInt(i64))))
3486 ceiled < @as(f64, @floatFromInt(std.math.maxInt(i64))))
34853487 {
34863488 return Value{ .Int = @intFromFloat(ceiled) };
34873489 }
@@ -3497,7 +3499,7 @@ pub const Interpreter = struct {
34973499 if (val == .Float) {
34983500 const rounded = @round(val.Float);
34993501 if (rounded >= @as(f64, @floatFromInt(std.math.minInt(i64))) and
3500 rounded <= @as(f64, @floatFromInt(std.math.maxInt(i64))))
3502 rounded < @as(f64, @floatFromInt(std.math.maxInt(i64))))
35013503 {
35023504 return Value{ .Int = @intFromFloat(rounded) };
35033505 }
packages/interpreter/tests/program_eval_test.zigmodified+17-0
Changes to packages/interpreter/tests/program_eval_test.zig
@@ -46,6 +46,23 @@ test "eval: print a string literal (hello world)" {
4646 );
4747}
4848
49test "eval: floor, ceil and round keep 2^63 as a float" {
50 try runProgram(
51 \\fn main() {
52 \\ let max = 9223372036854775807.0
53 \\ assert(is_float(floor(max)))
54 \\ assert(is_float(ceil(max)))
55 \\ assert(is_float(round(max)))
56 \\ assert(is_int(floor(9223372036854774784.0)))
57 \\ assert(floor(9223372036854774784.0) == 9223372036854774784)
58 \\ assert(is_int(ceil(-9223372036854775808.0)))
59 \\ assert(ceil(-9223372036854775808.0) == -9223372036854775807 - 1)
60 \\ assert(is_int(round(2.5)))
61 \\ assert(round(2.5) == 3)
62 \\}
63 );
64}
65
4966test "eval: let-binding then use" {
5067 try runProgram(
5168 \\fn main() {