diff --git a/alee-msp430.cpp b/alee-msp430.cpp index 3121dc1..ca00026 100644 --- a/alee-msp430.cpp +++ b/alee-msp430.cpp @@ -66,14 +66,15 @@ int main() serputs("\n\r"); - if (auto r = Parser::parse(state, strbuf); r == 0) { + if (auto r = Parser::parse(state, strbuf); r == Error::none) { serputs(state.compiling() ? " compiled" : " ok"); } else { switch (r) { - case Parser::UnknownWord: + case Error::noword: serputs("unknown word..."); break; default: + serputs("error..."); break; } } diff --git a/alee-standalone.cpp b/alee-standalone.cpp index 3c4eb3d..2c971ce 100644 --- a/alee-standalone.cpp +++ b/alee-standalone.cpp @@ -79,7 +79,6 @@ static void load(State& state) state.dict.writebyte(i++, file.get()); } -#include void user_sys(State& state) { char buf[32] = {0}; @@ -107,55 +106,41 @@ void user_sys(State& state) std::cout << buf << ' '; } break; - case 5: // eval - { - auto oldip = state.ip; - std::jmp_buf oldjb; - memcpy(oldjb, state.jmpbuf, sizeof(std::jmp_buf)); - state.ip = 0; - Parser::parseSource(state); - memcpy(state.jmpbuf, oldjb, sizeof(std::jmp_buf)); - state.ip = oldip; - } + default: break; } } void parseLine(State& state, const std::string& line) { - if (auto r = Parser::parse(state, line.c_str()); r == 0) { + if (auto r = Parser::parse(state, line.c_str()); r == Error::none) { if (okay) - std::cout << (state.compiling() ? "compiled" : "ok") << std::endl; + std::cout << (state.compiling() ? " compiled" : " ok") << std::endl; } else { switch (r) { - case Parser::UnknownWord: + case Error::noword: std::cout << "word not found in: " << line << std::endl; break; - case static_cast(State::Error::push): + case Error::push: std::cout << "stack overflow" << std::endl; break; - case static_cast(State::Error::pushr): + case Error::pushr: std::cout << "return stack overflow" << std::endl; break; - case static_cast(State::Error::popr): + case Error::popr: std::cout << "return stack underflow" << std::endl; break; - case static_cast(State::Error::pop): - case static_cast(State::Error::top): - case static_cast(State::Error::pick): + case Error::pop: + case Error::top: + case Error::pick: std::cout << "stack underflow" << std::endl; break; default: - std::cout << "error: " << r << std::endl; + std::cout << "unknown error" << std::endl; break; } - while (state.size()) - state.pop(); - while (state.rsize()) - state.popr(); - state.dict.write(Dictionary::Compiling, 0); - state.ip = 0; + state.reset(); } } diff --git a/alee.cpp b/alee.cpp index e222363..92af969 100644 --- a/alee.cpp +++ b/alee.cpp @@ -26,7 +26,7 @@ static bool okay = false; -static void readchar(State& state); +static void readchar(State&); static void parseLine(State&, const std::string&); static void parseFile(State&, std::istream&); @@ -76,12 +76,10 @@ static void load(State& state) { std::ifstream file ("alee.dat", std::ios::binary); - Addr i = 0; - while (file.good()) - state.dict.writebyte(i++, file.get()); + for (Addr i = 0; file.good(); i++) + state.dict.writebyte(i, file.get()); } -#include void user_sys(State& state) { char buf[32] = {0}; @@ -109,55 +107,41 @@ void user_sys(State& state) std::cout << buf << ' '; } break; - case 5: // eval - { - auto oldip = state.ip; - std::jmp_buf oldjb; - memcpy(oldjb, state.jmpbuf, sizeof(std::jmp_buf)); - state.ip = 0; - Parser::parseSource(state); - memcpy(state.jmpbuf, oldjb, sizeof(std::jmp_buf)); - state.ip = oldip; - } + default: break; } } void parseLine(State& state, const std::string& line) { - if (auto r = Parser::parse(state, line.c_str()); r == 0) { + if (auto r = Parser::parse(state, line.c_str()); r == Error::none) { if (okay) - std::cout << (state.compiling() ? "compiled" : "ok") << std::endl; + std::cout << (state.compiling() ? " compiled" : " ok") << std::endl; } else { switch (r) { - case Parser::UnknownWord: + case Error::noword: std::cout << "word not found in: " << line << std::endl; break; - case static_cast(State::Error::push): + case Error::push: std::cout << "stack overflow" << std::endl; break; - case static_cast(State::Error::pushr): + case Error::pushr: std::cout << "return stack overflow" << std::endl; break; - case static_cast(State::Error::popr): + case Error::popr: std::cout << "return stack underflow" << std::endl; break; - case static_cast(State::Error::pop): - case static_cast(State::Error::top): - case static_cast(State::Error::pick): + case Error::pop: + case Error::top: + case Error::pick: std::cout << "stack underflow" << std::endl; break; default: - std::cout << "error: " << r << std::endl; + std::cout << "unknown error" << std::endl; break; } - while (state.size()) - state.pop(); - while (state.rsize()) - state.popr(); - state.dict.write(Dictionary::Compiling, 0); - state.ip = 0; + state.reset(); } } diff --git a/core.fth b/core.fth index c23c366..a8ccb9d 100644 --- a/core.fth +++ b/core.fth @@ -199,5 +199,5 @@ : :noname 0 , here ] ; : evaluate _source @ >r _sourceu @ >r >in @ >r - 0 >in ! _sourceu ! _source ! 5 sys + 0 >in ! _sourceu ! _source ! _ev r> >in ! r> _sourceu ! r> _source ! ; diff --git a/libalee/corewords.cpp b/libalee/corewords.cpp index ced3973..b8a415e 100644 --- a/libalee/corewords.cpp +++ b/libalee/corewords.cpp @@ -17,6 +17,7 @@ */ #include "corewords.hpp" +#include "parser.hpp" #include #include @@ -171,10 +172,8 @@ execute: goto execute; case 25: // exit state.ip = state.popr(); - if (state.ip == 0) { - std::longjmp(state.jmpbuf, - static_cast(State::Error::exit)); - } + if (state.ip == 0) + std::longjmp(state.jmpbuf, static_cast(Error::exit)); break; case 26: // semic { @@ -206,6 +205,14 @@ execute: case 31: // _in state.input(state); break; + case 32: // _ex + { + const auto st = state.save(); + state.ip = 0; + Parser::parseSource(state); + state.load(st); + } + break; default: state.push(index - WordCount); break; diff --git a/libalee/corewords.hpp b/libalee/corewords.hpp index 70cbb30..33f4fc5 100644 --- a/libalee/corewords.hpp +++ b/libalee/corewords.hpp @@ -27,7 +27,7 @@ void user_sys(State&); class CoreWords { public: - constexpr static std::size_t WordCount = 32; + constexpr static std::size_t WordCount = 33; constexpr static Cell Immediate = (1 << 5); @@ -44,7 +44,7 @@ public: "<\0&\0|\0^\0" "<<\0>>\0:\0_'\0execute\0" "exit\0;\0_jmp0\0_jmp\0" - "depth\0_rdepth\0_in\0"; + "depth\0_rdepth\0_in\0_ev\0"; }; #endif // ALEEFORTH_COREWORDS_HPP diff --git a/libalee/parser.cpp b/libalee/parser.cpp index 3b14224..39695c4 100644 --- a/libalee/parser.cpp +++ b/libalee/parser.cpp @@ -22,7 +22,7 @@ #include -int Parser::parse(State& state, const char *str) +Error Parser::parse(State& state, const char *str) { auto addr = Dictionary::Input; state.dict.write(addr, 0); @@ -38,20 +38,20 @@ int Parser::parse(State& state, const char *str) return parseSource(state); } -int Parser::parseSource(State& state) +Error Parser::parseSource(State& state) { auto word = state.dict.input(); while (word.size() > 0) { - if (auto ret = parseWord(state, word); ret) + if (auto ret = parseWord(state, word); ret != Error::none) return ret; word = state.dict.input(); } - return 0; + return Error::none; } -int Parser::parseWord(State& state, Word word) +Error Parser::parseWord(State& state, Word word) { int ins, imm; @@ -71,13 +71,13 @@ int Parser::parseWord(State& state, Word word) if (state.compiling() && !imm) state.dict.add(ins); - else if (auto stat = state.execute(ins); stat != State::Error::none) - return static_cast(stat); + else if (auto stat = state.execute(ins); stat != Error::none) + return stat; - return 0; + return Error::none; } -int Parser::parseNumber(State& state, Word word) +Error Parser::parseNumber(State& state, Word word) { const auto base = state.dict.read(Dictionary::Base); DoubleCell result = 0; @@ -97,7 +97,7 @@ int Parser::parseNumber(State& state, Word word) result *= base; result += 10 + (c > 'a' ? c - 'a' : c - 'A'); } else { - return UnknownWord; + return Error::noword; } if (++i < word.wend) @@ -121,6 +121,6 @@ int Parser::parseNumber(State& state, Word word) state.push(value); } - return 0; + return Error::none; } diff --git a/libalee/parser.hpp b/libalee/parser.hpp index f211781..be6f3f7 100644 --- a/libalee/parser.hpp +++ b/libalee/parser.hpp @@ -26,14 +26,12 @@ class Parser { public: - constexpr static int UnknownWord = -1; - - static int parse(State&, const char *); - static int parseSource(State&); + static Error parse(State&, const char *); + static Error parseSource(State&); private: - static int parseWord(State&, Word); - static int parseNumber(State&, Word); + static Error parseWord(State&, Word); + static Error parseNumber(State&, Word); }; #endif // ALEEFORTH_PARSER_HPP diff --git a/libalee/state.cpp b/libalee/state.cpp index b3c98b1..bfd29d1 100644 --- a/libalee/state.cpp +++ b/libalee/state.cpp @@ -19,6 +19,7 @@ #include "corewords.hpp" #include "state.hpp" +#include #include bool State::compiling() const @@ -31,11 +32,25 @@ void State::compiling(bool yes) dict.write(Dictionary::Compiling, yes); } -State::Error State::execute(Addr addr) +std::pair State::save() { - auto stat = static_cast(setjmp(jmpbuf)); + std::pair st; + st.first = ip; + std::memcpy(st.second, jmpbuf, sizeof(std::jmp_buf)); + return st; +} + +void State::load(const std::pair& st) +{ + ip = st.first; + std::memcpy(jmpbuf, st.second, sizeof(std::jmp_buf)); +} + +Error State::execute(Addr addr) +{ + auto stat = static_cast(setjmp(jmpbuf)); - if (stat == State::Error::none) { + if (stat == Error::none) { CoreWords::run(addr, *this); if (ip >= Dictionary::Begin) { @@ -46,13 +61,24 @@ State::Error State::execute(Addr addr) // addr was a CoreWord, all done now. ip = 0; } - } else if (stat == State::Error::exit) { - stat = State::Error::none; + } else if (stat == Error::exit) { + stat = Error::none; } return stat; } +void State::reset() +{ + while (size()) + pop(); + while (rsize()) + popr(); + + dict.write(Dictionary::Compiling, 0); + ip = 0; +} + std::size_t State::size() const noexcept { return std::distance(dstack, static_cast(dsp)); diff --git a/libalee/state.hpp b/libalee/state.hpp index 648b868..325f405 100644 --- a/libalee/state.hpp +++ b/libalee/state.hpp @@ -24,6 +24,7 @@ #include #include +#include constexpr unsigned DataStackSize = 16; constexpr unsigned ReturnStackSize = 16; @@ -31,17 +32,6 @@ constexpr unsigned ReturnStackSize = 16; class State { public: - enum class Error : int { - none = 0, - push, - pop, - pushr, - popr, - top, - pick, - exit - }; - Addr ip = 0; Dictionary& dict; void (*input)(State&); @@ -54,7 +44,11 @@ public: bool compiling() const; void compiling(bool); + std::pair save(); + void load(const std::pair&); + Error execute(Addr); + void reset(); std::size_t size() const noexcept; std::size_t rsize() const noexcept; diff --git a/libalee/types.hpp b/libalee/types.hpp index 5b577f2..0a7f7ee 100644 --- a/libalee/types.hpp +++ b/libalee/types.hpp @@ -32,6 +32,18 @@ using Func = void (*)(State&); constexpr unsigned int MaxCellNumberChars = 6; // -32768 +enum class Error : int { + none = 0, + push, + pop, + pushr, + popr, + top, + pick, + exit, + noword +}; + struct Word { struct iterator;