diff --git a/build-debug-windows/PorygonLangTests.exe b/build-debug-windows/PorygonLangTests.exe new file mode 100755 index 0000000..9dd450a Binary files /dev/null and b/build-debug-windows/PorygonLangTests.exe differ diff --git a/build-debug-windows/libPorygonLang.so b/build-debug-windows/libPorygonLang.so new file mode 100755 index 0000000..fc5b845 Binary files /dev/null and b/build-debug-windows/libPorygonLang.so differ diff --git a/src/Evaluator/Iterator/Iterator.hpp b/src/Evaluator/Iterator/Iterator.hpp index ff32dbd..c9cb865 100644 --- a/src/Evaluator/Iterator/Iterator.hpp +++ b/src/Evaluator/Iterator/Iterator.hpp @@ -10,7 +10,7 @@ using namespace std; namespace Porygon::Evaluation{ class Iterator { public: - virtual EvalValue* GetCurrent() = 0; + virtual const EvalValue* GetCurrent() = 0; virtual bool MoveNext() = 0; virtual void Reset() = 0; virtual ~Iterator(){} diff --git a/src/Evaluator/Iterator/NumericalKeyIterator.hpp b/src/Evaluator/Iterator/NumericalKeyIterator.hpp index ca95f8b..9db05d1 100644 --- a/src/Evaluator/Iterator/NumericalKeyIterator.hpp +++ b/src/Evaluator/Iterator/NumericalKeyIterator.hpp @@ -16,7 +16,7 @@ namespace Porygon::Evaluation{ explicit NumericalKeyIterator(const NumericalTableEvalValue* table) : _vec(table->GetTable()), _size(_vec->size() + 1){} - inline EvalValue* GetCurrent() final{ + inline const EvalValue* GetCurrent() final{ return new IntegerEvalValue(_position); } diff --git a/src/Evaluator/Iterator/SimpleKeyIterator.hpp b/src/Evaluator/Iterator/SimpleKeyIterator.hpp index d8208f1..4bd3996 100644 --- a/src/Evaluator/Iterator/SimpleKeyIterator.hpp +++ b/src/Evaluator/Iterator/SimpleKeyIterator.hpp @@ -15,7 +15,7 @@ namespace Porygon::Evaluation{ explicit TableKeyIterator(const TableEvalValue* table) : _iterator(table->GetTableIterator()), _end(table->GetTableIteratorEnd()){} - inline EvalValue* GetCurrent() final{ + inline const EvalValue* GetCurrent() final{ return new StringEvalValue(*_iterator->first.GetString()); } diff --git a/src/UserData/UserDataCollections/UserDataCollectionIterator.cpp b/src/UserData/UserDataCollections/UserDataCollectionIterator.cpp new file mode 100644 index 0000000..29bc7a0 --- /dev/null +++ b/src/UserData/UserDataCollections/UserDataCollectionIterator.cpp @@ -0,0 +1 @@ +#include "UserDataCollectionIterator.hpp" diff --git a/src/UserData/UserDataCollections/UserDataCollectionIterator.hpp b/src/UserData/UserDataCollections/UserDataCollectionIterator.hpp new file mode 100644 index 0000000..4799dcd --- /dev/null +++ b/src/UserData/UserDataCollections/UserDataCollectionIterator.hpp @@ -0,0 +1,33 @@ +#ifndef PORYGONLANG_USERDATACOLLECTIONITERATOR_HPP +#define PORYGONLANG_USERDATACOLLECTIONITERATOR_HPP + +#include "../../Evaluator/Iterator/Iterator.hpp" + +namespace Porygon::UserData{ + class UserDataCollectionIterator : public Evaluation::Iterator{ + const Evaluation::EvalValue* (*_getCurrent)(); + const Evaluation::EvalValue* (*_moveNext)(); + const Evaluation::EvalValue* (*_reset)(); + public: + UserDataCollectionIterator(const Evaluation::EvalValue* (*getCurrent)(), + const Evaluation::EvalValue* (*moveNext)(), + const Evaluation::EvalValue* (*reset)()){ + _getCurrent = getCurrent; + _moveNext = moveNext; + _reset = reset; + } + + const Evaluation::EvalValue* GetCurrent() final{ + return _getCurrent(); + } + bool MoveNext() final{ + _moveNext(); + } + void Reset() final{ + _reset(); + } + }; +} + + +#endif //PORYGONLANG_USERDATACOLLECTIONITERATOR_HPP diff --git a/src/UserData/UserDataCollections/UserDataCollectionRangeIterator.cpp b/src/UserData/UserDataCollections/UserDataCollectionRangeIterator.cpp new file mode 100644 index 0000000..e2815fa --- /dev/null +++ b/src/UserData/UserDataCollections/UserDataCollectionRangeIterator.cpp @@ -0,0 +1 @@ +#include "UserDataCollectionRangeIterator.hpp" diff --git a/src/UserData/UserDataCollections/UserDataCollectionRangeIterator.hpp b/src/UserData/UserDataCollections/UserDataCollectionRangeIterator.hpp new file mode 100644 index 0000000..7fe1767 --- /dev/null +++ b/src/UserData/UserDataCollections/UserDataCollectionRangeIterator.hpp @@ -0,0 +1,33 @@ +#ifndef PORYGONLANG_USERDATACOLLECTIONRANGEITERATOR_HPP +#define PORYGONLANG_USERDATACOLLECTIONRANGEITERATOR_HPP + +#include "../../Evaluator/Iterator/Iterator.hpp" +#include "../../Evaluator/EvalValues/NumericEvalValue.hpp" + +namespace Porygon::UserData{ + class UserDataCollectionRangeIterator : public Evaluation::Iterator{ + size_t _start; + size_t _end; + + size_t _current; + public: + UserDataCollectionRangeIterator(size_t start, size_t end){ + _start = start; + _end = end; + _current = start; + } + + const Evaluation::EvalValue* GetCurrent() final{ + return new Evaluation::IntegerEvalValue(_current); + } + bool MoveNext() final{ + _current ++; + return _current <= _end; + } + void Reset() final{ + _current = _start; + } + }; +} + +#endif //PORYGONLANG_USERDATACOLLECTIONRANGEITERATOR_HPP diff --git a/src/UserData/UserDataCollectionType.cpp b/src/UserData/UserDataCollections/UserDataCollectionType.cpp similarity index 100% rename from src/UserData/UserDataCollectionType.cpp rename to src/UserData/UserDataCollections/UserDataCollectionType.cpp diff --git a/src/UserData/UserDataCollectionType.hpp b/src/UserData/UserDataCollections/UserDataCollectionType.hpp similarity index 98% rename from src/UserData/UserDataCollectionType.hpp rename to src/UserData/UserDataCollections/UserDataCollectionType.hpp index 789a7a5..6f12ed2 100644 --- a/src/UserData/UserDataCollectionType.hpp +++ b/src/UserData/UserDataCollections/UserDataCollectionType.hpp @@ -2,7 +2,7 @@ #define PORYGONLANG_USERDATACOLLECTIONTYPE_HPP #include -#include "../ScriptTypes/ScriptType.hpp" +#include "../../ScriptTypes/ScriptType.hpp" namespace Porygon::UserData { class UserDataCollectionType : public ScriptType { diff --git a/src/UserData/UserDataCollectionValue.cpp b/src/UserData/UserDataCollections/UserDataCollectionValue.cpp similarity index 100% rename from src/UserData/UserDataCollectionValue.cpp rename to src/UserData/UserDataCollections/UserDataCollectionValue.cpp diff --git a/src/UserData/UserDataCollectionValue.hpp b/src/UserData/UserDataCollections/UserDataCollectionValue.hpp similarity index 78% rename from src/UserData/UserDataCollectionValue.hpp rename to src/UserData/UserDataCollections/UserDataCollectionValue.hpp index bc41b8c..0fd1f2f 100644 --- a/src/UserData/UserDataCollectionValue.hpp +++ b/src/UserData/UserDataCollections/UserDataCollectionValue.hpp @@ -4,8 +4,8 @@ #include #include "UserDataCollectionType.hpp" -#include "../Evaluator/EvalValues/EvalValue.hpp" -#include "../Utilities/Random.hpp" +#include "../../Evaluator/EvalValues/EvalValue.hpp" +#include "../../Utilities/Random.hpp" using namespace Porygon::Evaluation; @@ -14,12 +14,13 @@ namespace Porygon::UserData { void* _parentObject; const EvalValue* (*_get)(void*, const EvalValue*); void (*_set)(void*, const EvalValue* , const EvalValue*); - + Iterator* (*_getIterator)(void*); public: UserDataCollectionHelper(void* parentObject, const EvalValue* (*get)(void*, const EvalValue*), - void (*set)(void*, const EvalValue*, const EvalValue*)) - : _parentObject(parentObject), _get(get), _set(set){} + void (*set)(void*, const EvalValue*, const EvalValue*), + Iterator* (*getIterator)(void*)) + : _parentObject(parentObject), _get(get), _set(set), _getIterator(getIterator){} const EvalValue* Get(const EvalValue* key) const{ return _get(_parentObject, key); @@ -28,6 +29,10 @@ namespace Porygon::UserData { void Set(const EvalValue* key, const EvalValue* value) const{ _set(_parentObject, key, value); } + + [[nodiscard]] Iterator* GetIterator() const{ + return _getIterator(_parentObject); + } }; class UserDataCollectionValue : public Evaluation::EvalValue{ @@ -42,7 +47,7 @@ namespace Porygon::UserData { public: UserDataCollectionValue(ScriptType* type, const UserDataCollectionHelper* helper) - : _type((UserDataCollectionType*)type), _helper(helper), _hash(Utilities::Random::Get()) + : _type(dynamic_cast(type)), _helper(helper), _hash(Utilities::Random::Get()) { } @@ -67,6 +72,11 @@ namespace Porygon::UserData { return _helper->Get(val); } + [[nodiscard]] + Iterator * GetKeyIterator() const final{ + return _helper->GetIterator(); + } + void SetIndexValue(const EvalValue *key, const EvalValue* value) const final{ _helper->Set(key, value); delete value; diff --git a/src/UserData/UserDataTemplates.hpp b/src/UserData/UserDataTemplates.hpp index 10adbae..ded2940 100644 --- a/src/UserData/UserDataTemplates.hpp +++ b/src/UserData/UserDataTemplates.hpp @@ -85,7 +85,13 @@ , [](void* obj, const EvalValue* key, const EvalValue* value){ \ auto index = key->EvaluateInteger() - 1;\ ((T_USERDATA*)obj)->fieldName[index] = value->EvaluateInteger(); \ - }) \ + } \ + , [](void* obj) -> Porygon::Evaluation::Iterator* {\ + auto val = ((T_USERDATA*)obj)->fieldName; \ + auto size = val.size(); \ + return new Porygon::UserData::UserDataCollectionRangeIterator(0, size); \ + } \ + ) \ ) \ ) diff --git a/tests/integration/UserDataTests.cpp b/tests/integration/UserDataTests.cpp index 21f5478..2c91d07 100644 --- a/tests/integration/UserDataTests.cpp +++ b/tests/integration/UserDataTests.cpp @@ -8,10 +8,10 @@ #include "../../src/UserData/UserDataFunction.hpp" #include "../../src/UserData/UserDataFunctionType.hpp" #include "../../src/UserData/UserDataTemplates.hpp" -#include "../../src/UserData/UserDataCollectionType.hpp" -#include "../../src/UserData/UserDataCollectionValue.hpp" +#include "../../src/UserData/UserDataCollections/UserDataCollectionType.hpp" +#include "../../src/UserData/UserDataCollections/UserDataCollectionValue.hpp" +#include "../../src/UserData/UserDataCollections/UserDataCollectionRangeIterator.hpp" #include "../../src/Evaluator/EvalValues/EvalValueHelper.hpp" -#include "../../src/Utilities/Random.hpp" using namespace Porygon; using namespace Porygon::UserData; @@ -173,5 +173,58 @@ end UserDataStorage::ClearTypes(); } +TEST_CASE( "Iterate over userdata vector keys", "[integration]" ) { + UserDataStorage::RegisterType(HashedString::ConstHash("testObject"), UserDataTestObject::__createUserData()); + Script* script = Script::Create(R"( +function testFunc(testObject obj) + local val = 0 + for i in obj.fooVector do + val = val + i + end + return val +end +)"); + REQUIRE(!script->Diagnostics -> HasErrors()); + script->Evaluate(); + auto func = (GenericFunctionEvalValue*)script -> GetVariable(u"testFunc"); + auto funcType = func -> GetType(); + auto obj = new UserDataTestObject(); + auto parameter = new UserDataValue(HashedString::ConstHash("testObject"), obj); + auto result = script->CallFunction(u"testFunc", {parameter}); + REQUIRE(result->EvaluateInteger() == 6); + delete obj; + delete parameter; + delete script; + delete func; + delete result; + UserDataStorage::ClearTypes(); +} + +TEST_CASE( "Iterate over userdata vector values", "[integration]" ) { + UserDataStorage::RegisterType(HashedString::ConstHash("testObject"), UserDataTestObject::__createUserData()); + Script* script = Script::Create(R"( +function testFunc(testObject obj) + local val = 0 + for i, v in obj.fooVector do + val = val + v + end + return val +end +)"); + REQUIRE(!script->Diagnostics -> HasErrors()); + script->Evaluate(); + auto func = (GenericFunctionEvalValue*)script -> GetVariable(u"testFunc"); + auto funcType = func -> GetType(); + auto obj = new UserDataTestObject(); + auto parameter = new UserDataValue(HashedString::ConstHash("testObject"), obj); + auto result = script->CallFunction(u"testFunc", {parameter}); + REQUIRE(result->EvaluateInteger() == 55); + delete obj; + delete parameter; + delete script; + delete func; + delete result; + UserDataStorage::ClearTypes(); +} #endif