|
|
@ -28,9 +28,12 @@
|
|
|
|
#include <string_view>
|
|
|
|
#include <string_view>
|
|
|
|
#include <utility>
|
|
|
|
#include <utility>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
extern bool sforth_debug_hook();
|
|
|
|
|
|
|
|
|
|
|
|
namespace sforth {
|
|
|
|
namespace sforth {
|
|
|
|
|
|
|
|
|
|
|
|
constexpr bool enable_exceptions = true;
|
|
|
|
constexpr bool enable_exceptions = true;
|
|
|
|
|
|
|
|
constexpr bool enable_debugger = false;
|
|
|
|
|
|
|
|
|
|
|
|
enum class error : int
|
|
|
|
enum class error : int
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -198,7 +201,13 @@ struct forth : public word_list
|
|
|
|
|
|
|
|
|
|
|
|
void execute(const func *body) {
|
|
|
|
void execute(const func *body) {
|
|
|
|
assert<error::execute_error>(body && *body);
|
|
|
|
assert<error::execute_error>(body && *body);
|
|
|
|
(*body)(body);
|
|
|
|
|
|
|
|
|
|
|
|
if constexpr (!enable_debugger) {
|
|
|
|
|
|
|
|
(*body)(body);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
if (::sforth_debug_hook())
|
|
|
|
|
|
|
|
(*body)(body);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
constexpr forth(const word_base *latest):
|
|
|
|
constexpr forth(const word_base *latest):
|
|
|
@ -243,6 +252,17 @@ constexpr auto initialize()
|
|
|
|
fthp->push(*ptr);
|
|
|
|
fthp->push(*ptr);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
constexpr static func jmp_impl = [](auto){
|
|
|
|
|
|
|
|
auto ptr = ++fthp->ip;
|
|
|
|
|
|
|
|
fthp->ip = *std::bit_cast<func **>(ptr) - 1;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
constexpr static func jmp0_impl = [](auto){
|
|
|
|
|
|
|
|
auto ptr = ++fthp->ip;
|
|
|
|
|
|
|
|
if (fthp->pop() == 0)
|
|
|
|
|
|
|
|
fthp->ip = *std::bit_cast<func **>(ptr) - 1;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
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{"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
|
|
|
@ -292,13 +312,8 @@ constexpr auto initialize()
|
|
|
|
fthp->rpush(d);
|
|
|
|
fthp->rpush(d);
|
|
|
|
*fthp->here++ = std::bit_cast<cell>(prologue); }, 0
|
|
|
|
*fthp->here++ = std::bit_cast<cell>(prologue); }, 0
|
|
|
|
, S{"CELL" }, [](auto) { fthp->push(sizeof(cell)); }, 0
|
|
|
|
, S{"CELL" }, [](auto) { fthp->push(sizeof(cell)); }, 0
|
|
|
|
, S{"_JMP" }, [](auto) {
|
|
|
|
, S{"_JMP" }, [](auto) { fthp->push(std::bit_cast<cell>(&jmp_impl)); }, 0
|
|
|
|
auto ptr = ++fthp->ip;
|
|
|
|
, S{"_JMP0"}, [](auto) { fthp->push(std::bit_cast<cell>(&jmp0_impl)); }, 0
|
|
|
|
fthp->ip = *std::bit_cast<func **>(ptr) - 1; }, 0
|
|
|
|
|
|
|
|
, S{"_JMP0"}, [](auto) {
|
|
|
|
|
|
|
|
auto ptr = ++fthp->ip;
|
|
|
|
|
|
|
|
if (fthp->pop() == 0)
|
|
|
|
|
|
|
|
fthp->ip = *std::bit_cast<func **>(ptr) - 1; }, 0
|
|
|
|
|
|
|
|
, S{"_PARSE"}, [](auto) {
|
|
|
|
, S{"_PARSE"}, [](auto) {
|
|
|
|
auto w = fthp->parse();
|
|
|
|
auto w = fthp->parse();
|
|
|
|
fthp->push(std::bit_cast<cell>(w.data()), w.size()); }, 0
|
|
|
|
fthp->push(std::bit_cast<cell>(w.data()), w.size()); }, 0
|
|
|
@ -325,17 +340,18 @@ constexpr auto initialize()
|
|
|
|
fthp->push(fthp->source[fthp->sourcei++]);
|
|
|
|
fthp->push(fthp->source[fthp->sourcei++]);
|
|
|
|
else
|
|
|
|
else
|
|
|
|
fthp->push(0); }, 0
|
|
|
|
fthp->push(0); }, 0
|
|
|
|
, S{"EVALUATE"}, [](auto) {
|
|
|
|
, S{"_eval"}, [](auto) {
|
|
|
|
const auto u = std::bit_cast<addr>(fthp->pop());
|
|
|
|
const addr u = fthp->pop();
|
|
|
|
const auto caddr = std::bit_cast<const char *>(fthp->pop());
|
|
|
|
const auto caddr = std::bit_cast<const char *>(fthp->pop());
|
|
|
|
const auto olds = fthp->source;
|
|
|
|
fthp->parse_line({caddr, u}); }, 0
|
|
|
|
const auto oldi = fthp->sourcei;
|
|
|
|
|
|
|
|
fthp->parse_line({caddr, u});
|
|
|
|
|
|
|
|
fthp->source = olds;
|
|
|
|
|
|
|
|
fthp->sourcei = oldi; }, 0
|
|
|
|
|
|
|
|
>::word;
|
|
|
|
>::word;
|
|
|
|
|
|
|
|
|
|
|
|
constexpr static auto& dict2 = comp_dict<prologue, &dict1
|
|
|
|
constexpr static auto& dict2 = comp_dict<prologue, &dict1
|
|
|
|
//, S{"*/MOD" }, S{">R M* R> SM/REM"}, 0
|
|
|
|
//, S{"*/MOD" }, S{">R M* R> SM/REM"}, 0
|
|
|
|
|
|
|
|
, S{"evaluate"}, S{"tib @ >in @ 2>r _eval 2r> >in ! tib !"}, 0
|
|
|
|
|
|
|
|
, S{"if" }, S{"_jmp0 , here 0 ,"}, word_base::immediate
|
|
|
|
|
|
|
|
, S{"then" }, S{"here swap !"}, word_base::immediate
|
|
|
|
|
|
|
|
, S{"else" }, S{"_jmp , here 0 , swap here swap !"}, word_base::immediate
|
|
|
|
, S{"*/" }, S{">R M* D>S R> /"}, 0
|
|
|
|
, S{"*/" }, S{">R M* D>S R> /"}, 0
|
|
|
|
, S{"/MOD" }, S{"2DUP MOD -ROT /"}, 0
|
|
|
|
, S{"/MOD" }, S{"2DUP MOD -ROT /"}, 0
|
|
|
|
, S{"RECURSE"}, S{"R> R> DUP >R SWAP >R >XT ,"}, word_base::immediate
|
|
|
|
, S{"RECURSE"}, S{"R> R> DUP >R SWAP >R >XT ,"}, word_base::immediate
|
|
|
@ -397,7 +413,7 @@ constexpr auto initialize()
|
|
|
|
, S{"RP" }, S{"_D 2 CELLS +"}, 0
|
|
|
|
, S{"RP" }, S{"_D 2 CELLS +"}, 0
|
|
|
|
, S{"IP" }, S{"_D 3 CELLS +"}, 0
|
|
|
|
, S{"IP" }, S{"_D 3 CELLS +"}, 0
|
|
|
|
, S{"DP" }, S{"_D 4 CELLS +"}, 0
|
|
|
|
, S{"DP" }, S{"_D 4 CELLS +"}, 0
|
|
|
|
, S{"TIB" }, S{"_D 5 CELLS + @"}, 0
|
|
|
|
, S{"TIB" }, S{"_D 5 CELLS +"}, 0
|
|
|
|
, S{">IN" }, S{"_D 6 CELLS +"}, 0
|
|
|
|
, S{">IN" }, S{"_D 6 CELLS +"}, 0
|
|
|
|
, S{"STATE" }, S{"_D 7 CELLS +"}, 0
|
|
|
|
, S{"STATE" }, S{"_D 7 CELLS +"}, 0
|
|
|
|
, S{"BASE" }, S{"_D 8 CELLS +"}, 0
|
|
|
|
, S{"BASE" }, S{"_D 8 CELLS +"}, 0
|
|
|
|