refactor: replace type_p with type_ref in thing

Damn, this was such a great call.

Closes: #46
This commit is contained in:
2026-07-07 19:29:30 +02:00
parent 2519560451
commit 7de645d323
5 changed files with 76 additions and 94 deletions
+42 -58
View File
@@ -28,19 +28,10 @@ public:
/**
* @brief Constructs a thing.
*
* @param type Thing type.
* @param type Thing type reference.
* @param allocator Allocator for the thing's data.
*/
thing(const type& type, const mod_container& modules = nullptr, const allocator_type& allocator = {})
: thing(std::make_shared<class type>(type), modules, allocator) {}
/**
* @brief Constructs a thing.
*
* @param type Thing type.
* @param allocator Allocator for the thing's data.
*/
thing(const type_p& type, const mod_container& modules = nullptr, const allocator_type& allocator = {})
thing(const type_ref& type, const mod_container& modules = nullptr, const allocator_type& allocator = {})
: m_type(type), m_size(compute_size(resolve_type(type, modules))), m_modules(modules), m_allocator(allocator) {
// TODO: Account for alignment
m_data = m_allocator.allocate(m_size);
@@ -94,15 +85,16 @@ public:
* @return A clone of this thing.
*/
thing clone() const {
auto type = resolve_type(m_type, m_modules);
auto type = resolve_type(m_type, m_modules);
if (m_size == 0) {
return reference();
}
thing res(type, m_modules, m_allocator);
switch (type->t) {
case type_t::Primitive:
case type_t::Reference: {
std::memcpy(res.m_data, m_data, m_size);
} break;
case type_t::Array: {
copy_list(type, res.get<array_t>(), get<array_t>());
copy_list(*type.type, res.get<array_t>(), get<array_t>());
} break;
case type_t::Import:
default: throw std::runtime_error("unreachable");
@@ -111,18 +103,18 @@ public:
}
public:
/**
* @brief Returns the thing's type.
* @brief Returns the thing's type reference.
*
* @return The type.
*/
constexpr auto type() const { return *m_type; }
/**
* @brief Returns the thing's type.
*
* @return The shared pointer to the type.
* @return The type reference.
*/
auto type() { return m_type; }
/**
* @brief Returns the thing's type reference.
*
* @return The type reference.
*/
constexpr auto type() const { return m_type; }
public:
/**
* @brief Returns a raw data pointer.
@@ -266,18 +258,9 @@ public:
}
}
thing reference() const {
thing res = { std::make_shared<class type>(m_type), m_modules, m_allocator };
res.get<reference_t>() = m_data;
return std::move(res);
}
thing reference() const { return { m_type, m_data, m_modules, m_allocator }; }
thing resolve() const {
thing rsv = { resolve_type(m_type, m_modules), m_data, m_allocator };
while (rsv.type()->t == type_t::Reference)
rsv = { rsv.m_type->reference, rsv.get<reference_t>(), std::move(rsv.m_allocator) };
return rsv;
}
constexpr bool is_reference() const { return m_size == 0; }
void resize(long_t newSize) {
if (m_type->t != type_t::Array) throw bad_thing_access();
@@ -297,18 +280,18 @@ public:
if (m_type->t != type_t::Array) throw bad_thing_access();
std::size_t elementSize = compute_size_na(*m_type->array.type);
thing res = { std::make_shared<class type>(*m_type->array.type), m_modules, m_allocator };
if (m_type->array.size == 0) {
auto& array = get<array_t>();
if (index < 0 || index >= array.dynamic.size) throw std::out_of_range("index out of range");
res.get<reference_t>() = array.dynamic.data + (index * elementSize);
return std::move(res);
return { { m_type.mod, m_type->array.type },
array.dynamic.data + (index * elementSize),
m_modules,
m_allocator };
}
std::byte* data = reinterpret_cast<array_t*>(m_data)->data;
if (index < 0 || index >= m_type->array.size) throw std::out_of_range("index out of range");
res.get<reference_t>() = data + (index * elementSize);
return std::move(res);
return { { m_type.mod, m_type->array.type }, data + (index * elementSize), m_modules, m_allocator };
}
std::size_t size() const {
@@ -317,10 +300,12 @@ public:
return m_type->array.size;
}
public:
static type_p resolve_type(const type_p& initType, const mod_container& modules) {
type_p rsv = initType;
while (rsv->t == type_t::Import)
rsv = *modules->at(initType->imp.mod)->type_at(initType->imp.type);
static type_ref resolve_type(const type_ref& initType, const mod_container& modules) {
type_ref rsv = initType;
while (rsv->t == type_t::Import) {
auto mod = modules->at(initType->imp.mod);
rsv = type_ref{ mod, mod->type_at(initType->imp.type) };
}
return rsv;
}
private:
@@ -350,8 +335,7 @@ private:
}
switch (innerType->t) {
case type_t::Primitive:
case type_t::Reference: std::memcpy(dst.data, src.data, size); break;
case type_t::Primitive: std::memcpy(dst.data, src.data, size); break;
case type_t::Array:
for (std::size_t i = 0; i < size; ++i) {
copy_list(*innerType->array.type,
@@ -366,7 +350,6 @@ private:
static std::size_t compute_size_na(const type_p& type) {
switch (type->t) {
case type_t::Primitive: return type->primitive;
case type_t::Reference: return sizeof(reference_t);
case type_t::Array: {
if (type->array.size == 0) return sizeof(array_t);
return compute_size_na(*type->array.type) * type->array.size;
@@ -377,23 +360,24 @@ private:
throw std::runtime_error("unreachable");
}
static std::size_t compute_size_na(const type_ref& type) { return compute_size_na(*type.type); }
// NOTE: Align to 4 bytes
static std::size_t compute_size(const type_p& type) { return (compute_size_na(type) + 3) & ~3; }
static std::size_t compute_size(const type_ref& type) { return compute_size(*type.type); }
private:
thing(const type_p& type, std::byte* data, const allocator_type& allocator = {})
: m_type(type), m_size(0), m_data(data), m_allocator(allocator) {}
thing(const type_ref& type, std::byte* data, const mod_container& modules, const allocator_type& allocator = {})
: m_type(type), m_size(0), m_data(data), m_modules(modules), m_allocator(allocator) {}
private:
template <typename Op>
thing binary_op(const thing& rhs, const Op& op) const {
const thing lhsRsv = resolve();
const thing rhsRsv = rhs.resolve();
if (m_type->t == type_t::Primitive && rhs.type()->t == type_t::Primitive) {
type_ref type = m_type->primitive >= rhs.type()->primitive ? m_type : rhs.type();
std::size_t size = std::max(m_type->primitive, rhs.type()->primitive);
if (lhsRsv.type().t == type_t::Primitive && rhsRsv.type().t == type_t::Primitive) {
std::size_t size = std::max(lhsRsv.type().primitive, rhsRsv.type().primitive);
long_t result = op(integer(), rhs.integer());
long_t result = op(lhsRsv.integer(), rhsRsv.integer());
thing res({ size }, m_modules, m_allocator);
thing res(type, m_modules, m_allocator);
switch (size) {
case sizeof(byte_t): res.get<byte_t>() = result; break;
case sizeof(short_t): res.get<short_t>() = result; break;
@@ -407,7 +391,7 @@ private:
throw std::runtime_error("unexpected operation");
}
private:
type_p m_type;
type_ref m_type;
std::size_t m_size;
std::byte* m_data;
+13 -15
View File
@@ -10,14 +10,12 @@ namespace furvm {
enum class type_t : std::uint32_t {
Primitive = 0,
Reference,
Array,
Import,
};
using primitive_type = std::uint64_t;
using reference_type = type_p;
/**
* @brief Array type.
@@ -41,21 +39,17 @@ struct import_type {
struct type {
type_t t;
union {
primitive_type primitive;
reference_type reference;
primitive_type primitive{};
array_type array;
import_type imp;
};
type(type_t type)
: t(type), primitive(0) {}
: t(type) {}
type(primitive_type primitive)
: t(type_t::Primitive), primitive(primitive) {}
type(const reference_type& reference)
: t(type_t::Reference), reference(reference) {}
type(const type_h& type, std::size_t size = 0)
: t(type_t::Array), array(array_type{ type, size }) {}
@@ -67,7 +61,6 @@ struct type {
~type() {
switch (t) {
case type_t::Reference: reference.~reference_type(); break;
case type_t::Array: array.~array_type(); break;
case type_t::Import: imp.~import_type(); break;
default: break;
@@ -78,7 +71,6 @@ struct type {
: t(other.t) {
switch (t) {
case type_t::Primitive: primitive = other.primitive; break;
case type_t::Reference: reference = std::move(other.reference); break;
case type_t::Array: array = std::move(other.array); break;
case type_t::Import: imp = std::move(other.imp); break;
}
@@ -89,7 +81,6 @@ struct type {
t = other.t;
switch (t) {
case type_t::Primitive: primitive = other.primitive; break;
case type_t::Reference: reference = std::move(other.reference); break;
case type_t::Array: array = std::move(other.array); break;
case type_t::Import: imp = std::move(other.imp); break;
}
@@ -101,7 +92,6 @@ struct type {
: t(other.t) {
switch (t) {
case type_t::Primitive: primitive = other.primitive; break;
case type_t::Reference: reference = other.reference; break;
case type_t::Array: array = other.array; break;
case type_t::Import: imp = other.imp; break;
}
@@ -112,7 +102,6 @@ struct type {
t = other.t;
switch (t) {
case type_t::Primitive: primitive = other.primitive; break;
case type_t::Reference: reference = other.reference; break;
case type_t::Array: array = other.array; break;
case type_t::Import: imp = other.imp; break;
}
@@ -126,8 +115,6 @@ using short_t = std::int16_t; /**< A 2-byte integer. */
using int_t = std::int32_t; /**< A 4-byte integer. */
using long_t = std::int64_t; /**< An 8-byte integer. */
using reference_t = std::byte*;
/**
* @brief Array type's data layout.
*/
@@ -159,6 +146,17 @@ inline static type intType = { sizeof(int_t) }; // NOLINT
*/
inline static type longType = { sizeof(long_t) }; // NOLINT
/**
* @brief Reference to a type.
*/
struct type_ref {
mod_h mod;
type_h type;
class type* operator->() { return &**type; }
const class type* operator->() const { return &**type; }
};
} // namespace furvm
#endif // FURVM_TYPE_HPP