aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClyne Sullivan <clyne@bitgloo.com>2023-10-13 10:13:31 -0400
committerClyne Sullivan <clyne@bitgloo.com>2023-10-13 10:13:31 -0400
commitf7a9103bbef39b7f6c5909d7f74fa2aea4b81fe1 (patch)
treed0cedbfaa20a205c05951977173667273e33e134
parent15c0c2f789902ac764919913e123466ac46e4746 (diff)
more refactoring, object organization
-rw-r--r--libalee/corewords.cpp23
-rw-r--r--libalee/parser.cpp19
-rw-r--r--libalee/state.cpp22
-rw-r--r--libalee/state.hpp68
4 files changed, 69 insertions, 63 deletions
diff --git a/libalee/corewords.cpp b/libalee/corewords.cpp
index 34125bd..e9b9f47 100644
--- a/libalee/corewords.cpp
+++ b/libalee/corewords.cpp
@@ -44,6 +44,8 @@ void CoreWords::run(Cell ins, State& state)
Addr index = ins;
+ auto& ip = state.ip();
+
auto popd = [](State& s) {
DoubleCell dcell = s.pop();
dcell <<= sizeof(Cell) * 8;
@@ -59,8 +61,8 @@ void CoreWords::run(Cell ins, State& state)
execute:
if (index >= Dictionary::Begin) {
// must be calling a defined subroutine
- state.pushr(state.ip);
- state.ip = index;
+ state.pushr(ip);
+ ip = index;
return;
} else switch (index) {
case 0: // _lit
@@ -154,22 +156,21 @@ execute:
case 22: // colon
state.push(state.dict.alignhere());
while (!state.dict.hasInput())
- state.input(state);
+ state.input();
state.dict.addDefinition(state.dict.input());
state.compiling(true);
break;
case 23: // tick
while (!state.dict.hasInput())
- state.input(state);
+ state.input();
find(state, state.dict.input());
break;
case 24: // execute
index = state.pop();
goto execute;
case 25: // exit
- state.ip = state.popr();
- if (state.ip == 0)
- std::longjmp(state.jmpbuf, static_cast<int>(Error::exit));
+ ip = state.popr();
+ state.verify(ip != 0, Error::exit);
break;
case 26: // semic
state.dict.add(findi("exit"));
@@ -188,7 +189,7 @@ execute:
}
[[fallthrough]];
case 28: // _jmp
- state.ip = state.beyondip();
+ ip = state.beyondip();
return;
case 29: // depth
state.push(static_cast<Cell>(state.size()));
@@ -197,12 +198,12 @@ execute:
state.push(static_cast<Cell>(state.rsize()));
break;
case 31: // _in
- state.input(state);
+ state.input();
break;
case 32: // _ex
{
const auto st = state.save();
- state.ip = 0;
+ ip = 0;
Parser::parseSource(state);
state.load(st);
}
@@ -244,7 +245,7 @@ execute:
break;
}
- state.ip += sizeof(Cell);
+ ip += sizeof(Cell);
}
template<typename Iter>
diff --git a/libalee/parser.cpp b/libalee/parser.cpp
index 2b1d8e1..da7ae0b 100644
--- a/libalee/parser.cpp
+++ b/libalee/parser.cpp
@@ -20,14 +20,14 @@
#include "ctype.hpp"
#include "parser.hpp"
+#include <algorithm>
+#include <cstring>
+
Error Parser::parse(State& state, const char *str)
{
auto addr = Dictionary::Input;
- Cell len = 0;
- for (auto ptr = str; *ptr; ++ptr)
- ++len;
-
+ const auto len = static_cast<Cell>(std::strlen(str));
state.dict.write(addr, 0);
state.dict.write(Dictionary::SourceLen, len);
@@ -43,15 +43,12 @@ Error Parser::parse(State& state, const char *str)
Error Parser::parseSource(State& state)
{
- auto word = state.dict.input();
- while (word.size() > 0) {
- if (auto ret = parseWord(state, word); ret != Error::none)
- return ret;
+ auto err = Error::none;
- word = state.dict.input();
- }
+ while (err == Error::none && state.dict.hasInput())
+ err = parseWord(state, state.dict.input());
- return Error::none;
+ return err;
}
Error Parser::parseWord(State& state, Word word)
diff --git a/libalee/state.cpp b/libalee/state.cpp
index b19d291..6e12999 100644
--- a/libalee/state.cpp
+++ b/libalee/state.cpp
@@ -32,34 +32,30 @@ void State::compiling(bool yes)
dict.write(Dictionary::Compiling, yes);
}
-std::pair<Addr, std::jmp_buf> State::save()
+State::Context State::save()
{
- std::pair<Addr, std::jmp_buf> st;
- st.first = ip;
- std::memcpy(st.second, jmpbuf, sizeof(std::jmp_buf));
- return st;
+ return context;
}
-void State::load(const std::pair<Addr, std::jmp_buf>& st)
+void State::load(const State::Context& ctx)
{
- ip = st.first;
- std::memcpy(jmpbuf, st.second, sizeof(std::jmp_buf));
+ context = ctx;
}
Error State::execute(Addr addr)
{
- auto stat = static_cast<Error>(setjmp(jmpbuf));
+ auto stat = static_cast<Error>(setjmp(context.jmpbuf));
if (stat == Error::none) {
CoreWords::run(addr, *this);
- if (ip >= Dictionary::Begin) {
+ if (context.ip >= Dictionary::Begin) {
// longjmp will exit this loop.
for (;;)
- CoreWords::run(dict.read(ip), *this);
+ CoreWords::run(dict.read(context.ip), *this);
} else {
// addr was a CoreWord, all done now.
- ip = 0;
+ context.ip = 0;
}
} else if (stat == Error::exit) {
stat = Error::none;
@@ -76,7 +72,7 @@ void State::reset()
popr();
dict.write(Dictionary::Compiling, 0);
- ip = 0;
+ context.ip = 0;
}
std::size_t State::size() const noexcept
diff --git a/libalee/state.hpp b/libalee/state.hpp
index 3a79693..12a3aeb 100644
--- a/libalee/state.hpp
+++ b/libalee/state.hpp
@@ -24,25 +24,24 @@
#include <csetjmp>
#include <cstddef>
-#include <tuple>
constexpr unsigned DataStackSize = 16;
constexpr unsigned ReturnStackSize = 16;
class State
{
- friend class CoreWords;
+ using InputFunc = void (*)(State&);
+
+ struct Context {
+ Addr ip = 0;
+ std::jmp_buf jmpbuf = {};
+ };
public:
- Addr ip = 0;
Dictionary& dict;
- void (*input)(State&); // User-provided function to collect "stdin" input.
- constexpr State(Dictionary& d, void (*i)(State&)):
- dict(d), input(i) {}
-
- bool compiling() const;
- void compiling(bool);
+ constexpr State(Dictionary& d, InputFunc i):
+ dict(d), inputfunc(i), context() {}
/**
* Begins execution at the given execution token.
@@ -58,9 +57,31 @@ public:
*/
void reset();
+ Addr& ip() noexcept {
+ return context.ip;
+ }
+
+ void input() noexcept {
+ inputfunc(*this);
+ }
+
+ bool compiling() const;
+ void compiling(bool);
+
std::size_t size() const noexcept;
std::size_t rsize() const noexcept;
+ /**
+ * Saves execution state so that a new execution can begin.
+ * Used for EVALUATE.
+ */
+ Context save();
+
+ /**
+ * Reloads the given execution state.
+ */
+ void load(const Context&);
+
inline void push(Cell value) {
verify(dsp < dstack + DataStackSize, Error::push);
*dsp++ = value;
@@ -93,32 +114,23 @@ public:
// Advances the instruction pointer and returns that cell's contents.
inline Cell beyondip() {
- ip += sizeof(Cell);
- return dict.read(ip);
+ context.ip += sizeof(Cell);
+ return dict.read(context.ip);
}
-private:
- Cell dstack[DataStackSize] = {};
- 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));
+ std::longjmp(context.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();
+private:
+ InputFunc inputfunc; // User-provided function to collect "stdin" input.
+ Context context;
- /**
- * Reloads the given execution state.
- */
- void load(const std::pair<Addr, std::jmp_buf>&);
+ Cell dstack[DataStackSize] = {};
+ Cell rstack[ReturnStackSize] = {};
+ Cell *dsp = dstack;
+ Cell *rsp = rstack;
};
#endif // ALEEFORTH_STATE_HPP