diff --git a/src/Evaluator/Evaluator.cpp b/src/Evaluator/Evaluator.cpp index baa5d5c..f6f3821 100644 --- a/src/Evaluator/Evaluator.cpp +++ b/src/Evaluator/Evaluator.cpp @@ -369,7 +369,10 @@ namespace Porygon::Evaluation { arr[i] = parameters[i].Get(); } delete function; - return scriptOption -> Call(this -> _scriptOptions, arr, parameters.size()); + auto ret = scriptOption -> Call(this -> _scriptOptions, arr, parameters.size()); + auto v = ret->Evaluate(); + delete ret; + return v; } } diff --git a/src/StandardLibraries/BasicLibrary.hpp b/src/StandardLibraries/BasicLibrary.hpp index 9c22e6a..e59beb5 100644 --- a/src/StandardLibraries/BasicLibrary.hpp +++ b/src/StandardLibraries/BasicLibrary.hpp @@ -19,7 +19,9 @@ namespace Porygon::StandardLibraries{ class BasicLibrary{ //region Assert - static const Evaluation::EvalValue* _assert(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount){ + typedef UserData::UserDataReturnValue Return; + + static const UserData::UserDataReturnValue* _assert(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount){ auto assertion = parameters[0]->EvaluateBool(); if (!assertion){ if (parameterCount >= 2){ @@ -29,7 +31,7 @@ namespace Porygon::StandardLibraries{ } throw Evaluation::EvaluationException("assertion failed!"); } - return new Evaluation::BooleanEvalValue(true); + return new Return(new Evaluation::BooleanEvalValue(true)); } static shared_ptr GetAssertFuncType(){ @@ -40,7 +42,7 @@ namespace Porygon::StandardLibraries{ //endregion //region Error - static const Evaluation::EvalValue* _error(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount){ + static const UserData::UserDataReturnValue* _error(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount){ auto message = parameters[0]->EvaluateString(); auto conv = Utilities::StringUtils::FromUTF8(message); throw Evaluation::EvaluationException(conv); @@ -51,10 +53,10 @@ namespace Porygon::StandardLibraries{ //endregion //region Print - static const Evaluation::EvalValue* _print(void*, const ScriptOptions* options, const Evaluation::EvalValue* parameters[], int parameterCount){ + static const UserData::UserDataReturnValue* _print(void*, const ScriptOptions* options, const Evaluation::EvalValue* parameters[], int parameterCount){ auto message = parameters[0]->EvaluateString(); options->Print(message.c_str()); - return new Evaluation::NilEvalValue(); + return new Return(new Evaluation::NilEvalValue()); } static shared_ptr GetPrintFuncType(){ return GetFuncType(ScriptType::NilType, {{StringScriptType::Dynamic}}); @@ -62,10 +64,10 @@ namespace Porygon::StandardLibraries{ //endregion //region ToInt - static const Evaluation::EvalValue* _toInt(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount){ + static const UserData::UserDataReturnValue* _toInt(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount){ auto parameter = parameters[0]->EvaluateString(); auto parsed = Utilities::StringUtils::ParseInteger(parameter); - return new Evaluation::NumericEvalValue(parsed); + return new Return(new Evaluation::NumericEvalValue(parsed)); } static shared_ptr GetToIntFuncType(){ return GetFuncType(NumericScriptType::AwareInt, @@ -74,10 +76,10 @@ namespace Porygon::StandardLibraries{ //endregion //region ToFloat - static const Evaluation::EvalValue* _toFloat(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount){ + static const UserData::UserDataReturnValue* _toFloat(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount){ auto parameter = parameters[0]->EvaluateString(); auto parsed = Utilities::StringUtils::ParseFloat(parameter); - return new Evaluation::NumericEvalValue(parsed); + return new Return(new Evaluation::NumericEvalValue(parsed)); } static shared_ptr GetToFloatFuncType(){ return GetFuncType(NumericScriptType::AwareFloat, @@ -86,9 +88,9 @@ namespace Porygon::StandardLibraries{ //endregion //region ToString - static const Evaluation::EvalValue* _toString(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount){ + static const UserData::UserDataReturnValue* _toString(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount){ auto parameter = parameters[0]->EvaluateString(); - return new Evaluation::StringEvalValue(parameter); + return new Return(new Evaluation::StringEvalValue(parameter)); } static shared_ptr GetToStringFuncType(){ return GetFuncType(StringScriptType::Dynamic, {{make_shared(TypeClass::Any)}}); @@ -96,20 +98,20 @@ namespace Porygon::StandardLibraries{ //endregion //region Type - static const Evaluation::EvalValue* _type(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount){ + static const UserData::UserDataReturnValue* _type(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount){ auto parameter = parameters[0]->GetTypeClass(); switch (parameter){ - case TypeClass::Error: return new Evaluation::StringEvalValue(u"error"); - case TypeClass::Nil: return new Evaluation::StringEvalValue(u"nil"); - case TypeClass::Number: return new Evaluation::StringEvalValue(u"number"); - case TypeClass::Bool: return new Evaluation::StringEvalValue(u"bool"); - case TypeClass::String: return new Evaluation::StringEvalValue(u"string"); - case TypeClass::Function: return new Evaluation::StringEvalValue(u"function"); - case TypeClass::UserData: return new Evaluation::StringEvalValue(u"userdata"); - case TypeClass::UserDataCollection: return new Evaluation::StringEvalValue(u"userdata-collection"); - case TypeClass::Table: return new Evaluation::StringEvalValue(u"table"); - case TypeClass::Any: return new Evaluation::StringEvalValue(u"all"); + case TypeClass::Error: return new Return(new Evaluation::StringEvalValue(u"error")); + case TypeClass::Nil: return new Return(new Evaluation::StringEvalValue(u"nil")); + case TypeClass::Number: return new Return(new Evaluation::StringEvalValue(u"number")); + case TypeClass::Bool: return new Return(new Evaluation::StringEvalValue(u"bool")); + case TypeClass::String: return new Return(new Evaluation::StringEvalValue(u"string")); + case TypeClass::Function: return new Return(new Evaluation::StringEvalValue(u"function")); + case TypeClass::UserData: return new Return(new Evaluation::StringEvalValue(u"userdata")); + case TypeClass::UserDataCollection: return new Return(new Evaluation::StringEvalValue(u"userdata-collection")); + case TypeClass::Table: return new Return(new Evaluation::StringEvalValue(u"table")); + case TypeClass::Any: return new Return(new Evaluation::StringEvalValue(u"all")); } throw exception(); } @@ -119,9 +121,9 @@ namespace Porygon::StandardLibraries{ //endregion //region IsFloat - static const Evaluation::EvalValue* _isFloat(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount){ + static const UserData::UserDataReturnValue* _isFloat(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount){ auto parameter = dynamic_cast(parameters[0]); - return new Evaluation::BooleanEvalValue(parameter->IsFloat()); + return new Return(new Evaluation::BooleanEvalValue(parameter->IsFloat())); } static shared_ptr GetIsFloatFuncType(){ return GetFuncType(ScriptType::BoolType, {{NumericScriptType::Unaware}}); @@ -140,10 +142,10 @@ namespace Porygon::StandardLibraries{ return funcType; } - static Evaluation::EvalValue* GetFuncEvalValue( - const Evaluation::EvalValue* (*func)(void* obj, const ScriptOptions*, - const Evaluation::EvalValue* parameters[], int parameterCount), - const shared_ptr& type, size_t optionLength){ + static Evaluation::EvalValue* GetFuncEvalValue(const UserData::UserDataReturnValue* (*func)(void* obj, const ScriptOptions*, + const Evaluation::EvalValue* parameters[], int parameterCount), + const shared_ptr& type, size_t optionLength) + { auto f = new Evaluation::GenericFunctionEvalValue(type, Utilities::Random::Get()); for (size_t i = 0; i < optionLength; i++){ auto funcOption = new UserData::UserDataFunction(func, nullptr); diff --git a/src/StandardLibraries/MathLibrary.hpp b/src/StandardLibraries/MathLibrary.hpp index cedbe73..4da3dc4 100644 --- a/src/StandardLibraries/MathLibrary.hpp +++ b/src/StandardLibraries/MathLibrary.hpp @@ -24,6 +24,7 @@ namespace Porygon::StandardLibraries { using namespace Porygon::Evaluation; using namespace Porygon::Utilities; class MathLibrary { + typedef UserData::UserDataReturnValue Return; //region templates @@ -31,7 +32,7 @@ namespace Porygon::StandardLibraries { #define INTEGER_TYPE NumericScriptType::AwareInt #define BOOL_TYPE ScriptType::BoolType #define FUNCTION(fieldName) \ - [](void* obj) -> const Porygon::Evaluation::EvalValue* { \ + [](void* obj) -> const EvalValue* { \ auto t = new Porygon::Evaluation::GenericFunctionEvalValue(make_shared(), \ Porygon::Utilities::Random::Get()); \ t->RegisterOption(new Porygon::UserData::UserDataFunction(fieldName, nullptr)); \ @@ -39,83 +40,91 @@ namespace Porygon::StandardLibraries { nullptr //endregion - static const EvalValue* _abs(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount){ + inline static const Return* RETURN(double d){ + return new Return(new NumericEvalValue(d)); + } + inline static const Return* RETURN(int64_t i){ + return new Return(new NumericEvalValue(i)); + } + + + static const Return* _abs(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount){ auto parameter = dynamic_cast(parameters[0]); if (parameter->IsFloat()){ - return new NumericEvalValue(std::abs(parameter->EvaluateFloat())); + return RETURN(std::abs(parameter->EvaluateFloat())); } else{ - return new NumericEvalValue(std::abs(parameter->EvaluateInteger())); + return RETURN(std::abs(parameter->EvaluateInteger())); } } - static const EvalValue* _acos(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount) { + static const Return* _acos(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount) { auto parameter = dynamic_cast(parameters[0]); - return new NumericEvalValue(std::acos(parameter->EvaluateFloat())); + return RETURN(std::acos(parameter->EvaluateFloat())); } - static const EvalValue* _asin(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount) { + static const Return* _asin(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount) { auto parameter = dynamic_cast(parameters[0]); - return new NumericEvalValue(std::asin(parameter->EvaluateFloat())); + return RETURN(std::asin(parameter->EvaluateFloat())); } - static const EvalValue* _atan(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount) { + static const Return* _atan(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount) { if (parameterCount == 1){ auto parameter = dynamic_cast(parameters[0]); - return new NumericEvalValue(std::atan(parameter->EvaluateFloat())); + return RETURN(std::atan(parameter->EvaluateFloat())); } else{ auto parameter1 = dynamic_cast(parameters[0]); auto parameter2 = dynamic_cast(parameters[1]); - return new NumericEvalValue(std::atan2(parameter1->EvaluateFloat(), parameter2->EvaluateFloat())); + return RETURN(std::atan2(parameter1->EvaluateFloat(), parameter2->EvaluateFloat())); } } - static const EvalValue* _ceil(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount) { + static const Return* _ceil(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount) { auto parameter = dynamic_cast(parameters[0]); auto f = parameter->EvaluateFloat(); - return new NumericEvalValue(static_cast(std::ceil(f))); + return RETURN(static_cast(std::ceil(f))); } - static const EvalValue* _cos(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount) { + static const Return* _cos(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount) { auto parameter = dynamic_cast(parameters[0]); auto f = parameter->EvaluateFloat(); - return new NumericEvalValue(std::cos(f)); + return RETURN(std::cos(f)); } - static const EvalValue* _deg(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount) { + static const Return* _deg(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount) { auto parameter = dynamic_cast(parameters[0]); auto f = parameter->EvaluateFloat(); - return new NumericEvalValue(f * 180 / M_PI); + return RETURN(f * 180 / M_PI); } - static const EvalValue* _exp(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount) { + static const Return* _exp(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount) { auto parameter = dynamic_cast(parameters[0]); auto f = parameter->EvaluateFloat(); - return new NumericEvalValue(std::exp(f)); + return RETURN(std::exp(f)); } - static const EvalValue* _floor(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount) { + static const Return* _floor(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount) { auto parameter = dynamic_cast(parameters[0]); auto f = parameter->EvaluateFloat(); - return new NumericEvalValue(std::floor(f)); + return RETURN(std::floor(f)); } - static const EvalValue* _fmod(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount) { + static const Return* _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 NumericEvalValue(std::fmod(f1, f2)); + return RETURN(std::fmod(f1, f2)); } static const EvalValue* _huge; - static const EvalValue* _log(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount){ + static const Return* _log(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount){ if (parameterCount == 1){ auto f = dynamic_cast(parameters[0])->EvaluateFloat(); - return new NumericEvalValue(std::log(f)); + return RETURN(std::log(f)); } else{ auto f1 = dynamic_cast(parameters[0])->EvaluateFloat(); auto f2 = dynamic_cast(parameters[1])->EvaluateFloat(); - return new NumericEvalValue(std::log(f2) / std::log(f1)); + return RETURN(std::log(f2) / std::log(f1)); } } @@ -123,31 +132,31 @@ namespace Porygon::StandardLibraries { static const EvalValue* _minInteger; static const EvalValue* _pi; - static const EvalValue* _rad(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount) { + static const Return* _rad(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount) { auto parameter = dynamic_cast(parameters[0]); auto f = parameter->EvaluateFloat(); - return new NumericEvalValue(M_PI *(f / 180)); + return RETURN(M_PI *(f / 180)); } - static const EvalValue* _sin(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount) { + static const Return* _sin(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount) { auto parameter = dynamic_cast(parameters[0]); - return new NumericEvalValue(std::sin(parameter->EvaluateFloat())); + return RETURN(std::sin(parameter->EvaluateFloat())); } - static const EvalValue* _sqrt(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount) { + static const Return* _sqrt(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount) { auto parameter = dynamic_cast(parameters[0]); - return new NumericEvalValue(std::sqrt(parameter->EvaluateFloat())); + return RETURN(std::sqrt(parameter->EvaluateFloat())); } - static const EvalValue* _tan(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount) { + static const Return* _tan(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount) { auto parameter = dynamic_cast(parameters[0]); - return new NumericEvalValue(std::tan(parameter->EvaluateFloat())); + return RETURN(std::tan(parameter->EvaluateFloat())); } - static const EvalValue* _ult(void*, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount) { + static const Return* _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); + return new Return(new BooleanEvalValue(parameter1 < parameter2)); } static UserData::UserDataFunctionOption* CreateFunctionOption(const shared_ptr& returnType, diff --git a/src/UserData/UserDataFunction.cpp b/src/UserData/UserDataFunction.cpp index b3501df..d2f053f 100644 --- a/src/UserData/UserDataFunction.cpp +++ b/src/UserData/UserDataFunction.cpp @@ -6,7 +6,7 @@ using namespace Porygon::Evaluation; namespace Porygon::UserData{ extern "C" { - const EvalValue * CreateFunctionEvalValue(const Evaluation::EvalValue* (*func)(void*, const ScriptOptions*, + const EvalValue * CreateFunctionEvalValue(const UserData::UserDataReturnValue* (*func)(void*, const ScriptOptions*, const EvalValue* [], int ), void* obj) { auto opt = new UserDataFunction(func, obj); auto t = new GenericFunctionEvalValue(make_shared(), Utilities::Random::Get()); @@ -15,7 +15,7 @@ namespace Porygon::UserData{ } void RegisterFunctionEvalValueOption(const GenericFunctionEvalValue* val, - const Evaluation::EvalValue* (*func)(void*, const ScriptOptions*, const EvalValue* [], int ), void* obj){ + const UserData::UserDataReturnValue* (*func)(void*, const ScriptOptions*, const EvalValue* [], int ), void* obj){ auto opt = new UserDataFunction(func, obj); val->RegisterOption(opt); } diff --git a/src/UserData/UserDataFunction.hpp b/src/UserData/UserDataFunction.hpp index ea19e71..cd92a05 100644 --- a/src/UserData/UserDataFunction.hpp +++ b/src/UserData/UserDataFunction.hpp @@ -5,21 +5,22 @@ #include "UserDataFunctionType.hpp" #include "../ScriptTypes/FunctionScriptType.hpp" #include "../ScriptOptions.hpp" +#include "UserDataReturnValue.hpp" namespace Porygon::UserData{ class UserDataFunction : public Evaluation::GenericFunctionOption { - const Evaluation::EvalValue* (*_call)(void* obj, const ScriptOptions*, const Evaluation::EvalValue* parameters[], + const UserDataReturnValue* (*_call)(void* obj, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount); void *_obj; - UserDataFunction(const Evaluation::EvalValue* (*call)(void* obj, const ScriptOptions*, + UserDataFunction(const UserDataReturnValue* (*call)(void* obj, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount), void* obj, const shared_ptr& type, size_t hash) : GenericFunctionOption(){ _call = call; _obj = obj; } public: - UserDataFunction(const Evaluation::EvalValue* (*call)(void* obj, const ScriptOptions*, + UserDataFunction(const UserDataReturnValue* (*call)(void* obj, const ScriptOptions*, const Evaluation::EvalValue* parameters[], int parameterCount), void* obj) : GenericFunctionOption(){ _call = call; @@ -29,7 +30,7 @@ namespace Porygon::UserData{ ~UserDataFunction() final = default; [[nodiscard]] - inline const Evaluation::EvalValue* Call(const ScriptOptions* script, + inline const UserDataReturnValue* Call(const ScriptOptions* script, const Evaluation::EvalValue* parameters[], int parameterCount) const{ return _call(_obj, script, parameters, parameterCount); } diff --git a/src/UserData/UserDataReturnValue.cpp b/src/UserData/UserDataReturnValue.cpp new file mode 100644 index 0000000..9c0a35d --- /dev/null +++ b/src/UserData/UserDataReturnValue.cpp @@ -0,0 +1,12 @@ +#include "UserDataReturnValue.hpp" + +extern "C"{ + Porygon::UserData::UserDataReturnValue* ReturnValue(Porygon::Evaluation::EvalValue* value){ + return new Porygon::UserData::UserDataReturnValue(value); + } + + Porygon::UserData::UserDataReturnValue* ErrorValue(const char* message){ + return new Porygon::UserData::UserDataReturnValue(message); + } + +} \ No newline at end of file diff --git a/src/UserData/UserDataReturnValue.hpp b/src/UserData/UserDataReturnValue.hpp new file mode 100644 index 0000000..a174531 --- /dev/null +++ b/src/UserData/UserDataReturnValue.hpp @@ -0,0 +1,29 @@ +#ifndef PORYGONLANG_USERDATARETURNVALUE_HPP +#define PORYGONLANG_USERDATARETURNVALUE_HPP + +#include "../Evaluator/EvalValues/EvalValue.hpp" + +extern "C" { +namespace Porygon::UserData { + struct UserDataReturnValue { + bool _success; + union { + const char *_message; + const Evaluation::EvalValue *_value; + }; + public: + UserDataReturnValue(Evaluation::EvalValue *value) : _success(true), _value(value) {} + UserDataReturnValue(const Evaluation::EvalValue *value) : _success(true), _value(value) {} + UserDataReturnValue(const char *message) : _success(false), _message(message) {} + + inline const Evaluation::EvalValue *Evaluate() const{ + if (_success) { + return _value; + } + throw Evaluation::EvaluationException(_message); + } + }; +} +} + +#endif //PORYGONLANG_USERDATARETURNVALUE_HPP diff --git a/src/UserData/UserDataTemplates.hpp b/src/UserData/UserDataTemplates.hpp index 285e3ca..f4d3b65 100644 --- a/src/UserData/UserDataTemplates.hpp +++ b/src/UserData/UserDataTemplates.hpp @@ -117,7 +117,8 @@ Porygon::Utilities::HashedString* Convert(const char* k){ Porygon::Utilities::Random::Get()); \ t->RegisterOption(new Porygon::UserData::UserDataFunction( \ [](void* obj, const ScriptOptions* opts, const Porygon::Evaluation::EvalValue* par[], int parameterCount) \ - -> const Porygon::Evaluation::EvalValue*{return ((const T_USERDATA*)obj)->invoke__##fieldName(obj, opts, par, parameterCount);}, \ + -> const Porygon::UserData::UserDataReturnValue*{ \ + return new Porygon::UserData::UserDataReturnValue (((const T_USERDATA*)obj)->invoke__##fieldName(obj, opts, par, parameterCount));}, \ obj)); \ return t;}, \ nullptr) \