feat(furvm): add variables
This commit is contained in:
@@ -4,6 +4,7 @@
|
|||||||
#include "furvm/fwd.hpp"
|
#include "furvm/fwd.hpp"
|
||||||
|
|
||||||
#include <stack>
|
#include <stack>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace furvm {
|
namespace furvm {
|
||||||
|
|
||||||
@@ -44,6 +45,8 @@ public:
|
|||||||
mod_p mod; /**< Shared pointer to a module with the bytecode. */
|
mod_p mod; /**< Shared pointer to a module with the bytecode. */
|
||||||
std::size_t position; /**< Cursor to a current instruction in the bytecode. */
|
std::size_t position; /**< Cursor to a current instruction in the bytecode. */
|
||||||
std::size_t stackBase; /**< Snapshot of the stack size before this frame. */
|
std::size_t stackBase; /**< Snapshot of the stack size before this frame. */
|
||||||
|
|
||||||
|
std::vector<thing_p> variables; /**< Frame variables. */
|
||||||
};
|
};
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
@@ -139,6 +142,30 @@ public:
|
|||||||
* @return The thing.
|
* @return The thing.
|
||||||
*/
|
*/
|
||||||
thing_p thing() const;
|
thing_p thing() const;
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Stores a thing in a variable.
|
||||||
|
*
|
||||||
|
* @param variable Variable to store the thing in.
|
||||||
|
* @param thing Thing to store.
|
||||||
|
*/
|
||||||
|
void store_thing(variable_t variable, const thing_p& thing);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Stores a thing in a variable.
|
||||||
|
*
|
||||||
|
* @param variable Variable to store the thing in.
|
||||||
|
* @param thing Thing to store.
|
||||||
|
*/
|
||||||
|
void store_thing(variable_t variable, thing_p&& thing);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns a thing stored in a variable.
|
||||||
|
*
|
||||||
|
* @param variable Variable where the thing is stored.
|
||||||
|
* @return The thing stored in the variable.
|
||||||
|
*/
|
||||||
|
thing_p load_thing(variable_t variable) const;
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Executes next instruction.
|
* @brief Executes next instruction.
|
||||||
|
|||||||
@@ -132,6 +132,11 @@ using thing_handle = std::uint32_t;
|
|||||||
|
|
||||||
// executor.hpp
|
// executor.hpp
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A variable index type.
|
||||||
|
*/
|
||||||
|
using variable_t = std::uint16_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @enum executor_flags
|
* @enum executor_flags
|
||||||
* @brief Flags of an executor.
|
* @brief Flags of an executor.
|
||||||
|
|||||||
@@ -65,6 +65,20 @@ enum class instruction_t : byte {
|
|||||||
*/
|
*/
|
||||||
Mod,
|
Mod,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Pushes a variable onto the stack.
|
||||||
|
*
|
||||||
|
* Fetches a variable denoted by next two bytes in little-endian and pushes it onto the stack.
|
||||||
|
*/
|
||||||
|
Load,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Stores an element from the stack in a variable.
|
||||||
|
*
|
||||||
|
* Pops a thing from the stack and stores it in a variable denoted by next two bytes in little-endian.
|
||||||
|
*/
|
||||||
|
Store,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Calls a function.
|
* @brief Calls a function.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -3,9 +3,11 @@
|
|||||||
#include "furvm/context.hpp" // IWYU pragma: keep
|
#include "furvm/context.hpp" // IWYU pragma: keep
|
||||||
#include "furvm/exceptions.hpp"
|
#include "furvm/exceptions.hpp"
|
||||||
#include "furvm/function.hpp" // IWYU pragma: keep
|
#include "furvm/function.hpp" // IWYU pragma: keep
|
||||||
|
#include "furvm/fwd.hpp"
|
||||||
#include "furvm/instruction.hpp"
|
#include "furvm/instruction.hpp"
|
||||||
#include "furvm/thing.hpp"
|
#include "furvm/thing.hpp"
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
namespace furvm {
|
namespace furvm {
|
||||||
@@ -62,6 +64,31 @@ thing_p executor::thing() const {
|
|||||||
return m_stack.top();
|
return m_stack.top();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void executor::store_thing(variable_t variable, const thing_p& thing) {
|
||||||
|
auto& frame = m_frames.top();
|
||||||
|
frame.variables.resize(variable + 1);
|
||||||
|
if (frame.variables[variable] != nullptr) {
|
||||||
|
frame.variables[variable]->remove_reference();
|
||||||
|
}
|
||||||
|
frame.variables[variable] = thing;
|
||||||
|
thing->add_reference();
|
||||||
|
}
|
||||||
|
|
||||||
|
void executor::store_thing(variable_t variable, thing_p&& thing) {
|
||||||
|
auto& frame = m_frames.top();
|
||||||
|
frame.variables.resize(variable + 1);
|
||||||
|
if (frame.variables[variable] != nullptr) {
|
||||||
|
frame.variables[variable]->remove_reference();
|
||||||
|
}
|
||||||
|
thing->add_reference();
|
||||||
|
frame.variables[variable] = std::move(thing);
|
||||||
|
}
|
||||||
|
|
||||||
|
thing_p executor::load_thing(variable_t variable) const {
|
||||||
|
const auto& frame = m_frames.top();
|
||||||
|
return frame.variables[variable];
|
||||||
|
}
|
||||||
|
|
||||||
void executor::step() {
|
void executor::step() {
|
||||||
if ((m_flags & executor_flags::Suspended) == executor_flags::Suspended) return;
|
if ((m_flags & executor_flags::Suspended) == executor_flags::Suspended) return;
|
||||||
|
|
||||||
@@ -109,6 +136,16 @@ void executor::step() {
|
|||||||
auto lhs = pop_thing();
|
auto lhs = pop_thing();
|
||||||
push_thing(lhs % rhs);
|
push_thing(lhs % rhs);
|
||||||
} break;
|
} 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);
|
||||||
|
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);
|
||||||
|
store_thing(variable, std::move(pop_thing()));
|
||||||
|
} break;
|
||||||
case instruction_t::Call: {
|
case instruction_t::Call: {
|
||||||
function_handle funcId = static_cast<std::uint16_t>(frame.mod->byte(frame.position)) |
|
function_handle funcId = static_cast<std::uint16_t>(frame.mod->byte(frame.position)) |
|
||||||
(static_cast<std::uint16_t>(frame.mod->byte(frame.position + 1)) << 8);
|
(static_cast<std::uint16_t>(frame.mod->byte(frame.position + 1)) << 8);
|
||||||
|
|||||||
Reference in New Issue
Block a user