diff --git a/bin/test.wasm b/bin/test.wasm index 5deeb94..1e6ed42 100644 --- a/bin/test.wasm +++ b/bin/test.wasm @@ -90,7 +90,10 @@ int $3; # Jump over the interrupt call noop_function; -int $3; + +# Echo a character +int $4; +int $0; exit; noop_function: diff --git a/include/execute/error.hpp b/include/execute/error.hpp index 5e899d6..590358c 100644 --- a/include/execute/error.hpp +++ b/include/execute/error.hpp @@ -33,6 +33,12 @@ namespace Execute MissingLabel(std::string const & label); }; + class InterruptIndexOutOfRange : public RuntimeError + { + public: + InterruptIndexOutOfRange(int const index); + }; + namespace Internal { class BadValueType : public RuntimeError diff --git a/src/execute/error.cpp b/src/execute/error.cpp index b4876b2..5c39726 100644 --- a/src/execute/error.cpp +++ b/src/execute/error.cpp @@ -34,6 +34,13 @@ namespace Execute message += '"'; } + InterruptIndexOutOfRange::InterruptIndexOutOfRange(int const index) + { + message = "Interrupt index "; + message += std::to_string(index); + message += " is out of range"; + } + namespace Internal { BadValueType::BadValueType() diff --git a/src/execute/interrupts.cpp b/src/execute/interrupts.cpp index 325b4e6..867fed9 100644 --- a/src/execute/interrupts.cpp +++ b/src/execute/interrupts.cpp @@ -7,6 +7,7 @@ namespace Execute { return std::vector { + /* STDOUT INTERRUPTS */ // 0 print char [](Execute::Registers & registers, std::vector & memory) { std::putc(registers.A, stdout); }, // 1 print decimal integer @@ -21,6 +22,13 @@ namespace Execute { std::putc(memory[i], stdout); } + }, + + /* STDIN INTERRUPTS */ + // 10 get char from STDIN + [](Execute::Registers & registers, std::vector & memory) + { + registers.A = std::getchar(); } }; } diff --git a/src/interpret/statement.cpp b/src/interpret/statement.cpp index bd9b789..1a39720 100644 --- a/src/interpret/statement.cpp +++ b/src/interpret/statement.cpp @@ -89,7 +89,13 @@ namespace Interpret 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(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)