|
|
|
@ -110,7 +110,7 @@ struct forth : public word_list
|
|
|
|
|
return *rp++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
forth& add(std::string_view name, func entry = nullptr) {
|
|
|
|
|
auto begin_def(std::string_view name) -> word_base * {
|
|
|
|
|
const auto namesz = (name.size() + 1 + sizeof(cell) - 1) & ~(sizeof(cell) - 1);
|
|
|
|
|
const auto size = (sizeof(word_base) + namesz) / sizeof(cell);
|
|
|
|
|
|
|
|
|
@ -118,12 +118,12 @@ struct forth : public word_list
|
|
|
|
|
//assert<error::dictionary_overflow>(state->here + size < &dictionary.back());
|
|
|
|
|
|
|
|
|
|
const auto h = std::exchange(here, here + size);
|
|
|
|
|
next = new (h) word_base (next, namesz);
|
|
|
|
|
auto def = new (h) word_base (next, namesz);
|
|
|
|
|
std::copy(name.begin(), name.end(),
|
|
|
|
|
std::bit_cast<char *>(h) + sizeof(word_base));
|
|
|
|
|
if (entry)
|
|
|
|
|
*here++ = std::bit_cast<cell>(entry);
|
|
|
|
|
return *this;
|
|
|
|
|
|
|
|
|
|
compiling = true;
|
|
|
|
|
return def;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto parse() -> std::string_view {
|
|
|
|
@ -197,6 +197,8 @@ constexpr auto initialize()
|
|
|
|
|
fthp->ip = fthp->rpop();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
constexpr static func comma = [](auto) { *fthp->here++ = fthp->pop(); };
|
|
|
|
|
|
|
|
|
|
constexpr static func lit_impl = [](auto) {
|
|
|
|
|
auto ptr = std::bit_cast<cell *>(++fthp->ip);
|
|
|
|
|
fthp->push(*ptr);
|
|
|
|
@ -213,6 +215,7 @@ constexpr auto initialize()
|
|
|
|
|
, S{"DEPTH"}, [](auto) { fthp->push(std::distance(fthp->sp, fthp->dstack.end())); }, 0
|
|
|
|
|
, S{"UNUSED"}, [](auto) { fthp->push(sizeof(cell) * std::distance(fthp->here, fthp->dict.end())); }, 0
|
|
|
|
|
, S{"_LIT" }, lit_impl, 0
|
|
|
|
|
, S{"," }, comma, 0
|
|
|
|
|
, S{"SWAP" }, [](auto) { auto a = fthp->pop(); auto b = fthp->pop(); fthp->push(a, b); }, 0
|
|
|
|
|
, S{"DROP" }, [](auto) { fthp->pop(); }, 0
|
|
|
|
|
, S{"DUP" }, [](auto) { fthp->push(fthp->top()); }, 0
|
|
|
|
@ -260,16 +263,26 @@ constexpr auto initialize()
|
|
|
|
|
addr v = fthp->pop();
|
|
|
|
|
addr w = fthp->pop();
|
|
|
|
|
fthp->push(-(w < v)); }, 0
|
|
|
|
|
, S{"FIND" }, [](auto) {
|
|
|
|
|
const auto caddr = std::bit_cast<const char *>(fthp->pop());
|
|
|
|
|
std::string_view w {caddr + 1, std::bit_cast<unsigned char>(caddr[0])};
|
|
|
|
|
if (auto g = fthp->get(w); !g.has_value())
|
|
|
|
|
fthp->push(std::bit_cast<cell>(caddr), 0);
|
|
|
|
|
else
|
|
|
|
|
fthp->push(std::bit_cast<cell>((*g)->body()), (*g)->is_immediate() ? 1 : -1); }, 0
|
|
|
|
|
, S{"\'" }, [](auto) {
|
|
|
|
|
auto w = fthp->parse();
|
|
|
|
|
auto g = fthp->get(w);
|
|
|
|
|
fthp->push(g ? std::bit_cast<cell>((*g)->body()) : 0); }, 0
|
|
|
|
|
, S{":" }, [](auto) {
|
|
|
|
|
auto w = fthp->parse();
|
|
|
|
|
fthp->add(w);
|
|
|
|
|
*fthp->here++ = std::bit_cast<cell>(prologue);
|
|
|
|
|
fthp->compiling = true; }, 0
|
|
|
|
|
, S{";" }, [](auto) { *fthp->here++ = 0; fthp->compiling = false; }, word_base::immediate
|
|
|
|
|
auto d = std::bit_cast<func *>(fthp->begin_def(w));
|
|
|
|
|
fthp->rpush(d);
|
|
|
|
|
*fthp->here++ = std::bit_cast<cell>(prologue); }, 0
|
|
|
|
|
, S{";" }, [](auto) {
|
|
|
|
|
*fthp->here++ = 0;
|
|
|
|
|
fthp->next = std::bit_cast<word_base *>(fthp->rpop());
|
|
|
|
|
fthp->compiling = false; }, word_base::immediate
|
|
|
|
|
, S{"\\" }, [](auto) { fthp->sourcei = std::string_view::npos; }, word_base::immediate
|
|
|
|
|
, S{"CELL" }, [](auto) { fthp->push(sizeof(cell)); }, 0
|
|
|
|
|
, S{"_JMP" }, [](auto) {
|
|
|
|
@ -285,7 +298,14 @@ constexpr auto initialize()
|
|
|
|
|
auto w = fthp->parse();
|
|
|
|
|
auto g = fthp->get(w);
|
|
|
|
|
assert<error::word_not_found>(g.has_value());
|
|
|
|
|
*fthp->here++ = std::bit_cast<cell>((*g)->body()); }, word_base::immediate
|
|
|
|
|
|
|
|
|
|
if ((*g)->is_immediate()) {
|
|
|
|
|
*fthp->here++ = std::bit_cast<cell>((*g)->body());
|
|
|
|
|
} else {
|
|
|
|
|
*fthp->here++ = std::bit_cast<cell>(&lit_impl);
|
|
|
|
|
*fthp->here++ = std::bit_cast<cell>((*g)->body());
|
|
|
|
|
*fthp->here++ = std::bit_cast<cell>(&comma);
|
|
|
|
|
} }, word_base::immediate
|
|
|
|
|
, S{"SOURCE"}, [](auto) {
|
|
|
|
|
auto len = 0u;
|
|
|
|
|
while (fthp->source[len])
|
|
|
|
@ -298,8 +318,18 @@ constexpr auto initialize()
|
|
|
|
|
fthp->push(fthp->source[fthp->sourcei++]);
|
|
|
|
|
else
|
|
|
|
|
fthp->push(0); }, 0
|
|
|
|
|
, S{"EVALUATE"}, [](auto) {
|
|
|
|
|
const auto u = std::bit_cast<addr>(fthp->pop());
|
|
|
|
|
const auto caddr = std::bit_cast<const char *>(fthp->pop());
|
|
|
|
|
const auto olds = fthp->source;
|
|
|
|
|
const auto oldi = fthp->sourcei;
|
|
|
|
|
fthp->parse_line({caddr, u});
|
|
|
|
|
fthp->source = olds;
|
|
|
|
|
fthp->sourcei = oldi; }, 0
|
|
|
|
|
>::word;
|
|
|
|
|
constexpr static auto& dict2 = comp_dict<prologue, &dict1
|
|
|
|
|
, S{"RECURSE"}, S{"R> R> DUP >R SWAP >R >XT ,"}, word_base::immediate
|
|
|
|
|
, S{">XT" }, S{"CELL+ DUP @ 127 AND + CELL+"}, 0
|
|
|
|
|
, S{"ALIGN" }, S{"HERE DUP ALIGNED SWAP - ALLOT"}, 0
|
|
|
|
|
, S{"ALIGNED"}, S{"CELL 1- + CELL 1- INVERT AND"}, 0
|
|
|
|
|
, S{"DECIMAL"}, S{"10 BASE !"}, 0
|
|
|
|
@ -309,12 +339,14 @@ constexpr auto initialize()
|
|
|
|
|
, S{"2@" }, S{"DUP CELL+ @ SWAP @"}, 0
|
|
|
|
|
, S{"C," }, S{"HERE C! 1 ALLOT"}, 0
|
|
|
|
|
, S{"EXIT" }, S{"0 ,"}, word_base::immediate
|
|
|
|
|
, S{"," }, S{"HERE ! CELL ALLOT"}, 0
|
|
|
|
|
, S{"ALLOT" }, S{"DP +!"}, 0
|
|
|
|
|
, S{"+!" }, S{"DUP >R SWAP R> @ + SWAP !"}, 0
|
|
|
|
|
, S{"2SWAP" }, S{"ROT >R ROT R>"}, 0
|
|
|
|
|
, S{"2DUP" }, S{"OVER OVER"}, 0
|
|
|
|
|
, S{"2OVER" }, S{"3 PICK 3 PICK"}, 0
|
|
|
|
|
, S{"2R>" }, S{"R> R> R> ROT >R SWAP"}, 0
|
|
|
|
|
, S{"2>R" }, S{"R> -ROT SWAP >R >R >R"}, 0
|
|
|
|
|
, S{"R@" }, S{"R> R> DUP >R SWAP >R"}, 0
|
|
|
|
|
, S{">R" }, S{"RP@ CELL - RP ! RP@ CELL+ @ RP@ ! RP@ CELL+ !"}, 0
|
|
|
|
|
, S{"R>" }, S{"RP@ @ RP@ CELL+ RP ! RP@ @ SWAP RP@ !"}, 0
|
|
|
|
|
, S{"OVER" }, S{"1 PICK"}, 0
|
|
|
|
|