aboutsummaryrefslogtreecommitdiffstats
path: root/sprit.cpp
blob: faab0848007440a3c718cdb1a446d5b949447fa5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
// 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;
    }
}