From e809eb82c72835baec26fcc66b10581770c30436 Mon Sep 17 00:00:00 2001 From: CHatingPython Date: Sun, 14 Jun 2026 23:45:29 +0200 Subject: [PATCH 1/3] fix(furvm): handle import function in function move operators --- furvm/src/function.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/furvm/src/function.cpp b/furvm/src/function.cpp index 4d1ca25..ac74dc8 100644 --- a/furvm/src/function.cpp +++ b/furvm/src/function.cpp @@ -17,6 +17,10 @@ function::function(function&& other) noexcept case function_t::Native: { new (&m_value.native) native_function(std::move(other.m_value.native)); } break; + case function_t::Import: { + m_value.imp.mod = other.m_value.imp.mod; + m_value.imp.function = other.m_value.imp.function; + } break; } other.m_value.position = 0; } @@ -34,10 +38,14 @@ function& function::operator=(function&& other) noexcept { case function_t::Native: { new (&m_value.native) native_function(std::move(other.m_value.native)); } break; + case function_t::Import: { + m_value.imp.mod = other.m_value.imp.mod; + m_value.imp.function = other.m_value.imp.function; + } break; } other.m_value.position = 0; return *this; } -} // namespace furvm \ No newline at end of file +} // namespace furvm From eec25e3aea63998af75ea8dc5e23c8c2917db2e7 Mon Sep 17 00:00:00 2001 From: CHatingPython Date: Sun, 14 Jun 2026 23:49:29 +0200 Subject: [PATCH 2/3] feat(furvm): introduce jump and jump not zero instructions --- furvm/include/furvm/instruction.hpp | 15 +++++++++++++++ furvm/src/executor.cpp | 10 ++++++++++ 2 files changed, 25 insertions(+) diff --git a/furvm/include/furvm/instruction.hpp b/furvm/include/furvm/instruction.hpp index 2a73ea7..6c70574 100644 --- a/furvm/include/furvm/instruction.hpp +++ b/furvm/include/furvm/instruction.hpp @@ -86,6 +86,21 @@ enum class instruction_t : byte { */ Call, + /** + * @brief Jumps to an instruction relative to the current instruction. + * + * Jumps to an instruction relative to the current instruction with offset denoted by next byte. + */ + Jump, + + /** + * @brief Jumps to an instruction relative to the current instruction if top thing on the stack is not zero. + * + * Jumps to an instruction relative to the current instruction with offset denoted by next byte if the top thing on + * the stack is not zero (is true). + */ + JumpNotZero, + /** * @brief Pops the current call frame. */ diff --git a/furvm/src/executor.cpp b/furvm/src/executor.cpp index e4b5f28..ae10e70 100644 --- a/furvm/src/executor.cpp +++ b/furvm/src/executor.cpp @@ -139,11 +139,13 @@ void executor::step() { case instruction_t::Load: { variable_t variable = static_cast(frame.mod->byte(frame.position)) | (static_cast(frame.mod->byte(frame.position + 1)) << 8); + frame.position += 2; 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); + frame.position += 2; store_thing(variable, std::move(pop_thing())); } break; case instruction_t::Call: { @@ -161,6 +163,14 @@ void executor::step() { } break; } } break; + case instruction_t::Jump: { + frame.position += frame.mod->byte(frame.position++); + } break; + case instruction_t::JumpNotZero: { + byte offset = frame.mod->byte(frame.position++); + auto cond = pop_thing(); + if (cond->int32() != 0) frame.position += offset; + } break; case instruction_t::Return: { pop_frame(); if (m_frames.empty()) m_flags = m_flags | executor_flags::Done; From 8dfc880c07b125917e5d2efdf1f5d8fe5232850b Mon Sep 17 00:00:00 2001 From: CHatingPython Date: Mon, 15 Jun 2026 00:06:50 +0200 Subject: [PATCH 3/3] feat(furvm): introduce comparison operators --- furvm/include/furvm/instruction.hpp | 30 +++++++++++++ furvm/include/furvm/thing.hpp | 55 ++++++++++++++++++++++- furvm/src/executor.cpp | 30 +++++++++++++ furvm/src/thing.cpp | 68 ++++++++++++++++++++++++++++- 4 files changed, 181 insertions(+), 2 deletions(-) diff --git a/furvm/include/furvm/instruction.hpp b/furvm/include/furvm/instruction.hpp index 6c70574..fa4e44b 100644 --- a/furvm/include/furvm/instruction.hpp +++ b/furvm/include/furvm/instruction.hpp @@ -65,6 +65,36 @@ enum class instruction_t : byte { */ Mod, + /** + * @brief Compares two top-most things from the stack for equality. + */ + Equals, + + /** + * @brief Compares two top-most things from the stack for inequality. + */ + NotEquals, + + /** + * @brief Compares if the first top-most thing is less than the second top-most thing. + */ + LessThan, + + /** + * @brief Compares if the first top-most thing is greater than the second top-most thing. + */ + GreaterThan, + + /** + * @brief Compares if the first top-most thing is less than or equal to the second top-most thing. + */ + LessEqual, + + /** + * @brief Compares if the first top-most thing is greater than or equal to the second top-most thing. + */ + GreaterEqual, + /** * @brief Pushes a variable onto the stack. * diff --git a/furvm/include/furvm/thing.hpp b/furvm/include/furvm/thing.hpp index cea5cce..830e978 100644 --- a/furvm/include/furvm/thing.hpp +++ b/furvm/include/furvm/thing.hpp @@ -135,6 +135,59 @@ public: * @return Shared pointer to result thing. */ friend thing_p operator%(const thing_p& lhs, const thing_p& rhs); + + /** + * @brief Compares two things for equality. + * + * @param lhs Left-hand-side thing. + * @param rhs Right-hand-side thing. + * @return Shared pointer to result thing. + */ + friend thing_p operator==(const thing_p& lhs, const thing_p& rhs); + + /** + * @brief Compares two things for equality. + * + * @param lhs Left-hand-side thing. + * @param rhs Right-hand-side thing. + * @return Shared pointer to result thing. + */ + friend thing_p operator!=(const thing_p& lhs, const thing_p& rhs); + /** + * @brief Compares if the left thing is less than the right thing. + * + * @param lhs Left-hand-side thing. + * @param rhs Right-hand-side thing. + * @return Shared pointer to result thing. + */ + friend thing_p operator<(const thing_p& lhs, const thing_p& rhs); + + /** + * @brief Compares if the left thing is greater than the right thing. + * + * @param lhs Left-hand-side thing. + * @param rhs Right-hand-side thing. + * @return Shared pointer to result thing. + */ + friend thing_p operator>(const thing_p& lhs, const thing_p& rhs); + + /** + * @brief Compares if the left thing is less than or equal to the right thing. + * + * @param lhs Left-hand-side thing. + * @param rhs Right-hand-side thing. + * @return Shared pointer to result thing. + */ + friend thing_p operator<=(const thing_p& lhs, const thing_p& rhs); + + /** + * @brief Compares if the left thing is greater than or equal to the right thing. + * + * @param lhs Left-hand-side thing. + * @param rhs Right-hand-side thing. + * @return Shared pointer to result thing. + */ + friend thing_p operator>=(const thing_p& lhs, const thing_p& rhs); public: /** * @brief Returns a new thing. @@ -208,4 +261,4 @@ private: } // namespace furvm -#endif // FURVM_THING_HPP \ No newline at end of file +#endif // FURVM_THING_HPP diff --git a/furvm/src/executor.cpp b/furvm/src/executor.cpp index ae10e70..6e858bd 100644 --- a/furvm/src/executor.cpp +++ b/furvm/src/executor.cpp @@ -136,6 +136,36 @@ void executor::step() { auto lhs = pop_thing(); push_thing(lhs % rhs); } break; + case instruction_t::Equals: { + auto rhs = pop_thing(); + auto lhs = pop_thing(); + push_thing(lhs == rhs); + } break; + case instruction_t::NotEquals: { + auto rhs = pop_thing(); + auto lhs = pop_thing(); + push_thing(lhs != rhs); + } break; + case instruction_t::LessThan: { + auto rhs = pop_thing(); + auto lhs = pop_thing(); + push_thing(lhs < rhs); + } break; + case instruction_t::GreaterThan: { + auto rhs = pop_thing(); + auto lhs = pop_thing(); + push_thing(lhs > rhs); + } break; + case instruction_t::LessEqual: { + auto rhs = pop_thing(); + auto lhs = pop_thing(); + push_thing(lhs <= rhs); + } break; + case instruction_t::GreaterEqual: { + auto rhs = pop_thing(); + 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); diff --git a/furvm/src/thing.cpp b/furvm/src/thing.cpp index 272f7b8..a75aa4c 100644 --- a/furvm/src/thing.cpp +++ b/furvm/src/thing.cpp @@ -141,6 +141,72 @@ thing_p operator%(const thing_p& lhs, const thing_p& rhs) { } } +thing_p operator==(const thing_p& lhs, const thing_p& rhs) { + switch (thing_type_pair(lhs->m_type, rhs->m_type)) { + case thing_type_pair(thing_t::Int32, thing_t::Int32): { + auto res = thing::create(lhs->m_context, thing_t::Int32); + res->int32() = static_cast(lhs->int32() == rhs->int32()); + return res; + } + default: throw std::runtime_error("unexpected operator"); + } +} + +thing_p operator!=(const thing_p& lhs, const thing_p& rhs) { + switch (thing_type_pair(lhs->m_type, rhs->m_type)) { + case thing_type_pair(thing_t::Int32, thing_t::Int32): { + auto res = thing::create(lhs->m_context, thing_t::Int32); + res->int32() = static_cast(lhs->int32() != rhs->int32()); + return res; + } + default: throw std::runtime_error("unexpected operator"); + } +} + +thing_p operator<(const thing_p& lhs, const thing_p& rhs) { + switch (thing_type_pair(lhs->m_type, rhs->m_type)) { + case thing_type_pair(thing_t::Int32, thing_t::Int32): { + auto res = thing::create(lhs->m_context, thing_t::Int32); + res->int32() = static_cast(lhs->int32() < rhs->int32()); + return res; + } + default: throw std::runtime_error("unexpected operator"); + } +} + +thing_p operator>(const thing_p& lhs, const thing_p& rhs) { + switch (thing_type_pair(lhs->m_type, rhs->m_type)) { + case thing_type_pair(thing_t::Int32, thing_t::Int32): { + auto res = thing::create(lhs->m_context, thing_t::Int32); + res->int32() = static_cast(lhs->int32() > rhs->int32()); + return res; + } + default: throw std::runtime_error("unexpected operator"); + } +} + +thing_p operator<=(const thing_p& lhs, const thing_p& rhs) { + switch (thing_type_pair(lhs->m_type, rhs->m_type)) { + case thing_type_pair(thing_t::Int32, thing_t::Int32): { + auto res = thing::create(lhs->m_context, thing_t::Int32); + res->int32() = static_cast(lhs->int32() <= rhs->int32()); + return res; + } + default: throw std::runtime_error("unexpected operator"); + } +} + +thing_p operator>=(const thing_p& lhs, const thing_p& rhs) { + switch (thing_type_pair(lhs->m_type, rhs->m_type)) { + case thing_type_pair(thing_t::Int32, thing_t::Int32): { + auto res = thing::create(lhs->m_context, thing_t::Int32); + res->int32() = static_cast(lhs->int32() >= rhs->int32()); + return res; + } + default: throw std::runtime_error("unexpected operator"); + } +} + thing_p thing::clone(const thing_p& thing) { thing_handle id = thing->m_context->m_things.size(); if (!thing->m_context->m_deadThings.empty()) { @@ -174,4 +240,4 @@ const std::int32_t& thing::int32() const { } // namespace furvm -// NOLINTEND(cppcoreguidelines-no-malloc) \ No newline at end of file +// NOLINTEND(cppcoreguidelines-no-malloc)