@@ -3,7 +3,8 @@
|
||||
|
||||
#include "furvm/fwd.hpp"
|
||||
#include "furvm/module.hpp" // IWYU pragma: keep
|
||||
#include "furvm/thing.hpp" // IWYU pragma: keep
|
||||
#include "furvm/stack.hpp"
|
||||
#include "furvm/thing.hpp" // IWYU pragma: keep
|
||||
|
||||
#include <functional>
|
||||
#include <stack>
|
||||
@@ -39,6 +40,8 @@ public:
|
||||
static constexpr executor_flags STATE_FLAGS = executor_flags::JustHit;
|
||||
|
||||
using new_frame_callback = std::function<void(executor&)>;
|
||||
|
||||
using stack_thing = thing<stack_allocator>;
|
||||
public:
|
||||
/**
|
||||
* @brief Executor frame.
|
||||
@@ -50,8 +53,8 @@ public:
|
||||
std::size_t position; /**< Cursor to a current instruction in the bytecode. */
|
||||
std::size_t stackBase; /**< Snapshot of the stack size before this frame. */
|
||||
|
||||
thing_type* returnType; /**< Return type. */
|
||||
std::vector<thing<>> variables; /**< Frame variables. */
|
||||
thing_type* returnType; /**< Return type. */
|
||||
std::vector<stack_thing> variables; /**< Frame variables. */
|
||||
};
|
||||
public:
|
||||
~executor() = default;
|
||||
@@ -131,27 +134,27 @@ public:
|
||||
* @param thing Thing.
|
||||
* @return The pushed handle.
|
||||
*/
|
||||
thing<>& push_thing(thing<>&& thing);
|
||||
stack_thing& push_thing(stack_thing&& thing);
|
||||
|
||||
thing<>& push_thing(const thing<>& thing);
|
||||
stack_thing& push_thing(const stack_thing& thing);
|
||||
|
||||
/**
|
||||
* @brief Pops a thing from the stack.
|
||||
*
|
||||
* @return A handle to the popped thing.
|
||||
*/
|
||||
thing<> pop_thing();
|
||||
stack_thing pop_thing();
|
||||
|
||||
/**
|
||||
* @brief Returns the top thing on the stack.
|
||||
*
|
||||
* @return A handle to the top thing.
|
||||
*/
|
||||
thing<>& top_thing();
|
||||
stack_thing& top_thing();
|
||||
|
||||
const thing<>& top_thing() const;
|
||||
const stack_thing& top_thing() const;
|
||||
|
||||
const std::vector<thing<>>& stack() const { return m_stack; }
|
||||
const std::vector<stack_thing>& stack() const { return m_stack; }
|
||||
public:
|
||||
/**
|
||||
* @brief Stores a thing in a frame variable.
|
||||
@@ -159,7 +162,7 @@ public:
|
||||
* @param variable Id of the variable in which the handle will be put.
|
||||
* @param thing Thing handle.
|
||||
*/
|
||||
void store_thing(variable_t variable, const thing<>& thing);
|
||||
void store_thing(variable_t variable, const stack_thing& thing);
|
||||
|
||||
/**
|
||||
* @brief Stores a thing in a frame variable.
|
||||
@@ -167,7 +170,7 @@ public:
|
||||
* @param variable Id of the variable in which the handle will be put.
|
||||
* @param thing Thing handle.
|
||||
*/
|
||||
void store_thing(variable_t variable, thing<>&& thing);
|
||||
void store_thing(variable_t variable, stack_thing&& thing);
|
||||
|
||||
/**
|
||||
* @brief Returns a thing stored in a variable.
|
||||
@@ -175,9 +178,9 @@ public:
|
||||
* @param variable Id of the variable from which the handle will be fetched.
|
||||
* @return A handle stored in the variable.
|
||||
*/
|
||||
thing<>& load_thing(variable_t variable);
|
||||
stack_thing& load_thing(variable_t variable);
|
||||
|
||||
const thing<>& load_thing(variable_t variable) const;
|
||||
const stack_thing& load_thing(variable_t variable) const;
|
||||
public:
|
||||
/**
|
||||
* @brief Executes next instruction.
|
||||
@@ -190,11 +193,12 @@ private:
|
||||
private:
|
||||
static bool compare_thing_types(const thing_type& lhs, const thing_type& rhs);
|
||||
private:
|
||||
executor_flags m_flags = executor_flags::Done;
|
||||
context* m_context;
|
||||
executor_flags m_flags = executor_flags::Done;
|
||||
context* m_context;
|
||||
furvm::stack<std::byte> m_stackStorage;
|
||||
|
||||
std::stack<frame> m_frames;
|
||||
std::vector<thing<>> m_stack;
|
||||
std::stack<frame> m_frames;
|
||||
std::vector<stack_thing> m_stack;
|
||||
|
||||
new_frame_callback m_newFrameCb = nullptr;
|
||||
};
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#ifndef FURVM_FUNCTION_HPP
|
||||
#define FURVM_FUNCTION_HPP
|
||||
|
||||
#include "furlang/utility/hash.hpp"
|
||||
#include "furvm/fwd.hpp"
|
||||
#include "furvm/handle.hpp" // IWYU pragma: keep
|
||||
|
||||
|
||||
@@ -194,6 +194,9 @@ private:
|
||||
template <template <typename> typename Allocator>
|
||||
class thing final {
|
||||
friend class executor;
|
||||
|
||||
template <template <typename> class Other>
|
||||
friend class thing;
|
||||
public:
|
||||
using allocator_type = Allocator<std::byte>; /**< Allocator type. */
|
||||
public:
|
||||
@@ -206,7 +209,8 @@ public:
|
||||
thing_type type;
|
||||
};
|
||||
public:
|
||||
thing() {}
|
||||
thing(const allocator_type& allocator = {})
|
||||
: m_allocator(allocator) {}
|
||||
|
||||
/**
|
||||
* @brief Constructs a thing.
|
||||
@@ -230,15 +234,15 @@ public:
|
||||
*
|
||||
* TODO: Reword the note above.
|
||||
*/
|
||||
static thing make_reference(const thing& owner) {
|
||||
thing ref;
|
||||
template <template <typename> class Other = Allocator>
|
||||
static thing make_reference(const thing<Other>& owner, const allocator_type& allocator = {}) {
|
||||
thing ref = { allocator };
|
||||
ref.m_reference = true;
|
||||
ref.m_data = owner.m_data;
|
||||
ref.m_type = owner.m_type;
|
||||
ref.m_size = owner.m_size;
|
||||
return ref;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Destructs a thing.
|
||||
*/
|
||||
@@ -247,7 +251,16 @@ public:
|
||||
/**
|
||||
* @brief Move constructor.
|
||||
*/
|
||||
thing(thing&& other) noexcept { *this = std::move(other); }
|
||||
thing(thing&& other) noexcept
|
||||
: m_reference(other.m_reference),
|
||||
m_type(other.m_type),
|
||||
m_size(other.m_size),
|
||||
m_data(other.m_data),
|
||||
m_allocator(other.m_allocator) {
|
||||
other.m_type = nullptr;
|
||||
other.m_data = nullptr;
|
||||
other.m_size = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Move constructor.
|
||||
@@ -266,7 +279,16 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
thing(const thing& other) { *this = other; }
|
||||
thing(const thing& other)
|
||||
: m_reference(other.m_reference), m_size(other.m_size), m_allocator(other.m_allocator) {
|
||||
if (m_reference) {
|
||||
m_type = other.m_type;
|
||||
m_data = other.m_data;
|
||||
return;
|
||||
}
|
||||
allocate(other.type());
|
||||
other.copy(*this);
|
||||
}
|
||||
|
||||
thing& operator=(const thing& other) {
|
||||
if (this == &other) return *this;
|
||||
@@ -275,7 +297,38 @@ public:
|
||||
|
||||
m_reference = other.m_reference;
|
||||
m_size = other.m_size;
|
||||
m_allocator = other.m_allocator;
|
||||
|
||||
if (m_reference) {
|
||||
m_type = other.m_type;
|
||||
m_data = other.m_data;
|
||||
return *this;
|
||||
}
|
||||
allocate(other.type());
|
||||
other.copy(*this);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <template <typename> class Other>
|
||||
thing(const thing<Other>& other)
|
||||
: m_reference(other.m_reference), m_size(other.m_size) {
|
||||
if (m_reference) {
|
||||
m_type = other.m_type;
|
||||
m_data = other.m_data;
|
||||
return;
|
||||
}
|
||||
allocate(other.type());
|
||||
other.copy(*this);
|
||||
}
|
||||
|
||||
template <template <typename> class Other>
|
||||
thing& operator=(const thing<Other>& other) {
|
||||
if (this == &other) return *this;
|
||||
|
||||
free();
|
||||
|
||||
m_reference = other.m_reference;
|
||||
m_size = other.m_size;
|
||||
|
||||
if (m_reference) {
|
||||
m_type = other.m_type;
|
||||
@@ -299,7 +352,8 @@ public:
|
||||
return res;
|
||||
}
|
||||
private:
|
||||
void copy(thing<>& dst) const {
|
||||
template <template <typename> class Other>
|
||||
void copy(thing<Other>& dst) const {
|
||||
switch (m_type->type) {
|
||||
case thing_type::S8:
|
||||
case thing_type::S16:
|
||||
@@ -499,7 +553,7 @@ public:
|
||||
thing at(thing_type::u64 index) const {
|
||||
if (!is(thing_type::Array)) throw bad_thing_access();
|
||||
|
||||
thing ref = {};
|
||||
thing ref = { m_allocator };
|
||||
ref.m_reference = true;
|
||||
ref.m_size = compute_size_na(*type().value.array.type);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user