From 76b8ba3ebc7e77d91cc74b0b5c03e0ca87137960 Mon Sep 17 00:00:00 2001 From: Deukhoofd Date: Sun, 23 Jun 2019 15:58:14 +0200 Subject: [PATCH] Initial work on iterators, rework of variable handling by including actual string --- src/Binder/Binder.cpp | 18 ++++---- src/Binder/BoundVariables/BoundScope.cpp | 14 +++--- src/Binder/BoundVariables/BoundScope.hpp | 16 +++---- .../BoundVariables/BoundVariableKey.hpp | 9 ++-- src/Evaluator/BinaryEvaluation.cpp | 4 +- src/Evaluator/EvalValues/EvalValue.cpp | 2 +- src/Evaluator/EvalValues/EvalValue.hpp | 2 +- src/Evaluator/EvalValues/NumericEvalValue.hpp | 6 +++ src/Evaluator/EvalValues/StringEvalValue.hpp | 4 +- src/Evaluator/EvalValues/TableEvalValue.hpp | 25 +++++++---- .../EvaluationScope/EvaluationScope.cpp | 4 +- .../EvaluationScope/EvaluationScope.hpp | 8 ++-- src/Evaluator/Evaluator.cpp | 10 +++-- src/Evaluator/Evaluator.hpp | 4 +- src/Evaluator/Iterator/Iterator.cpp | 2 + src/Evaluator/Iterator/Iterator.hpp | 43 +++++++++++++++++++ src/Script.cpp | 11 ++--- src/Script.hpp | 4 +- src/TableScriptType.hpp | 10 ++--- src/Utilities/HashedString.hpp | 30 +++++++++++-- src/Utilities/StringUtils.hpp | 21 +++++++++ tests/integration/IndexTests.cpp | 4 +- tests/integration/StringOperationsTests.cpp | 6 +-- tests/integration/TablesTests.cpp | 4 +- tests/integration/VariablesTests.cpp | 2 +- 25 files changed, 185 insertions(+), 78 deletions(-) create mode 100644 src/Evaluator/Iterator/Iterator.cpp create mode 100644 src/Evaluator/Iterator/Iterator.hpp create mode 100644 src/Utilities/StringUtils.hpp diff --git a/src/Binder/Binder.cpp b/src/Binder/Binder.cpp index c9274a4..ae5a077 100644 --- a/src/Binder/Binder.cpp +++ b/src/Binder/Binder.cpp @@ -72,8 +72,8 @@ namespace Porygon::Binder { auto boundExpression = this->BindExpression(s->GetExpression()); VariableAssignment assignment = s->IsLocal() ? - this->_scope->CreateExplicitLocal(s->GetIdentifier().GetHash(), boundExpression->GetType()) - : this->_scope->AssignVariable(s->GetIdentifier().GetHash(), boundExpression->GetType()); + this->_scope->CreateExplicitLocal(s->GetIdentifier(), boundExpression->GetType()) + : this->_scope->AssignVariable(s->GetIdentifier(), boundExpression->GetType()); if (assignment.GetResult() == VariableAssignmentResult::Ok) { auto key = assignment.GetKey(); return new BoundAssignmentStatement(key, boundExpression); @@ -139,7 +139,7 @@ namespace Porygon::Binder { return new BoundBadStatement(); } parameterTypes.at(i) = parsedType; - auto parameterAssignment = this->_scope->CreateExplicitLocal(var->GetIdentifier().GetHash(), parsedType); + auto parameterAssignment = this->_scope->CreateExplicitLocal(var->GetIdentifier(), parsedType); if (parameterAssignment.GetResult() == VariableAssignmentResult::Ok) { parameterKeys.at(i) = std::shared_ptr(parameterAssignment.GetKey()); } else { @@ -153,7 +153,7 @@ namespace Porygon::Binder { auto type = make_shared(returnType, parameterTypes, parameterKeys, scopeIndex); this->_currentFunction = type; - auto assignment = this->_scope->AssignVariable(identifier.GetHash(), type); + auto assignment = this->_scope->AssignVariable(identifier, type); if (assignment.GetResult() != VariableAssignmentResult::Ok) { this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::CantAssignVariable, statement->GetStartPosition(), statement->GetLength()); @@ -242,7 +242,7 @@ namespace Porygon::Binder { } this -> _scope ->GoInnerScope(); - auto variableKey = this -> _scope ->CreateExplicitLocal(identifier.GetHash(), make_shared(true, false)); + auto variableKey = this -> _scope ->CreateExplicitLocal(identifier, make_shared(true, false)); if (variableKey.GetResult() != VariableAssignmentResult::Ok){ this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::CantAssignVariable, statement->GetStartPosition(), statement->GetLength()); @@ -300,15 +300,15 @@ namespace Porygon::Binder { BoundExpression *Binder::BindVariableExpression(const VariableExpression *expression) { auto key = expression->GetValue(); - auto scope = this->_scope->Exists(key.GetHash()); + auto scope = this->_scope->Exists(key); if (scope == -1) { this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::VariableNotFound, expression->GetStartPosition(), expression->GetLength()); return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); } - auto var = this->_scope->GetVariable(scope, key.GetHash()); + auto var = this->_scope->GetVariable(scope, key); auto type = var->GetType(); - return new BoundVariableExpression(new BoundVariableKey(key.GetHash(), scope, false), type, + return new BoundVariableExpression(new BoundVariableKey(key, scope, false), type, expression->GetStartPosition(), expression->GetLength()); } @@ -616,7 +616,7 @@ namespace Porygon::Binder { } BoundExpression *Binder::BindTableExpression(const ParsedTableExpression *expression) { - auto tableScope = new unordered_map(); + auto tableScope = new map(); auto innerScope = new BoundScope(tableScope); auto currentScope = this->_scope; this->_scope = innerScope; diff --git a/src/Binder/BoundVariables/BoundScope.cpp b/src/Binder/BoundVariables/BoundScope.cpp index 0aad208..12a5d3d 100644 --- a/src/Binder/BoundVariables/BoundScope.cpp +++ b/src/Binder/BoundVariables/BoundScope.cpp @@ -4,11 +4,11 @@ #include "BoundScope.hpp" namespace Porygon::Binder { - BoundScope::BoundScope(unordered_map *tableScope) { + BoundScope::BoundScope(map *tableScope) { _tableScope = tableScope; _currentScope = 1; _lastCreatedScope = 1; - auto localUpmostScope = new unordered_map(); + auto localUpmostScope = new map(); _localScope.push_back(localUpmostScope); } @@ -25,7 +25,7 @@ namespace Porygon::Binder { _lastCreatedScope++; _currentScope = _lastCreatedScope; if (_localScope.size() < _currentScope) { - auto innerScope = new unordered_map(); + auto innerScope = new map(); _localScope.push_back(innerScope); } } @@ -39,7 +39,7 @@ namespace Porygon::Binder { _currentScope--; } - int BoundScope::Exists(int key) { + int BoundScope::Exists(Utilities::HashedString key) { auto found = this->_tableScope->find(key); if (found != _tableScope->end()) { return 0; @@ -54,7 +54,7 @@ namespace Porygon::Binder { return -1; } - BoundVariable *BoundScope::GetVariable(uint32_t scope, uint32_t identifier) { + BoundVariable *BoundScope::GetVariable(uint32_t scope, Utilities::HashedString identifier) { if (scope == 0) { auto find = this->_tableScope->find(identifier); if (find != _tableScope->end()) { @@ -71,7 +71,7 @@ namespace Porygon::Binder { } } - VariableAssignment BoundScope::CreateExplicitLocal(uint32_t identifier, std::shared_ptr type) { + VariableAssignment BoundScope::CreateExplicitLocal(Utilities::HashedString identifier, std::shared_ptr type) { auto scope = this->_localScope.at(this->_currentScope - 1); if (scope->find(identifier) != scope->end()) { return VariableAssignment(VariableAssignmentResult::ExplicitLocalVariableExists, nullptr); @@ -81,7 +81,7 @@ namespace Porygon::Binder { new BoundVariableKey(identifier, this->_currentScope, true)); } - VariableAssignment BoundScope::AssignVariable(uint32_t identifier, const std::shared_ptr &type) { + VariableAssignment BoundScope::AssignVariable(Utilities::HashedString identifier, const std::shared_ptr &type) { int exists = this->Exists(identifier); if (exists == -1) { // Creation diff --git a/src/Binder/BoundVariables/BoundScope.hpp b/src/Binder/BoundVariables/BoundScope.hpp index 6fe602f..1af538b 100644 --- a/src/Binder/BoundVariables/BoundScope.hpp +++ b/src/Binder/BoundVariables/BoundScope.hpp @@ -3,7 +3,7 @@ #define PORYGONLANG_BOUNDSCOPE_HPP #include -#include +#include #include #include #include "BoundVariable.hpp" @@ -15,12 +15,12 @@ using namespace std; namespace Porygon::Binder { class BoundScope { - unordered_map *_tableScope; - vector *> _localScope; + map *_tableScope; + vector *> _localScope; int _currentScope; int _lastCreatedScope; public: - explicit BoundScope(unordered_map *tableScope); + explicit BoundScope(map *tableScope); ~BoundScope(); @@ -28,13 +28,13 @@ namespace Porygon::Binder { void GoOuterScope(); - int Exists(int key); + int Exists(Utilities::HashedString key); - BoundVariable *GetVariable(uint32_t scope, uint32_t identifier); + BoundVariable *GetVariable(uint32_t scope, Utilities::HashedString identifier); - VariableAssignment CreateExplicitLocal(uint32_t identifier, std::shared_ptr type); + VariableAssignment CreateExplicitLocal(Utilities::HashedString identifier, std::shared_ptr type); - VariableAssignment AssignVariable(uint32_t identifier, const std::shared_ptr &type); + VariableAssignment AssignVariable(Utilities::HashedString identifier, const std::shared_ptr &type); size_t GetLocalVariableCount() { return _localScope.size(); diff --git a/src/Binder/BoundVariables/BoundVariableKey.hpp b/src/Binder/BoundVariables/BoundVariableKey.hpp index bd84c53..b08a8ae 100644 --- a/src/Binder/BoundVariables/BoundVariableKey.hpp +++ b/src/Binder/BoundVariables/BoundVariableKey.hpp @@ -3,10 +3,11 @@ #define PORYGONLANG_BOUNDVARIABLEKEY_HPP #include +#include "../../Utilities/HashedString.hpp" namespace Porygon::Binder { class BoundVariableKey { - const int _identifier; + const Utilities::HashedString _identifier; const unsigned int _scopeId; const bool _isCreation; const uint64_t _hash; @@ -18,14 +19,14 @@ namespace Porygon::Binder { } public: - BoundVariableKey(int id, unsigned int scope, bool creation) + BoundVariableKey(Utilities::HashedString id, unsigned int scope, bool creation) : _identifier(id), _scopeId(scope), _isCreation(creation), - _hash(KnuthsHash(id, scope)) {} + _hash(KnuthsHash(id.GetHash(), scope)) {} - const int GetIdentifier() const { + const Utilities::HashedString GetIdentifier() const { return _identifier; } diff --git a/src/Evaluator/BinaryEvaluation.cpp b/src/Evaluator/BinaryEvaluation.cpp index 80210b4..a119a52 100644 --- a/src/Evaluator/BinaryEvaluation.cpp +++ b/src/Evaluator/BinaryEvaluation.cpp @@ -83,9 +83,9 @@ namespace Porygon::Evaluation { throw; std::basic_ostringstream stringStream; auto left = this->EvaluateStringExpression(expression->GetLeft()); - stringStream << *left->EvaluateString(); + stringStream << left->EvaluateString(); auto right = this->EvaluateExpression(expression->GetRight()); - stringStream << *right->EvaluateString(); + stringStream << right->EvaluateString(); return make_shared(stringStream.str()); } } \ No newline at end of file diff --git a/src/Evaluator/EvalValues/EvalValue.cpp b/src/Evaluator/EvalValues/EvalValue.cpp index 1c2f52c..681c927 100644 --- a/src/Evaluator/EvalValues/EvalValue.cpp +++ b/src/Evaluator/EvalValues/EvalValue.cpp @@ -24,7 +24,7 @@ namespace Porygon::Evaluation { } const char16_t *EvaluateEvalValueString(EvalValue *v) { - return v->EvaluateString()->c_str(); + return (new u16string(v->EvaluateString()))->c_str(); } diff --git a/src/Evaluator/EvalValues/EvalValue.hpp b/src/Evaluator/EvalValues/EvalValue.hpp index 745d78a..e7c71b8 100644 --- a/src/Evaluator/EvalValues/EvalValue.hpp +++ b/src/Evaluator/EvalValues/EvalValue.hpp @@ -37,7 +37,7 @@ namespace Porygon::Evaluation { throw EvaluationException("Can't evaluate this EvalValue as bool."); } - virtual const std::u16string *EvaluateString() const { + virtual const std::u16string EvaluateString() const { throw EvaluationException("Can't evaluate this EvalValue as string."); } diff --git a/src/Evaluator/EvalValues/NumericEvalValue.hpp b/src/Evaluator/EvalValues/NumericEvalValue.hpp index 29430b1..ba63e34 100644 --- a/src/Evaluator/EvalValues/NumericEvalValue.hpp +++ b/src/Evaluator/EvalValues/NumericEvalValue.hpp @@ -4,6 +4,8 @@ #include #include "EvalValue.hpp" +#include "../../Utilities/StringUtils.hpp" + namespace Porygon::Evaluation { class NumericEvalValue : public EvalValue { @@ -58,6 +60,10 @@ namespace Porygon::Evaluation { return _value; } + const std::u16string EvaluateString() const final{ + return Utilities::StringUtils::IntToString(_value); + } + const shared_ptr Clone() const final { return make_shared(_value); } diff --git a/src/Evaluator/EvalValues/StringEvalValue.hpp b/src/Evaluator/EvalValues/StringEvalValue.hpp index b8ce918..c782946 100644 --- a/src/Evaluator/EvalValues/StringEvalValue.hpp +++ b/src/Evaluator/EvalValues/StringEvalValue.hpp @@ -28,8 +28,8 @@ namespace Porygon::Evaluation { return this->_hash == b->GetHashCode(); }; - const u16string *EvaluateString() const final { - return &_value; + const u16string EvaluateString() const final { + return _value; } const shared_ptr Clone() const final { diff --git a/src/Evaluator/EvalValues/TableEvalValue.hpp b/src/Evaluator/EvalValues/TableEvalValue.hpp index 5f1dcd7..9a14c8b 100644 --- a/src/Evaluator/EvalValues/TableEvalValue.hpp +++ b/src/Evaluator/EvalValues/TableEvalValue.hpp @@ -1,23 +1,23 @@ #ifndef PORYGONLANG_TABLEEVALVALUE_HPP #define PORYGONLANG_TABLEEVALVALUE_HPP #include -#include +#include #include "EvalValue.hpp" using namespace std; namespace Porygon::Evaluation { class TableEvalValue : public EvalValue { - shared_ptr>> _table; + shared_ptr>> _table; size_t _hash; - explicit TableEvalValue(shared_ptr>> table, size_t hash) { + explicit TableEvalValue(shared_ptr>> table, size_t hash) { _table = std::move(table); _hash = hash; } public: - explicit TableEvalValue(shared_ptr>> table) { + explicit TableEvalValue(shared_ptr>> table) { _table = std::move(table); _hash = rand(); } @@ -39,23 +39,30 @@ namespace Porygon::Evaluation { } const shared_ptr IndexValue(EvalValue *val) const final { - auto hash = val->GetHashCode(); - return this->_table->at(hash); + const auto stringKey = val->EvaluateString(); + return this->_table->at(Utilities::HashedString(stringKey)); } const shared_ptr IndexValue(uint32_t hash) const final { - return this->_table->at(hash); + return this->_table->at(Utilities::HashedString(hash)); } const shared_ptr IndexValue(const char *val) const { auto hash = Utilities::HashedString::ConstHash(val); - return this->_table->at(hash); + return this->_table->at(Utilities::HashedString(hash)); } void SetIndexValue(EvalValue *key, const shared_ptr &value) const final { auto hash = key->GetHashCode(); - this->_table->at(hash) = value; + this->_table->at(Utilities::HashedString(hash)) = value; } + + const _Rb_tree_const_iterator>> GetTableIterator() const{ + return _table->cbegin(); + }; + const _Rb_tree_const_iterator>> GetTableIteratorEnd() const{ + return _table->cend(); + }; }; } diff --git a/src/Evaluator/EvaluationScope/EvaluationScope.cpp b/src/Evaluator/EvaluationScope/EvaluationScope.cpp index c50bf4d..d4476ba 100644 --- a/src/Evaluator/EvaluationScope/EvaluationScope.cpp +++ b/src/Evaluator/EvaluationScope/EvaluationScope.cpp @@ -3,10 +3,10 @@ #include namespace Porygon::Evaluation { - EvaluationScope::EvaluationScope(unordered_map> *scriptVariables, + EvaluationScope::EvaluationScope(map> *scriptVariables, int localVariableCount) { _scriptScope = scriptVariables; - _localScope = unordered_map>(localVariableCount); + _localScope = map>(); } void EvaluationScope::CreateVariable(const BoundVariableKey *key, const shared_ptr &value) { diff --git a/src/Evaluator/EvaluationScope/EvaluationScope.hpp b/src/Evaluator/EvaluationScope/EvaluationScope.hpp index 57e8620..9829aef 100644 --- a/src/Evaluator/EvaluationScope/EvaluationScope.hpp +++ b/src/Evaluator/EvaluationScope/EvaluationScope.hpp @@ -2,17 +2,17 @@ #ifndef PORYGONLANG_EVALUATIONSCOPE_HPP #define PORYGONLANG_EVALUATIONSCOPE_HPP -#include +#include #include #include "../EvalValues/EvalValue.hpp" using namespace Porygon::Binder; namespace Porygon::Evaluation { class EvaluationScope { - unordered_map> *_scriptScope; - unordered_map> _localScope; + map> *_scriptScope; + map> _localScope; public: - explicit EvaluationScope(unordered_map> *scriptVariables, int deepestScope); + explicit EvaluationScope(map> *scriptVariables, int deepestScope); ~EvaluationScope() = default; diff --git a/src/Evaluator/Evaluator.cpp b/src/Evaluator/Evaluator.cpp index a2d3b65..75f85a6 100644 --- a/src/Evaluator/Evaluator.cpp +++ b/src/Evaluator/Evaluator.cpp @@ -10,6 +10,7 @@ #include "../Binder/BoundExpressions/BoundTableExpression.hpp" #include "../TableScriptType.hpp" #include "../UserData/UserDataFunction.hpp" +#include "../Utilities/StringUtils.hpp" using namespace std; using namespace Porygon::Binder; @@ -388,12 +389,13 @@ namespace Porygon::Evaluation { const shared_ptr Evaluator::EvaluateNumericTableExpression(const BoundExpression *expression) { auto tableExpression = (BoundNumericalTableExpression *) expression; auto valueExpressions = tableExpression->GetExpressions(); - auto values = new unordered_map>(valueExpressions->size()); + auto values = new map>(); for (int i = 0; i < valueExpressions->size(); i++) { auto val = this->EvaluateExpression(valueExpressions->at(i)); - values->insert({i + 1, val}); + auto key = Utilities::StringUtils::IntToString(i + 1); + values->insert({Utilities::HashedString(key), val}); } - auto valuesPointer = shared_ptr>>(values); + auto valuesPointer = shared_ptr>>(values); return make_shared(valuesPointer); } @@ -401,7 +403,7 @@ namespace Porygon::Evaluation { auto tableExpression = (BoundTableExpression *) expression; auto type = dynamic_pointer_cast(tableExpression->GetType()); auto declaredVars = type->GetValues(); - auto variables = make_shared>>(declaredVars->size()); + auto variables = make_shared>>(); for (auto i : *declaredVars) { variables->insert({i.first, nullptr}); } diff --git a/src/Evaluator/Evaluator.hpp b/src/Evaluator/Evaluator.hpp index bdfb8ee..237f06f 100644 --- a/src/Evaluator/Evaluator.hpp +++ b/src/Evaluator/Evaluator.hpp @@ -16,7 +16,7 @@ using namespace std; namespace Porygon::Evaluation{ class Evaluator { shared_ptr _returnValue; - unordered_map>* _scriptVariables; + map>* _scriptVariables; bool _hasReturned; shared_ptr _lastValue; @@ -56,7 +56,7 @@ namespace Porygon::Evaluation{ const shared_ptr GetVariable(const BoundVariableExpression *expression); public: - explicit Evaluator(unordered_map>* scriptVariables){ + explicit Evaluator(map>* scriptVariables){ _scriptVariables = scriptVariables; _hasReturned = false; _returnValue = nullptr; diff --git a/src/Evaluator/Iterator/Iterator.cpp b/src/Evaluator/Iterator/Iterator.cpp new file mode 100644 index 0000000..585c565 --- /dev/null +++ b/src/Evaluator/Iterator/Iterator.cpp @@ -0,0 +1,2 @@ + +#include "Iterator.hpp" diff --git a/src/Evaluator/Iterator/Iterator.hpp b/src/Evaluator/Iterator/Iterator.hpp new file mode 100644 index 0000000..7962723 --- /dev/null +++ b/src/Evaluator/Iterator/Iterator.hpp @@ -0,0 +1,43 @@ + +#ifndef PORYGONLANG_ITERATOR_HPP +#define PORYGONLANG_ITERATOR_HPP + +#include +#include "../EvalValues/EvalValue.hpp" +#include "../EvalValues/TableEvalValue.hpp" +#include "../EvalValues/StringEvalValue.hpp" + +using namespace std; + +namespace Porygon::Evaluation{ + class Iterator { + public: + virtual shared_ptr GetCurrent() = 0; + virtual bool MoveNext() = 0; + virtual void Reset() = 0; + }; + + class TableKeyIterator : Iterator{ + _Rb_tree_const_iterator>> _iterator; + _Rb_tree_const_iterator>> _end; + public: + TableKeyIterator(shared_ptr table) + : _iterator(table->GetTableIterator()), _end(table->GetTableIteratorEnd()){} + + shared_ptr GetCurrent() final{ + return make_shared(_iterator->first.GetString()); + } + + bool MoveNext() final{ + std::advance(_iterator, 1); + return _iterator != _end; + } + + void Reset(){ + throw EvaluationException("Can't reset table key iterator"); + } + }; +} + + +#endif //PORYGONLANG_ITERATOR_HPP diff --git a/src/Script.cpp b/src/Script.cpp index 684e2a5..92a623c 100644 --- a/src/Script.cpp +++ b/src/Script.cpp @@ -25,7 +25,8 @@ Porygon::Script *Porygon::Script::Create(const string &script) { Porygon::Script::Script(const u16string& s) { Diagnostics = new Diagnostics::DiagnosticsHolder(s); _boundScript = nullptr; - _scriptVariables = new unordered_map>(0); + + _scriptVariables = new map>(); _evaluator = new Evaluator(this -> _scriptVariables); this -> Parse(s); @@ -53,7 +54,7 @@ void Porygon::Script::Parse(const u16string& script) { } lexResult.clear(); if (!Diagnostics->HasErrors()){ - unordered_map scriptScope; + map scriptScope; auto bindScope = new BoundScope(&scriptScope); this->_boundScript = Binder::Binder::Bind(this, parseResult, bindScope); for (const auto& v : scriptScope){ @@ -66,11 +67,11 @@ void Porygon::Script::Parse(const u16string& script) { } EvalValue *Porygon::Script::GetVariable(const u16string &key) { - return _scriptVariables -> at(HashedString(key).GetHash()).get(); + return _scriptVariables -> at(HashedString(key)).get(); } bool Porygon::Script::HasVariable(const u16string &key) { - auto f = _scriptVariables->find(HashedString(key).GetHash()); + auto f = _scriptVariables->find(HashedString(key)); return f != _scriptVariables->end(); } @@ -79,7 +80,7 @@ EvalValue *Porygon::Script::GetLastValue() { } bool Porygon::Script::HasFunction(const u16string &key) { - auto f = _scriptVariables->find(HashedString(key).GetHash()); + auto f = _scriptVariables->find(HashedString(key)); return f != _scriptVariables->end() && f.operator->()->second->GetTypeClass() == TypeClass ::Function; } diff --git a/src/Script.hpp b/src/Script.hpp index 414d350..7441b60 100644 --- a/src/Script.hpp +++ b/src/Script.hpp @@ -5,7 +5,7 @@ #include #include -#include +#include #include "Diagnostics/DiagnosticsHolder.hpp" #include "Binder/BoundStatements/BoundStatement.hpp" #include "Evaluator/Evaluator.hpp" @@ -18,7 +18,7 @@ using namespace Porygon::Evaluation; namespace Porygon{ class Script { Evaluator* _evaluator; - unordered_map>* _scriptVariables; + map>* _scriptVariables; Binder::BoundScriptStatement* _boundScript; shared_ptr _returnType; diff --git a/src/TableScriptType.hpp b/src/TableScriptType.hpp index ca04433..af9fdc5 100644 --- a/src/TableScriptType.hpp +++ b/src/TableScriptType.hpp @@ -6,10 +6,10 @@ namespace Porygon{ class TableScriptType : public ScriptType{ - const unordered_map* _values; + const map* _values; const int _localVariableCount; public: - explicit TableScriptType(unordered_map* values, int localVariableCount) + explicit TableScriptType(map* values, int localVariableCount) : ScriptType(TypeClass::Table), _values(values), _localVariableCount(localVariableCount) @@ -33,16 +33,16 @@ namespace Porygon{ const shared_ptr GetIndexedType(ScriptType* indexer) const final{ auto stringKey = (StringScriptType*)indexer; if (stringKey->IsKnownAtBind()){ - return _values-> at(stringKey->GetHashValue())->GetType(); + return _values-> at(Utilities::HashedString(stringKey->GetHashValue()))->GetType(); } throw "TODO: indexing with dynamic keys"; } const shared_ptr GetIndexedType(uint32_t hash) const final{ - return _values-> at(hash)->GetType(); + return _values-> at(Utilities::HashedString(hash))->GetType(); } - const unordered_map* GetValues() const{ + const map* GetValues() const{ return _values; } diff --git a/src/Utilities/HashedString.hpp b/src/Utilities/HashedString.hpp index eb3d96d..4b77c32 100644 --- a/src/Utilities/HashedString.hpp +++ b/src/Utilities/HashedString.hpp @@ -7,16 +7,28 @@ namespace Porygon::Utilities{ class HashedString{ const uint32_t _hash; + const std::u16string _string; public: - explicit HashedString(const std::u16string& s) : _hash(ConstHash(s.c_str())){ + explicit HashedString(const std::u16string& s) + : _hash(ConstHash(s.c_str())), + _string(s) + { } - explicit HashedString(char16_t const *input) : _hash(ConstHash(input)){ + explicit HashedString(char16_t const *input) + : _hash(ConstHash(input)), + _string(std::u16string(input)) + { } explicit HashedString(char const *input) : _hash(ConstHash(input)){ } - HashedString(const HashedString& b) = default; + explicit HashedString(uint32_t hash) : _hash(hash){ + } + + HashedString(const HashedString& b) :_hash(b._hash), _string(b._string){ + + }; static uint32_t constexpr ConstHash(char16_t const *input) { return *input ? @@ -34,12 +46,24 @@ namespace Porygon::Utilities{ return _hash; } + const std::u16string* GetString() const{ + return &_string; + } + bool operator==(const HashedString& b) const{ return _hash == b._hash; } bool operator!=(const HashedString& b) const{ return _hash != b._hash; } + bool operator<(const HashedString& b) const{ + return _hash < b._hash; + } + bool operator>(const HashedString& b) const{ + return _hash > b._hash; + } + + }; } diff --git a/src/Utilities/StringUtils.hpp b/src/Utilities/StringUtils.hpp new file mode 100644 index 0000000..10dc159 --- /dev/null +++ b/src/Utilities/StringUtils.hpp @@ -0,0 +1,21 @@ + +#ifndef PORYGONLANG_STRINGUTILS_HPP +#define PORYGONLANG_STRINGUTILS_HPP + +#include +#include +#include +#include +#include + +namespace Porygon::Utilities{ + class StringUtils{ + public: + static std::u16string IntToString(long const &i) { + std::wstring_convert, char16_t> conv; + return conv.from_bytes(std::to_string(i)); + } + }; +} + +#endif //PORYGONLANG_STRINGUTILS_HPP diff --git a/tests/integration/IndexTests.cpp b/tests/integration/IndexTests.cpp index 8405c16..38829bb 100644 --- a/tests/integration/IndexTests.cpp +++ b/tests/integration/IndexTests.cpp @@ -8,7 +8,7 @@ TEST_CASE( "String indexing", "[integration]" ) { REQUIRE(!script->Diagnostics -> HasErrors()); script->Evaluate(); auto lastValue = script->GetLastValue(); - REQUIRE(*lastValue->EvaluateString() == u"b"); + REQUIRE(lastValue->EvaluateString() == u"b"); delete script; } @@ -21,7 +21,7 @@ return foo.bar )"); REQUIRE(!script->Diagnostics -> HasErrors()); auto result = script->Evaluate(); - REQUIRE(*result->EvaluateString() == u"test"); + REQUIRE(result->EvaluateString() == u"test"); delete script; } diff --git a/tests/integration/StringOperationsTests.cpp b/tests/integration/StringOperationsTests.cpp index 009c65a..338d144 100644 --- a/tests/integration/StringOperationsTests.cpp +++ b/tests/integration/StringOperationsTests.cpp @@ -10,7 +10,7 @@ TEST_CASE( "Simple String", "[integration]" ) { REQUIRE(!script->Diagnostics -> HasErrors()); script->Evaluate(); auto lastValue = script->GetLastValue(); - REQUIRE(*lastValue->EvaluateString() == u"foo bar"); + REQUIRE(lastValue->EvaluateString() == u"foo bar"); delete script; } @@ -19,7 +19,7 @@ TEST_CASE( "String Concat", "[integration]" ) { REQUIRE(!script->Diagnostics -> HasErrors()); script->Evaluate(); auto lastValue = script->GetLastValue(); - REQUIRE(*lastValue->EvaluateString() == u"foobar"); + REQUIRE(lastValue->EvaluateString() == u"foobar"); delete script; } @@ -28,7 +28,7 @@ TEST_CASE( "String Concat 2", "[integration]" ) { REQUIRE(!script->Diagnostics -> HasErrors()); script->Evaluate(); auto lastValue = script->GetLastValue(); - REQUIRE(*lastValue->EvaluateString() == u"foobar"); + REQUIRE(lastValue->EvaluateString() == u"foobar"); delete script; } diff --git a/tests/integration/TablesTests.cpp b/tests/integration/TablesTests.cpp index 89c5157..926099f 100644 --- a/tests/integration/TablesTests.cpp +++ b/tests/integration/TablesTests.cpp @@ -40,7 +40,7 @@ return table[3] REQUIRE(!script->Diagnostics -> HasErrors()); auto variable = script->Evaluate(); REQUIRE(variable != nullptr); - REQUIRE(*variable->EvaluateString() == u"foo"); + REQUIRE(variable->EvaluateString() == u"foo"); delete script; } @@ -57,7 +57,7 @@ table = { auto variable = script->GetVariable(u"table"); REQUIRE(variable != nullptr); auto table = (TableEvalValue*)variable; - CHECK(*table->IndexValue("foo")->EvaluateString() == u"test"); + CHECK(table->IndexValue("foo")->EvaluateString() == u"test"); CHECK(table->IndexValue("bar")->EvaluateInteger() == 100); delete script; } diff --git a/tests/integration/VariablesTests.cpp b/tests/integration/VariablesTests.cpp index 8bdb145..ee67248 100644 --- a/tests/integration/VariablesTests.cpp +++ b/tests/integration/VariablesTests.cpp @@ -73,7 +73,7 @@ TEST_CASE( "Able to use emoji", "[integration]" ) { REQUIRE(script -> HasVariable(uR"(💩)")); auto variable = script->GetVariable(uR"(💩)"); REQUIRE(variable != nullptr); - CHECK(*variable->EvaluateString() == u"LJ"); + CHECK(variable->EvaluateString() == u"LJ"); delete script; }