2019-05-24 17:14:30 +00:00
|
|
|
|
|
|
|
#ifndef PORYGONLANG_NUMERICEVALVALUE_HPP
|
|
|
|
#define PORYGONLANG_NUMERICEVALVALUE_HPP
|
|
|
|
|
2019-05-25 14:15:20 +00:00
|
|
|
#include <sstream>
|
2019-05-24 17:14:30 +00:00
|
|
|
#include "EvalValue.hpp"
|
2019-06-23 13:58:14 +00:00
|
|
|
#include "../../Utilities/StringUtils.hpp"
|
|
|
|
|
2019-06-17 16:35:12 +00:00
|
|
|
namespace Porygon::Evaluation {
|
|
|
|
class NumericEvalValue : public EvalValue {
|
2019-05-24 17:14:30 +00:00
|
|
|
|
2019-07-25 15:23:54 +00:00
|
|
|
[[nodiscard]]
|
|
|
|
virtual long GetIntegerValue() const = 0;
|
2019-06-17 16:35:12 +00:00
|
|
|
|
2019-07-25 15:23:54 +00:00
|
|
|
[[nodiscard]]
|
|
|
|
virtual double GetFloatValue() const = 0;
|
2019-06-17 16:35:12 +00:00
|
|
|
|
|
|
|
public:
|
2019-07-25 15:23:54 +00:00
|
|
|
[[nodiscard]]
|
|
|
|
virtual bool IsFloat() const = 0;
|
2019-06-17 16:35:12 +00:00
|
|
|
|
2019-07-25 15:23:54 +00:00
|
|
|
[[nodiscard]]
|
|
|
|
inline TypeClass GetTypeClass() const final {
|
2019-06-17 16:35:12 +00:00
|
|
|
return TypeClass::Number;
|
|
|
|
}
|
|
|
|
|
2019-07-25 15:23:54 +00:00
|
|
|
shared_ptr<const NumericEvalValue> operator+(const shared_ptr<const NumericEvalValue> &b) const;
|
2019-06-17 16:35:12 +00:00
|
|
|
|
2019-07-25 15:23:54 +00:00
|
|
|
shared_ptr<const NumericEvalValue> operator-(const shared_ptr<const NumericEvalValue> &b) const;
|
2019-06-17 16:35:12 +00:00
|
|
|
|
2019-07-25 15:23:54 +00:00
|
|
|
shared_ptr<const NumericEvalValue> operator*(const shared_ptr<const NumericEvalValue> &b) const;
|
2019-06-17 16:35:12 +00:00
|
|
|
|
2019-07-25 15:23:54 +00:00
|
|
|
shared_ptr<const NumericEvalValue> operator/(const shared_ptr<const NumericEvalValue> &b) const;
|
2019-06-17 16:35:12 +00:00
|
|
|
|
2019-07-25 15:23:54 +00:00
|
|
|
shared_ptr<const BooleanEvalValue> operator<(const shared_ptr<const NumericEvalValue> &b) const;
|
2019-06-17 16:35:12 +00:00
|
|
|
|
2019-07-25 15:23:54 +00:00
|
|
|
shared_ptr<const BooleanEvalValue> operator<=(const shared_ptr<const NumericEvalValue> &b) const;
|
2019-06-17 16:35:12 +00:00
|
|
|
|
2019-07-25 15:23:54 +00:00
|
|
|
shared_ptr<const BooleanEvalValue> operator>(const shared_ptr<const NumericEvalValue> &b) const;
|
2019-06-17 16:35:12 +00:00
|
|
|
|
2019-07-25 15:23:54 +00:00
|
|
|
shared_ptr<const BooleanEvalValue> operator>=(const shared_ptr<const NumericEvalValue> &b) const;
|
2019-06-17 16:35:12 +00:00
|
|
|
|
2019-07-25 15:23:54 +00:00
|
|
|
bool operator==(const EvalValue *b) const final;
|
2019-06-17 16:35:12 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class IntegerEvalValue : public NumericEvalValue {
|
|
|
|
const long _value;
|
|
|
|
|
2019-07-25 15:23:54 +00:00
|
|
|
[[nodiscard]]
|
|
|
|
long GetIntegerValue() const final { return _value; }
|
2019-06-17 16:35:12 +00:00
|
|
|
|
2019-07-25 15:23:54 +00:00
|
|
|
[[nodiscard]]
|
|
|
|
double GetFloatValue() const final {
|
2019-06-17 16:35:12 +00:00
|
|
|
throw EvaluationException("Attempting to retrieve float from int eval value.");
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
explicit IntegerEvalValue(long value) : _value(value) {
|
|
|
|
}
|
|
|
|
|
2019-07-25 15:23:54 +00:00
|
|
|
[[nodiscard]]
|
|
|
|
inline bool IsFloat() const final {
|
2019-06-17 16:35:12 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-07-25 15:23:54 +00:00
|
|
|
[[nodiscard]]
|
|
|
|
inline long EvaluateInteger() const final {
|
2019-06-17 16:35:12 +00:00
|
|
|
return _value;
|
|
|
|
}
|
|
|
|
|
2019-07-25 15:23:54 +00:00
|
|
|
[[nodiscard]]
|
|
|
|
inline std::u16string EvaluateString() const final{
|
2019-06-23 13:58:14 +00:00
|
|
|
return Utilities::StringUtils::IntToString(_value);
|
|
|
|
}
|
|
|
|
|
2019-07-25 15:23:54 +00:00
|
|
|
[[nodiscard]]
|
2019-07-27 15:59:42 +00:00
|
|
|
inline EvalValue* Clone() const final {
|
|
|
|
return new IntegerEvalValue(_value);
|
2019-06-17 16:35:12 +00:00
|
|
|
}
|
|
|
|
|
2019-07-25 15:23:54 +00:00
|
|
|
[[nodiscard]]
|
|
|
|
inline std::size_t GetHashCode() const final {
|
2019-06-17 16:35:12 +00:00
|
|
|
return std::hash<long>{}(_value);
|
|
|
|
}
|
2019-07-27 15:59:42 +00:00
|
|
|
|
|
|
|
[[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;
|
|
|
|
}
|
|
|
|
}
|
2019-06-17 16:35:12 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class FloatEvalValue : public NumericEvalValue {
|
|
|
|
const double _value;
|
|
|
|
|
2019-07-25 15:23:54 +00:00
|
|
|
[[nodiscard]]
|
|
|
|
inline long GetIntegerValue() const final {
|
2019-06-17 16:35:12 +00:00
|
|
|
throw EvaluationException("Attempting to retrieve float from int eval value.");
|
|
|
|
}
|
|
|
|
|
2019-07-25 15:23:54 +00:00
|
|
|
[[nodiscard]]
|
|
|
|
inline double GetFloatValue() const final {
|
2019-07-04 17:08:13 +00:00
|
|
|
return _value;
|
|
|
|
}
|
2019-06-17 16:35:12 +00:00
|
|
|
|
|
|
|
public:
|
|
|
|
explicit FloatEvalValue(double value) : _value(value) {
|
|
|
|
}
|
|
|
|
|
2019-07-25 15:23:54 +00:00
|
|
|
[[nodiscard]]
|
|
|
|
inline bool IsFloat() const final {
|
2019-06-17 16:35:12 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-07-25 15:23:54 +00:00
|
|
|
[[nodiscard]]
|
|
|
|
inline double EvaluateFloat() const final {
|
2019-06-17 16:35:12 +00:00
|
|
|
return _value;
|
|
|
|
}
|
|
|
|
|
2019-07-25 15:23:54 +00:00
|
|
|
[[nodiscard]]
|
2019-07-27 15:59:42 +00:00
|
|
|
inline EvalValue* Clone() const final {
|
|
|
|
return new FloatEvalValue(_value);
|
2019-06-17 16:35:12 +00:00
|
|
|
}
|
|
|
|
|
2019-07-25 15:23:54 +00:00
|
|
|
[[nodiscard]]
|
|
|
|
inline std::size_t GetHashCode() const final {
|
2019-06-17 16:35:12 +00:00
|
|
|
return std::hash<double>{}(_value);
|
|
|
|
}
|
2019-07-27 15:59:42 +00:00
|
|
|
|
|
|
|
[[nodiscard]]
|
2019-07-27 16:47:29 +00:00
|
|
|
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((long) _value + rightVal);
|
|
|
|
case Binder::BoundBinaryOperation::Subtraction:
|
|
|
|
return new IntegerEvalValue((long) _value - rightVal);
|
|
|
|
case Binder::BoundBinaryOperation::Multiplication:
|
|
|
|
return new IntegerEvalValue((long) _value * rightVal);
|
|
|
|
case Binder::BoundBinaryOperation::Division:
|
|
|
|
return new IntegerEvalValue((long) _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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-07-27 15:59:42 +00:00
|
|
|
|
|
|
|
[[nodiscard]]
|
|
|
|
EvalValue* UnaryOperation(Binder::BoundUnaryOperation operation) const final{
|
|
|
|
switch (operation){
|
|
|
|
case Binder::BoundUnaryOperation::Negation: return new FloatEvalValue(-_value);
|
|
|
|
default: throw;
|
|
|
|
}
|
|
|
|
}
|
2019-06-17 16:35:12 +00:00
|
|
|
};
|
|
|
|
}
|
2019-05-24 17:14:30 +00:00
|
|
|
|
|
|
|
#endif //PORYGONLANG_NUMERICEVALVALUE_HPP
|