diff --git a/src/Evaluator/EvalValues/NumericEvalValue.hpp b/src/Evaluator/EvalValues/NumericEvalValue.hpp index 3d9aaf3..593c5d4 100644 --- a/src/Evaluator/EvalValues/NumericEvalValue.hpp +++ b/src/Evaluator/EvalValues/NumericEvalValue.hpp @@ -68,6 +68,11 @@ namespace Porygon::Evaluation { return _value; } + [[nodiscard]] + inline double EvaluateFloat() const final { + return static_cast(_value); + } + [[nodiscard]] inline std::u16string EvaluateString() const final{ return Utilities::StringUtils::IntToString(_value); @@ -122,6 +127,11 @@ namespace Porygon::Evaluation { return _value; } + [[nodiscard]] + inline long EvaluateInteger() const final { + return static_cast(_value); + } + [[nodiscard]] inline std::u16string EvaluateString() const final{ return Utilities::StringUtils::FloatToString(_value); diff --git a/src/ScriptTypes/FunctionScriptType.hpp b/src/ScriptTypes/FunctionScriptType.hpp index 03afd9b..e1659d0 100644 --- a/src/ScriptTypes/FunctionScriptType.hpp +++ b/src/ScriptTypes/FunctionScriptType.hpp @@ -85,6 +85,12 @@ namespace Porygon { return this; } + const GenericFunctionScriptType* RegisterFunctionOption (size_t index, GenericFunctionOption * opt) const{ + opt->SetOption(index); + _options->push_back(opt); + return this; + } + GenericFunctionOption* GetFunctionOption(const vector>& parameters) const{ for (auto o: *_options){ if (o->IsValid(parameters)){ diff --git a/src/StandardLibraries/MathLibrary.cpp b/src/StandardLibraries/MathLibrary.cpp new file mode 100644 index 0000000..4e6f344 --- /dev/null +++ b/src/StandardLibraries/MathLibrary.cpp @@ -0,0 +1,9 @@ +#include "MathLibrary.hpp" + +namespace Porygon::StandardLibraries{ + using namespace Porygon::Evaluation; + const EvalValue* MathLibrary::_huge = new FloatEvalValue(DBL_MAX); + const EvalValue* MathLibrary::_maxInteger = new IntegerEvalValue(INT64_MAX); + const EvalValue* MathLibrary::_minInteger = new IntegerEvalValue(INT64_MIN); + const EvalValue* MathLibrary::_pi = new FloatEvalValue(M_PI); +} \ No newline at end of file diff --git a/src/StandardLibraries/MathLibrary.hpp b/src/StandardLibraries/MathLibrary.hpp index d195be1..04210e9 100644 --- a/src/StandardLibraries/MathLibrary.hpp +++ b/src/StandardLibraries/MathLibrary.hpp @@ -2,7 +2,8 @@ #define PORYGONLANG_MATHLIBRARY_HPP #include - +#include +#include #include "../Evaluator/EvalValues/EvalValue.hpp" #include "../Evaluator/EvalValues/NumericEvalValue.hpp" @@ -23,6 +24,7 @@ namespace Porygon::StandardLibraries { #define FLOAT_TYPE new NumericScriptType(true, true) #define INTEGER_TYPE new NumericScriptType(true, false) +#define BOOL_TYPE new ScriptType(TypeClass::Bool) #define FUNCTION(fieldName) \ [](void* obj) -> const Porygon::Evaluation::EvalValue* { \ auto t = new Porygon::Evaluation::GenericFunctionEvalValue(make_shared(), \ @@ -41,6 +43,108 @@ namespace Porygon::StandardLibraries { } } + static const EvalValue* _acos(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount) { + auto parameter = dynamic_cast(parameters[0]); + return new FloatEvalValue(std::acos(parameter->EvaluateFloat())); + } + + static const EvalValue* _asin(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount) { + auto parameter = dynamic_cast(parameters[0]); + return new FloatEvalValue(std::asin(parameter->EvaluateFloat())); + } + + static const EvalValue* _atan(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount) { + if (parameterCount == 1){ + auto parameter = dynamic_cast(parameters[0]); + return new FloatEvalValue(std::atan(parameter->EvaluateFloat())); + } + else{ + auto parameter1 = dynamic_cast(parameters[0]); + auto parameter2 = dynamic_cast(parameters[1]); + return new FloatEvalValue(std::atan2(parameter1->EvaluateFloat(), parameter2->EvaluateFloat())); + } + } + static const EvalValue* _ceil(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount) { + auto parameter = dynamic_cast(parameters[0]); + auto f = parameter->EvaluateFloat(); + return new IntegerEvalValue(std::ceil(f)); + } + + static const EvalValue* _cos(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount) { + auto parameter = dynamic_cast(parameters[0]); + auto f = parameter->EvaluateFloat(); + return new FloatEvalValue(std::cos(f)); + } + + static const EvalValue* _deg(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount) { + auto parameter = dynamic_cast(parameters[0]); + auto f = parameter->EvaluateFloat(); + return new FloatEvalValue(f * 180 / M_PI); + } + + static const EvalValue* _exp(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount) { + auto parameter = dynamic_cast(parameters[0]); + auto f = parameter->EvaluateFloat(); + return new FloatEvalValue(std::exp(f)); + } + + static const EvalValue* _floor(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount) { + auto parameter = dynamic_cast(parameters[0]); + auto f = parameter->EvaluateFloat(); + return new IntegerEvalValue(std::floor(f)); + } + + static const EvalValue* _fmod(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount) { + auto f1 = dynamic_cast(parameters[0])->EvaluateFloat(); + auto f2 = dynamic_cast(parameters[0])->EvaluateFloat(); + return new FloatEvalValue(std::fmod(f1, f2)); + } + + static const EvalValue* _huge; + + static const EvalValue* _log(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount){ + if (parameterCount == 1){ + auto f = dynamic_cast(parameters[0])->EvaluateFloat(); + return new FloatEvalValue(std::log(f)); + } + else{ + auto f1 = dynamic_cast(parameters[0])->EvaluateFloat(); + auto f2 = dynamic_cast(parameters[1])->EvaluateFloat(); + return new FloatEvalValue(std::log(f2) / std::log(f1)); + } + } + + static const EvalValue* _maxInteger; + static const EvalValue* _minInteger; + static const EvalValue* _pi; + + static const EvalValue* _rad(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount) { + auto parameter = dynamic_cast(parameters[0]); + auto f = parameter->EvaluateFloat(); + return new FloatEvalValue(M_PI *(f / 180)); + } + + static const EvalValue* _sin(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount) { + auto parameter = dynamic_cast(parameters[0]); + return new FloatEvalValue(std::sin(parameter->EvaluateFloat())); + } + + static const EvalValue* _sqrt(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount) { + auto parameter = dynamic_cast(parameters[0]); + return new FloatEvalValue(std::sqrt(parameter->EvaluateFloat())); + } + + static const EvalValue* _tan(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount) { + auto parameter = dynamic_cast(parameters[0]); + return new FloatEvalValue(std::tan(parameter->EvaluateFloat())); + } + + static const EvalValue* _ult(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount) { + auto parameter1 = dynamic_cast(parameters[0])->EvaluateInteger(); + auto parameter2 = dynamic_cast(parameters[1])->EvaluateInteger(); + return new BooleanEvalValue(parameter1 < parameter2); + } + static UserData::UserDataFunctionOption* CreateFunctionOption(ScriptType* returnType, std::vector params){ return UserData::UserDataFunctionOption::FromRawPointers(returnType, std::move(params)); } @@ -49,13 +153,167 @@ namespace Porygon::StandardLibraries { public: static UserData::UserData* CreateUserData(){ return new UserData::UserData({ - {HashedString::ConstHash("abs"), + { + HashedString::ConstHash("abs"), new UserData::UserDataField( (new GenericFunctionScriptType()) - ->RegisterFunctionOption(CreateFunctionOption(INTEGER_TYPE, {INTEGER_TYPE})) - ->RegisterFunctionOption(CreateFunctionOption(FLOAT_TYPE, {FLOAT_TYPE})) - , FUNCTION(_abs))} - }); + ->RegisterFunctionOption(0, CreateFunctionOption(INTEGER_TYPE, {INTEGER_TYPE})) + ->RegisterFunctionOption(0, CreateFunctionOption(FLOAT_TYPE, {FLOAT_TYPE})) + , FUNCTION(_abs)) + }, + { + HashedString::ConstHash("acos"), + new UserData::UserDataField( + (new GenericFunctionScriptType()) + ->RegisterFunctionOption(0, CreateFunctionOption(FLOAT_TYPE, {INTEGER_TYPE})) + ->RegisterFunctionOption(0, CreateFunctionOption(FLOAT_TYPE, {FLOAT_TYPE})) + , FUNCTION(_acos)) + }, + { + HashedString::ConstHash("asin"), + new UserData::UserDataField( + (new GenericFunctionScriptType()) + ->RegisterFunctionOption(0, CreateFunctionOption(FLOAT_TYPE, {INTEGER_TYPE})) + ->RegisterFunctionOption(0, CreateFunctionOption(FLOAT_TYPE, {FLOAT_TYPE})) + , FUNCTION(_asin)) + }, + { + HashedString::ConstHash("atan"), + new UserData::UserDataField( + (new GenericFunctionScriptType()) + ->RegisterFunctionOption(0, CreateFunctionOption(FLOAT_TYPE, {INTEGER_TYPE})) + ->RegisterFunctionOption(0, CreateFunctionOption(FLOAT_TYPE, {FLOAT_TYPE})) + ->RegisterFunctionOption(0, CreateFunctionOption(FLOAT_TYPE, {INTEGER_TYPE, INTEGER_TYPE})) + ->RegisterFunctionOption(0, CreateFunctionOption(FLOAT_TYPE, {INTEGER_TYPE, FLOAT_TYPE})) + ->RegisterFunctionOption(0, CreateFunctionOption(FLOAT_TYPE, {FLOAT_TYPE, INTEGER_TYPE})) + ->RegisterFunctionOption(0, CreateFunctionOption(FLOAT_TYPE, {FLOAT_TYPE, FLOAT_TYPE})) + , FUNCTION(_atan)) + }, + { + HashedString::ConstHash("ceil"), + new UserData::UserDataField( + (new GenericFunctionScriptType()) + ->RegisterFunctionOption(0, CreateFunctionOption(FLOAT_TYPE, {INTEGER_TYPE})) + , FUNCTION(_ceil)) + }, + { + HashedString::ConstHash("cos"), + new UserData::UserDataField( + (new GenericFunctionScriptType()) + ->RegisterFunctionOption(0, CreateFunctionOption(FLOAT_TYPE, {INTEGER_TYPE})) + ->RegisterFunctionOption(0, CreateFunctionOption(FLOAT_TYPE, {FLOAT_TYPE})) + , FUNCTION(_cos)) + }, + { + HashedString::ConstHash("deg"), + new UserData::UserDataField( + (new GenericFunctionScriptType()) + ->RegisterFunctionOption(0, CreateFunctionOption(FLOAT_TYPE, {INTEGER_TYPE})) + ->RegisterFunctionOption(0, CreateFunctionOption(FLOAT_TYPE, {FLOAT_TYPE})) + , FUNCTION(_deg)) + }, + { + HashedString::ConstHash("exp"), + new UserData::UserDataField( + (new GenericFunctionScriptType()) + ->RegisterFunctionOption(0, CreateFunctionOption(FLOAT_TYPE, {INTEGER_TYPE})) + ->RegisterFunctionOption(0, CreateFunctionOption(FLOAT_TYPE, {FLOAT_TYPE})) + , FUNCTION(_exp)) + }, + { + HashedString::ConstHash("floor"), + new UserData::UserDataField( + (new GenericFunctionScriptType()) + ->RegisterFunctionOption(0, CreateFunctionOption(FLOAT_TYPE, {INTEGER_TYPE})) + , FUNCTION(_floor)) + }, + { + HashedString::ConstHash("fmod"), + new UserData::UserDataField( + (new GenericFunctionScriptType()) + ->RegisterFunctionOption(0, CreateFunctionOption(FLOAT_TYPE, {INTEGER_TYPE, INTEGER_TYPE})) + ->RegisterFunctionOption(0, CreateFunctionOption(FLOAT_TYPE, {FLOAT_TYPE, INTEGER_TYPE})) + ->RegisterFunctionOption(0, CreateFunctionOption(FLOAT_TYPE, {INTEGER_TYPE, FLOAT_TYPE})) + ->RegisterFunctionOption(0, CreateFunctionOption(FLOAT_TYPE, {FLOAT_TYPE, FLOAT_TYPE})) + , FUNCTION(_fmod)) + }, + { + HashedString::ConstHash("huge"), + new UserData::UserDataField( + FLOAT_TYPE + , [](void* obj) -> const Porygon::Evaluation::EvalValue* {return _huge;}, nullptr) + }, + { + HashedString::ConstHash("log"), + new UserData::UserDataField( + (new GenericFunctionScriptType()) + ->RegisterFunctionOption(0, CreateFunctionOption(FLOAT_TYPE, {INTEGER_TYPE})) + ->RegisterFunctionOption(0, CreateFunctionOption(FLOAT_TYPE, {FLOAT_TYPE})) + ->RegisterFunctionOption(0, CreateFunctionOption(FLOAT_TYPE, {INTEGER_TYPE, INTEGER_TYPE})) + ->RegisterFunctionOption(0, CreateFunctionOption(FLOAT_TYPE, {INTEGER_TYPE, FLOAT_TYPE})) + ->RegisterFunctionOption(0, CreateFunctionOption(FLOAT_TYPE, {FLOAT_TYPE, INTEGER_TYPE})) + ->RegisterFunctionOption(0, CreateFunctionOption(FLOAT_TYPE, {FLOAT_TYPE, FLOAT_TYPE})) + , FUNCTION(_log)) + }, + { + HashedString::ConstHash("maxinteger"), + new UserData::UserDataField( + INTEGER_TYPE + , [](void* obj) -> const Porygon::Evaluation::EvalValue* {return _maxInteger;}, nullptr) + }, + { + HashedString::ConstHash("mininteger"), + new UserData::UserDataField( + INTEGER_TYPE + , [](void* obj) -> const Porygon::Evaluation::EvalValue* {return _minInteger;}, nullptr) + }, + { + HashedString::ConstHash("pi"), + new UserData::UserDataField( + FLOAT_TYPE + , [](void* obj) -> const Porygon::Evaluation::EvalValue* {return _pi;}, nullptr) + }, + { + HashedString::ConstHash("rad"), + new UserData::UserDataField( + (new GenericFunctionScriptType()) + ->RegisterFunctionOption(0, CreateFunctionOption(FLOAT_TYPE, {INTEGER_TYPE})) + ->RegisterFunctionOption(0, CreateFunctionOption(FLOAT_TYPE, {FLOAT_TYPE})) + , FUNCTION(_rad)) + }, + { + HashedString::ConstHash("sin"), + new UserData::UserDataField( + (new GenericFunctionScriptType()) + ->RegisterFunctionOption(0, CreateFunctionOption(FLOAT_TYPE, {INTEGER_TYPE})) + ->RegisterFunctionOption(0, CreateFunctionOption(FLOAT_TYPE, {FLOAT_TYPE})) + , FUNCTION(_sin)) + }, + { + HashedString::ConstHash("sqrt"), + new UserData::UserDataField( + (new GenericFunctionScriptType()) + ->RegisterFunctionOption(0, CreateFunctionOption(FLOAT_TYPE, {INTEGER_TYPE})) + ->RegisterFunctionOption(0, CreateFunctionOption(FLOAT_TYPE, {FLOAT_TYPE})) + , FUNCTION(_sqrt)) + }, + { + HashedString::ConstHash("tan"), + new UserData::UserDataField( + (new GenericFunctionScriptType()) + ->RegisterFunctionOption(0, CreateFunctionOption(FLOAT_TYPE, {INTEGER_TYPE})) + ->RegisterFunctionOption(0, CreateFunctionOption(FLOAT_TYPE, {FLOAT_TYPE})) + , FUNCTION(_tan)) + }, + { + HashedString::ConstHash("ult"), + new UserData::UserDataField( + (new GenericFunctionScriptType()) + ->RegisterFunctionOption(0, CreateFunctionOption(BOOL_TYPE, {INTEGER_TYPE, INTEGER_TYPE})) + , FUNCTION(_ult)) + }, + + }); } }; } diff --git a/tests/standardLibraries/MatLibrary.cpp b/tests/standardLibraries/MatLibrary.cpp deleted file mode 100644 index ad73b1f..0000000 --- a/tests/standardLibraries/MatLibrary.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#ifdef TESTS_BUILD -#include -#include "../src/Script.hpp" -#include "../../src/ScriptOptions.hpp" -#include - -using namespace Porygon; - -TEST_CASE( "Abs positive returns positive", "[integration]" ) { - Script* script = Script::Create(u"return math.abs(684)"); - REQUIRE(!script->Diagnostics -> HasErrors()); - auto result = script -> Evaluate(); - CHECK(result->EvaluateInteger() == 684); - delete script; -} - -TEST_CASE( "Abs negative returns positive", "[integration]" ) { - Script* script = Script::Create(u"return math.abs(-684)"); - REQUIRE(!script->Diagnostics -> HasErrors()); - auto result = script -> Evaluate(); - CHECK(result->EvaluateInteger() == 684); - delete script; -} - -#endif - diff --git a/tests/standardLibraries/MathLibrary.cpp b/tests/standardLibraries/MathLibrary.cpp new file mode 100644 index 0000000..335e6be --- /dev/null +++ b/tests/standardLibraries/MathLibrary.cpp @@ -0,0 +1,269 @@ +#ifdef TESTS_BUILD +#include +#include +#include +#include +#include "../src/Script.hpp" +#include "../../src/ScriptOptions.hpp" + +using namespace Porygon; + +TEST_CASE( "Abs positive returns positive", "[integration]" ) { + Script* script = Script::Create(u"return math.abs(684)"); + REQUIRE(!script->Diagnostics -> HasErrors()); + auto result = script -> Evaluate(); + CHECK(result->EvaluateInteger() == 684); + delete script; +} + +TEST_CASE( "Abs negative returns positive", "[integration]" ) { + Script* script = Script::Create(u"return math.abs(-684)"); + REQUIRE(!script->Diagnostics -> HasErrors()); + auto result = script -> Evaluate(); + CHECK(result->EvaluateInteger() == 684); + delete script; +} + +TEST_CASE( "math.acos(1) == 0", "[integration]" ) { + Script* script = Script::Create(u"return math.acos(1)"); + REQUIRE(!script->Diagnostics -> HasErrors()); + auto result = script -> Evaluate(); + CHECK(result->EvaluateFloat() == 0); + delete script; +} + +TEST_CASE( "math.acos(0) == 1.5707963267949", "[integration]" ) { + Script* script = Script::Create(u"return math.acos(0)"); + REQUIRE(!script->Diagnostics -> HasErrors()); + auto result = script -> Evaluate(); + CHECK(result->EvaluateFloat() == Approx(1.5707963267949)); + delete script; +} + +TEST_CASE( "math.asin(0) == 0", "[integration]" ) { + Script* script = Script::Create(u"return math.asin(0)"); + REQUIRE(!script->Diagnostics -> HasErrors()); + auto result = script -> Evaluate(); + CHECK(result->EvaluateFloat() == 0); + delete script; +} + +TEST_CASE( "math.asin(1) == 1.5707963267949", "[integration]" ) { + Script* script = Script::Create(u"return math.asin(1)"); + REQUIRE(!script->Diagnostics -> HasErrors()); + auto result = script -> Evaluate(); + CHECK(result->EvaluateFloat() == Approx(1.5707963267949)); + delete script; +} + +TEST_CASE( "math.atan(1,0) == 1.5707963267949", "[integration]" ) { + Script* script = Script::Create(u"return math.atan(1,0)"); + REQUIRE(!script->Diagnostics -> HasErrors()); + auto result = script -> Evaluate(); + CHECK(result->EvaluateFloat() == Approx(1.5707963267949)); + delete script; +} + +TEST_CASE( "math.atan(-1,0) == -1.5707963267949", "[integration]" ) { + Script* script = Script::Create(u"return math.atan(-1,0)"); + REQUIRE(!script->Diagnostics -> HasErrors()); + auto result = script -> Evaluate(); + CHECK(result->EvaluateFloat() == Approx(-1.5707963267949)); + delete script; +} + +TEST_CASE( "math.atan(0,1) == 0", "[integration]" ) { + Script* script = Script::Create(u"return math.atan(0,1)"); + REQUIRE(!script->Diagnostics -> HasErrors()); + auto result = script -> Evaluate(); + CHECK(result->EvaluateFloat() == Approx(0)); + delete script; +} + +TEST_CASE( "math.atan(0,-1) == 3.1415926535898", "[integration]" ) { + Script* script = Script::Create(u"return math.atan(0,-1)"); + REQUIRE(!script->Diagnostics -> HasErrors()); + auto result = script -> Evaluate(); + CHECK(result->EvaluateFloat() == Approx(3.1415926535898)); + delete script; +} + +TEST_CASE( "math.ceil(0.5) == 1", "[integration]" ) { + Script* script = Script::Create(u"return math.ceil(0.5)"); + REQUIRE(!script->Diagnostics -> HasErrors()); + auto result = script -> Evaluate(); + CHECK(result->EvaluateInteger() == 1); + delete script; +} + +TEST_CASE( "math.ceil(0.1) == 1", "[integration]" ) { + Script* script = Script::Create(u"return math.ceil(0.1)"); + REQUIRE(!script->Diagnostics -> HasErrors()); + auto result = script -> Evaluate(); + CHECK(result->EvaluateInteger() == 1); + delete script; +} + +TEST_CASE( "math.floor(0.5) == 0", "[integration]" ) { + Script* script = Script::Create(u"return math.floor(0.5)"); + REQUIRE(!script->Diagnostics -> HasErrors()); + auto result = script -> Evaluate(); + CHECK(result->EvaluateInteger() == 0); + delete script; +} + +TEST_CASE( "math.floor(0.9) == 0", "[integration]" ) { + Script* script = Script::Create(u"return math.floor(0.9)"); + REQUIRE(!script->Diagnostics -> HasErrors()); + auto result = script -> Evaluate(); + CHECK(result->EvaluateInteger() == 0); + delete script; +} + +TEST_CASE( "math.cos(0.7853981634) == 0.70710678118655", "[integration]" ) { + Script* script = Script::Create(u"return math.cos(0.7853981634)"); + REQUIRE(!script->Diagnostics -> HasErrors()); + auto result = script -> Evaluate(); + CHECK(result->EvaluateFloat() == Approx(0.70710678118655)); + delete script; +} + +TEST_CASE( "math.sin(0.123) == 0.12269009002432", "[integration]" ) { + Script* script = Script::Create(u"return math.sin(0.123)"); + REQUIRE(!script->Diagnostics -> HasErrors()); + auto result = script -> Evaluate(); + CHECK(result->EvaluateFloat() == Approx(0.12269009002432)); + delete script; +} + +TEST_CASE( "math.tan(1.25) == 3.0095696738628", "[integration]" ) { + Script* script = Script::Create(u"return math.tan(1.25)"); + REQUIRE(!script->Diagnostics -> HasErrors()); + auto result = script -> Evaluate(); + CHECK(result->EvaluateFloat() == Approx(3.0095696738628)); + delete script; +} + +TEST_CASE( "math.tan(0.77) == 0.96966832796149", "[integration]" ) { + Script* script = Script::Create(u"return math.tan(0.77)"); + REQUIRE(!script->Diagnostics -> HasErrors()); + auto result = script -> Evaluate(); + CHECK(result->EvaluateFloat() == Approx(0.96966832796149)); + delete script; +} + +TEST_CASE( "math.deg(3.1415926535898) == 180", "[integration]" ) { + Script* script = Script::Create(u"return math.deg(3.1415926535898)"); + REQUIRE(!script->Diagnostics -> HasErrors()); + auto result = script -> Evaluate(); + CHECK(result->EvaluateFloat() == Approx(180)); + delete script; +} + +TEST_CASE( "math.deg(1.5707963267949) == 90", "[integration]" ) { + Script* script = Script::Create(u"return math.deg(1.5707963267949)"); + REQUIRE(!script->Diagnostics -> HasErrors()); + auto result = script -> Evaluate(); + CHECK(result->EvaluateFloat() == Approx(90)); + delete script; +} + +TEST_CASE( "math.rad(180) == 3.1415926535898", "[integration]" ) { + Script* script = Script::Create(u"return math.rad(180)"); + REQUIRE(!script->Diagnostics -> HasErrors()); + auto result = script -> Evaluate(); + CHECK(result->EvaluateFloat() == Approx(3.1415926535898)); + delete script; +} + +TEST_CASE( "math.rad(1) == 0.017453292519943", "[integration]" ) { + Script* script = Script::Create(u"return math.rad(1)"); + REQUIRE(!script->Diagnostics -> HasErrors()); + auto result = script -> Evaluate(); + CHECK(result->EvaluateFloat() == Approx(0.017453292519943)); + delete script; +} + +TEST_CASE( "math.exp(0) == 1", "[integration]" ) { + Script* script = Script::Create(u"return math.exp(0)"); + REQUIRE(!script->Diagnostics -> HasErrors()); + auto result = script -> Evaluate(); + CHECK(result->EvaluateFloat() == Approx(1)); + delete script; +} + +TEST_CASE( "math.exp(1) == 2.718281828459", "[integration]" ) { + Script* script = Script::Create(u"return math.exp(1)"); + REQUIRE(!script->Diagnostics -> HasErrors()); + auto result = script -> Evaluate(); + CHECK(result->EvaluateFloat() == Approx(2.718281828459)); + delete script; +} + +TEST_CASE( "math.exp(27) == 532048240601.8", "[integration]" ) { + Script* script = Script::Create(u"return math.exp(27)"); + REQUIRE(!script->Diagnostics -> HasErrors()); + auto result = script -> Evaluate(); + CHECK(result->EvaluateFloat() == Approx(532048240601.8)); + delete script; +} + +TEST_CASE( "math.log(532048240601) == 26.999999999998", "[integration]" ) { + Script* script = Script::Create(u"return math.log(532048240601)"); + REQUIRE(!script->Diagnostics -> HasErrors()); + auto result = script -> Evaluate(); + CHECK(result->EvaluateFloat() == Approx(26.999999999998)); + delete script; +} + +TEST_CASE( "math.log(3) == 1.0986122886681", "[integration]" ) { + Script* script = Script::Create(u"return math.log(3)"); + REQUIRE(!script->Diagnostics -> HasErrors()); + auto result = script -> Evaluate(); + CHECK(result->EvaluateFloat() == Approx(1.0986122886681)); + delete script; +} + +TEST_CASE( "math.sqrt(100) == 10", "[integration]" ) { + Script* script = Script::Create(u"return math.sqrt(100)"); + REQUIRE(!script->Diagnostics -> HasErrors()); + auto result = script -> Evaluate(); + CHECK(result->EvaluateFloat() == Approx(10)); + delete script; +} + +TEST_CASE( "math.sqrt(1234) == 35.128336140501", "[integration]" ) { + Script* script = Script::Create(u"return math.sqrt(1234)"); + REQUIRE(!script->Diagnostics -> HasErrors()); + auto result = script -> Evaluate(); + CHECK(result->EvaluateFloat() == Approx(35.128336140501)); + delete script; +} + +TEST_CASE( "math.sqrt(-7) == nan", "[integration]" ) { + Script* script = Script::Create(u"return math.sqrt(-7)"); + REQUIRE(!script->Diagnostics -> HasErrors()); + auto result = script -> Evaluate(); + CHECK(isnan(result->EvaluateFloat())); + delete script; +} + +TEST_CASE( "math.huge == max_double", "[integration]" ) { + Script* script = Script::Create(u"return math.huge"); + REQUIRE(!script->Diagnostics -> HasErrors()); + auto result = script -> Evaluate(); + CHECK(result->EvaluateFloat() == DBL_MAX); + delete script; +} + +TEST_CASE( "math.pi == pi", "[integration]" ) { + Script* script = Script::Create(u"return math.pi"); + REQUIRE(!script->Diagnostics -> HasErrors()); + auto result = script -> Evaluate(); + CHECK(result->EvaluateFloat() == M_PI); + delete script; +} + + +#endif +