diff --git a/src/UserData/UserDataFunctionType.hpp b/src/UserData/UserDataFunctionType.hpp index 3919d73..f7dc352 100644 --- a/src/UserData/UserDataFunctionType.hpp +++ b/src/UserData/UserDataFunctionType.hpp @@ -11,6 +11,22 @@ namespace Porygon::UserData{ : GenericFunctionScriptType(std::move(returnType), std::move(parameterTypes)){ } + static UserDataFunctionType* FromRawPointers(ScriptType* returnType, vector parameterTypes){ + auto rt = shared_ptr(returnType); + auto p = vector>(parameterTypes.size()); + for (int i = 0; i < parameterTypes.size(); i++){ + p[i] = shared_ptr(parameterTypes[i]); + } + return new UserDataFunctionType(rt, p); + } + + static UserDataFunctionType* FromRawPointers(ScriptType* returnType){ + auto rt = shared_ptr(returnType); + return new UserDataFunctionType(rt, {}); + } + + + const bool IsScriptFunction() const final{ return false; diff --git a/src/UserData/UserDataTemplates.hpp b/src/UserData/UserDataTemplates.hpp new file mode 100644 index 0000000..51717ed --- /dev/null +++ b/src/UserData/UserDataTemplates.hpp @@ -0,0 +1,77 @@ +#ifndef PORYGONLANG_USERDATATEMPLATES_HPP +#define PORYGONLANG_USERDATATEMPLATES_HPP + +#define PORYGON_USERDATA_START() \ + static Porygon::UserData::UserData* __createUserData(){ \ + return new Porygon::UserData::UserData({ \ + +#define PORYGON_USERDATA_END() });}; + +#define PORYGON_INTEGER_TYPE ((Porygon::ScriptType*)new Porygon::NumericScriptType(true, false)) +#define PORYGON_FLOAT_TYPE ((Porygon::ScriptType*)new Porygon::NumericScriptType(true, true)) +#define PORYGON_STRING_TYPE ((Porygon::ScriptType*)new Porygon::StringScriptType(false, 0)) + +#define PORYGON_FIELD(userDataTypeName, fieldName, fieldType, getterHelper, setterHelper) \ + { \ + Porygon::Utilities::HashedString::ConstHash(#fieldName), \ + new Porygon::UserData::UserDataField(fieldType, \ + [](void* obj) -> Porygon::Evaluation::EvalValue* { return new getterHelper;}, \ + [](void* obj, Porygon::Evaluation::EvalValue* val) { ((userDataTypeName*)obj)->fieldName = setterHelper;} \ + ) \ + }, \ + +#define PORYGON_READONLY_FIELD(userDataTypeName, fieldName, fieldType, getterHelper) \ + { \ + Porygon::Utilities::HashedString::ConstHash(#fieldName), \ + new Porygon::UserData::UserDataField(fieldType, \ + [](void* obj) -> Porygon::Evaluation::EvalValue* { return new getterHelper;}, \ + nullptr \ + ) \ + }, \ + +#define PORYGON_INTEGER_FIELD(userDataTypeName, fieldName) \ + PORYGON_FIELD(userDataTypeName, fieldName, PORYGON_INTEGER_TYPE, \ + Porygon::Evaluation::IntegerEvalValue(((userDataTypeName*)obj)->fieldName), val->EvaluateInteger()) + +#define PORYGON_READONLY_INTEGER_FIELD(userDataTypeName, fieldName) \ + PORYGON_READONLY_FIELD(userDataTypeName, fieldName, PORYGON_INTEGER_TYPE, \ + Porygon::Evaluation::IntegerEvalValue(((userDataTypeName*)obj)->fieldName)) + +#define PORYGON_FLOAT_FIELD(userDataTypeName, fieldName) \ + PORYGON_FIELD(userDataTypeName, fieldName, PORYGON_FLOAT_TYPE, \ + Porygon::EvaluationFloatEvalValue(((userDataTypeName*)obj)->fieldName), val->EvaluateFloat()) + +#define PORYGON_READONLY_FLOAT_FIELD(userDataTypeName, fieldName) \ + PORYGON_READONLY_FIELD(userDataTypeName, fieldName, PORYGON_FLOAT_TYPE, \ + Porygon::EvaluationFloatEvalValue(((userDataTypeName*)obj)->fieldName)) + + +#define PORYGON_FUNCTION(userDataTypeName, fieldName, returnType, ...) \ + { \ + Porygon::Utilities::HashedString::ConstHash(#fieldName), \ + new Porygon::UserData::UserDataField(Porygon::UserData::UserDataFunctionType::FromRawPointers(returnType, {__VA_ARGS__} ), \ + \ + \ + [](void* obj) -> Porygon::Evaluation::EvalValue* { \ + return new Porygon::UserData::UserDataFunction( \ + [](void* obj, Porygon::Evaluation::EvalValue* parameters[], int parameterCount) \ + -> Porygon::Evaluation::EvalValue*{return ((userDataTypeName*)obj)->invoke__##fieldName(obj, parameters, parameterCount);}, \ + obj);}, \ + nullptr) \ + }, + +#define PORYGON_INTEGER_FUNCTION(userDataTypeName, fieldName, ...) \ + PORYGON_FUNCTION(userDataTypeName, fieldName, new Porygon::NumericScriptType(true, false), __VA_ARGS__ ) + + +#define PORYGON_PREPARE_FUNCTION(userDataTypeName, fieldName, returnType, ...) \ + static Porygon::Evaluation::EvalValue* invoke__##fieldName(void* obj, Porygon::Evaluation::EvalValue* parameters[], int parameterCount){ \ + return new returnType(((userDataTypeName*)obj)->fieldName( \ + __VA_ARGS__ \ + ));} + + + + + +#endif //PORYGONLANG_USERDATATEMPLATES_HPP diff --git a/tests/integration/UserDataTests.cpp b/tests/integration/UserDataTests.cpp index f288dd6..ecedccd 100644 --- a/tests/integration/UserDataTests.cpp +++ b/tests/integration/UserDataTests.cpp @@ -7,6 +7,7 @@ #include "../../src/UserData/UserDataValue.hpp" #include "../../src/UserData/UserDataFunction.hpp" #include "../../src/UserData/UserDataFunctionType.hpp" +#include "../../src/UserData/UserDataTemplates.hpp" using namespace Porygon; using namespace Porygon::UserData; @@ -23,65 +24,20 @@ public: return a + b; } + // Declare script properties private: - static EvalValue* GetFoo(void* obj){ - return new IntegerEvalValue(((UserDataTestObject*)obj)->foo); - } - - static void SetFoo(void* obj, EvalValue* val){ - ((UserDataTestObject*)obj)->foo = val->EvaluateInteger(); - } - - static EvalValue* CallFooFunction(void* obj, EvalValue* parameters[], int parameterCount){ - return new IntegerEvalValue(((UserDataTestObject*)obj)->getFoo()); - } - - static EvalValue* GetFooFunction(void* obj){ - return new UserDataFunction(CallFooFunction, obj); - } - - static EvalValue* CallAddition(void* obj, EvalValue* parameters[], int parameterCount){ - return new IntegerEvalValue(((UserDataTestObject*)obj)->Addition( - parameters[0] -> EvaluateInteger(), - parameters[1] -> EvaluateInteger() - )); - } - - static GenericFunctionScriptType* AdditionFunctionType(); - - static EvalValue* GetAdditionFunction(void* obj){ - return new UserDataFunction(CallAddition, obj); - } - + PORYGON_PREPARE_FUNCTION(UserDataTestObject, getFoo, IntegerEvalValue) + PORYGON_PREPARE_FUNCTION(UserDataTestObject, Addition, IntegerEvalValue, (parameters[0] -> EvaluateInteger()), (parameters[1] -> EvaluateInteger())) public: - static Porygon::UserData::UserData* CreateData(){ - return new Porygon::UserData::UserData({ - { - HashedString::ConstHash("foo"), - new UserDataField(new NumericScriptType(true, false), GetFoo, SetFoo) - }, - { - HashedString::ConstHash("getFoo"), - new UserDataField(new UserDataFunctionType(make_shared(true, false), {}), GetFooFunction, nullptr) - }, - { - HashedString::ConstHash("Addition"), - new UserDataField(AdditionFunctionType(), GetAdditionFunction, nullptr) - } - }); - } + PORYGON_USERDATA_START() + PORYGON_INTEGER_FIELD(UserDataTestObject, foo) + PORYGON_INTEGER_FUNCTION(UserDataTestObject, getFoo) + PORYGON_INTEGER_FUNCTION(UserDataTestObject, Addition, PORYGON_INTEGER_TYPE, PORYGON_INTEGER_TYPE) + PORYGON_USERDATA_END() }; -GenericFunctionScriptType* UserDataTestObject::AdditionFunctionType(){ - return new UserDataFunctionType(make_shared(true, false), - vector>{ - make_shared(true, false), - make_shared(true, false) - }); -} - TEST_CASE( "Gets UserData value", "[integration]" ) { - UserDataStorage::RegisterType(HashedString::ConstHash("testObject"), UserDataTestObject::CreateData()); + UserDataStorage::RegisterType(HashedString::ConstHash("testObject"), UserDataTestObject::__createUserData()); Script* script = Script::Create(R"( function testFunc(testObject obj) return obj["foo"] @@ -101,7 +57,7 @@ end } TEST_CASE( "Sets UserData value", "[integration]" ) { - UserDataStorage::RegisterType(HashedString::ConstHash("testObject"), UserDataTestObject::CreateData()); + UserDataStorage::RegisterType(HashedString::ConstHash("testObject"), UserDataTestObject::__createUserData()); Script* script = Script::Create(R"( function testFunc(testObject obj) obj["foo"] = 5000 @@ -120,7 +76,7 @@ end } TEST_CASE( "Calls UserData function", "[integration]" ) { - UserDataStorage::RegisterType(HashedString::ConstHash("testObject"), UserDataTestObject::CreateData()); + UserDataStorage::RegisterType(HashedString::ConstHash("testObject"), UserDataTestObject::__createUserData()); Script* script = Script::Create(R"( function testFunc(testObject obj) return obj.getFoo() @@ -139,7 +95,7 @@ end } TEST_CASE( "Calls UserData function with parameters", "[integration]" ) { - UserDataStorage::RegisterType(HashedString::ConstHash("testObject"), UserDataTestObject::CreateData()); + UserDataStorage::RegisterType(HashedString::ConstHash("testObject"), UserDataTestObject::__createUserData()); Script* script = Script::Create(R"( function testFunc(testObject obj) return obj.Addition(5046, 8432)