Implemented generic for loops
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2019-06-26 16:19:34 +02:00
parent cfd558b718
commit d86e9ba8ae
18 changed files with 325 additions and 44 deletions

View File

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

View File

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

View File

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