Better handling of casting
continuous-integration/drone/push Build is passing Details

This commit is contained in:
Deukhoofd 2019-08-18 13:17:53 +02:00
parent 0fde3d46df
commit 1d72e2eccd
Signed by: Deukhoofd
GPG Key ID: ADF2E9256009EDCE
8 changed files with 78 additions and 21 deletions

View File

@ -590,7 +590,7 @@ namespace Porygon::Binder {
boundParameters[i] = this -> BindExpression(givenParameters->at(i)); boundParameters[i] = this -> BindExpression(givenParameters->at(i));
} }
auto functionOption = functionType->GetFunctionOption(this->_scriptData->Diagnostics, boundParameters); auto functionOption = functionType->GetFunctionOption(this->_scriptData->Diagnostics, &boundParameters);
if (functionOption == nullptr){ if (functionOption == nullptr){
this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::InvalidFunctionParameters, this->_scriptData->Diagnostics->LogError(Diagnostics::DiagnosticCode::InvalidFunctionParameters,
expression->GetStartPosition(), expression->GetStartPosition(),

View File

@ -28,6 +28,7 @@ namespace Porygon::Binder {
NumericalTable, NumericalTable,
Table, Table,
Require, Require,
ImplicitCast,
}; };
class BoundExpression { class BoundExpression {
@ -332,6 +333,28 @@ namespace Porygon::Binder {
} }
}; };
class BoundImplicitCastExpression : public BoundExpression {
const BoundExpression* _expression;
public:
BoundImplicitCastExpression(BoundExpression* expression, shared_ptr<const ScriptType> castType)
: BoundExpression(expression->GetStartPosition(), expression->GetLength(), castType),
_expression(expression)
{}
const BoundExpression* GetExpression() const{
return _expression;
}
~BoundImplicitCastExpression() final {
delete _expression;
}
[[nodiscard]]
inline BoundExpressionKind GetKind() const final {
return BoundExpressionKind::ImplicitCast;
}
};
} }
#endif //PORYGONLANG_BOUNDEXPRESSION_HPP #endif //PORYGONLANG_BOUNDEXPRESSION_HPP

View File

@ -87,6 +87,11 @@ namespace Porygon::Evaluation {
virtual EvalValue* UnaryOperation(Binder::BoundUnaryOperation operation) const{ virtual EvalValue* UnaryOperation(Binder::BoundUnaryOperation operation) const{
throw EvaluationException("Unary operations are not implemented for this type."); throw EvaluationException("Unary operations are not implemented for this type.");
} }
[[nodiscard]]
virtual EvalValue* Cast(shared_ptr<const ScriptType> castType) const{
throw new EvaluationException("Casting to invalid type.");
}
}; };
class BooleanEvalValue : public EvalValue { class BooleanEvalValue : public EvalValue {

View File

@ -176,4 +176,24 @@ namespace Porygon::Evaluation {
} }
} }
} }
EvalValue *IntegerEvalValue::Cast(shared_ptr<const ScriptType> castType) const {
if (castType->GetClass() == TypeClass::Number){
auto num = static_pointer_cast<const NumericScriptType>(castType);
if (num->IsFloat()){
return new FloatEvalValue(GetIntegerValue());
}
}
return EvalValue::Cast(castType);
}
EvalValue *FloatEvalValue::Cast(shared_ptr<const ScriptType> castType) const {
if (castType->GetClass() == TypeClass::Number){
auto num = static_pointer_cast<const NumericScriptType>(castType);
if (!num->IsFloat()){
return new IntegerEvalValue(GetFloatValue());
}
}
return EvalValue::Cast(castType);
}
} }

View File

@ -68,11 +68,6 @@ namespace Porygon::Evaluation {
return _value; return _value;
} }
[[nodiscard]]
inline double EvaluateFloat() const final {
return static_cast<double>(_value);
}
[[nodiscard]] [[nodiscard]]
inline std::u16string EvaluateString() const final{ inline std::u16string EvaluateString() const final{
return Utilities::StringUtils::IntToString(_value); return Utilities::StringUtils::IntToString(_value);
@ -98,14 +93,17 @@ namespace Porygon::Evaluation {
default: throw; default: throw;
} }
} }
[[nodiscard]]
EvalValue* Cast(shared_ptr<const ScriptType> castType) const final;
}; };
class FloatEvalValue : public NumericEvalValue { class FloatEvalValue : public NumericEvalValue {
const double _value; const double _value;
[[nodiscard]] [[nodiscard]]
inline int64_t GetIntegerValue() const final { int64_t GetIntegerValue() const final {
return _value; throw EvaluationException("Attempting to retrieve int from float eval value.");
} }
[[nodiscard]] [[nodiscard]]
@ -127,11 +125,6 @@ namespace Porygon::Evaluation {
return _value; return _value;
} }
[[nodiscard]]
inline int64_t EvaluateInteger() const final {
return static_cast<int64_t >(_value);
}
[[nodiscard]] [[nodiscard]]
inline std::u16string EvaluateString() const final{ inline std::u16string EvaluateString() const final{
return Utilities::StringUtils::FloatToString(_value); return Utilities::StringUtils::FloatToString(_value);
@ -196,6 +189,9 @@ namespace Porygon::Evaluation {
default: throw; default: throw;
} }
} }
[[nodiscard]]
EvalValue* Cast(shared_ptr<const ScriptType> castType) const final;
}; };
} }

