]> code.bitgloo.com Git - clyne/sforth.git/commitdiff
roll our own from_chars
authorClyne Sullivan <clyne@bitgloo.com>
Sat, 30 Nov 2024 18:03:08 +0000 (13:03 -0500)
committerClyne Sullivan <clyne@bitgloo.com>
Sat, 30 Nov 2024 18:03:08 +0000 (13:03 -0500)
main.cpp
sforth/comp_word.hpp
sforth/forth.hpp
sforth/native_word.hpp
sforth/types.hpp

index 0cc5640665747c7ac89326121a6edac988136866..9453531bf7567d88dba1d2dac1d428db039ac7c2 100644 (file)
--- a/main.cpp
+++ b/main.cpp
@@ -26,8 +26,13 @@ constinit static sforth::forth<1024> forth {sforth::initialize<&forth>()};
 
 constinit static sforth::native_word<".", [](auto) {
     char buf[32] = {};
-    std::to_chars(buf, buf + sizeof(buf), forth.pop(), forth.base);
-    std::cout << buf << ' ';
+    auto ptr = buf + sizeof(buf);
+    auto v = forth.pop();
+    *--ptr = '\0';
+    do {
+        *--ptr = "0123456789abcdefghijklmnopqrstuvwxyz"[v % forth.base];
+    } while (v /= forth.base);
+    std::cout << ptr << ' ';
 }> dot;
 constinit static sforth::native_word<"emit", [](auto) {
     std::cout << static_cast<char>(forth.pop());
@@ -39,7 +44,6 @@ int main(int argc, const char *argv[])
 {
     std::span args (argv + 1, argc - 1);
 
-
     dot.next = std::exchange(forth.next, &emit);
 
     for (auto arg : args) {
index e75eee3632fa377ff7bf7edeb10b8894a69a298f..2b5978d3c37ff88e399f1bcc09d574c56a528cdd 100644 (file)
@@ -19,7 +19,7 @@
 
 #include "native_word.hpp"
 
-#include <charconv>
+#include <utility>
 
 namespace sforth {
 
@@ -59,15 +59,16 @@ struct comp_word : public native_word<Name, Prol, Prev>
 
             auto w = Prev->get_ct(word);
             if (w) {
-                bptr->f = Prev->get_ct(word);
+                bptr->f = w;
                 bptr++;
             } else {
-                cell n;
-                std::from_chars(word.cbegin(), word.cend(), n, 10);
+                const auto n = from_chars<cell>(word, 10);
+                if (!n.has_value())
+                    std::unreachable();
 
                 bptr->f = Prev->get_ct("_lit");
                 bptr++;
-                bptr->c = n;
+                bptr->c = *n;
                 bptr++;
             }
         }
index 320a466de9e649b378541825ed0b6943d0a3a247..9e0a59edac04eff5cc6ef812a5da4976b380ab5d 100644 (file)
@@ -24,7 +24,6 @@
 #include <array>
 #include <bit>
 #include <cstddef>
-#include <charconv>
 #include <string_view>
 #include <utility>
 
@@ -64,7 +63,7 @@ inline auto error_string(error err) noexcept -> std::string_view
     }
 }
 
-
+#undef assert
 template<error Err>
 inline void assert(bool condition)
 {
@@ -139,13 +138,10 @@ struct forth : public word_list
             const auto word = parse();
 
             if (auto ent = get(word); !ent) {
-                cell n;
-                const auto [p, e] = std::from_chars(word.cbegin(), word.cend(),
-                    n, base);
-
-                assert<error::word_not_found>(e == std::errc() && p == word.cend());
+                const auto n = from_chars<cell>(word, base);
+                assert<error::word_not_found>(n.has_value());
 
-                push(n);
+                push(*n);
 
                 if (compiling)
                     execute((*get("literal"))->body());
@@ -299,9 +295,9 @@ constexpr auto initialize()
         , S{"char+" }, S{"1 +" }, 0
         , S{"-rot"  }, S{"rot rot"}, 0
         , S{"2drop" }, S{"drop drop"}, 0
-        , S{"0="    }, S{"0 ="}, 0
         , S{"0<"    }, S{"0 <"}, 0
         , S{"<>"    }, S{"= 0="}, 0
+        , S{"0="    }, S{"0 ="}, 0
         , S{">"     }, S{"swap <"}, 0
         , S{"invert"}, S{"-1 xor"}, 0
         , S{"negate"}, S{"-1 *"}, 0
index da69b095a7beee27e063f014d0e131d846758732..e3cb867b96e5366f68731087c9765c27b2a40023 100644 (file)
@@ -30,7 +30,7 @@ struct native_word : public word_base
     std::array<char, N> namebuf;
     func body;
 
-    consteval const func *get_ct(std::string_view name) const {
+    constexpr const func *get_ct(std::string_view name) const {
         if (name == std::string_view{Name.data})
             return &body;
         else if constexpr (Prev != nullptr)
index d908b8f80fc4d5bfefacbeaabb00cec476643641..3d26581816bad1950c53ccef1b98748d6e49ca11 100644 (file)
@@ -31,6 +31,36 @@ using func = void (*)(const void *);
 
 struct word_base;
 
+template<typename T>
+constexpr std::optional<T> from_chars(std::string_view sv, int base = 10)
+{
+    T res {};
+    bool neg = false;
+
+    for (auto ch : sv) {
+        if (ch >= '0' && ch <= '9') {
+            if (ch - '0' < base) {
+                res *= base;
+                res += ch - '0';
+            } else return {};
+        } else if (ch >= 'A' && ch <= 'Z') {
+            if (base > 10 && ch - 'A' < base - 10) {
+                res *= base;
+                res += ch - 'A';
+            } else return {};
+        } else if (ch >= 'a' && ch <= 'z') {
+            if (base > 10 && ch - 'a' < base - 10) {
+                res *= base;
+                res += ch - 'a';
+            } else return {};
+        } else if (ch == '-' && res == 0) {
+            neg = true;
+        } else return {};
+    }
+
+    return neg ? -res : res;
+}
+
 struct word_list
 {
     const word_base *next;
@@ -45,7 +75,7 @@ struct word_list
         const auto e = sv.find_first_of(" \t\r\n", sourcei);
         const auto word = e != std::string_view::npos ?
             sv.substr(sourcei, e - sourcei) : sv.substr(sourcei);
-    
+
         sourcei = sv.find_first_not_of(" \t\r\n", e);
         return word;
     }