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 string_ref;
|
||||||
friend struct any_value;
|
friend struct any_value;
|
||||||
friend struct codegen_state;
|
friend struct codegen_state;
|
||||||
friend inline internal_state *state_get_internal(state &);
|
|
||||||
|
|
||||||
internal_state *p_state;
|
thread_state *p_tstate = nullptr;
|
||||||
thread_state *p_tstate;
|
|
||||||
|
|
||||||
int identflags = 0;
|
int identflags = 0;
|
||||||
|
|
||||||
|
@ -560,7 +558,6 @@ struct LIBCUBESCRIPT_EXPORT state {
|
||||||
void destroy();
|
void destroy();
|
||||||
|
|
||||||
void swap(state &s) {
|
void swap(state &s) {
|
||||||
std::swap(p_state, s.p_state);
|
|
||||||
std::swap(p_tstate, s.p_tstate);
|
std::swap(p_tstate, s.p_tstate);
|
||||||
std::swap(identflags, s.identflags);
|
std::swap(identflags, s.identflags);
|
||||||
std::swap(p_owner, s.p_owner);
|
std::swap(p_owner, s.p_owner);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "cs_bcode.hh"
|
#include "cs_bcode.hh"
|
||||||
#include "cs_state.hh"
|
#include "cs_state.hh"
|
||||||
|
#include "cs_thread.hh"
|
||||||
|
|
||||||
namespace cubescript {
|
namespace cubescript {
|
||||||
|
|
||||||
|
@ -44,11 +45,11 @@ struct bcode_hdr {
|
||||||
|
|
||||||
/* returned address is the 'init' member of the header */
|
/* returned address is the 'init' member of the header */
|
||||||
std::uint32_t *bcode_alloc(state &cs, std::size_t sz) {
|
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);
|
std::size_t hdrs = sizeof(bcode_hdr) / sizeof(std::uint32_t);
|
||||||
auto p = a.allocate(sz + hdrs - 1);
|
auto p = a.allocate(sz + hdrs - 1);
|
||||||
bcode_hdr *hdr = reinterpret_cast<bcode_hdr *>(p);
|
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;
|
hdr->asize = sz + hdrs - 1;
|
||||||
return p + 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) {
|
LIBCUBESCRIPT_EXPORT stack_state error::save_stack(state &cs) {
|
||||||
|
auto &ts = *cs.p_tstate;
|
||||||
integer_var *dalias = static_cast<integer_var *>(
|
integer_var *dalias = static_cast<integer_var *>(
|
||||||
cs.p_state->identmap[ID_IDX_DBGALIAS]
|
ts.istate->identmap[ID_IDX_DBGALIAS]
|
||||||
);
|
);
|
||||||
if (!dalias->get_value()) {
|
if (!dalias->get_value()) {
|
||||||
return stack_state(cs, nullptr, !!cs.p_tstate->callstack);
|
return stack_state(cs, nullptr, !!cs.p_tstate->callstack);
|
||||||
|
@ -58,7 +59,7 @@ LIBCUBESCRIPT_EXPORT stack_state error::save_stack(state &cs) {
|
||||||
if (!total) {
|
if (!total) {
|
||||||
return stack_state(cs, nullptr, false);
|
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())
|
std::min(total, dalias->get_value())
|
||||||
);
|
);
|
||||||
stack_state_node *ret = st, *nd = st;
|
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 codegen_state::get_str_dup() {
|
||||||
charbuf buf{cs};
|
charbuf buf{cs.p_tstate->istate};
|
||||||
unescape_string(std::back_inserter(buf), get_str());
|
unescape_string(std::back_inserter(buf), get_str());
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
@ -199,7 +199,7 @@ static inline void compileunescapestr(codegen_state &gs) {
|
||||||
gs.code.size() + str.size() / sizeof(uint32_t) + 1
|
gs.code.size() + str.size() / sizeof(uint32_t) + 1
|
||||||
);
|
);
|
||||||
size_t bufs = (gs.code.capacity() - gs.code.size()) * sizeof(uint32_t);
|
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);
|
auto *buf = alloc.allocate(bufs + 1);
|
||||||
char *wbuf = unescape_string(&buf[0], str);
|
char *wbuf = unescape_string(&buf[0], str);
|
||||||
memset(
|
memset(
|
||||||
|
@ -218,7 +218,7 @@ static bool compilearg(
|
||||||
);
|
);
|
||||||
|
|
||||||
static void compilelookup(codegen_state &gs, int ltype, int prevargs = MAX_RESULTS) {
|
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();
|
gs.next_char();
|
||||||
switch (gs.current()) {
|
switch (gs.current()) {
|
||||||
case '(':
|
case '(':
|
||||||
|
@ -466,7 +466,7 @@ static bool compileblockstr(codegen_state &gs, char const *str, char const *send
|
||||||
int startc = gs.code.size();
|
int startc = gs.code.size();
|
||||||
gs.code.push_back(BC_INST_VAL | BC_RET_STRING);
|
gs.code.push_back(BC_INST_VAL | BC_RET_STRING);
|
||||||
gs.code.reserve(gs.code.size() + (send - str) / sizeof(uint32_t) + 1);
|
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);
|
auto asz = ((send - str) / sizeof(uint32_t) + 1) * sizeof(uint32_t);
|
||||||
char *buf = alloc.allocate(asz);
|
char *buf = alloc.allocate(asz);
|
||||||
int len = 0;
|
int len = 0;
|
||||||
|
@ -519,7 +519,7 @@ done:
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool compileblocksub(codegen_state &gs, int prevargs) {
|
static bool compileblocksub(codegen_state &gs, int prevargs) {
|
||||||
charbuf lookup{gs.cs};
|
charbuf lookup{gs.cs.p_tstate->istate};
|
||||||
switch (gs.current()) {
|
switch (gs.current()) {
|
||||||
case '(':
|
case '(':
|
||||||
if (!compilearg(gs, VAL_ANY, prevargs)) {
|
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) {
|
static void compilestatements(codegen_state &gs, int rettype, int brak, int prevargs) {
|
||||||
charbuf idname{gs.cs};
|
charbuf idname{gs.cs.p_tstate->istate};
|
||||||
for (;;) {
|
for (;;) {
|
||||||
gs.skip_comments();
|
gs.skip_comments();
|
||||||
idname.clear();
|
idname.clear();
|
||||||
|
|
|
@ -33,7 +33,7 @@ struct codegen_state {
|
||||||
|
|
||||||
codegen_state() = delete;
|
codegen_state() = delete;
|
||||||
codegen_state(state &csr):
|
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{}
|
source{}, send{}, current_line{1}, src_name{}
|
||||||
{
|
{
|
||||||
csr.p_tstate->cstate = this;
|
csr.p_tstate->cstate = this;
|
||||||
|
@ -122,7 +122,7 @@ struct codegen_state {
|
||||||
}
|
}
|
||||||
|
|
||||||
void gen_ident() {
|
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) {
|
void gen_ident(std::string_view word) {
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
|
|
||||||
#include "cs_std.hh"
|
#include "cs_std.hh"
|
||||||
|
#include "cs_thread.hh"
|
||||||
|
|
||||||
namespace cubescript {
|
namespace cubescript {
|
||||||
|
|
||||||
|
@ -398,7 +399,7 @@ LIBCUBESCRIPT_EXPORT std::size_t list_parser::count() {
|
||||||
|
|
||||||
LIBCUBESCRIPT_EXPORT string_ref list_parser::get_item() const {
|
LIBCUBESCRIPT_EXPORT string_ref list_parser::get_item() const {
|
||||||
if (!p_quoted_item.empty() && (p_quoted_item.front() == '"')) {
|
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);
|
unescape_string(std::back_inserter(buf), p_item);
|
||||||
return string_ref{*p_state, buf.str()};
|
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(): state{default_alloc, nullptr} {}
|
||||||
|
|
||||||
state::state(alloc_func func, void *data):
|
state::state(alloc_func func, void *data) {
|
||||||
p_state{nullptr}
|
|
||||||
{
|
|
||||||
command *p;
|
command *p;
|
||||||
|
|
||||||
if (!func) {
|
if (!func) {
|
||||||
func = default_alloc;
|
func = default_alloc;
|
||||||
}
|
}
|
||||||
/* allocator is not set up yet, use func directly */
|
/* 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))
|
func(data, nullptr, 0, sizeof(internal_state))
|
||||||
);
|
);
|
||||||
/* allocator will be set up in the constructor */
|
/* allocator will be set up in the constructor */
|
||||||
new (p_state) internal_state{func, data};
|
new (statep) internal_state{func, data};
|
||||||
p_owner = true;
|
|
||||||
|
|
||||||
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) {
|
for (int i = 0; i < MAX_ARGUMENTS; ++i) {
|
||||||
char buf[32];
|
char buf[32];
|
||||||
|
@ -94,7 +100,7 @@ state::state(alloc_func func, void *data):
|
||||||
static_cast<command_impl *>(p)->p_type = ID_DO;
|
static_cast<command_impl *>(p)->p_type = ID_DO;
|
||||||
|
|
||||||
p = new_command("doargs", "e", [](auto &cs, auto args, auto &res) {
|
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);
|
cs.run(args[0].get_code(), res);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -182,30 +188,32 @@ LIBCUBESCRIPT_EXPORT state::~state() {
|
||||||
}
|
}
|
||||||
|
|
||||||
LIBCUBESCRIPT_EXPORT void state::destroy() {
|
LIBCUBESCRIPT_EXPORT void state::destroy() {
|
||||||
if (!p_state || !p_owner) {
|
if (!p_tstate || !p_owner) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (auto &p: p_state->idents) {
|
auto *sp = p_tstate->istate;
|
||||||
|
for (auto &p: sp->idents) {
|
||||||
ident *i = p.second;
|
ident *i = p.second;
|
||||||
alias *a = i->get_alias();
|
alias *a = i->get_alias();
|
||||||
if (a) {
|
if (a) {
|
||||||
a->get_value().force_none();
|
a->get_value().force_none();
|
||||||
static_cast<alias_impl *>(a)->clean_code();
|
static_cast<alias_impl *>(a)->clean_code();
|
||||||
}
|
}
|
||||||
p_state->destroy(i->p_impl);
|
sp->destroy(i->p_impl);
|
||||||
}
|
}
|
||||||
p_state->destroy(p_tstate);
|
sp->destroy(p_tstate);
|
||||||
p_state->destroy(p_state);
|
sp->destroy(sp);
|
||||||
}
|
}
|
||||||
|
|
||||||
state::state(internal_state *s):
|
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() {
|
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) {
|
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(
|
LIBCUBESCRIPT_EXPORT var_print_func state::set_var_printer(
|
||||||
var_print_func func
|
var_print_func func
|
||||||
) {
|
) {
|
||||||
auto fn = std::move(p_state->varprintf);
|
auto fn = std::move(p_tstate->istate->varprintf);
|
||||||
p_state->varprintf = std::move(func);
|
p_tstate->istate->varprintf = std::move(func);
|
||||||
return fn;
|
return fn;
|
||||||
}
|
}
|
||||||
|
|
||||||
LIBCUBESCRIPT_EXPORT var_print_func const &state::get_var_printer() const {
|
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 {
|
LIBCUBESCRIPT_EXPORT void state::print_var(global_var const &v) const {
|
||||||
if (p_state->varprintf) {
|
if (p_tstate->istate->varprintf) {
|
||||||
p_state->varprintf(*this, v);
|
p_tstate->istate->varprintf(*this, v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LIBCUBESCRIPT_EXPORT void *state::alloc(void *ptr, size_t os, size_t ns) {
|
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(
|
LIBCUBESCRIPT_EXPORT ident *state::add_ident(
|
||||||
|
@ -249,10 +257,10 @@ LIBCUBESCRIPT_EXPORT ident *state::add_ident(
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
id->p_impl = impl;
|
id->p_impl = impl;
|
||||||
p_state->idents[id->get_name()] = id;
|
p_tstate->istate->idents[id->get_name()] = id;
|
||||||
static_cast<ident_impl *>(impl)->p_index = p_state->identmap.size();
|
static_cast<ident_impl *>(impl)->p_index = p_tstate->istate->identmap.size();
|
||||||
p_state->identmap.push_back(id);
|
p_tstate->istate->identmap.push_back(id);
|
||||||
return p_state->identmap.back();
|
return p_tstate->istate->identmap.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
LIBCUBESCRIPT_EXPORT ident *state::new_ident(
|
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()
|
*this, "number %s is not a valid identifier name", name.data()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
auto *inst = p_state->create<alias_impl>(
|
auto *inst = p_tstate->istate->create<alias_impl>(
|
||||||
*this, string_ref{p_state, name}, flags
|
*this, string_ref{p_tstate->istate, name}, flags
|
||||||
);
|
);
|
||||||
id = add_ident(inst, inst);
|
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) {
|
LIBCUBESCRIPT_EXPORT ident *state::get_ident(std::string_view name) {
|
||||||
auto id = p_state->idents.find(name);
|
auto id = p_tstate->istate->idents.find(name);
|
||||||
if (id != p_state->idents.end()) {
|
if (id != p_tstate->istate->idents.end()) {
|
||||||
return id->second;
|
return id->second;
|
||||||
}
|
}
|
||||||
return nullptr;
|
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) {
|
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() {
|
LIBCUBESCRIPT_EXPORT std::span<ident *> state::get_idents() {
|
||||||
return std::span<ident *>{
|
return std::span<ident *>{
|
||||||
p_state->identmap.data(),
|
p_tstate->istate->identmap.data(),
|
||||||
p_state->identmap.size()
|
p_tstate->istate->identmap.size()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
LIBCUBESCRIPT_EXPORT std::span<ident const *> state::get_idents() const {
|
LIBCUBESCRIPT_EXPORT std::span<ident const *> state::get_idents() const {
|
||||||
auto ptr = const_cast<ident const **>(p_state->identmap.data());
|
auto ptr = const_cast<ident const **>(p_tstate->istate->identmap.data());
|
||||||
return std::span<ident const *>{ptr, p_state->identmap.size()};
|
return std::span<ident const *>{ptr, p_tstate->istate->identmap.size()};
|
||||||
}
|
}
|
||||||
|
|
||||||
LIBCUBESCRIPT_EXPORT integer_var *state::new_ivar(
|
LIBCUBESCRIPT_EXPORT integer_var *state::new_ivar(
|
||||||
std::string_view n, integer_type m, integer_type x, integer_type v,
|
std::string_view n, integer_type m, integer_type x, integer_type v,
|
||||||
var_cb_func f, int flags
|
var_cb_func f, int flags
|
||||||
) {
|
) {
|
||||||
auto *iv = p_state->create<ivar_impl>(
|
auto *iv = p_tstate->istate->create<ivar_impl>(
|
||||||
string_ref{p_state, n}, m, x, v, std::move(f), flags
|
string_ref{p_tstate->istate, n}, m, x, v, std::move(f), flags
|
||||||
);
|
);
|
||||||
add_ident(iv, iv);
|
add_ident(iv, iv);
|
||||||
return 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,
|
std::string_view n, float_type m, float_type x, float_type v,
|
||||||
var_cb_func f, int flags
|
var_cb_func f, int flags
|
||||||
) {
|
) {
|
||||||
auto *fv = p_state->create<fvar_impl>(
|
auto *fv = p_tstate->istate->create<fvar_impl>(
|
||||||
string_ref{p_state, n}, m, x, v, std::move(f), flags
|
string_ref{p_tstate->istate, n}, m, x, v, std::move(f), flags
|
||||||
);
|
);
|
||||||
add_ident(fv, fv);
|
add_ident(fv, fv);
|
||||||
return fv;
|
return fv;
|
||||||
|
@ -330,9 +338,9 @@ LIBCUBESCRIPT_EXPORT float_var *state::new_fvar(
|
||||||
LIBCUBESCRIPT_EXPORT string_var *state::new_svar(
|
LIBCUBESCRIPT_EXPORT string_var *state::new_svar(
|
||||||
std::string_view n, std::string_view v, var_cb_func f, int flags
|
std::string_view n, std::string_view v, var_cb_func f, int flags
|
||||||
) {
|
) {
|
||||||
auto *sv = p_state->create<svar_impl>(
|
auto *sv = p_tstate->istate->create<svar_impl>(
|
||||||
string_ref{p_state, n}, string_ref{p_state, v},
|
string_ref{p_tstate->istate, n}, string_ref{p_tstate->istate, v},
|
||||||
string_ref{p_state, ""}, std::move(f), flags
|
string_ref{p_tstate->istate, ""}, std::move(f), flags
|
||||||
);
|
);
|
||||||
add_ident(sv, sv);
|
add_ident(sv, sv);
|
||||||
return sv;
|
return sv;
|
||||||
|
@ -389,8 +397,8 @@ LIBCUBESCRIPT_EXPORT void state::set_alias(
|
||||||
} else if (!is_valid_name(name)) {
|
} else if (!is_valid_name(name)) {
|
||||||
throw error{*this, "cannot alias invalid name '%s'", name.data()};
|
throw error{*this, "cannot alias invalid name '%s'", name.data()};
|
||||||
} else {
|
} else {
|
||||||
auto *a = p_state->create<alias_impl>(
|
auto *a = p_tstate->istate->create<alias_impl>(
|
||||||
*this, string_ref{p_state, name}, std::move(v), identflags
|
*this, string_ref{p_tstate->istate, name}, std::move(v), identflags
|
||||||
);
|
);
|
||||||
add_ident(a, a);
|
add_ident(a, a);
|
||||||
}
|
}
|
||||||
|
@ -445,9 +453,10 @@ LIBCUBESCRIPT_EXPORT command *state::new_command(
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto *cmd = p_state->create<command_impl>(
|
auto *cmd = p_tstate->istate->create<command_impl>(
|
||||||
string_ref{p_state, name}, string_ref{p_state, args}, nargs,
|
string_ref{p_tstate->istate, name},
|
||||||
std::move(func)
|
string_ref{p_tstate->istate, args},
|
||||||
|
nargs, std::move(func)
|
||||||
);
|
);
|
||||||
add_ident(cmd, cmd);
|
add_ident(cmd, cmd);
|
||||||
return cmd;
|
return cmd;
|
||||||
|
@ -489,7 +498,7 @@ LIBCUBESCRIPT_EXPORT void state::clear_override(ident &id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
LIBCUBESCRIPT_EXPORT void state::clear_overrides() {
|
LIBCUBESCRIPT_EXPORT void state::clear_overrides() {
|
||||||
for (auto &p: p_state->idents) {
|
for (auto &p: p_tstate->istate->idents) {
|
||||||
clear_override(*(p.second));
|
clear_override(*(p.second));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -570,7 +579,7 @@ LIBCUBESCRIPT_EXPORT void state::set_var_str(
|
||||||
*this, sv, sv->p_flags,
|
*this, sv, sv->p_flags,
|
||||||
[&sv]() { sv->p_overrideval = sv->get_value(); }
|
[&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) {
|
if (dofunc) {
|
||||||
sv->changed(*this);
|
sv->changed(*this);
|
||||||
}
|
}
|
||||||
|
@ -600,7 +609,9 @@ state::get_var_str(std::string_view name) {
|
||||||
if (!id || id->is_svar()) {
|
if (!id || id->is_svar()) {
|
||||||
return std::nullopt;
|
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>
|
LIBCUBESCRIPT_EXPORT std::optional<integer_type>
|
||||||
|
@ -756,7 +767,7 @@ LIBCUBESCRIPT_EXPORT void state::set_var_str_checked(
|
||||||
*this, sv, svp->p_flags,
|
*this, sv, svp->p_flags,
|
||||||
[&svp]() { svp->p_overrideval = svp->p_storage; }
|
[&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);
|
svp->changed(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
|
|
||||||
namespace cubescript {
|
namespace cubescript {
|
||||||
|
|
||||||
struct state;
|
|
||||||
struct internal_state;
|
struct internal_state;
|
||||||
struct string_pool;
|
struct string_pool;
|
||||||
|
|
||||||
|
@ -19,7 +18,6 @@ struct std_allocator {
|
||||||
using value_type = T;
|
using value_type = T;
|
||||||
|
|
||||||
inline std_allocator(internal_state *s);
|
inline std_allocator(internal_state *s);
|
||||||
inline std_allocator(state &cs);
|
|
||||||
|
|
||||||
template<typename U>
|
template<typename U>
|
||||||
std_allocator(std_allocator<U> const &a): istate{a.istate} {};
|
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>
|
template<typename T>
|
||||||
inline std_allocator<T>::std_allocator(internal_state *s): istate{s} {}
|
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>
|
template<typename T>
|
||||||
inline T *std_allocator<T>::allocate(std::size_t n) {
|
inline T *std_allocator<T>::allocate(std::size_t n) {
|
||||||
return static_cast<T *>(istate->alloc(nullptr, 0, n * sizeof(T)));
|
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 {
|
namespace cubescript {
|
||||||
|
|
||||||
|
struct state;
|
||||||
|
|
||||||
/* run func, call the second one after finishing */
|
/* run func, call the second one after finishing */
|
||||||
|
|
||||||
template<typename F1, typename F2>
|
template<typename F1, typename F2>
|
||||||
|
@ -59,7 +61,6 @@ struct valbuf {
|
||||||
valbuf() = delete;
|
valbuf() = delete;
|
||||||
|
|
||||||
valbuf(internal_state *cs): buf{std_allocator<T>{cs}} {}
|
valbuf(internal_state *cs): buf{std_allocator<T>{cs}} {}
|
||||||
valbuf(state &cs): buf{std_allocator<T>{cs}} {}
|
|
||||||
|
|
||||||
using size_type = std::size_t;
|
using size_type = std::size_t;
|
||||||
using value_type = T;
|
using value_type = T;
|
||||||
|
@ -108,7 +109,7 @@ struct valbuf {
|
||||||
|
|
||||||
struct charbuf: valbuf<char> {
|
struct charbuf: valbuf<char> {
|
||||||
charbuf(internal_state *cs): valbuf<char>{cs} {}
|
charbuf(internal_state *cs): valbuf<char>{cs} {}
|
||||||
charbuf(state &cs): valbuf<char>{cs} {}
|
charbuf(state &cs);
|
||||||
|
|
||||||
void append(char const *beg, char const *end) {
|
void append(char const *beg, char const *end) {
|
||||||
valbuf<char>::append(beg, end);
|
valbuf<char>::append(beg, end);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include <cubescript/cubescript.hh>
|
#include <cubescript/cubescript.hh>
|
||||||
|
|
||||||
#include "cs_strman.hh"
|
#include "cs_strman.hh"
|
||||||
|
#include "cs_thread.hh"
|
||||||
|
|
||||||
namespace cubescript {
|
namespace cubescript {
|
||||||
|
|
||||||
|
@ -120,7 +121,7 @@ LIBCUBESCRIPT_EXPORT string_ref::string_ref(
|
||||||
}
|
}
|
||||||
|
|
||||||
LIBCUBESCRIPT_EXPORT string_ref::string_ref(state &cs, std::string_view str):
|
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);
|
p_str = p_state->strman->add(str);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,10 @@ struct codegen_state;
|
||||||
struct thread_state {
|
struct thread_state {
|
||||||
/* thread call stack */
|
/* thread call stack */
|
||||||
ident_link *callstack{};
|
ident_link *callstack{};
|
||||||
|
/* the shared state pointer */
|
||||||
|
internal_state *istate{};
|
||||||
|
/* the public state interface */
|
||||||
|
state *pstate{};
|
||||||
/* current codegen state for diagnostics */
|
/* current codegen state for diagnostics */
|
||||||
codegen_state *cstate{};
|
codegen_state *cstate{};
|
||||||
/* value stack for VM */
|
/* 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):
|
any_value::any_value(internal_state &st):
|
||||||
p_stor(), p_type(value_type::NONE)
|
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) {
|
for (stack_state_node const *nd = p_node; nd; nd = nd->next) {
|
||||||
++len;
|
++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) {
|
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(
|
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
|
std::size_t nargs, bool lookup = false
|
||||||
) {
|
) {
|
||||||
int i = -1, fakeargs = 0, numargs = int(nargs);
|
int i = -1, fakeargs = 0, numargs = int(nargs);
|
||||||
|
@ -168,7 +168,7 @@ static inline void callcommand(
|
||||||
if (str.empty()) {
|
if (str.empty()) {
|
||||||
args[i].set_int(0);
|
args[i].set_int(0);
|
||||||
} else {
|
} else {
|
||||||
args[i].force_code(cs);
|
args[i].force_code(*ts.pstate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -178,11 +178,11 @@ static inline void callcommand(
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
args[i].set_code(
|
args[i].set_code(
|
||||||
bcode_get_empty(state_get_internal(cs)->empty, VAL_NULL)
|
bcode_get_empty(ts.istate->empty, VAL_NULL)
|
||||||
);
|
);
|
||||||
fakeargs++;
|
fakeargs++;
|
||||||
} else {
|
} else {
|
||||||
args[i].force_code(cs);
|
args[i].force_code(*ts.pstate);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
|
@ -190,10 +190,10 @@ static inline void callcommand(
|
||||||
if (rep) {
|
if (rep) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
args[i].set_ident(cs.p_state->identmap[ID_IDX_DUMMY]);
|
args[i].set_ident(ts.istate->identmap[ID_IDX_DUMMY]);
|
||||||
fakeargs++;
|
fakeargs++;
|
||||||
} else {
|
} else {
|
||||||
args[i].force_ident(cs);
|
args[i].force_ident(*ts.pstate);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case '$':
|
case '$':
|
||||||
|
@ -206,19 +206,19 @@ static inline void callcommand(
|
||||||
break;
|
break;
|
||||||
case 'C': {
|
case 'C': {
|
||||||
i = std::max(i + 1, numargs);
|
i = std::max(i + 1, numargs);
|
||||||
any_value tv{cs};
|
any_value tv{*ts.pstate};
|
||||||
tv.set_str(concat_values(
|
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(
|
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;
|
return;
|
||||||
}
|
}
|
||||||
case 'V':
|
case 'V':
|
||||||
i = std::max(i + 1, numargs);
|
i = std::max(i + 1, numargs);
|
||||||
static_cast<command_impl *>(id)->call(
|
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;
|
return;
|
||||||
case '1':
|
case '1':
|
||||||
|
@ -234,54 +234,54 @@ static inline void callcommand(
|
||||||
}
|
}
|
||||||
++i;
|
++i;
|
||||||
static_cast<command_impl *>(id)->call(
|
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(
|
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(
|
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 callargs, std::size_t &nargs,
|
||||||
std::size_t offset, std::size_t skip, std::uint32_t op
|
std::size_t offset, std::size_t skip, std::uint32_t op
|
||||||
) {
|
) {
|
||||||
integer_var *anargs = static_cast<integer_var *>(
|
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++) {
|
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
|
args[offset + i], argstack[i], false
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
auto oldargs = anargs->get_value();
|
auto oldargs = anargs->get_value();
|
||||||
anargs->set_value(callargs);
|
anargs->set_value(callargs);
|
||||||
int oldflags = cs.identflags;
|
int oldflags = ts.pstate->identflags;
|
||||||
cs.identflags |= a->get_flags()&IDENT_FLAG_OVERRIDDEN;
|
ts.pstate->identflags |= a->get_flags()&IDENT_FLAG_OVERRIDDEN;
|
||||||
ident_link aliaslink = {
|
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<
|
std::uint32_t *codep = static_cast<
|
||||||
alias_impl *
|
alias_impl *
|
||||||
>(a)->compile_code(cs)->get_raw();
|
>(a)->compile_code(*ts.pstate)->get_raw();
|
||||||
bcode_incr(codep);
|
bcode_incr(codep);
|
||||||
call_with_cleanup([&]() {
|
call_with_cleanup([&]() {
|
||||||
runcode(cs, codep+1, result);
|
runcode(ts, codep+1, result);
|
||||||
}, [&]() {
|
}, [&]() {
|
||||||
bcode_decr(codep);
|
bcode_decr(codep);
|
||||||
cs.p_tstate->callstack = aliaslink.next;
|
ts.callstack = aliaslink.next;
|
||||||
cs.identflags = oldflags;
|
ts.pstate->identflags = oldflags;
|
||||||
for (std::size_t i = 0; i < callargs; i++) {
|
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);
|
int argmask = aliaslink.usedargs & int(~0U << callargs);
|
||||||
for (; argmask; ++callargs) {
|
for (; argmask; ++callargs) {
|
||||||
if (argmask & (1 << callargs)) {
|
if (argmask & (1 << callargs)) {
|
||||||
static_cast<alias_impl *>(
|
static_cast<alias_impl *>(
|
||||||
cs.p_state->identmap[callargs]
|
ts.istate->identmap[callargs]
|
||||||
)->pop_arg();
|
)->pop_arg();
|
||||||
argmask &= ~(1 << callargs);
|
argmask &= ~(1 << callargs);
|
||||||
}
|
}
|
||||||
|
@ -309,7 +309,7 @@ struct run_depth_guard {
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline alias *get_lookup_id(state &cs, std::uint32_t op) {
|
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) {
|
if (id->get_flags() & IDENT_FLAG_UNKNOWN) {
|
||||||
throw error(cs, "unknown alias lookup: %s", id->get_name().data());
|
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) {
|
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)) {
|
if (!ident_is_used_arg(id, cs)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -342,19 +342,22 @@ struct stack_guard {
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline int get_lookupu_type(
|
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) {
|
if (arg.get_type() != value_type::STRING) {
|
||||||
return -2; /* default case */
|
return -2; /* default case */
|
||||||
}
|
}
|
||||||
id = cs.get_ident(arg.get_str());
|
id = ts.pstate->get_ident(arg.get_str());
|
||||||
if (id) {
|
if (id) {
|
||||||
switch(id->get_type()) {
|
switch(id->get_type()) {
|
||||||
case ident_type::ALIAS:
|
case ident_type::ALIAS:
|
||||||
if (id->get_flags() & IDENT_FLAG_UNKNOWN) {
|
if (id->get_flags() & IDENT_FLAG_UNKNOWN) {
|
||||||
break;
|
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_UNKNOWN;
|
||||||
}
|
}
|
||||||
return ID_ALIAS;
|
return ID_ALIAS;
|
||||||
|
@ -365,14 +368,15 @@ static inline int get_lookupu_type(
|
||||||
case ident_type::FVAR:
|
case ident_type::FVAR:
|
||||||
return ID_FVAR;
|
return ID_FVAR;
|
||||||
case ident_type::COMMAND: {
|
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 *cimpl = static_cast<command_impl *>(id);
|
||||||
auto &args = cs.p_tstate->vmstack;
|
auto &args = ts.vmstack;
|
||||||
auto osz = args.size();
|
auto osz = args.size();
|
||||||
/* pad with as many empty values as we need */
|
/* 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();
|
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);
|
force_arg(arg, op & BC_INST_RET_MASK);
|
||||||
return -2; /* ignore */
|
return -2; /* ignore */
|
||||||
}
|
}
|
||||||
|
@ -380,16 +384,17 @@ static inline int get_lookupu_type(
|
||||||
return ID_UNKNOWN;
|
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(
|
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();
|
result.set_none();
|
||||||
|
auto &cs = *ts.pstate;
|
||||||
run_depth_guard level{cs}; /* incr and decr on scope exit */
|
run_depth_guard level{cs}; /* incr and decr on scope exit */
|
||||||
stack_guard guard{cs}; /* resize back to original */
|
stack_guard guard{cs}; /* resize back to original */
|
||||||
auto &args = cs.p_tstate->vmstack;
|
auto &args = ts.vmstack;
|
||||||
auto &chook = cs.get_call_hook();
|
auto &chook = cs.get_call_hook();
|
||||||
if (chook) {
|
if (chook) {
|
||||||
chook(cs);
|
chook(cs);
|
||||||
|
@ -454,10 +459,10 @@ static std::uint32_t *runcode(
|
||||||
args.pop_back();
|
args.pop_back();
|
||||||
continue;
|
continue;
|
||||||
case BC_INST_ENTER:
|
case BC_INST_ENTER:
|
||||||
code = runcode(cs, code, args.emplace_back(cs));
|
code = runcode(ts, code, args.emplace_back(cs));
|
||||||
continue;
|
continue;
|
||||||
case BC_INST_ENTER_RESULT:
|
case BC_INST_ENTER_RESULT:
|
||||||
code = runcode(cs, code, result);
|
code = runcode(ts, code, result);
|
||||||
continue;
|
continue;
|
||||||
case BC_INST_EXIT | BC_RET_STRING:
|
case BC_INST_EXIT | BC_RET_STRING:
|
||||||
case BC_INST_EXIT | BC_RET_INT:
|
case BC_INST_EXIT | BC_RET_INT:
|
||||||
|
@ -475,7 +480,7 @@ static std::uint32_t *runcode(
|
||||||
args.emplace_back(std::move(result));
|
args.emplace_back(std::move(result));
|
||||||
continue;
|
continue;
|
||||||
case BC_INST_PRINT:
|
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;
|
continue;
|
||||||
|
|
||||||
case BC_INST_LOCAL: {
|
case BC_INST_LOCAL: {
|
||||||
|
@ -486,7 +491,7 @@ static std::uint32_t *runcode(
|
||||||
push_alias(cs, args[offset + i].get_ident(), locals[i]);
|
push_alias(cs, args[offset + i].get_ident(), locals[i]);
|
||||||
}
|
}
|
||||||
call_with_cleanup([&]() {
|
call_with_cleanup([&]() {
|
||||||
code = runcode(cs, code, result);
|
code = runcode(ts, code, result);
|
||||||
}, [&]() {
|
}, [&]() {
|
||||||
for (std::size_t i = offset; i < args.size(); ++i) {
|
for (std::size_t i = offset; i < args.size(); ++i) {
|
||||||
pop_alias(args[i].get_ident());
|
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_STRING:
|
||||||
case BC_INST_DO_ARGS | BC_RET_INT:
|
case BC_INST_DO_ARGS | BC_RET_INT:
|
||||||
case BC_INST_DO_ARGS | BC_RET_FLOAT:
|
case BC_INST_DO_ARGS | BC_RET_FLOAT:
|
||||||
call_with_args(cs, [&]() {
|
call_with_args(ts, [&]() {
|
||||||
auto v = std::move(args.back());
|
auto v = std::move(args.back());
|
||||||
args.pop_back();
|
args.pop_back();
|
||||||
cs.run(v.get_code(), result);
|
cs.run(v.get_code(), result);
|
||||||
|
@ -571,14 +576,14 @@ static std::uint32_t *runcode(
|
||||||
if (cs.is_in_loop()) {
|
if (cs.is_in_loop()) {
|
||||||
throw break_exception();
|
throw break_exception();
|
||||||
} else {
|
} else {
|
||||||
throw error(cs, "no loop to break");
|
throw error{cs, "no loop to break"};
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case BC_INST_BREAK | BC_INST_FLAG_TRUE:
|
case BC_INST_BREAK | BC_INST_FLAG_TRUE:
|
||||||
if (cs.is_in_loop()) {
|
if (cs.is_in_loop()) {
|
||||||
throw continue_exception();
|
throw continue_exception();
|
||||||
} else {
|
} else {
|
||||||
throw error(cs, "no loop to continue");
|
throw error{cs, "no loop to continue"};
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -672,22 +677,22 @@ static std::uint32_t *runcode(
|
||||||
|
|
||||||
case BC_INST_EMPTY | BC_RET_NULL:
|
case BC_INST_EMPTY | BC_RET_NULL:
|
||||||
args.emplace_back(cs).set_code(
|
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;
|
break;
|
||||||
case BC_INST_EMPTY | BC_RET_STRING:
|
case BC_INST_EMPTY | BC_RET_STRING:
|
||||||
args.emplace_back(cs).set_code(
|
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;
|
break;
|
||||||
case BC_INST_EMPTY | BC_RET_INT:
|
case BC_INST_EMPTY | BC_RET_INT:
|
||||||
args.emplace_back(cs).set_code(
|
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;
|
break;
|
||||||
case BC_INST_EMPTY | BC_RET_FLOAT:
|
case BC_INST_EMPTY | BC_RET_FLOAT:
|
||||||
args.emplace_back(cs).set_code(
|
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;
|
break;
|
||||||
case BC_INST_BLOCK: {
|
case BC_INST_BLOCK: {
|
||||||
|
@ -700,7 +705,7 @@ static std::uint32_t *runcode(
|
||||||
}
|
}
|
||||||
case BC_INST_COMPILE: {
|
case BC_INST_COMPILE: {
|
||||||
any_value &arg = args.back();
|
any_value &arg = args.back();
|
||||||
codegen_state gs(cs);
|
codegen_state gs{cs};
|
||||||
switch (arg.get_type()) {
|
switch (arg.get_type()) {
|
||||||
case value_type::INT:
|
case value_type::INT:
|
||||||
gs.code.reserve(8);
|
gs.code.reserve(8);
|
||||||
|
@ -745,7 +750,7 @@ static std::uint32_t *runcode(
|
||||||
case value_type::STRING: {
|
case value_type::STRING: {
|
||||||
std::string_view s = arg.get_str();
|
std::string_view s = arg.get_str();
|
||||||
if (!s.empty()) {
|
if (!s.empty()) {
|
||||||
codegen_state gs(cs);
|
codegen_state gs{cs};
|
||||||
gs.code.reserve(64);
|
gs.code.reserve(64);
|
||||||
gs.gen_main(s);
|
gs.gen_main(s);
|
||||||
gs.done();
|
gs.done();
|
||||||
|
@ -769,36 +774,36 @@ static std::uint32_t *runcode(
|
||||||
}
|
}
|
||||||
|
|
||||||
case BC_INST_IDENT:
|
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;
|
continue;
|
||||||
case BC_INST_IDENT_ARG: {
|
case BC_INST_IDENT_ARG: {
|
||||||
alias *a = static_cast<alias *>(
|
alias *a = static_cast<alias *>(
|
||||||
cs.p_state->identmap[op >> 8]
|
ts.istate->identmap[op >> 8]
|
||||||
);
|
);
|
||||||
if (!ident_is_used_arg(a, cs)) {
|
if (!ident_is_used_arg(a, cs)) {
|
||||||
any_value nv{cs};
|
any_value nv{cs};
|
||||||
static_cast<alias_impl *>(a)->push_arg(
|
static_cast<alias_impl *>(a)->push_arg(
|
||||||
nv, cs.p_tstate->callstack->argstack[a->get_index()],
|
nv, ts.callstack->argstack[a->get_index()],
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
cs.p_tstate->callstack->usedargs |= 1 << a->get_index();
|
ts.callstack->usedargs |= 1 << a->get_index();
|
||||||
}
|
}
|
||||||
args.emplace_back(cs).set_ident(a);
|
args.emplace_back(cs).set_ident(a);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
case BC_INST_IDENT_U: {
|
case BC_INST_IDENT_U: {
|
||||||
any_value &arg = args.back();
|
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) {
|
if (arg.get_type() == value_type::STRING) {
|
||||||
id = cs.new_ident(arg.get_str());
|
id = cs.new_ident(arg.get_str());
|
||||||
}
|
}
|
||||||
if ((id->get_index() < MAX_ARGUMENTS) && !ident_is_used_arg(id, cs)) {
|
if ((id->get_index() < MAX_ARGUMENTS) && !ident_is_used_arg(id, cs)) {
|
||||||
any_value nv{cs};
|
any_value nv{cs};
|
||||||
static_cast<alias_impl *>(id)->push_arg(
|
static_cast<alias_impl *>(id)->push_arg(
|
||||||
nv, cs.p_tstate->callstack->argstack[id->get_index()],
|
nv, ts.callstack->argstack[id->get_index()],
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
cs.p_tstate->callstack->usedargs |= 1 << id->get_index();
|
ts.callstack->usedargs |= 1 << id->get_index();
|
||||||
}
|
}
|
||||||
arg.set_ident(id);
|
arg.set_ident(id);
|
||||||
continue;
|
continue;
|
||||||
|
@ -807,7 +812,7 @@ static std::uint32_t *runcode(
|
||||||
case BC_INST_LOOKUP_U | BC_RET_STRING: {
|
case BC_INST_LOOKUP_U | BC_RET_STRING: {
|
||||||
ident *id = nullptr;
|
ident *id = nullptr;
|
||||||
any_value &arg = args.back();
|
any_value &arg = args.back();
|
||||||
switch (get_lookupu_type(cs, arg, id, op)) {
|
switch (get_lookupu_type(ts, arg, id, op)) {
|
||||||
case ID_ALIAS:
|
case ID_ALIAS:
|
||||||
arg = static_cast<alias *>(id)->get_value();
|
arg = static_cast<alias *>(id)->get_value();
|
||||||
arg.force_str();
|
arg.force_str();
|
||||||
|
@ -850,7 +855,7 @@ static std::uint32_t *runcode(
|
||||||
case BC_INST_LOOKUP_U | BC_RET_INT: {
|
case BC_INST_LOOKUP_U | BC_RET_INT: {
|
||||||
ident *id = nullptr;
|
ident *id = nullptr;
|
||||||
any_value &arg = args.back();
|
any_value &arg = args.back();
|
||||||
switch (get_lookupu_type(cs, arg, id, op)) {
|
switch (get_lookupu_type(ts, arg, id, op)) {
|
||||||
case ID_ALIAS:
|
case ID_ALIAS:
|
||||||
arg.set_int(
|
arg.set_int(
|
||||||
static_cast<alias *>(id)->get_value().get_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: {
|
case BC_INST_LOOKUP_U | BC_RET_FLOAT: {
|
||||||
ident *id = nullptr;
|
ident *id = nullptr;
|
||||||
any_value &arg = args.back();
|
any_value &arg = args.back();
|
||||||
switch (get_lookupu_type(cs, arg, id, op)) {
|
switch (get_lookupu_type(ts, arg, id, op)) {
|
||||||
case ID_ALIAS:
|
case ID_ALIAS:
|
||||||
arg.set_float(
|
arg.set_float(
|
||||||
static_cast<alias *>(id)->get_value().get_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: {
|
case BC_INST_LOOKUP_U | BC_RET_NULL: {
|
||||||
ident *id = nullptr;
|
ident *id = nullptr;
|
||||||
any_value &arg = args.back();
|
any_value &arg = args.back();
|
||||||
switch (get_lookupu_type(cs, arg, id, op)) {
|
switch (get_lookupu_type(ts, arg, id, op)) {
|
||||||
case ID_ALIAS:
|
case ID_ALIAS:
|
||||||
static_cast<alias *>(id)->get_value().get_val(arg);
|
static_cast<alias *>(id)->get_value().get_val(arg);
|
||||||
continue;
|
continue;
|
||||||
|
@ -978,7 +983,7 @@ static std::uint32_t *runcode(
|
||||||
case BC_INST_LOOKUP_MU | BC_RET_STRING: {
|
case BC_INST_LOOKUP_MU | BC_RET_STRING: {
|
||||||
ident *id = nullptr;
|
ident *id = nullptr;
|
||||||
any_value &arg = args.back();
|
any_value &arg = args.back();
|
||||||
switch (get_lookupu_type(cs, arg, id, op)) {
|
switch (get_lookupu_type(ts, arg, id, op)) {
|
||||||
case ID_ALIAS:
|
case ID_ALIAS:
|
||||||
arg = static_cast<alias *>(id)->get_value();
|
arg = static_cast<alias *>(id)->get_value();
|
||||||
arg.force_str();
|
arg.force_str();
|
||||||
|
@ -1021,7 +1026,7 @@ static std::uint32_t *runcode(
|
||||||
case BC_INST_LOOKUP_MU | BC_RET_NULL: {
|
case BC_INST_LOOKUP_MU | BC_RET_NULL: {
|
||||||
ident *id = nullptr;
|
ident *id = nullptr;
|
||||||
any_value &arg = args.back();
|
any_value &arg = args.back();
|
||||||
switch (get_lookupu_type(cs, arg, id, op)) {
|
switch (get_lookupu_type(ts, arg, id, op)) {
|
||||||
case ID_ALIAS:
|
case ID_ALIAS:
|
||||||
static_cast<alias *>(id)->get_cval(arg);
|
static_cast<alias *>(id)->get_cval(arg);
|
||||||
continue;
|
continue;
|
||||||
|
@ -1057,20 +1062,20 @@ static std::uint32_t *runcode(
|
||||||
case BC_INST_SVAR | BC_RET_STRING:
|
case BC_INST_SVAR | BC_RET_STRING:
|
||||||
case BC_INST_SVAR | BC_RET_NULL:
|
case BC_INST_SVAR | BC_RET_NULL:
|
||||||
args.emplace_back(cs).set_str(static_cast<string_var *>(
|
args.emplace_back(cs).set_str(static_cast<string_var *>(
|
||||||
cs.p_state->identmap[op >> 8]
|
ts.istate->identmap[op >> 8]
|
||||||
)->get_value());
|
)->get_value());
|
||||||
continue;
|
continue;
|
||||||
case BC_INST_SVAR | BC_RET_INT:
|
case BC_INST_SVAR | BC_RET_INT:
|
||||||
args.emplace_back(cs).set_int(parse_int(
|
args.emplace_back(cs).set_int(parse_int(
|
||||||
static_cast<string_var *>(
|
static_cast<string_var *>(
|
||||||
cs.p_state->identmap[op >> 8]
|
ts.istate->identmap[op >> 8]
|
||||||
)->get_value()
|
)->get_value()
|
||||||
));
|
));
|
||||||
continue;
|
continue;
|
||||||
case BC_INST_SVAR | BC_RET_FLOAT:
|
case BC_INST_SVAR | BC_RET_FLOAT:
|
||||||
args.emplace_back(cs).set_float(parse_float(
|
args.emplace_back(cs).set_float(parse_float(
|
||||||
static_cast<string_var *>(
|
static_cast<string_var *>(
|
||||||
cs.p_state->identmap[op >> 8]
|
ts.istate->identmap[op >> 8]
|
||||||
)->get_value()
|
)->get_value()
|
||||||
));
|
));
|
||||||
continue;
|
continue;
|
||||||
|
@ -1078,7 +1083,7 @@ static std::uint32_t *runcode(
|
||||||
auto v = std::move(args.back());
|
auto v = std::move(args.back());
|
||||||
args.pop_back();
|
args.pop_back();
|
||||||
cs.set_var_str_checked(
|
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()
|
v.get_str()
|
||||||
);
|
);
|
||||||
continue;
|
continue;
|
||||||
|
@ -1087,13 +1092,13 @@ static std::uint32_t *runcode(
|
||||||
case BC_INST_IVAR | BC_RET_INT:
|
case BC_INST_IVAR | BC_RET_INT:
|
||||||
case BC_INST_IVAR | BC_RET_NULL:
|
case BC_INST_IVAR | BC_RET_NULL:
|
||||||
args.emplace_back(cs).set_int(static_cast<integer_var *>(
|
args.emplace_back(cs).set_int(static_cast<integer_var *>(
|
||||||
cs.p_state->identmap[op >> 8]
|
ts.istate->identmap[op >> 8]
|
||||||
)->get_value());
|
)->get_value());
|
||||||
continue;
|
continue;
|
||||||
case BC_INST_IVAR | BC_RET_STRING: {
|
case BC_INST_IVAR | BC_RET_STRING: {
|
||||||
auto &v = args.emplace_back(cs);
|
auto &v = args.emplace_back(cs);
|
||||||
v.set_int(static_cast<integer_var *>(
|
v.set_int(static_cast<integer_var *>(
|
||||||
cs.p_state->identmap[op >> 8]
|
ts.istate->identmap[op >> 8]
|
||||||
)->get_value());
|
)->get_value());
|
||||||
v.force_str();
|
v.force_str();
|
||||||
continue;
|
continue;
|
||||||
|
@ -1101,7 +1106,7 @@ static std::uint32_t *runcode(
|
||||||
case BC_INST_IVAR | BC_RET_FLOAT:
|
case BC_INST_IVAR | BC_RET_FLOAT:
|
||||||
args.emplace_back(cs).set_float(float_type(
|
args.emplace_back(cs).set_float(float_type(
|
||||||
static_cast<integer_var *>(
|
static_cast<integer_var *>(
|
||||||
cs.p_state->identmap[op >> 8]
|
ts.istate->identmap[op >> 8]
|
||||||
)->get_value()
|
)->get_value()
|
||||||
));
|
));
|
||||||
continue;
|
continue;
|
||||||
|
@ -1109,7 +1114,7 @@ static std::uint32_t *runcode(
|
||||||
auto v = std::move(args.back());
|
auto v = std::move(args.back());
|
||||||
args.pop_back();
|
args.pop_back();
|
||||||
cs.set_var_int_checked(
|
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()
|
v.get_int()
|
||||||
);
|
);
|
||||||
continue;
|
continue;
|
||||||
|
@ -1118,7 +1123,7 @@ static std::uint32_t *runcode(
|
||||||
auto v1 = std::move(args.back()); args.pop_back();
|
auto v1 = std::move(args.back()); args.pop_back();
|
||||||
auto v2 = std::move(args.back()); args.pop_back();
|
auto v2 = std::move(args.back()); args.pop_back();
|
||||||
cs.set_var_int_checked(
|
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)
|
(v2.get_int() << 16) | (v1.get_int() << 8)
|
||||||
);
|
);
|
||||||
continue;
|
continue;
|
||||||
|
@ -1128,7 +1133,7 @@ static std::uint32_t *runcode(
|
||||||
auto v2 = std::move(args.back()); args.pop_back();
|
auto v2 = std::move(args.back()); args.pop_back();
|
||||||
auto v3 = std::move(args.back()); args.pop_back();
|
auto v3 = std::move(args.back()); args.pop_back();
|
||||||
cs.set_var_int_checked(
|
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())
|
(v3.get_int() << 16) | (v2.get_int() << 8) | (v1.get_int())
|
||||||
);
|
);
|
||||||
continue;
|
continue;
|
||||||
|
@ -1137,26 +1142,26 @@ static std::uint32_t *runcode(
|
||||||
case BC_INST_FVAR | BC_RET_FLOAT:
|
case BC_INST_FVAR | BC_RET_FLOAT:
|
||||||
case BC_INST_FVAR | BC_RET_NULL:
|
case BC_INST_FVAR | BC_RET_NULL:
|
||||||
args.emplace_back(cs).set_float(static_cast<float_var *>(
|
args.emplace_back(cs).set_float(static_cast<float_var *>(
|
||||||
cs.p_state->identmap[op >> 8]
|
ts.istate->identmap[op >> 8]
|
||||||
)->get_value());
|
)->get_value());
|
||||||
continue;
|
continue;
|
||||||
case BC_INST_FVAR | BC_RET_STRING: {
|
case BC_INST_FVAR | BC_RET_STRING: {
|
||||||
auto &v = args.emplace_back(cs);
|
auto &v = args.emplace_back(cs);
|
||||||
v.set_int(static_cast<float_var *>(
|
v.set_int(static_cast<float_var *>(
|
||||||
cs.p_state->identmap[op >> 8]
|
ts.istate->identmap[op >> 8]
|
||||||
)->get_value());
|
)->get_value());
|
||||||
v.force_str();
|
v.force_str();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
case BC_INST_FVAR | BC_RET_INT:
|
case BC_INST_FVAR | BC_RET_INT:
|
||||||
args.emplace_back(cs).set_int(int(static_cast<float_var *>(
|
args.emplace_back(cs).set_int(int(static_cast<float_var *>(
|
||||||
cs.p_state->identmap[op >> 8]
|
ts.istate->identmap[op >> 8]
|
||||||
)->get_value()));
|
)->get_value()));
|
||||||
continue;
|
continue;
|
||||||
case BC_INST_FVAR1: {
|
case BC_INST_FVAR1: {
|
||||||
auto &v = args.back();
|
auto &v = args.back();
|
||||||
cs.set_var_float_checked(
|
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()
|
v.get_float()
|
||||||
);
|
);
|
||||||
args.pop_back();
|
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_FLOAT:
|
||||||
case BC_INST_COM | BC_RET_INT: {
|
case BC_INST_COM | BC_RET_INT: {
|
||||||
command_impl *id = static_cast<command_impl *>(
|
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();
|
std::size_t offset = args.size() - id->get_num_args();
|
||||||
result.force_none();
|
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_FLOAT:
|
||||||
case BC_INST_COM_V | BC_RET_INT: {
|
case BC_INST_COM_V | BC_RET_INT: {
|
||||||
command_impl *id = static_cast<command_impl *>(
|
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 callargs = (op >> 8) & 0x1F;
|
||||||
std::size_t offset = args.size() - callargs;
|
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_FLOAT:
|
||||||
case BC_INST_COM_C | BC_RET_INT: {
|
case BC_INST_COM_C | BC_RET_INT: {
|
||||||
command_impl *id = static_cast<command_impl *>(
|
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 callargs = (op >> 8) & 0x1F,
|
||||||
offset = args.size() - callargs;
|
offset = args.size() - callargs;
|
||||||
|
@ -1251,13 +1256,13 @@ static std::uint32_t *runcode(
|
||||||
|
|
||||||
case BC_INST_ALIAS:
|
case BC_INST_ALIAS:
|
||||||
static_cast<alias_impl *>(
|
static_cast<alias_impl *>(
|
||||||
cs.p_state->identmap[op >> 8]
|
ts.istate->identmap[op >> 8]
|
||||||
)->set_alias(cs, args.back());
|
)->set_alias(cs, args.back());
|
||||||
args.pop_back();
|
args.pop_back();
|
||||||
continue;
|
continue;
|
||||||
case BC_INST_ALIAS_ARG:
|
case BC_INST_ALIAS_ARG:
|
||||||
static_cast<alias_impl *>(
|
static_cast<alias_impl *>(
|
||||||
cs.p_state->identmap[op >> 8]
|
ts.istate->identmap[op >> 8]
|
||||||
)->set_arg(cs, args.back());
|
)->set_arg(cs, args.back());
|
||||||
args.pop_back();
|
args.pop_back();
|
||||||
continue;
|
continue;
|
||||||
|
@ -1274,18 +1279,18 @@ static std::uint32_t *runcode(
|
||||||
case BC_INST_CALL | BC_RET_FLOAT:
|
case BC_INST_CALL | BC_RET_FLOAT:
|
||||||
case BC_INST_CALL | BC_RET_INT: {
|
case BC_INST_CALL | BC_RET_INT: {
|
||||||
result.force_none();
|
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 callargs = (op >> 8) & 0x1F;
|
||||||
std::size_t nnargs = args.size();
|
std::size_t nnargs = args.size();
|
||||||
std::size_t offset = nnargs - callargs;
|
std::size_t offset = nnargs - callargs;
|
||||||
if (id->get_flags() & IDENT_FLAG_UNKNOWN) {
|
if (id->get_flags() & IDENT_FLAG_UNKNOWN) {
|
||||||
force_arg(result, op & BC_INST_RET_MASK);
|
force_arg(result, op & BC_INST_RET_MASK);
|
||||||
throw error(
|
throw error{
|
||||||
cs, "unknown command: %s", id->get_name().data()
|
cs, "unknown command: %s", id->get_name().data()
|
||||||
);
|
};
|
||||||
}
|
}
|
||||||
call_alias(
|
call_alias(
|
||||||
cs, static_cast<alias *>(id), &args[0], result, callargs,
|
ts, static_cast<alias *>(id), &args[0], result, callargs,
|
||||||
nnargs, offset, 0, op
|
nnargs, offset, 0, op
|
||||||
);
|
);
|
||||||
args.resize(nnargs, any_value{cs});
|
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_FLOAT:
|
||||||
case BC_INST_CALL_ARG | BC_RET_INT: {
|
case BC_INST_CALL_ARG | BC_RET_INT: {
|
||||||
result.force_none();
|
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 callargs = (op >> 8) & 0x1F;
|
||||||
std::size_t nnargs = args.size();
|
std::size_t nnargs = args.size();
|
||||||
std::size_t offset = nnargs - callargs;
|
std::size_t offset = nnargs - callargs;
|
||||||
|
@ -1306,7 +1311,7 @@ static std::uint32_t *runcode(
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
call_alias(
|
call_alias(
|
||||||
cs, static_cast<alias *>(id), &args[0], result, callargs,
|
ts, static_cast<alias *>(id), &args[0], result, callargs,
|
||||||
nnargs, offset, 0, op
|
nnargs, offset, 0, op
|
||||||
);
|
);
|
||||||
args.resize(nnargs, any_value{cs});
|
args.resize(nnargs, any_value{cs});
|
||||||
|
@ -1338,9 +1343,9 @@ noid:
|
||||||
result.force_none();
|
result.force_none();
|
||||||
force_arg(result, op & BC_INST_RET_MASK);
|
force_arg(result, op & BC_INST_RET_MASK);
|
||||||
std::string_view ids{idn};
|
std::string_view ids{idn};
|
||||||
throw error(
|
throw error{
|
||||||
cs, "unknown command: %s", ids.data()
|
cs, "unknown command: %s", ids.data()
|
||||||
);
|
};
|
||||||
}
|
}
|
||||||
result.force_none();
|
result.force_none();
|
||||||
switch (id->get_raw_type()) {
|
switch (id->get_raw_type()) {
|
||||||
|
@ -1353,7 +1358,7 @@ noid:
|
||||||
/* fallthrough */
|
/* fallthrough */
|
||||||
case ID_COMMAND:
|
case ID_COMMAND:
|
||||||
callcommand(
|
callcommand(
|
||||||
cs, static_cast<command_impl *>(id),
|
ts, static_cast<command_impl *>(id),
|
||||||
&args[offset], result, callargs
|
&args[offset], result, callargs
|
||||||
);
|
);
|
||||||
force_arg(result, op & BC_INST_RET_MASK);
|
force_arg(result, op & BC_INST_RET_MASK);
|
||||||
|
@ -1367,7 +1372,7 @@ noid:
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
call_with_cleanup([&]() {
|
call_with_cleanup([&]() {
|
||||||
code = runcode(cs, code, result);
|
code = runcode(ts, code, result);
|
||||||
}, [&]() {
|
}, [&]() {
|
||||||
for (size_t j = 0; j < size_t(callargs); ++j) {
|
for (size_t j = 0; j < size_t(callargs); ++j) {
|
||||||
pop_alias(args[offset + j].get_ident());
|
pop_alias(args[offset + j].get_ident());
|
||||||
|
@ -1425,7 +1430,7 @@ noid:
|
||||||
goto noid;
|
goto noid;
|
||||||
}
|
}
|
||||||
call_alias(
|
call_alias(
|
||||||
cs, a, &args[0], result, callargs, nnargs,
|
ts, a, &args[0], result, callargs, nnargs,
|
||||||
offset, 1, op
|
offset, 1, op
|
||||||
);
|
);
|
||||||
args.resize(nnargs, any_value{cs});
|
args.resize(nnargs, any_value{cs});
|
||||||
|
@ -1439,14 +1444,14 @@ noid:
|
||||||
}
|
}
|
||||||
|
|
||||||
void state::run(bcode *code, any_value &ret) {
|
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(
|
static void do_run(
|
||||||
state &cs, std::string_view file, std::string_view code,
|
state &cs, std::string_view file, std::string_view code,
|
||||||
any_value &ret
|
any_value &ret
|
||||||
) {
|
) {
|
||||||
codegen_state gs(cs);
|
codegen_state gs{cs};
|
||||||
gs.src_name = file;
|
gs.src_name = file;
|
||||||
gs.code.reserve(64);
|
gs.code.reserve(64);
|
||||||
gs.gen_main(code, VAL_ANY);
|
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));
|
std::memcpy(cbuf, gs.code.data(), gs.code.size() * sizeof(std::uint32_t));
|
||||||
bcode_incr(cbuf);
|
bcode_incr(cbuf);
|
||||||
call_with_cleanup([&cs, cbuf, &ret]() {
|
call_with_cleanup([&cs, cbuf, &ret]() {
|
||||||
runcode(cs, cbuf + 1, ret);
|
runcode(*cs.p_tstate, cbuf + 1, ret);
|
||||||
}, [cbuf]() {
|
}, [cbuf]() {
|
||||||
bcode_decr(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) {
|
for (std::size_t i = 0; i < nargs; ++i) {
|
||||||
targs[osz + i] = args[i];
|
targs[osz + i] = args[i];
|
||||||
}
|
}
|
||||||
callcommand(*this, cimpl, &targs[osz], ret, nargs, false);
|
callcommand(
|
||||||
|
*p_tstate, cimpl, &targs[osz], ret, nargs, false
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
callcommand(*this, cimpl, &args[0], ret, nargs, false);
|
callcommand(*p_tstate, cimpl, &args[0], ret, nargs, false);
|
||||||
}
|
}
|
||||||
nargs = 0;
|
nargs = 0;
|
||||||
break;
|
break;
|
||||||
|
@ -1535,7 +1542,7 @@ void state::run(ident *id, std::span<any_value> args, any_value &ret) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
call_alias(
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
22
src/cs_vm.hh
22
src/cs_vm.hh
|
@ -17,36 +17,36 @@ struct continue_exception {
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename F>
|
template<typename F>
|
||||||
static void call_with_args(state &cs, F body) {
|
static void call_with_args(thread_state &ts, F body) {
|
||||||
if (!cs.p_tstate->callstack) {
|
if (!ts.callstack) {
|
||||||
body();
|
body();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
valarray<ident_stack, MAX_ARGUMENTS> argstack{cs};
|
valarray<ident_stack, MAX_ARGUMENTS> argstack{*ts.pstate};
|
||||||
int argmask1 = cs.p_tstate->callstack->usedargs;
|
int argmask1 = ts.callstack->usedargs;
|
||||||
for (int i = 0; argmask1; argmask1 >>= 1, ++i) {
|
for (int i = 0; argmask1; argmask1 >>= 1, ++i) {
|
||||||
if (argmask1 & 1) {
|
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]
|
argstack[i]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ident_link *prevstack = cs.p_tstate->callstack->next;
|
ident_link *prevstack = ts.callstack->next;
|
||||||
ident_link aliaslink = {
|
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->usedargs : ((1 << MAX_ARGUMENTS) - 1),
|
||||||
prevstack ? prevstack->argstack : nullptr
|
prevstack ? prevstack->argstack : nullptr
|
||||||
};
|
};
|
||||||
cs.p_tstate->callstack = &aliaslink;
|
ts.callstack = &aliaslink;
|
||||||
call_with_cleanup(std::move(body), [&]() {
|
call_with_cleanup(std::move(body), [&]() {
|
||||||
if (prevstack) {
|
if (prevstack) {
|
||||||
prevstack->usedargs = aliaslink.usedargs;
|
prevstack->usedargs = aliaslink.usedargs;
|
||||||
}
|
}
|
||||||
cs.p_tstate->callstack = aliaslink.next;
|
ts.callstack = aliaslink.next;
|
||||||
int argmask2 = cs.p_tstate->callstack->usedargs;
|
int argmask2 = ts.callstack->usedargs;
|
||||||
for (int i = 0; argmask2; argmask2 >>= 1, ++i) {
|
for (int i = 0; argmask2; argmask2 >>= 1, ++i) {
|
||||||
if (argmask2 & 1) {
|
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]
|
argstack[i]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <cubescript/cubescript.hh>
|
#include <cubescript/cubescript.hh>
|
||||||
#include "cs_std.hh"
|
#include "cs_std.hh"
|
||||||
#include "cs_parser.hh"
|
#include "cs_parser.hh"
|
||||||
|
#include "cs_thread.hh"
|
||||||
|
|
||||||
namespace cubescript {
|
namespace cubescript {
|
||||||
|
|
||||||
|
@ -550,7 +551,7 @@ static void list_sort(
|
||||||
|
|
||||||
alias *xa = static_cast<alias *>(x), *ya = static_cast<alias *>(y);
|
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;
|
size_t total = 0;
|
||||||
|
|
||||||
for (list_parser p{cs, list}; p.parse();) {
|
for (list_parser p{cs, list}; p.parse();) {
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
#include "cs_std.hh"
|
#include "cs_std.hh"
|
||||||
#include "cs_strman.hh"
|
#include "cs_strman.hh"
|
||||||
|
#include "cs_thread.hh"
|
||||||
|
|
||||||
namespace cubescript {
|
namespace cubescript {
|
||||||
|
|
||||||
|
@ -59,7 +60,7 @@ void init_lib_string(state &cs) {
|
||||||
|
|
||||||
cs.new_command("strlower", "s", [](auto &ccs, auto args, auto &res) {
|
cs.new_command("strlower", "s", [](auto &ccs, auto args, auto &res) {
|
||||||
auto inps = std::string_view{args[0].get_str()};
|
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());
|
auto *buf = ics->strman->alloc_buf(inps.size());
|
||||||
for (std::size_t i = 0; i < inps.size(); ++i) {
|
for (std::size_t i = 0; i < inps.size(); ++i) {
|
||||||
buf[i] = tolower(inps[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) {
|
cs.new_command("strupper", "s", [](auto &ccs, auto args, auto &res) {
|
||||||
auto inps = std::string_view{args[0].get_str()};
|
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());
|
auto *buf = ics->strman->alloc_buf(inps.size());
|
||||||
for (std::size_t i = 0; i < inps.size(); ++i) {
|
for (std::size_t i = 0; i < inps.size(); ++i) {
|
||||||
buf[i] = toupper(inps[i]);
|
buf[i] = toupper(inps[i]);
|
||||||
|
|
|
@ -10,6 +10,7 @@ libcubescript_src = [
|
||||||
'cs_ident.cc',
|
'cs_ident.cc',
|
||||||
'cs_parser.cc',
|
'cs_parser.cc',
|
||||||
'cs_state.cc',
|
'cs_state.cc',
|
||||||
|
'cs_std.cc',
|
||||||
'cs_strman.cc',
|
'cs_strman.cc',
|
||||||
'cs_thread.cc',
|
'cs_thread.cc',
|
||||||
'cs_val.cc',
|
'cs_val.cc',
|
||||||
|
|
Loading…
Reference in New Issue