Implements support for functions with the same name, but different parameters
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2019-06-29 19:59:42 +02:00
parent 24c560b52d
commit db2d731b06
23 changed files with 362 additions and 204 deletions

View File

@@ -3,8 +3,9 @@
#include "Binder.hpp"
#include "../TableScriptType.hpp"
#include "BoundExpressions/BoundTableExpression.hpp"
#include "BoundExpressions/BoundFunctionCallExpression.hpp"
#include "../UserData/UserDataScriptType.hpp"
#include <memory>
#include "../FunctionScriptType.hpp"
using namespace Porygon::Parser;
@@ -158,19 +159,38 @@ namespace Porygon::Binder {
auto identifier = functionStatement->GetIdentifier();
auto returnType = make_shared<ScriptType>(TypeClass::Nil);
auto type = make_shared<FunctionScriptType>(returnType, parameterTypes, parameterKeys, scopeIndex);
this->_currentFunction = type;
auto option = new ScriptFunctionOption(returnType, parameterTypes, parameterKeys);
this->_currentFunction = option;
auto assignment = this->_scope->AssignVariable(identifier, type);
if (assignment.GetResult() != VariableAssignmentResult::Ok) {
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::CantAssignVariable, statement->GetStartPosition(),
statement->GetLength());
return new BoundBadStatement();
shared_ptr<GenericFunctionScriptType> type;
auto scope = this -> _scope -> Exists(identifier);
BoundVariableKey* assignmentKey;
if (scope >= 0){
auto var = this -> _scope -> GetVariable(scope, identifier);
auto varType =var->GetType();
if (varType->GetClass() != TypeClass::Function){
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::CantAssignVariable, statement->GetStartPosition(),
statement->GetLength());
}
type = dynamic_pointer_cast<GenericFunctionScriptType>(varType);
type->RegisterFunctionOption(option);
assignmentKey = new BoundVariableKey(identifier, scope, false);
} else{
type = make_shared<GenericFunctionScriptType>();
type->RegisterFunctionOption(option);
auto assignment = this->_scope->AssignVariable(identifier, type);
if (assignment.GetResult() != VariableAssignmentResult::Ok) {
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::CantAssignVariable, statement->GetStartPosition(),
statement->GetLength());
return new BoundBadStatement();
}
assignmentKey = assignment.GetKey();
}
auto boundBlock = this->BindBlockStatement(functionStatement->GetBlock());
this->_scope->GoOuterScope();
this->_currentFunction = nullptr;
return new BoundFunctionDeclarationStatement(type, assignment.GetKey(), (BoundBlockStatement *) boundBlock);
return new BoundFunctionDeclarationStatement(type, assignmentKey, (BoundBlockStatement *) boundBlock);
}
BoundStatement *Binder::BindReturnStatement(const ParsedStatement *statement) {
@@ -558,28 +578,23 @@ namespace Porygon::Binder {
return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength());
}
auto functionType = std::dynamic_pointer_cast<GenericFunctionScriptType>(type);
auto parameterTypes = functionType->GetParameterTypes();
auto givenParameters = expression->GetParameters();
if (parameterTypes.size() != givenParameters->size()) {
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::ParameterCountMismatch,
auto givenParameterTypes = vector<shared_ptr<ScriptType>>(givenParameters->size());
vector<BoundExpression *> boundParameters = vector<BoundExpression *>(givenParameters->size());
for (int i = 0; i < givenParameters->size(); i++){
boundParameters[i] = this -> BindExpression(givenParameters->at(i));
givenParameterTypes[i] = boundParameters[i]->GetType();
}
auto functionOption = functionType->GetFunctionOption(givenParameterTypes);
if (functionOption == nullptr){
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::InvalidFunctionParameters,
expression->GetStartPosition(),
expression->GetLength());
return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength());
}
vector<BoundExpression *> boundParameters = vector<BoundExpression *>(givenParameters->size());
for (int i = 0; i < givenParameters->size(); i++) {
auto parameter = givenParameters->at(i);
auto boundParameter = this->BindExpression(parameter);
if (boundParameter->GetType().get()->operator!=(parameterTypes.at(i).get())) {
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::ParameterTypeMismatch,
parameter->GetStartPosition(),
parameter->GetLength());
return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength());
}
boundParameters[i] = boundParameter;
}
return new BoundFunctionCallExpression(functionExpression, boundParameters, functionType.get()->GetReturnType(),
return new BoundFunctionCallExpression(functionExpression, boundParameters, functionOption, functionOption->GetReturnType(),
expression->GetStartPosition(), expression->GetLength());
}