Implemented generic for loops
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
@@ -46,6 +46,8 @@ namespace Porygon::Binder {
|
||||
return this->BindConditionalStatement(statement);
|
||||
case ParsedStatementKind::NumericalFor:
|
||||
return this->BindNumericalForStatement(statement);
|
||||
case ParsedStatementKind::GenericFor:
|
||||
return this -> BindGenericForStatement(statement);
|
||||
case ParsedStatementKind::Bad:
|
||||
return new BoundBadStatement();
|
||||
}
|
||||
@@ -105,7 +107,7 @@ namespace Porygon::Binder {
|
||||
return new BoundIndexAssignmentStatement(indexable, valueExpression);
|
||||
}
|
||||
|
||||
std::shared_ptr<ScriptType> ParseTypeIdentifier(HashedString s) {
|
||||
std::shared_ptr<ScriptType> ParseTypeIdentifier(const HashedString& s) {
|
||||
auto hash = s.GetHash();
|
||||
switch (hash) {
|
||||
case HashedString::ConstHash("number"):
|
||||
@@ -253,6 +255,46 @@ namespace Porygon::Binder {
|
||||
return new BoundNumericalForStatement(variableKey.GetKey(), start, end, step, block);
|
||||
}
|
||||
|
||||
BoundStatement *Binder::BindGenericForStatement(const ParsedStatement *statement) {
|
||||
auto genericFor = (ParsedGenericForStatement*) statement;
|
||||
auto boundIterator = BindExpression(genericFor -> GetIteratorExpression());
|
||||
const auto& itType = boundIterator -> GetType();
|
||||
if (!itType -> CanBeIterated()){
|
||||
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::CantIterateExpression, statement->GetStartPosition(),
|
||||
statement->GetLength());
|
||||
return new BoundBadStatement();
|
||||
}
|
||||
auto keyType = itType -> GetIteratorKeyType();
|
||||
auto keyIdentifier = genericFor -> GetKeyIdentifier();
|
||||
this -> _scope -> GoInnerScope();
|
||||
auto keyVariableAssignment = this -> _scope -> CreateExplicitLocal(keyIdentifier, keyType);
|
||||
if (keyVariableAssignment.GetResult() != VariableAssignmentResult::Ok){
|
||||
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::CantAssignVariable, statement->GetStartPosition(),
|
||||
statement->GetLength());
|
||||
return new BoundBadStatement();
|
||||
}
|
||||
auto keyVariable = keyVariableAssignment.GetKey();
|
||||
|
||||
auto valueIdentifier = genericFor -> GetValueIdentifier();
|
||||
auto isValueVariableDefined = valueIdentifier.GetHash() != 0;
|
||||
BoundVariableKey* valueVariable = nullptr;
|
||||
if (isValueVariableDefined){
|
||||
auto valueType = itType -> GetIndexedType(keyType.get());
|
||||
auto valueVariableAssignment = this -> _scope -> CreateExplicitLocal(valueIdentifier, valueType);
|
||||
if (valueVariableAssignment.GetResult() != VariableAssignmentResult::Ok){
|
||||
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::CantAssignVariable, statement->GetStartPosition(),
|
||||
statement->GetLength());
|
||||
return new BoundBadStatement();
|
||||
}
|
||||
valueVariable = valueVariableAssignment.GetKey();
|
||||
}
|
||||
auto boundBlock = this -> BindBlockStatement(genericFor -> GetBlock());
|
||||
|
||||
this -> _scope -> GoOuterScope();
|
||||
|
||||
return new BoundGenericForStatement(keyVariable, valueVariable, boundIterator, boundBlock);
|
||||
}
|
||||
|
||||
/////////////////
|
||||
// Expressions //
|
||||
/////////////////
|
||||
@@ -629,5 +671,4 @@ namespace Porygon::Binder {
|
||||
return new BoundTableExpression((BoundBlockStatement *) block, tableType, expression->GetStartPosition(),
|
||||
expression->GetLength());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ namespace Porygon::Binder {
|
||||
BoundStatement *BindReturnStatement(const ParsedStatement *statement);
|
||||
BoundStatement *BindConditionalStatement(const ParsedStatement *statement);
|
||||
BoundStatement *BindNumericalForStatement(const ParsedStatement *statement);
|
||||
BoundStatement *BindGenericForStatement(const ParsedStatement *statement);
|
||||
|
||||
// Expressions
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ namespace Porygon::Binder {
|
||||
Return,
|
||||
Conditional,
|
||||
NumericalFor,
|
||||
GenericFor,
|
||||
};
|
||||
|
||||
class BoundStatement {
|
||||
@@ -247,6 +248,48 @@ namespace Porygon::Binder {
|
||||
return _block;
|
||||
}
|
||||
};
|
||||
|
||||
class BoundGenericForStatement : public BoundStatement {
|
||||
const BoundVariableKey* _keyIdentifier;
|
||||
const BoundVariableKey* _valueIdentifier;
|
||||
const BoundExpression* _iterator;
|
||||
|
||||
const BoundStatement *_block;
|
||||
public:
|
||||
explicit BoundGenericForStatement(const BoundVariableKey *keyIdentifier,
|
||||
const BoundVariableKey *valueIdentifier,
|
||||
const BoundExpression *iterator, const BoundStatement *block)
|
||||
: _keyIdentifier(keyIdentifier), _valueIdentifier(valueIdentifier), _iterator(iterator), _block(block) {
|
||||
}
|
||||
|
||||
~BoundGenericForStatement() final {
|
||||
delete _keyIdentifier;
|
||||
delete _valueIdentifier;
|
||||
delete _iterator;
|
||||
delete _block;
|
||||
}
|
||||
|
||||
const BoundStatementKind GetKind() const final {
|
||||
return BoundStatementKind::GenericFor;
|
||||
}
|
||||
|
||||
const BoundVariableKey* GetKeyIdentifier() const{
|
||||
return _keyIdentifier;
|
||||
}
|
||||
|
||||
const BoundVariableKey* GetValueIdentifier() const{
|
||||
return _valueIdentifier;
|
||||
}
|
||||
|
||||
const BoundExpression* GetIterator() const{
|
||||
return _iterator;
|
||||
}
|
||||
|
||||
const BoundStatement* GetBlock() const{
|
||||
return _block;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user