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() {
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<const IdentifierToken*>(functionIdentifierToken)->GetValue();
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) {
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();
}
}
}

View File

@ -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<const StringScriptType*>(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<const ScriptType> GetIndexedType(const ScriptType *indexer) const final {
auto stringKey = dynamic_cast<const StringScriptType*>(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<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
#include <unordered_map>
#include "UserData.hpp"
#include <mutex>
#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;
}
};
}

View File

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