finish exceptionless impl; fix sp@ and pick

main
Clyne 3 weeks ago
parent ff4e488ca0
commit 334a2a0727
Signed by: clyne
GPG Key ID: 3267C8EBF3F9AFC7

@ -23,7 +23,7 @@
#include <span> #include <span>
#include <string> #include <string>
constinit static sforth::forth<4096> forth {sforth::initialize<&forth>()}; constinit static sforth::forth<8192> forth {sforth::initialize<&forth>()};
static bool parse_stream(auto&, std::istream&, bool say_okay = false); static bool parse_stream(auto&, std::istream&, bool say_okay = false);
@ -71,12 +71,19 @@ bool parse_stream(auto &fth, std::istream& str, bool say_okay)
if (sforth::isequal(line, "bye")) if (sforth::isequal(line, "bye"))
return true; return true;
if constexpr (sforth::enable_exceptions) {
try { try {
fth.parse_line(line); fth.parse_line(line);
} catch (sforth::error e) { } catch (sforth::error e) {
std::cerr << sforth::error_string(e) << " in " << line << std::endl; std::cerr << sforth::error_string(e) << " in " << line << std::endl;
continue; continue;
} }
} else {
if (auto e = fth.parse_line(line); e) {
std::cerr << sforth::error_string(*e) << " in " << line << std::endl;
continue;
}
}
} }
if (say_okay) if (say_okay)

@ -23,6 +23,7 @@
#include <algorithm> #include <algorithm>
#include <array> #include <array>
#include <bit> #include <bit>
#include <csetjmp>
#include <cstddef> #include <cstddef>
#include <string_view> #include <string_view>
#include <utility> #include <utility>
@ -31,9 +32,9 @@ namespace sforth {
constexpr bool enable_exceptions = true; constexpr bool enable_exceptions = true;
enum class error enum class error : int
{ {
init_error, init_error = 1,
parse_error, parse_error,
execute_error, execute_error,
dictionary_overflow, dictionary_overflow,
@ -64,14 +65,36 @@ inline auto error_string(error err) noexcept -> std::string_view
} }
#undef assert #undef assert
template<error Err>
inline void assert(bool condition) template<bool except>
{ struct catcher {
if constexpr (enable_exceptions) { constexpr catcher() = default;
if (!condition) };
throw Err;
template<> struct catcher<true> {
void operator()(error e) {
throw e;
}
std::optional<error> set() {
return {};
}
};
template<> struct catcher<false> {
std::jmp_buf buf = {};
void operator()(error e) {
std::longjmp(buf, static_cast<int>(e));
} }
}
std::optional<error> set() {
if (auto err = setjmp(buf); err) {
return static_cast<error>(err);
} else {
return {};
}
}
};
template<std::size_t Cells> template<std::size_t Cells>
struct forth : public word_list struct forth : public word_list
@ -81,6 +104,16 @@ struct forth : public word_list
static constexpr auto npos = std::string_view::npos; static constexpr auto npos = std::string_view::npos;
template<error Err>
inline void assert(bool condition)
{
if (!condition) {
sp = dstack.end();
rp = rstack.end();
cat(Err);
}
}
void push(cell v) { void push(cell v) {
assert<error::stack_overflow>(sp != dstack.begin()); assert<error::stack_overflow>(sp != dstack.begin());
*--sp = v; *--sp = v;
@ -130,10 +163,13 @@ struct forth : public word_list
return word_list::parse(source, sourcei); return word_list::parse(source, sourcei);
} }
void parse_line(std::string_view sv) { std::optional<error> parse_line(std::string_view sv) {
source = sv.data(); source = sv.data();
sourcei = sv.find_first_not_of(" \t\r\n"); sourcei = sv.find_first_not_of(" \t\r\n");
if (auto err = cat.set(); err)
return err;
while (sourcei != npos) { while (sourcei != npos) {
const auto word = parse(); const auto word = parse();
@ -156,6 +192,8 @@ struct forth : public word_list
sourcei = sv.find_first_not_of(" \t\r\n", sourcei); sourcei = sv.find_first_not_of(" \t\r\n", sourcei);
} }
return {};
} }
void execute(const func *body) { void execute(const func *body) {
@ -179,6 +217,7 @@ struct forth : public word_list
std::size_t sourcei = npos; std::size_t sourcei = npos;
cell compiling = false; cell compiling = false;
cell base = 10; cell base = 10;
[[no_unique_address]] catcher<enable_exceptions> cat;
std::array<cell, data_size> dstack {}; std::array<cell, data_size> dstack {};
std::array<func *, return_size> rstack {}; std::array<func *, return_size> rstack {};
std::array<cell, Cells> dict {}; std::array<cell, Cells> dict {};
@ -294,10 +333,10 @@ constexpr auto initialize()
fthp->ip = *std::bit_cast<func **>(ptr) - 1; }, 0 fthp->ip = *std::bit_cast<func **>(ptr) - 1; }, 0
, S{"CHARS"}, [](auto) {}, 0 , S{"CHARS"}, [](auto) {}, 0
, S{"POSTPONE"}, [](auto) { , S{"POSTPONE"}, [](auto) {
assert<error::compile_only_word>(fthp->compiling); fthp->template assert<error::compile_only_word>(fthp->compiling);
auto w = fthp->parse(); auto w = fthp->parse();
auto g = fthp->get(w); auto g = fthp->get(w);
assert<error::word_not_found>(g.has_value()); fthp->template assert<error::word_not_found>(g.has_value());
if ((*g)->is_immediate()) { if ((*g)->is_immediate()) {
*fthp->here++ = std::bit_cast<cell>((*g)->body()); *fthp->here++ = std::bit_cast<cell>((*g)->body());
@ -353,8 +392,8 @@ constexpr auto initialize()
, S{">R" }, S{"RP@ CELL - RP ! RP@ CELL+ @ RP@ ! RP@ CELL+ !"}, 0 , S{">R" }, S{"RP@ CELL - RP ! RP@ CELL+ @ RP@ ! RP@ CELL+ !"}, 0
, S{"R>" }, S{"RP@ @ RP@ CELL+ RP ! RP@ @ SWAP RP@ !"}, 0 , S{"R>" }, S{"RP@ @ RP@ CELL+ RP ! RP@ @ SWAP RP@ !"}, 0
, S{"OVER" }, S{"1 PICK"}, 0 , S{"OVER" }, S{"1 PICK"}, 0
, S{"PICK" }, S{"CELLS CELL+ SP@ + @"}, 0 , S{"PICK" }, S{"1 + CELLS SP@ + @"}, 0
, S{"SP@" }, S{"SP @"}, 0 , S{"SP@" }, S{"SP @ CELL+"}, 0
, S{"RP@" }, S{"RP @ CELL+"}, 0 , S{"RP@" }, S{"RP @ CELL+"}, 0
, S{"HERE" }, S{"DP @"}, 0 , S{"HERE" }, S{"DP @"}, 0
, S{"LATEST"}, S{"_D @"}, 0 , S{"LATEST"}, S{"_D @"}, 0

Loading…
Cancel
Save