PorygonLang/src/Evaluator/EvalValues/StringEvalValue.hpp

83 lines
2.7 KiB
C++

#ifndef PORYGONLANG_STRINGEVALVALUE_HPP
#define PORYGONLANG_STRINGEVALVALUE_HPP
#include <string>
#include "EvalValue.hpp"
#include "NumericEvalValue.hpp"
#include "../../Utilities/HashedString.hpp"
using namespace std;
namespace Porygon::Evaluation {
class StringEvalValue : public EvalValue {
shared_ptr<u16string> _value;
size_t _hash;
explicit StringEvalValue(shared_ptr<u16string> s) : _value(move(s)){
_hash = Utilities::HashedString::ConstHash(_value->c_str());
}
public:
explicit StringEvalValue(const u16string& s) : _value(make_shared<u16string>(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<char16_t> stringStream;
stringStream << *_value;
stringStream << b->EvaluateString();
auto str = stringStream.str();
return new StringEvalValue(str);
}
[[nodiscard]] EvalValue *UnaryOperation(Binder::BoundUnaryOperation operation) const override {
if (operation == Binder::BoundUnaryOperation ::Count){
return new NumericEvalValue(static_cast<int64_t >(_value->size()));
}
return EvalValue::UnaryOperation(operation);
}
};
}
#endif //PORYGONLANG_STRINGEVALVALUE_HPP