From 9a711c28b977d01b1b1b79ab1f16f3c1dbe9e343 Mon Sep 17 00:00:00 2001 From: Per Lundberg Date: Fri, 13 Oct 2023 21:59:12 +0300 Subject: [PATCH] WIP: Let's try to extract this to a separate PR another day. --- src/Perlang.Parser/NumberParser.cs | 13 +++++++++++-- .../Operator/Binary/BinaryOperatorData.cs | 2 +- src/stdlib/test/print.cc | 10 +++++++--- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/Perlang.Parser/NumberParser.cs b/src/Perlang.Parser/NumberParser.cs index 9caa8bc1..395fe725 100644 --- a/src/Perlang.Parser/NumberParser.cs +++ b/src/Perlang.Parser/NumberParser.cs @@ -22,8 +22,17 @@ public static INumericLiteral Parse(NumericToken numericToken) { // The explicit IFormatProvider is required to ensure we use 123.45 format, regardless of host OS // language/region settings. See #263 for more details. - float value = Single.Parse(numberCharacters, CultureInfo.InvariantCulture); - return new FloatingPointLiteral(value); + // + // An interesting detail: despite this being a `float` value, we parse it as a double since we + // might otherwise loose valuable precision. This is critical for working with numbers like + // 340282349999999991754788743781432688640.0f; parsing it as a Single at this point will round + // it to 3.4028235E+38 which looses a significant amount of precision. This is particularly + // important to get proper semantics for `double + float` operations. + + // TODO: Try to extract this change + changes to BinaryOperatorData to a PR of its own. Should + // work, and help provide smaller, more maintainable PRs. + double value = Double.Parse(numberCharacters, CultureInfo.InvariantCulture); + return new FloatingPointLiteral(value); } case 'd': diff --git a/src/Perlang.Tests.Integration/Operator/Binary/BinaryOperatorData.cs b/src/Perlang.Tests.Integration/Operator/Binary/BinaryOperatorData.cs index ec79de7c..f855ed24 100644 --- a/src/Perlang.Tests.Integration/Operator/Binary/BinaryOperatorData.cs +++ b/src/Perlang.Tests.Integration/Operator/Binary/BinaryOperatorData.cs @@ -341,7 +341,7 @@ public static class BinaryOperatorData { new object[] { "12", "34", "false" }, new object[] { "12", "12", "true" }, - new object[] { "12", "12.0", "false" }, // Same value but different types. Note: this is truthy in C# AND Java. + new object[] { "12", "12.0", "false" }, // Same value but different types. Note: this is truthy in C# AND Java. AND C++! We want to new object[] { "12.0", "12", "false" }, // Same value but different types. Note: this is truthy in C# AND Java. new object[] { "12.345", "12.345", "true" }, new object[] { "12.345", "67.890", "false" }, diff --git a/src/stdlib/test/print.cc b/src/stdlib/test/print.cc index ba2658af..a043eef5 100644 --- a/src/stdlib/test/print.cc +++ b/src/stdlib/test/print.cc @@ -86,7 +86,11 @@ TEST(PrintDouble_4294967283) TEST(PrintDouble_9223372036854775807) { - fwrite_mocked = true; - perlang::print(9223372036854775807.0); - fwrite_mocked = false; + float f = 12.0; + int i = 12; + perlang::print(f == i); + +// fwrite_mocked = true; +// perlang::print(9223372036854775807.0); +// fwrite_mocked = false; } \ No newline at end of file