From e250dbcc13c0e76b339dfe27a8ef5e3f268ce817 Mon Sep 17 00:00:00 2001 From: Piotr Fusik Date: Tue, 6 Aug 2024 19:16:20 +0200 Subject: [PATCH] [math] `long` and `float` overloads of Abs, Clamp, Max, Min. #172 --- AST.fu | 28 ++-- GenC.fu | 4 +- GenCl.fu | 14 +- GenCpp.fu | 6 +- GenCs.fu | 6 +- GenD.fu | 6 +- GenJava.fu | 6 +- GenJs.fu | 12 +- GenPy.fu | 6 +- GenSwift.fu | 6 +- Sema.fu | 6 + libfut.cpp | 86 +++++------ libfut.cs | 89 +++++------ libfut.hpp | 10 +- libfut.js | 383 +++++++++++++++++++++++------------------------- test/MathAbs.fu | 2 + 16 files changed, 316 insertions(+), 354 deletions(-) diff --git a/AST.fu b/AST.fu index 8b30d7aa..0baa42d7 100644 --- a/AST.fu +++ b/AST.fu @@ -77,6 +77,7 @@ public enum FuId DoubleType, FloatIntType, FloatingType, + NumericType, BoolType, StringClass, StringPtrType, @@ -223,10 +224,8 @@ public enum FuId MathIsInfinity, MathIsNaN, MathLog2, - MathMaxInt, - MathMaxDouble, - MathMinInt, - MathMinDouble, + MathMax, + MathMin, MathRound, MathTruncate } @@ -1094,7 +1093,7 @@ public class FuType : FuScope } } -abstract class FuNumericType : FuType +class FuNumericType : FuType { } @@ -1828,21 +1827,18 @@ public class FuSystem : FuScope jsonElementClass.Add(FuMethod.New(null, FuVisibility.Public, FuCallType.Normal, BoolType, FuId.JsonElementGetBoolean, "GetBoolean", false)); Add(jsonElementClass); - FuFloatingType# floatIntType = new FuFloatingType { Id = FuId.FloatIntType, Name = "float" }; + FuNumericType# numericType = new FuNumericType { Id = FuId.NumericType, Name = "numeric" }; FuFloatingType# floatingType = new FuFloatingType { Id = FuId.FloatingType, Name = "float" }; + FuFloatingType# floatIntType = new FuFloatingType { Id = FuId.FloatIntType, Name = "float" }; FuClass# mathClass = FuClass.New(FuCallType.Static, FuId.None, "Math"); - mathClass.Add(FuMethodGroup.New( - FuMethod.New(null, FuVisibility.Public, FuCallType.Static, IntType, FuId.MathAbs, "Abs", false, FuVar.New(LongType, "a")), - FuMethod.New(null, FuVisibility.Public, FuCallType.Static, FloatType, FuId.MathAbs, "Abs", false, FuVar.New(DoubleType, "a")))); + mathClass.AddStaticMethod(numericType, FuId.MathAbs, "Abs", FuVar.New(DoubleType, "a")); mathClass.AddStaticMethod(floatingType, FuId.MathMethod, "Acos", FuVar.New(DoubleType, "a")); mathClass.AddStaticMethod(floatingType, FuId.MathMethod, "Asin", FuVar.New(DoubleType, "a")); mathClass.AddStaticMethod(floatingType, FuId.MathMethod, "Atan", FuVar.New(DoubleType, "a")); mathClass.AddStaticMethod(floatingType, FuId.MathMethod, "Atan2", FuVar.New(DoubleType, "y"), FuVar.New(DoubleType, "x")); mathClass.AddStaticMethod(floatingType, FuId.MathMethod, "Cbrt", FuVar.New(DoubleType, "a")); mathClass.AddStaticMethod(floatIntType, FuId.MathCeiling, "Ceiling", FuVar.New(DoubleType, "a")); - mathClass.Add(FuMethodGroup.New( - FuMethod.New(null, FuVisibility.Public, FuCallType.Static, IntType, FuId.MathClamp, "Clamp", false, FuVar.New(LongType, "value"), FuVar.New(LongType, "min"), FuVar.New(LongType, "max")), - FuMethod.New(null, FuVisibility.Public, FuCallType.Static, FloatType, FuId.MathClamp, "Clamp", false, FuVar.New(DoubleType, "value"), FuVar.New(DoubleType, "min"), FuVar.New(DoubleType, "max")))); + mathClass.AddStaticMethod(numericType, FuId.MathClamp, "Clamp", FuVar.New(DoubleType, "value"), FuVar.New(DoubleType, "min"), FuVar.New(DoubleType, "max")); mathClass.AddStaticMethod(floatingType, FuId.MathMethod, "Cos", FuVar.New(DoubleType, "a")); mathClass.AddStaticMethod(floatingType, FuId.MathMethod, "Cosh", FuVar.New(DoubleType, "a")); mathClass.Add(NewConstDouble("E", Math.E)); @@ -1855,12 +1851,8 @@ public class FuSystem : FuScope mathClass.AddStaticMethod(floatingType, FuId.MathMethod, "Log", FuVar.New(DoubleType, "a")); mathClass.AddStaticMethod(floatingType, FuId.MathLog2, "Log2", FuVar.New(DoubleType, "a")); mathClass.AddStaticMethod(floatingType, FuId.MathMethod, "Log10", FuVar.New(DoubleType, "a")); - mathClass.Add(FuMethodGroup.New( - FuMethod.New(null, FuVisibility.Public, FuCallType.Static, IntType, FuId.MathMaxInt, "Max", false, FuVar.New(LongType, "a"), FuVar.New(LongType, "b")), - FuMethod.New(null, FuVisibility.Public, FuCallType.Static, FloatType, FuId.MathMaxDouble, "Max", false, FuVar.New(DoubleType, "a"), FuVar.New(DoubleType, "b")))); - mathClass.Add(FuMethodGroup.New( - FuMethod.New(null, FuVisibility.Public, FuCallType.Static, IntType, FuId.MathMinInt, "Min", false, FuVar.New(LongType, "a"), FuVar.New(LongType, "b")), - FuMethod.New(null, FuVisibility.Public, FuCallType.Static, FloatType, FuId.MathMinDouble, "Min", false, FuVar.New(DoubleType, "a"), FuVar.New(DoubleType, "b")))); + mathClass.AddStaticMethod(numericType, FuId.MathMax, "Max", FuVar.New(DoubleType, "a"), FuVar.New(DoubleType, "b")); + mathClass.AddStaticMethod(numericType, FuId.MathMin, "Min", FuVar.New(DoubleType, "a"), FuVar.New(DoubleType, "b")); mathClass.Add(FuStaticProperty.New(FloatType, FuId.MathNaN, "NaN")); mathClass.Add(FuStaticProperty.New(FloatType, FuId.MathNegativeInfinity, "NegativeInfinity")); mathClass.Add(NewConstDouble("PI", Math.PI)); diff --git a/GenC.fu b/GenC.fu index 542e3ef6..0dd9373f 100644 --- a/GenC.fu +++ b/GenC.fu @@ -2467,10 +2467,10 @@ public class GenC : GenCCpp IncludeMath(); WriteCall("isnan", args[0]); break; - case FuId.MathMaxDouble: + case FuId.MathMax: WriteMathFloating("fmax", args); break; - case FuId.MathMinDouble: + case FuId.MathMin: WriteMathFloating("fmin", args); break; case FuId.MathRound: diff --git a/GenCl.fu b/GenCl.fu index 6dc575c6..2972a85d 100644 --- a/GenCl.fu +++ b/GenCl.fu @@ -247,8 +247,6 @@ public class GenCl : GenC case FuId.MathIsFinite: case FuId.MathIsNaN: case FuId.MathLog2: - case FuId.MathMaxInt: - case FuId.MathMinInt: case FuId.MathRound: WriteLowercase(method.Name); WriteInParentheses(args); @@ -267,11 +265,15 @@ public class GenCl : GenC case FuId.MathIsInfinity: WriteCall("isinf", args[0]); break; - case FuId.MathMaxDouble: - WriteCall("fmax", args[0], args[1]); + case FuId.MathMax: + if (args[0].Type is FuFloatingType || args[1].Type is FuFloatingType) + WriteChar('f'); + WriteCall("max", args[0], args[1]); break; - case FuId.MathMinDouble: - WriteCall("fmin", args[0], args[1]); + case FuId.MathMin: + if (args[0].Type is FuFloatingType || args[1].Type is FuFloatingType) + WriteChar('f'); + WriteCall("min", args[0], args[1]); break; case FuId.MathTruncate: WriteCall("trunc", args[0]); diff --git a/GenCpp.fu b/GenCpp.fu index 0bd93a84..352c1fa6 100644 --- a/GenCpp.fu +++ b/GenCpp.fu @@ -1218,13 +1218,11 @@ public class GenCpp : GenCCpp IncludeMath(); WriteCall("std::isinf", args[0]); break; - case FuId.MathMaxInt: - case FuId.MathMaxDouble: // TODO: fmax ? + case FuId.MathMax: // TODO: fmax ? Include("algorithm"); WriteCall("(std::max)", args[0], args[1]); break; - case FuId.MathMinInt: - case FuId.MathMinDouble: // TODO: fmin ? + case FuId.MathMin: // TODO: fmin ? Include("algorithm"); WriteCall("(std::min)", args[0], args[1]); break; diff --git a/GenCs.fu b/GenCs.fu index b9a7451f..c82a1cab 100644 --- a/GenCs.fu +++ b/GenCs.fu @@ -729,10 +729,8 @@ public class GenCs : GenTyped break; case FuId.MathAbs: case FuId.MathClamp: - case FuId.MathMaxInt: - case FuId.MathMaxDouble: - case FuId.MathMinInt: - case FuId.MathMinDouble: + case FuId.MathMax: + case FuId.MathMin: Include("System"); Write("Math."); Write(method.Name); diff --git a/GenD.fu b/GenD.fu index 430e1f89..9b26cba7 100644 --- a/GenD.fu +++ b/GenD.fu @@ -1173,10 +1173,8 @@ public class GenD : GenCCppD WriteCall("ceil", args[0]); break; case FuId.MathClamp: - case FuId.MathMaxInt: - case FuId.MathMaxDouble: - case FuId.MathMinInt: - case FuId.MathMinDouble: + case FuId.MathMax: + case FuId.MathMin: Include("std.algorithm"); WriteLowercase(method.Name); WriteInParentheses(args); diff --git a/GenJava.fu b/GenJava.fu index 4b8dd231..bd39cbd1 100644 --- a/GenJava.fu +++ b/GenJava.fu @@ -628,10 +628,8 @@ public class GenJava : GenTyped case FuId.StringWriterToString: case FuId.MathMethod: case FuId.MathAbs: - case FuId.MathMaxInt: - case FuId.MathMaxDouble: - case FuId.MathMinInt: - case FuId.MathMinDouble: + case FuId.MathMax: + case FuId.MathMin: if (obj != null) { if (IsReferenceTo(obj, FuId.BasePtr)) Write("super"); diff --git a/GenJs.fu b/GenJs.fu index d28873e1..62f96317 100644 --- a/GenJs.fu +++ b/GenJs.fu @@ -520,7 +520,7 @@ public class GenJsNoModule : GenBase Write("((x, y) => x "); WriteChar(op); Write(" y ? x : y)"); - WriteCoercedArgsInParentheses(method, args); + WriteInParentheses(args); } else WriteCall(name, args[0], args[1]); @@ -548,8 +548,6 @@ public class GenJsNoModule : GenBase case FuId.StringWriterToString: case FuId.MathMethod: case FuId.MathLog2: - case FuId.MathMaxDouble: - case FuId.MathMinDouble: case FuId.MathRound: if (obj == null) WriteLocalName(method, FuPriority.Primary); @@ -900,9 +898,9 @@ public class GenJsNoModule : GenBase WriteCall("Math.ceil", args[0]); break; case FuId.MathClamp: - if (method.Type.Id == FuId.IntType && HasLong(args)) { + if (HasLong(args)) { Write("((x, min, max) => x < min ? min : x > max ? max : x)"); - WriteCoercedArgsInParentheses(method, args); + WriteInParentheses(args); } else { Write("Math.min(Math.max("); @@ -933,10 +931,10 @@ public class GenJsNoModule : GenBase if (parent > FuPriority.Equality) WriteChar(')'); break; - case FuId.MathMaxInt: + case FuId.MathMax: WriteMathMaxMin(method, "Math.max", '>', args); break; - case FuId.MathMinInt: + case FuId.MathMin: WriteMathMaxMin(method, "Math.min", '<', args); break; case FuId.MathTruncate: diff --git a/GenPy.fu b/GenPy.fu index 7d53b0fa..68448c19 100644 --- a/GenPy.fu +++ b/GenPy.fu @@ -1137,12 +1137,10 @@ public class GenPy : GenPySwift Include("math"); WriteCall("math.isinf", args[0]); break; - case FuId.MathMaxInt: - case FuId.MathMaxDouble: + case FuId.MathMax: WriteCall("max", args[0], args[1]); break; - case FuId.MathMinInt: - case FuId.MathMinDouble: + case FuId.MathMin: WriteCall("min", args[0], args[1]); break; case FuId.MathRound: diff --git a/GenSwift.fu b/GenSwift.fu index 3df7f49f..184d527f 100644 --- a/GenSwift.fu +++ b/GenSwift.fu @@ -789,10 +789,8 @@ public class GenSwift : GenPySwift WriteInParentheses(args); break; case FuId.MathAbs: - case FuId.MathMaxInt: - case FuId.MathMaxDouble: - case FuId.MathMinInt: - case FuId.MathMinDouble: + case FuId.MathMax: + case FuId.MathMin: WriteCamelCase(method.Name); WriteInParentheses(args); break; diff --git a/Sema.fu b/Sema.fu index 8152fc11..67e75959 100644 --- a/Sema.fu +++ b/Sema.fu @@ -1397,6 +1397,12 @@ public class FuSema FuType# type = method.Type; if (type.Id == FuId.FloatingType) type = arguments.Any(arg => arg.Type.Id == FuId.DoubleType) ? this.Host.Program.System.DoubleType : this.Host.Program.System.FloatType; + else if (type.Id == FuId.NumericType) { + type = arguments.Any(arg => arg.Type.Id == FuId.DoubleType) ? this.Host.Program.System.DoubleType + : arguments.Any(arg => arg.Type.Id == FuId.FloatType) ? this.Host.Program.System.FloatType + : arguments.Any(arg => arg.Type.Id == FuId.LongType) ? this.Host.Program.System.LongType + : this.Host.Program.System.IntType; + } else if (symbol.Left != null && symbol.Left.Type is FuClassType generic) type = EvalType(generic, type); expr.Type = type; diff --git a/libfut.cpp b/libfut.cpp index 005d72f7..b9713a9e 100644 --- a/libfut.cpp +++ b/libfut.cpp @@ -2908,21 +2908,24 @@ FuSystem::FuSystem() jsonElementClass->add(FuMethod::new_(nullptr, FuVisibility::public_, FuCallType::normal, this->doubleType, FuId::jsonElementGetDouble, "GetDouble", false)); jsonElementClass->add(FuMethod::new_(nullptr, FuVisibility::public_, FuCallType::normal, this->boolType, FuId::jsonElementGetBoolean, "GetBoolean", false)); add(jsonElementClass); - std::shared_ptr floatIntType = std::make_shared(); - floatIntType->id = FuId::floatIntType; - floatIntType->name = "float"; + std::shared_ptr numericType = std::make_shared(); + numericType->id = FuId::numericType; + numericType->name = "numeric"; std::shared_ptr floatingType = std::make_shared(); floatingType->id = FuId::floatingType; floatingType->name = "float"; + std::shared_ptr floatIntType = std::make_shared(); + floatIntType->id = FuId::floatIntType; + floatIntType->name = "float"; std::shared_ptr mathClass = FuClass::new_(FuCallType::static_, FuId::none, "Math"); - mathClass->add(FuMethodGroup::new_(FuMethod::new_(nullptr, FuVisibility::public_, FuCallType::static_, this->intType, FuId::mathAbs, "Abs", false, FuVar::new_(this->longType, "a")), FuMethod::new_(nullptr, FuVisibility::public_, FuCallType::static_, this->floatType, FuId::mathAbs, "Abs", false, FuVar::new_(this->doubleType, "a")))); + mathClass->addStaticMethod(numericType, FuId::mathAbs, "Abs", FuVar::new_(this->doubleType, "a")); mathClass->addStaticMethod(floatingType, FuId::mathMethod, "Acos", FuVar::new_(this->doubleType, "a")); mathClass->addStaticMethod(floatingType, FuId::mathMethod, "Asin", FuVar::new_(this->doubleType, "a")); mathClass->addStaticMethod(floatingType, FuId::mathMethod, "Atan", FuVar::new_(this->doubleType, "a")); mathClass->addStaticMethod(floatingType, FuId::mathMethod, "Atan2", FuVar::new_(this->doubleType, "y"), FuVar::new_(this->doubleType, "x")); mathClass->addStaticMethod(floatingType, FuId::mathMethod, "Cbrt", FuVar::new_(this->doubleType, "a")); mathClass->addStaticMethod(floatIntType, FuId::mathCeiling, "Ceiling", FuVar::new_(this->doubleType, "a")); - mathClass->add(FuMethodGroup::new_(FuMethod::new_(nullptr, FuVisibility::public_, FuCallType::static_, this->intType, FuId::mathClamp, "Clamp", false, FuVar::new_(this->longType, "value"), FuVar::new_(this->longType, "min"), FuVar::new_(this->longType, "max")), FuMethod::new_(nullptr, FuVisibility::public_, FuCallType::static_, this->floatType, FuId::mathClamp, "Clamp", false, FuVar::new_(this->doubleType, "value"), FuVar::new_(this->doubleType, "min"), FuVar::new_(this->doubleType, "max")))); + mathClass->addStaticMethod(numericType, FuId::mathClamp, "Clamp", FuVar::new_(this->doubleType, "value"), FuVar::new_(this->doubleType, "min"), FuVar::new_(this->doubleType, "max")); mathClass->addStaticMethod(floatingType, FuId::mathMethod, "Cos", FuVar::new_(this->doubleType, "a")); mathClass->addStaticMethod(floatingType, FuId::mathMethod, "Cosh", FuVar::new_(this->doubleType, "a")); mathClass->add(newConstDouble("E", 2.718281828459045)); @@ -2935,8 +2938,8 @@ FuSystem::FuSystem() mathClass->addStaticMethod(floatingType, FuId::mathMethod, "Log", FuVar::new_(this->doubleType, "a")); mathClass->addStaticMethod(floatingType, FuId::mathLog2, "Log2", FuVar::new_(this->doubleType, "a")); mathClass->addStaticMethod(floatingType, FuId::mathMethod, "Log10", FuVar::new_(this->doubleType, "a")); - mathClass->add(FuMethodGroup::new_(FuMethod::new_(nullptr, FuVisibility::public_, FuCallType::static_, this->intType, FuId::mathMaxInt, "Max", false, FuVar::new_(this->longType, "a"), FuVar::new_(this->longType, "b")), FuMethod::new_(nullptr, FuVisibility::public_, FuCallType::static_, this->floatType, FuId::mathMaxDouble, "Max", false, FuVar::new_(this->doubleType, "a"), FuVar::new_(this->doubleType, "b")))); - mathClass->add(FuMethodGroup::new_(FuMethod::new_(nullptr, FuVisibility::public_, FuCallType::static_, this->intType, FuId::mathMinInt, "Min", false, FuVar::new_(this->longType, "a"), FuVar::new_(this->longType, "b")), FuMethod::new_(nullptr, FuVisibility::public_, FuCallType::static_, this->floatType, FuId::mathMinDouble, "Min", false, FuVar::new_(this->doubleType, "a"), FuVar::new_(this->doubleType, "b")))); + mathClass->addStaticMethod(numericType, FuId::mathMax, "Max", FuVar::new_(this->doubleType, "a"), FuVar::new_(this->doubleType, "b")); + mathClass->addStaticMethod(numericType, FuId::mathMin, "Min", FuVar::new_(this->doubleType, "a"), FuVar::new_(this->doubleType, "b")); mathClass->add(FuStaticProperty::new_(this->floatType, FuId::mathNaN, "NaN")); mathClass->add(FuStaticProperty::new_(this->floatType, FuId::mathNegativeInfinity, "NegativeInfinity")); mathClass->add(newConstDouble("PI", 3.141592653589793)); @@ -5926,6 +5929,9 @@ std::shared_ptr FuSema::resolveCallWithArguments(std::shared_ptr type = method->type; if (type->id == FuId::floatingType) type = std::any_of(arguments->begin(), arguments->end(), [](const std::shared_ptr &arg) { return arg->type->id == FuId::doubleType; }) ? this->host->program->system->doubleType : this->host->program->system->floatType; + else if (type->id == FuId::numericType) { + type = std::any_of(arguments->begin(), arguments->end(), [](const std::shared_ptr &arg) { return arg->type->id == FuId::doubleType; }) ? this->host->program->system->doubleType : std::any_of(arguments->begin(), arguments->end(), [](const std::shared_ptr &arg) { return arg->type->id == FuId::floatType; }) ? std::static_pointer_cast(this->host->program->system->floatType) : std::static_pointer_cast(std::any_of(arguments->begin(), arguments->end(), [](const std::shared_ptr &arg) { return arg->type->id == FuId::longType; }) ? this->host->program->system->longType : this->host->program->system->intType); + } else { const FuClassType * generic; if (symbol->left != nullptr && (generic = dynamic_cast(symbol->left->type.get()))) @@ -11900,10 +11906,10 @@ void GenC::writeCallExpr(const FuExpr * obj, const FuMethod * method, const std: includeMath(); writeCall("isnan", (*args)[0].get()); break; - case FuId::mathMaxDouble: + case FuId::mathMax: writeMathFloating("fmax", args); break; - case FuId::mathMinDouble: + case FuId::mathMin: writeMathFloating("fmin", args); break; case FuId::mathRound: @@ -13496,8 +13502,6 @@ void GenCl::writeCallExpr(const FuExpr * obj, const FuMethod * method, const std case FuId::mathIsFinite: case FuId::mathIsNaN: case FuId::mathLog2: - case FuId::mathMaxInt: - case FuId::mathMinInt: case FuId::mathRound: writeLowercase(method->name); writeInParentheses(args); @@ -13516,11 +13520,15 @@ void GenCl::writeCallExpr(const FuExpr * obj, const FuMethod * method, const std case FuId::mathIsInfinity: writeCall("isinf", (*args)[0].get()); break; - case FuId::mathMaxDouble: - writeCall("fmax", (*args)[0].get(), (*args)[1].get()); + case FuId::mathMax: + if (dynamic_cast((*args)[0]->type.get()) || dynamic_cast((*args)[1]->type.get())) + writeChar('f'); + writeCall("max", (*args)[0].get(), (*args)[1].get()); break; - case FuId::mathMinDouble: - writeCall("fmin", (*args)[0].get(), (*args)[1].get()); + case FuId::mathMin: + if (dynamic_cast((*args)[0]->type.get()) || dynamic_cast((*args)[1]->type.get())) + writeChar('f'); + writeCall("min", (*args)[0].get(), (*args)[1].get()); break; case FuId::mathTruncate: writeCall("trunc", (*args)[0].get()); @@ -14718,13 +14726,11 @@ void GenCpp::writeCallExpr(const FuExpr * obj, const FuMethod * method, const st includeMath(); writeCall("std::isinf", (*args)[0].get()); break; - case FuId::mathMaxInt: - case FuId::mathMaxDouble: + case FuId::mathMax: include("algorithm"); writeCall("(std::max)", (*args)[0].get(), (*args)[1].get()); break; - case FuId::mathMinInt: - case FuId::mathMinDouble: + case FuId::mathMin: include("algorithm"); writeCall("(std::min)", (*args)[0].get(), (*args)[1].get()); break; @@ -16256,10 +16262,8 @@ void GenCs::writeCallExpr(const FuExpr * obj, const FuMethod * method, const std break; case FuId::mathAbs: case FuId::mathClamp: - case FuId::mathMaxInt: - case FuId::mathMaxDouble: - case FuId::mathMinInt: - case FuId::mathMinDouble: + case FuId::mathMax: + case FuId::mathMin: include("System"); write("Math."); write(method->name); @@ -17536,10 +17540,8 @@ void GenD::writeCallExpr(const FuExpr * obj, const FuMethod * method, const std: writeCall("ceil", (*args)[0].get()); break; case FuId::mathClamp: - case FuId::mathMaxInt: - case FuId::mathMaxDouble: - case FuId::mathMinInt: - case FuId::mathMinDouble: + case FuId::mathMax: + case FuId::mathMin: include("std.algorithm"); writeLowercase(method->name); writeInParentheses(args); @@ -18527,10 +18529,8 @@ void GenJava::writeCallExpr(const FuExpr * obj, const FuMethod * method, const s case FuId::stringWriterToString: case FuId::mathMethod: case FuId::mathAbs: - case FuId::mathMaxInt: - case FuId::mathMaxDouble: - case FuId::mathMinInt: - case FuId::mathMinDouble: + case FuId::mathMax: + case FuId::mathMin: if (obj != nullptr) { if (isReferenceTo(obj, FuId::basePtr)) write("super"); @@ -19847,7 +19847,7 @@ void GenJsNoModule::writeMathMaxMin(const FuMethod * method, std::string_view na write("((x, y) => x "); writeChar(op); write(" y ? x : y)"); - writeCoercedArgsInParentheses(method, args); + writeInParentheses(args); } else writeCall(name, (*args)[0].get(), (*args)[1].get()); @@ -19875,8 +19875,6 @@ void GenJsNoModule::writeCallExpr(const FuExpr * obj, const FuMethod * method, c case FuId::stringWriterToString: case FuId::mathMethod: case FuId::mathLog2: - case FuId::mathMaxDouble: - case FuId::mathMinDouble: case FuId::mathRound: if (obj == nullptr) writeLocalName(method, FuPriority::primary); @@ -20229,9 +20227,9 @@ void GenJsNoModule::writeCallExpr(const FuExpr * obj, const FuMethod * method, c writeCall("Math.ceil", (*args)[0].get()); break; case FuId::mathClamp: - if (method->type->id == FuId::intType && hasLong(args)) { + if (hasLong(args)) { write("((x, min, max) => x < min ? min : x > max ? max : x)"); - writeCoercedArgsInParentheses(method, args); + writeInParentheses(args); } else { write("Math.min(Math.max("); @@ -20262,10 +20260,10 @@ void GenJsNoModule::writeCallExpr(const FuExpr * obj, const FuMethod * method, c if (parent > FuPriority::equality) writeChar(')'); break; - case FuId::mathMaxInt: + case FuId::mathMax: writeMathMaxMin(method, "Math.max", '>', args); break; - case FuId::mathMinInt: + case FuId::mathMin: writeMathMaxMin(method, "Math.min", '<', args); break; case FuId::mathTruncate: @@ -22105,10 +22103,8 @@ void GenSwift::writeCallExpr(const FuExpr * obj, const FuMethod * method, const writeInParentheses(args); break; case FuId::mathAbs: - case FuId::mathMaxInt: - case FuId::mathMaxDouble: - case FuId::mathMinInt: - case FuId::mathMinDouble: + case FuId::mathMax: + case FuId::mathMin: writeCamelCase(method->name); writeInParentheses(args); break; @@ -24225,12 +24221,10 @@ void GenPy::writeCallExpr(const FuExpr * obj, const FuMethod * method, const std include("math"); writeCall("math.isinf", (*args)[0].get()); break; - case FuId::mathMaxInt: - case FuId::mathMaxDouble: + case FuId::mathMax: writeCall("max", (*args)[0].get(), (*args)[1].get()); break; - case FuId::mathMinInt: - case FuId::mathMinDouble: + case FuId::mathMin: writeCall("min", (*args)[0].get(), (*args)[1].get()); break; case FuId::mathRound: diff --git a/libfut.cs b/libfut.cs index 20ddea4c..4d63c0bc 100644 --- a/libfut.cs +++ b/libfut.cs @@ -1319,6 +1319,7 @@ public enum FuId DoubleType, FloatIntType, FloatingType, + NumericType, BoolType, StringClass, StringPtrType, @@ -1465,10 +1466,8 @@ public enum FuId MathIsInfinity, MathIsNaN, MathLog2, - MathMaxInt, - MathMaxDouble, - MathMinInt, - MathMinDouble, + MathMax, + MathMin, MathRound, MathTruncate } @@ -2652,7 +2651,7 @@ public FuClassType AsClassType() } } - abstract class FuNumericType : FuType + class FuNumericType : FuType { } @@ -3360,17 +3359,18 @@ internal FuSystem() jsonElementClass.Add(FuMethod.New(null, FuVisibility.Public, FuCallType.Normal, this.DoubleType, FuId.JsonElementGetDouble, "GetDouble", false)); jsonElementClass.Add(FuMethod.New(null, FuVisibility.Public, FuCallType.Normal, this.BoolType, FuId.JsonElementGetBoolean, "GetBoolean", false)); Add(jsonElementClass); - FuFloatingType floatIntType = new FuFloatingType { Id = FuId.FloatIntType, Name = "float" }; + FuNumericType numericType = new FuNumericType { Id = FuId.NumericType, Name = "numeric" }; FuFloatingType floatingType = new FuFloatingType { Id = FuId.FloatingType, Name = "float" }; + FuFloatingType floatIntType = new FuFloatingType { Id = FuId.FloatIntType, Name = "float" }; FuClass mathClass = FuClass.New(FuCallType.Static, FuId.None, "Math"); - mathClass.Add(FuMethodGroup.New(FuMethod.New(null, FuVisibility.Public, FuCallType.Static, this.IntType, FuId.MathAbs, "Abs", false, FuVar.New(this.LongType, "a")), FuMethod.New(null, FuVisibility.Public, FuCallType.Static, this.FloatType, FuId.MathAbs, "Abs", false, FuVar.New(this.DoubleType, "a")))); + mathClass.AddStaticMethod(numericType, FuId.MathAbs, "Abs", FuVar.New(this.DoubleType, "a")); mathClass.AddStaticMethod(floatingType, FuId.MathMethod, "Acos", FuVar.New(this.DoubleType, "a")); mathClass.AddStaticMethod(floatingType, FuId.MathMethod, "Asin", FuVar.New(this.DoubleType, "a")); mathClass.AddStaticMethod(floatingType, FuId.MathMethod, "Atan", FuVar.New(this.DoubleType, "a")); mathClass.AddStaticMethod(floatingType, FuId.MathMethod, "Atan2", FuVar.New(this.DoubleType, "y"), FuVar.New(this.DoubleType, "x")); mathClass.AddStaticMethod(floatingType, FuId.MathMethod, "Cbrt", FuVar.New(this.DoubleType, "a")); mathClass.AddStaticMethod(floatIntType, FuId.MathCeiling, "Ceiling", FuVar.New(this.DoubleType, "a")); - mathClass.Add(FuMethodGroup.New(FuMethod.New(null, FuVisibility.Public, FuCallType.Static, this.IntType, FuId.MathClamp, "Clamp", false, FuVar.New(this.LongType, "value"), FuVar.New(this.LongType, "min"), FuVar.New(this.LongType, "max")), FuMethod.New(null, FuVisibility.Public, FuCallType.Static, this.FloatType, FuId.MathClamp, "Clamp", false, FuVar.New(this.DoubleType, "value"), FuVar.New(this.DoubleType, "min"), FuVar.New(this.DoubleType, "max")))); + mathClass.AddStaticMethod(numericType, FuId.MathClamp, "Clamp", FuVar.New(this.DoubleType, "value"), FuVar.New(this.DoubleType, "min"), FuVar.New(this.DoubleType, "max")); mathClass.AddStaticMethod(floatingType, FuId.MathMethod, "Cos", FuVar.New(this.DoubleType, "a")); mathClass.AddStaticMethod(floatingType, FuId.MathMethod, "Cosh", FuVar.New(this.DoubleType, "a")); mathClass.Add(NewConstDouble("E", 2.718281828459045)); @@ -3383,8 +3383,8 @@ internal FuSystem() mathClass.AddStaticMethod(floatingType, FuId.MathMethod, "Log", FuVar.New(this.DoubleType, "a")); mathClass.AddStaticMethod(floatingType, FuId.MathLog2, "Log2", FuVar.New(this.DoubleType, "a")); mathClass.AddStaticMethod(floatingType, FuId.MathMethod, "Log10", FuVar.New(this.DoubleType, "a")); - mathClass.Add(FuMethodGroup.New(FuMethod.New(null, FuVisibility.Public, FuCallType.Static, this.IntType, FuId.MathMaxInt, "Max", false, FuVar.New(this.LongType, "a"), FuVar.New(this.LongType, "b")), FuMethod.New(null, FuVisibility.Public, FuCallType.Static, this.FloatType, FuId.MathMaxDouble, "Max", false, FuVar.New(this.DoubleType, "a"), FuVar.New(this.DoubleType, "b")))); - mathClass.Add(FuMethodGroup.New(FuMethod.New(null, FuVisibility.Public, FuCallType.Static, this.IntType, FuId.MathMinInt, "Min", false, FuVar.New(this.LongType, "a"), FuVar.New(this.LongType, "b")), FuMethod.New(null, FuVisibility.Public, FuCallType.Static, this.FloatType, FuId.MathMinDouble, "Min", false, FuVar.New(this.DoubleType, "a"), FuVar.New(this.DoubleType, "b")))); + mathClass.AddStaticMethod(numericType, FuId.MathMax, "Max", FuVar.New(this.DoubleType, "a"), FuVar.New(this.DoubleType, "b")); + mathClass.AddStaticMethod(numericType, FuId.MathMin, "Min", FuVar.New(this.DoubleType, "a"), FuVar.New(this.DoubleType, "b")); mathClass.Add(FuStaticProperty.New(this.FloatType, FuId.MathNaN, "NaN")); mathClass.Add(FuStaticProperty.New(this.FloatType, FuId.MathNegativeInfinity, "NegativeInfinity")); mathClass.Add(NewConstDouble("PI", 3.141592653589793)); @@ -6034,6 +6034,9 @@ FuExpr ResolveCallWithArguments(FuCallExpr expr, List arguments) FuType type = method.Type; if (type.Id == FuId.FloatingType) type = arguments.Exists(arg => arg.Type.Id == FuId.DoubleType) ? this.Host.Program.System.DoubleType : this.Host.Program.System.FloatType; + else if (type.Id == FuId.NumericType) { + type = arguments.Exists(arg => arg.Type.Id == FuId.DoubleType) ? this.Host.Program.System.DoubleType : arguments.Exists(arg => arg.Type.Id == FuId.FloatType) ? this.Host.Program.System.FloatType : arguments.Exists(arg => arg.Type.Id == FuId.LongType) ? this.Host.Program.System.LongType : this.Host.Program.System.IntType; + } else if (symbol.Left != null && symbol.Left.Type is FuClassType generic) type = EvalType(generic, type); expr.Type = type; @@ -12133,10 +12136,10 @@ protected override void WriteCallExpr(FuExpr obj, FuMethod method, List IncludeMath(); WriteCall("isnan", args[0]); break; - case FuId.MathMaxDouble: + case FuId.MathMax: WriteMathFloating("fmax", args); break; - case FuId.MathMinDouble: + case FuId.MathMin: WriteMathFloating("fmin", args); break; case FuId.MathRound: @@ -13737,8 +13740,6 @@ protected override void WriteCallExpr(FuExpr obj, FuMethod method, List case FuId.MathIsFinite: case FuId.MathIsNaN: case FuId.MathLog2: - case FuId.MathMaxInt: - case FuId.MathMinInt: case FuId.MathRound: WriteLowercase(method.Name); WriteInParentheses(args); @@ -13757,11 +13758,15 @@ protected override void WriteCallExpr(FuExpr obj, FuMethod method, List case FuId.MathIsInfinity: WriteCall("isinf", args[0]); break; - case FuId.MathMaxDouble: - WriteCall("fmax", args[0], args[1]); + case FuId.MathMax: + if (args[0].Type is FuFloatingType || args[1].Type is FuFloatingType) + WriteChar('f'); + WriteCall("max", args[0], args[1]); break; - case FuId.MathMinDouble: - WriteCall("fmin", args[0], args[1]); + case FuId.MathMin: + if (args[0].Type is FuFloatingType || args[1].Type is FuFloatingType) + WriteChar('f'); + WriteCall("min", args[0], args[1]); break; case FuId.MathTruncate: WriteCall("trunc", args[0]); @@ -15057,13 +15062,11 @@ protected override void WriteCallExpr(FuExpr obj, FuMethod method, List IncludeMath(); WriteCall("std::isinf", args[0]); break; - case FuId.MathMaxInt: - case FuId.MathMaxDouble: + case FuId.MathMax: Include("algorithm"); WriteCall("(std::max)", args[0], args[1]); break; - case FuId.MathMinInt: - case FuId.MathMinDouble: + case FuId.MathMin: Include("algorithm"); WriteCall("(std::min)", args[0], args[1]); break; @@ -16630,10 +16633,8 @@ protected override void WriteCallExpr(FuExpr obj, FuMethod method, List break; case FuId.MathAbs: case FuId.MathClamp: - case FuId.MathMaxInt: - case FuId.MathMaxDouble: - case FuId.MathMinInt: - case FuId.MathMinDouble: + case FuId.MathMax: + case FuId.MathMin: Include("System"); Write("Math."); Write(method.Name); @@ -18090,10 +18091,8 @@ protected override void WriteCallExpr(FuExpr obj, FuMethod method, List WriteCall("ceil", args[0]); break; case FuId.MathClamp: - case FuId.MathMaxInt: - case FuId.MathMaxDouble: - case FuId.MathMinInt: - case FuId.MathMinDouble: + case FuId.MathMax: + case FuId.MathMin: Include("std.algorithm"); WriteLowercase(method.Name); WriteInParentheses(args); @@ -19140,10 +19139,8 @@ protected override void WriteCallExpr(FuExpr obj, FuMethod method, List case FuId.StringWriterToString: case FuId.MathMethod: case FuId.MathAbs: - case FuId.MathMaxInt: - case FuId.MathMaxDouble: - case FuId.MathMinInt: - case FuId.MathMinDouble: + case FuId.MathMax: + case FuId.MathMin: if (obj != null) { if (IsReferenceTo(obj, FuId.BasePtr)) Write("super"); @@ -20469,7 +20466,7 @@ void WriteMathMaxMin(FuMethod method, string name, int op, List args) Write("((x, y) => x "); WriteChar(op); Write(" y ? x : y)"); - WriteCoercedArgsInParentheses(method, args); + WriteInParentheses(args); } else WriteCall(name, args[0], args[1]); @@ -20497,8 +20494,6 @@ protected override void WriteCallExpr(FuExpr obj, FuMethod method, List case FuId.StringWriterToString: case FuId.MathMethod: case FuId.MathLog2: - case FuId.MathMaxDouble: - case FuId.MathMinDouble: case FuId.MathRound: if (obj == null) WriteLocalName(method, FuPriority.Primary); @@ -20848,9 +20843,9 @@ protected override void WriteCallExpr(FuExpr obj, FuMethod method, List WriteCall("Math.ceil", args[0]); break; case FuId.MathClamp: - if (method.Type.Id == FuId.IntType && HasLong(args)) { + if (HasLong(args)) { Write("((x, min, max) => x < min ? min : x > max ? max : x)"); - WriteCoercedArgsInParentheses(method, args); + WriteInParentheses(args); } else { Write("Math.min(Math.max("); @@ -20881,10 +20876,10 @@ protected override void WriteCallExpr(FuExpr obj, FuMethod method, List if (parent > FuPriority.Equality) WriteChar(')'); break; - case FuId.MathMaxInt: + case FuId.MathMax: WriteMathMaxMin(method, "Math.max", '>', args); break; - case FuId.MathMinInt: + case FuId.MathMin: WriteMathMaxMin(method, "Math.min", '<', args); break; case FuId.MathTruncate: @@ -22851,10 +22846,8 @@ protected override void WriteCallExpr(FuExpr obj, FuMethod method, List WriteInParentheses(args); break; case FuId.MathAbs: - case FuId.MathMaxInt: - case FuId.MathMaxDouble: - case FuId.MathMinInt: - case FuId.MathMinDouble: + case FuId.MathMax: + case FuId.MathMin: WriteCamelCase(method.Name); WriteInParentheses(args); break; @@ -25065,12 +25058,10 @@ protected override void WriteCallExpr(FuExpr obj, FuMethod method, List Include("math"); WriteCall("math.isinf", args[0]); break; - case FuId.MathMaxInt: - case FuId.MathMaxDouble: + case FuId.MathMax: WriteCall("max", args[0], args[1]); break; - case FuId.MathMinInt: - case FuId.MathMinDouble: + case FuId.MathMin: WriteCall("min", args[0], args[1]); break; case FuId.MathRound: diff --git a/libfut.hpp b/libfut.hpp index 7d09492f..fa67851d 100644 --- a/libfut.hpp +++ b/libfut.hpp @@ -205,6 +205,7 @@ enum class FuId doubleType, floatIntType, floatingType, + numericType, boolType, stringClass, stringPtrType, @@ -351,10 +352,8 @@ enum class FuId mathIsInfinity, mathIsNaN, mathLog2, - mathMaxInt, - mathMaxDouble, - mathMinInt, - mathMinDouble, + mathMax, + mathMin, mathRound, mathTruncate }; @@ -1202,9 +1201,8 @@ class FuType : public FuScope class FuNumericType : public FuType { public: - virtual ~FuNumericType() = default; -protected: FuNumericType() = default; + virtual ~FuNumericType() = default; }; class FuIntegerType : public FuNumericType diff --git a/libfut.js b/libfut.js index 1d72f918..3a0163d1 100644 --- a/libfut.js +++ b/libfut.js @@ -1303,158 +1303,157 @@ export const FuId = { DOUBLE_TYPE : 14, FLOAT_INT_TYPE : 15, FLOATING_TYPE : 16, - BOOL_TYPE : 17, - STRING_CLASS : 18, - STRING_PTR_TYPE : 19, - STRING_STORAGE_TYPE : 20, - MAIN_ARGS_TYPE : 21, - ARRAY_PTR_CLASS : 22, - ARRAY_STORAGE_CLASS : 23, - EXCEPTION_CLASS : 24, - LIST_CLASS : 25, - QUEUE_CLASS : 26, - STACK_CLASS : 27, - HASH_SET_CLASS : 28, - SORTED_SET_CLASS : 29, - DICTIONARY_CLASS : 30, - SORTED_DICTIONARY_CLASS : 31, - ORDERED_DICTIONARY_CLASS : 32, - TEXT_WRITER_CLASS : 33, - STRING_WRITER_CLASS : 34, - REGEX_OPTIONS_ENUM : 35, - REGEX_CLASS : 36, - MATCH_CLASS : 37, - JSON_ELEMENT_CLASS : 38, - LOCK_CLASS : 39, - STRING_LENGTH : 40, - ARRAY_LENGTH : 41, - CONSOLE_ERROR : 42, - MAIN : 43, - CLASS_TO_STRING : 44, - MATCH_START : 45, - MATCH_END : 46, - MATCH_LENGTH : 47, - MATCH_VALUE : 48, - MATH_NA_N : 49, - MATH_NEGATIVE_INFINITY : 50, - MATH_POSITIVE_INFINITY : 51, - ENUM_FROM_INT : 52, - ENUM_HAS_FLAG : 53, - INT_TRY_PARSE : 54, - LONG_TRY_PARSE : 55, - DOUBLE_TRY_PARSE : 56, - STRING_CONTAINS : 57, - STRING_ENDS_WITH : 58, - STRING_INDEX_OF : 59, - STRING_LAST_INDEX_OF : 60, - STRING_REPLACE : 61, - STRING_STARTS_WITH : 62, - STRING_SUBSTRING : 63, - STRING_TO_LOWER : 64, - STRING_TO_UPPER : 65, - ARRAY_BINARY_SEARCH_ALL : 66, - ARRAY_BINARY_SEARCH_PART : 67, - ARRAY_CONTAINS : 68, - ARRAY_COPY_TO : 69, - ARRAY_FILL_ALL : 70, - ARRAY_FILL_PART : 71, - ARRAY_SORT_ALL : 72, - ARRAY_SORT_PART : 73, - LIST_ADD : 74, - LIST_ADD_RANGE : 75, - LIST_ALL : 76, - LIST_ANY : 77, - LIST_CLEAR : 78, - LIST_CONTAINS : 79, - LIST_COPY_TO : 80, - LIST_COUNT : 81, - LIST_INDEX_OF : 82, - LIST_INSERT : 83, - LIST_LAST : 84, - LIST_REMOVE_AT : 85, - LIST_REMOVE_RANGE : 86, - LIST_SORT_ALL : 87, - LIST_SORT_PART : 88, - QUEUE_CLEAR : 89, - QUEUE_COUNT : 90, - QUEUE_DEQUEUE : 91, - QUEUE_ENQUEUE : 92, - QUEUE_PEEK : 93, - STACK_CLEAR : 94, - STACK_COUNT : 95, - STACK_PEEK : 96, - STACK_PUSH : 97, - STACK_POP : 98, - HASH_SET_ADD : 99, - HASH_SET_CLEAR : 100, - HASH_SET_CONTAINS : 101, - HASH_SET_COUNT : 102, - HASH_SET_REMOVE : 103, - SORTED_SET_ADD : 104, - SORTED_SET_CLEAR : 105, - SORTED_SET_CONTAINS : 106, - SORTED_SET_COUNT : 107, - SORTED_SET_REMOVE : 108, - DICTIONARY_ADD : 109, - DICTIONARY_CLEAR : 110, - DICTIONARY_CONTAINS_KEY : 111, - DICTIONARY_COUNT : 112, - DICTIONARY_REMOVE : 113, - SORTED_DICTIONARY_CLEAR : 114, - SORTED_DICTIONARY_CONTAINS_KEY : 115, - SORTED_DICTIONARY_COUNT : 116, - SORTED_DICTIONARY_REMOVE : 117, - ORDERED_DICTIONARY_CLEAR : 118, - ORDERED_DICTIONARY_CONTAINS_KEY : 119, - ORDERED_DICTIONARY_COUNT : 120, - ORDERED_DICTIONARY_REMOVE : 121, - TEXT_WRITER_WRITE : 122, - TEXT_WRITER_WRITE_CHAR : 123, - TEXT_WRITER_WRITE_CODE_POINT : 124, - TEXT_WRITER_WRITE_LINE : 125, - CONSOLE_WRITE : 126, - CONSOLE_WRITE_LINE : 127, - STRING_WRITER_CLEAR : 128, - STRING_WRITER_TO_STRING : 129, - CONVERT_TO_BASE64_STRING : 130, - U_T_F8_GET_BYTE_COUNT : 131, - U_T_F8_GET_BYTES : 132, - U_T_F8_GET_STRING : 133, - ENVIRONMENT_GET_ENVIRONMENT_VARIABLE : 134, - REGEX_COMPILE : 135, - REGEX_ESCAPE : 136, - REGEX_IS_MATCH_STR : 137, - REGEX_IS_MATCH_REGEX : 138, - MATCH_FIND_STR : 139, - MATCH_FIND_REGEX : 140, - MATCH_GET_CAPTURE : 141, - JSON_ELEMENT_PARSE : 142, - JSON_ELEMENT_IS_OBJECT : 143, - JSON_ELEMENT_IS_ARRAY : 144, - JSON_ELEMENT_IS_STRING : 145, - JSON_ELEMENT_IS_NUMBER : 146, - JSON_ELEMENT_IS_BOOLEAN : 147, - JSON_ELEMENT_IS_NULL : 148, - JSON_ELEMENT_GET_OBJECT : 149, - JSON_ELEMENT_GET_ARRAY : 150, - JSON_ELEMENT_GET_STRING : 151, - JSON_ELEMENT_GET_DOUBLE : 152, - JSON_ELEMENT_GET_BOOLEAN : 153, - MATH_METHOD : 154, - MATH_ABS : 155, - MATH_CEILING : 156, - MATH_CLAMP : 157, - MATH_FUSED_MULTIPLY_ADD : 158, - MATH_IS_FINITE : 159, - MATH_IS_INFINITY : 160, - MATH_IS_NA_N : 161, - MATH_LOG2 : 162, - MATH_MAX_INT : 163, - MATH_MAX_DOUBLE : 164, - MATH_MIN_INT : 165, - MATH_MIN_DOUBLE : 166, - MATH_ROUND : 167, - MATH_TRUNCATE : 168 + NUMERIC_TYPE : 17, + BOOL_TYPE : 18, + STRING_CLASS : 19, + STRING_PTR_TYPE : 20, + STRING_STORAGE_TYPE : 21, + MAIN_ARGS_TYPE : 22, + ARRAY_PTR_CLASS : 23, + ARRAY_STORAGE_CLASS : 24, + EXCEPTION_CLASS : 25, + LIST_CLASS : 26, + QUEUE_CLASS : 27, + STACK_CLASS : 28, + HASH_SET_CLASS : 29, + SORTED_SET_CLASS : 30, + DICTIONARY_CLASS : 31, + SORTED_DICTIONARY_CLASS : 32, + ORDERED_DICTIONARY_CLASS : 33, + TEXT_WRITER_CLASS : 34, + STRING_WRITER_CLASS : 35, + REGEX_OPTIONS_ENUM : 36, + REGEX_CLASS : 37, + MATCH_CLASS : 38, + JSON_ELEMENT_CLASS : 39, + LOCK_CLASS : 40, + STRING_LENGTH : 41, + ARRAY_LENGTH : 42, + CONSOLE_ERROR : 43, + MAIN : 44, + CLASS_TO_STRING : 45, + MATCH_START : 46, + MATCH_END : 47, + MATCH_LENGTH : 48, + MATCH_VALUE : 49, + MATH_NA_N : 50, + MATH_NEGATIVE_INFINITY : 51, + MATH_POSITIVE_INFINITY : 52, + ENUM_FROM_INT : 53, + ENUM_HAS_FLAG : 54, + INT_TRY_PARSE : 55, + LONG_TRY_PARSE : 56, + DOUBLE_TRY_PARSE : 57, + STRING_CONTAINS : 58, + STRING_ENDS_WITH : 59, + STRING_INDEX_OF : 60, + STRING_LAST_INDEX_OF : 61, + STRING_REPLACE : 62, + STRING_STARTS_WITH : 63, + STRING_SUBSTRING : 64, + STRING_TO_LOWER : 65, + STRING_TO_UPPER : 66, + ARRAY_BINARY_SEARCH_ALL : 67, + ARRAY_BINARY_SEARCH_PART : 68, + ARRAY_CONTAINS : 69, + ARRAY_COPY_TO : 70, + ARRAY_FILL_ALL : 71, + ARRAY_FILL_PART : 72, + ARRAY_SORT_ALL : 73, + ARRAY_SORT_PART : 74, + LIST_ADD : 75, + LIST_ADD_RANGE : 76, + LIST_ALL : 77, + LIST_ANY : 78, + LIST_CLEAR : 79, + LIST_CONTAINS : 80, + LIST_COPY_TO : 81, + LIST_COUNT : 82, + LIST_INDEX_OF : 83, + LIST_INSERT : 84, + LIST_LAST : 85, + LIST_REMOVE_AT : 86, + LIST_REMOVE_RANGE : 87, + LIST_SORT_ALL : 88, + LIST_SORT_PART : 89, + QUEUE_CLEAR : 90, + QUEUE_COUNT : 91, + QUEUE_DEQUEUE : 92, + QUEUE_ENQUEUE : 93, + QUEUE_PEEK : 94, + STACK_CLEAR : 95, + STACK_COUNT : 96, + STACK_PEEK : 97, + STACK_PUSH : 98, + STACK_POP : 99, + HASH_SET_ADD : 100, + HASH_SET_CLEAR : 101, + HASH_SET_CONTAINS : 102, + HASH_SET_COUNT : 103, + HASH_SET_REMOVE : 104, + SORTED_SET_ADD : 105, + SORTED_SET_CLEAR : 106, + SORTED_SET_CONTAINS : 107, + SORTED_SET_COUNT : 108, + SORTED_SET_REMOVE : 109, + DICTIONARY_ADD : 110, + DICTIONARY_CLEAR : 111, + DICTIONARY_CONTAINS_KEY : 112, + DICTIONARY_COUNT : 113, + DICTIONARY_REMOVE : 114, + SORTED_DICTIONARY_CLEAR : 115, + SORTED_DICTIONARY_CONTAINS_KEY : 116, + SORTED_DICTIONARY_COUNT : 117, + SORTED_DICTIONARY_REMOVE : 118, + ORDERED_DICTIONARY_CLEAR : 119, + ORDERED_DICTIONARY_CONTAINS_KEY : 120, + ORDERED_DICTIONARY_COUNT : 121, + ORDERED_DICTIONARY_REMOVE : 122, + TEXT_WRITER_WRITE : 123, + TEXT_WRITER_WRITE_CHAR : 124, + TEXT_WRITER_WRITE_CODE_POINT : 125, + TEXT_WRITER_WRITE_LINE : 126, + CONSOLE_WRITE : 127, + CONSOLE_WRITE_LINE : 128, + STRING_WRITER_CLEAR : 129, + STRING_WRITER_TO_STRING : 130, + CONVERT_TO_BASE64_STRING : 131, + U_T_F8_GET_BYTE_COUNT : 132, + U_T_F8_GET_BYTES : 133, + U_T_F8_GET_STRING : 134, + ENVIRONMENT_GET_ENVIRONMENT_VARIABLE : 135, + REGEX_COMPILE : 136, + REGEX_ESCAPE : 137, + REGEX_IS_MATCH_STR : 138, + REGEX_IS_MATCH_REGEX : 139, + MATCH_FIND_STR : 140, + MATCH_FIND_REGEX : 141, + MATCH_GET_CAPTURE : 142, + JSON_ELEMENT_PARSE : 143, + JSON_ELEMENT_IS_OBJECT : 144, + JSON_ELEMENT_IS_ARRAY : 145, + JSON_ELEMENT_IS_STRING : 146, + JSON_ELEMENT_IS_NUMBER : 147, + JSON_ELEMENT_IS_BOOLEAN : 148, + JSON_ELEMENT_IS_NULL : 149, + JSON_ELEMENT_GET_OBJECT : 150, + JSON_ELEMENT_GET_ARRAY : 151, + JSON_ELEMENT_GET_STRING : 152, + JSON_ELEMENT_GET_DOUBLE : 153, + JSON_ELEMENT_GET_BOOLEAN : 154, + MATH_METHOD : 155, + MATH_ABS : 156, + MATH_CEILING : 157, + MATH_CLAMP : 158, + MATH_FUSED_MULTIPLY_ADD : 159, + MATH_IS_FINITE : 160, + MATH_IS_INFINITY : 161, + MATH_IS_NA_N : 162, + MATH_LOG2 : 163, + MATH_MAX : 164, + MATH_MIN : 165, + MATH_ROUND : 166, + MATH_TRUNCATE : 167 } export class FuDocInline @@ -3597,17 +3596,18 @@ export class FuSystem extends FuScope jsonElementClass.add(FuMethod.new(null, FuVisibility.PUBLIC, FuCallType.NORMAL, this.doubleType, FuId.JSON_ELEMENT_GET_DOUBLE, "GetDouble", false)); jsonElementClass.add(FuMethod.new(null, FuVisibility.PUBLIC, FuCallType.NORMAL, this.boolType, FuId.JSON_ELEMENT_GET_BOOLEAN, "GetBoolean", false)); this.add(jsonElementClass); - let floatIntType = Object.assign(new FuFloatingType(), { id: FuId.FLOAT_INT_TYPE, name: "float" }); + let numericType = Object.assign(new FuNumericType(), { id: FuId.NUMERIC_TYPE, name: "numeric" }); let floatingType = Object.assign(new FuFloatingType(), { id: FuId.FLOATING_TYPE, name: "float" }); + let floatIntType = Object.assign(new FuFloatingType(), { id: FuId.FLOAT_INT_TYPE, name: "float" }); let mathClass = FuClass.new(FuCallType.STATIC, FuId.NONE, "Math"); - mathClass.add(FuMethodGroup.new(FuMethod.new(null, FuVisibility.PUBLIC, FuCallType.STATIC, this.intType, FuId.MATH_ABS, "Abs", false, FuVar.new(this.longType, "a")), FuMethod.new(null, FuVisibility.PUBLIC, FuCallType.STATIC, this.floatType, FuId.MATH_ABS, "Abs", false, FuVar.new(this.doubleType, "a")))); + mathClass.addStaticMethod(numericType, FuId.MATH_ABS, "Abs", FuVar.new(this.doubleType, "a")); mathClass.addStaticMethod(floatingType, FuId.MATH_METHOD, "Acos", FuVar.new(this.doubleType, "a")); mathClass.addStaticMethod(floatingType, FuId.MATH_METHOD, "Asin", FuVar.new(this.doubleType, "a")); mathClass.addStaticMethod(floatingType, FuId.MATH_METHOD, "Atan", FuVar.new(this.doubleType, "a")); mathClass.addStaticMethod(floatingType, FuId.MATH_METHOD, "Atan2", FuVar.new(this.doubleType, "y"), FuVar.new(this.doubleType, "x")); mathClass.addStaticMethod(floatingType, FuId.MATH_METHOD, "Cbrt", FuVar.new(this.doubleType, "a")); mathClass.addStaticMethod(floatIntType, FuId.MATH_CEILING, "Ceiling", FuVar.new(this.doubleType, "a")); - mathClass.add(FuMethodGroup.new(FuMethod.new(null, FuVisibility.PUBLIC, FuCallType.STATIC, this.intType, FuId.MATH_CLAMP, "Clamp", false, FuVar.new(this.longType, "value"), FuVar.new(this.longType, "min"), FuVar.new(this.longType, "max")), FuMethod.new(null, FuVisibility.PUBLIC, FuCallType.STATIC, this.floatType, FuId.MATH_CLAMP, "Clamp", false, FuVar.new(this.doubleType, "value"), FuVar.new(this.doubleType, "min"), FuVar.new(this.doubleType, "max")))); + mathClass.addStaticMethod(numericType, FuId.MATH_CLAMP, "Clamp", FuVar.new(this.doubleType, "value"), FuVar.new(this.doubleType, "min"), FuVar.new(this.doubleType, "max")); mathClass.addStaticMethod(floatingType, FuId.MATH_METHOD, "Cos", FuVar.new(this.doubleType, "a")); mathClass.addStaticMethod(floatingType, FuId.MATH_METHOD, "Cosh", FuVar.new(this.doubleType, "a")); mathClass.add(this.#newConstDouble("E", 2.718281828459045)); @@ -3620,8 +3620,8 @@ export class FuSystem extends FuScope mathClass.addStaticMethod(floatingType, FuId.MATH_METHOD, "Log", FuVar.new(this.doubleType, "a")); mathClass.addStaticMethod(floatingType, FuId.MATH_LOG2, "Log2", FuVar.new(this.doubleType, "a")); mathClass.addStaticMethod(floatingType, FuId.MATH_METHOD, "Log10", FuVar.new(this.doubleType, "a")); - mathClass.add(FuMethodGroup.new(FuMethod.new(null, FuVisibility.PUBLIC, FuCallType.STATIC, this.intType, FuId.MATH_MAX_INT, "Max", false, FuVar.new(this.longType, "a"), FuVar.new(this.longType, "b")), FuMethod.new(null, FuVisibility.PUBLIC, FuCallType.STATIC, this.floatType, FuId.MATH_MAX_DOUBLE, "Max", false, FuVar.new(this.doubleType, "a"), FuVar.new(this.doubleType, "b")))); - mathClass.add(FuMethodGroup.new(FuMethod.new(null, FuVisibility.PUBLIC, FuCallType.STATIC, this.intType, FuId.MATH_MIN_INT, "Min", false, FuVar.new(this.longType, "a"), FuVar.new(this.longType, "b")), FuMethod.new(null, FuVisibility.PUBLIC, FuCallType.STATIC, this.floatType, FuId.MATH_MIN_DOUBLE, "Min", false, FuVar.new(this.doubleType, "a"), FuVar.new(this.doubleType, "b")))); + mathClass.addStaticMethod(numericType, FuId.MATH_MAX, "Max", FuVar.new(this.doubleType, "a"), FuVar.new(this.doubleType, "b")); + mathClass.addStaticMethod(numericType, FuId.MATH_MIN, "Min", FuVar.new(this.doubleType, "a"), FuVar.new(this.doubleType, "b")); mathClass.add(FuStaticProperty.new(this.floatType, FuId.MATH_NA_N, "NaN")); mathClass.add(FuStaticProperty.new(this.floatType, FuId.MATH_NEGATIVE_INFINITY, "NegativeInfinity")); mathClass.add(this.#newConstDouble("PI", 3.141592653589793)); @@ -6356,6 +6356,9 @@ export class FuSema let type = method.type; if (type.id == FuId.FLOATING_TYPE) type = arguments_.some(arg => arg.type.id == FuId.DOUBLE_TYPE) ? this.#host.program.system.doubleType : this.#host.program.system.floatType; + else if (type.id == FuId.NUMERIC_TYPE) { + type = arguments_.some(arg => arg.type.id == FuId.DOUBLE_TYPE) ? this.#host.program.system.doubleType : arguments_.some(arg => arg.type.id == FuId.FLOAT_TYPE) ? this.#host.program.system.floatType : arguments_.some(arg => arg.type.id == FuId.LONG_TYPE) ? this.#host.program.system.longType : this.#host.program.system.intType; + } else { let generic; if (symbol.left != null && (generic = symbol.left.type) instanceof FuClassType) @@ -12588,10 +12591,10 @@ export class GenC extends GenCCpp this.includeMath(); this.writeCall("isnan", args[0]); break; - case FuId.MATH_MAX_DOUBLE: + case FuId.MATH_MAX: this.#writeMathFloating("fmax", args); break; - case FuId.MATH_MIN_DOUBLE: + case FuId.MATH_MIN: this.#writeMathFloating("fmin", args); break; case FuId.MATH_ROUND: @@ -14217,8 +14220,6 @@ export class GenCl extends GenC case FuId.MATH_IS_FINITE: case FuId.MATH_IS_NA_N: case FuId.MATH_LOG2: - case FuId.MATH_MAX_INT: - case FuId.MATH_MIN_INT: case FuId.MATH_ROUND: this.writeLowercase(method.name); this.writeInParentheses(args); @@ -14237,11 +14238,15 @@ export class GenCl extends GenC case FuId.MATH_IS_INFINITY: this.writeCall("isinf", args[0]); break; - case FuId.MATH_MAX_DOUBLE: - this.writeCall("fmax", args[0], args[1]); + case FuId.MATH_MAX: + if (args[0].type instanceof FuFloatingType || args[1].type instanceof FuFloatingType) + this.writeChar(102); + this.writeCall("max", args[0], args[1]); break; - case FuId.MATH_MIN_DOUBLE: - this.writeCall("fmin", args[0], args[1]); + case FuId.MATH_MIN: + if (args[0].type instanceof FuFloatingType || args[1].type instanceof FuFloatingType) + this.writeChar(102); + this.writeCall("min", args[0], args[1]); break; case FuId.MATH_TRUNCATE: this.writeCall("trunc", args[0]); @@ -15541,13 +15546,11 @@ export class GenCpp extends GenCCpp this.includeMath(); this.writeCall("std::isinf", args[0]); break; - case FuId.MATH_MAX_INT: - case FuId.MATH_MAX_DOUBLE: + case FuId.MATH_MAX: this.include("algorithm"); this.writeCall("(std::max)", args[0], args[1]); break; - case FuId.MATH_MIN_INT: - case FuId.MATH_MIN_DOUBLE: + case FuId.MATH_MIN: this.include("algorithm"); this.writeCall("(std::min)", args[0], args[1]); break; @@ -17146,10 +17149,8 @@ export class GenCs extends GenTyped break; case FuId.MATH_ABS: case FuId.MATH_CLAMP: - case FuId.MATH_MAX_INT: - case FuId.MATH_MAX_DOUBLE: - case FuId.MATH_MIN_INT: - case FuId.MATH_MIN_DOUBLE: + case FuId.MATH_MAX: + case FuId.MATH_MIN: this.include("System"); this.write("Math."); this.write(method.name); @@ -18632,10 +18633,8 @@ export class GenD extends GenCCppD this.writeCall("ceil", args[0]); break; case FuId.MATH_CLAMP: - case FuId.MATH_MAX_INT: - case FuId.MATH_MAX_DOUBLE: - case FuId.MATH_MIN_INT: - case FuId.MATH_MIN_DOUBLE: + case FuId.MATH_MAX: + case FuId.MATH_MIN: this.include("std.algorithm"); this.writeLowercase(method.name); this.writeInParentheses(args); @@ -19712,10 +19711,8 @@ export class GenJava extends GenTyped case FuId.STRING_WRITER_TO_STRING: case FuId.MATH_METHOD: case FuId.MATH_ABS: - case FuId.MATH_MAX_INT: - case FuId.MATH_MAX_DOUBLE: - case FuId.MATH_MIN_INT: - case FuId.MATH_MIN_DOUBLE: + case FuId.MATH_MAX: + case FuId.MATH_MIN: if (obj != null) { if (GenJava.isReferenceTo(obj, FuId.BASE_PTR)) this.write("super"); @@ -21083,7 +21080,7 @@ export class GenJsNoModule extends GenBase this.write("((x, y) => x "); this.writeChar(op); this.write(" y ? x : y)"); - this.writeCoercedArgsInParentheses(method, args); + this.writeInParentheses(args); } else this.writeCall(name, args[0], args[1]); @@ -21111,8 +21108,6 @@ export class GenJsNoModule extends GenBase case FuId.STRING_WRITER_TO_STRING: case FuId.MATH_METHOD: case FuId.MATH_LOG2: - case FuId.MATH_MAX_DOUBLE: - case FuId.MATH_MIN_DOUBLE: case FuId.MATH_ROUND: if (obj == null) this.writeLocalName(method, FuPriority.PRIMARY); @@ -21463,9 +21458,9 @@ export class GenJsNoModule extends GenBase this.writeCall("Math.ceil", args[0]); break; case FuId.MATH_CLAMP: - if (method.type.id == FuId.INT_TYPE && GenJsNoModule.#hasLong(args)) { + if (GenJsNoModule.#hasLong(args)) { this.write("((x, min, max) => x < min ? min : x > max ? max : x)"); - this.writeCoercedArgsInParentheses(method, args); + this.writeInParentheses(args); } else { this.write("Math.min(Math.max("); @@ -21496,10 +21491,10 @@ export class GenJsNoModule extends GenBase if (parent > FuPriority.EQUALITY) this.writeChar(41); break; - case FuId.MATH_MAX_INT: + case FuId.MATH_MAX: this.#writeMathMaxMin(method, "Math.max", 62, args); break; - case FuId.MATH_MIN_INT: + case FuId.MATH_MIN: this.#writeMathMaxMin(method, "Math.min", 60, args); break; case FuId.MATH_TRUNCATE: @@ -23474,10 +23469,8 @@ export class GenSwift extends GenPySwift this.writeInParentheses(args); break; case FuId.MATH_ABS: - case FuId.MATH_MAX_INT: - case FuId.MATH_MAX_DOUBLE: - case FuId.MATH_MIN_INT: - case FuId.MATH_MIN_DOUBLE: + case FuId.MATH_MAX: + case FuId.MATH_MIN: this.writeCamelCase(method.name); this.writeInParentheses(args); break; @@ -25712,12 +25705,10 @@ export class GenPy extends GenPySwift this.include("math"); this.writeCall("math.isinf", args[0]); break; - case FuId.MATH_MAX_INT: - case FuId.MATH_MAX_DOUBLE: + case FuId.MATH_MAX: this.writeCall("max", args[0], args[1]); break; - case FuId.MATH_MIN_INT: - case FuId.MATH_MIN_DOUBLE: + case FuId.MATH_MIN: this.writeCall("min", args[0], args[1]); break; case FuId.MATH_ROUND: diff --git a/test/MathAbs.fu b/test/MathAbs.fu index 49677039..dd8ae471 100644 --- a/test/MathAbs.fu +++ b/test/MathAbs.fu @@ -4,11 +4,13 @@ public static class Test { int i = Math.Abs(-1000); long l = -1000000000; + int j = Math.Abs(l); l *= i; float f = -10.5; f = Math.Abs(f); double d = Math.Abs(-1e200); //FAIL: cl if no double support return i == 1000 + && j == 1000000000 && Math.Abs(l) == -l && f == 10.5 && d == 1e200;