From 30252e58633ba1292afdc0e71413a21dee82d4cf Mon Sep 17 00:00:00 2001 From: Tijmen van Nesselrooij Date: Sat, 16 May 2020 11:54:49 +0200 Subject: [PATCH] Improve runtime error handling --- include/execute/error.hpp | 29 +++++++++++++++++++----- src/execute/error.cpp | 40 +++++++++++++++++++++++++++++++++- src/execute/virtualmachine.cpp | 14 +++++++++++- src/interpret/statement.cpp | 4 ++-- 4 files changed, 77 insertions(+), 10 deletions(-) diff --git a/include/execute/error.hpp b/include/execute/error.hpp index 2b3b26c..5e899d6 100644 --- a/include/execute/error.hpp +++ b/include/execute/error.hpp @@ -1,27 +1,44 @@ #pragma once +#include namespace Execute { - struct RuntimeError + class RuntimeError { + protected: + std::string message; + public: + std::string const & GetMessage() const; + + RuntimeError(); + RuntimeError(std::string const & what); }; - struct StackUnderflow : RuntimeError + class StackUnderflow : public RuntimeError { - + public: + StackUnderflow(); }; - struct StackOverflow : RuntimeError + class StackOverflow : public RuntimeError { + public: + StackOverflow(); + }; + class MissingLabel : public RuntimeError + { + public: + MissingLabel(std::string const & label); }; namespace Internal { - struct BadValueType : RuntimeError + class BadValueType : public RuntimeError { - + public: + BadValueType(); }; } } \ No newline at end of file diff --git a/src/execute/error.cpp b/src/execute/error.cpp index e83a30a..b4876b2 100644 --- a/src/execute/error.cpp +++ b/src/execute/error.cpp @@ -2,5 +2,43 @@ namespace Execute { - + std::string const & RuntimeError::GetMessage() const + { + return message; + } + + RuntimeError::RuntimeError() + : message("Undocumented runtime error") + { + } + + RuntimeError::RuntimeError(std::string const & what) + : message(what) + { + } + + StackUnderflow::StackUnderflow() + : RuntimeError("Stack underflow error") + { + } + + StackOverflow::StackOverflow() + : RuntimeError("Stack overflow error") + { + } + + MissingLabel::MissingLabel(std::string const & label) + { + message = "Missing jump/function label \""; + message += label; + message += '"'; + } + + namespace Internal + { + BadValueType::BadValueType() + : RuntimeError("Internal error: bad value type") + { + } + } } \ No newline at end of file diff --git a/src/execute/virtualmachine.cpp b/src/execute/virtualmachine.cpp index 02267e6..b0a999d 100644 --- a/src/execute/virtualmachine.cpp +++ b/src/execute/virtualmachine.cpp @@ -1,4 +1,5 @@ #include +#include namespace Execute { @@ -6,7 +7,18 @@ namespace Execute { state.nextStatement = state.currentStatement + 1u; - code.statements[state.currentStatement]->Execute(flags, state, registers); + try + { + code.statements[state.currentStatement]->Execute(flags, state, registers); + } + catch(RuntimeError & ex) + { + terminated = true; + std::puts("\nA fatal error occurred and execution has been halted:"); + std::printf("%s\n", ex.GetMessage().c_str()); + + return; + } state.currentStatement = state.nextStatement; if (state.currentStatement >= code.statements.size()) diff --git a/src/interpret/statement.cpp b/src/interpret/statement.cpp index df1655e..87a902c 100644 --- a/src/interpret/statement.cpp +++ b/src/interpret/statement.cpp @@ -33,7 +33,7 @@ namespace Interpret } else { - throw std::runtime_error("Attempted jump to nonexisting label"); + throw Execute::MissingLabel(label); } } @@ -47,7 +47,7 @@ namespace Interpret auto const & elem = state.labelStatementIndice.find(label); if (elem == state.labelStatementIndice.end()) { - throw std::runtime_error("Attempted call nonexisting function (missing label)"); + throw Execute::MissingLabel(label); } if ((state.memory.size() - state.stackPointer) < sizeof(unsigned))