From 4c97a7c81185b5700b9946ebf457e577a956400e Mon Sep 17 00:00:00 2001 From: Deukhoofd Date: Sun, 25 Aug 2019 11:53:37 +0200 Subject: [PATCH] Handling for when userdata is not defined yet, but might be defined later --- src/Parser/Parser.cpp | 9 +++++++-- src/UserData/RetrievedUserData.cpp | 10 ++++++++++ src/UserData/RetrievedUserData.hpp | 22 ++++++++++++++++++++++ src/UserData/UserData.cpp | 4 ++-- src/UserData/UserDataScriptType.hpp | 25 +++++++++++++++---------- src/UserData/UserDataStorage.hpp | 14 +++++++++++--- src/UserData/UserDataValue.hpp | 22 +++++++++++++++------- 7 files changed, 82 insertions(+), 24 deletions(-) create mode 100644 src/UserData/RetrievedUserData.cpp create mode 100644 src/UserData/RetrievedUserData.hpp diff --git a/src/Parser/Parser.cpp b/src/Parser/Parser.cpp index 85d1823..f405f12 100644 --- a/src/Parser/Parser.cpp +++ b/src/Parser/Parser.cpp @@ -29,6 +29,8 @@ namespace Porygon::Parser { inline const Token *Parser::Next() { this->_position++; + if (_position > _tokens.size()) + return nullptr; return this->_tokens[_position - 1]; } @@ -183,11 +185,14 @@ namespace Porygon::Parser { auto block = this->ParseBlock({TokenKind::EndKeyword}); auto start = current->GetStartPosition(); + auto end = block->GetEndPosition(); if (hasErrors) { - return new ParsedBadStatement(start, block->GetEndPosition() - start); + delete block; + return new ParsedBadStatement(start, end - start); } if (block->GetKind() == ParsedStatementKind::Bad) { - return new ParsedBadStatement(start, block->GetEndPosition() - start); + delete block; + return new ParsedBadStatement(start, end - start); } auto functionIdentifier = dynamic_cast(functionIdentifierToken)->GetValue(); return new ParsedFunctionDeclarationStatement(HashedString(functionIdentifier), parameters, diff --git a/src/UserData/RetrievedUserData.cpp b/src/UserData/RetrievedUserData.cpp new file mode 100644 index 0000000..a7030d9 --- /dev/null +++ b/src/UserData/RetrievedUserData.cpp @@ -0,0 +1,10 @@ + +#include "RetrievedUserData.hpp" +#include "UserDataStorage.hpp" + +Porygon::UserData::UserData * Porygon::UserData::RetrievedUserData::Get() { + if (_ud == nullptr){ + _ud = UserDataStorage::GetUserDataTypeRaw(_key); + } + return _ud; +} diff --git a/src/UserData/RetrievedUserData.hpp b/src/UserData/RetrievedUserData.hpp new file mode 100644 index 0000000..23a4cff --- /dev/null +++ b/src/UserData/RetrievedUserData.hpp @@ -0,0 +1,22 @@ +#ifndef PORYGONLANG_RETRIEVEDUSERDATA_HPP +#define PORYGONLANG_RETRIEVEDUSERDATA_HPP + +#include "UserData.hpp" + +namespace Porygon::UserData{ + class RetrievedUserData{ + UserData* _ud; + uint32_t _key; + public: + explicit RetrievedUserData(UserData* ud) : _ud(ud), _key(0){} + explicit RetrievedUserData(uint32_t id) : _ud(nullptr), _key(id){} + + UserData * Get(); + + inline uint32_t GetKey() const{ + return _key; + } + }; +} + +#endif //PORYGONLANG_RETRIEVEDUSERDATA_HPP diff --git a/src/UserData/UserData.cpp b/src/UserData/UserData.cpp index 7cc91ce..bbc0acb 100644 --- a/src/UserData/UserData.cpp +++ b/src/UserData/UserData.cpp @@ -11,12 +11,12 @@ namespace Porygon::UserData { void RegisterUserDataField(uint32_t typeId, uint32_t fieldId, UserDataField *field) { auto ud = UserDataStorage::GetUserDataType(typeId); - ud->CreateField(fieldId, field); + ud->Get()->CreateField(fieldId, field); } int32_t GetUserDataFieldCount(uint32_t typeId) { auto ud = UserDataStorage::GetUserDataType(typeId); - return ud->GetFieldCount(); + return ud->Get()->GetFieldCount(); } } } \ No newline at end of file diff --git a/src/UserData/UserDataScriptType.hpp b/src/UserData/UserDataScriptType.hpp index 7b043fa..0b8571f 100644 --- a/src/UserData/UserDataScriptType.hpp +++ b/src/UserData/UserDataScriptType.hpp @@ -10,14 +10,19 @@ namespace Porygon::UserData { class UserDataScriptType : public ScriptType { - UserData* _userData; + RetrievedUserData* _userData; public: - explicit UserDataScriptType(uint32_t id) : ScriptType(TypeClass::UserData) { - _userData = UserDataStorage::GetUserDataType(id); + explicit UserDataScriptType(uint32_t id) : + _userData(UserDataStorage::GetUserDataType(id)), + ScriptType(TypeClass::UserData) { } - explicit UserDataScriptType(UserData* ud) : ScriptType(TypeClass::UserData) { - _userData = ud; + explicit UserDataScriptType(UserData* ud) : + _userData(new RetrievedUserData(ud)), + ScriptType(TypeClass::UserData) {} + + ~UserDataScriptType() final{ + delete _userData; } bool CanBeIndexedWith(const ScriptType *indexer) const final { @@ -27,27 +32,27 @@ namespace Porygon::UserData { auto str = dynamic_cast(indexer); if (!str->IsKnownAtBind()) return false; - return _userData->ContainsField(str->GetHashValue()); + return _userData->Get()->ContainsField(str->GetHashValue()); } [[nodiscard]] inline bool CanBeIndexedWithIdentifier(uint32_t hash) const final { - return _userData -> ContainsField(hash); + return _userData->Get() -> ContainsField(hash); } [[nodiscard]] inline UserDataField *GetField(uint32_t id) const{ - return _userData->GetField(id); + return _userData->Get()->GetField(id); } shared_ptr GetIndexedType(const ScriptType *indexer) const final { auto stringKey = dynamic_cast(indexer); if (stringKey->IsKnownAtBind()) { - return _userData->GetField(stringKey->GetHashValue())->GetType(); + return _userData->Get()->GetField(stringKey->GetHashValue())->GetType(); } throw "TODO: indexing with dynamic keys"; } [[nodiscard]] inline shared_ptr GetIndexedType(uint32_t hash) const final { - return _userData->GetField(hash)->GetType(); + return _userData->Get()->GetField(hash)->GetType(); } }; } diff --git a/src/UserData/UserDataStorage.hpp b/src/UserData/UserDataStorage.hpp index 1945d41..dbc4fe9 100644 --- a/src/UserData/UserDataStorage.hpp +++ b/src/UserData/UserDataStorage.hpp @@ -3,8 +3,9 @@ #define PORYGONLANG_USERDATASTORAGE_HPP #include -#include "UserData.hpp" #include +#include "UserData.hpp" +#include "RetrievedUserData.hpp" namespace Porygon::UserData { class UserDataStorage { @@ -43,8 +44,15 @@ namespace Porygon::UserData { return UserDataStorage::_internal._userData.find(i) != UserDataStorage::_internal._userData.end(); } - inline static UserData* GetUserDataType(uint32_t i) { - return UserDataStorage::_internal._userData.at(i).get(); + inline static RetrievedUserData* GetUserDataType(uint32_t i){ + if (UserDataStorage::_internal._userData.count(i)) + return new RetrievedUserData(UserDataStorage::_internal._userData.at(i).get()); + return new RetrievedUserData(i); + } + inline static UserData* GetUserDataTypeRaw(uint32_t i){ + if (UserDataStorage::_internal._userData.count(i)) + return UserDataStorage::_internal._userData.at(i).get(); + return nullptr; } }; } diff --git a/src/UserData/UserDataValue.hpp b/src/UserData/UserDataValue.hpp index 5ac057b..eb909c7 100644 --- a/src/UserData/UserDataValue.hpp +++ b/src/UserData/UserDataValue.hpp @@ -9,11 +9,11 @@ namespace Porygon::UserData { class UserDataValue : public Evaluation::EvalValue { - const UserData* _userData; + RetrievedUserData* _userData; void *_obj; public: - UserDataValue(const UserData* userData, void *obj) - : _userData(userData) { + UserDataValue(UserData* userData, void *obj) + : _userData(new RetrievedUserData(userData)) { _obj = obj; } @@ -22,6 +22,10 @@ namespace Porygon::UserData { _obj = obj; } + ~UserDataValue(){ + delete _userData; + } + [[nodiscard]] inline TypeClass GetTypeClass() const final { return TypeClass::UserData; @@ -35,7 +39,11 @@ namespace Porygon::UserData { [[nodiscard]] inline Evaluation::EvalValue* Clone() const final { - return new UserDataValue(_userData, _obj); + auto ud = _userData->Get(); + if (ud == nullptr){ + return new UserDataValue(_userData->GetKey(), _obj); + } + return new UserDataValue(ud, _obj); } [[nodiscard]] @@ -45,19 +53,19 @@ namespace Porygon::UserData { const Evaluation::EvalValue* IndexValue(const EvalValue *val) const final { auto fieldId = val->GetHashCode(); - auto field = _userData->GetField(fieldId); + auto field = _userData->Get()->GetField(fieldId); return field->Get(_obj); } [[nodiscard]] inline const EvalValue* IndexValue(uint32_t hash) const final { - auto field = _userData->GetField(hash); + auto field = _userData->Get()->GetField(hash); return field->Get(_obj); } void SetIndexValue(const EvalValue *key, const EvalValue* value) const final { auto fieldId = key->GetHashCode(); - auto field = _userData->GetField(fieldId); + auto field = _userData->Get()->GetField(fieldId); field->Set(_obj, value); delete value; }