slige/runtime/value.hpp

159 lines
4.2 KiB
C++
Raw Normal View History

2024-11-08 11:22:42 +00:00
#pragma once
#include <cstdint>
2024-11-20 13:46:19 +00:00
#include <cstdlib>
2024-11-19 04:06:27 +00:00
#include <format>
#include <iostream>
2024-11-08 11:22:42 +00:00
#include <string>
2024-11-19 04:06:27 +00:00
#include <utility>
2024-11-08 11:22:42 +00:00
#include <variant>
namespace sliger {
enum class ValueType {
Null,
Int,
Bool,
String,
Ptr,
};
2024-11-19 04:06:27 +00:00
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();
}
2024-11-08 11:22:42 +00:00
class Values;
struct Null { };
struct Int {
2024-11-11 14:31:54 +00:00
int32_t value;
2024-11-08 11:22:42 +00:00
};
struct Bool {
bool value;
};
struct String {
std::string value;
};
struct Ptr {
uint32_t value;
};
2024-11-20 13:46:19 +00:00
// clang-format off
template <ValueType op> struct ValueTypeToType { };
template <> struct ValueTypeToType<ValueType::Null> { using Type = Null; };
template <> struct ValueTypeToType<ValueType::Int> { using Type = Int; };
template <> struct ValueTypeToType<ValueType::Bool> { using Type = Bool; };
template <> struct ValueTypeToType<ValueType::String> { using Type = String; };
template <> struct ValueTypeToType<ValueType::Ptr> { using Type = Ptr; };
// clang-format on
2024-11-08 11:22:42 +00:00
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; };
2024-11-20 13:46:19 +00:00
template <ValueType VT> inline auto as() -> ValueTypeToType<VT>::Type&
2024-11-19 04:06:27 +00:00
{
try {
2024-11-20 13:46:19 +00:00
return std::get<typename ValueTypeToType<VT>::Type>(value);
2024-11-19 04:06:27 +00:00
} catch (const std::bad_variant_access& ex) {
2024-11-20 13:46:19 +00:00
std::cerr << std::format("error: tried to unwrap {} as {}\n",
value_type_to_string(this->m_type), value_type_to_string(VT));
std::exit(1);
2024-11-19 04:06:27 +00:00
}
}
2024-11-08 11:22:42 +00:00
2024-11-20 13:46:19 +00:00
template <ValueType VT>
inline auto as() const -> const ValueTypeToType<VT>::Type&
2024-11-19 04:06:27 +00:00
{
try {
2024-11-20 13:46:19 +00:00
return std::get<typename ValueTypeToType<VT>::Type>(value);
2024-11-19 04:06:27 +00:00
} catch (const std::bad_variant_access& ex) {
2024-11-20 13:46:19 +00:00
std::cerr << std::format("error: tried to unwrap {} as {}\n",
value_type_to_string(this->m_type), value_type_to_string(VT));
std::exit(1);
2024-11-19 04:06:27 +00:00
}
}
2024-11-08 11:22:42 +00:00
2024-11-20 13:46:19 +00:00
// clang-format off
inline auto as_null() -> Null& { return as<ValueType::Null>(); }
inline auto as_int() -> Int& { return as<ValueType::Int>(); }
inline auto as_bool() -> Bool& { return as<ValueType::Bool>(); }
inline auto as_string() -> String& { return as<ValueType::String>(); }
inline auto as_ptr() -> Ptr& { return as<ValueType::Ptr>(); }
2024-11-08 11:22:42 +00:00
2024-11-20 13:46:19 +00:00
inline auto as_null() const -> const Null& { return as<ValueType::Null>(); }
inline auto as_int() const -> const Int& { return as<ValueType::Int>(); }
inline auto as_bool() const -> const Bool& { return as<ValueType::Bool>(); }
inline auto as_string() const -> const String& { return as<ValueType::String>(); }
inline auto as_ptr() const -> const Ptr& { return as<ValueType::Ptr>(); }
// clang-format on
2024-11-19 04:06:27 +00:00
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());
}
2024-11-08 11:22:42 +00:00
private:
ValueType m_type;
std::variant<Null, Int, Bool, String, Ptr> value;
};
}