Initial work on implicit casting when calling a function
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
12
src/ScriptTypes/CastResult.hpp
Normal file
12
src/ScriptTypes/CastResult.hpp
Normal file
@@ -0,0 +1,12 @@
|
||||
#ifndef PORYGONLANG_CASTRESULT_HPP
|
||||
#define PORYGONLANG_CASTRESULT_HPP
|
||||
|
||||
namespace Porygon{
|
||||
enum class CastResult{
|
||||
Success,
|
||||
Failure,
|
||||
DataLoss,
|
||||
};
|
||||
}
|
||||
|
||||
#endif //PORYGONLANG_CASTRESULT_HPP
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
#include <utility>
|
||||
#include "ScriptType.hpp"
|
||||
#include "../Binder/BoundExpressions/BoundExpression.hpp"
|
||||
#include "../Diagnostics/DiagnosticsHolder.hpp"
|
||||
|
||||
namespace Porygon {
|
||||
class GenericFunctionOption{
|
||||
@@ -33,15 +35,25 @@ namespace Porygon {
|
||||
return _parameterTypes;
|
||||
}
|
||||
|
||||
bool IsValid(const vector<shared_ptr<const ScriptType>>& parameters){
|
||||
bool IsValid(const shared_ptr<Diagnostics::DiagnosticsHolder>& diagnostics,
|
||||
const vector<Binder::BoundExpression *>& parameters){
|
||||
if (parameters.size() != _parameterTypes.size()){
|
||||
return false;
|
||||
}
|
||||
for (size_t i = 0; i < parameters.size(); i++){
|
||||
if (_parameterTypes[i]->GetClass() == TypeClass::All)
|
||||
continue;
|
||||
if (parameters[i]->operator!=(_parameterTypes[i].get())){
|
||||
return false;
|
||||
auto parameter = parameters[i];
|
||||
const auto& parameterType = parameter->GetType();
|
||||
if (parameterType->operator!=(_parameterTypes[i].get())){
|
||||
auto castResult = parameterType->CastableTo(_parameterTypes[i], false);
|
||||
if (castResult == CastResult::Failure){
|
||||
return false;
|
||||
}
|
||||
else if (castResult == CastResult::DataLoss){
|
||||
diagnostics->LogWarning(Diagnostics::DiagnosticCode::DataLossOnImplicitCast, parameter->GetStartPosition(),
|
||||
parameter->GetLength());
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -91,9 +103,10 @@ namespace Porygon {
|
||||
return this;
|
||||
}
|
||||
|
||||
GenericFunctionOption* GetFunctionOption(const vector<shared_ptr<const ScriptType>>& parameters) const{
|
||||
GenericFunctionOption* GetFunctionOption(const shared_ptr<Diagnostics::DiagnosticsHolder>& diagnostics,
|
||||
const vector<Binder::BoundExpression *>& parameters) const{
|
||||
for (auto o: *_options){
|
||||
if (o->IsValid(parameters)){
|
||||
if (o->IsValid(diagnostics, parameters)){
|
||||
return o;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <memory>
|
||||
#include "../Binder/BoundVariables/BoundVariableKey.hpp"
|
||||
#include "../Utilities/HashedString.hpp"
|
||||
#include "CastResult.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -34,7 +35,7 @@ namespace Porygon{
|
||||
|
||||
virtual ~ScriptType() = default;
|
||||
|
||||
[[nodiscard]] const TypeClass GetClass() const{
|
||||
[[nodiscard]] inline TypeClass GetClass() const{
|
||||
return _class;
|
||||
}
|
||||
|
||||
@@ -74,6 +75,10 @@ namespace Porygon{
|
||||
virtual shared_ptr<const ScriptType> GetIteratorKeyType() const{
|
||||
throw "This type told the binder it can be iterated, but it does not implement the resulting type.";
|
||||
}
|
||||
|
||||
[[nodiscard]] virtual CastResult CastableTo(const shared_ptr<const ScriptType>& castType, bool explicitCast) const{
|
||||
return CastResult::Failure;
|
||||
}
|
||||
};
|
||||
|
||||
class NumericScriptType : public ScriptType{
|
||||
@@ -94,6 +99,34 @@ namespace Porygon{
|
||||
[[nodiscard]] inline bool IsFloat() const{
|
||||
return _isFloat;
|
||||
}
|
||||
|
||||
bool operator ==(const ScriptType& b) const final{
|
||||
if (b.GetClass() != TypeClass::Number)
|
||||
return false;
|
||||
auto bNum = dynamic_cast<const NumericScriptType&>(b);
|
||||
if (bNum.IsAwareOfFloat() && IsAwareOfFloat()){
|
||||
return bNum.IsFloat() == IsFloat();
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
bool operator !=(const ScriptType& b) const final{
|
||||
return ! (operator==(b));
|
||||
}
|
||||
bool operator !=(const ScriptType* b) const final{
|
||||
return ! (operator==(*b));
|
||||
}
|
||||
|
||||
[[nodiscard]] CastResult CastableTo(const shared_ptr<const ScriptType>& castType, bool explicitCast) const final{
|
||||
if (!explicitCast){
|
||||
if (castType->GetClass() != TypeClass::Number )
|
||||
return CastResult::Failure;
|
||||
auto bNum = dynamic_pointer_cast<const NumericScriptType>(castType);
|
||||
if (bNum->IsFloat() && !IsFloat()) return CastResult::Success;
|
||||
if (!bNum->IsFloat() && IsFloat()) return CastResult::DataLoss;
|
||||
}
|
||||
return CastResult::Success;
|
||||
}
|
||||
};
|
||||
|
||||
class StringScriptType : public ScriptType{
|
||||
|
||||
Reference in New Issue
Block a user