From 7a7a1ec64c77c2742b43f1769c39bf66d507b25a Mon Sep 17 00:00:00 2001 From: CHatingPython Date: Tue, 11 Aug 2026 13:56:34 +0200 Subject: [PATCH] feat(furvm): improve instruction abstraction Add reading and writing to instruction abstraction. --- furvm/include/furvm/instruction.hpp | 24 +++++-- furvm/src/instruction.cpp | 100 ++++++++++++++++++++++++++-- 2 files changed, 113 insertions(+), 11 deletions(-) diff --git a/furvm/include/furvm/instruction.hpp b/furvm/include/furvm/instruction.hpp index 5c6d2c0..4fdcceb 100644 --- a/furvm/include/furvm/instruction.hpp +++ b/furvm/include/furvm/instruction.hpp @@ -3,19 +3,26 @@ #include "furvm/fwd.hpp" +#include + namespace furvm { struct instruction_argument { enum type_e { None = 0, - Byte, - Short, - Int, + S8, + U8, + S16, + U16, + S32, + U32, Constant, Type, Variable, Function, Offset, + + Count, } type; union { std::int8_t s8; @@ -25,6 +32,12 @@ struct instruction_argument { std::int32_t s32; std::uint32_t u32; }; + + static const std::size_t s_sizes[Count]; + static const bool s_signedness[Count]; + + std::size_t size() const { return s_sizes[type]; } + bool is_signed() const { return s_signedness[type]; } }; using instruction_argument_t = instruction_argument::type_e; @@ -72,7 +85,10 @@ struct instruction { } type; instruction_argument arg; - static instruction_argument_t s_arguments[Count]; + static const instruction_argument_t s_arguments[Count]; + + std::size_t read(std::string_view in); + std::size_t write(std::string& out) const; }; using instruction_t = instruction::type_e; diff --git a/furvm/src/instruction.cpp b/furvm/src/instruction.cpp index bea7369..3dad2c5 100644 --- a/furvm/src/instruction.cpp +++ b/furvm/src/instruction.cpp @@ -1,22 +1,79 @@ #include "furvm/instruction.hpp" +#include +#include + namespace furvm { -instruction_argument_t instruction::s_arguments[instruction::Count] = { +const std::size_t instruction_argument::s_sizes[instruction_argument::Count] = { + // None: + 0, + // S8: + 1, + // U8: + 1, + // S16: + 2, + // U16: + 2, + // S32 + 4, + // U32 + 4, + // Constant: + 4, + // Type: + 4, + // Variable: + 2, + // Function: + 4, + // Offset: + 1, +}; + +const bool instruction_argument::s_signedness[instruction_argument::Count] = { + // None: + false, + // S8: + true, + // U8: + false, + // S16: + true, + // U16: + false, + // S32 + true, + // U32: + false, + // Constant: + false, + // Type: + false, + // Variable: + false, + // Function: + false, + // Offset: + true, +}; + +const instruction_argument_t instruction::s_arguments[instruction::Count] = { // NoOperation: instruction_argument::None, // PushS8: - instruction_argument::Byte, + instruction_argument::S8, // PushU8: - instruction_argument::Byte, + instruction_argument::U8, // PushS16: - instruction_argument::Short, + instruction_argument::S16, // PushU16: - instruction_argument::Short, + instruction_argument::U16, // PushS32: - instruction_argument::Int, + instruction_argument::S32, // PushU32: - instruction_argument::Int, + instruction_argument::U32, // PushConstant: instruction_argument::Constant, // Array: @@ -77,4 +134,33 @@ instruction_argument_t instruction::s_arguments[instruction::Count] = { instruction_argument::None, }; +std::size_t instruction::read(std::string_view in) { + type = static_cast(in[0]); + if (type >= Count) throw std::runtime_error("invalid instruction"); + arg.type = s_arguments[type]; + + std::string_view argView = in.substr(1, arg.size()); + switch (argView.size()) { + case 1: arg.u8 = argView[0]; break; + case 2: arg.u16 = argView[0] | (argView[1] << 8); break; + case 4: arg.u32 = argView[0] | (argView[1] << 8) | (argView[2] << 16) | (argView[3] << 24); break; + default: throw std::runtime_error("unreachable"); + } + + return 1 + argView.size(); } + +std::size_t instruction::write(std::string& out) const { + if (type >= Count) throw std::runtime_error("invalid instruction"); + if (s_arguments[type] != arg.type) throw std::runtime_error("malformed instruction"); + out += static_cast(type); + switch (arg.size()) { + case 1: out += arg.is_signed() ? std::to_string(arg.s8) : std::to_string(arg.u8); break; + case 2: out += arg.is_signed() ? std::to_string(arg.s16) : std::to_string(arg.u16); break; + case 4: out += arg.is_signed() ? std::to_string(arg.s32) : std::to_string(arg.u32); break; + default: throw std::runtime_error("unreachable"); + } + return 0; +} + +} // namespace furvm