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 <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);
@ -71,12 +71,19 @@ bool parse_stream(auto &fth, std::istream& str, bool say_okay)
if (sforth::isequal(line, "bye"))
return true;
if constexpr (sforth::enable_exceptions) {
try {
fth.parse_line(line);
} catch (sforth::error e) {
std::cerr << sforth::error_string(e) << " in " << line << std::endl;
continue;
}
} else {
if (auto e = fth.parse_line(line); e) {
std::cerr << sforth::error_string(*e) << " in " << line << std::endl;
continue;
}
}
}
if (say_okay)

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

Loading…
Cancel
Save