refactor(furvm): move thing type to types.hpp

This commit is contained in:
2026-09-04 20:59:14 +02:00
parent ddb60ca93a
commit 0354ec1e79
7 changed files with 231 additions and 239 deletions
+39 -173
View File
@@ -5,6 +5,7 @@
#include "furlang/utility/hash.hpp"
#include "furvm/exceptions.hpp"
#include "furvm/fwd.hpp"
#include "furvm/types.hpp"
#include <algorithm>
#include <cassert>
@@ -12,7 +13,6 @@
#include <cstring>
#include <functional>
#include <iterator>
#include <limits>
#include <new>
#include <stdexcept>
#include <type_traits>
@@ -21,124 +21,6 @@
namespace furvm {
struct thing_type {
using s8 = std::int8_t;
using s16 = std::int16_t;
using s32 = std::int32_t;
using s64 = std::int64_t;
using u8 = std::uint8_t;
using u16 = std::uint16_t;
using u32 = std::uint32_t;
using u64 = std::uint64_t;
struct array_value {
thing_type* type;
std::size_t size;
};
struct slice_value {
thing_type* type;
};
enum type { // NOLINT
S8 = 0,
S16,
S32,
S64,
U8,
U16,
U32,
U64,
Ptr,
Ref,
Array,
Slice,
Count,
} type = Count;
union value {
std::nullptr_t null = nullptr;
thing_type* typeRef;
array_value array;
slice_value slice;
value() = default;
value(thing_type* type)
: typeRef(type) {}
value(thing_type* type, std::size_t size)
: array({}) {
array.type = type;
array.size = size;
}
} value;
static constexpr thing_type_id INVALID_ID = std::numeric_limits<thing_type_id>::max();
thing_type_id id = INVALID_ID;
bool operator==(const thing_type& other) const {
if (type != other.type) return false;
switch (type) {
case S8:
case S16:
case S32:
case S64:
case U8:
case U16:
case U32:
case U64: return true;
case Ptr:
case Ref: return *value.typeRef == *other.value.typeRef;
case Array: return *value.array.type == *other.value.array.type && value.array.size == other.value.array.size;
case Slice: return *value.slice.type == *other.value.slice.type;
case Count: break;
}
return false;
}
bool operator!=(const thing_type& other) const { return !this->operator==(other); }
static bool is_primitive(enum type type) {
switch (type) {
case S8:
case S16:
case S32:
case S64:
case U8:
case U16:
case U32:
case U64: return true;
case Ptr:
case Ref:
case Array:
case Slice: return false;
case Count: break;
}
throw std::runtime_error("unreachable");
}
static std::size_t primitive_size(enum type type) {
switch (type) {
case thing_type::S8: return sizeof(s8);
case thing_type::S16: return sizeof(s16);
case thing_type::S32: return sizeof(s32);
case thing_type::S64: return sizeof(s64);
case thing_type::U8: return sizeof(u8);
case thing_type::U16: return sizeof(u16);
case thing_type::U32: return sizeof(u32);
case thing_type::U64: return sizeof(u64);
case Ptr:
case Ref:
case Array:
case Slice: return 0;
case Count: break;
}
throw std::runtime_error("unreachable");
}
};
namespace detail {
struct thing_type_hash {
@@ -633,21 +515,21 @@ public:
*
* @return The integer value.
*/
thing_type::s64 integer() const {
s64 integer() const {
switch (type().type) {
case thing_type::S8: return get<thing_type::s8>();
case thing_type::S16: return get<thing_type::s16>();
case thing_type::S32: return get<thing_type::s32>();
case thing_type::S64: return get<thing_type::s64>();
case thing_type::U8: return get<thing_type::u8>();
case thing_type::U16: return get<thing_type::u16>();
case thing_type::U32: return get<thing_type::u32>();
case thing_type::U64: return get<thing_type::u64>();
case thing_type::S8: return get<s8>();
case thing_type::S16: return get<s16>();
case thing_type::S32: return get<s32>();
case thing_type::S64: return get<s64>();
case thing_type::U8: return get<u8>();
case thing_type::U16: return get<u16>();
case thing_type::U32: return get<u32>();
case thing_type::U64: return get<u64>();
default: throw std::runtime_error("unreachable");
}
}
void resize(thing_type::u64 newSize) {
void resize(u64 newSize) {
if (!is(thing_type::Array)) throw bad_thing_access();
if (type().value.array.size > 0) throw std::runtime_error("cannot resize a static array");
@@ -655,13 +537,13 @@ public:
if (newSize < 0 || newSize == array.size) return;
std::size_t innerSize = compute_size_na(*type().value.array.type);
std::byte* newData = new std::byte[innerSize * newSize];
std::memcpy(newData, array.data, innerSize * std::min(static_cast<thing_type::u64>(array.size), newSize));
std::memcpy(newData, array.data, innerSize * std::min(static_cast<u64>(array.size), newSize));
array.size = newSize;
delete[] array.data;
array.data = newData;
}
thing at(thing_type::u64 index) const {
thing at(u64 index) const {
thing ref = { m_allocator };
ref.m_reference = true;
ref.m_size = compute_size_na(*(ref.m_type = &inner_type()));
@@ -690,7 +572,7 @@ public:
}
}
thing slice(thing_type::u64 begin, thing_type::u64 len) const {
thing slice(u64 begin, u64 len) const {
auto& inner = inner_type();
thing_type sliceType;
@@ -718,7 +600,7 @@ public:
return slice;
}
thing_type::u64 length() const {
u64 length() const {
switch (type().type) {
case thing_type::Array:
return type().value.array.size == 0 ? get<dynamic_array>().size : type().value.array.size;
@@ -833,14 +715,14 @@ private:
private:
static std::size_t compute_size_na(const thing_type& type) {
switch (type.type) {
case thing_type::S8: return sizeof(thing_type::s8);
case thing_type::S16: return sizeof(thing_type::s16);
case thing_type::S32: return sizeof(thing_type::s32);
case thing_type::S64: return sizeof(thing_type::s64);
case thing_type::U8: return sizeof(thing_type::u8);
case thing_type::U16: return sizeof(thing_type::u16);
case thing_type::U32: return sizeof(thing_type::u32);
case thing_type::U64: return sizeof(thing_type::u64);
case thing_type::S8: return sizeof(s8);
case thing_type::S16: return sizeof(s16);
case thing_type::S32: return sizeof(s32);
case thing_type::S64: return sizeof(s64);
case thing_type::U8: return sizeof(u8);
case thing_type::U16: return sizeof(u16);
case thing_type::U32: return sizeof(u32);
case thing_type::U64: return sizeof(u64);
case thing_type::Ptr: return sizeof(void*);
case thing_type::Array:
return type.value.array.size == 0 ? sizeof(dynamic_array)
@@ -859,14 +741,14 @@ private:
template <typename Func>
decltype(auto) visit_primitive(Func&& func) const {
switch (type().type) {
case thing_type::S8: return std::forward<Func>(func)(get<thing_type::s8>());
case thing_type::S16: return std::forward<Func>(func)(get<thing_type::s16>());
case thing_type::S32: return std::forward<Func>(func)(get<thing_type::s32>());
case thing_type::S64: return std::forward<Func>(func)(get<thing_type::s64>());
case thing_type::U8: return std::forward<Func>(func)(get<thing_type::u8>());
case thing_type::U16: return std::forward<Func>(func)(get<thing_type::u16>());
case thing_type::U32: return std::forward<Func>(func)(get<thing_type::u32>());
case thing_type::U64: return std::forward<Func>(func)(get<thing_type::u64>());
case thing_type::S8: return std::forward<Func>(func)(get<s8>());
case thing_type::S16: return std::forward<Func>(func)(get<s16>());
case thing_type::S32: return std::forward<Func>(func)(get<s32>());
case thing_type::S64: return std::forward<Func>(func)(get<s64>());
case thing_type::U8: return std::forward<Func>(func)(get<u8>());
case thing_type::U16: return std::forward<Func>(func)(get<u16>());
case thing_type::U32: return std::forward<Func>(func)(get<u32>());
case thing_type::U64: return std::forward<Func>(func)(get<u64>());
default: throw bad_thing_access();
}
}
@@ -953,30 +835,14 @@ private:
thing res = { thing_type{ resultType }, m_allocator };
switch (resultType) {
case thing_type::S8:
res.get<thing_type::s8>() = Op{}(cast_to<thing_type::s8>(), rhs.cast_to<thing_type::s8>());
return res;
case thing_type::S16:
res.get<thing_type::s16>() = Op{}(cast_to<thing_type::s16>(), rhs.cast_to<thing_type::s16>());
return res;
case thing_type::S32:
res.get<thing_type::s32>() = Op{}(cast_to<thing_type::s32>(), rhs.cast_to<thing_type::s32>());
return res;
case thing_type::S64:
res.get<thing_type::s64>() = Op{}(cast_to<thing_type::s64>(), rhs.cast_to<thing_type::s64>());
return res;
case thing_type::U8:
res.get<thing_type::u8>() = Op{}(cast_to<thing_type::u8>(), rhs.cast_to<thing_type::u8>());
return res;
case thing_type::U16:
res.get<thing_type::u16>() = Op{}(cast_to<thing_type::u16>(), rhs.cast_to<thing_type::u16>());
return res;
case thing_type::U32:
res.get<thing_type::u32>() = Op{}(cast_to<thing_type::u32>(), rhs.cast_to<thing_type::u32>());
return res;
case thing_type::U64:
res.get<thing_type::u64>() = Op{}(cast_to<thing_type::u64>(), rhs.cast_to<thing_type::u64>());
return res;
case thing_type::S8: res.get<s8>() = Op{}(cast_to<s8>(), rhs.cast_to<s8>()); return res;
case thing_type::S16: res.get<s16>() = Op{}(cast_to<s16>(), rhs.cast_to<s16>()); return res;
case thing_type::S32: res.get<s32>() = Op{}(cast_to<s32>(), rhs.cast_to<s32>()); return res;
case thing_type::S64: res.get<s64>() = Op{}(cast_to<s64>(), rhs.cast_to<s64>()); return res;
case thing_type::U8: res.get<u8>() = Op{}(cast_to<u8>(), rhs.cast_to<u8>()); return res;
case thing_type::U16: res.get<u16>() = Op{}(cast_to<u16>(), rhs.cast_to<u16>()); return res;
case thing_type::U32: res.get<u32>() = Op{}(cast_to<u32>(), rhs.cast_to<u32>()); return res;
case thing_type::U64: res.get<u64>() = Op{}(cast_to<u64>(), rhs.cast_to<u64>()); return res;
case thing_type::Ptr: // TODO: Pointer arithmetics
case thing_type::Ref:
case thing_type::Array:
+132
View File
@@ -0,0 +1,132 @@
#ifndef FURVM_TYPES_HPP
#define FURVM_TYPES_HPP
#include "furvm/fwd.hpp"
#include <cstdint>
#include <limits>
#include <stdexcept>
namespace furvm {
using s8 = std::int8_t;
using s16 = std::int16_t;
using s32 = std::int32_t;
using s64 = std::int64_t;
using u8 = std::uint8_t;
using u16 = std::uint16_t;
using u32 = std::uint32_t;
using u64 = std::uint64_t;
struct thing_type {
struct array_value {
thing_type* type;
std::size_t size;
};
struct slice_value {
thing_type* type;
};
enum type { // NOLINT
S8 = 0,
S16,
S32,
S64,
U8,
U16,
U32,
U64,
Ptr,
Ref,
Array,
Slice,
Count,
} type = Count;
union value {
std::nullptr_t null = nullptr;
thing_type* typeRef;
array_value array;
slice_value slice;
value() = default;
value(thing_type* type)
: typeRef(type) {}
value(thing_type* type, std::size_t size)
: array({}) {
array.type = type;
array.size = size;
}
} value;
static constexpr thing_type_id INVALID_ID = std::numeric_limits<thing_type_id>::max();
thing_type_id id = INVALID_ID;
bool operator==(const thing_type& other) const {
if (type != other.type) return false;
switch (type) {
case S8:
case S16:
case S32:
case S64:
case U8:
case U16:
case U32:
case U64: return true;
case Ptr:
case Ref: return *value.typeRef == *other.value.typeRef;
case Array: return *value.array.type == *other.value.array.type && value.array.size == other.value.array.size;
case Slice: return *value.slice.type == *other.value.slice.type;
case Count: break;
}
return false;
}
bool operator!=(const thing_type& other) const { return !this->operator==(other); }
static bool is_primitive(enum type type) {
switch (type) {
case S8:
case S16:
case S32:
case S64:
case U8:
case U16:
case U32:
case U64: return true;
case Ptr:
case Ref:
case Array:
case Slice: return false;
case Count: break;
}
throw std::runtime_error("unreachable");
}
static std::size_t primitive_size(enum type type) {
switch (type) {
case thing_type::S8: return sizeof(s8);
case thing_type::S16: return sizeof(s16);
case thing_type::S32: return sizeof(s32);
case thing_type::S64: return sizeof(s64);
case thing_type::U8: return sizeof(u8);
case thing_type::U16: return sizeof(u16);
case thing_type::U32: return sizeof(u32);
case thing_type::U64: return sizeof(u64);
case Ptr:
case Ref:
case Array:
case Slice: return 0;
case Count: break;
}
throw std::runtime_error("unreachable");
}
};
} // namespace furvm
#endif // FURVM_TYPES_HPP