From 48c6da113464eeadbbd54eb099ee51dcc74ab654 Mon Sep 17 00:00:00 2001 From: CHatingPython Date: Sun, 7 Jun 2026 12:02:36 +0200 Subject: [PATCH] feat(furvm): add stack underflow exception --- furvm/include/furvm/exceptions.hpp | 43 ++++++++++++++++++++++++++++++ furvm/include/furvm/fwd.hpp | 7 +++++ furvm/src/executor.cpp | 8 +++--- furvm/src/main.cpp | 3 ++- 4 files changed, 57 insertions(+), 4 deletions(-) create mode 100644 furvm/include/furvm/exceptions.hpp diff --git a/furvm/include/furvm/exceptions.hpp b/furvm/include/furvm/exceptions.hpp new file mode 100644 index 0000000..e9a0c58 --- /dev/null +++ b/furvm/include/furvm/exceptions.hpp @@ -0,0 +1,43 @@ +#ifndef FURVM_EXCEPTIONS_HPP +#define FURVM_EXCEPTIONS_HPP + +#include + +namespace furvm { + +class stack_underflow : public std::exception { +public: + stack_underflow() = default; + ~stack_underflow() override = default; + + /** + * @brief Move constructor. + */ + stack_underflow(stack_underflow&&) noexcept = default; + + /** + * @brief Move constructor. + */ + stack_underflow& operator=(stack_underflow&&) noexcept = default; + + /** + * @brief Copy constructor. + */ + stack_underflow(const stack_underflow&) = default; + + /** + * @brief Copy constructor. + */ + stack_underflow& operator=(const stack_underflow&) = default; +public: + /** + * @brief Returns a C-style string describing the cause of the error. + * + * @return The cause of the error. + */ + const char* what() const noexcept override { return "stack underflow"; } +}; + +} // namespace furvm + +#endif // FURVM_EXCEPTIONS_HPP \ No newline at end of file diff --git a/furvm/include/furvm/fwd.hpp b/furvm/include/furvm/fwd.hpp index 78a1a42..6d36280 100644 --- a/furvm/include/furvm/fwd.hpp +++ b/furvm/include/furvm/fwd.hpp @@ -140,6 +140,13 @@ class context; */ using context_p = std::shared_ptr; +// exceptions.hpp: + +/** + * @brief Stack underflow exception. + */ +class stack_underflow; + } // namespace furvm #endif // FURVM_FWD_HPP \ No newline at end of file diff --git a/furvm/src/executor.cpp b/furvm/src/executor.cpp index 9101fb2..687cb00 100644 --- a/furvm/src/executor.cpp +++ b/furvm/src/executor.cpp @@ -1,6 +1,7 @@ #include "furvm/executor.hpp" #include "furvm/context.hpp" // IWYU pragma: keep +#include "furvm/exceptions.hpp" #include "furvm/instruction.hpp" #include "furvm/thing.hpp" @@ -26,6 +27,7 @@ void executor::push_frame(const mod_p& mod, std::size_t position) { } struct executor::frame executor::pop_frame() { + if (m_frames.empty()) throw stack_underflow(); struct executor::frame frame = m_frames.top(); m_frames.pop(); return frame; @@ -40,14 +42,14 @@ void executor::push_thing(const thing_p& thing) { } thing_p executor::pop_thing() { - if (m_frames.top().stackBase >= m_stack.size()) return {}; + if (m_frames.top().stackBase >= m_stack.size()) throw stack_underflow(); thing_p top = std::move(m_stack.top()); m_stack.pop(); return top; } thing_p executor::thing() const { - if (m_frames.top().stackBase >= m_stack.size()) return {}; + if (m_frames.top().stackBase >= m_stack.size()) throw stack_underflow(); return m_stack.top(); } @@ -65,7 +67,7 @@ void executor::step() { m_stack.push(std::move(thing)); } break; case instruction_t::Drop: { - m_stack.pop(); + pop_thing(); } break; case instruction_t::Return: { pop_frame(); diff --git a/furvm/src/main.cpp b/furvm/src/main.cpp index f6b25a8..53474eb 100644 --- a/furvm/src/main.cpp +++ b/furvm/src/main.cpp @@ -8,9 +8,10 @@ #include #include -static constexpr std::array s_bytecode = { +static constexpr std::array s_bytecode = { furvm::byte(furvm::instruction_t::PushB2I), 67, + furvm::byte(furvm::instruction_t::Drop), furvm::byte(furvm::instruction_t::Return), };