#ifndef PORYGONLANG_STRINGEVALVALUE_HPP #define PORYGONLANG_STRINGEVALVALUE_HPP #include #include "EvalValue.hpp" #include "../../Utilities/HashedString.hpp" using namespace std; namespace Porygon::Evaluation { class StringEvalValue : public EvalValue { shared_ptr _value; size_t _hash; explicit StringEvalValue(shared_ptr s) : _value(move(s)){ _hash = Utilities::HashedString::ConstHash(_value->c_str()); } public: explicit StringEvalValue(const u16string& s) : _value(make_shared(s)){ _hash = Utilities::HashedString::ConstHash(_value->c_str()); } [[nodiscard]] inline TypeClass GetTypeClass() const final { return TypeClass::String; } bool operator==(const EvalValue *b) const final { if (b->GetTypeClass() != TypeClass::String) return false; return this->_hash == b->GetHashCode(); }; bool operator!=(const EvalValue *b) const override { return !operator==(b); } [[nodiscard]] inline u16string EvaluateString() const final { return *_value.get(); } [[nodiscard]] inline EvalValue* Clone() const final { return new StringEvalValue(_value); } EvalValue* IndexValue(const EvalValue *val) const final { // Porygon is 1-indexed, so we convert to that. auto l = val->EvaluateInteger() - 1; return new StringEvalValue(u16string(1, (*_value)[l])); } [[nodiscard]] inline std::size_t GetHashCode() const final { return _hash; } [[nodiscard]] inline EvalValue* BinaryOperation(Binder::BoundBinaryOperation operation, const EvalValue* b) const final{ if (operation != Binder::BoundBinaryOperation::Concatenation){ throw EvaluationException("Binary operation not supported for strings."); } std::basic_ostringstream stringStream; stringStream << *_value; stringStream << b->EvaluateString(); auto str = stringStream.str(); return new StringEvalValue(str); } }; } #endif //PORYGONLANG_STRINGEVALVALUE_HPP