diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 9a3013e8e..92ee2299f 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -4594,6 +4594,13 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As operand->value.value_float = bit_cast(abs); break; } + case ExactValue_Rational: { + mp_int n; mp_init(&n); + defer (mp_clear(&n)); + mp_abs(&operand->value.value_rational->num, &n); + operand->value = exact_value_rational_from_ints(&n, &operand->value.value_rational->den); + break; + } case ExactValue_Complex: { f64 r = operand->value.value_complex->real; f64 i = operand->value.value_complex->imag; diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 8c75dd8c0..9de4d8859 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -4873,6 +4873,11 @@ gb_internal void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, Typ fail = true; } break; + case ExactValue_Rational: + if (big_int_is_zero(&y->value.value_rational->num)) { + fail = true; + } + break; } if (fail) { diff --git a/src/checker.cpp b/src/checker.cpp index fa65098a8..59f1c9c25 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1480,6 +1480,7 @@ gb_internal void init_universal(void) { type = t_untyped_integer; break; case ExactValue_Float: + case ExactValue_Rational: type = t_untyped_float; break; } diff --git a/src/exact_value.cpp b/src/exact_value.cpp index 60126a401..1cd282c2a 100644 --- a/src/exact_value.cpp +++ b/src/exact_value.cpp @@ -502,7 +502,7 @@ gb_internal ExactValue exact_value_to_integer(ExactValue v) { return exact_value_i64(cast(i64)cast(intptr)v.value_pointer); case ExactValue_Rational: - // Only an exact integer (den == 1 after reduction) converts to an integer. + // NOTE(bill): Only an exact integer (den == 1 after reduction) converts to an integer if (mp_cmp_d(&v.value_rational->den, 1) == MP_EQ) { ExactValue r = {ExactValue_Integer}; r.value_integer = {0}; @@ -1339,6 +1339,14 @@ gb_internal gbString write_exact_value_to_string(gbString str, ExactValue const case ExactValue_Float: return gb_string_append_fmt(str, "%.17g", v.value_float); case ExactValue_Rational: + // Integer-valued (den == 1, e.g. an overflowing literal like `1.0e400`) prints its exact decimal, + // so a diagnostic shows the real magnitude rather than an f64 that has rounded to +Inf. + if (mp_cmp_d(&v.value_rational->den, 1) == MP_EQ) { + String s = big_int_to_string(heap_allocator(), &v.value_rational->num); + str = gb_string_append_length(str, s.text, s.len); + gb_free(heap_allocator(), s.text); + return str; + } return gb_string_append_fmt(str, "%.17g", big_rat_to_f64(&v.value_rational->num, &v.value_rational->den)); case ExactValue_Complex: return gb_string_append_fmt(str, "%.17g+%.17gi", v.value_complex->real, v.value_complex->imag);