Handling for when userdata is not defined yet, but might be defined later
continuous-integration/drone/push Build is passing Details

This commit is contained in:
Deukhoofd 2019-08-25 11:53:37 +02:00
parent 5b7da77027
commit 4c97a7c811
Signed by: Deukhoofd
GPG Key ID: ADF2E9256009EDCE
7 changed files with 82 additions and 24 deletions

View File

@ -29,6 +29,8 @@ namespace Porygon::Parser {
inline const Token *Parser::Next() { inline const Token *Parser::Next() {
this->_position++; this->_position++;
if (_position > _tokens.size())
return nullptr;
return this->_tokens[_position - 1]; return this->_tokens[_position - 1];
} }
@ -183,11 +185,14 @@ namespace Porygon::Parser {
auto block = this->ParseBlock({TokenKind::EndKeyword}); auto block = this->ParseBlock({TokenKind::EndKeyword});
auto start = current->GetStartPosition(); auto start = current->GetStartPosition();
auto end = block->GetEndPosition();
if (hasErrors) { if (hasErrors) {
return new ParsedBadStatement(start, block->GetEndPosition() - start); delete block;
return new ParsedBadStatement(start, end - start);
} }
if (block->GetKind() == ParsedStatementKind::Bad) { if (block->GetKind() == ParsedStatementKind::Bad) {
return new ParsedBadStatement(start, block->GetEndPosition() - start); delete block;
return new ParsedBadStatement(start, end - start);
} }
auto functionIdentifier = dynamic_cast<const IdentifierToken*>(functionIdentifierToken)->GetValue(); auto functionIdentifier = dynamic_cast<const IdentifierToken*>(functionIdentifierToken)->GetValue();
return new ParsedFunctionDeclarationStatement(HashedString(functionIdentifier), parameters, return new ParsedFunctionDeclarationStatement(HashedString(functionIdentifier), parameters,

View File

@ -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;
}

View File

@ -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

View File

@ -11,12 +11,12 @@ namespace Porygon::UserData {
void RegisterUserDataField(uint32_t typeId, uint32_t fieldId, UserDataField *field) { void RegisterUserDataField(uint32_t typeId, uint32_t fieldId, UserDataField *field) {
auto ud = UserDataStorage::GetUserDataType(typeId); auto ud = UserDataStorage::GetUserDataType(typeId);
ud->CreateField(fieldId, field); ud->Get()->CreateField(fieldId, field);
} }
int32_t GetUserDataFieldCount(uint32_t typeId) { int32_t GetUserDataFieldCount(uint32_t typeId) {
auto ud = UserDataStorage::GetUserDataType(typeId); auto ud = UserDataStorage::GetUserDataType(typeId);
return ud->GetFieldCount(); return ud->Get()->GetFieldCount();
} }
} }
} }

View File

