aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClyne Sullivan <clyne@bitgloo.com>2023-10-12 20:23:50 -0400
committerClyne Sullivan <clyne@bitgloo.com>2023-10-12 20:23:50 -0400
commit15c0c2f789902ac764919913e123466ac46e4746 (patch)
tree937eea767e593798871e6774999b857cdd81509b
parentd36bb13f52b3899fd0f57e38f00d97e2c3a0f627 (diff)
some class refactoring
-rw-r--r--libalee/corewords.cpp26
-rw-r--r--libalee/dictionary.cpp47
-rw-r--r--libalee/dictionary.hpp1
-rw-r--r--libalee/parser.cpp20
-rw-r--r--libalee/state.hpp49
-rw-r--r--libalee/types.cpp7
-rw-r--r--libalee/types.hpp12
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 <cstring>
#include <utility>
-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<Addr&>(state.top()) >>= static_cast<Addr>(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) {}
@@ -44,17 +45,6 @@ public:
void compiling(bool);
/**
- * Saves execution state so that a new execution can begin.
- * Used for EVALUATE.
- */
- std::pair<Addr, std::jmp_buf> save();
-
- /**
- * Reloads the given execution state.
- */
- void load(const std::pair<Addr, std::jmp_buf>&);
-
- /**
* Begins execution at the given execution token.
* If the token is a CoreWord, this function exits after its execution.
* Otherwise, execution continues until the word's execution completes.
@@ -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<int>(Error::push));
+ verify(dsp < dstack + DataStackSize, Error::push);
*dsp++ = value;
}
inline Cell pop() {
- if (dsp == dstack)
- std::longjmp(jmpbuf, static_cast<int>(Error::pop));
+ verify(dsp > dstack, Error::pop);
return *--dsp;
}
inline void pushr(Cell value) {
- if (rsp == rstack + ReturnStackSize)
- std::longjmp(jmpbuf, static_cast<int>(Error::pushr));
+ verify(rsp < rstack + ReturnStackSize, Error::pushr);
*rsp++ = value;
}
inline Cell popr() {
- if (rsp == rstack)
- std::longjmp(jmpbuf, static_cast<int>(Error::popr));
+ verify(rsp > rstack, Error::popr);
return *--rsp;
}
inline Cell& top() {
- if (dsp == dstack)
- std::longjmp(jmpbuf, static_cast<int>(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<int>(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<int>(error));
+ }
+
+ /**
+ * Saves execution state so that a new execution can begin.
+ * Used for EVALUATE.
+ */
+ std::pair<Addr, std::jmp_buf> save();
+
+ /**
+ * Reloads the given execution state.
+ */
+ void load(const std::pair<Addr, std::jmp_buf>&);
};
#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 <iterator>
/**
- * 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&);
};