|
|
|
// sprit-forth: A portable subroutine-threaded Forth.
|
|
|
|
// Copyright (C) 2024 Clyne Sullivan <clyne@bitgloo.com>
|
|
|
|
//
|
|
|
|
// 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 <algorithm>
|
|
|
|
#include <iostream>
|
|
|
|
#include <string>
|
|
|
|
|
|
|
|
#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<peek>),
|
|
|
|
Word("c@", WordWrap<peek, [] { *Forth.sp &= 0xFF; }>),
|
|
|
|
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<commaSP>),
|
|
|
|
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<colon>),
|
|
|
|
Word(";", WordWrap<semic>).markImmediate(),
|
|
|
|
Word("exit", fexit),
|
|
|
|
Word("drop", WordWrap<discard>),
|
|
|
|
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<align>),
|
|
|
|
Word("literal", WordWrap<[] { if (Forth.state) compileliteral(); }>).markImmediate(),
|
|
|
|
Word("\'", WordWrap<tick>),
|
|
|
|
Word("_i", WordWrap<[] { *Forth.sp = ((Word *)*Forth.sp)->immediate(); }, tobool>),
|
|
|
|
Word("[']", WordWrap<tick, compileliteral>).markImmediate(),
|
|
|
|
Word("compile,", WordWrap<peek, commaSP>),
|
|
|
|
Word("word", WordWrap<word>),
|
|
|
|
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<int>(result) << std::endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|