@@ -120,6 +120,13 @@ public:
|
|||||||
*/
|
*/
|
||||||
void push_thing(const thing_p& thing);
|
void push_thing(const thing_p& thing);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Pushes a thing onto the stack.
|
||||||
|
*
|
||||||
|
* @param thing The thing to push.
|
||||||
|
*/
|
||||||
|
void push_thing(thing_p&& thing);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Pops a thing from the stack.
|
* @brief Pops a thing from the stack.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -35,6 +35,11 @@ enum class instruction_t : byte {
|
|||||||
*/
|
*/
|
||||||
Duplicate,
|
Duplicate,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Clones top element on the stack.
|
||||||
|
*/
|
||||||
|
Clone,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Pops the current call frame.
|
* @brief Pops the current call frame.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#ifndef FURVM_THING_HPP
|
#ifndef FURVM_THING_HPP
|
||||||
#define FURVM_THING_HPP
|
#define FURVM_THING_HPP
|
||||||
|
|
||||||
|
#include "furvm/context.hpp" // IWYU pragma: keep
|
||||||
#include "furvm/fwd.hpp"
|
#include "furvm/fwd.hpp"
|
||||||
|
|
||||||
namespace furvm {
|
namespace furvm {
|
||||||
@@ -80,12 +81,12 @@ public:
|
|||||||
/**
|
/**
|
||||||
* @brief Move constructor.
|
* @brief Move constructor.
|
||||||
*/
|
*/
|
||||||
thing(thing&&) noexcept = default;
|
thing(thing&&) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Move constructor.
|
* @brief Move constructor.
|
||||||
*/
|
*/
|
||||||
thing& operator=(thing&&) noexcept = default;
|
thing& operator=(thing&&) noexcept;
|
||||||
|
|
||||||
thing(const thing&) = delete;
|
thing(const thing&) = delete;
|
||||||
thing& operator=(const thing&) = delete;
|
thing& operator=(const thing&) = delete;
|
||||||
@@ -94,10 +95,32 @@ public:
|
|||||||
* @brief Returns a new thing.
|
* @brief Returns a new thing.
|
||||||
*
|
*
|
||||||
* @param context Furvm context.
|
* @param context Furvm context.
|
||||||
* @param type Type of the new thing.
|
* @param args Arguments to forward to the thing constructor.
|
||||||
* @return Shared pointer to the new thing.
|
* @return Shared pointer to the new thing.
|
||||||
*/
|
*/
|
||||||
static thing_p create(const context_p& context, thing_t type);
|
template <typename... Args,
|
||||||
|
typename = std::enable_if_t<std::is_constructible_v<thing, rzecz, thing_handle, Args..., const context_p&>>>
|
||||||
|
static thing_p create(const context_p& context, Args&&... args) {
|
||||||
|
thing_handle id = context->m_things.size();
|
||||||
|
if (!context->m_deadThings.empty()) {
|
||||||
|
id = context->m_deadThings.front();
|
||||||
|
context->m_deadThings.pop();
|
||||||
|
id += 1 << GENERATION_SIZE;
|
||||||
|
}
|
||||||
|
thing_handle idx = id & ((1ULL << ((sizeof(id) * 8) - GENERATION_SIZE)) - 1);
|
||||||
|
|
||||||
|
auto th = std::make_shared<thing>(rzecz{}, id, std::forward<Args>(args)..., context);
|
||||||
|
context->m_things.emplace(context->m_things.begin() + idx, th);
|
||||||
|
return std::move(th);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns a clone of the thing.
|
||||||
|
*
|
||||||
|
* @param thing Thing to clone.
|
||||||
|
* @return Shared pointer to a clone of the thing.
|
||||||
|
*/
|
||||||
|
static thing_p clone(const thing_p& thing);
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Returns an int32 value from this thing.
|
* @brief Returns an int32 value from this thing.
|
||||||
|
|||||||
@@ -42,6 +42,11 @@ void executor::push_thing(const thing_p& thing) {
|
|||||||
m_stack.push(thing);
|
m_stack.push(thing);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void executor::push_thing(thing_p&& thing) {
|
||||||
|
thing->add_reference();
|
||||||
|
m_stack.push(std::move(thing));
|
||||||
|
}
|
||||||
|
|
||||||
thing_p executor::pop_thing() {
|
thing_p executor::pop_thing() {
|
||||||
if (m_frames.top().stackBase >= m_stack.size()) throw stack_underflow();
|
if (m_frames.top().stackBase >= m_stack.size()) throw stack_underflow();
|
||||||
thing_p top = std::move(m_stack.top());
|
thing_p top = std::move(m_stack.top());
|
||||||
@@ -66,7 +71,7 @@ void executor::step() {
|
|||||||
case instruction_t::PushB2I: {
|
case instruction_t::PushB2I: {
|
||||||
auto thing = thing::create(m_context, thing_t::Int32);
|
auto thing = thing::create(m_context, thing_t::Int32);
|
||||||
thing->int32() = frame.mod->byte(frame.position++);
|
thing->int32() = frame.mod->byte(frame.position++);
|
||||||
m_stack.push(std::move(thing));
|
push_thing(std::move(thing));
|
||||||
} break;
|
} break;
|
||||||
case instruction_t::Drop: {
|
case instruction_t::Drop: {
|
||||||
pop_thing();
|
pop_thing();
|
||||||
@@ -75,7 +80,7 @@ void executor::step() {
|
|||||||
push_thing(thing());
|
push_thing(thing());
|
||||||
} break;
|
} break;
|
||||||
case instruction_t::Clone: {
|
case instruction_t::Clone: {
|
||||||
push_thing(thing::clone(thing()));
|
push_thing(std::move(thing::clone(thing())));
|
||||||
} break;
|
} break;
|
||||||
case instruction_t::Return: {
|
case instruction_t::Return: {
|
||||||
pop_frame();
|
pop_frame();
|
||||||
@@ -84,7 +89,7 @@ void executor::step() {
|
|||||||
case instruction_t::ReturnValue: {
|
case instruction_t::ReturnValue: {
|
||||||
auto value = pop_thing();
|
auto value = pop_thing();
|
||||||
pop_frame();
|
pop_frame();
|
||||||
m_stack.push(std::move(value));
|
push_thing(std::move(value));
|
||||||
} break;
|
} break;
|
||||||
case instruction_t::PushConstant: throw std::runtime_error("unimplemented");
|
case instruction_t::PushConstant: throw std::runtime_error("unimplemented");
|
||||||
default: throw std::runtime_error("unknown instruction");
|
default: throw std::runtime_error("unknown instruction");
|
||||||
|
|||||||
+3
-1
@@ -8,9 +8,11 @@
|
|||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
static constexpr std::array<furvm::byte, 4> s_bytecode = {
|
static constexpr std::array<furvm::byte, 6> s_bytecode = {
|
||||||
furvm::byte(furvm::instruction_t::PushB2I),
|
furvm::byte(furvm::instruction_t::PushB2I),
|
||||||
67,
|
67,
|
||||||
|
furvm::byte(furvm::instruction_t::Clone),
|
||||||
|
furvm::byte(furvm::instruction_t::Drop),
|
||||||
furvm::byte(furvm::instruction_t::Drop),
|
furvm::byte(furvm::instruction_t::Drop),
|
||||||
furvm::byte(furvm::instruction_t::Return),
|
furvm::byte(furvm::instruction_t::Return),
|
||||||
};
|
};
|
||||||
|
|||||||
+41
-7
@@ -55,17 +55,51 @@ thing::~thing() {
|
|||||||
m_context->m_deadThingData.push_back(m_data);
|
m_context->m_deadThingData.push_back(m_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
thing_p thing::create(const context_p& context, thing_t type) {
|
thing::thing(thing&& other) noexcept
|
||||||
thing_handle id = context->m_things.size();
|
: m_id(other.m_id),
|
||||||
if (!context->m_deadThings.empty()) {
|
m_type(other.m_type),
|
||||||
id = context->m_deadThings.front();
|
m_context(std::move(other.m_context)),
|
||||||
context->m_deadThings.pop();
|
m_refCount(other.m_refCount),
|
||||||
|
m_data(other.m_data) {
|
||||||
|
other.m_id = {};
|
||||||
|
other.m_type = {};
|
||||||
|
other.m_refCount = {};
|
||||||
|
other.m_data = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
thing& thing::operator=(thing&& other) noexcept {
|
||||||
|
if (this == &other) return *this;
|
||||||
|
m_id = other.m_id;
|
||||||
|
m_type = other.m_type;
|
||||||
|
m_context = std::move(other.m_context);
|
||||||
|
m_refCount = other.m_refCount;
|
||||||
|
m_data = other.m_data;
|
||||||
|
|
||||||
|
other.m_id = {};
|
||||||
|
other.m_type = {};
|
||||||
|
other.m_refCount = {};
|
||||||
|
other.m_data = nullptr;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
thing_p thing::clone(const thing_p& thing) {
|
||||||
|
thing_handle id = thing->m_context->m_things.size();
|
||||||
|
if (!thing->m_context->m_deadThings.empty()) {
|
||||||
|
id = thing->m_context->m_deadThings.front();
|
||||||
|
thing->m_context->m_deadThings.pop();
|
||||||
id += 1 << GENERATION_SIZE;
|
id += 1 << GENERATION_SIZE;
|
||||||
}
|
}
|
||||||
thing_handle idx = id & ((1ULL << ((sizeof(id) * 8) - GENERATION_SIZE)) - 1);
|
thing_handle idx = id & ((1ULL << ((sizeof(id) * 8) - GENERATION_SIZE)) - 1);
|
||||||
|
|
||||||
auto th = std::make_shared<thing>(rzecz{}, id, type, context);
|
auto th = std::make_shared<class thing>(rzecz{}, id, thing->m_type, thing->m_context);
|
||||||
context->m_things.emplace(context->m_things.begin() + idx, th);
|
switch (thing->m_type) {
|
||||||
|
// Primitives
|
||||||
|
default: {
|
||||||
|
memcpy(th->m_data, thing->m_data, thing_type_size(thing->m_type));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
thing->m_context->m_things.emplace(thing->m_context->m_things.begin() + idx, th);
|
||||||
return std::move(th);
|
return std::move(th);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user