PorygonLang/src/Evaluator/EvalValues/NumericEvalValue.cpp

143 lines
7.6 KiB
C++

#include "NumericEvalValue.hpp"
namespace Porygon::Evaluation {
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{
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();
}
}
}
}
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() && !this->_isFloat){
return new NumericEvalValue(static_cast<double>(std::get<int64_t >(_intValue)));
}
else if(!num->IsFloat() && this->_isFloat){
return new NumericEvalValue(static_cast<int64_t>(std::get<double >(_floatValue)));
}
}
return EvalValue::Cast(castType);
}
EvalValue *NumericEvalValue::Clone() const {
if (_isFloat)
return new NumericEvalValue(std::get<double >(_floatValue));
return new NumericEvalValue(std::get<int64_t >(_intValue));
}
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 right = dynamic_cast<const NumericEvalValue*>(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<int64_t >(_intValue);;
}
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));
}
}