diff --git a/corewords.cpp b/corewords.cpp index 6aec5ab..97f53dc 100644 --- a/corewords.cpp +++ b/corewords.cpp @@ -168,19 +168,23 @@ execute: break; case 25: // exit state.ip = state.popr(); + if (state.ip == 0) { + std::longjmp(state.jmpbuf, + static_cast(State::Error::exit)); + } break; case 26: // semic state.dict.add(findi("exit")); state.compiling(false); break; - case 27: // _jmp - state.ip = state.beyondip() - sizeof(Cell); - break; - case 28: // _jmp0 - if (state.pop()) + case 27: // _jmp0 + if (state.pop()) { state.beyondip(); - else - state.ip = state.beyondip() - sizeof(Cell); + break; + } + [[fallthrough]]; + case 28: // _jmp + state.ip = state.beyondip() - sizeof(Cell); break; case 29: // depth state.push(state.size()); diff --git a/corewords.hpp b/corewords.hpp index fcb00e8..020694f 100644 --- a/corewords.hpp +++ b/corewords.hpp @@ -44,8 +44,8 @@ private: "_@\0_!\0>r\0r>\0=\0" "<\0&\0|\0^\0" "<<\0>>\0:\0'\0execute\0" - "exit\0;\1_jmp\0" - "_jmp0\0depth\0_rdepth\0key\0"; + "exit\0;\1_jmp0\0_jmp\0" + "depth\0_rdepth\0key\0"; }; #endif // ALEEFORTH_COREWORDS_HPP diff --git a/state.cpp b/state.cpp index 56ad8cd..c27d95b 100644 --- a/state.cpp +++ b/state.cpp @@ -35,20 +35,20 @@ State::Error State::execute(Addr addr) { auto stat = setjmp(jmpbuf); if (!stat) { - ip = 0; + if (addr < CoreWords::WordCount) { + CoreWords::run(addr, *this); + } else { + auto ins = addr; - auto ins = addr; - for (;;) { - CoreWords::run(ins, *this); - - if (!ip) - break; - - ip += sizeof(Cell); - ins = dict.read(ip); + for (;;) { + CoreWords::run(ins, *this); + ip += sizeof(Cell); + ins = dict.read(ip); + } } } else { - return static_cast(stat); + auto err = static_cast(stat); + return err == State::Error::exit ? State::Error::none : err; } return State::Error::none; diff --git a/state.hpp b/state.hpp index 69db2f6..76b3c67 100644 --- a/state.hpp +++ b/state.hpp @@ -37,7 +37,8 @@ struct State pushr, popr, top, - pick + pick, + exit }; Addr ip = 0;