diff --git a/src/Evaluator/EvalValues/NumericalTableEvalValue.cpp b/src/Evaluator/EvalValues/NumericalTableEvalValue.cpp new file mode 100644 index 0000000..c7878c4 --- /dev/null +++ b/src/Evaluator/EvalValues/NumericalTableEvalValue.cpp @@ -0,0 +1,6 @@ +#include "NumericalTableEvalValue.hpp" +#include "../Iterator/NumericalKeyIterator.hpp" + +Porygon::Evaluation::Iterator *Porygon::Evaluation::NumericalTableEvalValue::GetKeyIterator() const { + return new NumericalKeyIterator(this); +} diff --git a/src/Evaluator/EvalValues/NumericalTableEvalValue.hpp b/src/Evaluator/EvalValues/NumericalTableEvalValue.hpp new file mode 100644 index 0000000..e351638 --- /dev/null +++ b/src/Evaluator/EvalValues/NumericalTableEvalValue.hpp @@ -0,0 +1,69 @@ +#ifndef PORYGONLANG_NUMERICALTABLEEVALVALUE_HPP +#define PORYGONLANG_NUMERICALTABLEEVALVALUE_HPP + + +#include +#include +#include "EvalValue.hpp" + +using namespace std; + +namespace Porygon::Evaluation { + class NumericalTableEvalValue : public EvalValue { + const shared_ptr>> _table; + const size_t _hash; + + explicit NumericalTableEvalValue(shared_ptr>> table, size_t hash) + : _table(std::move(table)), + _hash(hash) + { + } + + public: + explicit NumericalTableEvalValue(shared_ptr>> table) : + _table(std::move(table)), + _hash(rand()) + { + } + + const TypeClass GetTypeClass() const final { + return TypeClass::Table; + } + + const size_t GetHashCode() const final { + return _hash; + } + + const bool operator==(EvalValue *b) const final { + return this->_hash == b->GetHashCode(); + } + + const shared_ptr Clone() const final { + return shared_ptr(new NumericalTableEvalValue(_table, _hash)); + } + + const shared_ptr IndexValue(EvalValue *val) const final { + const auto index = val->EvaluateInteger() - 1; + return this->_table->at(index); + } + + const shared_ptr IndexValue(uint32_t hash) const final { + return this->_table->at(hash - 1); + } + + void SetIndexValue(EvalValue *key, const shared_ptr &value) const final { + auto index = key->EvaluateInteger(); + this->_table->at(index - 1) = value; + } + + Iterator * GetKeyIterator() const final; + + const shared_ptr>> GetTable() const{ + return _table; + }; + }; +} + +#undef iteratorKind + +#endif //PORYGONLANG_NUMERICALTABLEEVALVALUE_HPP diff --git a/src/Evaluator/Evaluator.cpp b/src/Evaluator/Evaluator.cpp index 120f26f..97d495d 100644 --- a/src/Evaluator/Evaluator.cpp +++ b/src/Evaluator/Evaluator.cpp @@ -11,6 +11,7 @@ #include "../TableScriptType.hpp" #include "../UserData/UserDataFunction.hpp" #include "../Utilities/StringUtils.hpp" +#include "EvalValues/NumericalTableEvalValue.hpp" using namespace std; using namespace Porygon::Binder; @@ -417,14 +418,13 @@ namespace Porygon::Evaluation { const shared_ptr Evaluator::EvaluateNumericTableExpression(const BoundExpression *expression) { auto tableExpression = (BoundNumericalTableExpression *) expression; auto valueExpressions = tableExpression->GetExpressions(); - auto values = new map>(); + auto values = new vector>(valueExpressions->size()); for (int i = 0; i < valueExpressions->size(); i++) { auto val = this->EvaluateExpression(valueExpressions->at(i)); - auto key = new u16string(Utilities::StringUtils::IntToString(i + 1)); - values->insert({Utilities::HashedString(key), val}); + values->at(i) = val; } - auto valuesPointer = shared_ptr>>(values); - return make_shared(valuesPointer); + auto valuesPointer = shared_ptr>>(values); + return make_shared(valuesPointer); } const shared_ptr Evaluator::EvaluateComplexTableExpression(const BoundExpression *expression) { diff --git a/src/Evaluator/Iterator/NumericalKeyIterator.cpp b/src/Evaluator/Iterator/NumericalKeyIterator.cpp new file mode 100644 index 0000000..488cc46 --- /dev/null +++ b/src/Evaluator/Iterator/NumericalKeyIterator.cpp @@ -0,0 +1 @@ +#include "NumericalKeyIterator.hpp" diff --git a/src/Evaluator/Iterator/NumericalKeyIterator.hpp b/src/Evaluator/Iterator/NumericalKeyIterator.hpp new file mode 100644 index 0000000..180feb2 --- /dev/null +++ b/src/Evaluator/Iterator/NumericalKeyIterator.hpp @@ -0,0 +1,34 @@ +#ifndef PORYGONLANG_NUMERICALKEYITERATOR_HPP +#define PORYGONLANG_NUMERICALKEYITERATOR_HPP + + +#include "Iterator.hpp" +#include "../EvalValues/NumericalTableEvalValue.hpp" +#include "../EvalValues/NumericEvalValue.hpp" + + +namespace Porygon::Evaluation{ + class NumericalKeyIterator : public Iterator{ + const shared_ptr>> _vec; + const size_t _size; + long _position = 0; + public: + explicit NumericalKeyIterator(const NumericalTableEvalValue* table) + : _vec(table->GetTable()), _size(_vec->size() + 1){} + + shared_ptr GetCurrent() final{ + return make_shared(_position); + } + + bool MoveNext() final{ + _position++; + return _position != _size; + } + + void Reset() final{ + _position = 0; + } + }; +} + +#endif //PORYGONLANG_NUMERICALKEYITERATOR_HPP diff --git a/src/Evaluator/Iterator/SimpleKeyIterator.hpp b/src/Evaluator/Iterator/SimpleKeyIterator.hpp index d855b21..26b8808 100644 --- a/src/Evaluator/Iterator/SimpleKeyIterator.hpp +++ b/src/Evaluator/Iterator/SimpleKeyIterator.hpp @@ -28,7 +28,7 @@ namespace Porygon::Evaluation{ return _iterator != _end; } - void Reset(){ + void Reset() final{ throw EvaluationException("Can't reset table key iterator"); } }; diff --git a/src/ScriptType.hpp b/src/ScriptType.hpp index 59f3241..29024e3 100644 --- a/src/ScriptType.hpp +++ b/src/ScriptType.hpp @@ -182,7 +182,7 @@ namespace Porygon{ return true; } shared_ptr GetIteratorKeyType() const final{ - return make_shared(false, 0); + return make_shared(true, false); } }; } diff --git a/tests/integration/LoopTests.cpp b/tests/integration/LoopTests.cpp index 82dd0a0..572ee98 100644 --- a/tests/integration/LoopTests.cpp +++ b/tests/integration/LoopTests.cpp @@ -63,7 +63,7 @@ end TEST_CASE( "Generic for loop over simple numerical table, get keys", "[integration]" ) { auto script = Script::Create(uR"( local table = {1, 3, 5, 7, 9} -result = "" +result = 0 for i in table do result = result + i end @@ -71,14 +71,14 @@ end REQUIRE(!script->Diagnostics -> HasErrors()); script->Evaluate(); auto var = script->GetVariable(u"result"); - REQUIRE(var->EvaluateString() == u"12345"); + REQUIRE(var->EvaluateInteger() == 15); delete script; } TEST_CASE( "Generic for loop over simple numerical table, get values", "[integration]" ) { auto script = Script::Create(uR"( local table = {1, 3, 5, 7, 9} -result = "" +result = 0 for i,v in table do result = result + v end @@ -86,7 +86,7 @@ end REQUIRE(!script->Diagnostics -> HasErrors()); script->Evaluate(); auto var = script->GetVariable(u"result"); - REQUIRE(var->EvaluateString() == u"13579"); + REQUIRE(var->EvaluateInteger() == 25); delete script; }