From 8f6e529957d82f489bf4e7952a6129e4df000e58 Mon Sep 17 00:00:00 2001 From: Per Lundberg Date: Sun, 22 Oct 2023 22:55:02 +0300 Subject: [PATCH] (interpreter) Make `int == double` use value-type semantics (#413) This is an important preparation for https://github.com/perlang-org/perlang/pull/409, where we will use the same semantics. Doing the change already not for interpreted mode makes things easier, since we can then use the same tests for both interpreted and compiled mode. --- release-notes/v0.4.0.md | 2 ++ src/Perlang.Interpreter/PerlangInterpreter.cs | 16 +++++++++++++++- .../Operator/Binary/BinaryOperatorData.cs | 8 ++++---- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/release-notes/v0.4.0.md b/release-notes/v0.4.0.md index 6aa7a69c..8d558144 100644 --- a/release-notes/v0.4.0.md +++ b/release-notes/v0.4.0.md @@ -24,6 +24,7 @@ - Remove Moq dependency [[#380][380]] ### Fixed +- Make `int == double` use value-type semantics [[#413][413]] ### Tests - Minor test improvements [[#410][410]] @@ -39,3 +40,4 @@ [407]: https://github.com/perlang-org/perlang/pull/407 [410]: https://github.com/perlang-org/perlang/pull/410 [412]: https://github.com/perlang-org/perlang/pull/412 +[413]: https://github.com/perlang-org/perlang/pull/413 diff --git a/src/Perlang.Interpreter/PerlangInterpreter.cs b/src/Perlang.Interpreter/PerlangInterpreter.cs index dbf3c28a..f2f7feb9 100644 --- a/src/Perlang.Interpreter/PerlangInterpreter.cs +++ b/src/Perlang.Interpreter/PerlangInterpreter.cs @@ -9,6 +9,7 @@ using System.Numerics; using System.Reflection; using System.Text; +using Microsoft.CSharp.RuntimeBinder; using Perlang.Attributes; using Perlang.Exceptions; using Perlang.Internal.Extensions; @@ -948,10 +949,23 @@ private static bool IsEqual(object? a, object? b) if (a == null) { + // null != non-null return false; } - return a.Equals(b); + // Note: must use dynamic here since `object == object` behaves differently than e.g. `int == double`, + // tragically enough. More details: + // https://learn.microsoft.com/en-us/dotnet/api/System.Object.Equals?view=net-7.0#notes-for-callers + try + { + return (dynamic)a == (dynamic?)b; + } + catch (RuntimeBinderException) + { + // This will happen when trying to compare e.g `double == BigInteger`. We fall back to Equals() in this + // case, hoping that it will make sense... + return a.Equals(b); + } } public object? VisitGroupingExpr(Expr.Grouping expr) diff --git a/src/Perlang.Tests.Integration/Operator/Binary/BinaryOperatorData.cs b/src/Perlang.Tests.Integration/Operator/Binary/BinaryOperatorData.cs index afbb0e69..9616d111 100644 --- a/src/Perlang.Tests.Integration/Operator/Binary/BinaryOperatorData.cs +++ b/src/Perlang.Tests.Integration/Operator/Binary/BinaryOperatorData.cs @@ -284,8 +284,8 @@ public static class BinaryOperatorData { new object[] { "12", "34", "True" }, new object[] { "12", "12", "False" }, - new object[] { "12", "12.0", "True" }, // Same value but different types. Note: this is truthy in C# AND Java. - new object[] { "12.0", "12", "True" }, // Same value but different types. Note: this is truthy in C# AND Java. + new object[] { "12", "12.0", "False" }, // Same value but different types. We follow the precedent of C#, Java and C++ and consider these to be equal. + new object[] { "12.0", "12", "False" }, // Likewise new object[] { "2147483647", "4294967295", "True" }, new object[] { "2147483647", "9223372036854775807", "True" }, @@ -341,8 +341,8 @@ 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.0", "12", "False" }, // Same value but different types. Note: this is truthy in C# AND Java. + new object[] { "12", "12.0", "True" }, // Same value but different types. We follow the precedent of C#, Java and C++ and consider these to be equal. + new object[] { "12.0", "12", "True" }, // Likewise new object[] { "12.345", "12.345", "True" }, new object[] { "12.345", "67.890", "False" },