Browse Source

hide internal_state from public state struct

master
Daniel Kolesa 4 months ago
parent
commit
d80af7b159
  1. 5
      include/cubescript/cubescript.hh
  2. 5
      src/cs_bcode.cc
  3. 5
      src/cs_error.cc
  4. 12
      src/cs_gen.cc
  5. 4
      src/cs_gen.hh
  6. 3
      src/cs_parser.cc
  7. 113
      src/cs_state.cc
  8. 9
      src/cs_state.hh
  9. 9
      src/cs_std.cc
  10. 5
      src/cs_std.hh
  11. 3
      src/cs_strman.cc
  12. 4
      src/cs_thread.hh
  13. 2
      src/cs_val.cc
  14. 209
      src/cs_vm.cc
  15. 22
      src/cs_vm.hh
  16. 3
      src/lib_list.cc
  17. 5
      src/lib_str.cc
  18. 1
      src/meson.build

5
include/cubescript/cubescript.hh

@ -534,10 +534,8 @@ struct LIBCUBESCRIPT_EXPORT state {
friend struct string_ref;
friend struct any_value;
friend struct codegen_state;
friend inline internal_state *state_get_internal(state &);
internal_state *p_state;
thread_state *p_tstate;
thread_state *p_tstate = nullptr;
int identflags = 0;
@ -560,7 +558,6 @@ struct LIBCUBESCRIPT_EXPORT state {
void destroy();
void swap(state &s) {
std::swap(p_state, s.p_state);
std::swap(p_tstate, s.p_tstate);
std::swap(identflags, s.identflags);
std::swap(p_owner, s.p_owner);

5
src/cs_bcode.cc

@ -1,5 +1,6 @@
#include "cs_bcode.hh"
#include "cs_state.hh"
#include "cs_thread.hh"
namespace cubescript {
@ -44,11 +45,11 @@ struct bcode_hdr {
/* returned address is the 'init' member of the header */
std::uint32_t *bcode_alloc(state &cs, std::size_t sz) {
auto a = std_allocator<std::uint32_t>{cs};
auto a = std_allocator<std::uint32_t>{cs.p_tstate->istate};
std::size_t hdrs = sizeof(bcode_hdr) / sizeof(std::uint32_t);
auto p = a.allocate(sz + hdrs - 1);
bcode_hdr *hdr = reinterpret_cast<bcode_hdr *>(p);
hdr->cs = state_get_internal(cs);
hdr->cs = cs.p_tstate->istate;
hdr->asize = sz + hdrs - 1;
return p + hdrs - 1;
}

5
src/cs_error.cc

@ -45,8 +45,9 @@ LIBCUBESCRIPT_EXPORT char *error::request_buf(
}
LIBCUBESCRIPT_EXPORT stack_state error::save_stack(state &cs) {
auto &ts = *cs.p_tstate;
integer_var *dalias = static_cast<integer_var *>(
cs.p_state->identmap[ID_IDX_DBGALIAS]
ts.istate->identmap[ID_IDX_DBGALIAS]
);
if (!dalias->get_value()) {
return stack_state(cs, nullptr, !!cs.p_tstate->callstack);
@ -58,7 +59,7 @@ LIBCUBESCRIPT_EXPORT stack_state error::save_stack(state &cs) {
if (!total) {
return stack_state(cs, nullptr, false);
}
stack_state_node *st = cs.p_state->create_array<stack_state_node>(
stack_state_node *st = ts.istate->create_array<stack_state_node>(
std::min(total, dalias->get_value())
);
stack_state_node *ret = st, *nd = st;

12
src/cs_gen.cc

@ -22,7 +22,7 @@ std::string_view codegen_state::get_str() {
}
charbuf codegen_state::get_str_dup() {
charbuf buf{cs};
charbuf buf{cs.p_tstate->istate};
unescape_string(std::back_inserter(buf), get_str());
return buf;
}
@ -199,7 +199,7 @@ static inline void compileunescapestr(codegen_state &gs) {
gs.code.size() + str.size() / sizeof(uint32_t) + 1
);
size_t bufs = (gs.code.capacity() - gs.code.size()) * sizeof(uint32_t);
auto alloc = std_allocator<char>{gs.cs};
auto alloc = std_allocator<char>{gs.cs.p_tstate->istate};
auto *buf = alloc.allocate(bufs + 1);
char *wbuf = unescape_string(&buf[0], str);
memset(
@ -218,7 +218,7 @@ static bool compilearg(
);
static void compilelookup(codegen_state &gs, int ltype, int prevargs = MAX_RESULTS) {
charbuf lookup{gs.cs};
charbuf lookup{gs.cs.p_tstate->istate};
gs.next_char();
switch (gs.current()) {
case '(':
@ -466,7 +466,7 @@ static bool compileblockstr(codegen_state &gs, char const *str, char const *send
int startc = gs.code.size();
gs.code.push_back(BC_INST_VAL | BC_RET_STRING);
gs.code.reserve(gs.code.size() + (send - str) / sizeof(uint32_t) + 1);
auto alloc = std_allocator<char>{gs.cs};
auto alloc = std_allocator<char>{gs.cs.p_tstate->istate};
auto asz = ((send - str) / sizeof(uint32_t) + 1) * sizeof(uint32_t);
char *buf = alloc.allocate(asz);
int len = 0;
@ -519,7 +519,7 @@ done:
}
static bool compileblocksub(codegen_state &gs, int prevargs) {
charbuf lookup{gs.cs};
charbuf lookup{gs.cs.p_tstate->istate};
switch (gs.current()) {
case '(':
if (!compilearg(gs, VAL_ANY, prevargs)) {
@ -1214,7 +1214,7 @@ static void compile_and_or(
}
static void compilestatements(codegen_state &gs, int rettype, int brak, int prevargs) {
charbuf idname{gs.cs};
charbuf idname{gs.cs.p_tstate->istate};
for (;;) {
gs.skip_comments();
idname.clear();

4
src/cs_gen.hh

@ -33,7 +33,7 @@ struct codegen_state {
codegen_state() = delete;
codegen_state(state &csr):
cs{csr}, prevps{csr.p_tstate->cstate}, code{cs},
cs{csr}, prevps{csr.p_tstate->cstate}, code{csr.p_tstate->istate},
source{}, send{}, current_line{1}, src_name{}
{
csr.p_tstate->cstate = this;
@ -122,7 +122,7 @@ struct codegen_state {
}
void gen_ident() {
gen_ident(cs.p_state->identmap[ID_IDX_DUMMY]);
gen_ident(cs.p_tstate->istate->identmap[ID_IDX_DUMMY]);
}
void gen_ident(std::string_view word) {

3
src/cs_parser.cc

@ -4,6 +4,7 @@
#include <cctype>
#include "cs_std.hh"
#include "cs_thread.hh"
namespace cubescript {
@ -398,7 +399,7 @@ LIBCUBESCRIPT_EXPORT std::size_t list_parser::count() {
LIBCUBESCRIPT_EXPORT string_ref list_parser::get_item() const {
if (!p_quoted_item.empty() && (p_quoted_item.front() == '"')) {
charbuf buf{*p_state};
charbuf buf{p_state->p_tstate->istate};
unescape_string(std::back_inserter(buf), p_item);
return string_ref{*p_state, buf.str()};
}

113
src/cs_state.cc

@ -49,23 +49,29 @@ void init_lib_list(state &cs);
state::state(): state{default_alloc, nullptr} {}
state::state(alloc_func func, void *data):
p_state{nullptr}
{
state::state(alloc_func func, void *data) {
command *p;
if (!func) {
func = default_alloc;
}
/* allocator is not set up yet, use func directly */
p_state = static_cast<internal_state *>(
auto *statep = static_cast<internal_state *>(
func(data, nullptr, 0, sizeof(internal_state))
);
/* allocator will be set up in the constructor */
new (p_state) internal_state{func, data};
p_owner = true;
new (statep) internal_state{func, data};
try {
p_tstate = statep->create<thread_state>(statep);
} catch (...) {
statep->destroy(statep);
throw;
}
p_tstate = p_state->create<thread_state>(p_state);
p_tstate->pstate = this;
p_tstate->istate = statep;
p_owner = true;
for (int i = 0; i < MAX_ARGUMENTS; ++i) {
char buf[32];
@ -94,7 +100,7 @@ state::state(alloc_func func, void *data):
static_cast<command_impl *>(p)->p_type = ID_DO;
p = new_command("doargs", "e", [](auto &cs, auto args, auto &res) {
call_with_args(cs, [&cs, &res, &args]() {
call_with_args(*cs.p_tstate, [&cs, &res, &args]() {
cs.run(args[0].get_code(), res);
});
});
@ -182,30 +188,32 @@ LIBCUBESCRIPT_EXPORT state::~state() {
}
LIBCUBESCRIPT_EXPORT void state::destroy() {
if (!p_state || !p_owner) {
if (!p_tstate || !p_owner) {
return;
}
for (auto &p: p_state->idents) {
auto *sp = p_tstate->istate;
for (auto &p: sp->idents) {
ident *i = p.second;
alias *a = i->get_alias();
if (a) {
a->get_value().force_none();
static_cast<alias_impl *>(a)->clean_code();
}
p_state->destroy(i->p_impl);
sp->destroy(i->p_impl);
}
p_state->destroy(p_tstate);
p_state->destroy(p_state);
sp->destroy(p_tstate);
sp->destroy(sp);
}
state::state(internal_state *s):
p_state(s), p_owner(false)
p_owner{false}
{
p_tstate = p_state->create<thread_state>(p_state);
p_tstate = s->create<thread_state>(s);
p_tstate->istate = s;
}
LIBCUBESCRIPT_EXPORT state state::new_thread() {
return state{p_state};
return state{p_tstate->istate};
}
LIBCUBESCRIPT_EXPORT hook_func state::set_call_hook(hook_func func) {
@ -223,23 +231,23 @@ LIBCUBESCRIPT_EXPORT hook_func &state::get_call_hook() {
LIBCUBESCRIPT_EXPORT var_print_func state::set_var_printer(
var_print_func func
) {
auto fn = std::move(p_state->varprintf);
p_state->varprintf = std::move(func);
auto fn = std::move(p_tstate->istate->varprintf);
p_tstate->istate->varprintf = std::move(func);
return fn;
}
LIBCUBESCRIPT_EXPORT var_print_func const &state::get_var_printer() const {
return p_state->varprintf;
return p_tstate->istate->varprintf;
}
LIBCUBESCRIPT_EXPORT void state::print_var(global_var const &v) const {
if (p_state->varprintf) {
p_state->varprintf(*this, v);
if (p_tstate->istate->varprintf) {
p_tstate->istate->varprintf(*this, v);
}
}
LIBCUBESCRIPT_EXPORT void *state::alloc(void *ptr, size_t os, size_t ns) {
return p_state->alloc(ptr, os, ns);
return p_tstate->istate->alloc(ptr, os, ns);
}
LIBCUBESCRIPT_EXPORT ident *state::add_ident(
@ -249,10 +257,10 @@ LIBCUBESCRIPT_EXPORT ident *state::add_ident(
return nullptr;
}
id->p_impl = impl;
p_state->idents[id->get_name()] = id;
static_cast<ident_impl *>(impl)->p_index = p_state->identmap.size();
p_state->identmap.push_back(id);
return p_state->identmap.back();
p_tstate->istate->idents[id->get_name()] = id;
static_cast<ident_impl *>(impl)->p_index = p_tstate->istate->identmap.size();
p_tstate->istate->identmap.push_back(id);
return p_tstate->istate->identmap.back();
}
LIBCUBESCRIPT_EXPORT ident *state::new_ident(
@ -265,8 +273,8 @@ LIBCUBESCRIPT_EXPORT ident *state::new_ident(
*this, "number %s is not a valid identifier name", name.data()
};
}
auto *inst = p_state->create<alias_impl>(
*this, string_ref{p_state, name}, flags
auto *inst = p_tstate->istate->create<alias_impl>(
*this, string_ref{p_tstate->istate, name}, flags
);
id = add_ident(inst, inst);
}
@ -274,8 +282,8 @@ LIBCUBESCRIPT_EXPORT ident *state::new_ident(
}
LIBCUBESCRIPT_EXPORT ident *state::get_ident(std::string_view name) {
auto id = p_state->idents.find(name);
if (id != p_state->idents.end()) {
auto id = p_tstate->istate->idents.find(name);
if (id != p_tstate->istate->idents.end()) {
return id->second;
}
return nullptr;
@ -290,27 +298,27 @@ LIBCUBESCRIPT_EXPORT alias *state::get_alias(std::string_view name) {
}
LIBCUBESCRIPT_EXPORT bool state::have_ident(std::string_view name) {
return p_state->idents.find(name) != p_state->idents.end();
return p_tstate->istate->idents.find(name) != p_tstate->istate->idents.end();
}
LIBCUBESCRIPT_EXPORT std::span<ident *> state::get_idents() {
return std::span<ident *>{
p_state->identmap.data(),
p_state->identmap.size()
p_tstate->istate->identmap.data(),
p_tstate->istate->identmap.size()
};
}
LIBCUBESCRIPT_EXPORT std::span<ident const *> state::get_idents() const {
auto ptr = const_cast<ident const **>(p_state->identmap.data());
return std::span<ident const *>{ptr, p_state->identmap.size()};
auto ptr = const_cast<ident const **>(p_tstate->istate->identmap.data());
return std::span<ident const *>{ptr, p_tstate->istate->identmap.size()};
}
LIBCUBESCRIPT_EXPORT integer_var *state::new_ivar(
std::string_view n, integer_type m, integer_type x, integer_type v,
var_cb_func f, int flags
) {
auto *iv = p_state->create<ivar_impl>(
string_ref{p_state, n}, m, x, v, std::move(f), flags
auto *iv = p_tstate->istate->create<ivar_impl>(
string_ref{p_tstate->istate, n}, m, x, v, std::move(f), flags
);
add_ident(iv, iv);
return iv;
@ -320,8 +328,8 @@ LIBCUBESCRIPT_EXPORT float_var *state::new_fvar(
std::string_view n, float_type m, float_type x, float_type v,
var_cb_func f, int flags
) {
auto *fv = p_state->create<fvar_impl>(
string_ref{p_state, n}, m, x, v, std::move(f), flags
auto *fv = p_tstate->istate->create<fvar_impl>(
string_ref{p_tstate->istate, n}, m, x, v, std::move(f), flags
);
add_ident(fv, fv);
return fv;
@ -330,9 +338,9 @@ LIBCUBESCRIPT_EXPORT float_var *state::new_fvar(
LIBCUBESCRIPT_EXPORT string_var *state::new_svar(
std::string_view n, std::string_view v, var_cb_func f, int flags
) {
auto *sv = p_state->create<svar_impl>(
string_ref{p_state, n}, string_ref{p_state, v},
string_ref{p_state, ""}, std::move(f), flags
auto *sv = p_tstate->istate->create<svar_impl>(
string_ref{p_tstate->istate, n}, string_ref{p_tstate->istate, v},
string_ref{p_tstate->istate, ""}, std::move(f), flags
);
add_ident(sv, sv);
return sv;
@ -389,8 +397,8 @@ LIBCUBESCRIPT_EXPORT void state::set_alias(
} else if (!is_valid_name(name)) {
throw error{*this, "cannot alias invalid name '%s'", name.data()};
} else {
auto *a = p_state->create<alias_impl>(
*this, string_ref{p_state, name}, std::move(v), identflags
auto *a = p_tstate->istate->create<alias_impl>(
*this, string_ref{p_tstate->istate, name}, std::move(v), identflags
);
add_ident(a, a);
}
@ -445,9 +453,10 @@ LIBCUBESCRIPT_EXPORT command *state::new_command(
return nullptr;
}
}
auto *cmd = p_state->create<command_impl>(
string_ref{p_state, name}, string_ref{p_state, args}, nargs,
std::move(func)
auto *cmd = p_tstate->istate->create<command_impl>(
string_ref{p_tstate->istate, name},
string_ref{p_tstate->istate, args},
nargs, std::move(func)
);
add_ident(cmd, cmd);
return cmd;
@ -489,7 +498,7 @@ LIBCUBESCRIPT_EXPORT void state::clear_override(ident &id) {
}
LIBCUBESCRIPT_EXPORT void state::clear_overrides() {
for (auto &p: p_state->idents) {
for (auto &p: p_tstate->istate->idents) {
clear_override(*(p.second));
}
}
@ -570,7 +579,7 @@ LIBCUBESCRIPT_EXPORT void state::set_var_str(
*this, sv, sv->p_flags,
[&sv]() { sv->p_overrideval = sv->get_value(); }
);
sv->set_value(string_ref{p_state, v});
sv->set_value(string_ref{p_tstate->istate, v});
if (dofunc) {
sv->changed(*this);
}
@ -600,7 +609,9 @@ state::get_var_str(std::string_view name) {
if (!id || id->is_svar()) {
return std::nullopt;
}
return string_ref{p_state, static_cast<string_var *>(id)->get_value()};
return string_ref{
p_tstate->istate, static_cast<string_var *>(id)->get_value()
};
}
LIBCUBESCRIPT_EXPORT std::optional<integer_type>
@ -756,7 +767,7 @@ LIBCUBESCRIPT_EXPORT void state::set_var_str_checked(
*this, sv, svp->p_flags,
[&svp]() { svp->p_overrideval = svp->p_storage; }
);
sv->set_value(string_ref{p_state, v});
sv->set_value(string_ref{p_tstate->istate, v});
svp->changed(*this);
}

9
src/cs_state.hh

@ -10,7 +10,6 @@
namespace cubescript {
struct state;
struct internal_state;
struct string_pool;
@ -19,7 +18,6 @@ struct std_allocator {
using value_type = T;
inline std_allocator(internal_state *s);
inline std_allocator(state &cs);
template<typename U>
std_allocator(std_allocator<U> const &a): istate{a.istate} {};
@ -91,16 +89,9 @@ struct internal_state {
}
};
inline internal_state *state_get_internal(state &cs) {
return cs.p_state;
}
template<typename T>
inline std_allocator<T>::std_allocator(internal_state *s): istate{s} {}
template<typename T>
inline std_allocator<T>::std_allocator(state &s): istate{state_get_internal(s)} {}
template<typename T>
inline T *std_allocator<T>::allocate(std::size_t n) {
return static_cast<T *>(istate->alloc(nullptr, 0, n * sizeof(T)));

9
src/cs_std.cc

@ -0,0 +1,9 @@
#include "cs_std.hh"
#include "cs_thread.hh"
namespace cubescript {
charbuf::charbuf(state &cs): charbuf{cs.p_tstate->istate} {}
} /* namespace cubescript */

5
src/cs_std.hh

@ -13,6 +13,8 @@
namespace cubescript {
struct state;
/* run func, call the second one after finishing */
template<typename F1, typename F2>
@ -59,7 +61,6 @@ struct valbuf {
valbuf() = delete;
valbuf(internal_state *cs): buf{std_allocator<T>{cs}} {}
valbuf(state &cs): buf{std_allocator<T>{cs}} {}
using size_type = std::size_t;
using value_type = T;
@ -108,7 +109,7 @@ struct valbuf {
struct charbuf: valbuf<char> {
charbuf(internal_state *cs): valbuf<char>{cs} {}
charbuf(state &cs): valbuf<char>{cs} {}
charbuf(state &cs);
void append(char const *beg, char const *end) {
valbuf<char>::append(beg, end);

3
src/cs_strman.cc

@ -1,6 +1,7 @@
#include <cubescript/cubescript.hh>
#include "cs_strman.hh"
#include "cs_thread.hh"
namespace cubescript {
@ -120,7 +121,7 @@ LIBCUBESCRIPT_EXPORT string_ref::string_ref(
}
LIBCUBESCRIPT_EXPORT string_ref::string_ref(state &cs, std::string_view str):
p_state{cs.p_state}
p_state{cs.p_tstate->istate}
{
p_str = p_state->strman->add(str);
}

4
src/cs_thread.hh

@ -15,6 +15,10 @@ struct codegen_state;
struct thread_state {
/* thread call stack */
ident_link *callstack{};
/* the shared state pointer */
internal_state *istate{};
/* the public state interface */
state *pstate{};
/* current codegen state for diagnostics */
codegen_state *cstate{};
/* value stack for VM */

2
src/cs_val.cc

@ -83,7 +83,7 @@ static inline void csv_cleanup(value_type tv, T *stor) {
}
}
any_value::any_value(state &st): any_value(*st.p_state) {}
any_value::any_value(state &st): any_value(*st.p_tstate->istate) {}
any_value::any_value(internal_state &st):
p_stor(), p_type(value_type::NONE)

209
src/cs_vm.cc

@ -43,7 +43,7 @@ stack_state::~stack_state() {
for (stack_state_node const *nd = p_node; nd; nd = nd->next) {
++len;
}
p_state.p_state->destroy_array(p_node, len);
p_state.p_tstate->istate->destroy_array(p_node, len);
}
stack_state &stack_state::operator=(stack_state &&st) {
@ -83,7 +83,7 @@ static inline void force_arg(any_value &v, int type) {
}
static inline void callcommand(
state &cs, command_impl *id, any_value *args, any_value &res,
thread_state &ts, command_impl *id, any_value *args, any_value &res,
std::size_t nargs, bool lookup = false
) {
int i = -1, fakeargs = 0, numargs = int(nargs);
@ -168,7 +168,7 @@ static inline void callcommand(
if (str.empty()) {
args[i].set_int(0);
} else {
args[i].force_code(cs);
args[i].force_code(*ts.pstate);
}
}
break;
@ -178,11 +178,11 @@ static inline void callcommand(
break;
}
args[i].set_code(
bcode_get_empty(state_get_internal(cs)->empty, VAL_NULL)
bcode_get_empty(ts.istate->empty, VAL_NULL)
);
fakeargs++;
} else {
args[i].force_code(cs);
args[i].force_code(*ts.pstate);
}
break;
case 'r':
@ -190,10 +190,10 @@ static inline void callcommand(
if (rep) {
break;
}
args[i].set_ident(cs.p_state->identmap[ID_IDX_DUMMY]);
args[i].set_ident(ts.istate->identmap[ID_IDX_DUMMY]);
fakeargs++;
} else {
args[i].force_ident(cs);
args[i].force_ident(*ts.pstate);
}
break;
case '$':
@ -206,19 +206,19 @@ static inline void callcommand(
break;
case 'C': {
i = std::max(i + 1, numargs);
any_value tv{cs};
any_value tv{*ts.pstate};
tv.set_str(concat_values(
cs, std::span{args, std::size_t(i)}, " "
*ts.pstate, std::span{args, std::size_t(i)}, " "
));
static_cast<command_impl *>(id)->call(
cs, std::span<any_value>(&tv, &tv + 1), res
*ts.pstate, std::span<any_value>(&tv, &tv + 1), res
);
return;
}
case 'V':
i = std::max(i + 1, numargs);
static_cast<command_impl *>(id)->call(
cs, std::span{args, std::size_t(i)}, res
*ts.pstate, std::span{args, std::size_t(i)}, res
);
return;
case '1':
@ -234,54 +234,54 @@ static inline void callcommand(
}
++i;
static_cast<command_impl *>(id)->call(
cs, std::span<any_value>{args, std::size_t(i)}, res
*ts.pstate, std::span<any_value>{args, std::size_t(i)}, res
);
}
static std::uint32_t *runcode(
state &cs, std::uint32_t *code, any_value &result
thread_state &ts, std::uint32_t *code, any_value &result
);
static inline void call_alias(
state &cs, alias *a, any_value *args, any_value &result,
thread_state &ts, alias *a, any_value *args, any_value &result,
std::size_t callargs, std::size_t &nargs,
std::size_t offset, std::size_t skip, std::uint32_t op
) {
integer_var *anargs = static_cast<integer_var *>(
cs.p_state->identmap[ID_IDX_NUMARGS]
ts.istate->identmap[ID_IDX_NUMARGS]
);
valarray<ident_stack, MAX_ARGUMENTS> argstack{cs};
valarray<ident_stack, MAX_ARGUMENTS> argstack{*ts.pstate};
for(std::size_t i = 0; i < callargs; i++) {
static_cast<alias_impl *>(cs.p_state->identmap[i])->push_arg(
static_cast<alias_impl *>(ts.istate->identmap[i])->push_arg(
args[offset + i], argstack[i], false
);
}
auto oldargs = anargs->get_value();
anargs->set_value(callargs);
int oldflags = cs.identflags;
cs.identflags |= a->get_flags()&IDENT_FLAG_OVERRIDDEN;
int oldflags = ts.pstate->identflags;
ts.pstate->identflags |= a->get_flags()&IDENT_FLAG_OVERRIDDEN;
ident_link aliaslink = {
a, cs.p_tstate->callstack, (1<<callargs)-1, &argstack[0]
a, ts.callstack, (1<<callargs)-1, &argstack[0]
};
cs.p_tstate->callstack = &aliaslink;
ts.callstack = &aliaslink;
std::uint32_t *codep = static_cast<
alias_impl *
>(a)->compile_code(cs)->get_raw();
>(a)->compile_code(*ts.pstate)->get_raw();
bcode_incr(codep);
call_with_cleanup([&]() {
runcode(cs, codep+1, result);
runcode(ts, codep+1, result);
}, [&]() {
bcode_decr(codep);
cs.p_tstate->callstack = aliaslink.next;
cs.identflags = oldflags;
ts.callstack = aliaslink.next;
ts.pstate->identflags = oldflags;
for (std::size_t i = 0; i < callargs; i++) {
static_cast<alias_impl *>(cs.p_state->identmap[i])->pop_arg();
static_cast<alias_impl *>(ts.istate->identmap[i])->pop_arg();
}
int argmask = aliaslink.usedargs & int(~0U << callargs);
for (; argmask; ++callargs) {
if (argmask & (1 << callargs)) {
static_cast<alias_impl *>(
cs.p_state->identmap[callargs]
ts.istate->identmap[callargs]
)->pop_arg();
argmask &= ~(1 << callargs);
}
@ -309,7 +309,7 @@ struct run_depth_guard {
};
static inline alias *get_lookup_id(state &cs, std::uint32_t op) {
ident *id = cs.p_state->identmap[op >> 8];
ident *id = cs.p_tstate->istate->identmap[op >> 8];
if (id->get_flags() & IDENT_FLAG_UNKNOWN) {
throw error(cs, "unknown alias lookup: %s", id->get_name().data());
}
@ -317,7 +317,7 @@ static inline alias *get_lookup_id(state &cs, std::uint32_t op) {
}
static inline alias *get_lookuparg_id(state &cs, std::uint32_t op) {
ident *id = cs.p_state->identmap[op >> 8];
ident *id = cs.p_tstate->istate->identmap[op >> 8];
if (!ident_is_used_arg(id, cs)) {
return nullptr;
}
@ -342,19 +342,22 @@ struct stack_guard {
};
static inline int get_lookupu_type(
state &cs, any_value &arg, ident *&id, std::uint32_t op
thread_state &ts, any_value &arg, ident *&id, std::uint32_t op
) {
if (arg.get_type() != value_type::STRING) {
return -2; /* default case */
}
id = cs.get_ident(arg.get_str());
id = ts.pstate->get_ident(arg.get_str());
if (id) {
switch(id->get_type()) {
case ident_type::ALIAS:
if (id->get_flags() & IDENT_FLAG_UNKNOWN) {
break;
}
if ((id->get_index() < MAX_ARGUMENTS) && !ident_is_used_arg(id, cs)) {
if (
(id->get_index() < MAX_ARGUMENTS) &&
!ident_is_used_arg(id, *ts.pstate)
) {
return ID_UNKNOWN;
}
return ID_ALIAS;
@ -365,14 +368,15 @@ static inline int get_lookupu_type(
case ident_type::FVAR:
return ID_FVAR;
case ident_type::COMMAND: {
stack_guard s{cs}; /* make sure value stack gets restored */
/* make sure value stack gets restored */
stack_guard s{*ts.pstate};
auto *cimpl = static_cast<command_impl *>(id);
auto &args = cs.p_tstate->vmstack;
auto &args = ts.vmstack;
auto osz = args.size();
/* pad with as many empty values as we need */
args.resize(osz + cimpl->get_num_args(), any_value{cs});
args.resize(osz + cimpl->get_num_args(), any_value{*ts.pstate});
arg.set_none();
callcommand(cs, cimpl, &args[osz], arg, 0, true);
callcommand(ts, cimpl, &args[osz], arg, 0, true);
force_arg(arg, op & BC_INST_RET_MASK);
return -2; /* ignore */
}
@ -380,16 +384,17 @@ static inline int get_lookupu_type(
return ID_UNKNOWN;
}
}
throw error(cs, "unknown alias lookup: %s", arg.get_str().data());
throw error{*ts.pstate, "unknown alias lookup: %s", arg.get_str().data()};
}
static std::uint32_t *runcode(
state &cs, std::uint32_t *code, any_value &result
thread_state &ts, std::uint32_t *code, any_value &result
) {
result.set_none();
auto &cs = *ts.pstate;
run_depth_guard level{cs}; /* incr and decr on scope exit */
stack_guard guard{cs}; /* resize back to original */
auto &args = cs.p_tstate->vmstack;
auto &args = ts.vmstack;
auto &chook = cs.get_call_hook();
if (chook) {
chook(cs);
@ -454,10 +459,10 @@ static std::uint32_t *runcode(
args.pop_back();
continue;
case BC_INST_ENTER:
code = runcode(cs, code, args.emplace_back(cs));
code = runcode(ts, code, args.emplace_back(cs));
continue;
case BC_INST_ENTER_RESULT:
code = runcode(cs, code, result);
code = runcode(ts, code, result);
continue;
case BC_INST_EXIT | BC_RET_STRING:
case BC_INST_EXIT | BC_RET_INT:
@ -475,7 +480,7 @@ static std::uint32_t *runcode(
args.emplace_back(std::move(result));
continue;
case BC_INST_PRINT:
cs.print_var(*static_cast<global_var *>(cs.p_state->identmap[op >> 8]));
cs.print_var(*static_cast<global_var *>(ts.istate->identmap[op >> 8]));
continue;
case BC_INST_LOCAL: {
@ -486,7 +491,7 @@ static std::uint32_t *runcode(
push_alias(cs, args[offset + i].get_ident(), locals[i]);
}
call_with_cleanup([&]() {
code = runcode(cs, code, result);
code = runcode(ts, code, result);
}, [&]() {
for (std::size_t i = offset; i < args.size(); ++i) {
pop_alias(args[i].get_ident());
@ -499,7 +504,7 @@ static std::uint32_t *runcode(
case BC_INST_DO_ARGS | BC_RET_STRING:
case BC_INST_DO_ARGS | BC_RET_INT:
case BC_INST_DO_ARGS | BC_RET_FLOAT:
call_with_args(cs, [&]() {
call_with_args(ts, [&]() {
auto v = std::move(args.back());
args.pop_back();
cs.run(v.get_code(), result);
@ -571,14 +576,14 @@ static std::uint32_t *runcode(
if (cs.is_in_loop()) {
throw break_exception();
} else {
throw error(cs, "no loop to break");
throw error{cs, "no loop to break"};
}
break;
case BC_INST_BREAK | BC_INST_FLAG_TRUE:
if (cs.is_in_loop()) {
throw continue_exception();
} else {
throw error(cs, "no loop to continue");
throw error{cs, "no loop to continue"};
}
break;
@ -672,22 +677,22 @@ static std::uint32_t *runcode(
case BC_INST_EMPTY | BC_RET_NULL:
args.emplace_back(cs).set_code(
bcode_get_empty(state_get_internal(cs)->empty, VAL_NULL)
bcode_get_empty(ts.istate->empty, VAL_NULL)
);
break;
case BC_INST_EMPTY | BC_RET_STRING:
args.emplace_back(cs).set_code(
bcode_get_empty(state_get_internal(cs)->empty, VAL_STRING)
bcode_get_empty(ts.istate->empty, VAL_STRING)
);
break;
case BC_INST_EMPTY | BC_RET_INT:
args.emplace_back(cs).set_code(
bcode_get_empty(state_get_internal(cs)->empty, VAL_INT)
bcode_get_empty(ts.istate->empty, VAL_INT)
);
break;
case BC_INST_EMPTY | BC_RET_FLOAT:
args.emplace_back(cs).set_code(
bcode_get_empty(state_get_internal(cs)->empty, VAL_FLOAT)
bcode_get_empty(ts.istate->empty, VAL_FLOAT)
);
break;
case BC_INST_BLOCK: {
@ -700,7 +705,7 @@ static std::uint32_t *runcode(
}
case BC_INST_COMPILE: {
any_value &arg = args.back();
codegen_state gs(cs);
codegen_state gs{cs};
switch (arg.get_type()) {
case value_type::INT:
gs.code.reserve(8);
@ -745,7 +750,7 @@ static std::uint32_t *runcode(
case value_type::STRING: {
std::string_view s = arg.get_str();
if (!s.empty()) {
codegen_state gs(cs);
codegen_state gs{cs};
gs.code.reserve(64);
gs.gen_main(s);
gs.done();
@ -769,36 +774,36 @@ static std::uint32_t *runcode(
}
case BC_INST_IDENT:
args.emplace_back(cs).set_ident(cs.p_state->identmap[op >> 8]);
args.emplace_back(cs).set_ident(ts.istate->identmap[op >> 8]);
continue;
case BC_INST_IDENT_ARG: {
alias *a = static_cast<alias *>(
cs.p_state->identmap[op >> 8]
ts.istate->identmap[op >> 8]
);
if (!ident_is_used_arg(a, cs)) {
any_value nv{cs};
static_cast<alias_impl *>(a)->push_arg(
nv, cs.p_tstate->callstack->argstack[a->get_index()],
nv, ts.callstack->argstack[a->get_index()],
false
);
cs.p_tstate->callstack->usedargs |= 1 << a->get_index();
ts.callstack->usedargs |= 1 << a->get_index();
}
args.emplace_back(cs).set_ident(a);
continue;
}
case BC_INST_IDENT_U: {
any_value &arg = args.back();
ident *id = cs.p_state->identmap[ID_IDX_DUMMY];
ident *id = ts.istate->identmap[ID_IDX_DUMMY];
if (arg.get_type() == value_type::STRING) {
id = cs.new_ident(arg.get_str());
}
if ((id->get_index() < MAX_ARGUMENTS) && !ident_is_used_arg(id, cs)) {
any_value nv{cs};
static_cast<alias_impl *>(id)->push_arg(
nv, cs.p_tstate->callstack->argstack[id->get_index()],
nv, ts.callstack->argstack[id->get_index()],
false
);
cs.p_tstate->callstack->usedargs |= 1 << id->get_index();
ts.callstack->usedargs |= 1 << id->get_index();
}
arg.set_ident(id);
continue;
@ -807,7 +812,7 @@ static std::uint32_t *runcode(
case BC_INST_LOOKUP_U | BC_RET_STRING: {
ident *id = nullptr;
any_value &arg = args.back();
switch (get_lookupu_type(cs, arg, id, op)) {
switch (get_lookupu_type(ts, arg, id, op)) {
case ID_ALIAS:
arg = static_cast<alias *>(id)->get_value();
arg.force_str();
@ -850,7 +855,7 @@ static std::uint32_t *runcode(
case BC_INST_LOOKUP_U | BC_RET_INT: {
ident *id = nullptr;
any_value &arg = args.back();
switch (get_lookupu_type(cs, arg, id, op)) {
switch (get_lookupu_type(ts, arg, id, op)) {
case ID_ALIAS:
arg.set_int(
static_cast<alias *>(id)->get_value().get_int()
@ -893,7 +898,7 @@ static std::uint32_t *runcode(
case BC_INST_LOOKUP_U | BC_RET_FLOAT: {
ident *id = nullptr;
any_value &arg = args.back();
switch (get_lookupu_type(cs, arg, id, op)) {
switch (get_lookupu_type(ts, arg, id, op)) {
case ID_ALIAS:
arg.set_float(
static_cast<alias *>(id)->get_value().get_float()
@ -938,7 +943,7 @@ static std::uint32_t *runcode(
case BC_INST_LOOKUP_U | BC_RET_NULL: {
ident *id = nullptr;
any_value &arg = args.back();
switch (get_lookupu_type(cs, arg, id, op)) {
switch (get_lookupu_type(ts, arg, id, op)) {
case ID_ALIAS:
static_cast<alias *>(id)->get_value().get_val(arg);
continue;
@ -978,7 +983,7 @@ static std::uint32_t *runcode(
case BC_INST_LOOKUP_MU | BC_RET_STRING: {
ident *id = nullptr;
any_value &arg = args.back();
switch (get_lookupu_type(cs, arg, id, op)) {
switch (get_lookupu_type(ts, arg, id, op)) {
case ID_ALIAS:
arg = static_cast<alias *>(id)->get_value();
arg.force_str();
@ -1021,7 +1026,7 @@ static std::uint32_t *runcode(
case BC_INST_LOOKUP_MU | BC_RET_NULL: {
ident *id = nullptr;
any_value &arg = args.back();
switch (get_lookupu_type(cs, arg, id, op)) {
switch (get_lookupu_type(ts, arg, id, op)) {
case ID_ALIAS:
static_cast<alias *>(id)->get_cval(arg);
continue;
@ -1057,20 +1062,20 @@ static std::uint32_t *runcode(
case BC_INST_SVAR | BC_RET_STRING:
case BC_INST_SVAR | BC_RET_NULL:
args.emplace_back(cs).set_str(static_cast<string_var *>(
cs.p_state->identmap[op >> 8]
ts.istate->identmap[op >> 8]
)->get_value());
continue;
case BC_INST_SVAR | BC_RET_INT:
args.emplace_back(cs).set_int(parse_int(
static_cast<string_var *>(
cs.p_state->identmap[op >> 8]
ts.istate->identmap[op >> 8]
)->get_value()
));
continue;
case BC_INST_SVAR | BC_RET_FLOAT:
args.emplace_back(cs).set_float(parse_float(
static_cast<string_var *>(
cs.p_state->identmap[op >> 8]
ts.istate->identmap[op >> 8]
)->get_value()
));
continue;
@ -1078,7 +1083,7 @@ static std::uint32_t *runcode(
auto v = std::move(args.back());
args.pop_back();
cs.set_var_str_checked(
static_cast<string_var *>(cs.p_state->identmap[op >> 8]),
static_cast<string_var *>(ts.istate->identmap[op >> 8]),
v.get_str()
);
continue;
@ -1087,13 +1092,13 @@ static std::uint32_t *runcode(
case BC_INST_IVAR | BC_RET_INT:
case BC_INST_IVAR | BC_RET_NULL:
args.emplace_back(cs).set_int(static_cast<integer_var *>(
cs.p_state->identmap[op >> 8]
ts.istate->identmap[op >> 8]
)->get_value());
continue;
case BC_INST_IVAR | BC_RET_STRING: {
auto &v = args.emplace_back(cs);
v.set_int(static_cast<integer_var *>(
cs.p_state->identmap[op >> 8]
ts.istate->identmap[op >> 8]
)->get_value());
v.force_str();
continue;
@ -1101,7 +1106,7 @@ static std::uint32_t *runcode(
case BC_INST_IVAR | BC_RET_FLOAT:
args.emplace_back(cs).set_float(float_type(
static_cast<integer_var *>(
cs.p_state->identmap[op >> 8]
ts.istate->identmap[op >> 8]
)->get_value()
));
continue;
@ -1109,7 +1114,7 @@ static std::uint32_t *runcode(
auto v = std::move(args.back());
args.pop_back();
cs.set_var_int_checked(
static_cast<integer_var *>(cs.p_state->identmap[op >> 8]),
static_cast<integer_var *>(ts.istate->identmap[op >> 8]),
v.get_int()
);
continue;
@ -1118,7 +1123,7 @@ static std::uint32_t *runcode(
auto v1 = std::move(args.back()); args.pop_back();
auto v2 = std::move(args.back()); args.pop_back();
cs.set_var_int_checked(
static_cast<integer_var *>(cs.p_state->identmap[op >> 8]),
static_cast<integer_var *>(ts.istate->identmap[op >> 8]),
(v2.get_int() << 16) | (v1.get_int() << 8)
);
continue;
@ -1128,7 +1133,7 @@ static std::uint32_t *runcode(
auto v2 = std::move(args.back()); args.pop_back();
auto v3 = std::move(args.back()); args.pop_back();
cs.set_var_int_checked(
static_cast<integer_var *>(cs.p_state->identmap[op >> 8]),
static_cast<integer_var *>(ts.istate->identmap[op >> 8]),
(v3.get_int() << 16) | (v2.get_int() << 8) | (v1.get_int())
);
continue;
@ -1137,26 +1142,26 @@ static std::uint32_t *runcode(
case BC_INST_FVAR | BC_RET_FLOAT:
case BC_INST_FVAR | BC_RET_NULL:
args.emplace_back(cs).set_float(static_cast<float_var *>(
cs.p_state->identmap[op >> 8]
ts.istate->identmap[op >> 8]
)->get_value());
continue;
case BC_INST_FVAR | BC_RET_STRING: {
auto &v = args.emplace_back(cs);
v.set_int(static_cast<float_var *>(
cs.p_state->identmap[op >> 8]
ts.istate->identmap[op >> 8]
)->get_value());
v.force_str();
continue;
}
case BC_INST_FVAR | BC_RET_INT:
args.emplace_back(cs).set_int(int(static_cast<float_var *>(
cs.p_state->identmap[op >> 8]
ts.istate->identmap[op >> 8]
)->get_value()));
continue;
case BC_INST_FVAR1: {
auto &v = args.back();
cs.set_var_float_checked(
static_cast<float_var *>(cs.p_state->identmap[op >> 8]),
static_cast<float_var *>(ts.istate->identmap[op >> 8]),
v.get_float()
);
args.pop_back();
@ -1168,7 +1173,7 @@ static std::uint32_t *runcode(
case BC_INST_COM | BC_RET_FLOAT:
case BC_INST_COM | BC_RET_INT: {
command_impl *id = static_cast<command_impl *>(
cs.p_state->identmap[op >> 8]
ts.istate->identmap[op >> 8]
);
std::size_t offset = args.size() - id->get_num_args();
result.force_none();
@ -1185,7 +1190,7 @@ static std::uint32_t *runcode(
case BC_INST_COM_V | BC_RET_FLOAT:
case BC_INST_COM_V | BC_RET_INT: {
command_impl *id = static_cast<command_impl *>(
cs.p_state->identmap[op >> 13]
ts.istate->identmap[op >> 13]
);
std::size_t callargs = (op >> 8) & 0x1F;
std::size_t offset = args.size() - callargs;
@ -1200,7 +1205,7 @@ static std::uint32_t *runcode(
case BC_INST_COM_C | BC_RET_FLOAT:
case BC_INST_COM_C | BC_RET_INT: {
command_impl *id = static_cast<command_impl *>(
cs.p_state->identmap[op >> 13]
ts.istate->identmap[op >> 13]
);
std::size_t callargs = (op >> 8) & 0x1F,
offset = args.size() - callargs;
@ -1251,13 +1256,13 @@ static std::uint32_t *runcode(
case BC_INST_ALIAS:
static_cast<alias_impl *>(
cs.p_state->identmap[op >> 8]
ts.istate->identmap[op >> 8]
)->set_alias(cs, args.back());
args.pop_back();
continue;
case BC_INST_ALIAS_ARG:
static_cast<alias_impl *>(
cs.p_state->identmap[op >> 8]
ts.istate->identmap[op >> 8]
)->set_arg(cs, args.back());
args.pop_back();
continue;
@ -1274,18 +1279,18 @@ static std::uint32_t *runcode(
case BC_INST_CALL | BC_RET_FLOAT:
case BC_INST_CALL | BC_RET_INT: {
result.force_none();
ident *id = cs.p_state->identmap[op >> 13];
ident *id = ts.istate->identmap[op >> 13];
std::size_t callargs = (op >> 8) & 0x1F;
std::size_t nnargs = args.size();
std::size_t offset = nnargs - callargs;
if (id->get_flags() & IDENT_FLAG_UNKNOWN) {
force_arg(result, op & BC_INST_RET_MASK);
throw error(
throw error{
cs, "unknown command: %s", id->get_name().data()
);
};
}
call_alias(
cs, static_cast<alias *>(id), &args[0], result, callargs,
ts, static_cast<alias *>(id), &args[0], result, callargs,
nnargs, offset, 0, op
);
args.resize(nnargs, any_value{cs});
@ -1296,7 +1301,7 @@ static std::uint32_t *runcode(
case BC_INST_CALL_ARG | BC_RET_FLOAT:
case BC_INST_CALL_ARG | BC_RET_INT: {
result.force_none();
ident *id = cs.p_state->identmap[op >> 13];
ident *id = ts.istate->identmap[op >> 13];
std::size_t callargs = (op >> 8) & 0x1F;
std::size_t nnargs = args.size();
std::size_t offset = nnargs - callargs;
@ -1306,7 +1311,7 @@ static std::uint32_t *runcode(
continue;
}
call_alias(
cs, static_cast<alias *>(id), &args[0], result, callargs,
ts, static_cast<alias *>(id), &args[0], result, callargs,
nnargs, offset, 0, op
);
args.resize(nnargs, any_value{cs});
@ -1338,9 +1343,9 @@ noid:
result.force_none();
force_arg(result, op & BC_INST_RET_MASK);
std::string_view ids{idn};
throw error(
throw error{
cs, "unknown command: %s", ids.data()
);
};
}
result.force_none();
switch (id->get_raw_type()) {
@ -1353,7 +1358,7 @@ noid:
/* fallthrough */
case ID_COMMAND:
callcommand(
cs, static_cast<command_impl *>(id),
ts, static_cast<command_impl *>(id),
&args[offset], result, callargs
);
force_arg(result, op & BC_INST_RET_MASK);
@ -1367,7 +1372,7 @@ noid:
);
}
call_with_cleanup([&]() {
code = runcode(cs, code, result);