]> code.bitgloo.com Git - clyne/sforth.git/commitdiff
make base wordset constexpr
authorClyne Sullivan <clyne@bitgloo.com>
Mon, 25 Nov 2024 14:07:25 +0000 (09:07 -0500)
committerClyne Sullivan <clyne@bitgloo.com>
Mon, 25 Nov 2024 14:07:25 +0000 (09:07 -0500)
core.fth
forth.hpp

index 69ce9a2bd989cb48daae1dd1ad47ffed43f153e6..3f850b1bf517992892f2bca42b229cd0a9da0fe0 100644 (file)
--- 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 ;
 
index c19c24e1847929e05aceb4ce9d362abf60634aae..3873c68639409ce6889ac7fb78c28ab830703098 100644 (file)
--- 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;