feat(furvm): add breakpoints

This commit is contained in:
2026-08-16 19:59:46 +02:00
parent 29dd9abb3f
commit b3ce4fa0ed
3 changed files with 26 additions and 4 deletions
+3 -4
View File
@@ -7,7 +7,6 @@
#include <functional> #include <functional>
#include <stack> #include <stack>
#include <utility>
#include <vector> #include <vector>
namespace furvm { namespace furvm {
@@ -29,13 +28,13 @@ static inline executor_flags operator~(executor_flags flags) {
return executor_flags(~static_cast<std::uint32_t>(flags)); return executor_flags(~static_cast<std::uint32_t>(flags));
} }
using executor_callback = std::function<void(executor&)>;
class executor { class executor {
friend class context; friend class context;
private: private:
executor(context* context) executor(context* context)
: m_context(context) {} : m_context(context) {}
public:
using new_frame_callback = std::function<void(executor&)>;
public: public:
/** /**
* @brief Executor frame. * @brief Executor frame.
@@ -180,7 +179,7 @@ private:
std::stack<frame> m_frames; std::stack<frame> m_frames;
std::stack<thing<>> m_stack; std::stack<thing<>> m_stack;
executor_callback m_newFrameCb = nullptr; new_frame_callback m_newFrameCb = nullptr;
}; };
} // namespace furvm } // namespace furvm
+16
View File
@@ -145,6 +145,11 @@ struct mod_type {
} }
}; };
struct breakpoint {
std::function<void(executor&, void*)> callback;
void* data;
};
class mod { class mod {
friend class function; friend class function;
friend class serializer; friend class serializer;
@@ -379,6 +384,15 @@ public:
if (var >= m_globalVariables.size()) throw std::runtime_error("invalid slot"); if (var >= m_globalVariables.size()) throw std::runtime_error("invalid slot");
return m_globalVariables[var]; return m_globalVariables[var];
} }
public:
template <typename Fwd, typename = std::enable_if_t<std::is_constructible_v<breakpoint, Fwd>>>
void set_breakpoint(bytecode_pos pos, Fwd&& breakpoint) {
m_breakpoints[pos] = std::forward<Fwd>(breakpoint);
}
bool has_breakpoint(bytecode_pos pos) const { return m_breakpoints.find(pos) != m_breakpoints.end(); }
const breakpoint& breakpoint_at(bytecode_pos pos) const { return m_breakpoints.at(pos); }
public: public:
/** /**
* @brief Prints the module in a bytecode form to an output stream. * @brief Prints the module in a bytecode form to an output stream.
@@ -410,6 +424,8 @@ private:
std::vector<thing<>> m_globalVariables; std::vector<thing<>> m_globalVariables;
std::unordered_map<std::string, native_function> m_nativeFunctions; std::unordered_map<std::string, native_function> m_nativeFunctions;
std::unordered_map<bytecode_pos, breakpoint> m_breakpoints;
}; };
} // namespace furvm } // namespace furvm
+7
View File
@@ -176,6 +176,13 @@ void executor::step() {
struct frame& frame = m_frames.top(); struct frame& frame = m_frames.top();
if (frame.mod->has_breakpoint(frame.position)) {
m_flags = m_flags | executor_flags::Suspended;
const auto& bp = frame.mod->breakpoint_at(frame.position);
bp.callback(*this, bp.data);
return;
}
instruction instr{}; instruction instr{};
frame.position += instr.read(frame.mod->bytecode_view().subview(frame.position)); frame.position += instr.read(frame.mod->bytecode_view().subview(frame.position));
switch (instr.type) { switch (instr.type) {