#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) {
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();
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();
}
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)
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
* 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.
{
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';
} else {
return Error::noword;
}
-
- if (++i < word.wend)
- c = state.dict.readbyte(i);
- } while (i < word.wend);
+ }
if (inv)
result *= -1;
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) {}
bool compiling() const;
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.
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);
}
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
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);
#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;
};
/**
- * 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) {}
Addr size() const noexcept;
- // Iterators provided for std::equal.
- struct iterator;
iterator begin(const Dictionary *);
iterator end(const Dictionary *);
addr(a), dict(d) {}
iterator& operator++();
+ iterator operator++(int);
value_type operator*();
bool operator!=(const iterator&);
};