Support having no getter/setters on a userdata field
continuous-integration/drone/push Build is passing Details

This commit is contained in:
Deukhoofd 2019-06-15 15:38:52 +02:00
parent 7c345d85e8
commit 5cd05053e1
No known key found for this signature in database
GPG Key ID: B4C087AC81641654
5 changed files with 41 additions and 7 deletions

View File

@ -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<StringScriptType>(index -> GetType());
auto field = dynamic_pointer_cast<UserDataScriptType>(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());
}

View File

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

View File

@ -23,6 +23,8 @@ enum class DiagnosticCode{
ConditionNotABool,
InvalidTableValueType,
InvalidTypeName,
UserDataFieldNoGetter,
UserDataFieldNoSetter
};
#endif //PORYGONLANG_DIAGNOSTICCODE_HPP

View File

@ -9,9 +9,9 @@
class UserDataField {
shared_ptr<ScriptType> _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<ScriptType>(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);
}

View File

@ -28,6 +28,10 @@ public:
return _userData->ContainsField(str->GetHashValue());
}
UserDataField* GetField(uint32_t id){
return _userData -> GetField(id);
}
shared_ptr<ScriptType> GetIndexedType(ScriptType* indexer) final{
auto stringKey = (StringScriptType*)indexer;
if (stringKey->IsKnownAtBind()){