]> code.bitgloo.com Git - bitgloo/alee-forth.git/commitdiff
size reduction and refactoring
authorClyne Sullivan <clyne@bitgloo.com>
Fri, 10 Mar 2023 16:36:30 +0000 (11:36 -0500)
committerClyne Sullivan <clyne@bitgloo.com>
Fri, 10 Mar 2023 16:36:30 +0000 (11:36 -0500)
README.md
alee-msp430.cpp
libalee/corewords.cpp
libalee/ctype.cpp [new file with mode: 0644]
libalee/ctype.hpp [new file with mode: 0644]
libalee/dictionary.cpp
libalee/dictionary.hpp
libalee/parser.cpp

index b59c46310ee2fc204fee50ee479c424782414fea..bf8bf9d36c939dddeca2beb9fcae70d948ad1643 100644 (file)
--- a/README.md
+++ b/README.md
@@ -10,7 +10,7 @@ The goal of portability extends down to microcontroller targets with kilobytes o
 
 System-specific functionality is obtained through a `sys` Forth word. This word calls a user-supplied C++ function that implements the necessary (or any additional) functionality.
 
-# Forth compatibility
+## Forth compatibility
 
 Alee implements a large majority of the "core" and "core extension" [word sets](https://forth-standard.org/standard/core). Implementation is tracked in `compat.txt`, with missing words listed below. Fundamental words are built into Alee (written in C++); the rest of the implementation is in `core.fth` and `core-ext.fth`.
 
@@ -41,3 +41,5 @@ The `msp430` target builds Alee for the [MSP430G2553](https://www.ti.com/product
 
 Configurable constants and types are defined either in the Makefile or in `types.hpp`.
 
+   text           data     bss     dec     hex filename
+   8528              8     252    8788    2254 alee-msp430
index 4116118ff7c07079f267ca03dd97f8627bbf4061..3121dc1a64bde86120be35bab8711eb964c08ca4 100644 (file)
@@ -17,9 +17,9 @@
  */
 
 #include "alee.hpp"
+#include "libalee/ctype.hpp"
 #include "splitmemdict.hpp"
 
-#include <cctype>
 #include <msp430.h>
 
 #include "core.fth.h"
@@ -149,10 +149,10 @@ void user_sys(State& state)
         break;
     case 2:
         { auto addr = state.pop();
-          *((uint8_t *)addr) = state.pop(); }
+          *reinterpret_cast<uint8_t *>(addr) = state.pop(); }
         break;
     case 3:
-        state.push(*((uint8_t *)state.pop()));
+        state.push(*reinterpret_cast<uint8_t *>(state.pop()));
         break;
     default:
         break;
index 1d705f44ab2493001678d56589d011dc9629f954..ced3973405d61e948a0e9989a9bcc1e5f8980b13 100644 (file)
@@ -214,22 +214,22 @@ execute:
     state.ip += sizeof(Cell);
 }
 
