From 4d935ef75fb553d02e8a7468f27bdebb68fb82a6 Mon Sep 17 00:00:00 2001 From: CHatingPython Date: Wed, 10 Jun 2026 20:02:31 +0200 Subject: [PATCH] feat(furvm): add operation instructions --- furvm/include/furvm/instruction.hpp | 25 ++++++++ furvm/include/furvm/thing.hpp | 94 +++++++++++++++++++++++++++++ furvm/src/executor.cpp | 25 ++++++++ furvm/src/main.cpp | 2 +- 4 files changed, 145 insertions(+), 1 deletion(-) diff --git a/furvm/include/furvm/instruction.hpp b/furvm/include/furvm/instruction.hpp index 7758037..a73a810 100644 --- a/furvm/include/furvm/instruction.hpp +++ b/furvm/include/furvm/instruction.hpp @@ -40,6 +40,31 @@ enum class instruction_t : byte { */ Clone, + /** + * @brief Adds two things together on the stack. + */ + Add, + + /** + * @brief Subtracts two things together on the stack. + */ + Sub, + + /** + * @brief Multiplies two things together on the stack. + */ + Mul, + + /** + * @brief Divides two things together on the stack. + */ + Div, + + /** + * @brief Modulos two things together on the stack. + */ + Mod, + /** * @brief Pops the current call frame. */ diff --git a/furvm/include/furvm/thing.hpp b/furvm/include/furvm/thing.hpp index c1a1a16..ac84f92 100644 --- a/furvm/include/furvm/thing.hpp +++ b/furvm/include/furvm/thing.hpp @@ -4,6 +4,8 @@ #include "furvm/context.hpp" // IWYU pragma: keep #include "furvm/fwd.hpp" +#include + namespace furvm { enum class thing_t : std::uint8_t { @@ -90,6 +92,98 @@ public: thing(const thing&) = delete; thing& operator=(const thing&) = delete; +public: +#define x(lType, rType) ((std::uint16_t)((((std::uint8_t)(lType)) << 8) | ((std::uint8_t)(rType)))) + /** + * @brief Adds two things together. + * + * @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) { + switch (x(lhs->m_type, rhs->m_type)) { + case x(thing_t::Int32, thing_t::Int32): { + auto res = create(lhs->m_context, thing_t::Int32); + res->int32() = lhs->int32() + rhs->int32(); + return res; + } + default: throw std::runtime_error("unexpected operator"); + } + } + + /** + * @brief Subtracts two things together. + * + * @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) { + switch (x(lhs->m_type, rhs->m_type)) { + case x(thing_t::Int32, thing_t::Int32): { + auto res = create(lhs->m_context, thing_t::Int32); + res->int32() = lhs->int32() - rhs->int32(); + return res; + } + default: throw std::runtime_error("unexpected operator"); + } + } + + /** + * @brief Multiplies two things together. + * + * @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) { + switch (x(lhs->m_type, rhs->m_type)) { + case x(thing_t::Int32, thing_t::Int32): { + auto res = create(lhs->m_context, thing_t::Int32); + res->int32() = lhs->int32() * rhs->int32(); + return res; + } + default: throw std::runtime_error("unexpected operator"); + } + } + + /** + * @brief Divides two things together. + * + * @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) { + switch (x(lhs->m_type, rhs->m_type)) { + case x(thing_t::Int32, thing_t::Int32): { + auto res = create(lhs->m_context, thing_t::Int32); + res->int32() = lhs->int32() / rhs->int32(); + return res; + } + default: throw std::runtime_error("unexpected operator"); + } + } + + /** + * @brief Modulos two things together. + * + * @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) { + switch (x(lhs->m_type, rhs->m_type)) { + case x(thing_t::Int32, thing_t::Int32): { + auto res = create(lhs->m_context, thing_t::Int32); + res->int32() = lhs->int32() % rhs->int32(); + return res; + } + default: throw std::runtime_error("unexpected operator"); + } + } +#undef x public: /** * @brief Returns a new thing. diff --git a/furvm/src/executor.cpp b/furvm/src/executor.cpp index 48b4072..c523d28 100644 --- a/furvm/src/executor.cpp +++ b/furvm/src/executor.cpp @@ -82,6 +82,31 @@ void executor::step() { case instruction_t::Clone: { push_thing(std::move(thing::clone(thing()))); } break; + case instruction_t::Add: { + auto rhs = pop_thing(); + auto lhs = pop_thing(); + push_thing(lhs + rhs); + } break; + case instruction_t::Sub: { + auto rhs = pop_thing(); + auto lhs = pop_thing(); + push_thing(lhs - rhs); + } break; + case instruction_t::Mul: { + auto rhs = pop_thing(); + auto lhs = pop_thing(); + push_thing(lhs * rhs); + } break; + case instruction_t::Div: { + auto rhs = pop_thing(); + auto lhs = pop_thing(); + push_thing(lhs / rhs); + } break; + case instruction_t::Mod: { + auto rhs = pop_thing(); + auto lhs = pop_thing(); + push_thing(lhs % rhs); + } break; case instruction_t::Return: { pop_frame(); if (m_frames.empty()) m_flags = m_flags | executor_flags::Done; diff --git a/furvm/src/main.cpp b/furvm/src/main.cpp index 6bf1767..9f1d18c 100644 --- a/furvm/src/main.cpp +++ b/furvm/src/main.cpp @@ -12,7 +12,7 @@ static constexpr std::array s_bytecode = { furvm::byte(furvm::instruction_t::PushB2I), 67, furvm::byte(furvm::instruction_t::Clone), - furvm::byte(furvm::instruction_t::Drop), + furvm::byte(furvm::instruction_t::Add), furvm::byte(furvm::instruction_t::Drop), furvm::byte(furvm::instruction_t::Return), };