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) { BoundStatement *Binder::BindIndexAssignmentStatement(const ParsedStatement *statement) {
auto s = (ParsedIndexAssignmentStatement*) 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()); auto valueExpression = this -> BindExpression(s->GetValueExpression());
if (boundIndexExpression->GetType()->operator!=(valueExpression->GetType().get())){ if (boundIndexExpression->GetType()->operator!=(valueExpression->GetType().get())){
this -> _scriptData -> Diagnostics -> LogError(DiagnosticCode::InvalidTableValueType, statement->GetStartPosition(), statement->GetLength()); this -> _scriptData -> Diagnostics -> LogError(DiagnosticCode::InvalidTableValueType, statement->GetStartPosition(), statement->GetLength());
return new BoundBadStatement(); return new BoundBadStatement();
} }
return new BoundIndexAssignmentStatement(boundIndexExpression, valueExpression); return new BoundIndexAssignmentStatement(boundIndexExpression, valueExpression);
} }
@ -206,7 +207,7 @@ BoundExpression* Binder::BindExpression(const ParsedExpression* expression){
return this->BindFunctionCall((FunctionCallExpression*)expression); return this->BindFunctionCall((FunctionCallExpression*)expression);
case ParsedExpressionKind ::Indexer: case ParsedExpressionKind ::Indexer:
return this->BindIndexExpression((IndexExpression*)expression); return this->BindIndexExpression((IndexExpression*)expression, false);
case ParsedExpressionKind::NumericalTable: case ParsedExpressionKind::NumericalTable:
return this -> BindNumericalTableExpression((ParsedNumericalTableExpression*)expression); return this -> BindNumericalTableExpression((ParsedNumericalTableExpression*)expression);
case ParsedExpressionKind ::Table: case ParsedExpressionKind ::Table:
@ -415,15 +416,34 @@ BoundExpression* Binder::BindFunctionCall(const FunctionCallExpression* expressi
expression->GetStartPosition(), expression->GetLength()); 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 indexer = this->BindExpression(expression->GetIndexer());
auto index = this->BindExpression(expression->GetIndex()); 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(), this->_scriptData->Diagnostics->LogError(DiagnosticCode::CantIndex, index->GetStartPosition(),
index->GetLength()); index->GetLength());
return new BoundBadExpression(expression->GetStartPosition(), expression->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()); auto resultType = indexer->GetType()->GetIndexedType(index->GetType().get());
return new BoundIndexExpression(indexer, index, resultType, expression->GetStartPosition(), expression->GetLength()); return new BoundIndexExpression(indexer, index, resultType, expression->GetStartPosition(), expression->GetLength());
} }

View File

@ -30,7 +30,7 @@ class Binder {
BoundExpression *BindBinaryOperator(const BinaryExpression *expression); BoundExpression *BindBinaryOperator(const BinaryExpression *expression);
BoundExpression *BindUnaryOperator(const UnaryExpression *expression); BoundExpression *BindUnaryOperator(const UnaryExpression *expression);
BoundExpression *BindFunctionCall(const FunctionCallExpression *expression); BoundExpression *BindFunctionCall(const FunctionCallExpression *expression);
BoundExpression *BindIndexExpression(const IndexExpression *expression); BoundExpression *BindIndexExpression(const IndexExpression *expression, bool setter);
BoundExpression *BindNumericalTableExpression(const ParsedNumericalTableExpression *expression); BoundExpression *BindNumericalTableExpression(const ParsedNumericalTableExpression *expression);
BoundExpression *BindTableExpression(const ParsedTableExpression * expression); BoundExpression *BindTableExpression(const ParsedTableExpression * expression);
public: public:

View File

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

View File

@ -9,9 +9,9 @@
class UserDataField { class UserDataField {
shared_ptr<ScriptType> _type; shared_ptr<ScriptType> _type;
EvalValue* (*_get)(void* obj); EvalValue* (*_get)(void* obj);
void (*_set)(void* obj, EvalValue*); void (*_set)(void* obj, EvalValue* val);
public: 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); _type = shared_ptr<ScriptType>(type);
_get = getter; _get = getter;
_set = setter; _set = setter;
@ -21,10 +21,18 @@ public:
return _type; return _type;
} }
bool HasGetter(){
return _get != nullptr;
}
EvalValue* Get(void* obj){ EvalValue* Get(void* obj){
return this ->_get(obj); return this ->_get(obj);
} }
bool HasSetter(){
return _set != nullptr;
}
void Set(void* obj, EvalValue* val){ void Set(void* obj, EvalValue* val){
this->_set(obj, val); this->_set(obj, val);
} }

View File

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