-template<class Comp>
-int findi(Comp comp)
+template<typename Iter>
+int findi(Iter it, int size)
 {
-    std::size_t i = 0;
+    auto ptr = CoreWords::wordsarr;
     int wordsi = 0;
 
-    while (i < sizeof(CoreWords::wordsarr)) {
-        auto end = i;
-        while (CoreWords::wordsarr[end])
+    while (ptr < CoreWords::wordsarr + sizeof(CoreWords::wordsarr)) {
+        auto end = ptr;
+        while (*end)
             ++end;
 
-        if (comp(CoreWords::wordsarr + i, end - i))
+        if (end - ptr == size &&  Dictionary::equal(ptr, end, it))
             return wordsi;
 
         ++wordsi;
-        i = end + 1;
+        ptr = end + 1;
     }
 
     return -1;
@@ -237,13 +237,11 @@ int findi(Comp comp)
 
 int CoreWords::findi(const char *word)
 {
-    return ::findi([word](auto b, auto e) {
-        return !std::strncmp(word, b, e); });
+    return ::findi(word, strlen(word));
 }
 
 int CoreWords::findi(State& state, Word word)
 {
-    return ::findi([state, word](auto b, auto e) {
-        return state.dict.equal(word, b, e); });
+    return ::findi(word.begin(&state.dict), word.size());
 }
 
diff --git a/libalee/ctype.cpp b/libalee/ctype.cpp
new file mode 100644 (file)
index 0000000..a0c8dc1
--- /dev/null
@@ -0,0 +1,52 @@
+/**
+ * Alee Forth: A portable and concise Forth implementation in modern C++.
+ * Copyright (C) 2023  Clyne Sullivan <clyne@bitgloo.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "ctype.hpp"
+
+bool isspace(uint8_t c) {
+    return c == ' ' || c == '\t' || c == '\r' || c == '\n';
+}
+
+bool isspace(char c) {
+    return isspace(static_cast<uint8_t>(c));
+}
+
+bool isdigit(uint8_t c) {
+    return c >= '0' && c <= '9';
+}
+
+bool isdigit(char c) {
+    return isdigit(static_cast<uint8_t>(c));
+}
+
+bool isalpha(uint8_t c) {
+    return isupper(c) || (c >= 'a' && c <= 'z');
+}
+
+bool isalpha(char c) {
+    return isalpha(static_cast<uint8_t>(c));
+}
+
+bool isupper(uint8_t c) {
+    return c >= 'A' && c <= 'Z';
+}
+
+bool isupper(char c) {
+    return isupper(static_cast<uint8_t>(c));
+}
+
diff --git a/libalee/ctype.hpp b/libalee/ctype.hpp
new file mode 100644 (file)
index 0000000..d1a1d0b
--- /dev/null
@@ -0,0 +1,37 @@
+/**
+ * Alee Forth: A portable and concise Forth implementation in modern C++.
+ * Copyright (C) 2023  Clyne Sullivan <clyne@bitgloo.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef ALEEFORTH_CTYPE_HPP
+#define ALEEFORTH_CTYPE_HPP
+
+#include <cstdint>
+
+bool isspace(uint8_t);
+bool isspace(char);
+
+bool isdigit(uint8_t);
+bool isdigit(char);
+
+bool isalpha(uint8_t);
+bool isalpha(char);
+
+bool isupper(uint8_t);
+bool isupper(char);
+
+#endif // ALEEFORTH_CTYPE_HPP
+
index 8b617a9d92790da73224c49c96f24070925cc09f..81b5c646f6cfa2cabacdd145183985f518783db3 100644 (file)
@@ -16,9 +16,9 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 
+#include "ctype.hpp"
 #include "dictionary.hpp"
 
-#include <cctype>
 #include <cstring>
 
 void Dictionary::initialize()
@@ -68,9 +68,8 @@ void Dictionary::addDefinition(Word word) noexcept
 
 Addr Dictionary::find(Word word) noexcept
 {
-    Addr lt = latest(), oldlt;
-    do {
-        oldlt = lt;
+    Addr lt = latest();
+    for (;;) {
         const auto l = static_cast<Addr>(read(lt));
         const Addr len = l & 0x1F;
         const Word lw {
@@ -80,9 +79,11 @@ Addr Dictionary::find(Word word) noexcept
 
         if (equal(word, lw))
             return lt;
+        else if (lt == Begin)
+            break;
         else
             lt -= l >> 6;
-    } while (lt != oldlt);
+    }
 
     return 0;
 }
@@ -124,29 +125,21 @@ Word Dictionary::input() noexcept
     return word;
 }
 
-#include <algorithm>
-
 bool Dictionary::equal(Word word, const char *str, unsigned len) const noexcept
 {
-    if (word.size() != len)
-        return false;
-
-    return std::equal(word.begin(this), word.end(this), str,
-        [](auto wc, auto oc) {
-            return wc == oc ||
-                   (isalpha(wc) && isalpha(oc) && (wc | 32) == (oc | 32));
-        });
+    return word.size() == len &&
+           equal(word.begin(this), word.end(this), str);
 }
 
 bool Dictionary::equal(Word word, Word other) const noexcept
 {
-    if (word.size() != other.size())
-        return false;
-
-    return std::equal(word.begin(this), word.end(this), other.begin(this),
-        [](auto wc, auto oc) {
-            return wc == oc ||
-                   (isalpha(wc) && isalpha(oc) && (wc | 32) == (oc | 32));
-        });
+    return word.size() == other.size() &&
+           equal(word.begin(this), word.end(this), other.begin(this));
+}
+
+bool Dictionary::eqchars(char c1, char c2)
+{
+    return c1 == c2 ||
+        (isalpha(c1) && isalpha(c2) && (c1 | 32) == (c2 | 32));
 }
 
index 0a2e4d305934a2332284b90bc89cb7413461b446..53172d22b0e5bccd7f5690584faf63732a7c5a4b 100644 (file)
@@ -21,6 +21,7 @@
 
 #include "types.hpp"
 
+#include <algorithm>
 #include <cstddef>
 #include <cstdint>
 
@@ -74,7 +75,15 @@ public:
     bool equal(Word, const char *, unsigned) const noexcept;
     bool equal(Word, Word) const noexcept;
 
+    template<typename Iter1, typename Iter2>
+    static bool equal(Iter1 b1, Iter1 e1, Iter2 b2) {
+        return std::equal(b1, e1, b2, eqchars);
+    }
+
     virtual ~Dictionary() = default;
+
+private:
+    static bool eqchars(char c1, char c2);
 };
 
 #endif // ALEEFORTH_DICTIONARY_HPP
index bcef9637390b4b4d131f36e062893386d2e73cae..3b1422418c461998665e8ae8eae302c593ca93c7 100644 (file)
@@ -17,9 +17,9 @@
  */
 
 #include "corewords.hpp"
+#include "ctype.hpp"
 #include "parser.hpp"
 
-#include <cctype>
 #include <cstring>
 
 int Parser::parse(State& state, const char *str)