diff --git a/libalee/corewords.cpp b/libalee/corewords.cpp index 7c79aea..d47e092 100644 --- a/libalee/corewords.cpp +++ b/libalee/corewords.cpp @@ -27,9 +27,6 @@ static void pushd(State&, DoubleCell); LIBALEE_SECTION void CoreWords::run(Cell ins, State& state) { - Cell cell; - DoubleCell dcell; - Addr index = ins; auto& ip = state.ip(); @@ -40,191 +37,46 @@ execute: ip = index; return; } else switch (index) { - case token("_lit"): // Execution semantics of `literal`. - state.push(state.beyondip()); - break; - case token("drop"): - state.pop(); - break; - case token("dup"): - state.push(state.top()); - break; - case token("swap"): - std::swap(state.top(), state.pick(1)); - break; - case token("pick"): - state.push(state.pick(state.pop())); - break; - case token("sys"): // Calls user-defined "system" handler. - user_sys(state); - break; - case token("+"): - cell = state.pop(); - state.top() += cell; - break; - case token("-"): - cell = state.pop(); - state.top() -= cell; - break; - case token("m*"): // ( n n -- d ) - cell = state.pop(); - dcell = state.pop() * cell; - pushd(state, dcell); - break; - case token("_/"): // ( d n -- n ) - cell = state.pop(); - dcell = popd(state); - state.push(static_cast(dcell / cell)); - break; - case token("_%"): // ( d n -- n ) - cell = state.pop(); - dcell = popd(state); - state.push(static_cast(dcell % cell)); - break; - case token("_@"): // ( addr cell? -- n ) - if (state.pop()) - state.push(state.dict.read(state.pop())); - else - state.push(state.dict.readbyte(state.pop())); - break; - case token("_!"): // ( n addr cell? -- ) - cell = state.pop(); - if (auto addr = state.pop(); cell) - state.dict.write(addr, state.pop()); - else - state.dict.writebyte(addr, state.pop() & 0xFFu); - break; - case token(">r"): - state.pushr(state.pop()); - break; - case token("r>"): - state.push(state.popr()); - break; - case token("="): - cell = state.pop(); - state.top() = state.top() == cell ? -1 : 0; - break; - case token("<"): - cell = state.pop(); - state.top() = state.top() < cell ? -1 : 0; - break; - case token("&"): - cell = state.pop(); - state.top() &= cell; - break; - case token("|"): - cell = state.pop(); - state.top() |= cell; - break; - case token("^"): - cell = state.pop(); - state.top() ^= cell; - break; - case token("<<"): - cell = state.pop(); - reinterpret_cast(state.top()) <<= static_cast(cell); - break; - case token(">>"): - cell = state.pop(); - reinterpret_cast(state.top()) >>= static_cast(cell); - break; - case token(":"): // Begins definition/compilation of new word. - state.push(state.dict.alignhere()); - state.dict.write(Dictionary::CompToken, state.top()); - while (!state.dict.hasInput()) - state.input(); - state.dict.addDefinition(state.dict.input()); - state.compiling(true); - break; - case token("_'"): // Collects input word and finds execution token. - while (!state.dict.hasInput()) - state.input(); - find(state, state.dict.input()); - break; + case token("_lit"): word_lit(state); break;// Execution semantics of `literal`. + case token("drop"): word_drop(state); break; + case token("dup"): word_dup(state); break; + case token("swap"): word_swap(state); break; + case token("pick"): word_pick(state); break; + case token("sys"): word_sys(state); break; // Calls user-defined "system" handler. + case token("+"): word_add(state); break; + case token("-"): word_sub(state); break; + case token("m*"): word_mul(state); break; // ( n n -- d ) + case token("_/"): word_div(state); break; // ( d n -- n ) + case token("_%"): word_mod(state); break; // ( d n -- n ) + case token("_@"): word_peek(state); break; // ( addr cell? -- n ) + case token("_!"): word_poke(state); break; // ( n addr cell? -- ) + case token(">r"): word_rpush(state); break; + case token("r>"): word_rpop(state); break; + case token("="): word_eq(state); break; + case token("<"): word_lt(state); break; + case token("&"): word_and(state); break; + case token("|"): word_or(state); break; + case token("^"): word_xor(state); break; + case token("<<"): word_shl(state); break; + case token(">>"): word_shr(state); break; + case token(":"): word_colon(state); break; // Begins definition/compilation of new word. + case token("_'"): word_tick(state); break; // Collects input word and finds execution token. case token("execute"): + // TODO reimplement index = state.pop(); goto execute; - case token("exit"): - ip = state.popr(); - state.verify(ip != 0, Error::exit); - break; - case token(";"): // Concludes word definition. - state.dict.add(token("exit")); - state.compiling(false); - - cell = state.pop(); - dcell = cell - state.dict.latest(); - if (dcell >= Dictionary::MaxDistance) { - // Large distance to previous entry: store in dedicated cell. - state.dict.write(static_cast(cell) + sizeof(Cell), - static_cast(dcell)); - dcell = Dictionary::MaxDistance; - } - state.dict.write(cell, - (state.dict.read(cell) & 0x1F) | static_cast(dcell << 6)); - state.dict.latest(cell); - break; - case token("_jmp0"): // Jump if popped value equals zero. - if (state.pop()) { - state.beyondip(); - break; - } - [[fallthrough]]; - case token("_jmp"): // Unconditional jump. - ip = state.beyondip(); - return; - case token("depth"): - state.push(static_cast(state.size())); - break; - case token("_rdepth"): - state.push(static_cast(state.rsize())); - break; - case token("_in"): // Fetches more input from the user input source. - state.input(); - break; - case token("_ev"): // Evaluates words from current input source. - { - const auto st = state.save(); - ip = 0; - Parser::parseSource(state); - state.load(st); - } - break; - case token("find"): - cell = state.pop(); - find(state, - Word::fromLength(static_cast(cell + 1), - state.dict.readbyte(cell))); - break; - case token("_uma"): // ( d u u -- d ): Unsigned multiply-add. - { - const auto plus = state.pop(); - cell = state.pop(); - dcell = popd(state); - dcell *= static_cast(cell); - dcell += static_cast(plus); - pushd(state, dcell); - } - break; - case token("u<"): - cell = state.pop(); - state.top() = static_cast(state.top()) < - static_cast(cell) ? -1 : 0; - break; - case token("um/mod"): - cell = state.pop(); - dcell = popd(state); - - state.push(static_cast( - static_cast(dcell) % - static_cast(cell))); - state.push(static_cast( - static_cast(dcell) / - static_cast(cell))); - break; - default: // Compacted literals (WordCount <= ins < Begin). - state.push(ins - WordCount); - break; + case token("exit"): word_exit(state); break; + case token(";"): word_semic(state); break; // Concludes word definition. + case token("_jmp0"): word_jmp0(state); break; // Jump if popped value equals zero. + case token("_jmp"): word_jmp(state); break; // Unconditional jump. + case token("depth"): word_depth(state); break; + case token("_rdepth"): word_rdepth(state); break; + case token("_in"): word_in(state); break; // Fetches more input from the user input source. + case token("_ev"): word_ev(state); break; // Evaluates words from current input source. + case token("find"): word_find(state); break; + case token("_uma"): word_uma(state); break; // ( d u u -- d ): Unsigned multiply-add. + case token("u<"): word_ult(state); break; + case token("um/mod"): word_ummod(state); break; } ip += sizeof(Cell); @@ -267,3 +119,184 @@ void pushd(State& s, DoubleCell d) s.push(static_cast(d >> (sizeof(Cell) * 8))); } +void CoreWords::word_lit(State& state) { // Execution semantics of `literal`. + state.push(state.beyondip()); +} +void CoreWords::word_drop(State& state) { + state.pop(); +} +void CoreWords::word_dup(State& state) { + state.push(state.top()); +} +void CoreWords::word_swap(State& state) { + std::swap(state.top(), state.pick(1)); +} +void CoreWords::word_pick(State& state) { + state.push(state.pick(state.pop())); +} +void CoreWords::word_sys(State& state) { // Calls user-defined "system" handler. + user_sys(state); +} +void CoreWords::word_add(State& state) { + auto cell = state.pop(); + state.top() += cell; +} +void CoreWords::word_sub(State& state) { + auto cell = state.pop(); + state.top() -= cell; +} +void CoreWords::word_mul(State& state) { // ( n n -- d ) + auto cell = state.pop(); + auto dcell = state.pop() * cell; + pushd(state, dcell); +} +void CoreWords::word_div(State& state) { // ( d n -- n ) + auto cell = state.pop(); + auto dcell = popd(state); + state.push(static_cast(dcell / cell)); +} +void CoreWords::word_mod(State& state) { // ( d n -- n ) + auto cell = state.pop(); + auto dcell = popd(state); + state.push(static_cast(dcell % cell)); +} +void CoreWords::word_peek(State& state) { // ( addr cell? -- n ) + if (state.pop()) + state.push(state.dict.read(state.pop())); + else + state.push(state.dict.readbyte(state.pop())); +} +void CoreWords::word_poke(State& state) { // ( n addr cell? -- ) + auto cell = state.pop(); + if (auto addr = state.pop(); cell) + state.dict.write(addr, state.pop()); + else + state.dict.writebyte(addr, state.pop() & 0xFFu); +} +void CoreWords::word_rpush(State& state) { + state.pushr(state.pop()); +} +void CoreWords::word_rpop(State& state) { + state.push(state.popr()); +} +void CoreWords::word_eq(State& state) { + auto cell = state.pop(); + state.top() = state.top() == cell ? -1 : 0; +} +void CoreWords::word_lt(State& state) { + auto cell = state.pop(); + state.top() = state.top() < cell ? -1 : 0; +} +void CoreWords::word_and(State& state) { + auto cell = state.pop(); + state.top() &= cell; +} +void CoreWords::word_or(State& state) { + auto cell = state.pop(); + state.top() |= cell; +} +void CoreWords::word_xor(State& state) { + auto cell = state.pop(); + state.top() ^= cell; +} +void CoreWords::word_shl(State& state) { + auto cell = state.pop(); + reinterpret_cast(state.top()) <<= static_cast(cell); +} +void CoreWords::word_shr(State& state) { + auto cell = state.pop(); + reinterpret_cast(state.top()) >>= static_cast(cell); +} +void CoreWords::word_colon(State& state) { // Begins definition/compilation of new word. + state.push(state.dict.alignhere()); + state.dict.write(Dictionary::CompToken, state.top()); + while (!state.dict.hasInput()) + state.input(); + state.dict.addDefinition(state.dict.input()); + state.compiling(true); +} +void CoreWords::word_tick(State& state) { // Collects input word and finds execution token. + while (!state.dict.hasInput()) + state.input(); + find(state, state.dict.input()); +} +void CoreWords::word_execute(State& state) { + /*index =*/ state.pop(); + /* TODO goto execute; */ +} +void CoreWords::word_exit(State& state) { + state.ip() = state.popr(); + state.verify(state.ip() != 0, Error::exit); +} +void CoreWords::word_semic(State& state) { // Concludes word definition. + state.dict.add(token("exit")); + state.compiling(false); + + auto cell = state.pop(); + auto dcell = cell - state.dict.latest(); + if (dcell >= Dictionary::MaxDistance) { + // Large distance to previous entry: store in dedicated cell. + state.dict.write(static_cast(cell) + sizeof(Cell), + static_cast(dcell)); + dcell = Dictionary::MaxDistance; + } + state.dict.write(cell, + (state.dict.read(cell) & 0x1F) | static_cast(dcell << 6)); + state.dict.latest(cell); +} +void CoreWords::word_jmp0(State& state) { // Jump if popped value equals zero. + if (state.pop()) { + state.beyondip(); + } else { + state.ip() = static_cast(state.beyondip() - sizeof(Cell)); + } +} +void CoreWords::word_jmp(State& state) { // Unconditional jump. + state.ip() = static_cast(state.beyondip() - sizeof(Cell)); +} +void CoreWords::word_depth(State& state) { + state.push(static_cast(state.size())); +} +void CoreWords::word_rdepth(State& state) { + state.push(static_cast(state.rsize())); +} +void CoreWords::word_in(State& state) { // Fetches more input from the user input source. + state.input(); +} +void CoreWords::word_ev(State& state) { // Evaluates words from current input source. + const auto st = state.save(); + state.ip() = 0; + Parser::parseSource(state); + state.load(st); +} +void CoreWords::word_find(State& state) { + auto cell = state.pop(); + find(state, + Word::fromLength(static_cast(cell + 1), + state.dict.readbyte(cell))); +} +void CoreWords::word_uma(State& state) { // ( d u u -- d ): Unsigned multiply-add. + const auto plus = state.pop(); + auto cell = state.pop(); + auto dcell = popd(state); + dcell *= static_cast(cell); + dcell += static_cast(plus); + pushd(state, dcell); +} +void CoreWords::word_ult(State& state) { + auto cell = state.pop(); + state.top() = static_cast(state.top()) < + static_cast(cell) ? -1 : 0; +} +void CoreWords::word_ummod(State& state) { + auto cell = state.pop(); + auto dcell = popd(state); + + state.push(static_cast( + static_cast(dcell) % + static_cast(cell))); + state.push(static_cast( + static_cast(dcell) / + static_cast(cell))); +} + diff --git a/libalee/corewords.hpp b/libalee/corewords.hpp index 30d0a42..959d2e8 100644 --- a/libalee/corewords.hpp +++ b/libalee/corewords.hpp @@ -113,6 +113,44 @@ private: return -1; } + + static void word_lit(State&); + static void word_drop(State&); + static void word_dup(State&); + static void word_swap(State&); + static void word_pick(State&); + static void word_sys(State&); + static void word_add(State&); + static void word_sub(State&); + static void word_mul(State&); + static void word_div(State&); + static void word_mod(State&); + static void word_peek(State&); + static void word_poke(State&); + static void word_rpush(State&); + static void word_rpop(State&); + static void word_eq(State&); + static void word_lt(State&); + static void word_and(State&); + static void word_or(State&); + static void word_xor(State&); + static void word_shl(State&); + static void word_shr(State&); + static void word_colon(State&); + static void word_tick(State&); + static void word_execute(State&); + static void word_exit(State&); + static void word_semic(State&); + static void word_jmp0(State&); + static void word_jmp(State&); + static void word_depth(State&); + static void word_rdepth(State&); + static void word_in(State&); + static void word_ev(State&); + static void word_find(State&); + static void word_uma(State&); + static void word_ult(State&); + static void word_ummod(State&); }; #endif // ALEEFORTH_COREWORDS_HPP