]> code.bitgloo.com Git - clyne/sforth.git/commitdiff
constinit forth, build dict mem into forth
authorClyne Sullivan <clyne@bitgloo.com>
Sat, 30 Nov 2024 16:39:31 +0000 (11:39 -0500)
committerClyne Sullivan <clyne@bitgloo.com>
Sat, 30 Nov 2024 16:39:31 +0000 (11:39 -0500)
core.fth
main.cpp
sforth/forth.hpp

index 9c6b7cfeb84314b1a36022c11b5c7ff729418a4c..a194aa1925116d23471cb5f31d5d73f8cda7bc99 100644 (file)
--- a/core.fth
+++ b/core.fth
@@ -1,5 +1,3 @@
-: unused    [ _d 8 cells + ] literal @ here - ;
-
 : [']       ' [ ' literal , ] ; immediate
 
 : if        ['] _jmp0 , here 0 , ; immediate
index 60653dcc37c37994accc43d944e1e9f3547e3c79..0cc5640665747c7ac89326121a6edac988136866 100644 (file)
--- a/main.cpp
+++ b/main.cpp
 #include <span>
 #include <string>
 
-static std::array<sforth::cell, 1024> dict;
-static sforth::forth *fth =
-    [] constexpr {
-        fth = new (dict.data()) sforth::forth;
-        sforth::initialize<&fth>(dict.end());
-        return fth;
-    }();
+constinit static sforth::forth<1024> forth {sforth::initialize<&forth>()};
 
-static bool parse_stream(sforth::forth *, std::istream&, bool say_okay = false);
+constinit static sforth::native_word<".", [](auto) {
+    char buf[32] = {};
+    std::to_chars(buf, buf + sizeof(buf), forth.pop(), forth.base);
+    std::cout << buf << ' ';
+}> dot;
+constinit static sforth::native_word<"emit", [](auto) {
+    std::cout << static_cast<char>(forth.pop());
+}, &dot> emit;
+
+static bool parse_stream(auto&, std::istream&, bool say_okay = false);
 
 int main(int argc, const char *argv[])
 {
     std::span args (argv + 1, argc - 1);
 
-    fth->add(".", [](auto) {
-        char buf[32] = {};
-        std::to_chars(buf, buf + sizeof(buf), fth->pop(), fth->base);
-        std::cout << buf << ' ';
-    });
-    fth->add("emit", [](auto) { std::cout << static_cast<char>(fth->pop()); });
-    fth->add("dictsize", [](auto) { fth->push(dict.size() * sizeof(sforth::cell)); });
+
+    dot.next = std::exchange(forth.next, &emit);
 
     for (auto arg : args) {
-        if (std::ifstream file {arg}; parse_stream(fth, file))
+        if (std::ifstream file {arg}; parse_stream(forth, file))
             return 0;
     }
 
-    parse_stream(fth, std::cin, true);
+    parse_stream(forth, std::cin, true);
 }
 
-bool parse_stream(sforth::forth *fth, std::istream& str, bool say_okay)
+bool parse_stream(auto &fth, std::istream& str, bool say_okay)
 {
     std::string line;
 
@@ -63,7 +61,7 @@ bool parse_stream(sforth::forth *fth, std::istream& str, bool say_okay)
                 return true;
 
             try {
-                fth->parse_line(line);
+                fth.parse_line(line);
             } catch (sforth::error e) {
                 std::cerr << sforth::error_string(e) << " in " << line << std::endl;
                 continue;
@@ -71,7 +69,7 @@ bool parse_stream(sforth::forth *fth, std::istream& str, bool say_okay)
         }
 
         if (say_okay)
-            std::cout << (fth->compiling ? "compiled" : "ok") << std::endl;
+            std::cout << (fth.compiling ? "compiled" : "ok") << std::endl;
     }
 
     return false;
index 32f5d5368cbd44e59786d898234ce7e408a9a504..320a466de9e649b378541825ed0b6943d0a3a247 100644 (file)
@@ -26,7 +26,6 @@
 #include <cstddef>
 #include <charconv>
 #include <string_view>
-#include <tuple>
 #include <utility>
 
 namespace sforth {
@@ -75,6 +74,7 @@ inline void assert(bool condition)
     }
 }
 
+template<std::size_t Cells>
 struct forth : public word_list
 {
     static constexpr int data_size = 16;
@@ -111,17 +111,6 @@ struct forth : public word_list
         return *rp++;
     }
 
-    template<int N>
-    auto pop() {
-        static_assert(N > 0, "pop<N>() with N <= 0");
-
-        auto t = std::tuple {pop()};
-        if constexpr (N > 1)
-            return std::tuple_cat(t, pop<N - 1>());
-        else
-            return t;
-    }
-
     forth& add(std::string_view name, func entry = nullptr) {
         const auto namesz = (name.size() + 1 + sizeof(cell) - 1) & ~(sizeof(cell) - 1);
         const auto size = (sizeof(word_base) + namesz) / sizeof(cell);
@@ -176,109 +165,109 @@ struct forth : public word_list
         (*body)(body);
     }
 
-    constexpr forth() {
+    constexpr forth(const word_base *latest):
+        word_list{latest}
+    {
         sp = dstack.end();
         rp = rstack.end();
+        here = dict.begin();
     }
 
     cell *sp;
     func **rp;
     func *ip = nullptr;
-    cell *here = std::bit_cast<cell *>(this + 1);
+    cell *here;
     const char *source = nullptr;
     std::size_t sourcei = npos;
     cell compiling = false;
-    cell *end = nullptr;
     cell base = 10;
-    std::array<cell, data_size> dstack;
-    std::array<func *, return_size> rstack;
+    std::array<cell, data_size> dstack {};
+    std::array<func *, return_size> rstack {};
+    std::array<cell, Cells> dict {};
 };
 
-template<forth** fthp>
-void initialize(cell *end_value)
+template<auto* fthp>
+constexpr auto initialize()
 {
-    assert<error::init_error>(*fthp);
-
-    static auto& fth = **fthp;
-    static auto _d = std::bit_cast<cell>(*fthp);
-
     constexpr static auto prologue = +[](const void *bodyf) {
         auto body = (func *)bodyf;
-        fth.rpush(fth.ip);
+        fthp->rpush(fthp->ip);
     
-        for (fth.ip = body + 1; *fth.ip; fth.ip++)
-            fth.execute(std::bit_cast<func *>(*fth.ip));
+        for (fthp->ip = body + 1; *fthp->ip; fthp->ip++)
+            fthp->execute(std::bit_cast<func *>(*fthp->ip));
     
-        fth.ip = fth.rpop();
+        fthp->ip = fthp->rpop();
     };
 
     constexpr static func lit_impl = [](auto) {
-        auto ptr = std::bit_cast<cell *>(++fth.ip);
-        fth.push(*ptr);
+        auto ptr = std::bit_cast<cell *>(++fthp->ip);
+        fthp->push(*ptr);
     };
 
     constexpr static auto& dict1 = native_dict<
-          S{"_d"   }, [](auto) { fth.push(_d); }, 0
-        , S{"sp"   }, [](auto) { fth.push(_d + sizeof(cell)); }, 0
-        , S{"rp"   }, [](auto) { fth.push(_d + 2 * sizeof(cell)); }, 0
-        , S{"ip"   }, [](auto) { fth.push(_d + 3 * sizeof(cell)); }, 0
-        , S{"dp"   }, [](auto) { fth.push(_d + 4 * sizeof(cell)); }, 0
-        , S{"state"}, [](auto) { fth.push(_d + 7 * sizeof(cell)); }, 0
-        , S{"base" }, [](auto) { fth.push(_d + 9 * sizeof(cell)); }, 0
+          S{"_d"   }, [](auto) { fthp->push(std::bit_cast<cell>(fthp)); }, 0
+        , S{"sp"   }, [](auto) { fthp->push(std::bit_cast<cell>(fthp) + sizeof(cell)); }, 0
+        , S{"rp"   }, [](auto) { fthp->push(std::bit_cast<cell>(fthp) + 2 * sizeof(cell)); }, 0
+        , S{"ip"   }, [](auto) { fthp->push(std::bit_cast<cell>(fthp) + 3 * sizeof(cell)); }, 0
+        , S{"dp"   }, [](auto) { fthp->push(std::bit_cast<cell>(fthp) + 4 * sizeof(cell)); }, 0
+        , S{"state"}, [](auto) { fthp->push(std::bit_cast<cell>(fthp) + 7 * sizeof(cell)); }, 0
+        , S{"base" }, [](auto) { fthp->push(std::bit_cast<cell>(fthp) + 8 * sizeof(cell)); }, 0
+        , S{"unused"}, [](auto) { fthp->push(sizeof(cell) * std::distance(fthp->here, fthp->dict.end())); }, 0
         , S{"_lit" }, lit_impl, 0
-        , S{"swap" }, [](auto) { auto [a, b] = fth.pop<2>(); fth.push(a, b); }, 0
-        , S{"drop" }, [](auto) { fth.pop(); }, 0
-        , S{"dup"  }, [](auto) { fth.push(fth.top()); }, 0
-        , S{"rot"  }, [](auto) { auto [a, b, c] = fth.pop<3>(); fth.push(b, a, c); }, 0
-        , S{"+"    }, [](auto) { fth.top() += fth.pop(); }, 0
-        , S{"-"    }, [](auto) { fth.top() -= fth.pop(); }, 0
-        , S{"*"    }, [](auto) { fth.top() *= fth.pop(); }, 0
-        , S{"/"    }, [](auto) { fth.top() /= fth.pop(); }, 0
-        , S{"mod"  }, [](auto) { fth.top() %= fth.pop(); }, 0
-        , S{"and"  }, [](auto) { fth.top() &= fth.pop(); }, 0
-        , S{"or"   }, [](auto) { fth.top() |= fth.pop(); }, 0
-        , S{"xor"  }, [](auto) { fth.top() ^= fth.pop(); }, 0
-        , S{"lshift"}, [](auto) { fth.top() <<= fth.pop(); }, 0
-        , S{"rshift"}, [](auto) { fth.top() >>= fth.pop(); }, 0
-        , S{"["    }, [](auto) { fth.compiling = false; }, word_base::immediate
-        , S{"]"    }, [](auto) { fth.compiling = true; }, 0
-        , S{"immediate"}, [](auto) { const_cast<word_base *>(fth.next)->make_immediate(); }, 0
+        , S{"swap" }, [](auto) { auto a = fthp->pop(); auto b = fthp->pop(); fthp->push(a, b); }, 0
+        , S{"drop" }, [](auto) { fthp->pop(); }, 0
+        , S{"dup"  }, [](auto) { fthp->push(fthp->top()); }, 0
+        , S{"rot"  }, [](auto) { auto a = fthp->pop(); auto b = fthp->pop(); auto c = fthp->pop();
+            fthp->push(b, a, c); }, 0
+        , S{"+"    }, [](auto) { fthp->top() += fthp->pop(); }, 0
+        , S{"-"    }, [](auto) { fthp->top() -= fthp->pop(); }, 0
+        , S{"*"    }, [](auto) { fthp->top() *= fthp->pop(); }, 0
+        , S{"/"    }, [](auto) { fthp->top() /= fthp->pop(); }, 0
+        , S{"mod"  }, [](auto) { fthp->top() %= fthp->pop(); }, 0
+        , S{"and"  }, [](auto) { fthp->top() &= fthp->pop(); }, 0
+        , S{"or"   }, [](auto) { fthp->top() |= fthp->pop(); }, 0
+        , S{"xor"  }, [](auto) { fthp->top() ^= fthp->pop(); }, 0
+        , S{"lshift"}, [](auto) { fthp->top() <<= fthp->pop(); }, 0
+        , S{"rshift"}, [](auto) { fthp->top() >>= fthp->pop(); }, 0
+        , S{"["    }, [](auto) { fthp->compiling = false; }, word_base::immediate
+        , S{"]"    }, [](auto) { fthp->compiling = true; }, 0
+        , S{"immediate"}, [](auto) { const_cast<word_base *>(fthp->next)->make_immediate(); }, 0
         , S{"literal"}, [](auto) {
-            //assert<error::compile_only_word>(fth.compiling);
-            *fth.here++ = std::bit_cast<cell>(&lit_impl);
-            *fth.here++ = fth.pop(); }, word_base::immediate
-        , S{"@"    }, [](auto) { fth.push(*std::bit_cast<cell *>(fth.pop())); }, 0
-        , S{"!"    }, [](auto) { auto [p, v] = fth.pop<2>(); *std::bit_cast<cell *>(p) = v; }, 0
-        , S{"c@"   }, [](auto) { fth.push(*std::bit_cast<char *>(fth.pop())); }, 0
-        , S{"c!"   }, [](auto) { auto [p, v] = fth.pop<2>(); *std::bit_cast<char *>(p) = v; }, 0
-        , S{"="    }, [](auto) { auto v = fth.pop(); fth.top() = -(fth.top() == v); }, 0
-        , S{"<"    }, [](auto) { auto v = fth.pop(); fth.top() = -(fth.top() < v); }, 0
+            //assert<error::compile_only_word>(fthp->compiling);
+            *fthp->here++ = std::bit_cast<cell>(&lit_impl);
+            *fthp->here++ = fthp->pop(); }, word_base::immediate
+        , S{"@"    }, [](auto) { fthp->push(*std::bit_cast<cell *>(fthp->pop())); }, 0
+        , S{"!"    }, [](auto) { auto p = fthp->pop(); *std::bit_cast<cell *>(p) = fthp->pop(); }, 0
+        , S{"c@"   }, [](auto) { fthp->push(*std::bit_cast<char *>(fthp->pop())); }, 0
+        , S{"c!"   }, [](auto) { auto p = fthp->pop(); *std::bit_cast<char *>(p) = fthp->pop(); }, 0
+        , S{"="    }, [](auto) { auto v = fthp->pop(); fthp->top() = -(fthp->top() == v); }, 0
+        , S{"<"    }, [](auto) { auto v = fthp->pop(); fthp->top() = -(fthp->top() < v); }, 0
         , S{"\'"   }, [](auto) {
-            auto w = fth.parse();
-            auto g = fth.get(w);
-            fth.push(g ? std::bit_cast<cell>((*g)->body()) : 0); }, 0
+            auto w = fthp->parse();
+            auto g = fthp->get(w);
+            fthp->push(g ? std::bit_cast<cell>((*g)->body()) : 0); }, 0
         , S{":"    }, [](auto) {
-            auto w = fth.parse();
-            fth.add(w);
-            *fth.here++ = std::bit_cast<cell>(prologue);
-            fth.compiling = true; }, 0
-        , S{";"    }, [](auto) { *fth.here++ = 0; fth.compiling = false; }, word_base::immediate
-        , S{"\\"   }, [](auto) { fth.sourcei = forth::npos; }, word_base::immediate
-        , S{"cell" }, [](auto) { fth.push(sizeof(cell)); }, 0
+            auto w = fthp->parse();
+            fthp->add(w);
+            *fthp->here++ = std::bit_cast<cell>(prologue);
+            fthp->compiling = true; }, 0
+        , S{";"    }, [](auto) { *fthp->here++ = 0; fthp->compiling = false; }, word_base::immediate
+        , S{"\\"   }, [](auto) { fthp->sourcei = std::string_view::npos; }, word_base::immediate
+        , S{"cell" }, [](auto) { fthp->push(sizeof(cell)); }, 0
         , S{"_jmp" }, [](auto) {
-            auto ptr = ++fth.ip;
-            fth.ip = *std::bit_cast<func **>(ptr) - 1; }, 0
+            auto ptr = ++fthp->ip;
+            fthp->ip = *std::bit_cast<func **>(ptr) - 1; }, 0
         , S{"_jmp0"}, [](auto) {
-            auto ptr = ++fth.ip;
-            if (fth.pop() == 0)
-                fth.ip = *std::bit_cast<func **>(ptr) - 1; }, 0
+            auto ptr = ++fthp->ip;
+            if (fthp->pop() == 0)
+                fthp->ip = *std::bit_cast<func **>(ptr) - 1; }, 0
         , S{"chars"}, [](auto) {}, 0
         , S{"postpone"}, [](auto) {
-            assert<error::compile_only_word>(fth.compiling);
-            auto w = fth.parse();
-            auto g = fth.get(w);
+            assert<error::compile_only_word>(fthp->compiling);
+            auto w = fthp->parse();
+            auto g = fthp->get(w);
             assert<error::word_not_found>(g.has_value());
-            *fth.here++ = std::bit_cast<cell>((*g)->body()); }, word_base::immediate
+            *fthp->here++ = std::bit_cast<cell>((*g)->body()); }, word_base::immediate
     >::word;
     constexpr static auto& dict2 = comp_dict<prologue, &dict1
         , S{"align"  }, S{"here dup aligned swap - allot"}, 0
@@ -320,8 +309,7 @@ void initialize(cell *end_value)
         , S{"bl"    }, S{"32"}, 0
     >::word;
 
-    fth.next = &dict2;
-    fth.end = end_value;
+    return &dict2;
 }
 
 } // namespace sforth
@@ -334,8 +322,7 @@ void initialize(cell *end_value)
 //static_assert(offsetof(forth, source)    == 5 * sizeof(cell));
 //static_assert(offsetof(forth, sourcei)   == 6 * sizeof(cell));
 //static_assert(offsetof(forth, compiling) == 7 * sizeof(cell));
-//static_assert(offsetof(forth, end)       == 8 * sizeof(cell));
-//static_assert(offsetof(forth, base)      == 9 * sizeof(cell));
+//static_assert(offsetof(forth, base)      == 8 * sizeof(cell));
 
 #endif // SFORTH_HPP