From 9cf59954ba309158dd62baa970f58c1488b41cad Mon Sep 17 00:00:00 2001 From: Piotr Fusik Date: Mon, 13 Jan 2025 20:24:19 +0100 Subject: [PATCH] [cpp] Fix Math.Min/Max/Clamp with different types. --- GenCpp.fu | 27 +++++++++++++++++++++------ libfut.cpp | 27 +++++++++++++++++++++------ libfut.cs | 27 +++++++++++++++++++++------ libfut.hpp | 1 + libfut.js | 27 +++++++++++++++++++++------ test/MathMaxMin.fu | 4 ++-- 6 files changed, 87 insertions(+), 26 deletions(-) diff --git a/GenCpp.fu b/GenCpp.fu index e5dfda00..0904f6ef 100644 --- a/GenCpp.fu +++ b/GenCpp.fu @@ -766,6 +766,24 @@ public class GenCpp : GenCCpp } } + void WriteMathClampMaxMin!(FuType type, string function, List args) + { + Include("algorithm"); + Write(function); + WriteChar('('); + bool first = true; + foreach (FuExpr arg in args) { + if (!first) + Write(", "); + first = false; + if (arg.Type != type) + WriteStaticCast(type, arg); + else + arg.Accept(this, FuPriority.Argument); + } + WriteChar(')'); + } + protected override void WriteCallExpr!(FuType type, FuExpr? obj, FuMethod method, List args, FuPriority parent) { switch (method.Id) { @@ -1224,8 +1242,7 @@ public class GenCpp : GenCCpp WriteCall("std::ceil", args[0]); break; case FuId.MathClamp: - Include("algorithm"); - WriteCall("std::clamp", args[0], args[1], args[2]); + WriteMathClampMaxMin(type, "std::clamp", args); break; case FuId.MathFusedMultiplyAdd: IncludeMath(); @@ -1236,12 +1253,10 @@ public class GenCpp : GenCCpp WriteCall("std::isinf", args[0]); break; case FuId.MathMax: // TODO: fmax ? - Include("algorithm"); - WriteCall("(std::max)", args[0], args[1]); + WriteMathClampMaxMin(type, "(std::max)", args); break; case FuId.MathMin: // TODO: fmin ? - Include("algorithm"); - WriteCall("(std::min)", args[0], args[1]); + WriteMathClampMaxMin(type, "(std::min)", args); break; case FuId.MathTruncate: IncludeMath(); diff --git a/libfut.cpp b/libfut.cpp index ffd45407..764abe7a 100644 --- a/libfut.cpp +++ b/libfut.cpp @@ -14424,6 +14424,24 @@ void GenCpp::writeRegexArgument(const FuExpr * expr) } } +void GenCpp::writeMathClampMaxMin(const FuType * type, std::string_view function, const std::vector> * args) +{ + include("algorithm"); + write(function); + writeChar('('); + bool first = true; + for (const std::shared_ptr &arg : *args) { + if (!first) + write(", "); + first = false; + if (arg->type.get() != type) + writeStaticCast(type, arg.get()); + else + arg->accept(this, FuPriority::argument); + } + writeChar(')'); +} + void GenCpp::writeCallExpr(const FuType * type, const FuExpr * obj, const FuMethod * method, const std::vector> * args, FuPriority parent) { switch (method->id) { @@ -14888,8 +14906,7 @@ void GenCpp::writeCallExpr(const FuType * type, const FuExpr * obj, const FuMeth writeCall("std::ceil", (*args)[0].get()); break; case FuId::mathClamp: - include("algorithm"); - writeCall("std::clamp", (*args)[0].get(), (*args)[1].get(), (*args)[2].get()); + writeMathClampMaxMin(type, "std::clamp", args); break; case FuId::mathFusedMultiplyAdd: includeMath(); @@ -14900,12 +14917,10 @@ void GenCpp::writeCallExpr(const FuType * type, const FuExpr * obj, const FuMeth writeCall("std::isinf", (*args)[0].get()); break; case FuId::mathMax: - include("algorithm"); - writeCall("(std::max)", (*args)[0].get(), (*args)[1].get()); + writeMathClampMaxMin(type, "(std::max)", args); break; case FuId::mathMin: - include("algorithm"); - writeCall("(std::min)", (*args)[0].get(), (*args)[1].get()); + writeMathClampMaxMin(type, "(std::min)", args); break; case FuId::mathTruncate: includeMath(); diff --git a/libfut.cs b/libfut.cs index 3a4baf5f..0e849626 100644 --- a/libfut.cs +++ b/libfut.cs @@ -14769,6 +14769,24 @@ void WriteRegexArgument(FuExpr expr) } } + void WriteMathClampMaxMin(FuType type, string function, List args) + { + Include("algorithm"); + Write(function); + WriteChar('('); + bool first = true; + foreach (FuExpr arg in args) { + if (!first) + Write(", "); + first = false; + if (arg.Type != type) + WriteStaticCast(type, arg); + else + arg.Accept(this, FuPriority.Argument); + } + WriteChar(')'); + } + protected override void WriteCallExpr(FuType type, FuExpr obj, FuMethod method, List args, FuPriority parent) { switch (method.Id) { @@ -15227,8 +15245,7 @@ protected override void WriteCallExpr(FuType type, FuExpr obj, FuMethod method, WriteCall("std::ceil", args[0]); break; case FuId.MathClamp: - Include("algorithm"); - WriteCall("std::clamp", args[0], args[1], args[2]); + WriteMathClampMaxMin(type, "std::clamp", args); break; case FuId.MathFusedMultiplyAdd: IncludeMath(); @@ -15239,12 +15256,10 @@ protected override void WriteCallExpr(FuType type, FuExpr obj, FuMethod method, WriteCall("std::isinf", args[0]); break; case FuId.MathMax: - Include("algorithm"); - WriteCall("(std::max)", args[0], args[1]); + WriteMathClampMaxMin(type, "(std::max)", args); break; case FuId.MathMin: - Include("algorithm"); - WriteCall("(std::min)", args[0], args[1]); + WriteMathClampMaxMin(type, "(std::min)", args); break; case FuId.MathTruncate: IncludeMath(); diff --git a/libfut.hpp b/libfut.hpp index 85f3404c..036b7839 100644 --- a/libfut.hpp +++ b/libfut.hpp @@ -2458,6 +2458,7 @@ class GenCpp : public GenCCpp void writeRegex(const std::vector> * args, int argIndex); void writeWrite(const std::vector> * args, bool newLine); void writeRegexArgument(const FuExpr * expr); + void writeMathClampMaxMin(const FuType * type, std::string_view function, const std::vector> * args); void writeMatchProperty(const FuSymbolReference * expr, std::string_view name); void writeGtRawPtr(const FuExpr * expr); void writeIsVar(const FuExpr * expr, const FuVar * def, FuPriority parent); diff --git a/libfut.js b/libfut.js index bd68c932..5fe1fb00 100644 --- a/libfut.js +++ b/libfut.js @@ -15256,6 +15256,24 @@ export class GenCpp extends GenCCpp } } + #writeMathClampMaxMin(type, function_, args) + { + this.include("algorithm"); + this.write(function_); + this.writeChar(40); + let first = true; + for (const arg of args) { + if (!first) + this.write(", "); + first = false; + if (arg.type != type) + this.writeStaticCast(type, arg); + else + arg.accept(this, FuPriority.ARGUMENT); + } + this.writeChar(41); + } + writeCallExpr(type, obj, method, args, parent) { switch (method.id) { @@ -15716,8 +15734,7 @@ export class GenCpp extends GenCCpp this.writeCall("std::ceil", args[0]); break; case FuId.MATH_CLAMP: - this.include("algorithm"); - this.writeCall("std::clamp", args[0], args[1], args[2]); + this.#writeMathClampMaxMin(type, "std::clamp", args); break; case FuId.MATH_FUSED_MULTIPLY_ADD: this.includeMath(); @@ -15728,12 +15745,10 @@ export class GenCpp extends GenCCpp this.writeCall("std::isinf", args[0]); break; case FuId.MATH_MAX: - this.include("algorithm"); - this.writeCall("(std::max)", args[0], args[1]); + this.#writeMathClampMaxMin(type, "(std::max)", args); break; case FuId.MATH_MIN: - this.include("algorithm"); - this.writeCall("(std::min)", args[0], args[1]); + this.#writeMathClampMaxMin(type, "(std::min)", args); break; case FuId.MATH_TRUNCATE: this.includeMath(); diff --git a/test/MathMaxMin.fu b/test/MathMaxMin.fu index 02cbec27..22905dd6 100644 --- a/test/MathMaxMin.fu +++ b/test/MathMaxMin.fu @@ -5,7 +5,7 @@ public static class Test nint n = 1024; long l = 0x1000000; l *= l; - return Math.Min(-5, 10) == -5 && Math.Max(-5, 10) == 10 && Math.Min(n, -n) == -n && Math.Max(n, -n) == n && Math.Max(l, l) == l //FAIL: cl TODO - && Math.Min(-3.0, 10.5) == -3 && Math.Max(-3.0, 10.5) == 10.5; //FAIL: swift TODO https://github.com/swiftlang/swift/issues/76416 + return Math.Min(-5, 10) == -5 && Math.Max(-5, 10) == 10 && Math.Min(n, -n) == -n && Math.Max(n, -n) == n && Math.Max(l, l) == l && Math.Min(0, l) == 0 //FAIL: cl TODO + && Math.Min(-3, 10.5) == -3 && Math.Max(-3, 10.5) == 10.5; //FAIL: swift TODO https://github.com/swiftlang/swift/issues/76416 } }