Greatly simplify handling numerical eval values, using std::variant
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
@@ -39,11 +39,11 @@ namespace Porygon::Evaluation {
|
||||
|
||||
|
||||
EvalValue *CreateIntegerEvalValue(int64_t l) {
|
||||
return new IntegerEvalValue(l);
|
||||
return new NumericEvalValue(l);
|
||||
}
|
||||
|
||||
EvalValue *CreateFloatEvalValue(double d) {
|
||||
return new FloatEvalValue(d);
|
||||
return new NumericEvalValue(d);
|
||||
}
|
||||
|
||||
EvalValue *CreateBoolEvalValue(bool b) {
|
||||
|
||||
@@ -9,38 +9,38 @@ namespace Porygon::Evaluation{
|
||||
class EvalValueHelper{
|
||||
public:
|
||||
inline static EvalValue* Create(unsigned char i){
|
||||
return new IntegerEvalValue((int64_t )i);
|
||||
return new NumericEvalValue((int64_t )i);
|
||||
}
|
||||
inline static EvalValue* Create(signed char i){
|
||||
return new IntegerEvalValue((int64_t )i);
|
||||
return new NumericEvalValue((int64_t )i);
|
||||
}
|
||||
inline static EvalValue* Create(short int i){
|
||||
return new IntegerEvalValue(i);
|
||||
return new NumericEvalValue(i);
|
||||
}
|
||||
inline static EvalValue* Create(unsigned short int i){
|
||||
return new IntegerEvalValue(i);
|
||||
return new NumericEvalValue(i);
|
||||
}
|
||||
inline static EvalValue* Create(signed int i){
|
||||
return new IntegerEvalValue(i);
|
||||
return new NumericEvalValue(i);
|
||||
}
|
||||
inline static EvalValue* Create(unsigned int i){
|
||||
return new IntegerEvalValue(i);
|
||||
return new NumericEvalValue(static_cast<int64_t>(i));
|
||||
}
|
||||
inline static EvalValue* Create(int64_t l){
|
||||
return new IntegerEvalValue(l);
|
||||
return new NumericEvalValue(l);
|
||||
}
|
||||
inline static EvalValue* Create(uint64_t l){
|
||||
return new IntegerEvalValue(l);
|
||||
return new NumericEvalValue(static_cast<int64_t>(l));
|
||||
}
|
||||
|
||||
inline static EvalValue* Create(float f){
|
||||
return new FloatEvalValue(f);
|
||||
return new NumericEvalValue(f);
|
||||
}
|
||||
inline static EvalValue* Create(double f){
|
||||
return new FloatEvalValue(f);
|
||||
return new NumericEvalValue(f);
|
||||
}
|
||||
inline static EvalValue* Create(long double f){
|
||||
return new FloatEvalValue(f);
|
||||
return new NumericEvalValue(static_cast<double>(f));
|
||||
}
|
||||
|
||||
inline static EvalValue* Create(bool b){
|
||||
@@ -49,8 +49,8 @@ namespace Porygon::Evaluation{
|
||||
inline static EvalValue* Create(const string& s){
|
||||
return new StringEvalValue(Utilities::StringUtils::ToUTF8(s));
|
||||
}
|
||||
inline static EvalValue* Create(u16string s){
|
||||
return new StringEvalValue(std::move(s));
|
||||
inline static EvalValue* Create(const u16string& s){
|
||||
return new StringEvalValue(s);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,195 +3,44 @@
|
||||
#define PORYGONLANG_NUMERICEVALVALUE_HPP
|
||||
|
||||
#include <sstream>
|
||||
#include <variant>
|
||||
#include "EvalValue.hpp"
|
||||
#include "../../Utilities/StringUtils.hpp"
|
||||
|
||||
namespace Porygon::Evaluation {
|
||||
class NumericEvalValue : public EvalValue {
|
||||
std::variant<int64_t , double> _intValue, _floatValue;
|
||||
|
||||
[[nodiscard]]
|
||||
virtual int64_t GetIntegerValue() const = 0;
|
||||
|
||||
[[nodiscard]]
|
||||
virtual double GetFloatValue() const = 0;
|
||||
|
||||
bool _isFloat;
|
||||
public:
|
||||
|
||||
explicit NumericEvalValue(int64_t i) : _intValue(i), _isFloat(false) {}
|
||||
explicit NumericEvalValue(int32_t i) : _intValue(static_cast<int64_t>(i)), _isFloat(false) {}
|
||||
explicit NumericEvalValue(double d) : _floatValue(d), _isFloat(true) {}
|
||||
explicit NumericEvalValue(float f) : _floatValue(f), _isFloat(true) {}
|
||||
|
||||
[[nodiscard]]
|
||||
virtual bool IsFloat() const = 0;
|
||||
virtual bool IsFloat() const{
|
||||
return _isFloat;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
inline TypeClass GetTypeClass() const final {
|
||||
return TypeClass::Number;
|
||||
}
|
||||
|
||||
shared_ptr<const NumericEvalValue> operator+(const shared_ptr<const NumericEvalValue> &b) const;
|
||||
|
||||
shared_ptr<const NumericEvalValue> operator-(const shared_ptr<const NumericEvalValue> &b) const;
|
||||
|
||||
shared_ptr<const NumericEvalValue> operator*(const shared_ptr<const NumericEvalValue> &b) const;
|
||||
|
||||
shared_ptr<const NumericEvalValue> operator/(const shared_ptr<const NumericEvalValue> &b) const;
|
||||
|
||||
shared_ptr<const BooleanEvalValue> operator<(const shared_ptr<const NumericEvalValue> &b) const;
|
||||
|
||||
shared_ptr<const BooleanEvalValue> operator<=(const shared_ptr<const NumericEvalValue> &b) const;
|
||||
|
||||
shared_ptr<const BooleanEvalValue> operator>(const shared_ptr<const NumericEvalValue> &b) const;
|
||||
|
||||
shared_ptr<const BooleanEvalValue> operator>=(const shared_ptr<const NumericEvalValue> &b) const;
|
||||
|
||||
bool operator==(const EvalValue *b) const final;
|
||||
};
|
||||
|
||||
class IntegerEvalValue : public NumericEvalValue {
|
||||
const int64_t _value;
|
||||
[[nodiscard]] EvalValue *Clone() const override;
|
||||
[[nodiscard]] size_t GetHashCode() const override;
|
||||
[[nodiscard]] EvalValue* Cast(shared_ptr<const ScriptType> castType) const final;
|
||||
|
||||
[[nodiscard]]
|
||||
int64_t GetIntegerValue() const final { return _value; }
|
||||
[[nodiscard]] int64_t EvaluateInteger() const override;
|
||||
[[nodiscard]] double EvaluateFloat() const override;
|
||||
[[nodiscard]] u16string EvaluateString() const override;
|
||||
|
||||
[[nodiscard]]
|
||||
double GetFloatValue() const final {
|
||||
throw EvaluationException("Attempting to retrieve float from int eval value.");
|
||||
}
|
||||
|
||||
public:
|
||||
explicit IntegerEvalValue(int64_t value) : _value(value) {
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
inline bool IsFloat() const final {
|
||||
return false;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
inline int64_t EvaluateInteger() const final {
|
||||
return _value;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
inline std::u16string EvaluateString() const final{
|
||||
return Utilities::StringUtils::IntToString(_value);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
inline EvalValue* Clone() const final {
|
||||
return new IntegerEvalValue(_value);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
inline std::size_t GetHashCode() const final {
|
||||
return std::hash<int64_t >{}(_value);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
EvalValue* BinaryOperation(Binder::BoundBinaryOperation operation, const EvalValue* b) const final;
|
||||
|
||||
[[nodiscard]]
|
||||
EvalValue* UnaryOperation(Binder::BoundUnaryOperation operation) const final{
|
||||
switch (operation){
|
||||
case Binder::BoundUnaryOperation::Negation: return new IntegerEvalValue(-_value);
|
||||
default: throw;
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
EvalValue* Cast(shared_ptr<const ScriptType> castType) const final;
|
||||
};
|
||||
|
||||
class FloatEvalValue : public NumericEvalValue {
|
||||
const double _value;
|
||||
|
||||
[[nodiscard]]
|
||||
int64_t GetIntegerValue() const final {
|
||||
throw EvaluationException("Attempting to retrieve int from float eval value.");
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
inline double GetFloatValue() const final {
|
||||
return _value;
|
||||
}
|
||||
|
||||
public:
|
||||
explicit FloatEvalValue(double value) : _value(value) {
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
inline bool IsFloat() const final {
|
||||
return true;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
inline double EvaluateFloat() const final {
|
||||
return _value;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
inline std::u16string EvaluateString() const final{
|
||||
return Utilities::StringUtils::FloatToString(_value);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
inline EvalValue* Clone() const final {
|
||||
return new FloatEvalValue(_value);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
inline std::size_t GetHashCode() const final {
|
||||
return std::hash<double>{}(_value);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
inline EvalValue* BinaryOperation(Binder::BoundBinaryOperation operation, const EvalValue* b) const final{
|
||||
auto right = dynamic_cast<const NumericEvalValue*>(b);
|
||||
if (right->IsFloat()){
|
||||
auto rightVal = right->EvaluateFloat();
|
||||
switch (operation){
|
||||
case Binder::BoundBinaryOperation::Addition: return new FloatEvalValue(_value + rightVal);
|
||||
case Binder::BoundBinaryOperation::Subtraction: return new FloatEvalValue(_value - rightVal);
|
||||
case Binder::BoundBinaryOperation::Multiplication: return new FloatEvalValue(_value * rightVal);
|
||||
case Binder::BoundBinaryOperation::Division: return new FloatEvalValue(_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;
|
||||
}
|
||||
} else {
|
||||
auto rightVal = right->EvaluateInteger();
|
||||
switch (operation) {
|
||||
case Binder::BoundBinaryOperation::Addition:
|
||||
return new IntegerEvalValue((int64_t ) _value + rightVal);
|
||||
case Binder::BoundBinaryOperation::Subtraction:
|
||||
return new IntegerEvalValue((int64_t ) _value - rightVal);
|
||||
case Binder::BoundBinaryOperation::Multiplication:
|
||||
return new IntegerEvalValue((int64_t ) _value * rightVal);
|
||||
case Binder::BoundBinaryOperation::Division:
|
||||
return new IntegerEvalValue((int64_t ) _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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
EvalValue* UnaryOperation(Binder::BoundUnaryOperation operation) const final{
|
||||
switch (operation){
|
||||
case Binder::BoundUnaryOperation::Negation: return new FloatEvalValue(-_value);
|
||||
default: throw;
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
EvalValue* Cast(shared_ptr<const ScriptType> castType) const final;
|
||||
[[nodiscard]] EvalValue *BinaryOperation(Binder::BoundBinaryOperation operation, const EvalValue *b) const final;
|
||||
[[nodiscard]] EvalValue *UnaryOperation(Binder::BoundUnaryOperation operation) const override;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -154,7 +154,7 @@ namespace Porygon::Evaluation {
|
||||
auto statements = *block -> GetStatements();
|
||||
if (step >= 0){
|
||||
for (int64_t i = start; i <= end; i += step){
|
||||
this -> _evaluationScope -> SetVariable(identifier, new IntegerEvalValue(i));
|
||||
this -> _evaluationScope -> SetVariable(identifier, new NumericEvalValue(i));
|
||||
for (auto s: statements) {
|
||||
this->EvaluateStatement(s);
|
||||
if (this->_hasReturned || this -> _hasBroken)
|
||||
@@ -165,7 +165,7 @@ namespace Porygon::Evaluation {
|
||||
}
|
||||
} else{
|
||||
for (int64_t i = start; i >= end; i += step){
|
||||
this -> _evaluationScope -> SetVariable(identifier, new IntegerEvalValue(i));
|
||||
this -> _evaluationScope -> SetVariable(identifier, new NumericEvalValue(i));
|
||||
for (auto s: statements) {
|
||||
this->EvaluateStatement(s);
|
||||
if (this->_hasReturned || this -> _hasBroken)
|
||||
@@ -233,9 +233,9 @@ namespace Porygon::Evaluation {
|
||||
|
||||
case BoundExpressionKind::Bad: throw;
|
||||
case BoundExpressionKind::LiteralInteger:
|
||||
return new IntegerEvalValue(((BoundLiteralIntegerExpression *) expression)->GetValue());
|
||||
return new NumericEvalValue(((BoundLiteralIntegerExpression *) expression)->GetValue());
|
||||
case BoundExpressionKind::LiteralFloat:
|
||||
return new FloatEvalValue(((BoundLiteralFloatExpression *) expression)->GetValue());
|
||||
return new NumericEvalValue(((BoundLiteralFloatExpression *) expression)->GetValue());
|
||||
case BoundExpressionKind::LiteralString:
|
||||
return new StringEvalValue(*((BoundLiteralStringExpression *) expression)->GetValue());
|
||||
case BoundExpressionKind::LiteralBool:
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Porygon::Evaluation{
|
||||
: _vec(table->GetTable()), _size(_vec->size() + 1){}
|
||||
|
||||
inline const EvalValue* GetCurrent() final{
|
||||
return new IntegerEvalValue(_position);
|
||||
return new NumericEvalValue(static_cast<int64_t >(_position));
|
||||
}
|
||||
|
||||
inline bool MoveNext() final{
|
||||
|
||||
Reference in New Issue
Block a user