aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClyne Sullivan <clyne@bitgloo.com>2024-11-25 09:07:25 -0500
committerClyne Sullivan <clyne@bitgloo.com>2024-11-25 09:07:25 -0500
commit5cff8e25955dcc8e417e8be83a6746d2d42e7ff6 (patch)
tree60e784b2997ae2eec387abfbec0cd1355dbd5640
parent58e34a283d1eec14581a6efed52b68e87865f931 (diff)
make base wordset constexpr
-rw-r--r--core.fth13
-rw-r--r--forth.hpp172
2 files changed, 113 insertions, 72 deletions
diff --git a/core.fth b/core.fth
index 69ce9a2..3f850b1 100644
--- a/core.fth
+++ b/core.fth
@@ -1,12 +1,11 @@
-: cell 8 ;
: cell+ cell + ;
: cells cell * ;
: char+ 1 + ;
: chars ;
-: state _d 7 cells + ;
-: [ 0 state ! ; immediate
-: ] -1 state ! ;
+: state [ _d 7 cells + ] literal ;
+\ : [ 0 state ! ; immediate
+\ : ] -1 state ! ;
: sp _d ;
: rp [ _d cell+ ] literal ;
@@ -19,8 +18,8 @@
: unused [ _d 8 cells + ] literal @ here - ;
: latest [ _d 4 cells + ] literal @ ;
-: dup sp@ @ ;
-: drop sp@ cell+ sp ! ;
+\ : dup sp@ @ ;
+\ : drop sp@ cell+ sp ! ;
: pick cells cell+ sp@ + @ ;
: >r rp@ cell - rp !
rp@ cell+ @ rp@ !
@@ -28,7 +27,7 @@
: r> rp@ @
rp@ cell+ rp !
rp@ @ swap rp@ ! ;
-: rot >r swap r> swap ;
+\ : rot >r swap r> swap ;
: -rot rot rot ;
: over 1 pick ;
diff --git a/forth.hpp b/forth.hpp
index c19c24e..3873c68 100644
--- a/forth.hpp
+++ b/forth.hpp
@@ -32,7 +32,7 @@ struct forth
{
using cell = std::intptr_t;
using addr = std::uintptr_t;
- using func = void (*)(void *);
+ using func = void (*)(const void *);
static constexpr bool enable_exceptions = true;
static constexpr int data_size = 16;
@@ -64,19 +64,44 @@ struct forth
struct word_base {
static constexpr addr immediate = 1 << 8;
- word_base *next;
+ const word_base *next;
addr flags_len;
auto name() const -> std::string_view {
return {reinterpret_cast<const char *>(this + 1)};
}
- auto body() -> func * {
- auto ptr = reinterpret_cast<std::uint8_t *>(this + 1) + (flags_len & 0xFF);
- return reinterpret_cast<func *>(ptr);
+ auto body() const -> const func * {
+ auto ptr = reinterpret_cast<const std::uint8_t *>(this + 1)
+ + (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) {
assert<error::stack_overflow>(sp != dstack.begin());
*--sp = v;
@@ -138,11 +163,6 @@ struct forth
return *this;
}
- forth& make_immediate() {
- latest->flags_len |= word_base::immediate;
- return *this;
- }
-
void parse_line(std::string_view sv) {
source = sv.data();
sourcei = sv.find_first_not_of(" \t\r\n");
@@ -183,12 +203,12 @@ struct forth
return word;
}
- void execute(func *body) {
+ void execute(const func *body) {
assert<error::execute_error>(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) {
if (sv == lt->name())
return lt;
@@ -216,59 +236,81 @@ struct forth
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
- .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 {
@@ -297,7 +339,7 @@ struct forth
cell *rp;
func *ip = nullptr;
cell *here = reinterpret_cast<cell *>(this + 1);
- word_base *latest = nullptr;
+ const word_base *latest = nullptr;
const char *source = nullptr;
std::size_t sourcei = npos;
cell compiling = false;