#include "NumericEvalValue.hpp" namespace Porygon::Evaluation { EvalValue *NumericEvalValue::BinaryOperation(Binder::BoundBinaryOperation operation, const EvalValue *b) const { auto right = dynamic_cast(b); if (_isFloat){ double v1 = std::get(_floatValue); if (right->_isFloat){ double v2 =std::get(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(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(_intValue); if (right->_isFloat){ double v2 =std::get(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(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(); } } } } EvalValue *NumericEvalValue::Cast(shared_ptr castType) const { if (castType->GetClass() == TypeClass::Number){ auto num = static_pointer_cast(castType); if (num->IsFloat() && !this->_isFloat){ return new NumericEvalValue(static_cast(std::get(_intValue))); } else if(!num->IsFloat() && this->_isFloat){ return new NumericEvalValue(static_cast(std::get(_floatValue))); } } return EvalValue::Cast(castType); } EvalValue *NumericEvalValue::Clone() const { if (_isFloat) return new NumericEvalValue(std::get(_floatValue)); return new NumericEvalValue(std::get(_intValue)); } size_t NumericEvalValue::GetHashCode() const { if (_isFloat) return std::get(_floatValue); return std::get(_intValue);; } bool NumericEvalValue::operator==(const EvalValue *b) const { if (b->GetTypeClass() != TypeClass::Number) return false; auto right = dynamic_cast(b); if (_isFloat != right->_isFloat) return false; if (_isFloat){ return _floatValue == right->_floatValue; } return _intValue == right->_intValue; } int64_t NumericEvalValue::EvaluateInteger() const { return std::get(_intValue);; } double NumericEvalValue::EvaluateFloat() const { if (!_isFloat) return std::get(_intValue); return std::get(_floatValue); } u16string NumericEvalValue::EvaluateString() const { if (_isFloat){ return Utilities::StringUtils::FloatToString(std::get(_floatValue)); } return Utilities::StringUtils::IntToString(std::get(_intValue)); } EvalValue *NumericEvalValue::UnaryOperation(Binder::BoundUnaryOperation operation) const { if (_isFloat){ return new NumericEvalValue(- std::get(_floatValue)); } return new NumericEvalValue(- std::get(_intValue)); } }