PorygonLang/src/Evaluator/EvalValues/EvalValue.hpp

165 lines
5.1 KiB
C++

#ifndef PORYGONLANG_EVALVALUE_HPP
#define PORYGONLANG_EVALVALUE_HPP
#include <string>
#include <sstream>
#include <memory>
#include "../../ScriptTypes/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 int64_t 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 {
std::stringstream err;
err << "Can't index this EvalValue: " << ToString() << " with key: " << val->ToString();
throw EvaluationException(err.str());
}
[[nodiscard]]
virtual const EvalValue* IndexValue(const Utilities::HashedString* hash) const {
std::stringstream err;
err << "Can't index this EvalValue: " << ToString() << " with key hash: " << hash->GetDebugString();
throw EvaluationException(err.str());
}
virtual void SetIndexValue(const EvalValue *key, const EvalValue* value) const {
std::stringstream err;
err << "Can't index this EvalValue: " << ToString() << " with key: " << value->ToString();
throw EvaluationException(err.str());
}
[[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.");
}
[[nodiscard]]
virtual EvalValue* Cast(shared_ptr<const ScriptType> castType) const{
throw new EvaluationException("Casting to invalid type.");
}
virtual std::string ToString() const{
std::stringstream s;
s << "Type: " << ScriptType::ToString(this->GetTypeClass());
return s.str();
}
};
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