#pragma once #include #include #include #include #include #include namespace sliger { enum class ValueType { Null, Int, Bool, String, Ptr, }; inline auto value_type_to_string(ValueType type) -> std::string { switch (type) { case ValueType::Null: return "Null"; case ValueType::Int: return "Int"; case ValueType::Bool: return "Bool"; case ValueType::String: return "String"; case ValueType::Ptr: return "Ptr"; } std::unreachable(); } class Values; struct Null { }; struct Int { int32_t value; }; struct Bool { bool value; }; struct String { std::string value; }; struct Ptr { uint32_t value; }; class Value { public: Value(Null&& value) : m_type(ValueType::Null) , value(value) { } Value(Int&& value) : m_type(ValueType::Int) , value(value) { } Value(Bool&& value) : m_type(ValueType::Bool) , value(value) { } Value(String&& value) : m_type(ValueType::String) , value(value) { } Value(Ptr&& value) : m_type(ValueType::Ptr) , value(value) { } inline auto type() const -> ValueType { return m_type; }; inline auto as_null() -> Null& { // try { return std::get(value); } catch (const std::bad_variant_access& ex) { std::cout << std::format("tried to unwrap {} as Null\n", value_type_to_string(this->m_type)); throw; } } inline auto as_null() const -> const Null& { // try { return std::get(value); } catch (const std::bad_variant_access& ex) { std::cout << std::format("tried to unwrap {} as Null\n", value_type_to_string(this->m_type)); throw; } } inline auto as_int() -> Int& { // try { return std::get(value); } catch (const std::bad_variant_access& ex) { std::cout << std::format("tried to unwrap {} as Int\n", value_type_to_string(this->m_type)); throw; } } inline auto as_int() const -> const Int& { // try { return std::get(value); } catch (const std::bad_variant_access& ex) { std::cout << std::format("tried to unwrap {} as Int\n", value_type_to_string(this->m_type)); throw; } } inline auto as_bool() -> Bool& { // try { return std::get(value); } catch (const std::bad_variant_access& ex) { std::cout << std::format("tried to unwrap {} as Bool\n", value_type_to_string(this->m_type)); throw; } } inline auto as_bool() const -> const Bool& { // try { return std::get(value); } catch (const std::bad_variant_access& ex) { std::cout << std::format("tried to unwrap {} as Bool\n", value_type_to_string(this->m_type)); throw; } } inline auto as_string() -> String& { // try { return std::get(value); } catch (const std::bad_variant_access& ex) { std::cout << std::format("tried to unwrap {} as String\n", value_type_to_string(this->m_type)); throw; } } inline auto as_string() const -> const String& { // try { return std::get(value); } catch (const std::bad_variant_access& ex) { std::cout << std::format("tried to unwrap {} as String\n", value_type_to_string(this->m_type)); throw; } } inline auto as_ptr() -> Ptr& { // try { return std::get(value); } catch (const std::bad_variant_access& ex) { std::cout << std::format("tried to unwrap {} as Ptr\n", value_type_to_string(this->m_type)); throw; } } inline auto as_ptr() const -> const Ptr& { // try { return std::get(value); } catch (const std::bad_variant_access& ex) { std::cout << std::format("tried to unwrap {} as Ptr\n", value_type_to_string(this->m_type)); throw; } } inline auto to_string() const -> std::string { switch (this->m_type) { case ValueType::Null: return "null"; case ValueType::Int: return std::to_string(as_int().value); case ValueType::Bool: return as_bool().value ? "true" : "false"; case ValueType::String: return std::format("\"{}\"", as_string().value); case ValueType::Ptr: return std::to_string(as_ptr().value); } std::unreachable(); } inline auto to_repr_string() const -> std::string { return std::format( "{}({})", value_type_to_string(this->m_type), to_string()); } private: ValueType m_type; std::variant value; }; }