From e45926fa2a1bc332214f0467de6020529d91b7ba Mon Sep 17 00:00:00 2001 From: Clyne Sullivan Date: Thu, 16 Feb 2023 20:12:03 -0500 Subject: [PATCH] handle input within dictionary --- alee.cpp | 16 +++++- corewords.cpp | 60 +++++++++++++++++---- corewords.hpp | 8 +-- dictionary.cpp | 82 ++++++++++++++++++++++++---- dictionary.hpp | 16 ++++-- parser.cpp | 142 ++++++++++++++++++++++++++----------------------- parser.hpp | 4 ++ state.hpp | 5 +- types.hpp | 12 +++-- 9 files changed, 242 insertions(+), 103 deletions(-) diff --git a/alee.cpp b/alee.cpp index be71730..b38f8a0 100644 --- 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; diff --git a/corewords.cpp b/corewords.cpp index de5066e..6a47392 100644 --- a/corewords.cpp +++ b/corewords.cpp @@ -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; } diff --git a/corewords.hpp b/corewords.hpp index 24e1415..ed57dd6 100644 --- a/corewords.hpp +++ b/corewords.hpp @@ -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 diff --git a/dictionary.cpp b/dictionary.cpp index e047488..e1153cc 100644 --- a/dictionary.cpp +++ b/dictionary.cpp @@ -18,6 +18,8 @@ #include "dictionary.hpp" +#include + 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(lt + sizeof(Cell)), + static_cast(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; } diff --git a/dictionary.hpp b/dictionary.hpp index fd27920..b2c2107 100644 --- a/dictionary.hpp +++ b/dictionary.hpp @@ -28,9 +28,15 @@ 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: diff --git a/parser.cpp b/parser.cpp index d58b4ed..2d6e9ff 100644 --- a/parser.cpp +++ b/parser.cpp @@ -20,89 +20,99 @@ #include "executor.hpp" #include "parser.hpp" +#include #include 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(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(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; + //} diff --git a/parser.hpp b/parser.hpp index b45a5d0..49223f0 100644 --- a/parser.hpp +++ b/parser.hpp @@ -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 diff --git a/state.hpp b/state.hpp index e17d324..0308238 100644 --- 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); diff --git a/types.hpp b/types.hpp index 95f9ff1..5c4d358 100644 --- 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