]> code.bitgloo.com Git - bitgloo/alee-forth.git/commitdiff
handle input within dictionary
authorClyne Sullivan <clyne@bitgloo.com>
Fri, 17 Feb 2023 01:12:03 +0000 (20:12 -0500)
committerClyne Sullivan <clyne@bitgloo.com>
Fri, 17 Feb 2023 01:12:03 +0000 (20:12 -0500)
alee.cpp
corewords.cpp
corewords.hpp
dictionary.cpp
dictionary.hpp
parser.cpp
parser.hpp
state.hpp
types.hpp

index be717309d184e0daf1a0ea0055c69060441d49f6..b38f8a0c0cbcce097208c88ac5ccc9a58ef98ce5 100644 (file)
--- a/alee.cpp
+++ b/alee.cpp
@@ -28,10 +28,23 @@ static bool okay = false;
 static void parseLine(Parser&, State&, std::string_view);
 static void parseFile(Parser&, State&, std::istream&);
 
+static void readchar(State& state)
+{
+    auto len = state.dict.read(Dictionary::Input);
+    Addr addr = Dictionary::Input + sizeof(Cell) +
+                Dictionary::InputCells - len - 1;
+
+    for (Addr i = 0; i < len; ++i, ++addr)
+        state.dict.writebyte(addr, state.dict.readbyte(addr + 1));
+
+    state.dict.writebyte(addr, std::cin.get());
+    state.dict.write(Dictionary::Input, len + 1);
+}
+
 int main(int argc, char *argv[])
 {
     MemDict dict;
-    State state (dict);
+    State state (dict, readchar);
     Parser parser;
 
     std::vector args (argv + 1, argv + argc);
@@ -41,7 +54,6 @@ int main(int argc, char *argv[])
     }
 
     okay = true;
-    //std::cout << state.size() << ' ' << state.compiling << "> ";
     parseFile(parser, state, std::cin);
 
     return 0;
index de5066ef096053608a832894a3e7fad2dc7d2144..6a47392326996afc14cea29d21f75fa40c5108ef 100644 (file)
@@ -46,7 +46,7 @@ Func CoreWords::get(int index)
     case 22: return op_shr;
     case 23: return op_comment;
     case 24: return op_colon;
-    case 25: return op_semic;
+    case 25: return op_semic; // :267
     case 26: return op_here;
     case 27: return op_imm;
     case 28: return op_const;
@@ -203,13 +203,24 @@ int CoreWords::op_shr(State& state) {
 }
 
 int CoreWords::op_comment(State& state) {
-    state.pass = Pass::Comment;
+    do {
+        op_key(state);
+    } while (state.pop() != ')');
     return 0;
 }
 
 int CoreWords::op_colon(State& state) {
-    state.pass = Pass::Colon;
-    state.pushr(state.dict.alignhere());
+    if (state.compiling()) {
+        Word word = state.dict.input();
+        while (word.size() == 0) {
+            state.input(state);
+            word = state.dict.input();
+        }
+
+        state.pushr(state.dict.alignhere());
+        state.dict.addDefinition(word);
+    }
+
     return 0;
 }
 
@@ -244,8 +255,22 @@ int CoreWords::op_imm(State& state)
 
 int CoreWords::op_const(State& state)
 {
-    state.pass = Pass::Constant;
-    state.pushr(state.dict.alignhere());
+    if (state.compiling()) {
+        Word word = state.dict.input();
+        while (word.size() == 0) {
+            state.input(state);
+            word = state.dict.input();
+        }
+
+        state.pushr(state.dict.alignhere());
+        state.dict.addDefinition(word);
+        state.dict.add(CoreWords::HiddenWordLiteral);
+        state.dict.add(state.pop());
+        state.dict.add(25 | CoreImmediate);
+        op_semic(state);
+        state.compiling(false);
+    }
+
     return 0;
 }
 
@@ -309,7 +334,22 @@ int CoreWords::op_depth(State& state)
     return 0;
 }
 
