Implements numeric for loops
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2019-06-22 17:35:33 +02:00
parent 694b0ac0c0
commit e472dcec1c
16 changed files with 311 additions and 23 deletions

View File

@@ -44,7 +44,8 @@ namespace Porygon::Binder {
return this->BindReturnStatement(statement);
case ParsedStatementKind::Conditional:
return this->BindConditionalStatement(statement);
case ParsedStatementKind::NumericalFor:
return this->BindNumericalForStatement(statement);
case ParsedStatementKind::Bad:
return new BoundBadStatement();
}
@@ -214,6 +215,48 @@ namespace Porygon::Binder {
return new BoundConditionalStatement(boundCondition, boundBlock, elseStatement);
}
BoundStatement *Binder::BindNumericalForStatement(const ParsedStatement *statement) {
auto forStatement = (ParsedNumericalForStatement*) statement;
auto identifier = forStatement->GetIdentifier();
auto start = this -> BindExpression(forStatement->GetStart());
auto end = this -> BindExpression(forStatement->GetEnd());
auto parsedStep = forStatement -> GetStep();
BoundExpression* step = nullptr;
if (parsedStep != nullptr){
step = this -> BindExpression(parsedStep);
}
if (start -> GetType()->GetClass() != TypeClass::Number){
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::NumericalForArgumentNotANumber, start->GetStartPosition(),
start->GetLength());
return new BoundBadStatement();
}
if (end -> GetType()->GetClass() != TypeClass::Number){
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::NumericalForArgumentNotANumber, end->GetStartPosition(),
end->GetLength());
return new BoundBadStatement();
}
if (step != nullptr && step -> GetType()->GetClass() != TypeClass::Number){
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::NumericalForArgumentNotANumber, step->GetStartPosition(),
step->GetLength());
return new BoundBadStatement();
}
this -> _scope ->GoInnerScope();
auto variableKey = this -> _scope ->CreateExplicitLocal(identifier.GetHash(), make_shared<NumericScriptType>(true, false));
if (variableKey.GetResult() != VariableAssignmentResult::Ok){
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::CantAssignVariable, statement->GetStartPosition(),
statement->GetLength());
return new BoundBadStatement();
}
auto block = this -> BindBlockStatement(forStatement->GetBlock());
this -> _scope ->GoOuterScope();
return new BoundNumericalForStatement(variableKey.GetKey(), start, end, step, block);
}
/////////////////
// Expressions //
/////////////////
BoundExpression *Binder::BindExpression(const ParsedExpression *expression) {
switch (expression->GetKind()) {
case ParsedExpressionKind::LiteralInteger:
@@ -586,4 +629,5 @@ namespace Porygon::Binder {
return new BoundTableExpression((BoundBlockStatement *) block, tableType, expression->GetStartPosition(),
expression->GetLength());
}
}

View File

@@ -18,21 +18,19 @@ namespace Porygon::Binder {
~Binder();
// Statements
BoundStatement *BindStatement(const ParsedStatement *statement);
BoundStatement *BindBlockStatement(const ParsedStatement *statement);
BoundStatement *BindExpressionStatement(const ParsedStatement *statement);
BoundStatement *BindAssignmentStatement(const ParsedStatement *statement);
BoundStatement *BindIndexAssignmentStatement(const ParsedStatement *statement);
BoundStatement *BindFunctionDeclarationStatement(const ParsedStatement *statement);
BoundStatement *BindReturnStatement(const ParsedStatement *statement);
BoundStatement *BindConditionalStatement(const ParsedStatement *statement);
BoundStatement *BindNumericalForStatement(const ParsedStatement *statement);
// Expressions
BoundExpression *BindExpression(const ParsedExpression *expression);

View File

@@ -1,6 +1,3 @@
#include <utility>
#ifndef PORYGONLANG_BOUNDSTATEMENT_HPP
#define PORYGONLANG_BOUNDSTATEMENT_HPP
@@ -23,6 +20,7 @@ namespace Porygon::Binder {
FunctionDeclaration,
Return,
Conditional,
NumericalFor,
};
class BoundStatement {
@@ -202,6 +200,53 @@ namespace Porygon::Binder {
return _elseStatement;
}
};
class BoundNumericalForStatement : public BoundStatement {
const BoundVariableKey* _identifier;
const BoundExpression *_start;
const BoundExpression *_end;
const BoundExpression *_step;
const BoundStatement *_block;
public:
explicit BoundNumericalForStatement(const BoundVariableKey* identifier, const BoundExpression *start,
const BoundExpression *end, const BoundExpression *step,
const BoundStatement *block)
: _identifier(identifier), _start(start), _end(end), _step(step), _block(block) {
}
~BoundNumericalForStatement() final {
delete _identifier;
delete _start;
delete _end;
delete _step;
delete _block;
}
const BoundStatementKind GetKind() const final {
return BoundStatementKind::NumericalFor;
}
const BoundVariableKey* GetIdentifier() const{
return _identifier;
}
const BoundExpression* GetStart() const{
return _start;
}
const BoundExpression* GetEnd() const{
return _end;
}
const BoundExpression* GetStep() const{
return _step;
}
const BoundStatement* GetBlock() const{
return _block;
}
};
}