more refactoring, object organization

optimize
Clyne 1 year ago
parent 15c0c2f789
commit f7a9103bbe
Signed by: clyne
GPG Key ID: 1B74EE6C49C96795

@ -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>

@ -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)

@ -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

@ -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

Loading…
Cancel
Save