hide internal_state from public state struct
parent
14cd90116d
commit
d80af7b159
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
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};
|
||||
|
||||
p_tstate = p_state->create<thread_state>(p_state);
|
||||
try {
|
||||
p_tstate = statep->create<thread_state>(statep);
|
||||
} catch (...) {
|
||||
statep->destroy(statep);
|
||||
throw;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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)));
|
||||
|
|
|
@ -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 */
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
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);
|
||||
code = runcode(ts, code, result);
|
||||
}, [&]() {
|
||||
for (size_t j = 0; j < size_t(callargs); ++j) {
|
||||
pop_alias(args[offset + j].get_ident());
|
||||
|
@ -1425,7 +1430,7 @@ noid:
|
|||
goto noid;
|
||||
}
|
||||
call_alias(
|
||||
cs, a, &args[0], result, callargs, nnargs,
|
||||
ts, a, &args[0], result, callargs, nnargs,
|
||||
offset, 1, op
|
||||
);
|
||||
args.resize(nnargs, any_value{cs});
|
||||
|
@ -1439,14 +1444,14 @@ noid:
|
|||
}
|
||||
|
||||
void state::run(bcode *code, any_value &ret) {
|
||||
runcode(*this, reinterpret_cast<std::uint32_t *>(code), ret);
|
||||
runcode(*p_tstate, reinterpret_cast<std::uint32_t *>(code), ret);
|
||||
}
|
||||
|
||||
static void do_run(
|
||||
state &cs, std::string_view file, std::string_view code,
|
||||
any_value &ret
|
||||
) {
|
||||
codegen_state gs(cs);
|
||||
codegen_state gs{cs};
|
||||
gs.src_name = file;
|
||||
gs.code.reserve(64);
|
||||
gs.gen_main(code, VAL_ANY);
|
||||
|
@ -1455,7 +1460,7 @@ static void do_run(
|
|||
std::memcpy(cbuf, gs.code.data(), gs.code.size() * sizeof(std::uint32_t));
|
||||
bcode_incr(cbuf);
|
||||
call_with_cleanup([&cs, cbuf, &ret]() {
|
||||
runcode(cs, cbuf + 1, ret);
|
||||
runcode(*cs.p_tstate, cbuf + 1, ret);
|
||||
}, [cbuf]() {
|
||||
bcode_decr(cbuf);
|
||||
});
|
||||
|
@ -1492,9 +1497,11 @@ void state::run(ident *id, std::span<any_value> args, any_value &ret) {
|
|||
for (std::size_t i = 0; i < nargs; ++i) {
|
||||
targs[osz + i] = args[i];
|
||||
}
|
||||
callcommand(*this, cimpl, &targs[osz], ret, nargs, false);
|
||||
callcommand(
|
||||
*p_tstate, cimpl, &targs[osz], ret, nargs, false
|
||||
);
|
||||
} else {
|
||||
callcommand(*this, cimpl, &args[0], ret, nargs, false);
|
||||
callcommand(*p_tstate, cimpl, &args[0], ret, nargs, false);
|
||||
}
|
||||
nargs = 0;
|
||||
break;
|
||||
|
@ -1535,7 +1542,7 @@ void state::run(ident *id, std::span<any_value> args, any_value &ret) {
|
|||
break;
|
||||
}
|
||||
call_alias(
|
||||
*this, a, &args[0], ret, nargs, nargs, 0, 0, BC_RET_NULL
|
||||
*p_tstate, a, &args[0], ret, nargs, nargs, 0, 0, BC_RET_NULL
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
|
22
src/cs_vm.hh
22
src/cs_vm.hh
|
@ -17,36 +17,36 @@ struct continue_exception {
|
|||
};
|
||||
|
||||
template<typename F>
|
||||
static void call_with_args(state &cs, F body) {
|
||||
if (!cs.p_tstate->callstack) {
|
||||
static void call_with_args(thread_state &ts, F body) {
|
||||
if (!ts.callstack) {
|
||||
body();
|
||||
return;
|
||||
}
|
||||
valarray<ident_stack, MAX_ARGUMENTS> argstack{cs};
|
||||
int argmask1 = cs.p_tstate->callstack->usedargs;
|
||||
valarray<ident_stack, MAX_ARGUMENTS> argstack{*ts.pstate};
|
||||
int argmask1 = ts.callstack->usedargs;
|
||||
for (int i = 0; argmask1; argmask1 >>= 1, ++i) {
|
||||
if (argmask1 & 1) {
|
||||
static_cast<alias_impl *>(cs.p_state->identmap[i])->undo_arg(
|
||||
static_cast<alias_impl *>(ts.istate->identmap[i])->undo_arg(
|
||||
argstack[i]
|
||||
);
|
||||
}
|
||||
}
|
||||
ident_link *prevstack = cs.p_tstate->callstack->next;
|
||||
ident_link *prevstack = ts.callstack->next;
|
||||
ident_link aliaslink = {
|
||||
cs.p_tstate->callstack->id, cs.p_tstate->callstack,
|
||||
ts.callstack->id, ts.callstack,
|
||||
prevstack ? prevstack->usedargs : ((1 << MAX_ARGUMENTS) - 1),
|
||||
prevstack ? prevstack->argstack : nullptr
|
||||
};
|
||||
cs.p_tstate->callstack = &aliaslink;
|
||||
ts.callstack = &aliaslink;
|
||||
call_with_cleanup(std::move(body), [&]() {
|
||||
if (prevstack) {
|
||||
prevstack->usedargs = aliaslink.usedargs;
|
||||
}
|
||||
cs.p_tstate->callstack = aliaslink.next;
|
||||
int argmask2 = cs.p_tstate->callstack->usedargs;
|
||||
ts.callstack = aliaslink.next;
|
||||
int argmask2 = ts.callstack->usedargs;
|
||||
for (int i = 0; argmask2; argmask2 >>= 1, ++i) {
|
||||
if (argmask2 & 1) {
|
||||
static_cast<alias_impl *>(cs.p_state->identmap[i])->redo_arg(
|
||||
static_cast<alias_impl *>(ts.istate->identmap[i])->redo_arg(
|
||||
argstack[i]
|
||||
);
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <cubescript/cubescript.hh>
|
||||
#include "cs_std.hh"
|
||||
#include "cs_parser.hh"
|
||||
#include "cs_thread.hh"
|
||||
|
||||
namespace cubescript {
|
||||
|
||||
|
@ -550,7 +551,7 @@ static void list_sort(
|
|||
|
||||
alias *xa = static_cast<alias *>(x), *ya = static_cast<alias *>(y);
|
||||
|
||||
valbuf<ListSortItem> items{cs};
|
||||
valbuf<ListSortItem> items{cs.p_tstate->istate};
|
||||
size_t total = 0;
|
||||
|
||||
for (list_parser p{cs, list}; p.parse();) {
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include "cs_std.hh"
|
||||
#include "cs_strman.hh"
|
||||
#include "cs_thread.hh"
|
||||
|
||||
namespace cubescript {
|
||||
|
||||
|
@ -59,7 +60,7 @@ void init_lib_string(state &cs) {
|
|||
|
||||
cs.new_command("strlower", "s", [](auto &ccs, auto args, auto &res) {
|
||||
auto inps = std::string_view{args[0].get_str()};
|
||||
auto *ics = state_get_internal(ccs);
|
||||
auto *ics = ccs.p_tstate->istate;
|
||||
auto *buf = ics->strman->alloc_buf(inps.size());
|
||||
for (std::size_t i = 0; i < inps.size(); ++i) {
|
||||
buf[i] = tolower(inps[i]);
|
||||
|
@ -69,7 +70,7 @@ void init_lib_string(state &cs) {
|
|||
|
||||
cs.new_command("strupper", "s", [](auto &ccs, auto args, auto &res) {
|
||||
auto inps = std::string_view{args[0].get_str()};
|
||||
auto *ics = state_get_internal(ccs);
|
||||
auto *ics = ccs.p_tstate->istate;
|
||||
auto *buf = ics->strman->alloc_buf(inps.size());
|
||||
for (std::size_t i = 0; i < inps.size(); ++i) {
|
||||
buf[i] = toupper(inps[i]);
|
||||
|
|
|
@ -10,6 +10,7 @@ libcubescript_src = [
|
|||
'cs_ident.cc',
|
||||
'cs_parser.cc',
|
||||
'cs_state.cc',
|
||||
'cs_std.cc',
|
||||
'cs_strman.cc',
|
||||
'cs_thread.cc',
|
||||
'cs_val.cc',
|
||||
|
|
Loading…
Reference in New Issue