aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClyne Sullivan <clyne@bitgloo.com>2024-11-30 13:03:08 -0500
committerClyne Sullivan <clyne@bitgloo.com>2024-11-30 13:03:08 -0500
commitd8b279b7709410112002828199b0261508a9dda4 (patch)
treeeac3982365a633c6650e840335dea6282db00fa1
parent5b81d9c76dd115375efdd73ef15da9c37ce0c6fc (diff)
roll our own from_chars
-rw-r--r--main.cpp10
-rw-r--r--sforth/comp_word.hpp11
-rw-r--r--sforth/forth.hpp14
-rw-r--r--sforth/native_word.hpp2
-rw-r--r--sforth/types.hpp32
5 files changed, 50 insertions, 19 deletions
diff --git a/main.cpp b/main.cpp
index 0cc5640..9453531 100644
--- 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) {
diff --git a/sforth/comp_word.hpp b/sforth/comp_word.hpp
index e75eee3..2b5978d 100644
--- a/sforth/comp_word.hpp
+++ b/sforth/comp_word.hpp
@@ -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++;
}
}
diff --git a/sforth/forth.hpp b/sforth/forth.hpp
index 320a466..9e0a59e 100644
--- a/sforth/forth.hpp
+++ b/sforth/forth.hpp
@@ -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
diff --git a/sforth/native_word.hpp b/sforth/native_word.hpp
index da69b09..e3cb867 100644
--- a/sforth/native_word.hpp
+++ b/sforth/native_word.hpp
@@ -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)
diff --git a/sforth/types.hpp b/sforth/types.hpp
index d908b8f..3d26581 100644
--- a/sforth/types.hpp
+++ b/sforth/types.hpp
@@ -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;
}