Greatly simplify handling numerical eval values, using std::variant
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2019-09-07 10:57:09 +02:00
parent 7b5d03ed74
commit 5d700aa0e9
12 changed files with 183 additions and 393 deletions

View File

@@ -2,198 +2,139 @@
#include "NumericEvalValue.hpp"
namespace Porygon::Evaluation {
shared_ptr<const NumericEvalValue> NumericEvalValue::operator+(const shared_ptr<const NumericEvalValue> &b) const {
if (this->IsFloat()) {
if (b->IsFloat()) {
return make_shared<FloatEvalValue>(this->GetFloatValue() + b->GetFloatValue());
} else {
return make_shared<FloatEvalValue>(this->GetFloatValue() + (double) b->GetIntegerValue());
EvalValue *NumericEvalValue::BinaryOperation(Binder::BoundBinaryOperation operation, const EvalValue *b) const {
auto right = dynamic_cast<const NumericEvalValue*>(b);
if (_isFloat){
double v1 = std::get<double >(_floatValue);
if (right->_isFloat){
double v2 =std::get<double >(right->_floatValue);
switch (operation){
case Binder::BoundBinaryOperation::Addition: return new NumericEvalValue(v1 + v2);
case Binder::BoundBinaryOperation::Subtraction: return new NumericEvalValue(v1 - v2);
case Binder::BoundBinaryOperation::Multiplication: return new NumericEvalValue(v1 * v2);
case Binder::BoundBinaryOperation::Division: return new NumericEvalValue(v1 / v2);
case Binder::BoundBinaryOperation::Equality: return new BooleanEvalValue(v1 == v2);
case Binder::BoundBinaryOperation::Inequality: return new BooleanEvalValue(v1 != v2);
case Binder::BoundBinaryOperation::LessThan: return new BooleanEvalValue(v1 < v2);
case Binder::BoundBinaryOperation::LessThanEquals: return new BooleanEvalValue(v1 <= v2);
case Binder::BoundBinaryOperation::GreaterThan: return new BooleanEvalValue(v1 > v2);
case Binder::BoundBinaryOperation::GreaterThanEquals: return new BooleanEvalValue(v1 >= v2);
default: throw exception();
}
}
} else {
if (b->IsFloat()) {
return make_shared<FloatEvalValue>((double) this->GetIntegerValue() + b->GetFloatValue());
} else {
return make_shared<IntegerEvalValue>(this->GetIntegerValue() + b->GetIntegerValue());
else{
int64_t v2 = std::get<int64_t >(right->_intValue);
switch (operation){
case Binder::BoundBinaryOperation::Addition: return new NumericEvalValue(v1 + v2);
case Binder::BoundBinaryOperation::Subtraction: return new NumericEvalValue(v1 - v2);
case Binder::BoundBinaryOperation::Multiplication: return new NumericEvalValue(v1 * v2);
case Binder::BoundBinaryOperation::Division: return new NumericEvalValue(v1 / v2);
case Binder::BoundBinaryOperation::Equality: return new BooleanEvalValue(v1 == v2);
case Binder::BoundBinaryOperation::Inequality: return new BooleanEvalValue(v1 != v2);
case Binder::BoundBinaryOperation::LessThan: return new BooleanEvalValue(v1 < v2);
case Binder::BoundBinaryOperation::LessThanEquals: return new BooleanEvalValue(v1 <= v2);
case Binder::BoundBinaryOperation::GreaterThan: return new BooleanEvalValue(v1 > v2);
case Binder::BoundBinaryOperation::GreaterThanEquals: return new BooleanEvalValue(v1 >= v2);
default: throw exception();
}
}
}
else{
int64_t v1 = std::get<int64_t >(_intValue);
if (right->_isFloat){
double v2 =std::get<double>(right->_floatValue);;
switch (operation){
case Binder::BoundBinaryOperation::Addition: return new NumericEvalValue(v1 + v2);
case Binder::BoundBinaryOperation::Subtraction: return new NumericEvalValue(v1 - v2);
case Binder::BoundBinaryOperation::Multiplication: return new NumericEvalValue(v1 * v2);
case Binder::BoundBinaryOperation::Division: return new NumericEvalValue(v1 / v2);
case Binder::BoundBinaryOperation::Equality: return new BooleanEvalValue(v1 == v2);
case Binder::BoundBinaryOperation::Inequality: return new BooleanEvalValue(v1 != v2);
case Binder::BoundBinaryOperation::LessThan: return new BooleanEvalValue(v1 < v2);
case Binder::BoundBinaryOperation::LessThanEquals: return new BooleanEvalValue(v1 <= v2);
case Binder::BoundBinaryOperation::GreaterThan: return new BooleanEvalValue(v1 > v2);
case Binder::BoundBinaryOperation::GreaterThanEquals: return new BooleanEvalValue(v1 >= v2);
default: throw exception();
}
} else{
int64_t v2 = std::get<int64_t >(right->_intValue);
switch (operation){
case Binder::BoundBinaryOperation::Addition: return new NumericEvalValue(v1 + v2);
case Binder::BoundBinaryOperation::Subtraction: return new NumericEvalValue(v1 - v2);
case Binder::BoundBinaryOperation::Multiplication: return new NumericEvalValue(v1 * v2);
case Binder::BoundBinaryOperation::Division: return new NumericEvalValue(v1 / v2);
case Binder::BoundBinaryOperation::Equality: return new BooleanEvalValue(v1 == v2);
case Binder::BoundBinaryOperation::Inequality: return new BooleanEvalValue(v1 != v2);
case Binder::BoundBinaryOperation::LessThan: return new BooleanEvalValue(v1 < v2);
case Binder::BoundBinaryOperation::LessThanEquals: return new BooleanEvalValue(v1 <= v2);
case Binder::BoundBinaryOperation::GreaterThan: return new BooleanEvalValue(v1 > v2);
case Binder::BoundBinaryOperation::GreaterThanEquals: return new BooleanEvalValue(v1 >= v2);
default: throw exception();
}
}
}
}
shared_ptr<const NumericEvalValue> NumericEvalValue::operator-(const shared_ptr<const NumericEvalValue> &b) const {
if (this->IsFloat()) {
if (b->IsFloat()) {
return make_shared<FloatEvalValue>(this->GetFloatValue() - b->GetFloatValue());
} else {
return make_shared<FloatEvalValue>(this->GetFloatValue() - (double) b->GetIntegerValue());
}
} else {
if (b->IsFloat()) {
return make_shared<FloatEvalValue>((double) this->GetIntegerValue() - b->GetFloatValue());
} else {
return make_shared<IntegerEvalValue>(this->GetIntegerValue() - b->GetIntegerValue());
EvalValue *NumericEvalValue::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 NumericEvalValue(std::get<int64_t >(_intValue));
}
}
return EvalValue::Cast(castType);
}
shared_ptr<const NumericEvalValue> NumericEvalValue::operator*(const shared_ptr<const NumericEvalValue> &b) const {
if (this->IsFloat()) {
if (b->IsFloat()) {
return make_shared<FloatEvalValue>(this->GetFloatValue() * b->GetFloatValue());
} else {
return make_shared<FloatEvalValue>(this->GetFloatValue() * (double) b->GetIntegerValue());
}
} else {
if (b->IsFloat()) {
return make_shared<FloatEvalValue>((double) this->GetIntegerValue() * b->GetFloatValue());
} else {
return make_shared<IntegerEvalValue>(this->GetIntegerValue() * b->GetIntegerValue());
}
}
EvalValue *NumericEvalValue::Clone() const {
if (_isFloat)
return new NumericEvalValue(std::get<double >(_floatValue));
return new NumericEvalValue(std::get<int64_t >(_intValue));
}
shared_ptr<const NumericEvalValue> NumericEvalValue::operator/(const shared_ptr<const NumericEvalValue> &b) const {
if (this->IsFloat()) {
if (b->IsFloat()) {
return make_shared<FloatEvalValue>(this->GetFloatValue() / b->GetFloatValue());
} else {
return make_shared<FloatEvalValue>(this->GetFloatValue() / (double) b->GetIntegerValue());
}
} else {
if (b->IsFloat()) {
return make_shared<FloatEvalValue>((double) this->GetIntegerValue() / b->GetFloatValue());
} else {
return make_shared<IntegerEvalValue>(this->GetIntegerValue() / b->GetIntegerValue());
}
}
size_t NumericEvalValue::GetHashCode() const {
if (_isFloat)
return std::get<double >(_floatValue);
return std::get<int64_t >(_intValue);;
}
bool NumericEvalValue::operator==(const EvalValue *b) const {
if (b->GetTypeClass() != TypeClass::Number)
return false;
auto numVal = dynamic_cast<const NumericEvalValue*>(b);
if (this->IsFloat() != numVal->IsFloat())
return false;
if (this->IsFloat()) {
return this->EvaluateFloat() == numVal->EvaluateFloat();
} else {
return this->EvaluateInteger() == numVal->EvaluateInteger();
}
}
shared_ptr<const BooleanEvalValue> NumericEvalValue::operator<(const shared_ptr<const NumericEvalValue> &b) const {
if (this->IsFloat()) {
if (b->IsFloat()) {
return make_shared<BooleanEvalValue>(this->GetFloatValue() < b->GetFloatValue());
} else {
return make_shared<BooleanEvalValue>(this->GetFloatValue() < (double) b->GetIntegerValue());
}
} else {
if (b->IsFloat()) {
return make_shared<BooleanEvalValue>((double) this->GetIntegerValue() < b->GetFloatValue());
} else {
return make_shared<BooleanEvalValue>(this->GetIntegerValue() < b->GetIntegerValue());
}
}
}
shared_ptr<const BooleanEvalValue> NumericEvalValue::operator<=(const shared_ptr<const NumericEvalValue> &b) const {
if (this->IsFloat()) {
if (b->IsFloat()) {
return make_shared<BooleanEvalValue>(this->GetFloatValue() <= b->GetFloatValue());
} else {
return make_shared<BooleanEvalValue>(this->GetFloatValue() <=(double) b->GetIntegerValue());
}
} else {
if (b->IsFloat()) {
return make_shared<BooleanEvalValue>((double) this->GetIntegerValue() <= b->GetFloatValue());
} else {
return make_shared<BooleanEvalValue>(this->GetIntegerValue() <= b->GetIntegerValue());
}
}
}
shared_ptr<const BooleanEvalValue> NumericEvalValue::operator>(const shared_ptr<const NumericEvalValue> &b) const {
if (this->IsFloat()) {
if (b->IsFloat()) {
return make_shared<BooleanEvalValue>(this->GetFloatValue() > b->GetFloatValue());
} else {
return make_shared<BooleanEvalValue>(this->GetFloatValue() > (double) b->GetIntegerValue());
}
} else {
if (b->IsFloat()) {
return make_shared<BooleanEvalValue>((double) this->GetIntegerValue() > b->GetFloatValue());
} else {
return make_shared<BooleanEvalValue>(this->GetIntegerValue() > b->GetIntegerValue());
}
}
}
shared_ptr<const BooleanEvalValue> NumericEvalValue::operator>=(const shared_ptr<const NumericEvalValue> &b) const {
if (this->IsFloat()) {
if (b->IsFloat()) {
return make_shared<BooleanEvalValue>(this->GetFloatValue() >= b->GetFloatValue());
} else {
return make_shared<BooleanEvalValue>(this->GetFloatValue() >= (double) b->GetIntegerValue());
}
} else {
if (b->IsFloat()) {
return make_shared<BooleanEvalValue>((double) this->GetIntegerValue() >= b->GetFloatValue());
} else {
return make_shared<BooleanEvalValue>(this->GetIntegerValue() >= b->GetIntegerValue());
}
}
}
EvalValue *IntegerEvalValue::BinaryOperation(Binder::BoundBinaryOperation operation, const EvalValue *b) const {
auto right = dynamic_cast<const NumericEvalValue*>(b);
if (right->IsFloat()){
auto rightVal = right->EvaluateFloat();
switch (operation){
case Binder::BoundBinaryOperation::Addition: return new FloatEvalValue((double)_value + rightVal);
case Binder::BoundBinaryOperation::Subtraction: return new FloatEvalValue((double)_value - rightVal);
case Binder::BoundBinaryOperation::Multiplication: return new FloatEvalValue((double)_value * rightVal);
case Binder::BoundBinaryOperation::Division: return new FloatEvalValue((double)_value / rightVal);
case Binder::BoundBinaryOperation::LessThan: return new BooleanEvalValue((double)_value < rightVal);
case Binder::BoundBinaryOperation::LessThanEquals: return new BooleanEvalValue((double)_value <= rightVal);
case Binder::BoundBinaryOperation::GreaterThan: return new BooleanEvalValue((double)_value > rightVal);
case Binder::BoundBinaryOperation::GreaterThanEquals: return new BooleanEvalValue((double)_value >= rightVal);
default:
throw;
}
} else{
auto rightVal = right->EvaluateInteger();
switch (operation){
case Binder::BoundBinaryOperation::Addition: return new IntegerEvalValue(_value + rightVal);
case Binder::BoundBinaryOperation::Subtraction: return new IntegerEvalValue(_value - rightVal);
case Binder::BoundBinaryOperation::Multiplication: return new IntegerEvalValue(_value * rightVal);
case Binder::BoundBinaryOperation::Division: return new IntegerEvalValue(_value / rightVal);
case Binder::BoundBinaryOperation::LessThan: return new BooleanEvalValue(_value < rightVal);
case Binder::BoundBinaryOperation::LessThanEquals: return new BooleanEvalValue(_value <= rightVal);
case Binder::BoundBinaryOperation::GreaterThan: return new BooleanEvalValue(_value > rightVal);
case Binder::BoundBinaryOperation::GreaterThanEquals: return new BooleanEvalValue(_value >= rightVal);
default:
throw;
}
if (_isFloat != right->_isFloat)
return false;
if (_isFloat){
return _floatValue == right->_floatValue;
}
return _intValue == right->_intValue;
}
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);
int64_t NumericEvalValue::EvaluateInteger() const {
return std::get<int64_t >(_intValue);;
}
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);
double NumericEvalValue::EvaluateFloat() const {
if (!_isFloat)
return std::get<int64_t >(_intValue);
return std::get<double>(_floatValue);
}
u16string NumericEvalValue::EvaluateString() const {
if (_isFloat){
return Utilities::StringUtils::FloatToString(std::get<double >(_floatValue));
}
return Utilities::StringUtils::IntToString(std::get<int64_t >(_intValue));
}
EvalValue *NumericEvalValue::UnaryOperation(Binder::BoundUnaryOperation operation) const {
if (_isFloat){
return new NumericEvalValue(- std::get<double >(_floatValue));
}
return new NumericEvalValue(- std::get<int64_t >(_intValue));
}
}