serputs("\n\r");
- if (auto r = Parser::parse(state, strbuf); r == 0) {
+ if (auto r = Parser::parse(state, strbuf); r == Error::none) {
serputs(state.compiling() ? " compiled" : " ok");
} else {
switch (r) {
- case Parser::UnknownWord:
+ case Error::noword:
serputs("unknown word...");
break;
default:
+ serputs("error...");
break;
}
}
state.dict.writebyte(i++, file.get());
}
-#include <cstring>
void user_sys(State& state)
{
char buf[32] = {0};
std::cout << buf << ' ';
}
break;
- case 5: // eval
- {
- auto oldip = state.ip;
- std::jmp_buf oldjb;
- memcpy(oldjb, state.jmpbuf, sizeof(std::jmp_buf));
- state.ip = 0;
- Parser::parseSource(state);
- memcpy(state.jmpbuf, oldjb, sizeof(std::jmp_buf));
- state.ip = oldip;
- }
+ default:
break;
}
}
void parseLine(State& state, const std::string& line)
{
- if (auto r = Parser::parse(state, line.c_str()); r == 0) {
+ if (auto r = Parser::parse(state, line.c_str()); r == Error::none) {
if (okay)
- std::cout << (state.compiling() ? "compiled" : "ok") << std::endl;
+ std::cout << (state.compiling() ? " compiled" : " ok") << std::endl;
} else {
switch (r) {
- case Parser::UnknownWord:
+ case Error::noword:
std::cout << "word not found in: " << line << std::endl;
break;
- case static_cast<int>(State::Error::push):
+ case Error::push:
std::cout << "stack overflow" << std::endl;
break;
- case static_cast<int>(State::Error::pushr):
+ case Error::pushr:
std::cout << "return stack overflow" << std::endl;
break;
- case static_cast<int>(State::Error::popr):
+ case Error::popr:
std::cout << "return stack underflow" << std::endl;
break;
- case static_cast<int>(State::Error::pop):
- case static_cast<int>(State::Error::top):
- case static_cast<int>(State::Error::pick):
+ case Error::pop:
+ case Error::top:
+ case Error::pick:
std::cout << "stack underflow" << std::endl;
break;
default:
- std::cout << "error: " << r << std::endl;
+ std::cout << "unknown error" << std::endl;
break;
}
- while (state.size())
- state.pop();
- while (state.rsize())
- state.popr();
- state.dict.write(Dictionary::Compiling, 0);
- state.ip = 0;
+ state.reset();
}
}
static bool okay = false;
-static void readchar(State& state);
+static void readchar(State&);
static void parseLine(State&, const std::string&);
static void parseFile(State&, std::istream&);
{
std::ifstream file ("alee.dat", std::ios::binary);
- Addr i = 0;
- while (file.good())
- state.dict.writebyte(i++, file.get());
+ for (Addr i = 0; file.good(); i++)
+ state.dict.writebyte(i, file.get());
}
-#include <cstring>
void user_sys(State& state)
{
char buf[32] = {0};
std::cout << buf << ' ';
}
break;
- case 5: // eval
- {
- auto oldip = state.ip;
- std::jmp_buf oldjb;
- memcpy(oldjb, state.jmpbuf, sizeof(std::jmp_buf));
- state.ip = 0;
- Parser::parseSource(state);
- memcpy(state.jmpbuf, oldjb, sizeof(std::jmp_buf));
- state.ip = oldip;
- }
+ default:
break;
}
}
void parseLine(State& state, const std::string& line)
{
- if (auto r = Parser::parse(state, line.c_str()); r == 0) {
+ if (auto r = Parser::parse(state, line.c_str()); r == Error::none) {
if (okay)
- std::cout << (state.compiling() ? "compiled" : "ok") << std::endl;
+ std::cout << (state.compiling() ? " compiled" : " ok") << std::endl;
} else {
switch (r) {
- case Parser::UnknownWord:
+ case Error::noword:
std::cout << "word not found in: " << line << std::endl;
break;
- case static_cast<int>(State::Error::push):
+ case Error::push:
std::cout << "stack overflow" << std::endl;
break;
- case static_cast<int>(State::Error::pushr):
+ case Error::pushr:
std::cout << "return stack overflow" << std::endl;
break;
- case static_cast<int>(State::Error::popr):
+ case Error::popr:
std::cout << "return stack underflow" << std::endl;
break;
- case static_cast<int>(State::Error::pop):
- case static_cast<int>(State::Error::top):
- case static_cast<int>(State::Error::pick):
+ case Error::pop:
+ case Error::top:
+ case Error::pick:
std::cout << "stack underflow" << std::endl;
break;
default:
- std::cout << "error: " << r << std::endl;
+ std::cout << "unknown error" << std::endl;
break;
}
- while (state.size())
- state.pop();
- while (state.rsize())
- state.popr();
- state.dict.write(Dictionary::Compiling, 0);
- state.ip = 0;
+ state.reset();
}
}
: :noname 0 , here ] ;
: evaluate _source @ >r _sourceu @ >r >in @ >r
- 0 >in ! _sourceu ! _source ! 5 sys
+ 0 >in ! _sourceu ! _source ! _ev
r> >in ! r> _sourceu ! r> _source ! ;
*/
#include "corewords.hpp"
+#include "parser.hpp"
#include <cstring>
#include <utility>
goto execute;
case 25: // exit
state.ip = state.popr();
- if (state.ip == 0) {
- std::longjmp(state.jmpbuf,
- static_cast<int>(State::Error::exit));
- }
+ if (state.ip == 0)
+ std::longjmp(state.jmpbuf, static_cast<int>(Error::exit));
break;
case 26: // semic
{
case 31: // _in
state.input(state);
break;
+ case 32: // _ex
+ {
+ const auto st = state.save();
+ state.ip = 0;
+ Parser::parseSource(state);
+ state.load(st);
+ }
+ break;
default:
state.push(index - WordCount);
break;
class CoreWords
{
public:
- constexpr static std::size_t WordCount = 32;
+ constexpr static std::size_t WordCount = 33;
constexpr static Cell Immediate = (1 << 5);
"<\0&\0|\0^\0"
"<<\0>>\0:\0_'\0execute\0"
"exit\0;\0_jmp0\0_jmp\0"
- "depth\0_rdepth\0_in\0";
+ "depth\0_rdepth\0_in\0_ev\0";
};
#endif // ALEEFORTH_COREWORDS_HPP
#include <cstring>
-int Parser::parse(State& state, const char *str)
+Error Parser::parse(State& state, const char *str)
{
auto addr = Dictionary::Input;
state.dict.write(addr, 0);
return parseSource(state);
}
-int Parser::parseSource(State& state)
+Error Parser::parseSource(State& state)
{
auto word = state.dict.input();
while (word.size() > 0) {
- if (auto ret = parseWord(state, word); ret)
+ if (auto ret = parseWord(state, word); ret != Error::none)
return ret;
word = state.dict.input();
}
- return 0;
+ return Error::none;
}
-int Parser::parseWord(State& state, Word word)
+Error Parser::parseWord(State& state, Word word)
{
int ins, imm;
if (state.compiling() && !imm)
state.dict.add(ins);
- else if (auto stat = state.execute(ins); stat != State::Error::none)
- return static_cast<int>(stat);
+ else if (auto stat = state.execute(ins); stat != Error::none)
+ return stat;
- return 0;
+ return Error::none;
}
-int Parser::parseNumber(State& state, Word word)
+Error Parser::parseNumber(State& state, Word word)
{
const auto base = state.dict.read(Dictionary::Base);
DoubleCell result = 0;
result *= base;
result += 10 + (c > 'a' ? c - 'a' : c - 'A');
} else {
- return UnknownWord;
+ return Error::noword;
}
if (++i < word.wend)
state.push(value);
}
- return 0;
+ return Error::none;
}
class Parser
{
public:
- constexpr static int UnknownWord = -1;
-
- static int parse(State&, const char *);
- static int parseSource(State&);
+ static Error parse(State&, const char *);
+ static Error parseSource(State&);
private:
- static int parseWord(State&, Word);
- static int parseNumber(State&, Word);
+ static Error parseWord(State&, Word);
+ static Error parseNumber(State&, Word);
};
#endif // ALEEFORTH_PARSER_HPP
#include "corewords.hpp"
#include "state.hpp"
+#include <cstring>
#include <iterator>
bool State::compiling() const
dict.write(Dictionary::Compiling, yes);
}
-State::Error State::execute(Addr addr)
+std::pair<Addr, std::jmp_buf> State::save()
{
- auto stat = static_cast<State::Error>(setjmp(jmpbuf));
+ std::pair<Addr, std::jmp_buf> st;
+ 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)
+{
+ ip = st.first;
+ std::memcpy(jmpbuf, st.second, sizeof(std::jmp_buf));
+}
+
+Error State::execute(Addr addr)
+{
+ auto stat = static_cast<Error>(setjmp(jmpbuf));
- if (stat == State::Error::none) {
+ if (stat == Error::none) {
CoreWords::run(addr, *this);
if (ip >= Dictionary::Begin) {
// addr was a CoreWord, all done now.
ip = 0;
}
- } else if (stat == State::Error::exit) {
- stat = State::Error::none;
+ } else if (stat == Error::exit) {
+ stat = Error::none;
}
return stat;
}
+void State::reset()
+{
+ while (size())
+ pop();
+ while (rsize())
+ popr();
+
+ dict.write(Dictionary::Compiling, 0);
+ ip = 0;
+}
+
std::size_t State::size() const noexcept
{
return std::distance(dstack, static_cast<const Cell *>(dsp));
#include <csetjmp>
#include <cstddef>
+#include <tuple>
constexpr unsigned DataStackSize = 16;
constexpr unsigned ReturnStackSize = 16;
class State
{
public:
- enum class Error : int {
- none = 0,
- push,
- pop,
- pushr,
- popr,
- top,
- pick,
- exit
- };
-
Addr ip = 0;
Dictionary& dict;
void (*input)(State&);
bool compiling() const;
void compiling(bool);
+ std::pair<Addr, std::jmp_buf> save();
+ void load(const std::pair<Addr, std::jmp_buf>&);
+
Error execute(Addr);
+ void reset();
std::size_t size() const noexcept;
std::size_t rsize() const noexcept;
constexpr unsigned int MaxCellNumberChars = 6; // -32768
+enum class Error : int {
+ none = 0,
+ push,
+ pop,
+ pushr,
+ popr,
+ top,
+ pick,
+ exit,
+ noword
+};
+
struct Word
{
struct iterator;