#ifndef PORYGONLANG_EVALVALUE_HPP #define PORYGONLANG_EVALVALUE_HPP #include #include #include #include "../../ScriptType.hpp" #include "../EvaluationException.hpp" namespace Porygon::Evaluation{ class EvalValue; class Iterator; } #include "../Iterator/Iterator.hpp" #include "../../Binder/BoundOperators.hpp" namespace Porygon::Evaluation { class EvalValue { public: EvalValue() = default; virtual ~EvalValue() = default; [[nodiscard]] virtual TypeClass GetTypeClass() const = 0; [[nodiscard]] virtual bool operator==(const EvalValue *b) const = 0; [[nodiscard]] virtual bool operator!=(const EvalValue *b) const { return !(this->operator==(b)); } [[nodiscard]] virtual EvalValue* Clone() const = 0; [[nodiscard]] virtual long EvaluateInteger() const { throw EvaluationException("Can't evaluate this EvalValue as integer."); } [[nodiscard]] virtual double EvaluateFloat() const { throw EvaluationException("Can't evaluate this EvalValue as float."); } [[nodiscard]] virtual bool EvaluateBool() const { throw EvaluationException("Can't evaluate this EvalValue as bool."); } [[nodiscard]] virtual std::u16string EvaluateString() const { throw EvaluationException("Can't evaluate this EvalValue as string."); } [[nodiscard]] virtual std::size_t GetHashCode() const = 0; [[nodiscard]] virtual const EvalValue* IndexValue(const EvalValue *val) const { throw EvaluationException("Can't index this EvalValue"); } [[nodiscard]] virtual const EvalValue* IndexValue(uint32_t hash) const { throw EvaluationException("Can't index this EvalValue"); } virtual void SetIndexValue(const EvalValue *key, const EvalValue* value) const { throw EvaluationException("Can't index this EvalValue"); } [[nodiscard]] virtual Iterator * GetKeyIterator() const{ throw EvaluationException("Can't iterate over this EvalValue"); } [[nodiscard]] virtual EvalValue* BinaryOperation(Binder::BoundBinaryOperation operation, const EvalValue* b) const{ throw EvaluationException("Binary operations are not implemented for this type."); } [[nodiscard]] virtual EvalValue* UnaryOperation(Binder::BoundUnaryOperation operation) const{ throw EvaluationException("Unary operations are not implemented for this type."); } }; class BooleanEvalValue : public EvalValue { const bool _value; public: explicit BooleanEvalValue(bool val) : _value(val) { } [[nodiscard]] inline EvalValue* Clone() const final { return new BooleanEvalValue(_value); } [[nodiscard]] inline TypeClass GetTypeClass() const final { return TypeClass::Bool; } [[nodiscard]] inline bool EvaluateBool() const final { return _value; } [[nodiscard]] bool operator==(const EvalValue *b) const final { if (b->GetTypeClass() != TypeClass::Bool) return false; return this->EvaluateBool() == b->EvaluateBool(); }; [[nodiscard]] inline std::size_t GetHashCode() const final { return _value; } [[nodiscard]] inline EvalValue* BinaryOperation(Binder::BoundBinaryOperation operation, const EvalValue* b) const final{ auto bVal = b -> EvaluateBool(); switch (operation){ case Binder::BoundBinaryOperation::LogicalAnd: return new BooleanEvalValue(_value && bVal); case Binder::BoundBinaryOperation::LogicalOr: return new BooleanEvalValue(_value || bVal); default: throw; } } [[nodiscard]] EvalValue* UnaryOperation(Binder::BoundUnaryOperation operation) const final{ switch (operation){ case Binder::BoundUnaryOperation::LogicalNegation: return new BooleanEvalValue(!_value); default: throw; } } }; } #endif //PORYGONLANG_EVALVALUE_HPP