|
|
|
@ -1,5 +1,5 @@
|
|
|
|
|
#include <memory>
|
|
|
|
|
|
|
|
|
|
#include <memory>
|
|
|
|
|
#include "Binder.hpp"
|
|
|
|
|
#include "../ScriptTypes/TableScriptType.hpp"
|
|
|
|
|
#include "BoundExpressions/BoundTableExpression.hpp"
|
|
|
|
@ -48,9 +48,9 @@ namespace Porygon::Binder {
|
|
|
|
|
case ParsedStatementKind::NumericalFor:
|
|
|
|
|
return this->BindNumericalForStatement(statement);
|
|
|
|
|
case ParsedStatementKind::GenericFor:
|
|
|
|
|
return this -> BindGenericForStatement(statement);
|
|
|
|
|
return this->BindGenericForStatement(statement);
|
|
|
|
|
case ParsedStatementKind::While:
|
|
|
|
|
return this -> BindWhileStatement(statement);
|
|
|
|
|
return this->BindWhileStatement(statement);
|
|
|
|
|
case ParsedStatementKind::Break:
|
|
|
|
|
//TODO: Validate we're in a loop
|
|
|
|
|
return new BoundBreakStatement();
|
|
|
|
@ -87,7 +87,8 @@ namespace Porygon::Binder {
|
|
|
|
|
auto key = assignment.GetKey();
|
|
|
|
|
return new BoundAssignmentStatement(key, boundExpression);
|
|
|
|
|
} else {
|
|
|
|
|
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::CantAssignVariable, statement->GetStartPosition(),
|
|
|
|
|
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::CantAssignVariable,
|
|
|
|
|
statement->GetStartPosition(),
|
|
|
|
|
statement->GetLength());
|
|
|
|
|
return new BoundBadStatement();
|
|
|
|
|
}
|
|
|
|
@ -114,7 +115,7 @@ namespace Porygon::Binder {
|
|
|
|
|
return new BoundIndexAssignmentStatement(indexable, valueExpression);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::shared_ptr<ScriptType> ParseTypeIdentifier(const HashedString* s) {
|
|
|
|
|
std::shared_ptr<ScriptType> ParseTypeIdentifier(const HashedString *s) {
|
|
|
|
|
auto hash = s->GetHash();
|
|
|
|
|
switch (hash) {
|
|
|
|
|
case HashedString::ConstHash("number"):
|
|
|
|
@ -142,7 +143,8 @@ namespace Porygon::Binder {
|
|
|
|
|
auto var = parameters->at(i);
|
|
|
|
|
auto parsedType = ParseTypeIdentifier(var->GetType());
|
|
|
|
|
if (parsedType == nullptr) {
|
|
|
|
|
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::InvalidTypeName, statement->GetStartPosition(),
|
|
|
|
|
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::InvalidTypeName,
|
|
|
|
|
statement->GetStartPosition(),
|
|
|
|
|
statement->GetLength());
|
|
|
|
|
return new BoundBadStatement();
|
|
|
|
|
}
|
|
|
|
@ -162,31 +164,33 @@ namespace Porygon::Binder {
|
|
|
|
|
this->_currentFunction = option;
|
|
|
|
|
|
|
|
|
|
shared_ptr<const GenericFunctionScriptType> type;
|
|
|
|
|
auto scope = this -> _scope -> Exists(identifier);
|
|
|
|
|
const 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(),
|
|
|
|
|
auto scope = this->_scope->Exists(identifier);
|
|
|
|
|
const 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<const GenericFunctionScriptType>(varType);
|
|
|
|
|
type->RegisterFunctionOption(option);
|
|
|
|
|
assignmentKey = new BoundVariableKey(identifier, scope, false);
|
|
|
|
|
} else{
|
|
|
|
|
} else {
|
|
|
|
|
type = make_shared<const 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(),
|
|
|
|
|
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::CantAssignVariable,
|
|
|
|
|
statement->GetStartPosition(),
|
|
|
|
|
statement->GetLength());
|
|
|
|
|
return new BoundBadStatement();
|
|
|
|
|
}
|
|
|
|
|
assignmentKey = assignment.GetKey();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto boundBlock = dynamic_cast<BoundBlockStatement*>(this->BindBlockStatement(functionStatement->GetBlock()));
|
|
|
|
|
auto boundBlock = dynamic_cast<BoundBlockStatement *>(this->BindBlockStatement(functionStatement->GetBlock()));
|
|
|
|
|
this->_scope->GoOuterScope();
|
|
|
|
|
this->_currentFunction = nullptr;
|
|
|
|
|
return new BoundFunctionDeclarationStatement(type, assignmentKey, boundBlock);
|
|
|
|
@ -200,11 +204,13 @@ namespace Porygon::Binder {
|
|
|
|
|
} else {
|
|
|
|
|
currentReturnType = this->_currentFunction->GetReturnType();
|
|
|
|
|
}
|
|
|
|
|
if (expression == nullptr && (currentReturnType != nullptr && currentReturnType -> GetClass() != TypeClass::Nil)) {
|
|
|
|
|
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::InvalidReturnType, statement->GetStartPosition(),
|
|
|
|
|
if (expression == nullptr &&
|
|
|
|
|
(currentReturnType != nullptr && currentReturnType->GetClass() != TypeClass::Nil)) {
|
|
|
|
|
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::InvalidReturnType,
|
|
|
|
|
statement->GetStartPosition(),
|
|
|
|
|
statement->GetLength());
|
|
|
|
|
return new BoundBadStatement();
|
|
|
|
|
} else if (expression == nullptr){
|
|
|
|
|
} else if (expression == nullptr) {
|
|
|
|
|
currentReturnType = make_shared<ScriptType>(TypeClass::Nil);
|
|
|
|
|
return new BoundReturnStatement(nullptr);
|
|
|
|
|
}
|
|
|
|
@ -219,7 +225,8 @@ namespace Porygon::Binder {
|
|
|
|
|
return new BoundReturnStatement(boundExpression);
|
|
|
|
|
}
|
|
|
|
|
if (currentReturnType.get()->operator!=(expresionType.get())) {
|
|
|
|
|
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::InvalidReturnType, statement->GetStartPosition(),
|
|
|
|
|
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::InvalidReturnType,
|
|
|
|
|
statement->GetStartPosition(),
|
|
|
|
|
statement->GetLength());
|
|
|
|
|
return new BoundBadStatement();
|
|
|
|
|
}
|
|
|
|
@ -230,7 +237,8 @@ namespace Porygon::Binder {
|
|
|
|
|
auto conditionalStatement = (ParsedConditionalStatement *) statement;
|
|
|
|
|
auto boundCondition = this->BindExpression(conditionalStatement->GetCondition());
|
|
|
|
|
if (boundCondition->GetType()->GetClass() != TypeClass::Bool) {
|
|
|
|
|
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::ConditionNotABool, statement->GetStartPosition(),
|
|
|
|
|
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::ConditionNotABool,
|
|
|
|
|
statement->GetStartPosition(),
|
|
|
|
|
statement->GetLength());
|
|
|
|
|
return new BoundBadStatement();
|
|
|
|
|
}
|
|
|
|
@ -243,92 +251,100 @@ namespace Porygon::Binder {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BoundStatement *Binder::BindNumericalForStatement(const ParsedStatement *statement) {
|
|
|
|
|
auto forStatement = (ParsedNumericalForStatement*) 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);
|
|
|
|
|
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(),
|
|
|
|
|
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(),
|
|
|
|
|
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(),
|
|
|
|
|
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, make_shared<NumericScriptType>(true, false));
|
|
|
|
|
if (variableKey.GetResult() != VariableAssignmentResult::Ok){
|
|
|
|
|
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::CantAssignVariable, statement->GetStartPosition(),
|
|
|
|
|
this->_scope->GoInnerScope();
|
|
|
|
|
auto variableKey = this->_scope->CreateExplicitLocal(identifier, 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();
|
|
|
|
|
auto block = this->BindBlockStatement(forStatement->GetBlock());
|
|
|
|
|
this->_scope->GoOuterScope();
|
|
|
|
|
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(),
|
|
|
|
|
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(),
|
|
|
|
|
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 valueIdentifier = genericFor->GetValueIdentifier();
|
|
|
|
|
auto isValueVariableDefined = valueIdentifier.GetHash() != 0;
|
|
|
|
|
const 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(),
|
|
|
|
|
const 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());
|
|
|
|
|
auto boundBlock = this->BindBlockStatement(genericFor->GetBlock());
|
|
|
|
|
|
|
|
|
|
this -> _scope -> GoOuterScope();
|
|
|
|
|
this->_scope->GoOuterScope();
|
|
|
|
|
|
|
|
|
|
return new BoundGenericForStatement(keyVariable, valueVariable, boundIterator, boundBlock);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BoundStatement *Binder::BindWhileStatement(const ParsedStatement *statement) {
|
|
|
|
|
auto whileStatement = (ParsedWhileStatement*)statement;
|
|
|
|
|
auto boundCondition = this -> BindExpression(whileStatement->GetCondition());
|
|
|
|
|
if (boundCondition->GetType()->GetClass() != TypeClass::Bool){
|
|
|
|
|
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::ConditionNotABool, statement->GetStartPosition(),
|
|
|
|
|
auto whileStatement = (ParsedWhileStatement *) statement;
|
|
|
|
|
auto boundCondition = this->BindExpression(whileStatement->GetCondition());
|
|
|
|
|
if (boundCondition->GetType()->GetClass() != TypeClass::Bool) {
|
|
|
|
|
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::ConditionNotABool,
|
|
|
|
|
statement->GetStartPosition(),
|
|
|
|
|
statement->GetLength());
|
|
|
|
|
return new BoundBadStatement();
|
|
|
|
|
}
|
|
|
|
|
auto boundBlock = this -> BindBlockStatement(whileStatement->GetBlock());
|
|
|
|
|
auto boundBlock = this->BindBlockStatement(whileStatement->GetBlock());
|
|
|
|
|
return new BoundWhileStatement(boundCondition, boundBlock);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -382,7 +398,8 @@ namespace Porygon::Binder {
|
|
|
|
|
auto key = expression->GetValue();
|
|
|
|
|
auto scope = this->_scope->Exists(key);
|
|
|
|
|
if (scope == -1) {
|
|
|
|
|
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::VariableNotFound, expression->GetStartPosition(),
|
|
|
|
|
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::VariableNotFound,
|
|
|
|
|
expression->GetStartPosition(),
|
|
|
|
|
expression->GetLength());
|
|
|
|
|
return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength());
|
|
|
|
|
}
|
|
|
|
@ -526,7 +543,8 @@ namespace Porygon::Binder {
|
|
|
|
|
expression->GetStartPosition(), expression->GetLength());
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::NoBinaryOperationFound, expression->GetStartPosition(),
|
|
|
|
|
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::NoBinaryOperationFound,
|
|
|
|
|
expression->GetStartPosition(),
|
|
|
|
|
expression->GetLength());
|
|
|
|
|
return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength());
|
|
|
|
|
}
|
|
|
|
@ -561,7 +579,8 @@ namespace Porygon::Binder {
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::NoUnaryOperationFound, expression->GetStartPosition(),
|
|
|
|
|
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::NoUnaryOperationFound,
|
|
|
|
|
expression->GetStartPosition(),
|
|
|
|
|
expression->GetLength());
|
|
|
|
|
return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength());
|
|
|
|
|
|
|
|
|
@ -569,10 +588,13 @@ namespace Porygon::Binder {
|
|
|
|
|
|
|
|
|
|
BoundExpression *Binder::BindFunctionCall(const FunctionCallExpression *expression) {
|
|
|
|
|
auto func = expression->GetFunction();
|
|
|
|
|
if (func->GetKind() == ParsedExpressionKind::Variable){
|
|
|
|
|
auto variable = dynamic_cast<const VariableExpression*>(func);
|
|
|
|
|
if (variable->GetValue().GetHash() == HashedString::ConstHash("require")){
|
|
|
|
|
if (func->GetKind() == ParsedExpressionKind::Variable) {
|
|
|
|
|
auto variable = dynamic_cast<const VariableExpression *>(func);
|
|
|
|
|
auto hash = variable->GetValue().GetHash();
|
|
|
|
|
if (hash == HashedString::ConstHash("require")) {
|
|
|
|
|
return this->BindRequire(expression);
|
|
|
|
|
} else if (hash == HashedString::ConstHash("cast")) {
|
|
|
|
|
return this->BindCast(expression);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
auto functionExpression = BindExpression(func);
|
|
|
|
@ -586,58 +608,96 @@ namespace Porygon::Binder {
|
|
|
|
|
auto functionType = std::dynamic_pointer_cast<const GenericFunctionScriptType>(type);
|
|
|
|
|
auto givenParameters = expression->GetParameters();
|
|
|
|
|
vector<BoundExpression *> boundParameters = vector<BoundExpression *>(givenParameters->size());
|
|
|
|
|
for (size_t i = 0; i < givenParameters->size(); i++){
|
|
|
|
|
boundParameters[i] = this -> BindExpression(givenParameters->at(i));
|
|
|
|
|
for (size_t i = 0; i < givenParameters->size(); i++) {
|
|
|
|
|
boundParameters[i] = this->BindExpression(givenParameters->at(i));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto functionOption = functionType->GetFunctionOption(this->_scriptData->Diagnostics, &boundParameters);
|
|
|
|
|
if (functionOption == nullptr){
|
|
|
|
|
if (functionOption == nullptr) {
|
|
|
|
|
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::InvalidFunctionParameters,
|
|
|
|
|
expression->GetStartPosition(),
|
|
|
|
|
expression->GetLength());
|
|
|
|
|
return new BoundBadExpression(expression->GetStartPosition(), expression->GetLength());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return new BoundFunctionCallExpression(functionExpression, boundParameters, functionOption, functionOption->GetReturnType(),
|
|
|
|
|
return new BoundFunctionCallExpression(functionExpression, boundParameters, functionOption,
|
|
|
|
|
functionOption->GetReturnType(),
|
|
|
|
|
expression->GetStartPosition(), expression->GetLength());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BoundExpression *Binder::BindRequire(const FunctionCallExpression* exp){
|
|
|
|
|
BoundExpression *Binder::BindRequire(const FunctionCallExpression *exp) {
|
|
|
|
|
auto parameters = exp->GetParameters();
|
|
|
|
|
if (parameters->size() != 1){
|
|
|
|
|
if (parameters->size() != 1) {
|
|
|
|
|
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::InvalidFunctionParameters,
|
|
|
|
|
exp->GetStartPosition(),
|
|
|
|
|
exp->GetLength());
|
|
|
|
|
return new BoundBadExpression(exp->GetStartPosition(), exp ->GetLength());
|
|
|
|
|
return new BoundBadExpression(exp->GetStartPosition(), exp->GetLength());
|
|
|
|
|
}
|
|
|
|
|
auto parameter = parameters->at(0);
|
|
|
|
|
auto boundParameter = this -> BindExpression(parameter);
|
|
|
|
|
if (boundParameter->GetKind() != BoundExpressionKind::LiteralString){
|
|
|
|
|
auto boundParameter = this->BindExpression(parameter);
|
|
|
|
|
if (boundParameter->GetKind() != BoundExpressionKind::LiteralString) {
|
|
|
|
|
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::InvalidFunctionParameters,
|
|
|
|
|
exp->GetStartPosition(),
|
|
|
|
|
exp->GetLength());
|
|
|
|
|
return new BoundBadExpression(exp->GetStartPosition(), exp ->GetLength());
|
|
|
|
|
return new BoundBadExpression(exp->GetStartPosition(), exp->GetLength());
|
|
|
|
|
}
|
|
|
|
|
auto key = *dynamic_cast<BoundLiteralStringExpression*>(boundParameter)->GetValue();
|
|
|
|
|
auto key = *dynamic_cast<BoundLiteralStringExpression *>(boundParameter)->GetValue();
|
|
|
|
|
auto opt = this->_scriptData->GetScriptOptions();
|
|
|
|
|
auto transformedKey = Utilities::StringUtils::FromUTF8(key);
|
|
|
|
|
delete boundParameter;
|
|
|
|
|
if (!opt->DoesModuleExist(transformedKey)){
|
|
|
|
|
if (!opt->DoesModuleExist(transformedKey)) {
|
|
|
|
|
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::ModuleDoesntExist,
|
|
|
|
|
exp->GetStartPosition(),
|
|
|
|
|
exp->GetLength());
|
|
|
|
|
return new BoundBadExpression(exp->GetStartPosition(), exp ->GetLength());
|
|
|
|
|
return new BoundBadExpression(exp->GetStartPosition(), exp->GetLength());
|
|
|
|
|
}
|
|
|
|
|
auto module = Script::Clone(opt->ResolveModule(transformedKey));
|
|
|
|
|
if (module -> GetReturnType() == nullptr){
|
|
|
|
|
for (const auto& v: *module->GetScriptVariables()){
|
|
|
|
|
if (module->GetReturnType() == nullptr) {
|
|
|
|
|
for (const auto &v: *module->GetScriptVariables()) {
|
|
|
|
|
auto type = module->GetVariableType(v.first);
|
|
|
|
|
auto result = this -> _scope -> AssignVariable(v.first, type);
|
|
|
|
|
auto result = this->_scope->AssignVariable(v.first, type);
|
|
|
|
|
delete result.GetKey();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
return new BoundRequireExpression(module, exp->GetStartPosition(), exp ->GetLength());
|
|
|
|
|
return new BoundRequireExpression(module, exp->GetStartPosition(), exp->GetLength());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BoundExpression *Binder::BindCast(const FunctionCallExpression* exp){
|
|
|
|
|
auto parameters = exp->GetParameters();
|
|
|
|
|
if (parameters->size() != 2) {
|
|
|
|
|
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::InvalidFunctionParameters,
|
|
|
|
|
exp->GetStartPosition(),
|
|
|
|
|
exp->GetLength());
|
|
|
|
|
return new BoundBadExpression(exp->GetStartPosition(), exp->GetLength());
|
|
|
|
|
}
|
|
|
|
|
auto toCastParameter = this ->BindExpression(parameters->at(0));
|
|
|
|
|
const auto& toCastParameterType = toCastParameter->GetType();
|
|
|
|
|
|
|
|
|
|
auto destinationTypeParameter = parameters -> at(1);
|
|
|
|
|
if (destinationTypeParameter ->GetKind() != ParsedExpressionKind::Variable){
|
|
|
|
|
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::InvalidFunctionParameters,
|
|
|
|
|
exp->GetStartPosition(),
|
|
|
|
|
exp->GetLength());
|
|
|
|
|
return new BoundBadExpression(exp->GetStartPosition(), exp->GetLength());
|
|
|
|
|
}
|
|
|
|
|
auto destinationTypeContent = dynamic_cast<const VariableExpression*>(destinationTypeParameter)->GetValue();
|
|
|
|
|
auto destinationType = ParseTypeIdentifier(&destinationTypeContent);
|
|
|
|
|
auto castResult = toCastParameterType->CastableTo(destinationType, true);
|
|
|
|
|
if (castResult == CastResult::InvalidCast){
|
|
|
|
|
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::InvalidCast, exp->GetStartPosition(),
|
|
|
|
|
exp->GetLength());
|
|
|
|
|
return new BoundBadExpression(exp->GetStartPosition(), exp->GetLength());
|
|
|
|
|
}
|
|
|
|
|
else if (castResult == CastResult::DataLoss){
|
|
|
|
|
this->_scriptData->Diagnostics->LogWarning(Diagnostics::DiagnosticCode::DataLossOnCast, exp->GetStartPosition(),
|
|
|
|
|
exp->GetLength());
|
|
|
|
|
}
|
|
|
|
|
else if (castResult == CastResult::UncheckedCast){
|
|
|
|
|
this->_scriptData->Diagnostics->LogInfo(Diagnostics::DiagnosticCode::UnvalidatedCast, exp->GetStartPosition(),
|
|
|
|
|
exp->GetLength());
|
|
|
|
|
}
|
|
|
|
|
return new BoundCastExpression(toCastParameter, destinationType);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BoundExpression *Binder::BindIndexExpression(const IndexExpression *expression, bool setter) {
|
|
|
|
|