diff --git a/Makefile b/Makefile index 30e210b..66d9132 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ msp430: alee-msp430 small: CXXFLAGS += -Os small: alee -fast: CXXFLAGS += -O3 -march=native -mtune=native +fast: CXXFLAGS += -O3 -march=native -mtune=native -flto fast: alee alee: $(LIBFILE) diff --git a/core.fth b/core.fth index 24ef536..1475224 100644 --- a/core.fth +++ b/core.fth @@ -19,7 +19,7 @@ : here 1 cells @ ; : allot 1 cells +! ; : _latest 2 cells ; -: imm _latest @ dup @ 1 5 << | swap ! ; +: imm _latest @ dup @ 1 6 << | swap ! ; : state 3 cells ; : postpone 1 4 cells ! ; imm : _input 5 cells ; @@ -46,7 +46,7 @@ : decimal 10 base ! ; : hex 16 base ! ; -: literal 0 , , ; imm +: literal 1 , , ; imm : ['] ' postpone literal ; imm : [ 0 state ! ; imm : ] 1 state ! ; @@ -151,7 +151,7 @@ : create align here bl word count nip cell+ allot align ['] _lit , here 3 cells + , ['] exit dup , , - dup @ 31 & over _latest @ - 6 << or over ! _latest ! ; + dup @ 31 & over _latest @ - 7 << or over ! _latest ! ; : _latword _latest @ dup @ 31 & + cell+ aligned ; : _does> _latword 2 cells + diff --git a/corewords.cpp b/corewords.cpp index 9043dba..1ee7928 100644 --- a/corewords.cpp +++ b/corewords.cpp @@ -36,7 +36,7 @@ void newdef(Dictionary& dict, Word word) dict.addDefinition(word); dict.write(addr, (dict.read(addr) & 0x1F) | - ((addr - dict.latest()) << 6)); + ((addr - dict.latest()) << 7)); dict.latest(addr); }; void tick(State& state) @@ -45,7 +45,7 @@ void tick(State& state) if (auto j = state.dict.find(word); j > 0) state.push(state.dict.getexec(j)); else if (auto i = CoreWords::findi(state, word); i >= 0) - state.push(i & ~CoreWords::Immediate); + state.push(((i & ~CoreWords::Immediate) << 1) | 1); else state.push(0); } @@ -56,14 +56,14 @@ void CoreWords::run(unsigned int index, State& state) DoubleCell dcell; execute: - switch (index) { - default: + if ((index & 1) == 0) { // must be calling a defined subroutine state.pushr(state.ip); state.ip = index; return; + } else switch ((index & 0x3E) >> 1) { case 0: // _lit - state.push(state.beyondip()); + state.push((index & 0xFF00) ? (index >> 8) - 1 : state.beyondip()); break; case 1: // drop state.pop(); @@ -165,7 +165,6 @@ execute: case 24: // execute index = state.pop(); goto execute; - break; case 25: // exit state.ip = state.popr(); if (state.ip == 0) { @@ -174,7 +173,7 @@ execute: } break; case 26: // semic - state.dict.add(findi("exit")); + state.dict.add((findi("exit") << 1) | 1); state.compiling(false); break; case 27: // _jmp0 @@ -213,17 +212,16 @@ execute: int CoreWords::findi(const char *word) { - const auto size = std::strlen(word); - std::size_t i; + std::size_t i = 0; int wordsi = 0; - for (i = 0; i < sizeof(wordsarr);) { + while (i < sizeof(wordsarr)) { auto end = i; - while (wordsarr[end] > '\1') + while (wordsarr[end]) ++end; - if (size == end - i && !std::strncmp(word, wordsarr + i, size)) - return wordsarr[end] == '\0' ? wordsi : (wordsi | Immediate); + if (!std::strcmp(word, wordsarr + i)) + return wordsi; ++wordsi; i = end + 1; @@ -234,16 +232,16 @@ int CoreWords::findi(const char *word) int CoreWords::findi(State& state, Word word) { - std::size_t i; + std::size_t i = 0; int wordsi = 0; - for (i = 0; i < sizeof(wordsarr);) { + while (i < sizeof(wordsarr)) { auto end = i; - while (wordsarr[end] > '\1') + while (wordsarr[end]) ++end; if (state.dict.equal(word, wordsarr + i, end - i)) - return wordsarr[end] == '\0' ? wordsi : (wordsi | Immediate); + return wordsi; ++wordsi; i = end + 1; diff --git a/corewords.hpp b/corewords.hpp index 020694f..56f7703 100644 --- a/corewords.hpp +++ b/corewords.hpp @@ -29,22 +29,22 @@ class CoreWords public: constexpr static std::size_t WordCount = 32; - constexpr static Cell Immediate = (1 << 5); + constexpr static Cell Immediate = (1 << 6); + + constexpr static int Semicolon = 26; static int findi(const char *); static int findi(State&, Word); static void run(unsigned int, State&); private: - // Ends with '\0': regular word - // Ends with '\1': compile-only word constexpr static char wordsarr[] = "_lit\0drop\0dup\0swap\0pick\0sys\0" "+\0-\0m*\0_/\0_%\0" "_@\0_!\0>r\0r>\0=\0" "<\0&\0|\0^\0" "<<\0>>\0:\0'\0execute\0" - "exit\0;\1_jmp0\0_jmp\0" + "exit\0;\0_jmp0\0_jmp\0" "depth\0_rdepth\0key\0"; }; diff --git a/dictionary.cpp b/dictionary.cpp index 199f3ed..fe19684 100644 --- a/dictionary.cpp +++ b/dictionary.cpp @@ -72,7 +72,7 @@ Addr Dictionary::find(Word word) noexcept if (equal(word, lw)) return lt; else - lt -= l >> 6; + lt -= l >> 7; } while (lt != oldlt); return 0; diff --git a/parser.cpp b/parser.cpp index 91c4e5c..7335f90 100644 --- a/parser.cpp +++ b/parser.cpp @@ -62,8 +62,9 @@ int Parser::parseWord(State& state, Word word) if (ins < 0) { return parseNumber(state, word); } else { - imm = ins & CoreWords::Immediate; + imm = ins == CoreWords::Semicolon; ins &= ~CoreWords::Immediate; + ins = (ins << 1) | 1; } } else { imm = state.dict.read(ins) & CoreWords::Immediate; @@ -97,8 +98,14 @@ int Parser::parseNumber(State& state, Word word) if (ec == std::errc() && ptr == buf + i) { if (state.compiling()) { - state.dict.add(CoreWords::findi("_lit")); - state.dict.add(l); + auto ins = (CoreWords::findi("_lit") << 1) | 1; + + if (l >= 0 && l < 0xFF) { + state.dict.add(ins | ((l + 1) << 8)); + } else { + state.dict.add(ins); + state.dict.add(l); + } } else { state.push(l); } diff --git a/state.cpp b/state.cpp index 8e0f78d..ea6c601 100644 --- a/state.cpp +++ b/state.cpp @@ -33,25 +33,24 @@ void State::compiling(bool yes) State::Error State::execute(Addr addr) { - auto stat = setjmp(jmpbuf); - if (!stat) { - if (addr < CoreWords::WordCount) { - CoreWords::run(addr, *this); - ip = 0; - } else { - auto ins = addr; + auto stat = static_cast(setjmp(jmpbuf)); + + if (stat == State::Error::none) { + CoreWords::run(addr, *this); - for (;;) { - CoreWords::run(ins, *this); - ins = dict.read(ip); - } + if (ip >= Dictionary::Begin) { + // longjmp will exit this loop. + for (;;) + CoreWords::run(dict.read(ip), *this); + } else { + // addr was a CoreWord, all done now. + ip = 0; } - } else { - auto err = static_cast(stat); - return err == State::Error::exit ? State::Error::none : err; + } else if (stat == State::Error::exit) { + stat = State::Error::none; } - return State::Error::none; + return stat; } std::size_t State::size() const noexcept diff --git a/state.hpp b/state.hpp index 76b3c67..28396dc 100644 --- a/state.hpp +++ b/state.hpp @@ -31,7 +31,7 @@ constexpr unsigned ReturnStackSize = 16; struct State { enum class Error : int { - none, + none = 0, push, pop, pushr,