// sprit-forth: A portable subroutine-threaded Forth. // Copyright (C) 2024 Clyne Sullivan // // This library is free software; you can redistribute it and/or modify it // under the terms of the GNU Library General Public License as published by // the Free Software Foundation; either version 2 of the License, or (at your // option) any later version. // // This library is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS // FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for // more details. // // You should have received a copy of the GNU Library General Public License // along with this library; if not, write to the Free Software Foundation, Inc., // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. #include #include #include #include "core.hpp" #include "parse.hpp" #include "state.hpp" #include "types.hpp" // TODO: // sys m* _/ _% _' depth _rdepth _in _ev find _uma u< um/mod static void peek() { *Forth.sp = *(Cell *)(*Forth.sp); } static void commaSP() { comma(Forth.pop()); } static void discard() { auto v = Forth.pop(); (void)v; } static void tobool() { if (*Forth.sp) *Forth.sp = -1; } constinit std::array words { Word("[", WordWrap<[] { Forth.state = 0; }>).markImmediate(), Word("]", WordWrap<[] { Forth.state = -1; }>), Word("@", WordWrap), Word("c@", WordWrap), Word("!", WordWrap<[] { auto a = (Cell *)Forth.pop(); *a = Forth.pop(); }>), Word("c!", WordWrap<[] { auto a = (char *)Forth.pop(); *a = Forth.pop(); }>), Word("_d", WordWrap<[] { *Forth.sp += (Cell)Forth.dictdata(); }>), Word("_jmp", WordWrap<[] { jump((FuncList)*++Exec.ip); }>), Word("_jmp0", WordWrap<[] { ++Exec.ip; if (Forth.pop() == 0) jump((FuncList)*Exec.ip); }>), Word(",", WordWrap), Word("emit", WordWrap<[] { std::putchar(Forth.pop()); }>), Word("key", WordWrap<[] { Forth.push(key()); }>), Word("key?", WordWrap<[] { Forth.push(haskey()); }, tobool>), Word("execute", WordWrap<[] { (void)Exec.executor((FuncList *)Forth.pop()); }>), Word(":", WordWrap), Word(";", WordWrap).markImmediate(), Word("exit", fexit), Word("drop", WordWrap), Word("dup", WordWrap<[] { Forth.push(*Forth.sp); }>), Word("swap", WordWrap<[] { std::swap(*Forth.sp, *(Forth.sp - 1)); }>), Word("pick", WordWrap<[] { auto t = *(Forth.sp - *Forth.sp - 1); *Forth.sp = t; }>), Word("cells", WordWrap<[] { *Forth.sp *= sizeof(Cell); }>), Word("+", WordWrap<[] { *(Forth.sp - 1) += *Forth.sp; }, discard>), Word("-", WordWrap<[] { *(Forth.sp - 1) -= *Forth.sp; }, discard>), Word("*", WordWrap<[] { *(Forth.sp - 1) *= *Forth.sp; }, discard>), Word("/", WordWrap<[] { *(Forth.sp - 1) /= *Forth.sp; }, discard>), Word("mod", WordWrap<[] { *(Forth.sp - 1) %= *Forth.sp; }, discard>), Word("=", WordWrap<[] { *(Forth.sp - 1) = *(Forth.sp - 1) == *Forth.sp; }, discard, tobool>), Word("<", WordWrap<[] { *(Forth.sp - 1) = *(Forth.sp - 1) < *Forth.sp; }, discard, tobool>), Word("or", WordWrap<[] { *(Forth.sp - 1) |= *Forth.sp; }, discard>), Word("and", WordWrap<[] { *(Forth.sp - 1) &= *Forth.sp; }, discard>), Word("xor", WordWrap<[] { *(Forth.sp - 1) ^= *Forth.sp; }, discard>), Word("lshift", WordWrap<[] { *(Forth.sp - 1) <<= *Forth.sp; }, discard>), Word("rshift", WordWrap<[] { *(Forth.sp - 1) >>= *Forth.sp; }, discard>), Word(">r", WordWrap<[] { Forth.rpush(Forth.pop()); }>), Word("r>", WordWrap<[] { Forth.push(Forth.rpop()); }>), Word("immediate", WordWrap<[] { Forth.latest->markImmediate(); }>), Word("aligned", WordWrap<[] { *Forth.sp = aligned(*Forth.sp); }>), Word("align", WordWrap), Word("literal", WordWrap<[] { if (Forth.state) compileliteral(); }>).markImmediate(), Word("\'", WordWrap), Word("_i", WordWrap<[] { *Forth.sp = ((Word *)*Forth.sp)->immediate(); }, tobool>), Word("[']", WordWrap).markImmediate(), Word("compile,", WordWrap), Word("word", WordWrap), Word("_b", WordWrap<[] { std::putchar('#'); // Gives a good breakpoint spot for gdb }>), Word(".", WordWrap<[] { std::cout << Forth.pop() << ' '; }>) }; void getinput() { std::string line; if (std::cin.good()) { std::getline(std::cin, line); std::for_each(line.begin(), line.end(), addkey); } } int main() { std::for_each(words.begin(), words.end(), [](Word& w) { Forth.add(w); }); while (std::cin.good()) { auto result = parse(); if (result == Error::none) std::cout << (Forth.state ? "compiled" : "ok") << std::endl; else std::cout << "error " << static_cast(result) << std::endl; } }