#include "NumericEvalValue.hpp" namespace Porygon::Evaluation { shared_ptr NumericEvalValue::operator+(const shared_ptr &b) const { if (this->IsFloat()) { if (b->IsFloat()) { return make_shared(this->GetFloatValue() + b->GetFloatValue()); } else { return make_shared(this->GetFloatValue() + (double) b->GetIntegerValue()); } } else { if (b->IsFloat()) { return make_shared((double) this->GetIntegerValue() + b->GetFloatValue()); } else { return make_shared(this->GetIntegerValue() + b->GetIntegerValue()); } } } shared_ptr NumericEvalValue::operator-(const shared_ptr &b) const { if (this->IsFloat()) { if (b->IsFloat()) { return make_shared(this->GetFloatValue() - b->GetFloatValue()); } else { return make_shared(this->GetFloatValue() - (double) b->GetIntegerValue()); } } else { if (b->IsFloat()) { return make_shared((double) this->GetIntegerValue() - b->GetFloatValue()); } else { return make_shared(this->GetIntegerValue() - b->GetIntegerValue()); } } } shared_ptr NumericEvalValue::operator*(const shared_ptr &b) const { if (this->IsFloat()) { if (b->IsFloat()) { return make_shared(this->GetFloatValue() * b->GetFloatValue()); } else { return make_shared(this->GetFloatValue() * (double) b->GetIntegerValue()); } } else { if (b->IsFloat()) { return make_shared((double) this->GetIntegerValue() * b->GetFloatValue()); } else { return make_shared(this->GetIntegerValue() * b->GetIntegerValue()); } } } shared_ptr NumericEvalValue::operator/(const shared_ptr &b) const { if (this->IsFloat()) { if (b->IsFloat()) { return make_shared(this->GetFloatValue() / b->GetFloatValue()); } else { return make_shared(this->GetFloatValue() / (double) b->GetIntegerValue()); } } else { if (b->IsFloat()) { return make_shared((double) this->GetIntegerValue() / b->GetFloatValue()); } else { return make_shared(this->GetIntegerValue() / b->GetIntegerValue()); } } } bool NumericEvalValue::operator==(const EvalValue *b) const { if (b->GetTypeClass() != TypeClass::Number) return false; auto numVal = dynamic_cast(b); if (this->IsFloat() != numVal->IsFloat()) return false; if (this->IsFloat()) { return this->EvaluateFloat() == numVal->EvaluateFloat(); } else { return this->EvaluateInteger() == numVal->EvaluateInteger(); } } shared_ptr NumericEvalValue::operator<(const shared_ptr &b) const { if (this->IsFloat()) { if (b->IsFloat()) { return make_shared(this->GetFloatValue() < b->GetFloatValue()); } else { return make_shared(this->GetFloatValue() < (double) b->GetIntegerValue()); } } else { if (b->IsFloat()) { return make_shared((double) this->GetIntegerValue() < b->GetFloatValue()); } else { return make_shared(this->GetIntegerValue() < b->GetIntegerValue()); } } } shared_ptr NumericEvalValue::operator<=(const shared_ptr &b) const { if (this->IsFloat()) { if (b->IsFloat()) { return make_shared(this->GetFloatValue() <= b->GetFloatValue()); } else { return make_shared(this->GetFloatValue() <=(double) b->GetIntegerValue()); } } else { if (b->IsFloat()) { return make_shared((double) this->GetIntegerValue() <= b->GetFloatValue()); } else { return make_shared(this->GetIntegerValue() <= b->GetIntegerValue()); } } } shared_ptr NumericEvalValue::operator>(const shared_ptr &b) const { if (this->IsFloat()) { if (b->IsFloat()) { return make_shared(this->GetFloatValue() > b->GetFloatValue()); } else { return make_shared(this->GetFloatValue() > (double) b->GetIntegerValue()); } } else { if (b->IsFloat()) { return make_shared((double) this->GetIntegerValue() > b->GetFloatValue()); } else { return make_shared(this->GetIntegerValue() > b->GetIntegerValue()); } } } shared_ptr NumericEvalValue::operator>=(const shared_ptr &b) const { if (this->IsFloat()) { if (b->IsFloat()) { return make_shared(this->GetFloatValue() >= b->GetFloatValue()); } else { return make_shared(this->GetFloatValue() >= (double) b->GetIntegerValue()); } } else { if (b->IsFloat()) { return make_shared((double) this->GetIntegerValue() >= b->GetFloatValue()); } else { return make_shared(this->GetIntegerValue() >= b->GetIntegerValue()); } } } EvalValue *IntegerEvalValue::BinaryOperation(Binder::BoundBinaryOperation operation, const EvalValue *b) const { auto right = dynamic_cast(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; } } } EvalValue *IntegerEvalValue::Cast(shared_ptr castType) const { if (castType->GetClass() == TypeClass::Number){ auto num = static_pointer_cast(castType); if (num->IsFloat()){ return new FloatEvalValue(GetIntegerValue()); } } return EvalValue::Cast(castType); } EvalValue *FloatEvalValue::Cast(shared_ptr castType) const { if (castType->GetClass() == TypeClass::Number){ auto num = static_pointer_cast(castType); if (!num->IsFloat()){ return new IntegerEvalValue(GetFloatValue()); } } return EvalValue::Cast(castType); } }