From ea22f6c9447ec6e6f3b3b2fe459ae343a9d8b55f Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Wed, 25 Mar 2026 16:42:22 +0300 Subject: [PATCH] transformer: fix different test results with and without -prod (fixes #26568) --- vlib/strconv/atof.c.v | 9 +++++ vlib/strconv/atof_test.c.v | 9 +++++ .../transformer/tests/const_infix_expr_test.v | 25 ++++++++++++ vlib/v/transformer/transformer.v | 39 +++++++++++-------- 4 files changed, 66 insertions(+), 16 deletions(-) diff --git a/vlib/strconv/atof.c.v b/vlib/strconv/atof.c.v index 36689d9cb..1433d2635 100644 --- a/vlib/strconv/atof.c.v +++ b/vlib/strconv/atof.c.v @@ -146,6 +146,10 @@ fn parser(s string) (ParserState, PrepNumber) { // read mantissa for i < s.len && s[i].is_digit() { + if pn.mantissa == 0 && s[i] == c_zero { + i++ + continue + } // println("${i} => ${s[i]}") if digx < digits { pn.mantissa *= 10 @@ -161,6 +165,11 @@ fn parser(s string) (ParserState, PrepNumber) { if i < s.len && s[i] == `.` { i++ for i < s.len && s[i].is_digit() { + if pn.mantissa == 0 && s[i] == c_zero { + pn.exponent-- + i++ + continue + } if digx < digits { pn.mantissa *= 10 pn.mantissa += u64(s[i] - c_zero) diff --git a/vlib/strconv/atof_test.c.v b/vlib/strconv/atof_test.c.v index 6d4dab2c7..df34b004c 100644 --- a/vlib/strconv/atof_test.c.v +++ b/vlib/strconv/atof_test.c.v @@ -105,6 +105,15 @@ fn test_atof_subnormal() { assert strconv.atof64('-1.0e-320') or { panic('parse error') } == -1.0e-320 } +fn test_atof_small_decimal_with_many_leading_zeroes() { + assert strconv.atof64('0.0000000000000000005') or { panic('parse error') } == strconv.atof64('5e-19') or { + panic('parse error') + } + assert strconv.atof64('-0.0000000000000000005') or { panic('parse error') } == strconv.atof64('-5e-19') or { + panic('parse error') + } +} + fn test_atof_errors() { if x := strconv.atof64('') { eprintln('> x: ${x}') diff --git a/vlib/v/transformer/tests/const_infix_expr_test.v b/vlib/v/transformer/tests/const_infix_expr_test.v index 123b0e63b..af6aa0c84 100644 --- a/vlib/v/transformer/tests/const_infix_expr_test.v +++ b/vlib/v/transformer/tests/const_infix_expr_test.v @@ -1,3 +1,4 @@ +import math import v.ast import v.pref import v.parser @@ -31,3 +32,27 @@ fn main() { dump(folded_expr) assert '${folded_expr}' == '5' } + +fn test_float_infix_expr_keeps_roundtrip_precision() { + println(@LOCATION) + source_text := ' +fn main() { + x := 9.765625000000004e-04 + 0.0 +} +' + mut table := ast.new_table() + vpref := &pref.Preferences{} + mut prog := parser.parse_text(source_text, '', mut table, .skip_comments, vpref) + mut checker_ := checker.new_checker(table, vpref) + checker_.check(mut prog) + mut t := transformer.new_transformer_with_table(table, vpref) + + main_fn := table.cur_fn + assign_stmt := main_fn.stmts[0] as ast.AssignStmt + mut infix_expr := assign_stmt.right[0] as ast.InfixExpr + folded_expr := t.infix_expr(mut infix_expr) + + assert folded_expr is ast.FloatLiteral + literal := folded_expr as ast.FloatLiteral + assert math.f64_bits(literal.val.f64()) == math.f64_bits('9.765625000000004e-04'.f64()) +} diff --git a/vlib/v/transformer/transformer.v b/vlib/v/transformer/transformer.v index 506efef22..e5cbd5c7c 100644 --- a/vlib/v/transformer/transformer.v +++ b/vlib/v/transformer/transformer.v @@ -3,8 +3,10 @@ // that can be found in the LICENSE file. module transformer +import math import v.pref import v.ast +import v.token import v.util pub struct Transformer { @@ -60,6 +62,23 @@ pub fn (mut t Transformer) transform(mut ast_file ast.File) { } } +fn folded_float_literal(value f64, pos token.Pos) ast.FloatLiteral { + // ast.FloatLiteral stores source text, so the folded value needs a + // decimal/scientific form that reparses to the same bits. + short := value.str() + if math.f64_bits(short.f64()) == math.f64_bits(value) { + return ast.FloatLiteral{ + val: short + pos: pos + } + } + exact := value.strsci(17) + return ast.FloatLiteral{ + val: exact + pos: pos + } +} + pub fn (mut t Transformer) find_new_range(node ast.AssignStmt) { if !t.pref.is_prod { return @@ -985,28 +1004,16 @@ pub fn (mut t Transformer) infix_expr(mut node ast.InfixExpr) ast.Expr { } } .plus { - return ast.FloatLiteral{ - val: (left_val + right_val).str() - pos: pos - } + return folded_float_literal(left_val + right_val, pos) } .mul { - return ast.FloatLiteral{ - val: (left_val * right_val).str() - pos: pos - } + return folded_float_literal(left_val * right_val, pos) } .minus { - return ast.FloatLiteral{ - val: (left_val - right_val).str() - pos: pos - } + return folded_float_literal(left_val - right_val, pos) } .div { - return ast.FloatLiteral{ - val: (left_val / right_val).str() - pos: pos - } + return folded_float_literal(left_val / right_val, pos) } else {} } -- 2.39.5