refactor(furvm): move thing type to types.hpp
This commit is contained in:
@@ -121,14 +121,14 @@ static void print_thing(const furvm::thing<>& thing) {
|
|||||||
print_type(thing.type());
|
print_type(thing.type());
|
||||||
std::cout << ") ";
|
std::cout << ") ";
|
||||||
switch (thing.type().type) {
|
switch (thing.type().type) {
|
||||||
case furvm::thing_type::S8: std::cout << std::to_string(thing.get<furvm::thing_type::s8>()); break;
|
case furvm::thing_type::S8: std::cout << std::to_string(thing.get<furvm::s8>()); break;
|
||||||
case furvm::thing_type::S16: std::cout << thing.get<furvm::thing_type::s16>(); break;
|
case furvm::thing_type::S16: std::cout << thing.get<furvm::s16>(); break;
|
||||||
case furvm::thing_type::S32: std::cout << thing.get<furvm::thing_type::s32>(); break;
|
case furvm::thing_type::S32: std::cout << thing.get<furvm::s32>(); break;
|
||||||
case furvm::thing_type::S64: std::cout << thing.get<furvm::thing_type::s64>(); break;
|
case furvm::thing_type::S64: std::cout << thing.get<furvm::s64>(); break;
|
||||||
case furvm::thing_type::U8: std::cout << std::to_string(thing.get<furvm::thing_type::u8>()); break;
|
case furvm::thing_type::U8: std::cout << std::to_string(thing.get<furvm::u8>()); break;
|
||||||
case furvm::thing_type::U16: std::cout << thing.get<furvm::thing_type::u16>(); break;
|
case furvm::thing_type::U16: std::cout << thing.get<furvm::u16>(); break;
|
||||||
case furvm::thing_type::U32: std::cout << thing.get<furvm::thing_type::u32>(); break;
|
case furvm::thing_type::U32: std::cout << thing.get<furvm::u32>(); break;
|
||||||
case furvm::thing_type::U64: std::cout << thing.get<furvm::thing_type::u64>(); break;
|
case furvm::thing_type::U64: std::cout << thing.get<furvm::u64>(); break;
|
||||||
case furvm::thing_type::Ptr: std::cout << thing.get<const void*>(); break;
|
case furvm::thing_type::Ptr: std::cout << thing.get<const void*>(); break;
|
||||||
case furvm::thing_type::Array:
|
case furvm::thing_type::Array:
|
||||||
case furvm::thing_type::Slice: {
|
case furvm::thing_type::Slice: {
|
||||||
|
|||||||
+9
-9
@@ -15,17 +15,17 @@ static void print_thing(const furvm::thing<>& thing) {
|
|||||||
using namespace furvm;
|
using namespace furvm;
|
||||||
|
|
||||||
switch (thing.type().type) {
|
switch (thing.type().type) {
|
||||||
case thing_type::S8: std::cout << thing.cast_to<thing_type::s16>(); break;
|
case thing_type::S8: std::cout << thing.cast_to<s16>(); break;
|
||||||
case thing_type::S16: std::cout << thing.get<thing_type::s16>(); break;
|
case thing_type::S16: std::cout << thing.get<s16>(); break;
|
||||||
case thing_type::S32: std::cout << thing.get<thing_type::s32>(); break;
|
case thing_type::S32: std::cout << thing.get<s32>(); break;
|
||||||
case thing_type::S64: std::cout << thing.get<thing_type::s64>(); break;
|
case thing_type::S64: std::cout << thing.get<s64>(); break;
|
||||||
case thing_type::U8: std::cout << thing.get<thing_type::u8>(); break;
|
case thing_type::U8: std::cout << thing.get<u8>(); break;
|
||||||
case thing_type::U16: std::cout << thing.get<thing_type::u16>(); break;
|
case thing_type::U16: std::cout << thing.get<u16>(); break;
|
||||||
case thing_type::U32: std::cout << thing.get<thing_type::u32>(); break;
|
case thing_type::U32: std::cout << thing.get<u32>(); break;
|
||||||
case thing_type::U64: std::cout << thing.get<thing_type::u64>(); break;
|
case thing_type::U64: std::cout << thing.get<u64>(); break;
|
||||||
case thing_type::Array:
|
case thing_type::Array:
|
||||||
std::cout << "{ ";
|
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 << ", ";
|
if (i > 0) std::cout << ", ";
|
||||||
print_thing(thing.at(i));
|
print_thing(thing.at(i));
|
||||||
}
|
}
|
||||||
|
|||||||
+39
-173
@@ -5,6 +5,7 @@
|
|||||||
#include "furlang/utility/hash.hpp"
|
#include "furlang/utility/hash.hpp"
|
||||||
#include "furvm/exceptions.hpp"
|
#include "furvm/exceptions.hpp"
|
||||||
#include "furvm/fwd.hpp"
|
#include "furvm/fwd.hpp"
|
||||||
|
#include "furvm/types.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
@@ -12,7 +13,6 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <limits>
|
|
||||||
#include <new>
|
#include <new>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
@@ -21,124 +21,6 @@
|
|||||||
|
|
||||||
namespace furvm {
|
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<thing_type_id>::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 {
|
namespace detail {
|
||||||
|
|
||||||
struct thing_type_hash {
|
struct thing_type_hash {
|
||||||
@@ -633,21 +515,21 @@ public:
|
|||||||
*
|
*
|
||||||
* @return The integer value.
|
* @return The integer value.
|
||||||
*/
|
*/
|
||||||
thing_type::s64 integer() const {
|
s64 integer() const {
|
||||||
switch (type().type) {
|
switch (type().type) {
|
||||||
case thing_type::S8: return get<thing_type::s8>();
|
case thing_type::S8: return get<s8>();
|
||||||
case thing_type::S16: return get<thing_type::s16>();
|
case thing_type::S16: return get<s16>();
|
||||||
case thing_type::S32: return get<thing_type::s32>();
|
case thing_type::S32: return get<s32>();
|
||||||
case thing_type::S64: return get<thing_type::s64>();
|
case thing_type::S64: return get<s64>();
|
||||||
case thing_type::U8: return get<thing_type::u8>();
|
case thing_type::U8: return get<u8>();
|
||||||
case thing_type::U16: return get<thing_type::u16>();
|
case thing_type::U16: return get<u16>();
|
||||||
case thing_type::U32: return get<thing_type::u32>();
|
case thing_type::U32: return get<u32>();
|
||||||
case thing_type::U64: return get<thing_type::u64>();
|
case thing_type::U64: return get<u64>();
|
||||||
default: throw std::runtime_error("unreachable");
|
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 (!is(thing_type::Array)) throw bad_thing_access();
|
||||||
if (type().value.array.size > 0) throw std::runtime_error("cannot resize a static array");
|
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;
|
if (newSize < 0 || newSize == array.size) return;
|
||||||
std::size_t innerSize = compute_size_na(*type().value.array.type);
|
std::size_t innerSize = compute_size_na(*type().value.array.type);
|
||||||
std::byte* newData = new std::byte[innerSize * newSize];
|
std::byte* newData = new std::byte[innerSize * newSize];
|
||||||
std::memcpy(newData, array.data, innerSize * std::min(static_cast<thing_type::u64>(array.size), newSize));
|
std::memcpy(newData, array.data, innerSize * std::min(static_cast<u64>(array.size), newSize));
|
||||||
array.size = newSize;
|
array.size = newSize;
|
||||||
delete[] array.data;
|
delete[] array.data;
|
||||||
array.data = newData;
|
array.data = newData;
|
||||||
}
|
}
|
||||||
|
|
||||||
thing at(thing_type::u64 index) const {
|
thing at(u64 index) const {
|
||||||
thing ref = { m_allocator };
|
thing ref = { m_allocator };
|
||||||
ref.m_reference = true;
|
ref.m_reference = true;
|
||||||
ref.m_size = compute_size_na(*(ref.m_type = &inner_type()));
|
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();
|
auto& inner = inner_type();
|
||||||
|
|
||||||
thing_type sliceType;
|
thing_type sliceType;
|
||||||
@@ -718,7 +600,7 @@ public:
|
|||||||
return slice;
|
return slice;
|
||||||
}
|
}
|
||||||
|
|
||||||
thing_type::u64 length() const {
|
u64 length() const {
|
||||||
switch (type().type) {
|
switch (type().type) {
|
||||||
case thing_type::Array:
|
case thing_type::Array:
|
||||||
return type().value.array.size == 0 ? get<dynamic_array>().size : type().value.array.size;
|
return type().value.array.size == 0 ? get<dynamic_array>().size : type().value.array.size;
|
||||||
@@ -833,14 +715,14 @@ private:
|
|||||||
private:
|
private:
|
||||||
static std::size_t compute_size_na(const thing_type& type) {
|
static std::size_t compute_size_na(const thing_type& type) {
|
||||||
switch (type.type) {
|
switch (type.type) {
|
||||||
case thing_type::S8: return sizeof(thing_type::s8);
|
case thing_type::S8: return sizeof(s8);
|
||||||
case thing_type::S16: return sizeof(thing_type::s16);
|
case thing_type::S16: return sizeof(s16);
|
||||||
case thing_type::S32: return sizeof(thing_type::s32);
|
case thing_type::S32: return sizeof(s32);
|
||||||
case thing_type::S64: return sizeof(thing_type::s64);
|
case thing_type::S64: return sizeof(s64);
|
||||||
case thing_type::U8: return sizeof(thing_type::u8);
|
case thing_type::U8: return sizeof(u8);
|
||||||
case thing_type::U16: return sizeof(thing_type::u16);
|
case thing_type::U16: return sizeof(u16);
|
||||||
case thing_type::U32: return sizeof(thing_type::u32);
|
case thing_type::U32: return sizeof(u32);
|
||||||
case thing_type::U64: return sizeof(thing_type::u64);
|
case thing_type::U64: return sizeof(u64);
|
||||||
case thing_type::Ptr: return sizeof(void*);
|
case thing_type::Ptr: return sizeof(void*);
|
||||||
case thing_type::Array:
|
case thing_type::Array:
|
||||||
return type.value.array.size == 0 ? sizeof(dynamic_array)
|
return type.value.array.size == 0 ? sizeof(dynamic_array)
|
||||||
@@ -859,14 +741,14 @@ private:
|
|||||||
template <typename Func>
|
template <typename Func>
|
||||||
decltype(auto) visit_primitive(Func&& func) const {
|
decltype(auto) visit_primitive(Func&& func) const {
|
||||||
switch (type().type) {
|
switch (type().type) {
|
||||||
case thing_type::S8: return std::forward<Func>(func)(get<thing_type::s8>());
|
case thing_type::S8: return std::forward<Func>(func)(get<s8>());
|
||||||
case thing_type::S16: return std::forward<Func>(func)(get<thing_type::s16>());
|
case thing_type::S16: return std::forward<Func>(func)(get<s16>());
|
||||||
case thing_type::S32: return std::forward<Func>(func)(get<thing_type::s32>());
|
case thing_type::S32: return std::forward<Func>(func)(get<s32>());
|
||||||
case thing_type::S64: return std::forward<Func>(func)(get<thing_type::s64>());
|
case thing_type::S64: return std::forward<Func>(func)(get<s64>());
|
||||||
case thing_type::U8: return std::forward<Func>(func)(get<thing_type::u8>());
|
case thing_type::U8: return std::forward<Func>(func)(get<u8>());
|
||||||
case thing_type::U16: return std::forward<Func>(func)(get<thing_type::u16>());
|
case thing_type::U16: return std::forward<Func>(func)(get<u16>());
|
||||||
case thing_type::U32: return std::forward<Func>(func)(get<thing_type::u32>());
|
case thing_type::U32: return std::forward<Func>(func)(get<u32>());
|
||||||
case thing_type::U64: return std::forward<Func>(func)(get<thing_type::u64>());
|
case thing_type::U64: return std::forward<Func>(func)(get<u64>());
|
||||||
default: throw bad_thing_access();
|
default: throw bad_thing_access();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -953,30 +835,14 @@ private:
|
|||||||
|
|
||||||
thing res = { thing_type{ resultType }, m_allocator };
|
thing res = { thing_type{ resultType }, m_allocator };
|
||||||
switch (resultType) {
|
switch (resultType) {
|
||||||
case thing_type::S8:
|
case thing_type::S8: res.get<s8>() = Op{}(cast_to<s8>(), rhs.cast_to<s8>()); return res;
|
||||||
res.get<thing_type::s8>() = Op{}(cast_to<thing_type::s8>(), rhs.cast_to<thing_type::s8>());
|
case thing_type::S16: res.get<s16>() = Op{}(cast_to<s16>(), rhs.cast_to<s16>()); return res;
|
||||||
return res;
|
case thing_type::S32: res.get<s32>() = Op{}(cast_to<s32>(), rhs.cast_to<s32>()); return res;
|
||||||
case thing_type::S16:
|
case thing_type::S64: res.get<s64>() = Op{}(cast_to<s64>(), rhs.cast_to<s64>()); return res;
|
||||||
res.get<thing_type::s16>() = Op{}(cast_to<thing_type::s16>(), rhs.cast_to<thing_type::s16>());
|
case thing_type::U8: res.get<u8>() = Op{}(cast_to<u8>(), rhs.cast_to<u8>()); return res;
|
||||||
return res;
|
case thing_type::U16: res.get<u16>() = Op{}(cast_to<u16>(), rhs.cast_to<u16>()); return res;
|
||||||
case thing_type::S32:
|
case thing_type::U32: res.get<u32>() = Op{}(cast_to<u32>(), rhs.cast_to<u32>()); return res;
|
||||||
res.get<thing_type::s32>() = Op{}(cast_to<thing_type::s32>(), rhs.cast_to<thing_type::s32>());
|
case thing_type::U64: res.get<u64>() = Op{}(cast_to<u64>(), rhs.cast_to<u64>()); return res;
|
||||||
return res;
|
|
||||||
case thing_type::S64:
|
|
||||||
res.get<thing_type::s64>() = Op{}(cast_to<thing_type::s64>(), rhs.cast_to<thing_type::s64>());
|
|
||||||
return res;
|
|
||||||
case thing_type::U8:
|
|
||||||
res.get<thing_type::u8>() = Op{}(cast_to<thing_type::u8>(), rhs.cast_to<thing_type::u8>());
|
|
||||||
return res;
|
|
||||||
case thing_type::U16:
|
|
||||||
res.get<thing_type::u16>() = Op{}(cast_to<thing_type::u16>(), rhs.cast_to<thing_type::u16>());
|
|
||||||
return res;
|
|
||||||
case thing_type::U32:
|
|
||||||
res.get<thing_type::u32>() = Op{}(cast_to<thing_type::u32>(), rhs.cast_to<thing_type::u32>());
|
|
||||||
return res;
|
|
||||||
case thing_type::U64:
|
|
||||||
res.get<thing_type::u64>() = Op{}(cast_to<thing_type::u64>(), rhs.cast_to<thing_type::u64>());
|
|
||||||
return res;
|
|
||||||
case thing_type::Ptr: // TODO: Pointer arithmetics
|
case thing_type::Ptr: // TODO: Pointer arithmetics
|
||||||
case thing_type::Ref:
|
case thing_type::Ref:
|
||||||
case thing_type::Array:
|
case thing_type::Array:
|
||||||
|
|||||||
@@ -0,0 +1,132 @@
|
|||||||
|
#ifndef FURVM_TYPES_HPP
|
||||||
|
#define FURVM_TYPES_HPP
|
||||||
|
|
||||||
|
#include "furvm/fwd.hpp"
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <limits>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
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<thing_type_id>::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
|
||||||
+16
-22
@@ -211,44 +211,41 @@ void executor::step() {
|
|||||||
switch (instr.type) {
|
switch (instr.type) {
|
||||||
case instruction_t::NoOperation: break;
|
case instruction_t::NoOperation: break;
|
||||||
case instruction_t::PushS8: {
|
case instruction_t::PushS8: {
|
||||||
push_thing({ (struct thing_type){ thing_type::S8 }, { m_stackStorage } }).get<thing_type::s8>() = instr.arg.s8;
|
push_thing({ (struct thing_type){ thing_type::S8 }, { m_stackStorage } }).get<s8>() = instr.arg.s8;
|
||||||
} break;
|
} break;
|
||||||
case instruction_t::PushU8: {
|
case instruction_t::PushU8: {
|
||||||
push_thing({ (struct thing_type){ thing_type::U8 }, { m_stackStorage } }).get<thing_type::u8>() = instr.arg.u8;
|
push_thing({ (struct thing_type){ thing_type::U8 }, { m_stackStorage } }).get<u8>() = instr.arg.u8;
|
||||||
} break;
|
} break;
|
||||||
case instruction_t::PushS16: {
|
case instruction_t::PushS16: {
|
||||||
push_thing({ (struct thing_type){ thing_type::S16 }, { m_stackStorage } }).get<thing_type::s16>() =
|
push_thing({ (struct thing_type){ thing_type::S16 }, { m_stackStorage } }).get<s16>() = instr.arg.s16;
|
||||||
instr.arg.s16;
|
|
||||||
} break;
|
} break;
|
||||||
case instruction_t::PushU16: {
|
case instruction_t::PushU16: {
|
||||||
push_thing({ (struct thing_type){ thing_type::U16 }, { m_stackStorage } }).get<thing_type::u16>() =
|
push_thing({ (struct thing_type){ thing_type::U16 }, { m_stackStorage } }).get<u16>() = instr.arg.u16;
|
||||||
instr.arg.u16;
|
|
||||||
} break;
|
} break;
|
||||||
case instruction_t::PushS32: {
|
case instruction_t::PushS32: {
|
||||||
push_thing({ (struct thing_type){ thing_type::S32 }, { m_stackStorage } }).get<thing_type::s32>() =
|
push_thing({ (struct thing_type){ thing_type::S32 }, { m_stackStorage } }).get<s32>() = instr.arg.s8; // NOLINT
|
||||||
instr.arg.s8; // NOLINT
|
|
||||||
} break;
|
} break;
|
||||||
case instruction_t::PushU32: {
|
case instruction_t::PushU32: {
|
||||||
push_thing({ (struct thing_type){ thing_type::U32 }, { m_stackStorage } }).get<thing_type::u32>() =
|
push_thing({ (struct thing_type){ thing_type::U32 }, { m_stackStorage } }).get<u32>() =
|
||||||
static_cast<thing_type::u32>(instr.arg.u8);
|
static_cast<u32>(instr.arg.u8);
|
||||||
} break;
|
} break;
|
||||||
case instruction_t::PushConstant: {
|
case instruction_t::PushConstant: {
|
||||||
auto constant = frame.mod->constant_at(instr.arg.u16);
|
auto constant = frame.mod->constant_at(instr.arg.u16);
|
||||||
switch (constant.type) {
|
switch (constant.type) {
|
||||||
case constant::S32:
|
case constant::S32:
|
||||||
push_thing({ (struct thing_type){ thing_type::S32 }, { m_stackStorage } }).get<thing_type::s32>() =
|
push_thing({ (struct thing_type){ thing_type::S32 }, { m_stackStorage } }).get<s32>() =
|
||||||
constant.s32; // NOLINT
|
constant.s32; // NOLINT
|
||||||
break;
|
break;
|
||||||
case constant::U32:
|
case constant::U32:
|
||||||
push_thing({ (struct thing_type){ thing_type::U32 }, { m_stackStorage } }).get<thing_type::u32>() =
|
push_thing({ (struct thing_type){ thing_type::U32 }, { m_stackStorage } }).get<u32>() =
|
||||||
constant.u32; // NOLINT
|
constant.u32; // NOLINT
|
||||||
break;
|
break;
|
||||||
case constant::S64:
|
case constant::S64:
|
||||||
push_thing({ (struct thing_type){ thing_type::S64 }, { m_stackStorage } }).get<thing_type::s64>() =
|
push_thing({ (struct thing_type){ thing_type::S64 }, { m_stackStorage } }).get<s64>() =
|
||||||
constant.s64; // NOLINT
|
constant.s64; // NOLINT
|
||||||
break;
|
break;
|
||||||
case constant::U64:
|
case constant::U64:
|
||||||
push_thing({ (struct thing_type){ thing_type::U64 }, { m_stackStorage } }).get<thing_type::u64>() =
|
push_thing({ (struct thing_type){ thing_type::U64 }, { m_stackStorage } }).get<u64>() =
|
||||||
constant.u64; // NOLINT
|
constant.u64; // NOLINT
|
||||||
break;
|
break;
|
||||||
case constant::String: throw std::runtime_error("unimplemented");
|
case constant::String: throw std::runtime_error("unimplemented");
|
||||||
@@ -375,23 +372,20 @@ void executor::step() {
|
|||||||
case thing_type::U8:
|
case thing_type::U8:
|
||||||
case thing_type::U16:
|
case thing_type::U16:
|
||||||
case thing_type::U32:
|
case thing_type::U32:
|
||||||
case thing_type::U64:
|
case thing_type::U64: size.get<u64>() = static_cast<u64>(thing_type::primitive_size(thing.type().type)); break;
|
||||||
size.get<thing_type::u64>() = static_cast<thing_type::u64>(thing_type::primitive_size(thing.type().type));
|
case thing_type::Ptr: size.get<u64>() = static_cast<u64>(sizeof(void*)); break;
|
||||||
break;
|
|
||||||
case thing_type::Ptr: size.get<thing_type::u64>() = static_cast<thing_type::u64>(sizeof(void*)); break;
|
|
||||||
case thing_type::Array:
|
case thing_type::Array:
|
||||||
/* TODO: Return actual memory size of the array
|
/* TODO: Return actual memory size of the array
|
||||||
* By the memory size I mean the length times sizeof single element.
|
* By the memory size I mean the length times sizeof single element.
|
||||||
*/
|
*/
|
||||||
size.get<thing_type::u64>() = thing.length();
|
size.get<u64>() = thing.length();
|
||||||
break;
|
break;
|
||||||
default: throw std::runtime_error("unreachable");
|
default: throw std::runtime_error("unreachable");
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case instruction_t::Lengthof: {
|
case instruction_t::Lengthof: {
|
||||||
auto thing = pop_thing();
|
auto thing = pop_thing();
|
||||||
push_thing({ (struct thing_type){ thing_type::U64 }, { m_stackStorage } }).get<thing_type::u64>() =
|
push_thing({ (struct thing_type){ thing_type::U64 }, { m_stackStorage } }).get<u64>() = thing.length();
|
||||||
thing.length();
|
|
||||||
} break;
|
} break;
|
||||||
case instruction_t::Load: {
|
case instruction_t::Load: {
|
||||||
push_thing(std::move(stack_thing::make_reference(load_thing(instr.arg.u16), { m_stackStorage })));
|
push_thing(std::move(stack_thing::make_reference(load_thing(instr.arg.u16), { m_stackStorage })));
|
||||||
|
|||||||
+10
-10
@@ -14,17 +14,17 @@ static void print_thing(const furvm::thing<>& thing) {
|
|||||||
using namespace furvm;
|
using namespace furvm;
|
||||||
|
|
||||||
switch (thing.type().type) {
|
switch (thing.type().type) {
|
||||||
case thing_type::S8: std::cout << thing.cast_to<thing_type::s16>(); break;
|
case thing_type::S8: std::cout << thing.cast_to<s16>(); break;
|
||||||
case thing_type::S16: std::cout << thing.get<thing_type::s16>(); break;
|
case thing_type::S16: std::cout << thing.get<s16>(); break;
|
||||||
case thing_type::S32: std::cout << thing.get<thing_type::s32>(); break;
|
case thing_type::S32: std::cout << thing.get<s32>(); break;
|
||||||
case thing_type::S64: std::cout << thing.get<thing_type::s64>(); break;
|
case thing_type::S64: std::cout << thing.get<s64>(); break;
|
||||||
case thing_type::U8: std::cout << thing.get<thing_type::u8>(); break;
|
case thing_type::U8: std::cout << thing.get<u8>(); break;
|
||||||
case thing_type::U16: std::cout << thing.get<thing_type::u16>(); break;
|
case thing_type::U16: std::cout << thing.get<u16>(); break;
|
||||||
case thing_type::U32: std::cout << thing.get<thing_type::u32>(); break;
|
case thing_type::U32: std::cout << thing.get<u32>(); break;
|
||||||
case thing_type::U64: std::cout << thing.get<thing_type::u64>(); break;
|
case thing_type::U64: std::cout << thing.get<u64>(); break;
|
||||||
case thing_type::Array:
|
case thing_type::Array:
|
||||||
std::cout << "{ ";
|
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 << ", ";
|
if (i > 0) std::cout << ", ";
|
||||||
print_thing(thing.at(i));
|
print_thing(thing.at(i));
|
||||||
}
|
}
|
||||||
@@ -32,7 +32,7 @@ static void print_thing(const furvm::thing<>& thing) {
|
|||||||
break;
|
break;
|
||||||
case thing_type::Slice:
|
case thing_type::Slice:
|
||||||
std::cout << "Slice [" << thing.length() << "] { ";
|
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 << ", ";
|
if (i > 0) std::cout << ", ";
|
||||||
print_thing(thing.at(i));
|
print_thing(thing.at(i));
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-17
@@ -10,28 +10,28 @@ namespace {
|
|||||||
|
|
||||||
TEST(ThingOps, Add) {
|
TEST(ThingOps, Add) {
|
||||||
furvm::thing lhs{ furvm::thing_type{ furvm::thing_type::U32 } };
|
furvm::thing lhs{ furvm::thing_type{ furvm::thing_type::U32 } };
|
||||||
lhs.get<furvm::thing_type::u32>() = 6;
|
lhs.get<furvm::u32>() = 6;
|
||||||
furvm::thing rhs{ furvm::thing_type{ furvm::thing_type::U32 } };
|
furvm::thing rhs{ furvm::thing_type{ furvm::thing_type::U32 } };
|
||||||
rhs.get<furvm::thing_type::u32>() = 7;
|
rhs.get<furvm::u32>() = 7;
|
||||||
|
|
||||||
auto res = lhs.add(rhs);
|
auto res = lhs.add(rhs);
|
||||||
ASSERT_EQ(res.type().type, furvm::thing_type::U32);
|
ASSERT_EQ(res.type().type, furvm::thing_type::U32);
|
||||||
EXPECT_EQ(lhs.get<furvm::thing_type::u32>(), 6);
|
EXPECT_EQ(lhs.get<furvm::u32>(), 6);
|
||||||
EXPECT_EQ(rhs.get<furvm::thing_type::u32>(), 7);
|
EXPECT_EQ(rhs.get<furvm::u32>(), 7);
|
||||||
EXPECT_EQ(res.get<furvm::thing_type::u32>(), 6 + 7);
|
EXPECT_EQ(res.get<furvm::u32>(), 6 + 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ThingOps, Array) {
|
TEST(ThingOps, Array) {
|
||||||
furvm::thing_type innerType = { furvm::thing_type::U32 };
|
furvm::thing_type innerType = { furvm::thing_type::U32 };
|
||||||
|
|
||||||
static constexpr std::size_t LENGTH = 10;
|
static constexpr std::size_t LENGTH = 10;
|
||||||
static constexpr std::array<furvm::thing_type::u32, LENGTH> values = { 0, 1, 2, 3, 4, 5, 6, 7, 6, 7 };
|
static constexpr std::array<furvm::u32, LENGTH> values = { 0, 1, 2, 3, 4, 5, 6, 7, 6, 7 };
|
||||||
|
|
||||||
furvm::thing array{ furvm::thing_type{ furvm::thing_type::Array, { &innerType, LENGTH } } };
|
furvm::thing array{ furvm::thing_type{ furvm::thing_type::Array, { &innerType, LENGTH } } };
|
||||||
EXPECT_EQ(array.length(), LENGTH);
|
EXPECT_EQ(array.length(), LENGTH);
|
||||||
for (std::size_t i = 0; i < LENGTH; ++i) {
|
for (std::size_t i = 0; i < LENGTH; ++i) {
|
||||||
auto el = array.at(i);
|
auto el = array.at(i);
|
||||||
el.get<furvm::thing_type::u32>() = values[i];
|
el.get<furvm::u32>() = values[i];
|
||||||
EXPECT_EQ(array.at(i).integer(), values[i]);
|
EXPECT_EQ(array.at(i).integer(), values[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -39,16 +39,16 @@ TEST(ThingOps, Array) {
|
|||||||
TEST(ThingOps, Slice) {
|
TEST(ThingOps, Slice) {
|
||||||
furvm::thing_type innerType = { furvm::thing_type::U32 };
|
furvm::thing_type innerType = { furvm::thing_type::U32 };
|
||||||
|
|
||||||
static constexpr std::size_t LENGTH = 10;
|
static constexpr std::size_t LENGTH = 10;
|
||||||
static constexpr std::array<furvm::thing_type::u32, LENGTH> values = { 0, 1, 2, 3, 4, 5, 6, 7, 6, 7 };
|
static constexpr std::array<furvm::u32, LENGTH> values = { 0, 1, 2, 3, 4, 5, 6, 7, 6, 7 };
|
||||||
|
|
||||||
furvm::thing array{ furvm::thing_type{ furvm::thing_type::Array, { &innerType, LENGTH } } };
|
furvm::thing array{ furvm::thing_type{ furvm::thing_type::Array, { &innerType, LENGTH } } };
|
||||||
EXPECT_EQ(array.length(), LENGTH);
|
EXPECT_EQ(array.length(), LENGTH);
|
||||||
furvm::thing slice = array.slice(0, LENGTH);
|
furvm::thing slice = array.slice(0, LENGTH);
|
||||||
EXPECT_EQ(slice.length(), LENGTH);
|
EXPECT_EQ(slice.length(), LENGTH);
|
||||||
for (std::size_t i = 0; i < LENGTH; ++i) {
|
for (std::size_t i = 0; i < LENGTH; ++i) {
|
||||||
auto el = slice.at(i);
|
auto el = slice.at(i);
|
||||||
el.get<furvm::thing_type::u32>() = values[i];
|
el.get<furvm::u32>() = values[i];
|
||||||
EXPECT_EQ(array.at(i).integer(), values[i]);
|
EXPECT_EQ(array.at(i).integer(), values[i]);
|
||||||
EXPECT_EQ(slice.at(i).integer(), array.at(i).integer());
|
EXPECT_EQ(slice.at(i).integer(), array.at(i).integer());
|
||||||
}
|
}
|
||||||
@@ -57,14 +57,14 @@ TEST(ThingOps, Slice) {
|
|||||||
TEST(ThingOps, Iterators) {
|
TEST(ThingOps, Iterators) {
|
||||||
furvm::thing_type innerType = { furvm::thing_type::U32 };
|
furvm::thing_type innerType = { furvm::thing_type::U32 };
|
||||||
|
|
||||||
static constexpr std::size_t LENGTH = 10;
|
static constexpr std::size_t LENGTH = 10;
|
||||||
static constexpr std::array<furvm::thing_type::u32, LENGTH> values = { 0, 1, 2, 3, 4, 5, 6, 7, 6, 7 };
|
static constexpr std::array<furvm::u32, LENGTH> values = { 0, 1, 2, 3, 4, 5, 6, 7, 6, 7 };
|
||||||
|
|
||||||
furvm::thing array{ furvm::thing_type{ furvm::thing_type::Array, { &innerType, LENGTH } } };
|
furvm::thing array{ furvm::thing_type{ furvm::thing_type::Array, { &innerType, LENGTH } } };
|
||||||
EXPECT_EQ(array.length(), LENGTH);
|
EXPECT_EQ(array.length(), LENGTH);
|
||||||
for (std::size_t i = 0; i < LENGTH; ++i) {
|
for (std::size_t i = 0; i < LENGTH; ++i) {
|
||||||
auto el = array.at(i);
|
auto el = array.at(i);
|
||||||
el.get<furvm::thing_type::u32>() = values[i];
|
el.get<furvm::u32>() = values[i];
|
||||||
EXPECT_EQ(array.at(i).integer(), values[i]);
|
EXPECT_EQ(array.at(i).integer(), values[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user