Add STDIN interrupt and error handling for all interrupts

This commit is contained in:
2020-05-17 13:28:59 +02:00
parent f8eaabfc55
commit 06de5290da
5 changed files with 32 additions and 2 deletions

View File

@@ -90,7 +90,10 @@ int $3;
# Jump over the interrupt # Jump over the interrupt
call noop_function; call noop_function;
int $3;
# Echo a character
int $4;
int $0;
exit; exit;
noop_function: noop_function:

View File

@@ -33,6 +33,12 @@ namespace Execute
MissingLabel(std::string const & label); MissingLabel(std::string const & label);
}; };
class InterruptIndexOutOfRange : public RuntimeError
{
public:
InterruptIndexOutOfRange(int const index);
};
namespace Internal namespace Internal
{ {
class BadValueType : public RuntimeError class BadValueType : public RuntimeError

View File

@@ -34,6 +34,13 @@ namespace Execute
message += '"'; message += '"';
} }
InterruptIndexOutOfRange::InterruptIndexOutOfRange(int const index)
{
message = "Interrupt index ";
message += std::to_string(index);
message += " is out of range";
}
namespace Internal namespace Internal
{ {
BadValueType::BadValueType() BadValueType::BadValueType()

View File

@@ -7,6 +7,7 @@ namespace Execute
{ {
return std::vector<InterruptFn> return std::vector<InterruptFn>
{ {
/* STDOUT INTERRUPTS */
// 0 print char // 0 print char
[](Execute::Registers & registers, std::vector<std::uint8_t> & memory) { std::putc(registers.A, stdout); }, [](Execute::Registers & registers, std::vector<std::uint8_t> & memory) { std::putc(registers.A, stdout); },
// 1 print decimal integer // 1 print decimal integer
@@ -21,6 +22,13 @@ namespace Execute
{ {
std::putc(memory[i], stdout); std::putc(memory[i], stdout);
} }
},
/* STDIN INTERRUPTS */
// 10 get char from STDIN
[](Execute::Registers & registers, std::vector<std::uint8_t> & memory)
{
registers.A = std::getchar();
} }
}; };
} }

View File

@@ -89,7 +89,13 @@ namespace Interpret
void InterruptStatement::Execute(Execute::Flags & flags, Execute::State & state, Execute::Registers & registers) void InterruptStatement::Execute(Execute::Flags & flags, Execute::State & state, Execute::Registers & registers)
{ {
state.interrupts[firstArgument.GetValue(state, registers)](registers, state.memory); auto const interruptIndex = firstArgument.GetValue(state, registers);
if (interruptIndex < 0 || static_cast<unsigned>(interruptIndex) > state.interrupts.size())
{
throw Execute::InterruptIndexOutOfRange(interruptIndex);
}
state.interrupts[interruptIndex](registers, state.memory);
} }
void PopStatement::Execute(Execute::Flags & flags, Execute::State & state, Execute::Registers & registers) void PopStatement::Execute(Execute::Flags & flags, Execute::State & state, Execute::Registers & registers)