View File

@ -257,6 +257,8 @@ namespace Porygon::Evaluation {
return this->EvaluateComplexTableExpression(expression); return this->EvaluateComplexTableExpression(expression);
case BoundExpressionKind::Require: case BoundExpressionKind::Require:
return this -> EvaluateRequireExpression(expression); return this -> EvaluateRequireExpression(expression);
case BoundExpressionKind::ImplicitCast:
return this -> EvaluateImplicitCastExpression(expression);
} }
} }
@ -412,4 +414,10 @@ namespace Porygon::Evaluation {
return result.Take(); return result.Take();
} }
} }
EvalValuePointer Evaluator::EvaluateImplicitCastExpression(const BoundExpression *pExpression) {
auto iCExpression = dynamic_cast<const BoundImplicitCastExpression*>(pExpression);
auto val = EvaluateExpression(iCExpression->GetExpression());
return val->Cast(iCExpression->GetType());
}
} }

View File

@ -48,6 +48,7 @@ namespace Porygon::Evaluation{
EvalValuePointer EvaluateComplexTableExpression(const BoundExpression *expression); EvalValuePointer EvaluateComplexTableExpression(const BoundExpression *expression);
EvalValuePointer EvaluateRequireExpression(const BoundExpression* expression); EvalValuePointer EvaluateRequireExpression(const BoundExpression* expression);
EvalValuePointer EvaluateImplicitCastExpression(const BoundExpression *pExpression);
EvalValuePointer GetVariable(const BoundVariableExpression *expression); EvalValuePointer GetVariable(const BoundVariableExpression *expression);
public: public:

View File

@ -36,23 +36,26 @@ namespace Porygon {
} }
bool IsValid(const shared_ptr<Diagnostics::DiagnosticsHolder>& diagnostics, bool IsValid(const shared_ptr<Diagnostics::DiagnosticsHolder>& diagnostics,
const vector<Binder::BoundExpression *>& parameters){ vector<Binder::BoundExpression *>* parameters){
if (parameters.size() != _parameterTypes.size()){ if (parameters->size() != _parameterTypes.size()){
return false; return false;
} }
for (size_t i = 0; i < parameters.size(); i++){ for (size_t i = 0; i < parameters->size(); i++){
if (_parameterTypes[i]->GetClass() == TypeClass::All) if (_parameterTypes[i]->GetClass() == TypeClass::All)
continue; continue;
auto parameter = parameters[i]; auto parameter = parameters->at(i);
const auto& parameterType = parameter->GetType(); const auto& parameterType = parameter->GetType();
if (parameterType->operator!=(_parameterTypes[i].get())){ if (parameterType->operator!=(_parameterTypes[i].get())){
auto castResult = parameterType->CastableTo(_parameterTypes[i], false); auto castResult = parameterType->CastableTo(_parameterTypes[i], false);
if (castResult == CastResult::Failure){ if (castResult == CastResult::Failure){
return false; return false;
} }
else if (castResult == CastResult::DataLoss){ else{
diagnostics->LogWarning(Diagnostics::DiagnosticCode::DataLossOnImplicitCast, parameter->GetStartPosition(), if (castResult == CastResult::DataLoss){
parameter->GetLength()); diagnostics->LogWarning(Diagnostics::DiagnosticCode::DataLossOnImplicitCast, parameter->GetStartPosition(),
parameter->GetLength());
}
parameters->at(i) = new Binder::BoundImplicitCastExpression(parameter, _parameterTypes[i]);
} }
} }
} }
@ -103,8 +106,9 @@ namespace Porygon {
return this; return this;
} }
[[nodiscard]]
GenericFunctionOption* GetFunctionOption(const shared_ptr<Diagnostics::DiagnosticsHolder>& diagnostics, GenericFunctionOption* GetFunctionOption(const shared_ptr<Diagnostics::DiagnosticsHolder>& diagnostics,
const vector<Binder::BoundExpression *>& parameters) const{ vector<Binder::BoundExpression *>* parameters) const{
for (auto o: *_options){ for (auto o: *_options){
if (o->IsValid(diagnostics, parameters)){ if (o->IsValid(diagnostics, parameters)){
return o; return o;