You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

115 lines
4.8 KiB
C++

// sprit-forth: A portable subroutine-threaded Forth.
// Copyright (C) 2023 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.
10 months ago
#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
10 months ago
static void peek() { *sp() = *(Cell *)(*sp()); }
static void commaSP() { comma(pop()); }
static void discard() { auto v = pop(); (void)v; }
static void tobool() { if (*sp()) *sp() = -1; }
10 months ago
constinit WordSet words (
10 months ago
Word("[", WordWrap<[] { STATE = 0; }>).markImmediate(),
Word("]", WordWrap<[] { STATE = -1; }>),
Word("@", WordWrap<peek>),
Word("c@", WordWrap<peek, [] { *sp() &= 0xFF; }>),
Word("!", WordWrap<[] { auto a = (Cell *)pop(); *a = pop(); }>),
Word("c!", WordWrap<[] { auto a = (char *)pop(); *a = pop(); }>),
Word("_d", WordWrap<[] { *sp() += (Cell)DICT.data(); }>),
Word("_jmp", WordWrap<[] { jump((FuncList)*++IP); }>),
10 months ago
Word("_jmp0", WordWrap<[] {
++IP;
10 months ago
if (pop() == 0)
10 months ago
jump((FuncList)*IP);
10 months ago
}>),
Word(",", WordWrap<commaSP>),
Word("emit", WordWrap<[] { std::putchar(pop()); }>),
Word("key", WordWrap<[] { push(key()); }>),
Word("key?", WordWrap<[] { push(haskey()); }, tobool>),
Word("execute", WordWrap<[] { (void)executor((FuncList *)pop()); }>),
Word(":", WordWrap<colon>),
Word(";", WordWrap<semic>).markImmediate(),
10 months ago
Word("exit", fexit),
10 months ago
Word("drop", WordWrap<discard>),
Word("dup", WordWrap<[] { push(*sp()); }>),
Word("swap", WordWrap<[] { std::swap(*sp(), *(sp() - 1)); }>),
Word("pick", WordWrap<[] { auto t = *(sp() - *sp() - 1); *sp() = t; }>),
Word("cells", WordWrap<[] { *sp() *= sizeof(Cell); }>),
Word("+", WordWrap<[] { *(sp() - 1) += *sp(); }, discard>),
Word("-", WordWrap<[] { *(sp() - 1) -= *sp(); }, discard>),
Word("*", WordWrap<[] { *(sp() - 1) *= *sp(); }, discard>),
Word("/", WordWrap<[] { *(sp() - 1) /= *sp(); }, discard>),
Word("mod", WordWrap<[] { *(sp() - 1) %= *sp(); }, discard>),
Word("=", WordWrap<[] { *(sp() - 1) = *(sp() - 1) == *sp(); }, discard, tobool>),
Word("<", WordWrap<[] { *(sp() - 1) = *(sp() - 1) < *sp(); }, discard, tobool>),
Word("or", WordWrap<[] { *(sp() - 1) |= *sp(); }, discard>),
Word("and", WordWrap<[] { *(sp() - 1) &= *sp(); }, discard>),
Word("xor", WordWrap<[] { *(sp() - 1) ^= *sp(); }, discard>),
Word("lshift", WordWrap<[] { *(sp() - 1) <<= *sp(); }, discard>),
Word("rshift", WordWrap<[] { *(sp() - 1) >>= *sp(); }, discard>),
Word(">r", WordWrap<[] { rpush(pop()); }>),
Word("r>", WordWrap<[] { push(rpop()); }>),
Word("immediate", WordWrap<[] { ((Word *)LATEST)->markImmediate(); }>),
Word("aligned", WordWrap<[] { *sp() = aligned(*sp()); }>),
Word("align", WordWrap<align>),
Word("literal", WordWrap<[] { if (STATE) compileliteral(); }>).markImmediate(),
Word("\'", WordWrap<tick>),
Word("_i", WordWrap<[] { *sp() = ((Word *)*sp())->immediate(); }, tobool>),
Word("[']", WordWrap<tick, compileliteral>).markImmediate(),
Word("compile,", WordWrap<peek, commaSP>),
Word("word", WordWrap<word>),
10 months ago
Word("_b", WordWrap<[] {
std::putchar('#'); // Gives a good breakpoint spot for gdb
10 months ago
}>),
Word(".", WordWrap<[] { std::cout << pop() << ' '; }>)
10 months ago
);
void getinput()
{
std::string line;
if (std::cin.good()) {
std::getline(std::cin, line);
std::for_each(line.rbegin(), line.rend(), addkey);
}
}
int main()
{
initialize(words);
while (std::cin.good()) {
10 months ago
auto result = parse();
if (result == Error::none)
std::cout << (STATE ? "compiled" : "ok") << std::endl;
else
std::cout << "error " << static_cast<int>(result) << std::endl;
10 months ago
}
}