diff --git a/furvm/include/furvm/thing.hpp b/furvm/include/furvm/thing.hpp index 06b073b..02f91a4 100644 --- a/furvm/include/furvm/thing.hpp +++ b/furvm/include/furvm/thing.hpp @@ -5,7 +5,6 @@ #include "furvm/exceptions.hpp" #include "furvm/fwd.hpp" -#include #include #include #include @@ -20,11 +19,66 @@ namespace furvm { enum class type_t : std::uint32_t { Primitive = 0, + Reference, }; +using primitive_type = std::uint64_t; +using reference_type = std::shared_ptr; + struct type { - type_t type; - std::uint64_t value; + type_t t; + union { + primitive_type primitive; + reference_type reference; + }; + + type(primitive_type primitive) + : t(type_t::Primitive), primitive(primitive) {} + + type(const reference_type& reference) + : t(type_t::Reference), reference(reference) {} + + ~type() { + if (t == type_t::Reference) reference.~reference_type(); + } + + type(type&& other) noexcept + : t(other.t) { + switch (t) { + case type_t::Primitive: primitive = other.primitive; break; + case type_t::Reference: reference = std::move(other.reference); break; + } + } + + type& operator=(type&& other) noexcept { + if (this == &other) return *this; + t = other.t; + switch (t) { + case type_t::Primitive: primitive = other.primitive; break; + case type_t::Reference: reference = std::move(other.reference); break; + } + + return *this; + } + + type(const type& other) + : t(other.t) { + switch (t) { + case type_t::Primitive: primitive = other.primitive; break; + case type_t::Reference: reference = other.reference; break; + } + } + + type& operator=(const type& other) { + if (this == &other) return *this; + t = other.t; + switch (t) { + case type_t::Primitive: primitive = other.primitive; break; + case type_t::Reference: reference = other.reference; break; + } + + return *this; + } }; using byte_t = std::int8_t; /**< A 1-byte integer. */ @@ -32,25 +86,27 @@ 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 A 1-byte integer thing type. */ -static constexpr type ByteType = { type_t::Primitive, sizeof(byte_t) }; +inline static type byteType = { sizeof(byte_t) }; // NOLINT /** * @brief A 2-byte integer thing type. */ -static constexpr type ShortType = { type_t::Primitive, sizeof(short_t) }; +inline static type shortType = { sizeof(short_t) }; // NOLINT /** * @brief A 4-byte integer thing type. */ -static constexpr type IntType = { type_t::Primitive, sizeof(int_t) }; +inline static type intType = { sizeof(int_t) }; // NOLINT /** * @brief An 8-byte integer thing type. */ -static constexpr type LongType = { type_t::Primitive, sizeof(long_t) }; +inline static type longType = { sizeof(long_t) }; // NOLINT template