Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 38 additions & 1 deletion Coder.Test/Languages/FloatingRemainderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,20 @@
StringAssert.Contains(code, compoundRemainder, StringComparison.Ordinal);
}

/// <summary>
/// Tests that Go widens an <c>int</c> or <c>float32</c> operand of a <c>float64</c> remainder,
/// and of a <c>float64</c> <c>%=</c>, because <c>math.Mod</c> takes <c>float64</c> alone (#376).
/// </summary>
[TestMethod]
public void Go_MixedOperandsOfADoubleRemainderAreWidened()
{
string code = new GoGenerator().Generate(FileOfMixedRemainders());

StringAssert.Contains(code, "math.Mod(float64(x), d)", StringComparison.Ordinal, code);

Check warning on line 71 in Coder.Test/Languages/FloatingRemainderTests.cs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use 'Assert.Contains' instead of 'StringAssert.Contains'

See more on https://sonarcloud.io/project/issues?id=ktsu-dev_Coder&issues=AaGvKefcrRkUM4lFPxje&open=AaGvKefcrRkUM4lFPxje&pullRequest=458
StringAssert.Contains(code, "r = math.Mod(r, float64(i))", StringComparison.Ordinal, code);

Check warning on line 72 in Coder.Test/Languages/FloatingRemainderTests.cs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use 'Assert.Contains' instead of 'StringAssert.Contains'

See more on https://sonarcloud.io/project/issues?id=ktsu-dev_Coder&issues=AaGvKefcrRkUM4lFPxjf&open=AaGvKefcrRkUM4lFPxjf&pullRequest=458
StringAssert.Contains(code, "math.Mod(float64(i), d)", StringComparison.Ordinal, code);

Check warning on line 73 in Coder.Test/Languages/FloatingRemainderTests.cs

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use 'Assert.Contains' instead of 'StringAssert.Contains'

See more on https://sonarcloud.io/project/issues?id=ktsu-dev_Coder&issues=AaGvKefcrRkUM4lFPxjg&open=AaGvKefcrRkUM4lFPxjg&pullRequest=458
}

/// <summary>
/// Tests that a file taking a floating remainder includes or imports the call's declaration once,
/// and that one taking only integer remainders does not.
Expand Down Expand Up @@ -119,7 +133,7 @@
return;
}

SourceFile[] files = [FileOfRemainders(), FileOfIntegerRemainders(), FileOfAccessorRemainder(), FileOfEntryPointRemainder()];
SourceFile[] files = [FileOfRemainders(), FileOfIntegerRemainders(), FileOfMixedRemainders(), FileOfAccessorRemainder(), FileOfEntryPointRemainder()];
foreach (SourceFile file in files)
{
ToolchainHarness.InTemporaryDirectory(directory =>
Expand Down Expand Up @@ -239,6 +253,29 @@
return file;
}

/// <summary>
/// Builds <c>double rem(float x, double d, int i) { double r = x % d; r %= i; return r + (i % d); }</c>,
/// whose remainders each mix a <c>double</c> with a narrower operand (#376).
/// </summary>
private static SourceFile FileOfMixedRemainders()
{
FunctionDeclaration function = new("rem") { ReturnType = new TypeReference("double") };
function.Parameters.Add(new Parameter("x", "float"));
function.Parameters.Add(new Parameter("d", "double"));
function.Parameters.Add(new Parameter("i", "int"));
function.Body.Add(new VariableDeclaration("r", "double", new BinaryExpression(
new VariableReference("x"), BinaryOperator.Modulo, new VariableReference("d"))));
function.Body.Add(new AssignmentStatement(new VariableReference("r"), new VariableReference("i"), AssignmentOperator.ModuloAssign));
function.Body.Add(new ReturnStatement(new BinaryExpression(
new VariableReference("r"),
BinaryOperator.Add,
new BinaryExpression(new VariableReference("i"), BinaryOperator.Modulo, new VariableReference("d")))));

SourceFile file = new("remainders");
file.Members.Add(function);
return file;
}

private static FunctionDeclaration Remainder(string name, string type)
{
FunctionDeclaration function = new(name) { ReturnType = new TypeReference(type) };
Expand Down
7 changes: 5 additions & 2 deletions Coder/Languages/GoGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -310,10 +310,13 @@ protected override void WriteFloatingRemainder(Expression dividend, Expression d
Ensure.NotNull(code);
if (floatingType == "double")
{
// math.Mod takes float64 alone, and Go converts nothing implicitly, so an int or a
// float32 operand is widened here as the float32 path below widens both (#376).
TypeReference float64 = new("double");
code.Write("math.Mod(");
GenerateInternal(dividend, code);
GenerateWidenedTo(dividend, float64, code);
code.Write(", ");
GenerateInternal(divisor, code);
GenerateWidenedTo(divisor, float64, code);
code.Write(")");
return;
}
Expand Down
Loading