-int CoreWords::findi(std::string_view str)
+int CoreWords::op_key(State& state)
+{
+    auto len = state.dict.read(Dictionary::Input);
+    while (len <= 0)
+        state.input(state);
+
+    state.dict.write(Dictionary::Input, len - 1);
+    Addr addr = Dictionary::Input + sizeof(Cell) +
+                Dictionary::InputCells - len;
+    Cell val = state.dict.readbyte(addr);
+
+    state.push(val);
+    return 0;
+}
+
+int CoreWords::findi(State& state, Word word)
 {
     std::size_t i;
     int wordsi = 0;
@@ -319,7 +359,7 @@ int CoreWords::findi(std::string_view str)
     for (i = 0; i < words.size();) {
         const auto end = words.find_first_of({"\0\1", 2}, i);
 
-        if (words.compare(i, end - i, str) == 0)
+        if (state.dict.equal(word, words.substr(i, end - i)))
             return words[end] == '\0' ? wordsi : (wordsi | CoreImmediate);
 
         ++wordsi;
@@ -329,9 +369,9 @@ int CoreWords::findi(std::string_view str)
     return -1;
 }
 
-Func CoreWords::find(std::string_view str)
+Func CoreWords::find(State& state, Word word)
 {
-    const auto i = findi(str);
+    const auto i = findi(state, word);
     return i >= 0 ? get(i & ~CoreWords::CoreImmediate) : nullptr;
 }
 
index 24e1415068719672d858892eea7e0d39d11a2220..ed57dd6f215ed43f346fb17f265d577fff8b4b04 100644 (file)
@@ -35,8 +35,8 @@ public:
     constexpr static Cell Immediate     = (1 << 5);
     constexpr static Cell CoreImmediate = (1 << 6);
 
-    static int findi(std::string_view);
-    static Func find(std::string_view);
+    static int findi(State&, Word);
+    static Func find(State&, Word);
     static void run(int, State&);
 
 private:
@@ -45,7 +45,7 @@ private:
         "+\0-\0*\0/\0%\0"
         "_@\0_!\0rot\0>r\0r>\0"
         "=\0<\0allot\0&\0|\0"
-        "^\0<<\0>>\0(\0:\0"
+        "^\0<<\0>>\0(\0:\1"
         ";\1here\0imm\0const\0"
         "if\1then\1else\1depth\0";
 
@@ -86,6 +86,8 @@ private:
     static int op_then(State&);
     static int op_else(State&);
     static int op_depth(State&);
+    static int op_key(State&);
+    static int op_word(State&);
 };
 
 #endif // ALEEFORTH_COREWORDS_HPP
index e047488159c5022161ff6b1e597c744a9dae0f3c..e1153cc9721e37105c161db2441e60371fc69ba7 100644 (file)
@@ -18,6 +18,8 @@
 
 #include "dictionary.hpp"
 
+#include <cctype>
+
 Addr Dictionary::allot(Cell amount)
 {
     Addr old = here;
@@ -38,11 +40,11 @@ Addr Dictionary::alignhere()
     return here;
 }
 
-void Dictionary::addDefinition(std::string_view str)
+void Dictionary::addDefinition(Word word)
 {
-    add(str.size());
-    for (char c : str)
-        add(c);
+    add(word.size());
+    for (unsigned i = 0; i < word.size(); ++i)
+        writebyte(allot(1), readbyte(word.start + i));
 }
 
 bool Dictionary::issame(Addr addr, std::string_view str, std::size_t n)
@@ -60,7 +62,7 @@ bool Dictionary::issame(Addr addr, std::string_view str, std::size_t n)
     return true;
 }
 
