make base wordset constexpr

main
Clyne 3 weeks ago
parent 58e34a283d
commit 5cff8e2595
Signed by: clyne
GPG Key ID: 1B74EE6C49C96795

@ -1,12 +1,11 @@
: cell 8 ;
: cell+ cell + ; : cell+ cell + ;
: cells cell * ; : cells cell * ;
: char+ 1 + ; : char+ 1 + ;
: chars ; : chars ;
: state _d 7 cells + ; : state [ _d 7 cells + ] literal ;
: [ 0 state ! ; immediate \ : [ 0 state ! ; immediate
: ] -1 state ! ; \ : ] -1 state ! ;
: sp _d ; : sp _d ;
: rp [ _d cell+ ] literal ; : rp [ _d cell+ ] literal ;
@ -19,8 +18,8 @@
: unused [ _d 8 cells + ] literal @ here - ; : unused [ _d 8 cells + ] literal @ here - ;
: latest [ _d 4 cells + ] literal @ ; : latest [ _d 4 cells + ] literal @ ;
: dup sp@ @ ; \ : dup sp@ @ ;
: drop sp@ cell+ sp ! ; \ : drop sp@ cell+ sp ! ;
: pick cells cell+ sp@ + @ ; : pick cells cell+ sp@ + @ ;
: >r rp@ cell - rp ! : >r rp@ cell - rp !
rp@ cell+ @ rp@ ! rp@ cell+ @ rp@ !
@ -28,7 +27,7 @@
: r> rp@ @ : r> rp@ @
rp@ cell+ rp ! rp@ cell+ rp !
rp@ @ swap rp@ ! ; rp@ @ swap rp@ ! ;
: rot >r swap r> swap ; \ : rot >r swap r> swap ;
: -rot rot rot ; : -rot rot rot ;
: over 1 pick ; : over 1 pick ;

