feat(furvm): add variables

This commit is contained in:
2026-06-14 14:22:45 +02:00
parent f0fe6b4179
commit f6f716e8c9
4 changed files with 86 additions and 3 deletions
+28 -1
View File
@@ -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.
@@ -155,4 +182,4 @@ private:
} // namespace furvm } // namespace furvm
#endif // FURVM_EXECUTOR_HPP #endif // FURVM_EXECUTOR_HPP
+6 -1
View File
@@ -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.
@@ -181,4 +186,4 @@ class stack_underflow;
} // namespace furvm } // namespace furvm
#endif // FURVM_FWD_HPP #endif // FURVM_FWD_HPP
+15 -1
View File
@@ -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.
* *
@@ -96,4 +110,4 @@ struct instruction {
} // namespace furvm } // namespace furvm
#endif // FURVM_INSTRUCTION_HPP #endif // FURVM_INSTRUCTION_HPP
+37
View File
@@ -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);