#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/types.hpp" #include #include #include #include #include #include #include #include #include #include #include namespace furvm { 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::S8: case thing_type::S16: case thing_type::S32: case thing_type::S64: case thing_type::U8: case thing_type::U16: case thing_type::U32: case thing_type::U64: case thing_type::String: return seed; case thing_type::Ptr: case thing_type::Ref: return furlang::utility::hash_combine(seed, thing_type_hash{}(*type.value.typeRef)); 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::Slice: return furlang::utility::hash_combine(seed, thing_type_hash{}(*type.value.slice.type)); 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* insert(const thing_type& type) { if (auto it = m_typeMap.find(type); it != m_typeMap.end()) return m_map[it->second]; thing_type_id id = m_counter++; thing_type* ptr = m_arena.allocate(type); m_map[id] = ptr; m_typeMap[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