From 15c0c2f789902ac764919913e123466ac46e4746 Mon Sep 17 00:00:00 2001 From: Clyne Sullivan Date: Thu, 12 Oct 2023 20:23:50 -0400 Subject: [PATCH] some class refactoring --- libalee/corewords.cpp | 26 ++++++---------------- libalee/dictionary.cpp | 47 +++++++++++++++++++++++++++++----------- libalee/dictionary.hpp | 1 + libalee/parser.cpp | 20 ++++++++--------- libalee/state.hpp | 49 +++++++++++++++++++++--------------------- libalee/types.cpp | 7 ++++++ libalee/types.hpp | 12 ++++++----- 7 files changed, 90 insertions(+), 72 deletions(-) diff --git a/libalee/corewords.cpp b/libalee/corewords.cpp index 1344ca0..34125bd 100644 --- a/libalee/corewords.cpp +++ b/libalee/corewords.cpp @@ -22,23 +22,6 @@ #include #include -Word getword(State& state) -{ - auto word = state.dict.input(); - while (word.size() == 0) { - state.input(state); - word = state.dict.input(); - } - return word; -} -void newdef(State& state, Word word) -{ - auto& dict = state.dict; - - auto addr = dict.alignhere(); - dict.addDefinition(word); - state.push(addr); -}; void find(State& state, Word word) { if (auto j = state.dict.find(word); j > 0) { @@ -169,11 +152,16 @@ execute: reinterpret_cast(state.top()) >>= static_cast(cell); break; case 22: // colon - newdef(state, getword(state)); + state.push(state.dict.alignhere()); + while (!state.dict.hasInput()) + state.input(state); + state.dict.addDefinition(state.dict.input()); state.compiling(true); break; case 23: // tick - find(state, getword(state)); + while (!state.dict.hasInput()) + state.input(state); + find(state, state.dict.input()); break; case 24: // execute index = state.pop(); diff --git a/libalee/dictionary.cpp b/libalee/dictionary.cpp index 7ae0043..64c0ac2 100644 --- a/libalee/dictionary.cpp +++ b/libalee/dictionary.cpp @@ -71,8 +71,11 @@ void Dictionary::addDefinition(Word word) noexcept Cell wsize = word.size(); add(wsize); - for (auto w = word.start; w != word.wend; ++w) - writebyte(allot(1), readbyte(w)); + auto it = word.begin(this); + const auto end = word.end(this); + + while (it != end) + writebyte(allot(1), *it++); alignhere(); } @@ -83,10 +86,8 @@ Addr Dictionary::find(Word word) noexcept for (;;) { const Addr l = read(lt); const Addr len = l & 0x1F; - Word lw; - lw.start = lt + sizeof(Cell); - lw.wend = lw.start + len; + const auto lw = Word::fromLength(lt + sizeof(Cell), len); if (equal(word, lw)) return lt; else if (lt == Begin) @@ -106,34 +107,54 @@ Addr Dictionary::getexec(Addr addr) noexcept return aligned(addr); } +bool Dictionary::hasInput() const noexcept +{ + const Addr src = read(Dictionary::Source); + const Addr end = read(Dictionary::SourceLen); + uint8_t idx = read(Dictionary::Input) & 0xFFu; + + while (idx < end) { + auto ch = readbyte(src + idx); + + if (ch == '\0') { + break; + } else if (!isspace(ch)) { + return true; + } + + ++idx; + } + + return false; +} + Word Dictionary::input() noexcept { const Addr src = read(Dictionary::Source); const Addr end = read(Dictionary::SourceLen); uint8_t idx = read(Dictionary::Input) & 0xFFu; - Word word; - word.start = src + idx; - word.wend = word.start; + Addr wstart = src + idx; + Addr wend = wstart; while (idx < end) { - auto ch = readbyte(word.wend); + auto ch = readbyte(wend); if (isspace(ch)) { - if (word.size() > 0) + if (wend - wstart > 0) break; - ++word.start; + ++wstart; } else if (ch == '\0') { break; } - ++word.wend; + ++wend; ++idx; } writebyte(Dictionary::Input, ++idx); - return word; + return Word(wstart, wend); } bool Dictionary::equal(Word word, const char *str, unsigned len) const noexcept diff --git a/libalee/dictionary.hpp b/libalee/dictionary.hpp index 2f17a77..14366a5 100644 --- a/libalee/dictionary.hpp +++ b/libalee/dictionary.hpp @@ -109,6 +109,7 @@ public: * Returns an empty word if the buffer is empty or entirely read. */ Word input() noexcept; + bool hasInput() const noexcept; /** * Checks if this dictionary's word is equivalent to the given string/size. diff --git a/libalee/parser.cpp b/libalee/parser.cpp index cdec1a5..2b1d8e1 100644 --- a/libalee/parser.cpp +++ b/libalee/parser.cpp @@ -85,15 +85,16 @@ Error Parser::parseNumber(State& state, Word word) { const auto base = state.dict.read(Dictionary::Base); DoubleCell result = 0; - auto i = word.start; - bool inv; - char c; + auto it = word.begin(&state.dict); - c = state.dict.readbyte(i); - if (inv = c == '-'; inv) - c = state.dict.readbyte(++i); + bool inv = *it == '-'; + if (inv) + ++it; + + const auto end = word.end(&state.dict); + for (char c; it != end; ++it) { + c = *it; - do { if (isdigit(c)) { result *= base; result += c - '0'; @@ -103,10 +104,7 @@ Error Parser::parseNumber(State& state, Word word) } else { return Error::noword; } - - if (++i < word.wend) - c = state.dict.readbyte(i); - } while (i < word.wend); + } if (inv) result *= -1; diff --git a/libalee/state.hpp b/libalee/state.hpp index 4c74f9a..3a79693 100644 --- a/libalee/state.hpp +++ b/libalee/state.hpp @@ -31,11 +31,12 @@ constexpr unsigned ReturnStackSize = 16; class State { + friend class CoreWords; + public: Addr ip = 0; Dictionary& dict; void (*input)(State&); // User-provided function to collect "stdin" input. - std::jmp_buf jmpbuf = {}; // Used when catching execution errors. constexpr State(Dictionary& d, void (*i)(State&)): dict(d), input(i) {} @@ -43,17 +44,6 @@ public: bool compiling() const; void compiling(bool); - /** - * Saves execution state so that a new execution can begin. - * Used for EVALUATE. - */ - std::pair save(); - - /** - * Reloads the given execution state. - */ - void load(const std::pair&); - /** * Begins execution at the given execution token. * If the token is a CoreWord, this function exits after its execution. @@ -72,38 +62,32 @@ public: std::size_t rsize() const noexcept; inline void push(Cell value) { - if (dsp == dstack + DataStackSize) - std::longjmp(jmpbuf, static_cast(Error::push)); + verify(dsp < dstack + DataStackSize, Error::push); *dsp++ = value; } inline Cell pop() { - if (dsp == dstack) - std::longjmp(jmpbuf, static_cast(Error::pop)); + verify(dsp > dstack, Error::pop); return *--dsp; } inline void pushr(Cell value) { - if (rsp == rstack + ReturnStackSize) - std::longjmp(jmpbuf, static_cast(Error::pushr)); + verify(rsp < rstack + ReturnStackSize, Error::pushr); *rsp++ = value; } inline Cell popr() { - if (rsp == rstack) - std::longjmp(jmpbuf, static_cast(Error::popr)); + verify(rsp > rstack, Error::popr); return *--rsp; } inline Cell& top() { - if (dsp == dstack) - std::longjmp(jmpbuf, static_cast(Error::top)); + verify(dsp > dstack, Error::top); return *(dsp - 1); } inline Cell& pick(std::size_t i) { - if (dsp - i == dstack) - std::longjmp(jmpbuf, static_cast(Error::pick)); + verify(dsp - i > dstack, Error::pick); return *(dsp - i - 1); } @@ -118,6 +102,23 @@ private: Cell rstack[ReturnStackSize] = {}; Cell *dsp = dstack; Cell *rsp = rstack; + std::jmp_buf jmpbuf = {}; // Used when catching execution errors. + + inline void verify(bool condition, Error error) { + if (!condition) + std::longjmp(jmpbuf, static_cast(error)); + } + + /** + * Saves execution state so that a new execution can begin. + * Used for EVALUATE. + */ + std::pair save(); + + /** + * Reloads the given execution state. + */ + void load(const std::pair&); }; #endif // ALEEFORTH_STATE_HPP diff --git a/libalee/types.cpp b/libalee/types.cpp index baaa5ce..83cf1f7 100644 --- a/libalee/types.cpp +++ b/libalee/types.cpp @@ -40,6 +40,13 @@ Word::iterator& Word::iterator::operator++() return *this; } +Word::iterator Word::iterator::operator++(int) +{ + const auto copy = *this; + addr++; + return copy; +} + Word::iterator::value_type Word::iterator::operator*() { return dict->readbyte(addr); diff --git a/libalee/types.hpp b/libalee/types.hpp index 95daee6..4d86c5d 100644 --- a/libalee/types.hpp +++ b/libalee/types.hpp @@ -23,7 +23,7 @@ #include /** - * Configure the below three types to match your platform. + * Configure the below types for your platform. */ using Addr = uint16_t; using Cell = int16_t; @@ -48,13 +48,16 @@ enum class Error : int { }; /** - * Stores the start and (past-the-)end addresses of a dictionary's word. + * Stores the start and past-the-end addresses of a dictionary's word. */ -struct Word +class Word { Addr start; Addr wend; +public: + struct iterator; + constexpr explicit Word(Addr s = 0, Addr e = 0): start(s), wend(e) {} @@ -64,8 +67,6 @@ struct Word Addr size() const noexcept; - // Iterators provided for std::equal. - struct iterator; iterator begin(const Dictionary *); iterator end(const Dictionary *); @@ -83,6 +84,7 @@ struct Word addr(a), dict(d) {} iterator& operator++(); + iterator operator++(int); value_type operator*(); bool operator!=(const iterator&); };