|
|
@ -144,7 +144,7 @@ struct forth : public word_list
|
|
|
|
push(*n);
|
|
|
|
push(*n);
|
|
|
|
|
|
|
|
|
|
|
|
if (compiling)
|
|
|
|
if (compiling)
|
|
|
|
execute((*get("literal"))->body());
|
|
|
|
execute((*get("LITERAL"))->body());
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
auto body = (*ent)->body();
|
|
|
|
auto body = (*ent)->body();
|
|
|
|
|
|
|
|
|
|
|
@ -203,44 +203,55 @@ constexpr auto initialize()
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
constexpr static auto& dict1 = native_dict<
|
|
|
|
constexpr static auto& dict1 = native_dict<
|
|
|
|
S{"_d" }, [](auto) { fthp->push(std::bit_cast<cell>(fthp)); }, 0
|
|
|
|
S{"_D" }, [](auto) { fthp->push(std::bit_cast<cell>(fthp)); }, 0
|
|
|
|
, S{"sp" }, [](auto) { fthp->push(std::bit_cast<cell>(fthp) + sizeof(cell)); }, 0
|
|
|
|
, S{"SP" }, [](auto) { fthp->push(std::bit_cast<cell>(fthp) + sizeof(cell)); }, 0
|
|
|
|
, S{"rp" }, [](auto) { fthp->push(std::bit_cast<cell>(fthp) + 2 * sizeof(cell)); }, 0
|
|
|
|
, S{"RP" }, [](auto) { fthp->push(std::bit_cast<cell>(fthp) + 2 * sizeof(cell)); }, 0
|
|
|
|
, S{"ip" }, [](auto) { fthp->push(std::bit_cast<cell>(fthp) + 3 * sizeof(cell)); }, 0
|
|
|
|
, S{"IP" }, [](auto) { fthp->push(std::bit_cast<cell>(fthp) + 3 * sizeof(cell)); }, 0
|
|
|
|
, S{"dp" }, [](auto) { fthp->push(std::bit_cast<cell>(fthp) + 4 * sizeof(cell)); }, 0
|
|
|
|
, S{"DP" }, [](auto) { fthp->push(std::bit_cast<cell>(fthp) + 4 * sizeof(cell)); }, 0
|
|
|
|
, S{"state"}, [](auto) { fthp->push(std::bit_cast<cell>(fthp) + 7 * sizeof(cell)); }, 0
|
|
|
|
, S{"STATE"}, [](auto) { fthp->push(std::bit_cast<cell>(fthp) + 7 * sizeof(cell)); }, 0
|
|
|
|
, S{"base" }, [](auto) { fthp->push(std::bit_cast<cell>(fthp) + 8 * sizeof(cell)); }, 0
|
|
|
|
, S{"BASE" }, [](auto) { fthp->push(std::bit_cast<cell>(fthp) + 8 * sizeof(cell)); }, 0
|
|
|
|
, S{"depth"}, [](auto) { fthp->push(std::distance(fthp->sp, fthp->dstack.end())); }, 0
|
|
|
|
, 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{"UNUSED"}, [](auto) { fthp->push(sizeof(cell) * std::distance(fthp->here, fthp->dict.end())); }, 0
|
|
|
|
, S{"_lit" }, lit_impl, 0
|
|
|
|
, S{"_LIT" }, lit_impl, 0
|
|
|
|
, S{"swap" }, [](auto) { auto a = fthp->pop(); auto b = fthp->pop(); fthp->push(a, b); }, 0
|
|
|
|
, S{"SWAP" }, [](auto) { auto a = fthp->pop(); auto b = fthp->pop(); fthp->push(a, b); }, 0
|
|
|
|
, S{"drop" }, [](auto) { fthp->pop(); }, 0
|
|
|
|
, S{"DROP" }, [](auto) { fthp->pop(); }, 0
|
|
|
|
, S{"dup" }, [](auto) { fthp->push(fthp->top()); }, 0
|
|
|
|
, S{"DUP" }, [](auto) { fthp->push(fthp->top()); }, 0
|
|
|
|
, S{"rot" }, [](auto) { auto a = fthp->pop(); auto b = fthp->pop(); auto c = fthp->pop();
|
|
|
|
, S{"ROT" }, [](auto) { auto a = fthp->pop(); auto b = fthp->pop(); auto c = fthp->pop();
|
|
|
|
fthp->push(b, a, c); }, 0
|
|
|
|
fthp->push(b, a, c); }, 0
|
|
|
|
, S{"+" }, [](auto) { fthp->top() += fthp->pop(); }, 0
|
|
|
|
, S{"+" }, [](auto) { fthp->top() += fthp->pop(); }, 0
|
|
|
|
, S{"-" }, [](auto) { fthp->top() -= fthp->pop(); }, 0
|
|
|
|
, S{"-" }, [](auto) { fthp->top() -= fthp->pop(); }, 0
|
|
|
|
, S{"*" }, [](auto) { fthp->top() *= fthp->pop(); }, 0
|
|
|
|
, S{"*" }, [](auto) { fthp->top() *= fthp->pop(); }, 0
|
|
|
|
, S{"/" }, [](auto) { fthp->top() /= fthp->pop(); }, 0
|
|
|
|
, S{"/" }, [](auto) { fthp->top() /= fthp->pop(); }, 0
|
|
|
|
, S{"mod" }, [](auto) { fthp->top() %= fthp->pop(); }, 0
|
|
|
|
, S{"MOD" }, [](auto) { fthp->top() %= fthp->pop(); }, 0
|
|
|
|
, S{"and" }, [](auto) { fthp->top() &= fthp->pop(); }, 0
|
|
|
|
, S{"AND" }, [](auto) { fthp->top() &= fthp->pop(); }, 0
|
|
|
|
, S{"or" }, [](auto) { fthp->top() |= fthp->pop(); }, 0
|
|
|
|
, S{"OR" }, [](auto) { fthp->top() |= fthp->pop(); }, 0
|
|
|
|
, S{"xor" }, [](auto) { fthp->top() ^= fthp->pop(); }, 0
|
|
|
|
, S{"XOR" }, [](auto) { fthp->top() ^= fthp->pop(); }, 0
|
|
|
|
, S{"lshift"}, [](auto) { fthp->top() <<= fthp->pop(); }, 0
|
|
|
|
, S{"LSHIFT"}, [](auto) { fthp->top() <<= fthp->pop(); }, 0
|
|
|
|
, S{"rshift"}, [](auto) { fthp->top() >>= fthp->pop(); }, 0
|
|
|
|
, S{"RSHIFT"}, [](auto) {
|
|
|
|
|
|
|
|
const auto shift = fthp->pop();
|
|
|
|
|
|
|
|
addr val = fthp->pop();
|
|
|
|
|
|
|
|
val >>= shift;
|
|
|
|
|
|
|
|
fthp->push(val); }, 0
|
|
|
|
, S{"[" }, [](auto) { fthp->compiling = false; }, word_base::immediate
|
|
|
|
, S{"[" }, [](auto) { fthp->compiling = false; }, word_base::immediate
|
|
|
|
, S{"]" }, [](auto) { fthp->compiling = true; }, 0
|
|
|
|
, S{"]" }, [](auto) { fthp->compiling = true; }, 0
|
|
|
|
, S{"immediate"}, [](auto) { const_cast<word_base *>(fthp->next)->make_immediate(); }, 0
|
|
|
|
, S{"IMMEDIATE"}, [](auto) { const_cast<word_base *>(fthp->next)->make_immediate(); }, 0
|
|
|
|
, S{"literal"}, [](auto) {
|
|
|
|
, S{"LITERAL"}, [](auto x) {
|
|
|
|
//assert<error::compile_only_word>(fthp->compiling);
|
|
|
|
if (fthp->compiling) {
|
|
|
|
*fthp->here++ = std::bit_cast<cell>(&lit_impl);
|
|
|
|
*fthp->here++ = std::bit_cast<cell>(&lit_impl);
|
|
|
|
*fthp->here++ = fthp->pop(); }, word_base::immediate
|
|
|
|
*fthp->here++ = fthp->pop();
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
lit_impl(x);
|
|
|
|
|
|
|
|
} }, word_base::immediate
|
|
|
|
, S{"@" }, [](auto) { fthp->push(*std::bit_cast<cell *>(fthp->pop())); }, 0
|
|
|
|
, S{"@" }, [](auto) { fthp->push(*std::bit_cast<cell *>(fthp->pop())); }, 0
|
|
|
|
, S{"!" }, [](auto) { auto p = fthp->pop(); *std::bit_cast<cell *>(p) = fthp->pop(); }, 0
|
|
|
|
, S{"!" }, [](auto) { auto p = fthp->pop(); *std::bit_cast<cell *>(p) = fthp->pop(); }, 0
|
|
|
|
, S{"c@" }, [](auto) { fthp->push(*std::bit_cast<char *>(fthp->pop())); }, 0
|
|
|
|
, S{"C@" }, [](auto) { fthp->push(*std::bit_cast<char *>(fthp->pop())); }, 0
|
|
|
|
, S{"c!" }, [](auto) { auto p = fthp->pop(); *std::bit_cast<char *>(p) = fthp->pop(); }, 0
|
|
|
|
, S{"C!" }, [](auto) { auto p = fthp->pop(); *std::bit_cast<char *>(p) = fthp->pop(); }, 0
|
|
|
|
, S{"=" }, [](auto) { auto v = fthp->pop(); fthp->top() = -(fthp->top() == v); }, 0
|
|
|
|
, S{"=" }, [](auto) { auto v = fthp->pop(); fthp->top() = -(fthp->top() == v); }, 0
|
|
|
|
, S{"<" }, [](auto) { auto v = fthp->pop(); fthp->top() = -(fthp->top() < v); }, 0
|
|
|
|
, S{"<" }, [](auto) { auto v = fthp->pop(); fthp->top() = -(fthp->top() < v); }, 0
|
|
|
|
|
|
|
|
, S{"U<" }, [](auto) {
|
|
|
|
|
|
|
|
addr v = fthp->pop();
|
|
|
|
|
|
|
|
addr w = fthp->pop();
|
|
|
|
|
|
|
|
fthp->push(-(w < v)); }, 0
|
|
|
|
, S{"\'" }, [](auto) {
|
|
|
|
, S{"\'" }, [](auto) {
|
|
|
|
auto w = fthp->parse();
|
|
|
|
auto w = fthp->parse();
|
|
|
|
auto g = fthp->get(w);
|
|
|
|
auto g = fthp->get(w);
|
|
|
@ -252,76 +263,76 @@ constexpr auto initialize()
|
|
|
|
fthp->compiling = true; }, 0
|
|
|
|
fthp->compiling = true; }, 0
|
|
|
|
, S{";" }, [](auto) { *fthp->here++ = 0; fthp->compiling = false; }, word_base::immediate
|
|
|
|
, S{";" }, [](auto) { *fthp->here++ = 0; fthp->compiling = false; }, word_base::immediate
|
|
|
|
, S{"\\" }, [](auto) { fthp->sourcei = std::string_view::npos; }, word_base::immediate
|
|
|
|
, S{"\\" }, [](auto) { fthp->sourcei = std::string_view::npos; }, word_base::immediate
|
|
|
|
, S{"cell" }, [](auto) { fthp->push(sizeof(cell)); }, 0
|
|
|
|
, S{"CELL" }, [](auto) { fthp->push(sizeof(cell)); }, 0
|
|
|
|
, S{"_jmp" }, [](auto) {
|
|
|
|
, S{"_JMP" }, [](auto) {
|
|
|
|
auto ptr = ++fthp->ip;
|
|
|
|
auto ptr = ++fthp->ip;
|
|
|
|
fthp->ip = *std::bit_cast<func **>(ptr) - 1; }, 0
|
|
|
|
fthp->ip = *std::bit_cast<func **>(ptr) - 1; }, 0
|
|
|
|
, S{"_jmp0"}, [](auto) {
|
|
|
|
, S{"_JMP0"}, [](auto) {
|
|
|
|
auto ptr = ++fthp->ip;
|
|
|
|
auto ptr = ++fthp->ip;
|
|
|
|
if (fthp->pop() == 0)
|
|
|
|
if (fthp->pop() == 0)
|
|
|
|
fthp->ip = *std::bit_cast<func **>(ptr) - 1; }, 0
|
|
|
|
fthp->ip = *std::bit_cast<func **>(ptr) - 1; }, 0
|
|
|
|
, S{"chars"}, [](auto) {}, 0
|
|
|
|
, S{"CHARS"}, [](auto) {}, 0
|
|
|
|
, S{"postpone"}, [](auto) {
|
|
|
|
, S{"POSTPONE"}, [](auto) {
|
|
|
|
assert<error::compile_only_word>(fthp->compiling);
|
|
|
|
assert<error::compile_only_word>(fthp->compiling);
|
|
|
|
auto w = fthp->parse();
|
|
|
|
auto w = fthp->parse();
|
|
|
|
auto g = fthp->get(w);
|
|
|
|
auto g = fthp->get(w);
|
|
|
|
assert<error::word_not_found>(g.has_value());
|
|
|
|
assert<error::word_not_found>(g.has_value());
|
|
|
|
*fthp->here++ = std::bit_cast<cell>((*g)->body()); }, word_base::immediate
|
|
|
|
*fthp->here++ = std::bit_cast<cell>((*g)->body()); }, word_base::immediate
|
|
|
|
, S{"source"}, [](auto) {
|
|
|
|
, S{"SOURCE"}, [](auto) {
|
|
|
|
auto len = 0u;
|
|
|
|
auto len = 0u;
|
|
|
|
while (fthp->source[len])
|
|
|
|
while (fthp->source[len])
|
|
|
|
len++;
|
|
|
|
len++;
|
|
|
|
fthp->push(std::bit_cast<cell>(fthp->source));
|
|
|
|
fthp->push(std::bit_cast<cell>(fthp->source));
|
|
|
|
fthp->push(len); }, 0
|
|
|
|
fthp->push(len); }, 0
|
|
|
|
, S{">in"}, [](auto) { fthp->push(std::bit_cast<cell>(&fthp->sourcei)); }, 0
|
|
|
|
, S{">IN"}, [](auto) { fthp->push(std::bit_cast<cell>(&fthp->sourcei)); }, 0
|
|
|
|
, S{"key"}, [](auto) {
|
|
|
|
, S{"KEY"}, [](auto) {
|
|
|
|
if (fthp->sourcei != std::string_view::npos)
|
|
|
|
if (fthp->sourcei != std::string_view::npos)
|
|
|
|
fthp->push(fthp->source[fthp->sourcei++]);
|
|
|
|
fthp->push(fthp->source[fthp->sourcei++]);
|
|
|
|
else
|
|
|
|
else
|
|
|
|
fthp->push(0); }, 0
|
|
|
|
fthp->push(0); }, 0
|
|
|
|
>::word;
|
|
|
|
>::word;
|
|
|
|
constexpr static auto& dict2 = comp_dict<prologue, &dict1
|
|
|
|
constexpr static auto& dict2 = comp_dict<prologue, &dict1
|
|
|
|
, S{"align" }, S{"here dup aligned swap - allot"}, 0
|
|
|
|
, S{"ALIGN" }, S{"HERE DUP ALIGNED SWAP - ALLOT"}, 0
|
|
|
|
, S{"aligned"}, S{"cell 1- + cell 1- invert and"}, 0
|
|
|
|
, S{"ALIGNED"}, S{"CELL 1- + CELL 1- INVERT AND"}, 0
|
|
|
|
, S{"decimal"}, S{"10 base !"}, 0
|
|
|
|
, S{"DECIMAL"}, S{"10 BASE !"}, 0
|
|
|
|
, S{"hex" }, S{"16 base !"}, 0
|
|
|
|
, S{"HEX" }, S{"16 BASE !"}, 0
|
|
|
|
, S{"<=" }, S{"2dup < >r = r> or"}, 0
|
|
|
|
, S{"<=" }, S{"2DUP < >R = R> OR"}, 0
|
|
|
|
, S{"2!" }, S{"swap over ! cell+ !"}, 0
|
|
|
|
, S{"2!" }, S{"SWAP OVER ! CELL+ !"}, 0
|
|
|
|
, S{"2@" }, S{"dup cell+ @ swap @"}, 0
|
|
|
|
, S{"2@" }, S{"DUP CELL+ @ SWAP @"}, 0
|
|
|
|
, S{"c," }, S{"here c! 1 allot"}, 0
|
|
|
|
, S{"C," }, S{"HERE C! 1 ALLOT"}, 0
|
|
|
|
, S{"exit" }, S{"0 ,"}, word_base::immediate
|
|
|
|
, S{"EXIT" }, S{"0 ,"}, word_base::immediate
|
|
|
|
, S{"," }, S{"here ! cell allot"}, 0
|
|
|
|
, S{"," }, S{"HERE ! CELL ALLOT"}, 0
|
|
|
|
, S{"allot" }, S{"dp +!"}, 0
|
|
|
|
, S{"ALLOT" }, S{"DP +!"}, 0
|
|
|
|
, S{"+!" }, S{"dup >r swap r> @ + swap !"}, 0
|
|
|
|
, S{"+!" }, S{"DUP >R SWAP R> @ + SWAP !"}, 0
|
|
|
|
, S{"2swap" }, S{"rot >r rot r>"}, 0
|
|
|
|
, S{"2SWAP" }, S{"ROT >R ROT R>"}, 0
|
|
|
|
, S{"2dup" }, S{"over over"}, 0
|
|
|
|
, S{"2DUP" }, S{"OVER OVER"}, 0
|
|
|
|
, S{"2over" }, S{"3 pick 3 pick"}, 0
|
|
|
|
, S{"2OVER" }, S{"3 PICK 3 PICK"}, 0
|
|
|
|
, S{">r" }, S{"rp@ cell - rp ! rp@ cell+ @ rp@ ! rp@ cell+ !"}, 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{"R>" }, S{"RP@ @ RP@ CELL+ RP ! RP@ @ SWAP RP@ !"}, 0
|
|
|
|
, S{"over" }, S{"1 pick"}, 0
|
|
|
|
, S{"OVER" }, S{"1 PICK"}, 0
|
|
|
|
, S{"pick" }, S{"cells cell+ sp@ + @"}, 0
|
|
|
|
, S{"PICK" }, S{"CELLS CELL+ SP@ + @"}, 0
|
|
|
|
, S{"sp@" }, S{"sp @"}, 0
|
|
|
|
, S{"SP@" }, S{"SP @"}, 0
|
|
|
|
, S{"rp@" }, S{"rp @ cell+"}, 0
|
|
|
|
, S{"RP@" }, S{"RP @ CELL+"}, 0
|
|
|
|
, S{"here" }, S{"dp @"}, 0
|
|
|
|
, S{"HERE" }, S{"DP @"}, 0
|
|
|
|
, S{"latest"}, S{"_d @"}, 0
|
|
|
|
, S{"LATEST"}, S{"_D @"}, 0
|
|
|
|
, S{"1-" }, S{"1 -" }, 0
|
|
|
|
, S{"1-" }, S{"1 -" }, 0
|
|
|
|
, S{"1+" }, S{"1 +" }, 0
|
|
|
|
, S{"1+" }, S{"1 +" }, 0
|
|
|
|
, S{"cell+" }, S{"cell +"}, 0
|
|
|
|
, S{"CELL+" }, S{"CELL +"}, 0
|
|
|
|
, S{"cells" }, S{"cell *"}, 0
|
|
|
|
, S{"CELLS" }, S{"CELL *"}, 0
|
|
|
|
, S{"char+" }, S{"1 +" }, 0
|
|
|
|
, S{"CHAR+" }, S{"1 +" }, 0
|
|
|
|
, S{"-rot" }, S{"rot rot"}, 0
|
|
|
|
, S{"-ROT" }, S{"ROT ROT"}, 0
|
|
|
|
, S{"2drop" }, S{"drop drop"}, 0
|
|
|
|
, S{"2DROP" }, S{"DROP DROP"}, 0
|
|
|
|
, S{"0<" }, S{"0 <"}, 0
|
|
|
|
, S{"0<" }, S{"0 <"}, 0
|
|
|
|
, S{"0<>" }, S{"0 <>"}, 0
|
|
|
|
, S{"0<>" }, S{"0 <>"}, 0
|
|
|
|
, S{"<>" }, S{"= 0="}, 0
|
|
|
|
, S{"<>" }, S{"= 0="}, 0
|
|
|
|
, S{"0=" }, S{"0 ="}, 0
|
|
|
|
, S{"0=" }, S{"0 ="}, 0
|
|
|
|
, S{">" }, S{"swap <"}, 0
|
|
|
|
, S{">" }, S{"SWAP <"}, 0
|
|
|
|
, S{"invert"}, S{"-1 xor"}, 0
|
|
|
|
, S{"INVERT"}, S{"-1 XOR"}, 0
|
|
|
|
, S{"negate"}, S{"-1 *"}, 0
|
|
|
|
, S{"NEGATE"}, S{"-1 *"}, 0
|
|
|
|
, S{"2*" }, S{"2 *"}, 0
|
|
|
|
, S{"2*" }, S{"2 *"}, 0
|
|
|
|
, S{"bl" }, S{"32"}, 0
|
|
|
|
, S{"BL" }, S{"32"}, 0
|
|
|
|
, S{"false" }, S{"0"}, 0
|
|
|
|
, S{"FALSE" }, S{"0"}, 0
|
|
|
|
, S{"true" }, S{"-1"}, 0
|
|
|
|
, S{"TRUE" }, S{"-1"}, 0
|
|
|
|
>::word;
|
|
|
|
>::word;
|
|
|
|
|
|
|
|
|
|
|
|
return &dict2;
|
|
|
|
return &dict2;
|
|
|
|