From f6f716e8c98b786f12076b41a6fe6ee053ace899 Mon Sep 17 00:00:00 2001 From: CHatingPython Date: Sun, 14 Jun 2026 14:22:45 +0200 Subject: [PATCH] feat(furvm): add variables --- furvm/include/furvm/executor.hpp | 29 +++++++++++++++++++++- furvm/include/furvm/fwd.hpp | 7 +++++- furvm/include/furvm/instruction.hpp | 16 ++++++++++++- furvm/src/executor.cpp | 37 +++++++++++++++++++++++++++++ 4 files changed, 86 insertions(+), 3 deletions(-) diff --git a/furvm/include/furvm/executor.hpp b/furvm/include/furvm/executor.hpp index 15f6af1..a2c264c 100644 --- a/furvm/include/furvm/executor.hpp +++ b/furvm/include/furvm/executor.hpp @@ -4,6 +4,7 @@ #include "furvm/fwd.hpp" #include +#include namespace furvm { @@ -44,6 +45,8 @@ public: 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 stackBase; /**< Snapshot of the stack size before this frame. */ + + std::vector variables; /**< Frame variables. */ }; public: /** @@ -139,6 +142,30 @@ public: * @return The thing. */ 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: /** * @brief Executes next instruction. @@ -155,4 +182,4 @@ private: } // namespace furvm -#endif // FURVM_EXECUTOR_HPP \ No newline at end of file +#endif // FURVM_EXECUTOR_HPP diff --git a/furvm/include/furvm/fwd.hpp b/furvm/include/furvm/fwd.hpp index c7bb8ff..aaa832a 100644 --- a/furvm/include/furvm/fwd.hpp +++ b/furvm/include/furvm/fwd.hpp @@ -132,6 +132,11 @@ using thing_handle = std::uint32_t; // executor.hpp +/** + * @brief A variable index type. + */ +using variable_t = std::uint16_t; + /** * @enum executor_flags * @brief Flags of an executor. @@ -181,4 +186,4 @@ class stack_underflow; } // namespace furvm -#endif // FURVM_FWD_HPP \ No newline at end of file +#endif // FURVM_FWD_HPP diff --git a/furvm/include/furvm/instruction.hpp b/furvm/include/furvm/instruction.hpp index 5ec3714..2a73ea7 100644 --- a/furvm/include/furvm/instruction.hpp +++ b/furvm/include/furvm/instruction.hpp @@ -65,6 +65,20 @@ enum class instruction_t : byte { */ 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. * @@ -96,4 +110,4 @@ struct instruction { } // namespace furvm -#endif // FURVM_INSTRUCTION_HPP \ No newline at end of file +#endif // FURVM_INSTRUCTION_HPP diff --git a/furvm/src/executor.cpp b/furvm/src/executor.cpp index 4a6cb78..e4b5f28 100644 --- a/furvm/src/executor.cpp +++ b/furvm/src/executor.cpp @@ -3,9 +3,11 @@ #include "furvm/context.hpp" // IWYU pragma: keep #include "furvm/exceptions.hpp" #include "furvm/function.hpp" // IWYU pragma: keep +#include "furvm/fwd.hpp" #include "furvm/instruction.hpp" #include "furvm/thing.hpp" +#include #include namespace furvm { @@ -62,6 +64,31 @@ thing_p executor::thing() const { 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() { if ((m_flags & executor_flags::Suspended) == executor_flags::Suspended) return; @@ -109,6 +136,16 @@ void executor::step() { auto lhs = pop_thing(); push_thing(lhs % rhs); } break; + case instruction_t::Load: { + variable_t variable = static_cast(frame.mod->byte(frame.position)) | + (static_cast(frame.mod->byte(frame.position + 1)) << 8); + push_thing(load_thing(variable)); + } break; + case instruction_t::Store: { + variable_t variable = static_cast(frame.mod->byte(frame.position)) | + (static_cast(frame.mod->byte(frame.position + 1)) << 8); + store_thing(variable, std::move(pop_thing())); + } break; case instruction_t::Call: { function_handle funcId = static_cast(frame.mod->byte(frame.position)) | (static_cast(frame.mod->byte(frame.position + 1)) << 8);