aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClyne Sullivan <clyne@bitgloo.com>2023-03-11 07:36:11 -0500
committerClyne Sullivan <clyne@bitgloo.com>2023-03-11 07:36:11 -0500
commitbc3e952b487365fdf5e60e9fcfa0841c23972e30 (patch)
treecc53facc2a62db4dc93a25c772f521786305ead8
parentf8270776e79f4d2edb7c2a19c1ecd3bf3b2bf153 (diff)
common error enum; eval to _ev
-rw-r--r--alee-msp430.cpp5
-rw-r--r--alee-standalone.cpp39
-rw-r--r--alee.cpp46
-rw-r--r--core.fth2
-rw-r--r--libalee/corewords.cpp15
-rw-r--r--libalee/corewords.hpp4
-rw-r--r--libalee/parser.cpp22
-rw-r--r--libalee/parser.hpp10
-rw-r--r--libalee/state.cpp36
-rw-r--r--libalee/state.hpp16
-rw-r--r--libalee/types.hpp12
11 files changed, 107 insertions, 100 deletions
diff --git a/alee-msp430.cpp b/alee-msp430.cpp
index 3121dc1..ca00026 100644
--- a/alee-msp430.cpp
+++ b/alee-msp430.cpp
@@ -66,14 +66,15 @@ int main()
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;
}
}
diff --git a/alee-standalone.cpp b/alee-standalone.cpp
index 3c4eb3d..2c971ce 100644
--- a/alee-standalone.cpp
+++ b/alee-standalone.cpp
@@ -79,7 +79,6 @@ static void load(State& state)
state.dict.writebyte(i++, file.get());
}
-#include <cstring>
void user_sys(State& state)
{
char buf[32] = {0};
@@ -107,55 +106,41 @@ void user_sys(State& state)
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();
}
}
diff --git a/alee.cpp b/alee.cpp
index e222363..92af969 100644
--- a/alee.cpp
+++ b/alee.cpp
@@ -26,7 +26,7 @@
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&);
@@ -76,12 +76,10 @@ static void load(State& state)
{
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};
@@ -109,55 +107,41 @@ void user_sys(State& state)
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();
}
}
diff --git a/core.fth b/core.fth
index c23c366..a8ccb9d 100644
--- a/core.fth
+++ b/core.fth
@@ -199,5 +199,5 @@
: :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 ! ;
diff --git a/libalee/corewords.cpp b/libalee/corewords.cpp
index ced3973..b8a415e 100644
--- a/libalee/corewords.cpp
+++ b/libalee/corewords.cpp
@@ -17,6 +17,7 @@
*/
#include "corewords.hpp"
+#include "parser.hpp"
#include <cstring>
#include <utility>
@@ -171,10 +172,8 @@ execute:
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
{
@@ -206,6 +205,14 @@ execute:
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;
diff --git a/libalee/corewords.hpp b/libalee/corewords.hpp
index 70cbb30..33f4fc5 100644
--- a/libalee/corewords.hpp
+++ b/libalee/corewords.hpp
@@ -27,7 +27,7 @@ void user_sys(State&);
class CoreWords
{
public:
- constexpr static std::size_t WordCount = 32;
+ constexpr static std::size_t WordCount = 33;
constexpr static Cell Immediate = (1 << 5);
@@ -44,7 +44,7 @@ public:
"<\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
diff --git a/libalee/parser.cpp b/libalee/parser.cpp
index 3b14224..39695c4 100644
--- a/libalee/parser.cpp
+++ b/libalee/parser.cpp
@@ -22,7 +22,7 @@
#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);
@@ -38,20 +38,20 @@ int Parser::parse(State& state, const char *str)
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;
@@ -71,13 +71,13 @@ int Parser::parseWord(State& state, Word word)
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;
@@ -97,7 +97,7 @@ int Parser::parseNumber(State& state, Word word)
result *= base;
result += 10 + (c > 'a' ? c - 'a' : c - 'A');
} else {
- return UnknownWord;
+ return Error::noword;
}
if (++i < word.wend)
@@ -121,6 +121,6 @@ int Parser::parseNumber(State& state, Word word)
state.push(value);
}
- return 0;
+ return Error::none;
}
diff --git a/libalee/parser.hpp b/libalee/parser.hpp
index f211781..be6f3f7 100644
--- a/libalee/parser.hpp
+++ b/libalee/parser.hpp
@@ -26,14 +26,12 @@
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
diff --git a/libalee/state.cpp b/libalee/state.cpp
index b3c98b1..bfd29d1 100644
--- a/libalee/state.cpp
+++ b/libalee/state.cpp
@@ -19,6 +19,7 @@
#include "corewords.hpp"
#include "state.hpp"
+#include <cstring>
#include <iterator>
bool State::compiling() const
@@ -31,11 +32,25 @@ void State::compiling(bool yes)
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) {
@@ -46,13 +61,24 @@ State::Error State::execute(Addr addr)
// 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));
diff --git a/libalee/state.hpp b/libalee/state.hpp
index 648b868..325f405 100644
--- a/libalee/state.hpp
+++ b/libalee/state.hpp
@@ -24,6 +24,7 @@
#include <csetjmp>
#include <cstddef>
+#include <tuple>
constexpr unsigned DataStackSize = 16;
constexpr unsigned ReturnStackSize = 16;
@@ -31,17 +32,6 @@ 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&);
@@ -54,7 +44,11 @@ public:
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;
diff --git a/libalee/types.hpp b/libalee/types.hpp
index 5b577f2..0a7f7ee 100644
--- a/libalee/types.hpp
+++ b/libalee/types.hpp
@@ -32,6 +32,18 @@ using Func = void (*)(State&);
constexpr unsigned int MaxCellNumberChars = 6; // -32768
+enum class Error : int {
+ none = 0,
+ push,
+ pop,
+ pushr,
+ popr,
+ top,
+ pick,
+ exit,
+ noword
+};
+
struct Word
{
struct iterator;