|
|
@ -80,10 +80,10 @@ struct word_base : public word_list
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
template<unsigned N>
|
|
|
|
template<unsigned N>
|
|
|
|
struct ctstring {
|
|
|
|
struct cS {
|
|
|
|
char data[N];
|
|
|
|
char data[N];
|
|
|
|
|
|
|
|
|
|
|
|
consteval ctstring(const char (&s)[N]) {
|
|
|
|
consteval cS(const char (&s)[N]) {
|
|
|
|
std::copy(s, s + N, data);
|
|
|
|
std::copy(s, s + N, data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
consteval operator const char *() const {
|
|
|
|
consteval operator const char *() const {
|
|
|
@ -94,17 +94,39 @@ struct ctstring {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
template<ctstring Name, ctstring Body, auto *Prev = (const word_base *)nullptr>
|
|
|
|
template<cS Name, func Body, auto *Prev = (const word_base *)nullptr>
|
|
|
|
struct comp_word : public word_base
|
|
|
|
struct native_word : public word_base
|
|
|
|
{
|
|
|
|
{
|
|
|
|
constexpr static auto N = (sizeof(Name) + sizeof(cell) - 1) & ~(sizeof(cell) - 1);
|
|
|
|
constexpr static auto N = (sizeof(Name) + sizeof(cell) - 1) & ~(sizeof(cell) - 1);
|
|
|
|
|
|
|
|
std::array<char, N> namebuf;
|
|
|
|
|
|
|
|
func body;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
consteval const func *get_ct(std::string_view name) const {
|
|
|
|
|
|
|
|
if (name == std::string_view{Name.data})
|
|
|
|
|
|
|
|
return &body;
|
|
|
|
|
|
|
|
else if constexpr (Prev != nullptr)
|
|
|
|
|
|
|
|
return Prev->get_ct(name);
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
consteval native_word(addr flags = 0):
|
|
|
|
|
|
|
|
word_base{Prev, N | flags}, namebuf{}, body{Body}
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
std::copy(Name.data, Name.data + sizeof(Name), namebuf.data());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<const func Prol, cS Name, cS Body, auto *Prev = (const word_base *)nullptr>
|
|
|
|
|
|
|
|
struct comp_word : public native_word<Name, Prol, Prev>
|
|
|
|
|
|
|
|
{
|
|
|
|
static constexpr std::size_t B =
|
|
|
|
static constexpr std::size_t B =
|
|
|
|
[] {
|
|
|
|
[] {
|
|
|
|
std::size_t b = 1;
|
|
|
|
std::size_t b = 1;
|
|
|
|
std::string_view sv {Body.data};
|
|
|
|
std::string_view sv {Body.data};
|
|
|
|
auto sourcei = sv.find_first_not_of(" \t\r\n");
|
|
|
|
auto sourcei = sv.find_first_not_of(" \t\r\n");
|
|
|
|
while (sourcei != std::string_view::npos) {
|
|
|
|
while (sourcei != std::string_view::npos) {
|
|
|
|
const auto word = parse(Body.data, sourcei);
|
|
|
|
const auto word = word_list::parse(Body.data, sourcei);
|
|
|
|
|
|
|
|
|
|
|
|
b++;
|
|
|
|
b++;
|
|
|
|
if (!Prev->get_ct(word))
|
|
|
|
if (!Prev->get_ct(word))
|
|
|
@ -118,39 +140,26 @@ struct comp_word : public word_base
|
|
|
|
cell c;
|
|
|
|
cell c;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
std::array<char, N> namebuf;
|
|
|
|
std::array<bodyt, B> bodybuf {};
|
|
|
|
const func prologue;
|
|
|
|
|
|
|
|
std::array<bodyt, B> bodybuf;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
consteval const func *get_ct(std::string_view name) const {
|
|
|
|
|
|
|
|
if (name == std::string_view{Name.data})
|
|
|
|
|
|
|
|
return &prologue;
|
|
|
|
|
|
|
|
else if (Prev)
|
|
|
|
|
|
|
|
return Prev->get_ct(name);
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
consteval comp_word(const func prol, addr flags = 0):
|
|
|
|
consteval comp_word(addr flags = 0):
|
|
|
|
word_base{Prev, N | flags}, namebuf{}, prologue{prol}, bodybuf{}
|
|
|
|
native_word<Name, Prol, Prev>{flags}
|
|
|
|
{
|
|
|
|
{
|
|
|
|
std::copy(Name.data, Name.data + sizeof(Name), namebuf.data());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
auto bptr = bodybuf.begin();
|
|
|
|
auto bptr = bodybuf.begin();
|
|
|
|
std::string_view sv {Body};
|
|
|
|
std::string_view sv {Body};
|
|
|
|
auto sourcei = sv.find_first_not_of(" \t\r\n");
|
|
|
|
auto sourcei = sv.find_first_not_of(" \t\r\n");
|
|
|
|
while (sourcei != std::string_view::npos) {
|
|
|
|
while (sourcei != std::string_view::npos) {
|
|
|
|
const auto word = parse(Body, sourcei);
|
|
|
|
const auto word = word_list::parse(Body, sourcei);
|
|
|
|
|
|
|
|
|
|
|
|
auto w = get_ct(word);
|
|
|
|
auto w = Prev->get_ct(word);
|
|
|
|
if (w) {
|
|
|
|
if (w) {
|
|
|
|
bptr->f = get_ct(word);
|
|
|
|
bptr->f = Prev->get_ct(word);
|
|
|
|
bptr++;
|
|
|
|
bptr++;
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
cell n;
|
|
|
|
cell n;
|
|
|
|
std::from_chars(word.cbegin(), word.cend(), n, 10);
|
|
|
|
std::from_chars(word.cbegin(), word.cend(), n, 10);
|
|
|
|
|
|
|
|
|
|
|
|
bptr->f = get_ct("_lit");
|
|
|
|
bptr->f = Prev->get_ct("_lit");
|
|
|
|
bptr++;
|
|
|
|
bptr++;
|
|
|
|
bptr->c = n;
|
|
|
|
bptr->c = n;
|
|
|
|
bptr++;
|
|
|
|
bptr++;
|
|
|
@ -159,30 +168,7 @@ struct comp_word : public word_base
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
template<ctstring Name, func Body, auto *Prev = (const word_base *)nullptr>
|
|
|
|
template<cS Name, func Body, addr Flags, auto... Next>
|
|
|
|
struct native_word : public word_base
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
constexpr static auto N = (sizeof(Name) + sizeof(cell) - 1) & ~(sizeof(cell) - 1);
|
|
|
|
|
|
|
|
std::array<char, N> namebuf;
|
|
|
|
|
|
|
|
func body;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
consteval const func *get_ct(std::string_view name) const {
|
|
|
|
|
|
|
|
if (name == std::string_view{Name.data})
|
|
|
|
|
|
|
|
return &body;
|
|
|
|
|
|
|
|
else if constexpr (Prev != nullptr)
|
|
|
|
|
|
|
|
return Prev->get_ct(name);
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
consteval native_word(addr flags = 0):
|
|
|
|
|
|
|
|
word_base{Prev, N | flags}, namebuf{}, body{Body}
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
std::copy(Name.data, Name.data + sizeof(Name), namebuf.data());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<ctstring Name, func Body, addr Flags, auto... Next>
|
|
|
|
|
|
|
|
struct native_dict
|
|
|
|
struct native_dict
|
|
|
|
{
|
|
|
|
{
|
|
|
|
constexpr static native_word<Name, Body,
|
|
|
|
constexpr static native_word<Name, Body,
|
|
|
@ -194,15 +180,15 @@ struct native_dict
|
|
|
|
}()> word {Flags};
|
|
|
|
}()> word {Flags};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
template<ctstring Name, ctstring Body, addr Flags, auto... Next>
|
|
|
|
template<func Prol, auto *Prev, cS Name, cS Body, addr Flags, auto... Next>
|
|
|
|
struct comp_dict
|
|
|
|
struct comp_dict
|
|
|
|
{
|
|
|
|
{
|
|
|
|
constexpr static comp_word<Name, Body,
|
|
|
|
constexpr static comp_word<Prol, Name, Body,
|
|
|
|
[] {
|
|
|
|
[] {
|
|
|
|
if constexpr (sizeof...(Next))
|
|
|
|
if constexpr (sizeof...(Next))
|
|
|
|
return &native_dict<Next...>::word;
|
|
|
|
return &comp_dict<Prol, Prev, Next...>::word;
|
|
|
|
else
|
|
|
|
else
|
|
|
|
return (const word_base *)nullptr;
|
|
|
|
return Prev;
|
|
|
|
}()> word {Flags};
|
|
|
|
}()> word {Flags};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
@ -424,54 +410,62 @@ struct forth : public word_list
|
|
|
|
*fth.here++ = std::bit_cast<cell>((*g)->body());
|
|
|
|
*fth.here++ = std::bit_cast<cell>((*g)->body());
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
constexpr static auto& asdf = native_dict<
|
|
|
|
constexpr static auto& dict1 = native_dict<
|
|
|
|
ctstring{"_d"}, f_dict, 0,
|
|
|
|
cS{"_d"}, f_dict, 0,
|
|
|
|
ctstring{"_lit"}, lit_impl, 0,
|
|
|
|
cS{"_lit"}, lit_impl, 0,
|
|
|
|
ctstring{"swap"}, f_swap, 0,
|
|
|
|
cS{"swap"}, f_swap, 0,
|
|
|
|
ctstring{"drop"}, f_drop, 0,
|
|
|
|
cS{"drop"}, f_drop, 0,
|
|
|
|
ctstring{"dup"}, f_dup, 0,
|
|
|
|
cS{"dup"}, f_dup, 0,
|
|
|
|
ctstring{"rot"}, f_rot, 0,
|
|
|
|
cS{"rot"}, f_rot, 0,
|
|
|
|
ctstring{"+"}, f_add, 0,
|
|
|
|
cS{"+"}, f_add, 0,
|
|
|
|
ctstring{"-"}, f_minus, 0,
|
|
|
|
cS{"-"}, f_minus, 0,
|
|
|
|
ctstring{"*"}, f_times, 0,
|
|
|
|
cS{"*"}, f_times, 0,
|
|
|
|
ctstring{"/"}, f_divide, 0,
|
|
|
|
cS{"/"}, f_divide, 0,
|
|
|
|
ctstring{"mod"}, f_mod, 0,
|
|
|
|
cS{"mod"}, f_mod, 0,
|
|
|
|
ctstring{"and"}, f_bitand, 0,
|
|
|
|
cS{"and"}, f_bitand, 0,
|
|
|
|
ctstring{"or"}, f_bitor, 0,
|
|
|
|
cS{"or"}, f_bitor, 0,
|
|
|
|
ctstring{"xor"}, f_bitxor, 0,
|
|
|
|
cS{"xor"}, f_bitxor, 0,
|
|
|
|
ctstring{"lshift"}, f_lshift, 0,
|
|
|
|
cS{"lshift"}, f_lshift, 0,
|
|
|
|
ctstring{"rshift"}, f_rshift, 0,
|
|
|
|
cS{"rshift"}, f_rshift, 0,
|
|
|
|
ctstring{"["}, f_lbrac, word_base::immediate,
|
|
|
|
cS{"["}, f_lbrac, word_base::immediate,
|
|
|
|
ctstring{"]"}, f_rbrac, 0,
|
|
|
|
cS{"]"}, f_rbrac, 0,
|
|
|
|
ctstring{"immediate"}, f_imm, 0,
|
|
|
|
cS{"immediate"}, f_imm, 0,
|
|
|
|
ctstring{"literal"}, f_lit, word_base::immediate,
|
|
|
|
cS{"literal"}, f_lit, word_base::immediate,
|
|
|
|
ctstring{"@"}, f_peek, 0,
|
|
|
|
cS{"@"}, f_peek, 0,
|
|
|
|
ctstring{"!"}, f_poke, 0,
|
|
|
|
cS{"!"}, f_poke, 0,
|
|
|
|
ctstring{"c@"}, f_cpeek, 0,
|
|
|
|
cS{"c@"}, f_cpeek, 0,
|
|
|
|
ctstring{"c!"}, f_cpoke, 0,
|
|
|
|
cS{"c!"}, f_cpoke, 0,
|
|
|
|
ctstring{"="}, f_eq, 0,
|
|
|
|
cS{"="}, f_eq, 0,
|
|
|
|
ctstring{"<"}, f_lt, 0,
|
|
|
|
cS{"<"}, f_lt, 0,
|
|
|
|
ctstring{"\'"}, f_tick, 0,
|
|
|
|
cS{"\'"}, f_tick, 0,
|
|
|
|
ctstring{":"}, f_colon, 0,
|
|
|
|
cS{":"}, f_colon, 0,
|
|
|
|
ctstring{";"}, f_semic, word_base::immediate,
|
|
|
|
cS{";"}, f_semic, word_base::immediate,
|
|
|
|
ctstring{"\\"}, f_comm, word_base::immediate,
|
|
|
|
cS{"\\"}, f_comm, word_base::immediate,
|
|
|
|
ctstring{"cell"}, f_cell, 0,
|
|
|
|
cS{"cell"}, f_cell, 0,
|
|
|
|
ctstring{"_jmp"}, f_jmp, 0,
|
|
|
|
cS{"_jmp"}, f_jmp, 0,
|
|
|
|
ctstring{"_jmp0"}, f_jmp0, 0,
|
|
|
|
cS{"_jmp0"}, f_jmp0, 0,
|
|
|
|
ctstring{"postpone"}, f_postpone, word_base::immediate
|
|
|
|
cS{"chars"}, [](auto) {}, 0,
|
|
|
|
|
|
|
|
cS{"postpone"}, f_postpone, word_base::immediate
|
|
|
|
|
|
|
|
>::word;
|
|
|
|
|
|
|
|
constexpr static auto& dict2 = comp_dict<forth::prologue<fthp>, &dict1
|
|
|
|
|
|
|
|
, cS{"1-" }, cS{"1 -" }, 0
|
|
|
|
|
|
|
|
, cS{"1+" }, cS{"1 +" }, 0
|
|
|
|
|
|
|
|
, cS{"cell+" }, cS{"cell +"}, 0
|
|
|
|
|
|
|
|
, cS{"cells" }, cS{"cell *"}, 0
|
|
|
|
|
|
|
|
, cS{"char+" }, cS{"1 +" }, 0
|
|
|
|
|
|
|
|
, cS{"-rot" }, cS{"rot rot"}, 0
|
|
|
|
|
|
|
|
, cS{"2drop" }, cS{"drop drop"}, 0
|
|
|
|
|
|
|
|
, cS{"0=" }, cS{"0 ="}, 0
|
|
|
|
|
|
|
|
, cS{"0<" }, cS{"0 <"}, 0
|
|
|
|
|
|
|
|
, cS{"<>" }, cS{"= 0="}, 0
|
|
|
|
|
|
|
|
, cS{">" }, cS{"swap <"}, 0
|
|
|
|
|
|
|
|
, cS{"invert"}, cS{"-1 xor"}, 0
|
|
|
|
|
|
|
|
, cS{"negate"}, cS{"-1 *"}, 0
|
|
|
|
|
|
|
|
, cS{"2*" }, cS{"2 *"}, 0
|
|
|
|
|
|
|
|
, cS{"bl" }, cS{"32"}, 0
|
|
|
|
>::word;
|
|
|
|
>::word;
|
|
|
|
constexpr static comp_word<"cell+", "cell +", &asdf> w_cellp
|
|
|
|
|
|
|
|
{forth::prologue<fthp>};
|
|
|
|
fth.next = &dict2;
|
|
|
|
constexpr static comp_word<"cells", "cell *", &w_cellp> w_cells
|
|
|
|
|
|
|
|
{forth::prologue<fthp>};
|
|
|
|
|
|
|
|
constexpr static comp_word<"char+", "1 +", &w_cells> w_charp
|
|
|
|
|
|
|
|
{forth::prologue<fthp>};
|
|
|
|
|
|
|
|
constexpr static comp_word<"1+", "1 +", &w_charp> w_inc
|
|
|
|
|
|
|
|
{forth::prologue<fthp>};
|
|
|
|
|
|
|
|
constexpr static comp_word<"1-", "1 -", &w_inc> w_dec
|
|
|
|
|
|
|
|
{forth::prologue<fthp>};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fth.next = &w_dec;
|
|
|
|
|
|
|
|
fth.end = end_value;
|
|
|
|
fth.end = end_value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|