refactor: remove furc for later remake
This commit is contained in:
@@ -126,7 +126,7 @@ public:
|
||||
*/
|
||||
thing_allocator<std::byte> thing_alloc() const { return m_thingAllocator; }
|
||||
|
||||
thing_type_store& thing_type_store() { return m_thingTypeStore; }
|
||||
thing_type_store& tt_store() { return m_thingTypeStore; }
|
||||
private:
|
||||
handle_container<mod_h> m_modules;
|
||||
handle_container<thing_h> m_things;
|
||||
|
||||
@@ -169,7 +169,7 @@ public:
|
||||
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;
|
||||
thing_type* mod_to_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;
|
||||
|
||||
@@ -18,12 +18,12 @@
|
||||
namespace furvm {
|
||||
|
||||
struct mod_type {
|
||||
struct array {
|
||||
struct array_value {
|
||||
mod_type_id typeId;
|
||||
std::size_t size;
|
||||
};
|
||||
|
||||
struct imprt {
|
||||
struct import_value {
|
||||
mod_id modId;
|
||||
mod_type_id typeId;
|
||||
};
|
||||
@@ -47,8 +47,8 @@ struct mod_type {
|
||||
union value {
|
||||
std::nullptr_t null = nullptr;
|
||||
mod_type_id typeRef;
|
||||
array array;
|
||||
imprt imprt;
|
||||
array_value array;
|
||||
import_value imprt;
|
||||
|
||||
value() = default;
|
||||
|
||||
@@ -91,8 +91,8 @@ struct mod_type {
|
||||
|
||||
~mod_type() {
|
||||
switch (type) {
|
||||
case Array: value.array.~array(); break;
|
||||
case Import: value.imprt.~imprt(); break;
|
||||
case Array: value.array.~array_value(); break;
|
||||
case Import: value.imprt.~import_value(); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
@@ -100,8 +100,8 @@ struct mod_type {
|
||||
mod_type(mod_type&& other) noexcept
|
||||
: type(other.type) {
|
||||
switch (type) {
|
||||
case Array: new (&value.array) array(other.value.array); break;
|
||||
case Import: new (&value.imprt) imprt(std::move(other.value.imprt)); break;
|
||||
case Array: new (&value.array) array_value(other.value.array); break;
|
||||
case Import: new (&value.imprt) import_value(std::move(other.value.imprt)); break;
|
||||
default: break;
|
||||
}
|
||||
other.type = Count;
|
||||
@@ -111,8 +111,8 @@ struct mod_type {
|
||||
if (this == &other) return *this;
|
||||
type = other.type;
|
||||
switch (type) {
|
||||
case Array: new (&value.array) array(other.value.array); break;
|
||||
case Import: new (&value.imprt) imprt(std::move(other.value.imprt)); break;
|
||||
case Array: new (&value.array) array_value(other.value.array); break;
|
||||
case Import: new (&value.imprt) import_value(std::move(other.value.imprt)); break;
|
||||
default: break;
|
||||
}
|
||||
other.type = Count;
|
||||
@@ -122,8 +122,8 @@ struct mod_type {
|
||||
mod_type(const mod_type& other)
|
||||
: type(other.type) {
|
||||
switch (type) {
|
||||
case Array: new (&value.array) array(other.value.array); break;
|
||||
case Import: new (&value.imprt) imprt(other.value.imprt); break;
|
||||
case Array: new (&value.array) array_value(other.value.array); break;
|
||||
case Import: new (&value.imprt) import_value(other.value.imprt); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
@@ -132,8 +132,8 @@ struct mod_type {
|
||||
if (this == &other) return *this;
|
||||
type = other.type;
|
||||
switch (type) {
|
||||
case Array: new (&value.array) array(other.value.array); break;
|
||||
case Import: new (&value.imprt) imprt(other.value.imprt); break;
|
||||
case Array: new (&value.array) array_value(other.value.array); break;
|
||||
case Import: new (&value.imprt) import_value(other.value.imprt); break;
|
||||
default: break;
|
||||
}
|
||||
return *this;
|
||||
@@ -181,7 +181,7 @@ public:
|
||||
* @param offset An offset of the byte.
|
||||
* @return The byte.
|
||||
*/
|
||||
constexpr byte byte(std::size_t offset) const { return m_bytecode.at(offset); }
|
||||
byte byte_at(std::size_t offset) const { return m_bytecode.at(offset); }
|
||||
|
||||
/**
|
||||
* @brief Returns the module's bytecode.
|
||||
|
||||
@@ -30,7 +30,7 @@ struct thing_type {
|
||||
using u32 = std::uint32_t;
|
||||
using u64 = std::uint64_t;
|
||||
|
||||
struct array {
|
||||
struct array_value {
|
||||
thing_type* type;
|
||||
std::size_t size;
|
||||
};
|
||||
@@ -53,7 +53,7 @@ struct thing_type {
|
||||
union value {
|
||||
std::nullptr_t null = nullptr;
|
||||
thing_type* typeRef;
|
||||
array array;
|
||||
array_value array;
|
||||
|
||||
value() = default;
|
||||
|
||||
@@ -197,12 +197,9 @@ class thing final {
|
||||
public:
|
||||
using allocator_type = Allocator<std::byte>; /**< Allocator type. */
|
||||
public:
|
||||
union array {
|
||||
std::byte flat[];
|
||||
struct {
|
||||
std::size_t size;
|
||||
std::byte* data;
|
||||
} dynamic;
|
||||
struct dynamic_array {
|
||||
std::size_t size;
|
||||
std::byte* data;
|
||||
};
|
||||
public:
|
||||
/**
|
||||
@@ -270,7 +267,7 @@ public:
|
||||
case thing_type::U32:
|
||||
case thing_type::U64:
|
||||
case thing_type::Ptr: std::memcpy(res.m_data, m_data, m_size); return std::move(res);
|
||||
case thing_type::Array: copy_list(m_type, res.get<array>(), get<array>()); return std::move(res);
|
||||
case thing_type::Array: copy_list(m_type, res.m_data, m_data); return std::move(res);
|
||||
case thing_type::Ref: throw std::runtime_error("cannot clone references");
|
||||
case thing_type::Count: break;
|
||||
}
|
||||
@@ -450,16 +447,14 @@ public:
|
||||
if (!is(thing_type::Array)) throw bad_thing_access();
|
||||
if (true_type().value.array.size > 0) throw std::runtime_error("cannot resize a static array");
|
||||
|
||||
auto& array = get<union array>();
|
||||
if (newSize < 0 || newSize == array.dynamic.size) return;
|
||||
auto& array = get<dynamic_array>();
|
||||
if (newSize < 0 || newSize == array.size) return;
|
||||
std::size_t innerSize = compute_size_na(*true_type().value.array.type);
|
||||
std::byte* newData = new std::byte[innerSize * newSize];
|
||||
std::memcpy(newData,
|
||||
array.dynamic.data,
|
||||
innerSize * std::min(static_cast<thing_type::u64>(array.dynamic.size), newSize));
|
||||
array.dynamic.size = newSize;
|
||||
delete[] array.dynamic.data;
|
||||
array.dynamic.data = newData;
|
||||
std::memcpy(newData, array.data, innerSize * std::min(static_cast<thing_type::u64>(array.size), newSize));
|
||||
array.size = newSize;
|
||||
delete[] array.data;
|
||||
array.data = newData;
|
||||
}
|
||||
|
||||
thing at(thing_type::u64 index) const {
|
||||
@@ -467,23 +462,22 @@ public:
|
||||
|
||||
std::size_t elementSize = compute_size_na(*m_type.value.array.type);
|
||||
if (m_type.value.array.size == 0) {
|
||||
auto& array = get<union array>();
|
||||
if (index < 0 || index >= array.dynamic.size) throw std::out_of_range("index out of range");
|
||||
auto& array = get<dynamic_array>();
|
||||
if (index < 0 || index >= array.size) throw std::out_of_range("index out of range");
|
||||
thing ref = { { thing_type::Ref, m_type.value.array.type }, m_allocator };
|
||||
ref.m_data = array.dynamic.data + (index * elementSize);
|
||||
ref.m_data = array.data + (index * elementSize);
|
||||
return ref;
|
||||
}
|
||||
|
||||
std::byte* data = reinterpret_cast<array*>(m_data)->flat;
|
||||
if (index < 0 || index >= m_type.value.array.size) throw std::out_of_range("index out of range");
|
||||
thing ref = { { thing_type::Ref, m_type.value.array.type }, m_allocator };
|
||||
ref.m_data = data + (index * elementSize);
|
||||
ref.m_data = m_data + (index * elementSize);
|
||||
return ref;
|
||||
}
|
||||
|
||||
thing_type::u64 length() const {
|
||||
if (!is(thing_type::Array)) throw bad_thing_access();
|
||||
return true_type().value.array.size == 0 ? get<array>().dynamic.size : true_type().value.array.size;
|
||||
return true_type().value.array.size == 0 ? get<dynamic_array>().size : true_type().value.array.size;
|
||||
}
|
||||
|
||||
template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
|
||||
@@ -529,29 +523,28 @@ public:
|
||||
throw std::runtime_error("unreachable");
|
||||
}
|
||||
private:
|
||||
static void copy_list(const thing_type& arrayType, array& dst, const array& src) {
|
||||
static void copy_list(const thing_type& arrayType, void* dst, const void* src) {
|
||||
if (arrayType.type != thing_type::Array || arrayType.value.array.type == nullptr)
|
||||
throw std::runtime_error("invalid type");
|
||||
|
||||
const auto& innerType = *arrayType.value.array.type;
|
||||
std::size_t elementSize = compute_size_na(innerType);
|
||||
|
||||
std::byte* data = nullptr;
|
||||
const std::byte* srcData = nullptr;
|
||||
std::size_t size = 0;
|
||||
std::size_t size = 0;
|
||||
if (arrayType.value.array.size == 0) {
|
||||
size = dst.dynamic.size = src.dynamic.size;
|
||||
if (dst.dynamic.size < 0) {
|
||||
dst.dynamic.data = nullptr;
|
||||
const dynamic_array& srcDynArr = *std::launder(reinterpret_cast<const dynamic_array*>(src));
|
||||
dynamic_array& dstDynArr = *std::launder(reinterpret_cast<dynamic_array*>(dst));
|
||||
|
||||
size = dstDynArr.size = srcDynArr.size;
|
||||
if (dstDynArr.size < 0) {
|
||||
dstDynArr.data = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
srcData = src.dynamic.data;
|
||||
data = dst.dynamic.data = new std::byte[dst.dynamic.size];
|
||||
src = srcDynArr.data;
|
||||
dst = dstDynArr.data = new std::byte[dstDynArr.size];
|
||||
} else {
|
||||
data = dst.flat;
|
||||
srcData = src.flat;
|
||||
size = arrayType.value.array.size;
|
||||
size = arrayType.value.array.size;
|
||||
}
|
||||
|
||||
switch (innerType.type) {
|
||||
@@ -564,12 +557,12 @@ private:
|
||||
case thing_type::U32:
|
||||
case thing_type::U64:
|
||||
case thing_type::Ptr:
|
||||
case thing_type::Ref: std::memcpy(dst.flat, src.flat, size); return;
|
||||
case thing_type::Ref: std::memcpy(dst, src, size * elementSize); return;
|
||||
case thing_type::Array:
|
||||
for (std::size_t i = 0; i < size; ++i) {
|
||||
copy_list(*innerType.value.array.type,
|
||||
*std::launder(reinterpret_cast<array*>(data + (i * elementSize))),
|
||||
*std::launder(reinterpret_cast<const array*>(srcData + (i * elementSize))));
|
||||
reinterpret_cast<std::byte*>(dst) + (i * elementSize),
|
||||
reinterpret_cast<const std::byte*>(src) + (i * elementSize));
|
||||
}
|
||||
return;
|
||||
case thing_type::Count: break;
|
||||
@@ -590,7 +583,7 @@ private:
|
||||
case thing_type::Ptr: return sizeof(void*);
|
||||
case thing_type::Ref: return compute_size_na(*type.value.typeRef);
|
||||
case thing_type::Array:
|
||||
return type.value.array.size == 0 ? sizeof(array)
|
||||
return type.value.array.size == 0 ? sizeof(dynamic_array)
|
||||
: compute_size_na(*type.value.array.type) * type.value.array.size;
|
||||
case thing_type::Count: break;
|
||||
}
|
||||
|
||||
+31
-32
@@ -30,18 +30,18 @@ thing_type executor::thing_type_impl(mod_h mod, mod_type type) const {
|
||||
case thing_type::U16:
|
||||
case thing_type::U32:
|
||||
case thing_type::U64: return { static_cast<enum thing_type::type>(type.type) };
|
||||
case thing_type::Ptr: return { thing_type::Ptr, thing_type(mod, *mod->type_at(type.value.typeRef)) };
|
||||
case thing_type::Ptr: return { thing_type::Ptr, mod_to_thing_type(mod, *mod->type_at(type.value.typeRef)) };
|
||||
case thing_type::Array: {
|
||||
return { static_cast<enum thing_type::type>(type.type),
|
||||
{ thing_type(mod, *mod->type_at(type.value.array.typeId)), type.value.array.size } };
|
||||
{ mod_to_thing_type(mod, *mod->type_at(type.value.array.typeId)), type.value.array.size } };
|
||||
}
|
||||
default: throw std::runtime_error("invalid thing type");
|
||||
}
|
||||
}
|
||||
|
||||
thing_type* executor::thing_type(const mod_h& mod, const mod_type& type) const {
|
||||
thing_type* executor::mod_to_thing_type(const mod_h& mod, const mod_type& type) const {
|
||||
struct thing_type thingType = thing_type_impl(mod, type);
|
||||
return m_context->thing_type_store().insert(thingType);
|
||||
return m_context->tt_store().insert(thingType);
|
||||
}
|
||||
|
||||
void executor::push_frame(const mod_h& mod, function function) {
|
||||
@@ -56,13 +56,13 @@ void executor::push_frame(const mod_h& mod, function function) {
|
||||
args.reserve(signature.params.size());
|
||||
for (const auto& param : signature.params) {
|
||||
auto arg = pop_thing();
|
||||
if (arg->type() != *thing_type(mod, *param)) throw std::runtime_error("function argument type mismatch");
|
||||
if (arg->type() != *mod_to_thing_type(mod, *param)) throw std::runtime_error("function argument type mismatch");
|
||||
args.push_back(std::move(arg));
|
||||
}
|
||||
|
||||
struct thing_type* returnType = nullptr;
|
||||
if (function.signature().returnType.has_value())
|
||||
returnType = thing_type(mod, *function.signature().returnType.value()); // NOLINT
|
||||
returnType = mod_to_thing_type(mod, *function.signature().returnType.value()); // NOLINT
|
||||
|
||||
switch (function.type()) {
|
||||
case function_t::Normal: {
|
||||
@@ -131,45 +131,45 @@ void executor::step() {
|
||||
|
||||
struct frame& frame = m_frames.top();
|
||||
|
||||
instruction_t instr = static_cast<instruction_t>((*frame.mod).byte(frame.position++));
|
||||
instruction_t instr = static_cast<instruction_t>((*frame.mod).byte_at(frame.position++));
|
||||
switch (instr) {
|
||||
case instruction_t::NoOperation: break;
|
||||
case instruction_t::PushS8: {
|
||||
push_thing({ (struct thing_type){ thing_type::S8 }, m_context->thing_alloc() })->get<thing_type::s8>() =
|
||||
static_cast<thing_type::s8>(frame.mod->byte(frame.position++));
|
||||
static_cast<thing_type::s8>(frame.mod->byte_at(frame.position++));
|
||||
} break;
|
||||
case instruction_t::PushU8: {
|
||||
push_thing({ (struct thing_type){ thing_type::U8 }, m_context->thing_alloc() })->get<thing_type::u8>() =
|
||||
static_cast<thing_type::u8>(frame.mod->byte(frame.position++));
|
||||
static_cast<thing_type::u8>(frame.mod->byte_at(frame.position++));
|
||||
} break;
|
||||
case instruction_t::PushS16: {
|
||||
thing_type::u16 value = frame.mod->byte(frame.position++);
|
||||
value |= static_cast<thing_type::u16>(frame.mod->byte(frame.position++) << 8);
|
||||
thing_type::u16 value = frame.mod->byte_at(frame.position++);
|
||||
value |= static_cast<thing_type::u16>(frame.mod->byte_at(frame.position++) << 8);
|
||||
push_thing({ (struct thing_type){ thing_type::S16 }, m_context->thing_alloc() })->get<thing_type::s16>() =
|
||||
static_cast<thing_type::s16>(value);
|
||||
} break;
|
||||
case instruction_t::PushU16: {
|
||||
thing_type::u16 value = frame.mod->byte(frame.position++);
|
||||
value |= static_cast<thing_type::u16>(frame.mod->byte(frame.position++) << 8);
|
||||
thing_type::u16 value = frame.mod->byte_at(frame.position++);
|
||||
value |= static_cast<thing_type::u16>(frame.mod->byte_at(frame.position++) << 8);
|
||||
push_thing({ (struct thing_type){ thing_type::U16 }, m_context->thing_alloc() })->get<thing_type::u16>() =
|
||||
value;
|
||||
} break;
|
||||
case instruction_t::PushS32: {
|
||||
push_thing({ (struct thing_type){ thing_type::S32 }, m_context->thing_alloc() })->get<thing_type::s32>() =
|
||||
static_cast<thing_type::s32>(frame.mod->byte(frame.position++));
|
||||
static_cast<thing_type::s32>(frame.mod->byte_at(frame.position++));
|
||||
} break;
|
||||
case instruction_t::PushU32: {
|
||||
push_thing({ (struct thing_type){ thing_type::U32 }, m_context->thing_alloc() })->get<thing_type::u32>() =
|
||||
static_cast<thing_type::u32>(frame.mod->byte(frame.position++));
|
||||
static_cast<thing_type::u32>(frame.mod->byte_at(frame.position++));
|
||||
} break;
|
||||
case instruction_t::Array: {
|
||||
mod_type_id typeId = static_cast<mod_type_id>(frame.mod->byte(frame.position)) |
|
||||
(static_cast<mod_type_id>(frame.mod->byte(frame.position + 1)) << 8) |
|
||||
(static_cast<mod_type_id>(frame.mod->byte(frame.position + 2)) << 16) |
|
||||
(static_cast<mod_type_id>(frame.mod->byte(frame.position + 3)) << 24);
|
||||
mod_type_id typeId = static_cast<mod_type_id>(frame.mod->byte_at(frame.position)) |
|
||||
(static_cast<mod_type_id>(frame.mod->byte_at(frame.position + 1)) << 8) |
|
||||
(static_cast<mod_type_id>(frame.mod->byte_at(frame.position + 2)) << 16) |
|
||||
(static_cast<mod_type_id>(frame.mod->byte_at(frame.position + 3)) << 24);
|
||||
frame.position += 4;
|
||||
|
||||
const auto& type = *thing_type(frame.mod, *frame.mod->type_at(typeId));
|
||||
const auto& type = *mod_to_thing_type(frame.mod, *frame.mod->type_at(typeId));
|
||||
if (type.type != thing_type::Array || type.value.array.type == nullptr || type.value.array.type == &type)
|
||||
throw std::runtime_error("invalid array type");
|
||||
|
||||
@@ -209,7 +209,7 @@ void executor::step() {
|
||||
} break;
|
||||
case instruction_t::Reference: {
|
||||
auto thing = pop_thing();
|
||||
push_thing({ (struct thing_type){ thing_type::Ref, m_context->thing_type_store().insert(thing->type()) },
|
||||
push_thing({ (struct thing_type){ thing_type::Ref, m_context->tt_store().insert(thing->type()) },
|
||||
m_context->thing_alloc() })
|
||||
->reference(*thing);
|
||||
} break;
|
||||
@@ -270,9 +270,8 @@ void executor::step() {
|
||||
} break;
|
||||
case instruction_t::Pointerof: {
|
||||
auto thing = pop_thing();
|
||||
auto ptr =
|
||||
push_thing({ (struct thing_type){ thing_type::Ptr, m_context->thing_type_store().at(thing->type().id) },
|
||||
m_context->thing_alloc() });
|
||||
auto ptr = push_thing({ (struct thing_type){ thing_type::Ptr, m_context->tt_store().at(thing->type().id) },
|
||||
m_context->thing_alloc() });
|
||||
ptr->get<void*>() = thing->raw();
|
||||
} break;
|
||||
case instruction_t::Sizeof: {
|
||||
@@ -305,29 +304,29 @@ void executor::step() {
|
||||
length->get<thing_type::u64>() = thing->length();
|
||||
} break;
|
||||
case instruction_t::Load: {
|
||||
variable_t variable = static_cast<std::uint16_t>(frame.mod->byte(frame.position)) |
|
||||
(static_cast<std::uint16_t>(frame.mod->byte(frame.position + 1)) << 8);
|
||||
variable_t variable = static_cast<std::uint16_t>(frame.mod->byte_at(frame.position)) |
|
||||
(static_cast<std::uint16_t>(frame.mod->byte_at(frame.position + 1)) << 8);
|
||||
frame.position += 2;
|
||||
push_thing(load_thing(variable));
|
||||
} break;
|
||||
case instruction_t::Store: {
|
||||
variable_t variable = static_cast<std::uint16_t>(frame.mod->byte(frame.position)) |
|
||||
(static_cast<std::uint16_t>(frame.mod->byte(frame.position + 1)) << 8);
|
||||
variable_t variable = static_cast<std::uint16_t>(frame.mod->byte_at(frame.position)) |
|
||||
(static_cast<std::uint16_t>(frame.mod->byte_at(frame.position + 1)) << 8);
|
||||
frame.position += 2;
|
||||
store_thing(variable, std::move(pop_thing()));
|
||||
} break;
|
||||
case instruction_t::Call: {
|
||||
function_id funcId = static_cast<std::uint16_t>(frame.mod->byte(frame.position)) |
|
||||
(static_cast<std::uint16_t>(frame.mod->byte(frame.position + 1)) << 8);
|
||||
function_id funcId = static_cast<std::uint16_t>(frame.mod->byte_at(frame.position)) |
|
||||
(static_cast<std::uint16_t>(frame.mod->byte_at(frame.position + 1)) << 8);
|
||||
frame.position += 2;
|
||||
push_frame(frame.mod, *frame.mod->function_at(funcId));
|
||||
} break;
|
||||
case instruction_t::Jump: {
|
||||
std::int8_t offset = static_cast<std::int8_t>(frame.mod->byte(frame.position++));
|
||||
std::int8_t offset = static_cast<std::int8_t>(frame.mod->byte_at(frame.position++));
|
||||
frame.position += offset;
|
||||
} break;
|
||||
case instruction_t::JumpNotZero: {
|
||||
byte offset = frame.mod->byte(frame.position++);
|
||||
byte offset = frame.mod->byte_at(frame.position++);
|
||||
auto cond = pop_thing();
|
||||
if (cond->integer() != 0) frame.position += (std::int8_t)offset;
|
||||
} break;
|
||||
|
||||
Reference in New Issue
Block a user