@ -10,14 +10,19 @@
namespace Porygon::UserData { namespace Porygon::UserData {
class UserDataScriptType : public ScriptType { class UserDataScriptType : public ScriptType {
UserData* _userData; RetrievedUserData* _userData;
public: public:
explicit UserDataScriptType(uint32_t id) : ScriptType(TypeClass::UserData) { explicit UserDataScriptType(uint32_t id) :
_userData = UserDataStorage::GetUserDataType(id); _userData(UserDataStorage::GetUserDataType(id)),
ScriptType(TypeClass::UserData) {
} }
explicit UserDataScriptType(UserData* ud) : ScriptType(TypeClass::UserData) { explicit UserDataScriptType(UserData* ud) :
_userData = ud; _userData(new RetrievedUserData(ud)),
ScriptType(TypeClass::UserData) {}
~UserDataScriptType() final{
delete _userData;
} }
bool CanBeIndexedWith(const ScriptType *indexer) const final { bool CanBeIndexedWith(const ScriptType *indexer) const final {
@ -27,27 +32,27 @@ namespace Porygon::UserData {
auto str = dynamic_cast<const StringScriptType*>(indexer); auto str = dynamic_cast<const StringScriptType*>(indexer);
if (!str->IsKnownAtBind()) if (!str->IsKnownAtBind())
return false; return false;
return _userData->ContainsField(str->GetHashValue()); return _userData->Get()->ContainsField(str->GetHashValue());
} }
[[nodiscard]] inline bool CanBeIndexedWithIdentifier(uint32_t hash) const final { [[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{ [[nodiscard]] inline UserDataField *GetField(uint32_t id) const{
return _userData->GetField(id); return _userData->Get()->GetField(id);
} }
shared_ptr<const ScriptType> GetIndexedType(const ScriptType *indexer) const final { shared_ptr<const ScriptType> GetIndexedType(const ScriptType *indexer) const final {
auto stringKey = dynamic_cast<const StringScriptType*>(indexer); auto stringKey = dynamic_cast<const StringScriptType*>(indexer);
if (stringKey->IsKnownAtBind()) { if (stringKey->IsKnownAtBind()) {
return _userData->GetField(stringKey->GetHashValue())->GetType(); return _userData->Get()->GetField(stringKey->GetHashValue())->GetType();
} }
throw "TODO: indexing with dynamic keys"; throw "TODO: indexing with dynamic keys";
} }
[[nodiscard]] inline shared_ptr<const ScriptType> GetIndexedType(uint32_t hash) const final { [[nodiscard]] inline shared_ptr<const ScriptType> GetIndexedType(uint32_t hash) const final {
return _userData->GetField(hash)->GetType(); return _userData->Get()->GetField(hash)->GetType();
} }
}; };
} }

View File

@ -3,8 +3,9 @@
#define PORYGONLANG_USERDATASTORAGE_HPP #define PORYGONLANG_USERDATASTORAGE_HPP
#include <unordered_map> #include <unordered_map>
#include "UserData.hpp"
#include <mutex> #include <mutex>
#include "UserData.hpp"
#include "RetrievedUserData.hpp"
namespace Porygon::UserData { namespace Porygon::UserData {
class UserDataStorage { class UserDataStorage {
@ -43,8 +44,15 @@ namespace Porygon::UserData {
return UserDataStorage::_internal._userData.find(i) != UserDataStorage::_internal._userData.end(); return UserDataStorage::_internal._userData.find(i) != UserDataStorage::_internal._userData.end();
} }
inline static UserData* GetUserDataType(uint32_t i) { 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 UserDataStorage::_internal._userData.at(i).get();
return nullptr;
} }
}; };
} }

View File

@ -9,11 +9,11 @@
namespace Porygon::UserData { namespace Porygon::UserData {
class UserDataValue : public Evaluation::EvalValue { class UserDataValue : public Evaluation::EvalValue {
const UserData* _userData; RetrievedUserData* _userData;
void *_obj; void *_obj;
public: public:
UserDataValue(const UserData* userData, void *obj) UserDataValue(UserData* userData, void *obj)
: _userData(userData) { : _userData(new RetrievedUserData(userData)) {
_obj = obj; _obj = obj;
} }
@ -22,6 +22,10 @@ namespace Porygon::UserData {
_obj = obj; _obj = obj;
} }
~UserDataValue(){
delete _userData;
}
[[nodiscard]] [[nodiscard]]
inline TypeClass GetTypeClass() const final { inline TypeClass GetTypeClass() const final {
return TypeClass::UserData; return TypeClass::UserData;
@ -35,7 +39,11 @@ namespace Porygon::UserData {
[[nodiscard]] [[nodiscard]]
inline Evaluation::EvalValue* Clone() const final { 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]] [[nodiscard]]
@ -45,19 +53,19 @@ namespace Porygon::UserData {
const Evaluation::EvalValue* IndexValue(const EvalValue *val) const final { const Evaluation::EvalValue* IndexValue(const EvalValue *val) const final {
auto fieldId = val->GetHashCode(); auto fieldId = val->GetHashCode();
auto field = _userData->GetField(fieldId); auto field = _userData->Get()->GetField(fieldId);
return field->Get(_obj); return field->Get(_obj);
} }
[[nodiscard]] [[nodiscard]]
inline const EvalValue* IndexValue(uint32_t hash) const final { inline const EvalValue* IndexValue(uint32_t hash) const final {
auto field = _userData->GetField(hash); auto field = _userData->Get()->GetField(hash);
return field->Get(_obj); return field->Get(_obj);
} }
void SetIndexValue(const EvalValue *key, const EvalValue* value) const final { void SetIndexValue(const EvalValue *key, const EvalValue* value) const final {
auto fieldId = key->GetHashCode(); auto fieldId = key->GetHashCode();
auto field = _userData->GetField(fieldId); auto field = _userData->Get()->GetField(fieldId);
field->Set(_obj, value); field->Set(_obj, value);
delete value; delete value;
} }