diff --git a/furdb/src/command.cpp b/furdb/src/command.cpp index 91a9620..4e57f8e 100644 --- a/furdb/src/command.cpp +++ b/furdb/src/command.cpp @@ -121,14 +121,14 @@ static void print_thing(const furvm::thing<>& thing) { print_type(thing.type()); std::cout << ") "; switch (thing.type().type) { - case furvm::thing_type::S8: std::cout << std::to_string(thing.get()); break; - case furvm::thing_type::S16: std::cout << thing.get(); break; - case furvm::thing_type::S32: std::cout << thing.get(); break; - case furvm::thing_type::S64: std::cout << thing.get(); break; - case furvm::thing_type::U8: std::cout << std::to_string(thing.get()); break; - case furvm::thing_type::U16: std::cout << thing.get(); break; - case furvm::thing_type::U32: std::cout << thing.get(); break; - case furvm::thing_type::U64: std::cout << thing.get(); break; + case furvm::thing_type::S8: std::cout << std::to_string(thing.get()); break; + case furvm::thing_type::S16: std::cout << thing.get(); break; + case furvm::thing_type::S32: std::cout << thing.get(); break; + case furvm::thing_type::S64: std::cout << thing.get(); break; + case furvm::thing_type::U8: std::cout << std::to_string(thing.get()); break; + case furvm::thing_type::U16: std::cout << thing.get(); break; + case furvm::thing_type::U32: std::cout << thing.get(); break; + case furvm::thing_type::U64: std::cout << thing.get(); break; case furvm::thing_type::Ptr: std::cout << thing.get(); break; case furvm::thing_type::Array: case furvm::thing_type::Slice: { diff --git a/furdb/src/main.cpp b/furdb/src/main.cpp index cd4f83a..4d009d0 100644 --- a/furdb/src/main.cpp +++ b/furdb/src/main.cpp @@ -15,17 +15,17 @@ static void print_thing(const furvm::thing<>& thing) { using namespace furvm; switch (thing.type().type) { - case thing_type::S8: std::cout << thing.cast_to(); break; - case thing_type::S16: std::cout << thing.get(); break; - case thing_type::S32: std::cout << thing.get(); break; - case thing_type::S64: std::cout << thing.get(); break; - case thing_type::U8: std::cout << thing.get(); break; - case thing_type::U16: std::cout << thing.get(); break; - case thing_type::U32: std::cout << thing.get(); break; - case thing_type::U64: std::cout << thing.get(); break; + case thing_type::S8: std::cout << thing.cast_to(); break; + case thing_type::S16: std::cout << thing.get(); break; + case thing_type::S32: std::cout << thing.get(); break; + case thing_type::S64: std::cout << thing.get(); break; + case thing_type::U8: std::cout << thing.get(); break; + case thing_type::U16: std::cout << thing.get(); break; + case thing_type::U32: std::cout << thing.get(); break; + case thing_type::U64: std::cout << thing.get(); break; case thing_type::Array: std::cout << "{ "; - for (thing_type::u64 i = 0; i < thing.length(); ++i) { + for (u64 i = 0; i < thing.length(); ++i) { if (i > 0) std::cout << ", "; print_thing(thing.at(i)); } diff --git a/furvm/include/furvm/thing.hpp b/furvm/include/furvm/thing.hpp index 1463035..e479c84 100644 --- a/furvm/include/furvm/thing.hpp +++ b/furvm/include/furvm/thing.hpp @@ -5,6 +5,7 @@ #include "furlang/utility/hash.hpp" #include "furvm/exceptions.hpp" #include "furvm/fwd.hpp" +#include "furvm/types.hpp" #include #include @@ -12,7 +13,6 @@ #include #include #include -#include #include #include #include @@ -21,124 +21,6 @@ namespace furvm { -struct thing_type { - using s8 = std::int8_t; - using s16 = std::int16_t; - using s32 = std::int32_t; - using s64 = std::int64_t; - using u8 = std::uint8_t; - using u16 = std::uint16_t; - using u32 = std::uint32_t; - using u64 = std::uint64_t; - - struct array_value { - thing_type* type; - std::size_t size; - }; - - struct slice_value { - thing_type* type; - }; - - enum type { // NOLINT - S8 = 0, - S16, - S32, - S64, - U8, - U16, - U32, - U64, - Ptr, - Ref, - Array, - Slice, - - Count, - } type = Count; - union value { - std::nullptr_t null = nullptr; - thing_type* typeRef; - array_value array; - slice_value slice; - - value() = default; - - value(thing_type* type) - : typeRef(type) {} - - 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 S8: - case S16: - case S32: - case S64: - case U8: - case U16: - case U32: - case U64: return true; - case Ptr: - case Ref: return *value.typeRef == *other.value.typeRef; - case Array: return *value.array.type == *other.value.array.type && value.array.size == other.value.array.size; - case Slice: return *value.slice.type == *other.value.slice.type; - case Count: break; - } - return false; - } - - bool operator!=(const thing_type& other) const { return !this->operator==(other); } - - static bool is_primitive(enum type type) { - switch (type) { - case S8: - case S16: - case S32: - case S64: - case U8: - case U16: - case U32: - case U64: return true; - case Ptr: - case Ref: - case Array: - case Slice: return false; - case Count: break; - } - throw std::runtime_error("unreachable"); - } - - static std::size_t primitive_size(enum type type) { - switch (type) { - case thing_type::S8: return sizeof(s8); - case thing_type::S16: return sizeof(s16); - case thing_type::S32: return sizeof(s32); - case thing_type::S64: return sizeof(s64); - case thing_type::U8: return sizeof(u8); - case thing_type::U16: return sizeof(u16); - case thing_type::U32: return sizeof(u32); - case thing_type::U64: return sizeof(u64); - case Ptr: - case Ref: - case Array: - case Slice: return 0; - case Count: break; - } - throw std::runtime_error("unreachable"); - } -}; - namespace detail { struct thing_type_hash { @@ -633,21 +515,21 @@ public: * * @return The integer value. */ - thing_type::s64 integer() const { + s64 integer() const { switch (type().type) { - case thing_type::S8: return get(); - case thing_type::S16: return get(); - case thing_type::S32: return get(); - case thing_type::S64: return get(); - case thing_type::U8: return get(); - case thing_type::U16: return get(); - case thing_type::U32: return get(); - case thing_type::U64: return get(); + case thing_type::S8: return get(); + case thing_type::S16: return get(); + case thing_type::S32: return get(); + case thing_type::S64: return get(); + case thing_type::U8: return get(); + case thing_type::U16: return get(); + case thing_type::U32: return get(); + case thing_type::U64: return get(); default: throw std::runtime_error("unreachable"); } } - void resize(thing_type::u64 newSize) { + void resize(u64 newSize) { if (!is(thing_type::Array)) throw bad_thing_access(); if (type().value.array.size > 0) throw std::runtime_error("cannot resize a static array"); @@ -655,13 +537,13 @@ public: if (newSize < 0 || newSize == array.size) return; std::size_t innerSize = compute_size_na(*type().value.array.type); std::byte* newData = new std::byte[innerSize * newSize]; - std::memcpy(newData, array.data, innerSize * std::min(static_cast(array.size), newSize)); + std::memcpy(newData, array.data, innerSize * std::min(static_cast(array.size), newSize)); array.size = newSize; delete[] array.data; array.data = newData; } - thing at(thing_type::u64 index) const { + thing at(u64 index) const { thing ref = { m_allocator }; ref.m_reference = true; ref.m_size = compute_size_na(*(ref.m_type = &inner_type())); @@ -690,7 +572,7 @@ public: } } - thing slice(thing_type::u64 begin, thing_type::u64 len) const { + thing slice(u64 begin, u64 len) const { auto& inner = inner_type(); thing_type sliceType; @@ -718,7 +600,7 @@ public: return slice; } - thing_type::u64 length() const { + u64 length() const { switch (type().type) { case thing_type::Array: return type().value.array.size == 0 ? get().size : type().value.array.size; @@ -833,14 +715,14 @@ private: private: static std::size_t compute_size_na(const thing_type& type) { switch (type.type) { - case thing_type::S8: return sizeof(thing_type::s8); - case thing_type::S16: return sizeof(thing_type::s16); - case thing_type::S32: return sizeof(thing_type::s32); - case thing_type::S64: return sizeof(thing_type::s64); - case thing_type::U8: return sizeof(thing_type::u8); - case thing_type::U16: return sizeof(thing_type::u16); - case thing_type::U32: return sizeof(thing_type::u32); - case thing_type::U64: return sizeof(thing_type::u64); + case thing_type::S8: return sizeof(s8); + case thing_type::S16: return sizeof(s16); + case thing_type::S32: return sizeof(s32); + case thing_type::S64: return sizeof(s64); + case thing_type::U8: return sizeof(u8); + case thing_type::U16: return sizeof(u16); + case thing_type::U32: return sizeof(u32); + case thing_type::U64: return sizeof(u64); case thing_type::Ptr: return sizeof(void*); case thing_type::Array: return type.value.array.size == 0 ? sizeof(dynamic_array) @@ -859,14 +741,14 @@ private: template decltype(auto) visit_primitive(Func&& func) const { switch (type().type) { - case thing_type::S8: return std::forward(func)(get()); - case thing_type::S16: return std::forward(func)(get()); - case thing_type::S32: return std::forward(func)(get()); - case thing_type::S64: return std::forward(func)(get()); - case thing_type::U8: return std::forward(func)(get()); - case thing_type::U16: return std::forward(func)(get()); - case thing_type::U32: return std::forward(func)(get()); - case thing_type::U64: return std::forward(func)(get()); + case thing_type::S8: return std::forward(func)(get()); + case thing_type::S16: return std::forward(func)(get()); + case thing_type::S32: return std::forward(func)(get()); + case thing_type::S64: return std::forward(func)(get()); + case thing_type::U8: return std::forward(func)(get()); + case thing_type::U16: return std::forward(func)(get()); + case thing_type::U32: return std::forward(func)(get()); + case thing_type::U64: return std::forward(func)(get()); default: throw bad_thing_access(); } } @@ -953,30 +835,14 @@ private: thing res = { thing_type{ resultType }, m_allocator }; switch (resultType) { - case thing_type::S8: - res.get() = Op{}(cast_to(), rhs.cast_to()); - return res; - case thing_type::S16: - res.get() = Op{}(cast_to(), rhs.cast_to()); - return res; - case thing_type::S32: - res.get() = Op{}(cast_to(), rhs.cast_to()); - return res; - case thing_type::S64: - res.get() = Op{}(cast_to(), rhs.cast_to()); - return res; - case thing_type::U8: - res.get() = Op{}(cast_to(), rhs.cast_to()); - return res; - case thing_type::U16: - res.get() = Op{}(cast_to(), rhs.cast_to()); - return res; - case thing_type::U32: - res.get() = Op{}(cast_to(), rhs.cast_to()); - return res; - case thing_type::U64: - res.get() = Op{}(cast_to(), rhs.cast_to()); - return res; + case thing_type::S8: res.get() = Op{}(cast_to(), rhs.cast_to()); return res; + case thing_type::S16: res.get() = Op{}(cast_to(), rhs.cast_to()); return res; + case thing_type::S32: res.get() = Op{}(cast_to(), rhs.cast_to()); return res; + case thing_type::S64: res.get() = Op{}(cast_to(), rhs.cast_to()); return res; + case thing_type::U8: res.get() = Op{}(cast_to(), rhs.cast_to()); return res; + case thing_type::U16: res.get() = Op{}(cast_to(), rhs.cast_to()); return res; + case thing_type::U32: res.get() = Op{}(cast_to(), rhs.cast_to()); return res; + case thing_type::U64: res.get() = Op{}(cast_to(), rhs.cast_to()); return res; case thing_type::Ptr: // TODO: Pointer arithmetics case thing_type::Ref: case thing_type::Array: diff --git a/furvm/include/furvm/types.hpp b/furvm/include/furvm/types.hpp new file mode 100644 index 0000000..6d27c3c --- /dev/null +++ b/furvm/include/furvm/types.hpp @@ -0,0 +1,132 @@ +#ifndef FURVM_TYPES_HPP +#define FURVM_TYPES_HPP + +#include "furvm/fwd.hpp" + +#include +#include +#include + +namespace furvm { + +using s8 = std::int8_t; +using s16 = std::int16_t; +using s32 = std::int32_t; +using s64 = std::int64_t; +using u8 = std::uint8_t; +using u16 = std::uint16_t; +using u32 = std::uint32_t; +using u64 = std::uint64_t; + +struct thing_type { + struct array_value { + thing_type* type; + std::size_t size; + }; + + struct slice_value { + thing_type* type; + }; + + enum type { // NOLINT + S8 = 0, + S16, + S32, + S64, + U8, + U16, + U32, + U64, + Ptr, + Ref, + Array, + Slice, + + Count, + } type = Count; + union value { + std::nullptr_t null = nullptr; + thing_type* typeRef; + array_value array; + slice_value slice; + + value() = default; + + value(thing_type* type) + : typeRef(type) {} + + 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 S8: + case S16: + case S32: + case S64: + case U8: + case U16: + case U32: + case U64: return true; + case Ptr: + case Ref: return *value.typeRef == *other.value.typeRef; + case Array: return *value.array.type == *other.value.array.type && value.array.size == other.value.array.size; + case Slice: return *value.slice.type == *other.value.slice.type; + case Count: break; + } + return false; + } + + bool operator!=(const thing_type& other) const { return !this->operator==(other); } + + static bool is_primitive(enum type type) { + switch (type) { + case S8: + case S16: + case S32: + case S64: + case U8: + case U16: + case U32: + case U64: return true; + case Ptr: + case Ref: + case Array: + case Slice: return false; + case Count: break; + } + throw std::runtime_error("unreachable"); + } + + static std::size_t primitive_size(enum type type) { + switch (type) { + case thing_type::S8: return sizeof(s8); + case thing_type::S16: return sizeof(s16); + case thing_type::S32: return sizeof(s32); + case thing_type::S64: return sizeof(s64); + case thing_type::U8: return sizeof(u8); + case thing_type::U16: return sizeof(u16); + case thing_type::U32: return sizeof(u32); + case thing_type::U64: return sizeof(u64); + case Ptr: + case Ref: + case Array: + case Slice: return 0; + case Count: break; + } + throw std::runtime_error("unreachable"); + } +}; + +} // namespace furvm + +#endif // FURVM_TYPES_HPP diff --git a/furvm/src/executor.cpp b/furvm/src/executor.cpp index e1a9862..c85e2b3 100644 --- a/furvm/src/executor.cpp +++ b/furvm/src/executor.cpp @@ -211,44 +211,41 @@ void executor::step() { switch (instr.type) { case instruction_t::NoOperation: break; case instruction_t::PushS8: { - push_thing({ (struct thing_type){ thing_type::S8 }, { m_stackStorage } }).get() = instr.arg.s8; + push_thing({ (struct thing_type){ thing_type::S8 }, { m_stackStorage } }).get() = instr.arg.s8; } break; case instruction_t::PushU8: { - push_thing({ (struct thing_type){ thing_type::U8 }, { m_stackStorage } }).get() = instr.arg.u8; + push_thing({ (struct thing_type){ thing_type::U8 }, { m_stackStorage } }).get() = instr.arg.u8; } break; case instruction_t::PushS16: { - push_thing({ (struct thing_type){ thing_type::S16 }, { m_stackStorage } }).get() = - instr.arg.s16; + push_thing({ (struct thing_type){ thing_type::S16 }, { m_stackStorage } }).get() = instr.arg.s16; } break; case instruction_t::PushU16: { - push_thing({ (struct thing_type){ thing_type::U16 }, { m_stackStorage } }).get() = - instr.arg.u16; + push_thing({ (struct thing_type){ thing_type::U16 }, { m_stackStorage } }).get() = instr.arg.u16; } break; case instruction_t::PushS32: { - push_thing({ (struct thing_type){ thing_type::S32 }, { m_stackStorage } }).get() = - instr.arg.s8; // NOLINT + push_thing({ (struct thing_type){ thing_type::S32 }, { m_stackStorage } }).get() = instr.arg.s8; // NOLINT } break; case instruction_t::PushU32: { - push_thing({ (struct thing_type){ thing_type::U32 }, { m_stackStorage } }).get() = - static_cast(instr.arg.u8); + push_thing({ (struct thing_type){ thing_type::U32 }, { m_stackStorage } }).get() = + static_cast(instr.arg.u8); } break; case instruction_t::PushConstant: { auto constant = frame.mod->constant_at(instr.arg.u16); switch (constant.type) { case constant::S32: - push_thing({ (struct thing_type){ thing_type::S32 }, { m_stackStorage } }).get() = + push_thing({ (struct thing_type){ thing_type::S32 }, { m_stackStorage } }).get() = constant.s32; // NOLINT break; case constant::U32: - push_thing({ (struct thing_type){ thing_type::U32 }, { m_stackStorage } }).get() = + push_thing({ (struct thing_type){ thing_type::U32 }, { m_stackStorage } }).get() = constant.u32; // NOLINT break; case constant::S64: - push_thing({ (struct thing_type){ thing_type::S64 }, { m_stackStorage } }).get() = + push_thing({ (struct thing_type){ thing_type::S64 }, { m_stackStorage } }).get() = constant.s64; // NOLINT break; case constant::U64: - push_thing({ (struct thing_type){ thing_type::U64 }, { m_stackStorage } }).get() = + push_thing({ (struct thing_type){ thing_type::U64 }, { m_stackStorage } }).get() = constant.u64; // NOLINT break; case constant::String: throw std::runtime_error("unimplemented"); @@ -375,23 +372,20 @@ void executor::step() { case thing_type::U8: case thing_type::U16: case thing_type::U32: - case thing_type::U64: - size.get() = static_cast(thing_type::primitive_size(thing.type().type)); - break; - case thing_type::Ptr: size.get() = static_cast(sizeof(void*)); break; + case thing_type::U64: size.get() = static_cast(thing_type::primitive_size(thing.type().type)); break; + case thing_type::Ptr: size.get() = static_cast(sizeof(void*)); break; case thing_type::Array: /* TODO: Return actual memory size of the array * By the memory size I mean the length times sizeof single element. */ - size.get() = thing.length(); + size.get() = thing.length(); break; default: throw std::runtime_error("unreachable"); } } break; case instruction_t::Lengthof: { - auto thing = pop_thing(); - push_thing({ (struct thing_type){ thing_type::U64 }, { m_stackStorage } }).get() = - thing.length(); + auto thing = pop_thing(); + push_thing({ (struct thing_type){ thing_type::U64 }, { m_stackStorage } }).get() = thing.length(); } break; case instruction_t::Load: { push_thing(std::move(stack_thing::make_reference(load_thing(instr.arg.u16), { m_stackStorage }))); diff --git a/furvm/src/main.cpp b/furvm/src/main.cpp index 591aa46..657e378 100644 --- a/furvm/src/main.cpp +++ b/furvm/src/main.cpp @@ -14,17 +14,17 @@ static void print_thing(const furvm::thing<>& thing) { using namespace furvm; switch (thing.type().type) { - case thing_type::S8: std::cout << thing.cast_to(); break; - case thing_type::S16: std::cout << thing.get(); break; - case thing_type::S32: std::cout << thing.get(); break; - case thing_type::S64: std::cout << thing.get(); break; - case thing_type::U8: std::cout << thing.get(); break; - case thing_type::U16: std::cout << thing.get(); break; - case thing_type::U32: std::cout << thing.get(); break; - case thing_type::U64: std::cout << thing.get(); break; + case thing_type::S8: std::cout << thing.cast_to(); break; + case thing_type::S16: std::cout << thing.get(); break; + case thing_type::S32: std::cout << thing.get(); break; + case thing_type::S64: std::cout << thing.get(); break; + case thing_type::U8: std::cout << thing.get(); break; + case thing_type::U16: std::cout << thing.get(); break; + case thing_type::U32: std::cout << thing.get(); break; + case thing_type::U64: std::cout << thing.get(); break; case thing_type::Array: std::cout << "{ "; - for (thing_type::u64 i = 0; i < thing.length(); ++i) { + for (u64 i = 0; i < thing.length(); ++i) { if (i > 0) std::cout << ", "; print_thing(thing.at(i)); } @@ -32,7 +32,7 @@ static void print_thing(const furvm::thing<>& thing) { break; case thing_type::Slice: std::cout << "Slice [" << thing.length() << "] { "; - for (thing_type::u64 i = 0; i < thing.length(); ++i) { + for (u64 i = 0; i < thing.length(); ++i) { if (i > 0) std::cout << ", "; print_thing(thing.at(i)); } diff --git a/furvm/test/test.cpp b/furvm/test/test.cpp index be41e69..c28248b 100644 --- a/furvm/test/test.cpp +++ b/furvm/test/test.cpp @@ -10,28 +10,28 @@ namespace { TEST(ThingOps, Add) { furvm::thing lhs{ furvm::thing_type{ furvm::thing_type::U32 } }; - lhs.get() = 6; + lhs.get() = 6; furvm::thing rhs{ furvm::thing_type{ furvm::thing_type::U32 } }; - rhs.get() = 7; + rhs.get() = 7; auto res = lhs.add(rhs); ASSERT_EQ(res.type().type, furvm::thing_type::U32); - EXPECT_EQ(lhs.get(), 6); - EXPECT_EQ(rhs.get(), 7); - EXPECT_EQ(res.get(), 6 + 7); + EXPECT_EQ(lhs.get(), 6); + EXPECT_EQ(rhs.get(), 7); + EXPECT_EQ(res.get(), 6 + 7); } TEST(ThingOps, Array) { furvm::thing_type innerType = { furvm::thing_type::U32 }; - static constexpr std::size_t LENGTH = 10; - static constexpr std::array values = { 0, 1, 2, 3, 4, 5, 6, 7, 6, 7 }; + static constexpr std::size_t LENGTH = 10; + static constexpr std::array values = { 0, 1, 2, 3, 4, 5, 6, 7, 6, 7 }; furvm::thing array{ furvm::thing_type{ furvm::thing_type::Array, { &innerType, LENGTH } } }; EXPECT_EQ(array.length(), LENGTH); for (std::size_t i = 0; i < LENGTH; ++i) { - auto el = array.at(i); - el.get() = values[i]; + auto el = array.at(i); + el.get() = values[i]; EXPECT_EQ(array.at(i).integer(), values[i]); } } @@ -39,16 +39,16 @@ TEST(ThingOps, Array) { TEST(ThingOps, Slice) { furvm::thing_type innerType = { furvm::thing_type::U32 }; - static constexpr std::size_t LENGTH = 10; - static constexpr std::array values = { 0, 1, 2, 3, 4, 5, 6, 7, 6, 7 }; + static constexpr std::size_t LENGTH = 10; + static constexpr std::array values = { 0, 1, 2, 3, 4, 5, 6, 7, 6, 7 }; furvm::thing array{ furvm::thing_type{ furvm::thing_type::Array, { &innerType, LENGTH } } }; EXPECT_EQ(array.length(), LENGTH); furvm::thing slice = array.slice(0, LENGTH); EXPECT_EQ(slice.length(), LENGTH); for (std::size_t i = 0; i < LENGTH; ++i) { - auto el = slice.at(i); - el.get() = values[i]; + auto el = slice.at(i); + el.get() = values[i]; EXPECT_EQ(array.at(i).integer(), values[i]); EXPECT_EQ(slice.at(i).integer(), array.at(i).integer()); } @@ -57,14 +57,14 @@ TEST(ThingOps, Slice) { TEST(ThingOps, Iterators) { furvm::thing_type innerType = { furvm::thing_type::U32 }; - static constexpr std::size_t LENGTH = 10; - static constexpr std::array values = { 0, 1, 2, 3, 4, 5, 6, 7, 6, 7 }; + static constexpr std::size_t LENGTH = 10; + static constexpr std::array values = { 0, 1, 2, 3, 4, 5, 6, 7, 6, 7 }; furvm::thing array{ furvm::thing_type{ furvm::thing_type::Array, { &innerType, LENGTH } } }; EXPECT_EQ(array.length(), LENGTH); for (std::size_t i = 0; i < LENGTH; ++i) { - auto el = array.at(i); - el.get() = values[i]; + auto el = array.at(i); + el.get() = values[i]; EXPECT_EQ(array.at(i).integer(), values[i]); }