From 8dfc880c07b125917e5d2efdf1f5d8fe5232850b Mon Sep 17 00:00:00 2001 From: CHatingPython Date: Mon, 15 Jun 2026 00:06:50 +0200 Subject: [PATCH] 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)