sx: format_number helper — defuse int_of_float overflow on huge floats
Shared formatter in sx_types.ml. Small integer-valued floats still print as plain ints; floats outside safe-int range (|n| >= 1e16) now print as %.17g (full precision) instead of silently wrapping to negative or 0. Non-integer values keep %g 6-digit behavior — no existing SX tests regress. Unblocks Number.MAX_VALUE / Math.pow(2,N) style tests in js-on-sx where iterative float loops were collapsing to 0 at ~2^63. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -79,9 +79,7 @@ let as_bool = function
|
||||
|
||||
let rec to_string = function
|
||||
| String s -> s
|
||||
| Number n ->
|
||||
if Float.is_integer n then string_of_int (int_of_float n)
|
||||
else Printf.sprintf "%g" n
|
||||
| Number n -> Sx_types.format_number n
|
||||
| Bool true -> "true"
|
||||
| Bool false -> "false"
|
||||
| Nil -> ""
|
||||
|
||||
@@ -15,9 +15,7 @@ let prim_call name args =
|
||||
(** Convert any SX value to an OCaml string (internal). *)
|
||||
let value_to_str = function
|
||||
| String s -> s
|
||||
| Number n ->
|
||||
if Float.is_integer n then string_of_int (int_of_float n)
|
||||
else Printf.sprintf "%g" n
|
||||
| Number n -> Sx_types.format_number n
|
||||
| Bool true -> "true"
|
||||
| Bool false -> "false"
|
||||
| Nil -> ""
|
||||
|
||||
@@ -378,9 +378,21 @@ let env_merge base overlay =
|
||||
|
||||
(** {1 Value extraction helpers} *)
|
||||
|
||||
(** Format a float safely — defuse [int_of_float] overflow on huge
|
||||
integer-valued floats, keep [%g] for fractions (unchanged). *)
|
||||
let format_number n =
|
||||
if Float.is_nan n then "nan"
|
||||
else if n = Float.infinity then "inf"
|
||||
else if n = Float.neg_infinity then "-inf"
|
||||
else if Float.is_integer n && Float.abs n < 1e16 then
|
||||
string_of_int (int_of_float n)
|
||||
else if Float.is_integer n then
|
||||
Printf.sprintf "%.17g" n
|
||||
else Printf.sprintf "%g" n
|
||||
|
||||
let value_to_string = function
|
||||
| String s -> s | Symbol s -> s | Keyword k -> k
|
||||
| Number n -> if Float.is_integer n then string_of_int (int_of_float n) else Printf.sprintf "%g" n
|
||||
| Number n -> format_number n
|
||||
| Bool true -> "true" | Bool false -> "false"
|
||||
| Nil -> "" | _ -> "<value>"
|
||||
|
||||
@@ -765,9 +777,7 @@ let rec inspect = function
|
||||
| Nil -> "nil"
|
||||
| Bool true -> "true"
|
||||
| Bool false -> "false"
|
||||
| Number n ->
|
||||
if Float.is_integer n then Printf.sprintf "%d" (int_of_float n)
|
||||
else Printf.sprintf "%g" n
|
||||
| Number n -> format_number n
|
||||
| String s ->
|
||||
let buf = Buffer.create (String.length s + 2) in
|
||||
Buffer.add_char buf '"';
|
||||
|
||||
Reference in New Issue
Block a user