more refactoring, object organization

optimize
Clyne 11 months 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; Addr index = ins;
auto& ip = state.ip();
auto popd = [](State& s) { auto popd = [](State& s) {
DoubleCell dcell = s.pop(); DoubleCell dcell = s.pop();
dcell <<= sizeof(Cell) * 8; dcell <<= sizeof(Cell) * 8;
@ -59,8 +61,8 @@ void CoreWords::run(Cell ins, State& state)
execute: execute:
if (index >= Dictionary::Begin) { if (index >= Dictionary::Begin) {
// must be calling a defined subroutine // must be calling a defined subroutine
state.pushr(state.ip); state.pushr(ip);
state.ip = index; ip = index;
return; return;
} else switch (index) { } else switch (index) {
case 0: // _lit case 0: // _lit
@ -154,22 +156,21 @@ execute:
case 22: // colon case 22: // colon
state.push(state.dict.alignhere()); state.push(state.dict.alignhere());
while (!state.dict.hasInput()) while (!state.dict.hasInput())
state.input(state); state.input();
state.dict.addDefinition(state.dict.input()); state.dict.addDefinition(state.dict.input());
state.compiling(true); state.compiling(true);
break; break;
case 23: // tick case 23: // tick
while (!state.dict.hasInput()) while (!state.dict.hasInput())
state.input(state); state.input();
find(state, state.dict.input()); find(state, state.dict.input());
break; break;
case 24: // execute case 24: // execute
index = state.pop(); index = state.pop();
goto execute; goto execute;
case 25: // exit case 25: // exit
state.ip = state.popr(); ip = state.popr();
if (state.ip == 0) state.verify(ip != 0, Error::exit);
std::longjmp(state.jmpbuf, static_cast<int>(Error::exit));
break; break;
case 26: // semic case 26: // semic
state.dict.add(findi("exit")); state.dict.add(findi("exit"));
@ -188,7 +189,7 @@ execute:
} }
[[fallthrough]]; [[fallthrough]];
case 28: // _jmp case 28: // _jmp
state.ip = state.beyondip(); ip = state.beyondip();
return; return;
case 29: // depth case 29: // depth
state.push(static_cast<Cell>(state.size())); state.push(static_cast<Cell>(state.size()));
@ -197,12 +198,12 @@ execute:
state.push(static_cast<Cell>(state.rsize())); state.push(static_cast<Cell>(state.rsize()));
break; break;
case 31: // _in case 31: // _in
state.input(state); state.input();
break; break;
case 32: // _ex case 32: // _ex
{ {
const auto st = state.save(); const auto st = state.save();
state.ip = 0; ip = 0;
Parser::parseSource(state); Parser::parseSource(state);
state.load(st); state.load(st);
} }
@ -244,7 +245,7 @@ execute:
break; break;
} }
state.ip += sizeof(Cell); ip += sizeof(Cell);
} }
template<typename Iter> template<typename Iter>

