feat: introduce import type

Closes: #39
This commit is contained in:
2026-07-03 19:43:18 +02:00
parent a7ab214ce3
commit 575054b75a
3 changed files with 53 additions and 20 deletions
+36 -19
View File
@@ -23,6 +23,8 @@ class thing final {
friend class executor; friend class executor;
public: public:
using allocator_type = Allocator<std::byte>; /**< Allocator type. */ using allocator_type = Allocator<std::byte>; /**< Allocator type. */
using mod_container = std::shared_ptr<handle_container<mod_h>>;
public: public:
/** /**
* @brief Constructs a thing. * @brief Constructs a thing.
@@ -30,8 +32,8 @@ public:
* @param type Thing type. * @param type Thing type.
* @param allocator Allocator for the thing's data. * @param allocator Allocator for the thing's data.
*/ */
thing(const type& type, const allocator_type& allocator = {}) thing(const type& type, const mod_container& modules = nullptr, const allocator_type& allocator = {})
: thing(std::make_shared<class type>(type), allocator) {} : thing(std::make_shared<class type>(type), modules, allocator) {}
/** /**
* @brief Constructs a thing. * @brief Constructs a thing.
@@ -39,8 +41,8 @@ public:
* @param type Thing type. * @param type Thing type.
* @param allocator Allocator for the thing's data. * @param allocator Allocator for the thing's data.
*/ */
thing(const type_p& type, const allocator_type& allocator = {}) thing(const type_p& type, const mod_container& modules = nullptr, const allocator_type& allocator = {})
: m_type(type), m_size(compute_size(type)), m_allocator(allocator) { : m_type(type), m_size(compute_size(resolve_type(type, modules))), m_modules(modules), m_allocator(allocator) {
// TODO: Account for alignment // TODO: Account for alignment
m_data = m_allocator.allocate(m_size); m_data = m_allocator.allocate(m_size);
std::memset(m_data, 0, m_size); std::memset(m_data, 0, m_size);
@@ -60,6 +62,7 @@ public:
: m_type(std::move(other.m_type)), : m_type(std::move(other.m_type)),
m_data(other.m_data), m_data(other.m_data),
m_size(other.m_size), m_size(other.m_size),
m_modules(std::move(other.m_modules)),
m_allocator(std::move(other.m_allocator)) { m_allocator(std::move(other.m_allocator)) {
other.m_type = {}; other.m_type = {};
other.m_data = nullptr; other.m_data = nullptr;
@@ -73,6 +76,7 @@ public:
if (this == &other) return *this; if (this == &other) return *this;
m_type = other.m_type; m_type = other.m_type;
m_data = other.m_data; m_data = other.m_data;
m_modules = std::move(other.m_modules);
m_allocator = std::move(other.m_allocator); m_allocator = std::move(other.m_allocator);
other.m_type = {}; other.m_type = {};
other.m_data = nullptr; other.m_data = nullptr;
@@ -82,6 +86,8 @@ public:
thing(const thing&) = delete; thing(const thing&) = delete;
thing& operator=(const thing&) = delete; thing& operator=(const thing&) = delete;
public:
void assign_mod_container(const mod_container& modules) { m_modules = modules; }
public: public:
/** /**
* @brief Returns a clone of the thing. * @brief Returns a clone of the thing.
@@ -89,15 +95,16 @@ public:
* @return A clone of this thing. * @return A clone of this thing.
*/ */
thing clone() const { thing clone() const {
thing res(m_type, m_allocator); thing res(resolve_type(m_type, m_modules), m_modules, m_allocator);
switch (m_type->t) { switch (m_type->t) {
case type_t::Primitive: case type_t::Primitive:
case type_t::Reference: { case type_t::Reference: {
std::memcpy(res.m_data, m_data, m_size); std::memcpy(res.m_data, m_data, m_size);
} break; } break;
case type_t::List: { case type_t::List: {
copy_list(m_type->list, res.get<list_t>(), get<list_t>()); copy_list(resolve_type(m_type->list, m_modules), res.get<list_t>(), get<list_t>());
} break; } break;
case type_t::Import: throw std::runtime_error("unreachable");
} }
return std::move(res); return std::move(res);
} }
@@ -130,7 +137,7 @@ public:
*/ */
template <typename T> template <typename T>
T& get() { T& get() {
std::size_t size = m_size > 0 ? m_size : compute_size_na(m_type); std::size_t size = m_size > 0 ? m_size : compute_size_na(resolve_type(m_type, m_modules));
if (size != sizeof(T)) throw bad_thing_access(); if (size != sizeof(T)) throw bad_thing_access();
return *std::launder(reinterpret_cast<T*>(m_data)); return *std::launder(reinterpret_cast<T*>(m_data));
} }
@@ -142,7 +149,7 @@ public:
*/ */
template <typename T> template <typename T>
const T& get() const { const T& get() const {
std::size_t size = m_size > 0 ? m_size : compute_size_na(m_type); std::size_t size = m_size > 0 ? m_size : compute_size_na(resolve_type(m_type, m_modules));
if (size != sizeof(T)) throw bad_thing_access(); if (size != sizeof(T)) throw bad_thing_access();
return *std::launder(reinterpret_cast<const T*>(m_data)); return *std::launder(reinterpret_cast<const T*>(m_data));
} }
@@ -252,13 +259,13 @@ public:
} }
thing reference() const { thing reference() const {
thing res = { std::make_shared<class type>(m_type), m_allocator }; thing res = { std::make_shared<class type>(m_type), m_modules, m_allocator };
res.get<reference_t>() = m_data; res.get<reference_t>() = m_data;
return std::move(res); return std::move(res);
} }
thing resolve() const { thing resolve() const {
thing rsv = { m_type, m_data, m_allocator }; thing rsv = { resolve_type(m_type, m_modules), m_data, m_allocator };
while (rsv.type().t == type_t::Reference) while (rsv.type().t == type_t::Reference)
rsv = { rsv.m_type->reference, rsv.get<reference_t>(), std::move(rsv.m_allocator) }; rsv = { rsv.m_type->reference, rsv.get<reference_t>(), std::move(rsv.m_allocator) };
return rsv; return rsv;
@@ -268,8 +275,10 @@ public:
if (m_type->t != type_t::List) throw bad_thing_access(); if (m_type->t != type_t::List) throw bad_thing_access();
auto& list = get<list_t>(); auto& list = get<list_t>();
if (newSize < 0 || newSize == list.size) return; if (newSize < 0 || newSize == list.size) return;
std::byte* newData = new std::byte[compute_size_na(m_type->list) * newSize]; std::byte* newData = new std::byte[compute_size_na(resolve_type(m_type->list, m_modules)) * newSize];
std::memcpy(newData, list.data, compute_size_na(m_type->list) * std::min(list.size, newSize)); std::memcpy(newData,
list.data,
compute_size_na(resolve_type(m_type->list, m_modules)) * std::min(list.size, newSize));
list.size = newSize; list.size = newSize;
delete[] list.data; delete[] list.data;
list.data = newData; list.data = newData;
@@ -279,10 +288,17 @@ public:
if (m_type->t != type_t::List) throw bad_thing_access(); if (m_type->t != type_t::List) throw bad_thing_access();
auto& list = get<list_t>(); auto& list = get<list_t>();
if (index < 0 || index >= list.size) throw std::out_of_range("index out of range"); if (index < 0 || index >= list.size) throw std::out_of_range("index out of range");
thing res = { m_type->list, m_allocator }; thing res = { m_type->list, m_modules, m_allocator };
res.get<reference_t>() = list.data; // TODO: Account for padding, alignment and stuff res.get<reference_t>() = list.data; // TODO: Account for padding, alignment and stuff
return std::move(res); return std::move(res);
} }
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);
return rsv;
}
private: private:
static void copy_list(const type_p& innerType, list_t& dst, const list_t& src) { static void copy_list(const type_p& innerType, list_t& dst, const list_t& src) {
dst.size = src.size; dst.size = src.size;
@@ -296,16 +312,15 @@ private:
dst.data = new std::byte[size]; dst.data = new std::byte[size];
switch (innerType->t) { switch (innerType->t) {
case type_t::Primitive: case type_t::Primitive:
case type_t::Reference: { case type_t::Reference: std::memcpy(dst.data, src.data, size); break;
std::memcpy(dst.data, src.data, size); case type_t::List:
} break;
case type_t::List: {
for (std::size_t i = 0; i < size; ++i) { for (std::size_t i = 0; i < size; ++i) {
copy_list(innerType->list, copy_list(innerType->list,
*std::launder(reinterpret_cast<list_t*>(dst.data)), *std::launder(reinterpret_cast<list_t*>(dst.data)),
*std::launder(reinterpret_cast<list_t*>(src.data))); *std::launder(reinterpret_cast<list_t*>(src.data)));
} }
} break; break;
case type_t::Import: throw std::runtime_error("unresolved type");
} }
} }
private: private:
@@ -314,6 +329,7 @@ private:
case type_t::Primitive: return type->primitive; case type_t::Primitive: return type->primitive;
case type_t::Reference: return sizeof(reference_t); case type_t::Reference: return sizeof(reference_t);
case type_t::List: return sizeof(list_t); case type_t::List: return sizeof(list_t);
case type_t::Import: throw std::runtime_error("unresolved type");
} }
throw std::runtime_error("unreachable"); throw std::runtime_error("unreachable");
@@ -335,7 +351,7 @@ private:
long_t result = op(lhsRsv.integer(), rhsRsv.integer()); long_t result = op(lhsRsv.integer(), rhsRsv.integer());
thing res({ size }, m_allocator); thing res({ size }, m_modules, m_allocator);
switch (size) { switch (size) {
case sizeof(byte_t): res.get<byte_t>() = result; break; case sizeof(byte_t): res.get<byte_t>() = result; break;
case sizeof(short_t): res.get<short_t>() = result; break; case sizeof(short_t): res.get<short_t>() = result; break;
@@ -353,6 +369,7 @@ private:
std::size_t m_size; std::size_t m_size;
std::byte* m_data; std::byte* m_data;
mod_container m_modules;
allocator_type m_allocator; allocator_type m_allocator;
}; };
+16
View File
@@ -13,18 +13,26 @@ enum class type_t : std::uint32_t {
Primitive = 0, Primitive = 0,
Reference, Reference,
List, List,
Import,
}; };
using primitive_type = std::uint64_t; using primitive_type = std::uint64_t;
using reference_type = std::shared_ptr<type>; using reference_type = std::shared_ptr<type>;
using list_type = std::shared_ptr<type>; using list_type = std::shared_ptr<type>;
struct import_type {
mod_id mod;
type_id type;
};
struct type { struct type {
type_t t; type_t t;
union { union {
primitive_type primitive; primitive_type primitive;
reference_type reference; reference_type reference;
list_type list; list_type list;
import_type imp;
}; };
type(type_t type) type(type_t type)
@@ -42,10 +50,14 @@ struct type {
return type; return type;
} }
type(const import_type& imp)
: t(type_t::Import), imp(imp) {}
~type() { ~type() {
switch (t) { switch (t) {
case type_t::Reference: reference.~reference_type(); break; case type_t::Reference: reference.~reference_type(); break;
case type_t::List: list.~list_type(); break; case type_t::List: list.~list_type(); break;
case type_t::Import: imp.~import_type(); break;
default: break; default: break;
} }
} }
@@ -56,6 +68,7 @@ struct type {
case type_t::Primitive: primitive = other.primitive; break; case type_t::Primitive: primitive = other.primitive; break;
case type_t::Reference: reference = std::move(other.reference); break; case type_t::Reference: reference = std::move(other.reference); break;
case type_t::List: list = std::move(other.list); break; case type_t::List: list = std::move(other.list); break;
case type_t::Import: imp = std::move(other.imp); break;
} }
} }
@@ -66,6 +79,7 @@ struct type {
case type_t::Primitive: primitive = other.primitive; break; case type_t::Primitive: primitive = other.primitive; break;
case type_t::Reference: reference = std::move(other.reference); break; case type_t::Reference: reference = std::move(other.reference); break;
case type_t::List: list = std::move(other.list); break; case type_t::List: list = std::move(other.list); break;
case type_t::Import: imp = std::move(other.imp); break;
} }
return *this; return *this;
@@ -77,6 +91,7 @@ struct type {
case type_t::Primitive: primitive = other.primitive; break; case type_t::Primitive: primitive = other.primitive; break;
case type_t::Reference: reference = other.reference; break; case type_t::Reference: reference = other.reference; break;
case type_t::List: list = other.list; break; case type_t::List: list = other.list; break;
case type_t::Import: imp = other.imp; break;
} }
} }
@@ -87,6 +102,7 @@ struct type {
case type_t::Primitive: primitive = other.primitive; break; case type_t::Primitive: primitive = other.primitive; break;
case type_t::Reference: reference = other.reference; break; case type_t::Reference: reference = other.reference; break;
case type_t::List: list = other.list; break; case type_t::List: list = other.list; break;
case type_t::Import: imp = other.imp; break;
} }
return *this; return *this;
+1 -1
View File
@@ -91,7 +91,7 @@ void executor::step() {
switch (instr) { switch (instr) {
case instruction_t::NoOperation: break; case instruction_t::NoOperation: break;
case instruction_t::PushB2I: { case instruction_t::PushB2I: {
push_thing({ intType, m_context->thing_alloc() })->get<int_t>() = frame.mod->byte(frame.position++); push_thing({ intType, m_context, m_context->thing_alloc() })->get<int_t>() = frame.mod->byte(frame.position++);
} break; } break;
case instruction_t::Drop: { case instruction_t::Drop: {
pop_thing(); pop_thing();