@ -32,7 +32,7 @@ struct forth
{ {
using cell = std::intptr_t; using cell = std::intptr_t;
using addr = std::uintptr_t; using addr = std::uintptr_t;
using func = void (*)(void *); using func = void (*)(const void *);
static constexpr bool enable_exceptions = true; static constexpr bool enable_exceptions = true;
static constexpr int data_size = 16; static constexpr int data_size = 16;
@ -64,19 +64,44 @@ struct forth
struct word_base { struct word_base {
static constexpr addr immediate = 1 << 8; static constexpr addr immediate = 1 << 8;
word_base *next; const word_base *next;
addr flags_len; addr flags_len;
auto name() const -> std::string_view { auto name() const -> std::string_view {
return {reinterpret_cast<const char *>(this + 1)}; return {reinterpret_cast<const char *>(this + 1)};
} }
auto body() -> func * { auto body() const -> const func * {
auto ptr = reinterpret_cast<std::uint8_t *>(this + 1) + (flags_len & 0xFF); auto ptr = reinterpret_cast<const std::uint8_t *>(this + 1)
return reinterpret_cast<func *>(ptr); + (flags_len & 0xFF);
return reinterpret_cast<const func *>(ptr);
}
void make_immediate() {
flags_len |= immediate;
}
};
template<std::size_t L>
struct word : public word_base {
std::array<char, L> name;
func body;
template<std::size_t N>
consteval word(const char (&nam)[N],
func bod = nullptr,
const word_base *prev = nullptr,
addr flags = 0):
word_base{prev, L | flags}, name{}, body{bod}
{
std::copy(nam, nam + N, name.begin());
} }
}; };
template<std::size_t N>
word(const char (&nam)[N], func b = nullptr, const word_base *w = nullptr,
addr flags = 0) -> word<(N + sizeof(cell)) & ~(sizeof(cell) - 1)>;
void push(cell v) { void push(cell v) {
assert<error::stack_overflow>(sp != dstack.begin()); assert<error::stack_overflow>(sp != dstack.begin());
*--sp = v; *--sp = v;
@ -138,11 +163,6 @@ struct forth
return *this; return *this;
} }
forth& make_immediate() {
latest->flags_len |= word_base::immediate;
return *this;
}
void parse_line(std::string_view sv) { void parse_line(std::string_view sv) {
source = sv.data(); source = sv.data();
sourcei = sv.find_first_not_of(" \t\r\n"); sourcei = sv.find_first_not_of(" \t\r\n");
@ -183,12 +203,12 @@ struct forth
return word; return word;
} }
void execute(func *body) { void execute(const func *body) {
assert<error::execute_error>(body && *body); assert<error::execute_error>(body && *body);
(*body)(body); (*body)(body);
} }
auto get(std::string_view sv) -> std::optional<word_base *> { auto get(std::string_view sv) -> std::optional<const word_base *> {
for (auto lt = latest; lt; lt = lt->next) { for (auto lt = latest; lt; lt = lt->next) {
if (sv == lt->name()) if (sv == lt->name())
return lt; return lt;
@ -216,59 +236,81 @@ struct forth
static auto& fth = **fthp; static auto& fth = **fthp;
auto f_dict = [](auto) { fth.push(reinterpret_cast<cell>(&fth)); };
auto f_add = [](auto) { fth.top() += fth.pop(); };
auto f_minus = [](auto) { fth.top() -= fth.pop(); };
auto f_times = [](auto) { fth.top() *= fth.pop(); };
auto f_divide = [](auto) { fth.top() /= fth.pop(); };
auto f_bitand = [](auto) { fth.top() &= fth.pop(); };
auto f_bitor = [](auto) { fth.top() |= fth.pop(); };
auto f_bitxor = [](auto) { fth.top() ^= fth.pop(); };
auto f_lbrac = [](auto) { fth.compiling = false; };
auto f_rbrac = [](auto) { fth.compiling = true; };
auto f_imm = [](auto) {
const_cast<word_base *>(fth.latest)->make_immediate(); };
auto f_lit = [](auto) {
static auto lit_impl = +[] {
auto ptr = reinterpret_cast<cell *>(++fth.ip);
fth.push(*ptr);
};
assert<error::compile_only_word>(fth.compiling);
*fth.here++ = reinterpret_cast<cell>(&lit_impl);
*fth.here++ = fth.pop(); };
auto f_peek = [](auto) { fth.push(*reinterpret_cast<cell *>(fth.pop())); };
auto f_poke = [](auto) {
auto [p, v] = fth.pop<2>();
*reinterpret_cast<cell *>(p) = v; };
auto f_swap = [](auto) { auto [a, b] = fth.pop<2>(); fth.push(a, b); };
auto f_drop = [](auto) { fth.pop(); };
auto f_dup = [](auto) { fth.push(fth.top()); };
auto f_rot = [](auto) { auto [a, b, c] = fth.pop<3>(); fth.push(b, a, c); };
auto f_eq = [](auto) { auto v = fth.pop(); fth.top() = -(fth.top() == v); };
auto f_lt = [](auto) { auto v = fth.pop(); fth.top() = -(fth.top() < v); };
auto f_tick = [](auto) {
auto w = fth.parse();
if (auto g = fth.get(w); g)
fth.push(reinterpret_cast<cell>((*g)->body()));
else
fth.push(0); };
auto f_colon = [](auto) {
auto w = fth.parse();
fth.add(w);
*fth.here++ = reinterpret_cast<cell>(forth::prologue<fthp>);
fth.compiling = true; };
auto f_semic = [](auto) { *fth.here++ = 0; fth.compiling = false; };
auto f_comm = [](auto) { fth.sourcei = npos; };
auto f_cell = [](auto) { fth.push(sizeof(cell)); };
constexpr static word w_dict {"_d", f_dict};
constexpr static word w_add {"+", f_add, &w_dict};
constexpr static word w_minus {"-", f_minus, &w_add};
constexpr static word w_times {"*", f_times, &w_minus};
constexpr static word w_divide {"/", f_divide, &w_times};
constexpr static word w_bitand {"and", f_bitand, &w_divide};
constexpr static word w_bitor {"or", f_bitor, &w_bitand};
constexpr static word w_bitxor {"xor", f_bitxor, &w_bitor};
constexpr static word w_lbrac {"[", f_lbrac, &w_bitxor, word_base::immediate};
constexpr static word w_rbrac {"]", f_rbrac, &w_lbrac};
constexpr static word w_imm {"immediate", f_imm, &w_rbrac};
constexpr static word w_lit {"literal", f_lit, &w_imm, word_base::immediate};
constexpr static word w_peek {"@", f_peek, &w_lit};
constexpr static word w_poke {"!", f_poke, &w_peek};
constexpr static word w_swap {"swap", f_swap, &w_poke};
constexpr static word w_drop {"drop", f_drop, &w_swap};
constexpr static word w_dup {"dup", f_dup, &w_drop};
constexpr static word w_rot {"rot", f_rot, &w_dup};
constexpr static word w_eq {"=", f_eq, &w_rot};
constexpr static word w_lt {"<", f_lt, &w_eq};
constexpr static word w_tick {"\'", f_tick, &w_lt};
constexpr static word w_colon {":", f_colon, &w_tick};
constexpr static word w_semic {";", f_semic, &w_colon, word_base::immediate};
constexpr static word w_comm {"\\", f_comm, &w_semic, word_base::immediate};
constexpr static word w_cell {"cell", f_cell, &w_comm};
fth.latest = &w_cell;
fth.end = end_value; fth.end = end_value;
fth
.add("_d", [](auto) { fth.push(reinterpret_cast<cell>(&fth)); })
//.add("[", [](auto) { fth.compiling = false; }).make_immediate()
//.add("]", [](auto) { fth.compiling = true; })
.add("immediate", [](auto) { fth.make_immediate(); }).make_immediate()
.add("literal", [](auto) {
static auto lit_impl = +[] {
auto ptr = reinterpret_cast<cell *>(++fth.ip);
fth.push(*ptr);
};
assert<error::compile_only_word>(fth.compiling);
*fth.here++ = reinterpret_cast<cell>(&lit_impl);
*fth.here++ = fth.pop();
}).make_immediate()
.add("@", [](auto) { fth.push(*reinterpret_cast<cell *>(fth.pop())); })
.add("!", [](auto) {
auto [p, v] = fth.pop<2>();
*reinterpret_cast<cell *>(p) = v; })
.add("swap", [](auto) { auto [a, b] = fth.pop<2>(); fth.push(a, b); })
//.add("drop", [](auto) { fth.pop(); })
//.add("dup", [](auto) { fth.push(fth.top()); })
//.add("rot", [](auto) { auto [a, b, c] = fth.pop<3>(); fth.push(b, a, c); })
.add("+", [](auto) { fth.top() += fth.pop(); })
.add("-", [](auto) { fth.top() -= fth.pop(); })
.add("*", [](auto) { fth.top() *= fth.pop(); })
.add("/", [](auto) { fth.top() /= fth.pop(); })
.add("and", [](auto) { fth.top() &= fth.pop(); })
.add("or", [](auto) { fth.top() |= fth.pop(); })
.add("xor", [](auto) { fth.top() ^= fth.pop(); })
.add("=", [](auto) { auto v = fth.pop(); fth.top() = -(fth.top() == v); })
.add("<", [](auto) { auto v = fth.pop(); fth.top() = -(fth.top() < v); })
.add("\'", [](auto) {
auto w = fth.parse();
if (auto g = fth.get(w); g)
fth.push(reinterpret_cast<cell>((*g)->body()));
else
fth.push(0);
})
.add(":", [](auto) {
auto w = fth.parse();
fth.add(w);
*fth.here++ = reinterpret_cast<cell>(forth::prologue<fthp>);
fth.compiling = true;
})
.add(";", [](auto) {
*fth.here++ = 0;
fth.compiling = false;
}).make_immediate()
.add("\\", [](auto) {
fth.sourcei = npos;
}).make_immediate();
} }
static auto error_string(error err) noexcept -> std::string_view { static auto error_string(error err) noexcept -> std::string_view {
@ -297,7 +339,7 @@ struct forth
cell *rp; cell *rp;
func *ip = nullptr; func *ip = nullptr;
cell *here = reinterpret_cast<cell *>(this + 1); cell *here = reinterpret_cast<cell *>(this + 1);
word_base *latest = nullptr; const word_base *latest = nullptr;
const char *source = nullptr; const char *source = nullptr;
std::size_t sourcei = npos; std::size_t sourcei = npos;
cell compiling = false; cell compiling = false;

Loading…
Cancel
Save