|
|
|
@ -19,6 +19,7 @@
|
|
|
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
#include <array>
|
|
|
|
|
#include <bit>
|
|
|
|
|
#include <charconv>
|
|
|
|
|
#include <cstdint>
|
|
|
|
|
#include <cstddef>
|
|
|
|
@ -68,16 +69,16 @@ struct forth
|
|
|
|
|
addr flags_len;
|
|
|
|
|
|
|
|
|
|
auto name() const -> std::string_view {
|
|
|
|
|
return {reinterpret_cast<const char *>(this + 1)};
|
|
|
|
|
return {std::bit_cast<const char *>(this + 1)};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto body() const -> const func * {
|
|
|
|
|
auto ptr = reinterpret_cast<const std::uint8_t *>(this + 1)
|
|
|
|
|
+ (flags_len & 0xFF);
|
|
|
|
|
return reinterpret_cast<const func *>(ptr);
|
|
|
|
|
const auto ptr = std::bit_cast<const std::uint8_t *>(this + 1);
|
|
|
|
|
const auto fptr = ptr + (flags_len & 0xFF);
|
|
|
|
|
return std::bit_cast<const func *>(fptr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void make_immediate() {
|
|
|
|
|
constexpr void make_immediate() {
|
|
|
|
|
flags_len |= immediate;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
@ -113,7 +114,7 @@ struct forth
|
|
|
|
|
|
|
|
|
|
void rpush(func *v) {
|
|
|
|
|
assert<error::return_stack_overflow>(rp != rstack.begin());
|
|
|
|
|
*--rp = reinterpret_cast<cell>(v);
|
|
|
|
|
*--rp = v;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cell& top() {
|
|
|
|
@ -123,16 +124,12 @@ struct forth
|
|
|
|
|
|
|
|
|
|
cell pop() {
|
|
|
|
|
assert<error::stack_underflow>(sp != dstack.end());
|
|
|
|
|
auto ret = *sp;
|
|
|
|
|
*sp++ = -1;
|
|
|
|
|
return ret;//*sp++;
|
|
|
|
|
return *sp++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto rpop() -> func * {
|
|
|
|
|
assert<error::return_stack_underflow>(rp != rstack.end());
|
|
|
|
|
auto ret = reinterpret_cast<func *>(*rp);
|
|
|
|
|
*rp++ = -1;
|
|
|
|
|
return ret;
|
|
|
|
|
return *rp++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<int N>
|
|
|
|
@ -154,12 +151,11 @@ struct forth
|
|
|
|
|
//assert<error::dictionary_overflow>(state->here + size < &dictionary.back());
|
|
|
|
|
|
|
|
|
|
const auto h = std::exchange(here, here + size);
|
|
|
|
|
auto w = new (h) word_base (nullptr, namesz);
|
|
|
|
|
w->next = std::exchange(latest, w);
|
|
|
|
|
latest = new (h) word_base (latest, namesz);
|
|
|
|
|
std::copy(name.begin(), name.end(),
|
|
|
|
|
reinterpret_cast<char *>(h) + sizeof(word_base));
|
|
|
|
|
std::bit_cast<char *>(h) + sizeof(word_base));
|
|
|
|
|
if (entry)
|
|
|
|
|
*here++ = reinterpret_cast<cell>(entry);
|
|
|
|
|
*here++ = std::bit_cast<cell>(entry);
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -185,7 +181,7 @@ struct forth
|
|
|
|
|
auto body = (*ent)->body();
|
|
|
|
|
|
|
|
|
|
if (compiling && ((*ent)->flags_len & word_base::immediate) == 0) {
|
|
|
|
|
*here++ = reinterpret_cast<cell>(body);
|
|
|
|
|
*here++ = std::bit_cast<cell>(body);
|
|
|
|
|
} else {
|
|
|
|
|
execute(body);
|
|
|
|
|
}
|
|
|
|
@ -225,7 +221,7 @@ struct forth
|
|
|
|
|
fth.rpush(fth.ip);
|
|
|
|
|
|
|
|
|
|
for (fth.ip = body + 1; *fth.ip; fth.ip++)
|
|
|
|
|
fth.execute(reinterpret_cast<func *>(*fth.ip));
|
|
|
|
|
fth.execute(std::bit_cast<func *>(*fth.ip));
|
|
|
|
|
|
|
|
|
|
fth.ip = fth.rpop();
|
|
|
|
|
}
|
|
|
|
@ -238,10 +234,10 @@ struct forth
|
|
|
|
|
static auto& fth = **fthp;
|
|
|
|
|
|
|
|
|
|
constexpr static func lit_impl = [](auto) {
|
|
|
|
|
auto ptr = reinterpret_cast<cell *>(++fth.ip);
|
|
|
|
|
auto ptr = std::bit_cast<cell *>(++fth.ip);
|
|
|
|
|
fth.push(*ptr);
|
|
|
|
|
};
|
|
|
|
|
auto f_dict = [](auto) { fth.push(reinterpret_cast<cell>(&fth)); };
|
|
|
|
|
auto f_dict = [](auto) { fth.push(std::bit_cast<cell>(&fth)); };
|
|
|
|
|
auto f_add = [](auto) { fth.top() += fth.pop(); };
|
|
|
|
|
auto f_minus = [](auto) { fth.top() -= fth.pop(); };
|
|
|
|
|
auto f_times = [](auto) { fth.top() *= fth.pop(); };
|
|
|
|
@ -258,16 +254,16 @@ struct forth
|
|
|
|
|
const_cast<word_base *>(fth.latest)->make_immediate(); };
|
|
|
|
|
auto f_lit = [](auto) {
|
|
|
|
|
//assert<error::compile_only_word>(fth.compiling);
|
|
|
|
|
*fth.here++ = reinterpret_cast<cell>(&lit_impl);
|
|
|
|
|
*fth.here++ = std::bit_cast<cell>(&lit_impl);
|
|
|
|
|
*fth.here++ = fth.pop(); };
|
|
|
|
|
auto f_peek = [](auto) { fth.push(*reinterpret_cast<cell *>(fth.pop())); };
|
|
|
|
|
auto f_peek = [](auto) { fth.push(*std::bit_cast<cell *>(fth.pop())); };
|
|
|
|
|
auto f_poke = [](auto) {
|
|
|
|
|
auto [p, v] = fth.pop<2>();
|
|
|
|
|
*reinterpret_cast<cell *>(p) = v; };
|
|
|
|
|
auto f_cpeek = [](auto) { fth.push(*reinterpret_cast<char *>(fth.pop())); };
|
|
|
|
|
*std::bit_cast<cell *>(p) = v; };
|
|
|
|
|
auto f_cpeek = [](auto) { fth.push(*std::bit_cast<char *>(fth.pop())); };
|
|
|
|
|
auto f_cpoke = [](auto) {
|
|
|
|
|
auto [p, v] = fth.pop<2>();
|
|
|
|
|
*reinterpret_cast<char *>(p) = v; };
|
|
|
|
|
*std::bit_cast<char *>(p) = v; };
|
|
|
|
|
auto f_swap = [](auto) { auto [a, b] = fth.pop<2>(); fth.push(a, b); };
|
|
|
|
|
auto f_drop = [](auto) { fth.pop(); };
|
|
|
|
|
auto f_dup = [](auto) { fth.push(fth.top()); };
|
|
|
|
@ -278,26 +274,27 @@ struct forth
|
|
|
|
|
auto w = fth.parse();
|
|
|
|
|
|
|
|
|
|
if (auto g = fth.get(w); g)
|
|
|
|
|
fth.push(reinterpret_cast<cell>((*g)->body()));
|
|
|
|
|
fth.push(std::bit_cast<cell>((*g)->body()));
|
|
|
|
|
else
|
|
|
|
|
fth.push(0); };
|
|
|
|
|
auto f_colon = [](auto) {
|
|
|
|
|
const auto prologue = forth::prologue<fthp>;
|
|
|
|
|
auto w = fth.parse();
|
|
|
|
|
fth.add(w);
|
|
|
|
|
*fth.here++ = reinterpret_cast<cell>(forth::prologue<fthp>);
|
|
|
|
|
*fth.here++ = std::bit_cast<cell>(prologue);
|
|
|
|
|
fth.compiling = true; };
|
|
|
|
|
auto f_semic = [](auto) { *fth.here++ = 0; fth.compiling = false; };
|
|
|
|
|
auto f_comm = [](auto) { fth.sourcei = npos; };
|
|
|
|
|
auto f_cell = [](auto) { fth.push(sizeof(cell)); };
|
|
|
|
|
auto f_jmp = [](auto) {
|
|
|
|
|
auto ptr = ++fth.ip;
|
|
|
|
|
fth.ip = *reinterpret_cast<func **>(ptr) - 1;
|
|
|
|
|
fth.ip = *std::bit_cast<func **>(ptr) - 1;
|
|
|
|
|
};
|
|
|
|
|
auto f_jmp0 = [](auto) {
|
|
|
|
|
auto ptr = ++fth.ip;
|
|
|
|
|
|
|
|
|
|
if (fth.pop() == 0)
|
|
|
|
|
fth.ip = *reinterpret_cast<func **>(ptr) - 1;
|
|
|
|
|
fth.ip = *std::bit_cast<func **>(ptr) - 1;
|
|
|
|
|
};
|
|
|
|
|
auto f_postpone = [](auto) {
|
|
|
|
|
assert<error::compile_only_word>(fth.compiling);
|
|
|
|
@ -307,7 +304,7 @@ struct forth
|
|
|
|
|
|
|
|
|
|
assert<error::word_not_found>(g.has_value());
|
|
|
|
|
|
|
|
|
|
*fth.here++ = reinterpret_cast<cell>((*g)->body());
|
|
|
|
|
*fth.here++ = std::bit_cast<cell>((*g)->body());
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
constexpr static word w_dict {"_d", f_dict};
|
|
|
|
@ -372,9 +369,9 @@ struct forth
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cell *sp;
|
|
|
|
|
cell *rp;
|
|
|
|
|
func **rp;
|
|
|
|
|
func *ip = nullptr;
|
|
|
|
|
cell *here = reinterpret_cast<cell *>(this + 1);
|
|
|
|
|
cell *here = std::bit_cast<cell *>(this + 1);
|
|
|
|
|
const word_base *latest = nullptr;
|
|
|
|
|
const char *source = nullptr;
|
|
|
|
|
std::size_t sourcei = npos;
|
|
|
|
@ -382,7 +379,7 @@ struct forth
|
|
|
|
|
cell *end = nullptr;
|
|
|
|
|
cell base = 10;
|
|
|
|
|
std::array<cell, data_size> dstack;
|
|
|
|
|
std::array<cell, return_size> rstack;
|
|
|
|
|
std::array<func *, return_size> rstack;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static_assert(offsetof(forth::word_base, flags_len) == 1 * sizeof(forth::cell));
|
|
|
|
|