From 3c0588e8db28cea377afcffbae4d8f7f221c34b0 Mon Sep 17 00:00:00 2001 From: CHatingPython Date: Sat, 11 Jul 2026 00:45:09 +0200 Subject: [PATCH] refactor(furvm): improve type system Closes: #52 --- .clang-tidy | 4 +- furvm/include/furvm/context.hpp | 6 +- furvm/include/furvm/executor.hpp | 4 + furvm/include/furvm/function.hpp | 6 +- furvm/include/furvm/fwd.hpp | 32 ++-- furvm/include/furvm/module.hpp | 124 +++++++++++- furvm/include/furvm/thing.hpp | 317 +++++++++++++++++++------------ furvm/include/furvm/type.hpp | 181 ------------------ furvm/src/context.cpp | 24 --- furvm/src/executor.cpp | 89 +++++---- furvm/src/function.cpp | 8 + furvm/src/main.cpp | 21 +- furvm/src/module.cpp | 48 ++--- 13 files changed, 438 insertions(+), 426 deletions(-) delete mode 100644 furvm/include/furvm/type.hpp delete mode 100644 furvm/src/context.cpp diff --git a/.clang-tidy b/.clang-tidy index 2ea4be6..cad92f5 100755 --- a/.clang-tidy +++ b/.clang-tidy @@ -31,7 +31,9 @@ Checks: > -cppcoreguidelines-non-private-member-variables-in-classes, -cppcoreguidelines-pro-bounds-avoid-unchecked-container-access, -cppcoreguidelines-pro-bounds-array-to-pointer-decay, - -bugprone-forward-declaration-namespace + -cppcoreguidelines-use-enum-class, + -bugprone-forward-declaration-namespace, + -bugprone-tagged-union-member-count WarningsAsErrors: "*" diff --git a/furvm/include/furvm/context.hpp b/furvm/include/furvm/context.hpp index 8941478..ef022a9 100644 --- a/furvm/include/furvm/context.hpp +++ b/furvm/include/furvm/context.hpp @@ -21,7 +21,8 @@ public: /** * @brief Constructs a context. */ - context(); + context() + : m_thingAllocator(m_thingArena) {} ~context() = default; @@ -124,6 +125,8 @@ public: * @return The thing allocator. */ thing_allocator thing_alloc() const { return m_thingAllocator; } + + thing_type_store& thing_type_store() { return m_thingTypeStore; } private: handle_container m_modules; handle_container m_things; @@ -131,6 +134,7 @@ private: furlang::arena m_thingArena; thing_allocator m_thingAllocator; + class thing_type_store m_thingTypeStore; }; } // namespace furvm diff --git a/furvm/include/furvm/executor.hpp b/furvm/include/furvm/executor.hpp index cb6a8ac..8bf43c6 100644 --- a/furvm/include/furvm/executor.hpp +++ b/furvm/include/furvm/executor.hpp @@ -164,6 +164,10 @@ public: * @brief Executes next instruction. */ void step(); +private: + thing_type thing_type_impl(mod_h mod, mod_type type) const; + + thing_type* thing_type(const mod_h& mod, const mod_type& type) const; private: executor_flags m_flags{}; // NOLINT(bugprone-invalid-enum-default-initialization) context_p m_context; diff --git a/furvm/include/furvm/function.hpp b/furvm/include/furvm/function.hpp index 8fdd194..7aef9e0 100644 --- a/furvm/include/furvm/function.hpp +++ b/furvm/include/furvm/function.hpp @@ -37,7 +37,7 @@ struct import_function { * @brief Function signature. */ struct function_sig { - std::vector params; + std::vector params; bool operator==(const function_sig& rhs) const { return params == rhs.params; } @@ -190,9 +190,7 @@ private: namespace detail { struct function_sig_hash { - std::size_t operator()(const function_sig& signature) const { - return furlang::utility::vector_hash>{}(signature.params); - } + std::size_t operator()(const function_sig& signature) const; }; } // namespace detail diff --git a/furvm/include/furvm/fwd.hpp b/furvm/include/furvm/fwd.hpp index 556ae25..d7d3798 100644 --- a/furvm/include/furvm/fwd.hpp +++ b/furvm/include/furvm/fwd.hpp @@ -115,6 +115,12 @@ using function_h = handle>; // module.hpp +struct mod_type; + +using mod_type_id = std::uint32_t; + +using mod_type_h = handle>; + /** * @class mod * @brief Module. @@ -138,34 +144,20 @@ using mod_id = std::string; */ using mod_h = handle>; +// thing_allocator.hpp + +template +class thing_allocator; + // thing.hpp -/** - * @enum type_t - * @brief Type of the thing's type. - */ -enum class type_t : std::uint32_t; - -/** - * @struct type - * @brief Thing type. - */ -struct type; - -using type_p = std::shared_ptr; - -using type_id = std::uint32_t; - -using type_h = handle>; - /** * @class bad_thing_access * @brief Bad thing access exception. */ class bad_thing_access; -template -class thing_allocator; +using thing_type_id = std::uint32_t; /** * @class thing diff --git a/furvm/include/furvm/module.hpp b/furvm/include/furvm/module.hpp index 976dc73..4e45123 100644 --- a/furvm/include/furvm/module.hpp +++ b/furvm/include/furvm/module.hpp @@ -5,7 +5,6 @@ #include "furvm/function.hpp" #include "furvm/fwd.hpp" #include "furvm/handle.hpp" -#include "furvm/type.hpp" // IWYU pragma: keep #include #include @@ -18,6 +17,125 @@ namespace furvm { +struct mod_type { + using primitive = std::uint64_t; + + struct array { + mod_type_id typeId; + std::size_t size; + }; + + struct imprt { + mod_id modId; + mod_type_id typeId; + }; + + enum type { + Primitive = 0, + Array, + + Import, + Count, + } type; + union value { + std::nullptr_t null = nullptr; + primitive primitive; + array array; + imprt imprt; + + value() = default; + + value(std::uint64_t primitive) + : primitive(primitive) {} + + value(mod_type_id id, std::size_t size) + : array({}) { + array.typeId = id; + array.size = size; + } + + template >> + value(ModIdFwd&& modId, mod_type_id typeId) + : imprt({}) { + imprt.modId = std::forward(modId); + imprt.typeId = typeId; + } + + ~value() {} + + value(value&& other) = delete; + value& operator=(value&& other) = delete; + value(const value& other) = delete; + value& operator=(const value& other) = delete; + } value; + + mod_type(primitive primitive) + : type(Primitive), value(primitive) {} + + mod_type(mod_type_id id, std::size_t size) + : type(Array), value(id, size) {} + + template >> + mod_type(ModIdFwd&& modId, mod_type_id typeId) + : type(Import), value(std::forward(modId), typeId) {} + + ~mod_type() { + switch (type) { + case Array: value.array.~array(); break; + case Import: value.imprt.~imprt(); break; + case Primitive: + case Count: + default: break; + } + } + + mod_type(mod_type&& other) noexcept + : type(other.type) { + switch (type) { + case Primitive: new (&value.primitive) primitive(other.value.primitive); break; + case Array: new (&value.array) array(other.value.array); break; + case Import: new (&value.imprt) imprt(std::move(other.value.imprt)); break; + case Count: break; + } + other.type = Count; + } + + mod_type& operator=(mod_type&& other) noexcept { + if (this == &other) return *this; + type = other.type; + switch (type) { + case Primitive: new (&value.primitive) primitive(other.value.primitive); break; + case Array: new (&value.array) array(other.value.array); break; + case Import: new (&value.imprt) imprt(std::move(other.value.imprt)); break; + case Count: break; + } + other.type = Count; + return *this; + } + + mod_type(const mod_type& other) + : type(other.type) { + switch (type) { + case Primitive: new (&value.primitive) primitive(other.value.primitive); break; + case Array: new (&value.array) array(other.value.array); break; + case Import: new (&value.imprt) imprt(other.value.imprt); break; + case Count: break; + } + } + + mod_type& operator=(const mod_type& other) { + if (this == &other) return *this; + type = other.type; + switch (type) { + case Primitive: new (&value.primitive) primitive(other.value.primitive); break; + case Array: new (&value.array) array(other.value.array); break; + case Import: new (&value.imprt) imprt(other.value.imprt); break; + case Count: break; + } + return *this; + } +}; + class mod { friend class function; friend class serializer; @@ -181,7 +299,7 @@ public: */ template auto emplace_type(Args&&... args) { - if constexpr (std::is_constructible_v) { + if constexpr (std::is_constructible_v) { return m_types.emplace_back(std::forward(args)...); } else { return m_types.emplace(std::forward(args)...); @@ -245,7 +363,7 @@ private: std::unordered_map m_functionMap; handle_container m_functions; - handle_container m_types; + handle_container m_types; std::unordered_map m_nativeFunctions; }; diff --git a/furvm/include/furvm/thing.hpp b/furvm/include/furvm/thing.hpp index bcf43b6..595812b 100644 --- a/furvm/include/furvm/thing.hpp +++ b/furvm/include/furvm/thing.hpp @@ -1,38 +1,142 @@ #ifndef FURVM_THING_HPP #define FURVM_THING_HPP +#include "furlang/arena.hpp" +#include "furlang/utility/hash.hpp" #include "furvm/exceptions.hpp" #include "furvm/fwd.hpp" -#include "furvm/module.hpp" -#include "furvm/type.hpp" +#include "furvm/thing_allocator.hpp" // IWYU pragma: keep #include #include #include #include -#include +#include #include #include +#include #include namespace furvm { +struct thing_type { + using primitive = std::uint64_t; + + struct array { + thing_type* type; + std::size_t size; + }; + + enum type { // NOLINT + Primitive = 0, + Array, + + Count, + } type; + union value { + primitive primitive; + array array; + + value(std::uint64_t primitive) + : primitive(primitive) {} + + 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::max(); + + thing_type_id id = INVALID_ID; + + bool operator==(const thing_type& other) const { + if (type != other.type) return false; + switch (type) { + case Primitive: return value.primitive == other.value.primitive; + case Array: return *value.array.type == *other.value.array.type && value.array.size == other.value.array.size; + case Count: break; + } + return false; + } + + bool operator!=(const thing_type& other) const { return !this->operator==(other); } +}; + +namespace detail { + +struct thing_type_hash { + std::size_t operator()(const thing_type& type) const { + std::size_t seed = std::hash{}(type.type); + switch (type.type) { + case thing_type::Primitive: + seed = + furlang::utility::hash_combine(seed, std::hash{}(type.value.primitive)); + return seed; + case thing_type::Array: + seed = furlang::utility::hash_combine(seed, thing_type_hash{}(*type.value.array.type)); + seed = furlang::utility::hash_combine(seed, + std::hash{}(type.value.array.size)); + return seed; + case thing_type::Count: break; + } + throw std::runtime_error("unreachable"); + } +}; + +} // namespace detail + +class thing_type_store { +public: + thing_type* insert(thing_type& type) { + if (auto it = m_typeMap.find(type); it != m_typeMap.end()) return m_map[type.id = it->second]; + if (type.id == thing_type::INVALID_ID) type.id = m_counter++; + + thing_type* ptr = m_arena.allocate(type); + m_map[type.id] = ptr; + m_typeMap[type] = type.id; + return ptr; + } + + thing_type* at(thing_type_id id) const { + if (auto it = m_map.find(id); it != m_map.end()) return it->second; + return nullptr; + } +private: + furlang::arena m_arena; + std::unordered_map m_map; + std::unordered_map m_typeMap; + thing_type_id m_counter = 0; +}; + template