Improve runtime error handling

This commit is contained in:
2020-05-16 11:54:49 +02:00
parent 41fb08373c
commit 30252e5863
4 changed files with 77 additions and 10 deletions

View File

@@ -1,27 +1,44 @@
#pragma once #pragma once
#include <string>
namespace Execute 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 namespace Internal
{ {
struct BadValueType : RuntimeError class BadValueType : public RuntimeError
{ {
public:
BadValueType();
}; };
} }
} }

View File

@@ -2,5 +2,43 @@
namespace Execute 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")
{
}
}
} }

View File

@@ -1,4 +1,5 @@
#include <execute/virtualmachine.hpp> #include <execute/virtualmachine.hpp>
#include <execute/error.hpp>
namespace Execute namespace Execute
{ {
@@ -6,7 +7,18 @@ namespace Execute
{ {
state.nextStatement = state.currentStatement + 1u; 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; state.currentStatement = state.nextStatement;
if (state.currentStatement >= code.statements.size()) if (state.currentStatement >= code.statements.size())

View File

@@ -33,7 +33,7 @@ namespace Interpret
} }
else 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); auto const & elem = state.labelStatementIndice.find(label);
if (elem == state.labelStatementIndice.end()) 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)) if ((state.memory.size() - state.stackPointer) < sizeof(unsigned))