diff --git a/src/Binder/Binder.cpp b/src/Binder/Binder.cpp index 6fb03af..904288d 100644 --- a/src/Binder/Binder.cpp +++ b/src/Binder/Binder.cpp @@ -1,5 +1,5 @@ -#include +#include #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 ParseTypeIdentifier(const HashedString* s) { + std::shared_ptr 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 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(varType); type->RegisterFunctionOption(option); assignmentKey = new BoundVariableKey(identifier, scope, false); - } else{ + } else { type = make_shared(); 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(this->BindBlockStatement(functionStatement->GetBlock())); + auto boundBlock = dynamic_cast(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(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(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(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(func); - if (variable->GetValue().GetHash() == HashedString::ConstHash("require")){ + if (func->GetKind() == ParsedExpressionKind::Variable) { + auto variable = dynamic_cast(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(type); auto givenParameters = expression->GetParameters(); vector boundParameters = vector(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(boundParameter)->GetValue(); + auto key = *dynamic_cast(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(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) { diff --git a/src/Binder/Binder.hpp b/src/Binder/Binder.hpp index b9adb11..9c5ba48 100644 --- a/src/Binder/Binder.hpp +++ b/src/Binder/Binder.hpp @@ -42,6 +42,7 @@ namespace Porygon::Binder { BoundExpression *BindUnaryOperator(const UnaryExpression *expression); BoundExpression *BindFunctionCall(const FunctionCallExpression *expression); BoundExpression *BindRequire(const FunctionCallExpression *exp); + BoundExpression *BindCast(const FunctionCallExpression *exp); BoundExpression *BindIndexExpression(const IndexExpression *expression, bool setter); BoundExpression *BindNumericalTableExpression(const ParsedNumericalTableExpression *expression); BoundExpression *BindTableExpression(const ParsedTableExpression *expression); diff --git a/src/Binder/BoundExpressions/BoundExpression.hpp b/src/Binder/BoundExpressions/BoundExpression.hpp index eb31d8f..a36be41 100644 --- a/src/Binder/BoundExpressions/BoundExpression.hpp +++ b/src/Binder/BoundExpressions/BoundExpression.hpp @@ -28,7 +28,7 @@ namespace Porygon::Binder { NumericalTable, Table, Require, - ImplicitCast, + Cast, }; class BoundExpression { @@ -333,10 +333,10 @@ namespace Porygon::Binder { } }; - class BoundImplicitCastExpression : public BoundExpression { + class BoundCastExpression : public BoundExpression { const BoundExpression* _expression; public: - BoundImplicitCastExpression(BoundExpression* expression, shared_ptr castType) + BoundCastExpression(BoundExpression* expression, shared_ptr castType) : BoundExpression(expression->GetStartPosition(), expression->GetLength(), castType), _expression(expression) {} @@ -345,13 +345,13 @@ namespace Porygon::Binder { return _expression; } - ~BoundImplicitCastExpression() final { + ~BoundCastExpression() final { delete _expression; } [[nodiscard]] inline BoundExpressionKind GetKind() const final { - return BoundExpressionKind::ImplicitCast; + return BoundExpressionKind::Cast; } }; diff --git a/src/Diagnostics/DiagnosticCode.hpp b/src/Diagnostics/DiagnosticCode.hpp index 639443c..317f23b 100644 --- a/src/Diagnostics/DiagnosticCode.hpp +++ b/src/Diagnostics/DiagnosticCode.hpp @@ -28,9 +28,13 @@ namespace Porygon::Diagnostics { CantIterateExpression, InvalidFunctionParameters, ModuleDoesntExist, + InvalidCast, // Bind warnings - DataLossOnImplicitCast, + DataLossOnCast, + + // Bind info + UnvalidatedCast, }; } #endif //PORYGONLANG_DIAGNOSTICCODE_HPP diff --git a/src/Evaluator/Evaluator.cpp b/src/Evaluator/Evaluator.cpp index a25715b..316722f 100644 --- a/src/Evaluator/Evaluator.cpp +++ b/src/Evaluator/Evaluator.cpp @@ -257,7 +257,7 @@ namespace Porygon::Evaluation { return this->EvaluateComplexTableExpression(expression); case BoundExpressionKind::Require: return this -> EvaluateRequireExpression(expression); - case BoundExpressionKind::ImplicitCast: + case BoundExpressionKind::Cast: return this -> EvaluateImplicitCastExpression(expression); } } @@ -416,7 +416,7 @@ namespace Porygon::Evaluation { } EvalValuePointer Evaluator::EvaluateImplicitCastExpression(const BoundExpression *pExpression) { - auto iCExpression = dynamic_cast(pExpression); + auto iCExpression = dynamic_cast(pExpression); auto val = EvaluateExpression(iCExpression->GetExpression()); return val->Cast(iCExpression->GetType()); } diff --git a/src/ScriptTypes/CastResult.hpp b/src/ScriptTypes/CastResult.hpp index b8dc379..0ef85a3 100644 --- a/src/ScriptTypes/CastResult.hpp +++ b/src/ScriptTypes/CastResult.hpp @@ -3,8 +3,9 @@ namespace Porygon{ enum class CastResult{ - Success, - Failure, + ValidCast, + InvalidCast, + UncheckedCast, DataLoss, }; } diff --git a/src/ScriptTypes/FunctionScriptType.hpp b/src/ScriptTypes/FunctionScriptType.hpp index b658986..14d774f 100644 --- a/src/ScriptTypes/FunctionScriptType.hpp +++ b/src/ScriptTypes/FunctionScriptType.hpp @@ -47,15 +47,15 @@ namespace Porygon { const auto& parameterType = parameter->GetType(); if (parameterType->operator!=(_parameterTypes[i].get())){ auto castResult = parameterType->CastableTo(_parameterTypes[i], false); - if (castResult == CastResult::Failure){ + if (castResult == CastResult::InvalidCast){ return false; } else{ if (castResult == CastResult::DataLoss){ - diagnostics->LogWarning(Diagnostics::DiagnosticCode::DataLossOnImplicitCast, parameter->GetStartPosition(), + diagnostics->LogWarning(Diagnostics::DiagnosticCode::DataLossOnCast, parameter->GetStartPosition(), parameter->GetLength()); } - parameters->at(i) = new Binder::BoundImplicitCastExpression(parameter, _parameterTypes[i]); + parameters->at(i) = new Binder::BoundCastExpression(parameter, _parameterTypes[i]); } } } diff --git a/src/ScriptTypes/ScriptType.hpp b/src/ScriptTypes/ScriptType.hpp index b1e35eb..0006d25 100644 --- a/src/ScriptTypes/ScriptType.hpp +++ b/src/ScriptTypes/ScriptType.hpp @@ -77,7 +77,9 @@ namespace Porygon{ } [[nodiscard]] virtual CastResult CastableTo(const shared_ptr& castType, bool explicitCast) const{ - return CastResult::Failure; + if (explicitCast) + return CastResult::InvalidCast; + return CastResult::InvalidCast; } }; @@ -120,12 +122,12 @@ namespace Porygon{ [[nodiscard]] CastResult CastableTo(const shared_ptr& castType, bool explicitCast) const final{ if (!explicitCast){ if (castType->GetClass() != TypeClass::Number ) - return CastResult::Failure; + return CastResult::InvalidCast; auto bNum = dynamic_pointer_cast(castType); - if (bNum->IsFloat() && !IsFloat()) return CastResult::Success; + if (bNum->IsFloat() && !IsFloat()) return CastResult::ValidCast; if (!bNum->IsFloat() && IsFloat()) return CastResult::DataLoss; } - return CastResult::Success; + return ScriptType::CastableTo(castType, explicitCast); } };