From 5cd05053e1ebf40c1da315207f32aa11d384b507 Mon Sep 17 00:00:00 2001 From: Deukhoofd Date: Sat, 15 Jun 2019 15:38:52 +0200 Subject: [PATCH] Support having no getter/setters on a userdata field --- src/Binder/Binder.cpp | 28 ++++++++++++++++++++++++---- src/Binder/Binder.hpp | 2 +- src/Diagnostics/DiagnosticCode.hpp | 2 ++ src/UserData/UserDataField.hpp | 12 ++++++++++-- src/UserData/UserDataScriptType.hpp | 4 ++++ 5 files changed, 41 insertions(+), 7 deletions(-) diff --git a/src/Binder/Binder.cpp b/src/Binder/Binder.cpp index 47dda2b..fbf12d4 100644 --- a/src/Binder/Binder.cpp +++ b/src/Binder/Binder.cpp @@ -73,12 +73,13 @@ BoundStatement* Binder::BindAssignmentStatement(const ParsedStatement *statement BoundStatement *Binder::BindIndexAssignmentStatement(const ParsedStatement *statement) { auto s = (ParsedIndexAssignmentStatement*) statement; - auto boundIndexExpression = this -> BindIndexExpression((IndexExpression*)s->GetIndexExpression()); + auto boundIndexExpression = this -> BindIndexExpression((IndexExpression*)s->GetIndexExpression(), true); auto valueExpression = this -> BindExpression(s->GetValueExpression()); if (boundIndexExpression->GetType()->operator!=(valueExpression->GetType().get())){ this -> _scriptData -> Diagnostics -> LogError(DiagnosticCode::InvalidTableValueType, statement->GetStartPosition(), statement->GetLength()); return new BoundBadStatement(); } + return new BoundIndexAssignmentStatement(boundIndexExpression, valueExpression); } @@ -206,7 +207,7 @@ BoundExpression* Binder::BindExpression(const ParsedExpression* expression){ return this->BindFunctionCall((FunctionCallExpression*)expression); case ParsedExpressionKind ::Indexer: - return this->BindIndexExpression((IndexExpression*)expression); + return this->BindIndexExpression((IndexExpression*)expression, false); case ParsedExpressionKind::NumericalTable: return this -> BindNumericalTableExpression((ParsedNumericalTableExpression*)expression); case ParsedExpressionKind ::Table: @@ -415,15 +416,34 @@ BoundExpression* Binder::BindFunctionCall(const FunctionCallExpression* expressi expression->GetStartPosition(), expression->GetLength()); } -BoundExpression *Binder::BindIndexExpression(const IndexExpression *expression) { +BoundExpression *Binder::BindIndexExpression(const IndexExpression *expression, bool setter) { auto indexer = this->BindExpression(expression->GetIndexer()); auto index = this->BindExpression(expression->GetIndex()); - if (!indexer->GetType()->CanBeIndexedWith(index->GetType().get())){ + auto indexerType = indexer -> GetType(); + if (!indexerType->CanBeIndexedWith(index->GetType().get())){ this->_scriptData->Diagnostics->LogError(DiagnosticCode::CantIndex, index->GetStartPosition(), index->GetLength()); return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); } + if (indexerType -> GetClass() == TypeClass::UserData){ + auto stringKey = dynamic_pointer_cast(index -> GetType()); + auto field = dynamic_pointer_cast(indexerType) -> GetField(stringKey->GetHashValue()); + if (!setter){ + if (!field->HasGetter()){ + this->_scriptData->Diagnostics->LogError(DiagnosticCode::UserDataFieldNoGetter, index->GetStartPosition(), + index->GetLength()); + return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); + } + } else{ + if (!field->HasSetter()){ + this->_scriptData->Diagnostics->LogError(DiagnosticCode::UserDataFieldNoSetter, index->GetStartPosition(), + index->GetLength()); + return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength()); + } + } + } + auto resultType = indexer->GetType()->GetIndexedType(index->GetType().get()); return new BoundIndexExpression(indexer, index, resultType, expression->GetStartPosition(), expression->GetLength()); } diff --git a/src/Binder/Binder.hpp b/src/Binder/Binder.hpp index e72c7c6..bcec464 100644 --- a/src/Binder/Binder.hpp +++ b/src/Binder/Binder.hpp @@ -30,7 +30,7 @@ class Binder { BoundExpression *BindBinaryOperator(const BinaryExpression *expression); BoundExpression *BindUnaryOperator(const UnaryExpression *expression); BoundExpression *BindFunctionCall(const FunctionCallExpression *expression); - BoundExpression *BindIndexExpression(const IndexExpression *expression); + BoundExpression *BindIndexExpression(const IndexExpression *expression, bool setter); BoundExpression *BindNumericalTableExpression(const ParsedNumericalTableExpression *expression); BoundExpression *BindTableExpression(const ParsedTableExpression * expression); public: diff --git a/src/Diagnostics/DiagnosticCode.hpp b/src/Diagnostics/DiagnosticCode.hpp index 669b520..33dfc0a 100644 --- a/src/Diagnostics/DiagnosticCode.hpp +++ b/src/Diagnostics/DiagnosticCode.hpp @@ -23,6 +23,8 @@ enum class DiagnosticCode{ ConditionNotABool, InvalidTableValueType, InvalidTypeName, + UserDataFieldNoGetter, + UserDataFieldNoSetter }; #endif //PORYGONLANG_DIAGNOSTICCODE_HPP diff --git a/src/UserData/UserDataField.hpp b/src/UserData/UserDataField.hpp index 1ff4af6..d79ad2f 100644 --- a/src/UserData/UserDataField.hpp +++ b/src/UserData/UserDataField.hpp @@ -9,9 +9,9 @@ class UserDataField { shared_ptr _type; EvalValue* (*_get)(void* obj); - void (*_set)(void* obj, EvalValue*); + void (*_set)(void* obj, EvalValue* val); public: - UserDataField(ScriptType* type, EvalValue* (*getter)(void* obj), void (*setter)(void* obj, EvalValue*)){ + UserDataField(ScriptType* type, EvalValue* (*getter)(void* obj), void (*setter)(void* obj, EvalValue* val)){ _type = shared_ptr(type); _get = getter; _set = setter; @@ -21,10 +21,18 @@ public: return _type; } + bool HasGetter(){ + return _get != nullptr; + } + EvalValue* Get(void* obj){ return this ->_get(obj); } + bool HasSetter(){ + return _set != nullptr; + } + void Set(void* obj, EvalValue* val){ this->_set(obj, val); } diff --git a/src/UserData/UserDataScriptType.hpp b/src/UserData/UserDataScriptType.hpp index 9e5d31b..d625776 100644 --- a/src/UserData/UserDataScriptType.hpp +++ b/src/UserData/UserDataScriptType.hpp @@ -28,6 +28,10 @@ public: return _userData->ContainsField(str->GetHashValue()); } + UserDataField* GetField(uint32_t id){ + return _userData -> GetField(id); + } + shared_ptr GetIndexedType(ScriptType* indexer) final{ auto stringKey = (StringScriptType*)indexer; if (stringKey->IsKnownAtBind()){