@ -20,14 +20,14 @@
#include "ctype.hpp" #include "ctype.hpp"
#include "parser.hpp" #include "parser.hpp"
#include <algorithm>
#include <cstring>
Error Parser::parse(State& state, const char *str) Error Parser::parse(State& state, const char *str)
{ {
auto addr = Dictionary::Input; auto addr = Dictionary::Input;
Cell len = 0; const auto len = static_cast<Cell>(std::strlen(str));
for (auto ptr = str; *ptr; ++ptr)
++len;
state.dict.write(addr, 0); state.dict.write(addr, 0);
state.dict.write(Dictionary::SourceLen, len); state.dict.write(Dictionary::SourceLen, len);
@ -43,15 +43,12 @@ Error Parser::parse(State& state, const char *str)
Error Parser::parseSource(State& state) Error Parser::parseSource(State& state)
{ {
auto word = state.dict.input(); auto err = Error::none;
while (word.size() > 0) {
if (auto ret = parseWord(state, word); ret != Error::none)
return ret;
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) Error Parser::parseWord(State& state, Word word)

@ -32,34 +32,30 @@ void State::compiling(bool yes)
dict.write(Dictionary::Compiling, 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; return context;
st.first = ip;
std::memcpy(st.second, jmpbuf, sizeof(std::jmp_buf));
return st;
} }
void State::load(const std::pair<Addr, std::jmp_buf>& st) void State::load(const State::Context& ctx)
{ {
ip = st.first; context = ctx;
std::memcpy(jmpbuf, st.second, sizeof(std::jmp_buf));
} }
Error State::execute(Addr addr) Error State::execute(Addr addr)
{ {
auto stat = static_cast<Error>(setjmp(jmpbuf)); auto stat = static_cast<Error>(setjmp(context.jmpbuf));
if (stat == Error::none) { if (stat == Error::none) {
CoreWords::run(addr, *this); CoreWords::run(addr, *this);
if (ip >= Dictionary::Begin) { if (context.ip >= Dictionary::Begin) {
// longjmp will exit this loop. // longjmp will exit this loop.
for (;;) for (;;)
CoreWords::run(dict.read(ip), *this); CoreWords::run(dict.read(context.ip), *this);
} else { } else {
// addr was a CoreWord, all done now. // addr was a CoreWord, all done now.
ip = 0; context.ip = 0;
} }
} else if (stat == Error::exit) { } else if (stat == Error::exit) {
stat = Error::none; stat = Error::none;
@ -76,7 +72,7 @@ void State::reset()
popr(); popr();
dict.write(Dictionary::Compiling, 0); dict.write(Dictionary::Compiling, 0);
ip = 0; context.ip = 0;
} }
std::size_t State::size() const noexcept std::size_t State::size() const noexcept

@ -24,25 +24,24 @@
#include <csetjmp> #include <csetjmp>
#include <cstddef> #include <cstddef>
#include <tuple>
constexpr unsigned DataStackSize = 16; constexpr unsigned DataStackSize = 16;
constexpr unsigned ReturnStackSize = 16; constexpr unsigned ReturnStackSize = 16;
class State class State
{ {
friend class CoreWords; using InputFunc = void (*)(State&);
public: struct Context {
Addr ip = 0; Addr ip = 0;
std::jmp_buf jmpbuf = {};
};
public:
Dictionary& dict; Dictionary& dict;
void (*input)(State&); // User-provided function to collect "stdin" input.
constexpr State(Dictionary& d, void (*i)(State&)): constexpr State(Dictionary& d, InputFunc i):
dict(d), input(i) {} dict(d), inputfunc(i), context() {}
bool compiling() const;
void compiling(bool);
/** /**
* Begins execution at the given execution token. * Begins execution at the given execution token.
@ -58,9 +57,31 @@ public:
*/ */
void reset(); 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 size() const noexcept;
std::size_t rsize() 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) { inline void push(Cell value) {
verify(dsp < dstack + DataStackSize, Error::push); verify(dsp < dstack + DataStackSize, Error::push);
*dsp++ = value; *dsp++ = value;
@ -93,32 +114,23 @@ public:
// Advances the instruction pointer and returns that cell's contents. // Advances the instruction pointer and returns that cell's contents.
inline Cell beyondip() { inline Cell beyondip() {
ip += sizeof(Cell); context.ip += sizeof(Cell);
return dict.read(ip); 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) { inline void verify(bool condition, Error error) {
if (!condition) if (!condition)
std::longjmp(jmpbuf, static_cast<int>(error)); std::longjmp(context.jmpbuf, static_cast<int>(error));
} }
/** private:
* Saves execution state so that a new execution can begin. InputFunc inputfunc; // User-provided function to collect "stdin" input.
* Used for EVALUATE. Context context;
*/
std::pair<Addr, std::jmp_buf> save();
/** Cell dstack[DataStackSize] = {};
* Reloads the given execution state. Cell rstack[ReturnStackSize] = {};
*/ Cell *dsp = dstack;
void load(const std::pair<Addr, std::jmp_buf>&); Cell *rsp = rstack;
}; };
#endif // ALEEFORTH_STATE_HPP #endif // ALEEFORTH_STATE_HPP

Loading…
Cancel
Save