-Addr Dictionary::find(std::string_view str)
+Addr Dictionary::find(Word word)
 {
     if (latest == 0)
         return 0;
@@ -68,10 +70,14 @@ Addr Dictionary::find(std::string_view str)
     Addr lt = latest, oldlt;
     do {
         oldlt = lt;
-        const auto l = read(lt);
-        const auto len = l & 0x1F;
-
-        if (issame(lt + sizeof(Cell), str, len))
+        const Cell l = read(lt);
+        const Addr len = l & 0x1F;
+        const Word lw {
+            static_cast<Addr>(lt + sizeof(Cell)),
+            static_cast<Addr>(lt + sizeof(Cell) + len)
+        };
+
+        if (equal(word, lw))
             return lt;
         else
             lt -= l >> 6;
@@ -83,6 +89,62 @@ Addr Dictionary::find(std::string_view str)
 Addr Dictionary::getexec(Addr addr)
 {
     const auto len = read(addr) & 0x1F;
-    return addr + (1 + len) * sizeof(Cell);
+    return addr + sizeof(Cell) + len;
+}
+
+Word Dictionary::input()
+{
+    const auto len = read(Dictionary::Input);
+    if (len == 0)
+        return {};
+
+    Addr wordstart = Dictionary::Input + sizeof(Cell) + Dictionary::InputCells
+                     - len;
+    Addr wordend = wordstart;
+
+    auto cnt = len;
+    while (cnt) {
+        auto b = readbyte(wordend);
+        if (isspace(b) || b == '\0') {
+            if (wordstart != wordend) {
+                Word word {wordstart, wordend};
+                writebyte(Dictionary::Input, cnt - 1);
+                return word;
+            } else {
+                ++wordstart;
+            }
+        }
+
+        ++wordend;
+        --cnt;
+    }
+
+    return {};
+}
+
+bool Dictionary::equal(Word word, std::string_view sv) const
+{
+    if (sv.size() != word.end - word.start)
+        return false;
+
+    for (unsigned i = 0; i < sv.size(); ++i) {
+        if (sv[i] != readbyte(word.start + i))
+            return false;
+    }
+
+    return true;
+}
+
+bool Dictionary::equal(Word word, Word other) const
+{
+    if (word.size() != other.size())
+        return false;
+
+    for (unsigned i = 0; i < word.size(); ++i) {
+        if (readbyte(word.start + i) != readbyte(other.start + i))
+            return false;
+    }
+
+    return true;
 }
 
index fd27920420c41964ce8aa127631459d744174fd1..b2c2107692b8a2487a4501ec5487682fcee8373e 100644 (file)
 class Dictionary
 {
 public:
-    constexpr static Addr Base      = 0 * sizeof(Cell);
-    constexpr static Addr Compiling = 1 * sizeof(Cell);
-    constexpr static Addr Begin     = 2 * sizeof(Cell);
+    constexpr static Addr Base       = 0;
+    constexpr static Addr Compiling  = Base + sizeof(Cell);
+    constexpr static Addr Input      = Compiling + sizeof(Cell); // len data...
+    constexpr static Addr InputCells = 80; // bytes!
+    constexpr static Addr Begin      = Input + sizeof(Cell) + InputCells;
+
+    Word input();
+    bool equal(Word, std::string_view) const;
+    bool equal(Word, Word) const;
 
     Addr here = Begin;
     Addr latest = Begin;
@@ -43,8 +49,8 @@ public:
     Addr alignhere();
     Addr allot(Cell);
     void add(Cell);
-    void addDefinition(std::string_view);
-    Addr find(std::string_view);
+    void addDefinition(Word);
+    Addr find(Word);
     Addr getexec(Addr);
 
 private:
index d58b4ed598e4d646e73ec84fb39cb8c541204631..2d6e9ffdac7c05a0e2411835b36b29eb75663727 100644 (file)
 #include "executor.hpp"
 #include "parser.hpp"
 
+#include <cctype>
 #include <cstdlib>
 
 ParseStatus Parser::parse(State& state, std::string_view& str)
 {
-    const auto end = str.find_first_of(" \t\n\r");
-    const auto sub = str.substr(0, end);
-    if (sub.empty())
-        return ParseStatus::Finished;
+    auto addr = Dictionary::Input;
+    state.dict.write(addr, str.size() + 1);
 
-    if (state.pass != Pass::None) {
-        switch (state.pass) {
-        case Pass::Comment:
-            if (str.front() == ')')
-                state.pass = Pass::None;
+    addr += sizeof(Cell) + Dictionary::InputCells - str.size() - 1;
+    for (char c : str)
+        state.dict.writebyte(addr++, c);
+    state.dict.writebyte(addr, '\0');
 
-            str = str.substr(1);
-            break;
-        case Pass::Colon:
-            state.pass = Pass::None;
-            state.compiling(true);
-            state.dict.addDefinition(sub);
-            break;
-        case Pass::Constant:
-            state.pass = Pass::None;
+    return parseSource(state);
+}
+
+ParseStatus Parser::parseSource(State& state)
+{
+    auto word = state.dict.input();
+    while (word.size() > 0) {
+        if (auto ret = parseWord(state, word); ret == ParseStatus::Error)
+            return ret;
+
+        word = state.dict.input();
+    }
+
+    return ParseStatus::Finished;
+}
+
+ParseStatus Parser::parseWord(State& state, Word word)
+{
+    if (auto i = CoreWords::findi(state, word); i >= 0) {
+        if (state.compiling()) {
+            state.dict.add(i & ~CoreWords::CoreImmediate);
+        } else if (state.dict.equal(word, ":")) {
             state.compiling(true);
-            state.dict.addDefinition(sub);
-            state.dict.add(CoreWords::HiddenWordLiteral);
-            state.dict.add(state.pop());
-            state.dict.add(CoreWords::findi(";"));
-            CoreWords::run(CoreWords::findi(";"), state);
-            break;
-        default:
-            break;
         }
-    } else {
-        if (auto i = CoreWords::findi(sub); i >= 0) {
-            if (state.compiling())
-                state.dict.add(i & ~CoreWords::CoreImmediate);
-            if (!state.compiling() || (i & CoreWords::CoreImmediate))
-                CoreWords::run(i & ~CoreWords::CoreImmediate, state);
-        } else if (auto j = state.dict.find(sub); j > 0) {
-            auto e = state.dict.getexec(j);
 
-            if (state.compiling()) {
-                if (state.dict.read(j) & CoreWords::Immediate) {
-                    state.compiling(false);
-                    Executor::fullexec(state, e);
-                    state.compiling(true);
-                } else {
-                    state.dict.add(CoreWords::HiddenWordJump);
-                    state.dict.add(e);
-                }
-            } else {
+        if (!state.compiling() || (i & CoreWords::CoreImmediate))
+            CoreWords::run(i & ~CoreWords::CoreImmediate, state);
+    } else if (auto j = state.dict.find(word); j > 0) {
+        auto e = state.dict.getexec(j);
+
+        if (state.compiling()) {
+            if (state.dict.read(j) & CoreWords::Immediate) {
+                state.compiling(false);
                 Executor::fullexec(state, e);
+                state.compiling(true);
+            } else {
+                state.dict.add(CoreWords::HiddenWordJump);
+                state.dict.add(e);
             }
         } else {
-            char *p;
-            const auto base = state.dict.read(0);
-            const auto l = static_cast<Cell>(std::strtol(sub.data(), &p, base));
+            Executor::fullexec(state, e);
+        }
+    } else {
+        char buf[word.size()];
+        for (unsigned i = 0; i < word.size(); ++i)
+            buf[i] = state.dict.readbyte(word.start + i);
+
+        char *p;
+        const auto base = state.dict.read(0);
+        const auto l = static_cast<Cell>(std::strtol(buf, &p, base));
 
-            if (p != sub.data()) {
-                if (state.compiling()) {
-                    state.dict.add(CoreWords::HiddenWordLiteral);
-                    state.dict.add(l);
-                } else {
-                    state.push(l);
-                }
+        if (p != buf) {
+            if (state.compiling()) {
+                state.dict.add(CoreWords::HiddenWordLiteral);
+                state.dict.add(l);
             } else {
-                return ParseStatus::Error;
+                state.push(l);
             }
+        } else {
+            return ParseStatus::Error;
         }
-
-        if (end == std::string_view::npos)
-            return ParseStatus::Finished;
     }
 
-    const auto next = str.find_first_not_of(" \t\n\r", end);
-
-    if (next == std::string_view::npos) {
-        return ParseStatus::Finished;
-    } else {
-        str = str.substr(next);
-        return ParseStatus::Continue;
-    }
+    return ParseStatus::Finished;
 }
 
+        //case Pass::Colon:
+        //    state.pass = Pass::None;
+        //    state.compiling(true);
+        //    state.dict.addDefinition(sub);
+        //    break;
+        //case Pass::Constant:
+        //    state.pass = Pass::None;
+        //    state.compiling(true);
+        //    state.dict.addDefinition(sub);
+        //    state.dict.add(CoreWords::HiddenWordLiteral);
+        //    state.dict.add(state.pop());
+        //    state.dict.add(CoreWords::findi(";"));
+        //    CoreWords::run(CoreWords::findi(";"), state);
+        //    break;
+        //default:
+        //    break;
+        //}
index b45a5d0b07f7b063ba0182620cf27b5a29562701..49223f052e7446498514bbcb1096897858ebdf59 100644 (file)
@@ -27,6 +27,10 @@ class Parser
 {
 public:
     ParseStatus parse(State&, std::string_view&);
+
+private:
+    ParseStatus parseSource(State&);
+    ParseStatus parseWord(State&, Word);
 };
 
 #endif // ALEEFORTH_PARSER_HPP
index e17d324288ed680bfdf80980b864aea79a911947..0308238b331277d5be855829eabd31c0050a7d7e 100644 (file)
--- a/state.hpp
+++ b/state.hpp
@@ -36,10 +36,11 @@ class State
 
 public:
     Addr ip = 0;
-    Pass pass = Pass::None;
     Dictionary& dict;
+    void (*input)(State&);
 
-    constexpr State(Dictionary& d): dict(d) {}
+    constexpr State(Dictionary& d, void (*i)(State&)):
+        dict(d), input(i) {}
 
     bool compiling() const;
     void compiling(bool);
index 95f9ff100777b8787807bf170035822817f6a8a4..5c4d3582ca81bf97e6082579d16366e50908ccad 100644 (file)
--- a/types.hpp
+++ b/types.hpp
@@ -28,12 +28,14 @@ using Addr = uint16_t;
 using Cell = int16_t;
 using Func = int (*)(State&);
 
-enum class Pass
+struct Word
 {
-    None,
-    Comment,
-    Colon,
-    Constant
+    Addr start = 0;
+    Addr end = 0;
+
+    unsigned size() const noexcept {
+        return end - start;
+    }
 };
 
 enum class ParseStatus