prepare codebase for per-thread alias stack
parent
e8856f8f9d
commit
881ba4bce9
|
@ -640,6 +640,7 @@ struct LIBCUBESCRIPT_EXPORT alias_local {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
alias *p_alias;
|
alias *p_alias;
|
||||||
|
void *p_sp;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LIBCUBESCRIPT_EXPORT list_parser {
|
struct LIBCUBESCRIPT_EXPORT list_parser {
|
||||||
|
|
|
@ -114,56 +114,6 @@ alias_impl::alias_impl(state &cs, string_ref name, any_value v, int fl):
|
||||||
p_initial.val_s = v;
|
p_initial.val_s = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
void alias_impl::push_arg(ident_stack &st) {
|
|
||||||
st.next = p_astack;
|
|
||||||
p_astack = &st;
|
|
||||||
}
|
|
||||||
|
|
||||||
void alias_impl::pop_arg() {
|
|
||||||
if (p_astack == &p_initial) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
p_astack = p_astack->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
void alias_impl::undo_arg(ident_stack &st) {
|
|
||||||
st.next = p_astack;
|
|
||||||
p_astack = p_astack->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
void alias_impl::redo_arg(ident_stack &st) {
|
|
||||||
p_astack = st.next;
|
|
||||||
}
|
|
||||||
|
|
||||||
void alias_impl::set_arg(thread_state &ts, any_value &v) {
|
|
||||||
if (ident_is_used_arg(this, ts)) {
|
|
||||||
p_astack->code = bcode_ref{};
|
|
||||||
} else {
|
|
||||||
push_arg(ts.idstack.emplace_back(*ts.pstate));
|
|
||||||
ts.callstack->usedargs[get_index()] = true;
|
|
||||||
}
|
|
||||||
p_astack->val_s = std::move(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
void alias_impl::set_alias(thread_state &ts, any_value &v) {
|
|
||||||
p_astack->val_s = std::move(v);
|
|
||||||
p_astack->code = bcode_ref{};
|
|
||||||
p_flags = (p_flags & ts.pstate->identflags) | ts.pstate->identflags;
|
|
||||||
}
|
|
||||||
|
|
||||||
bcode_ref const &alias_impl::compile_code(thread_state &ts) {
|
|
||||||
if (!p_astack->code) {
|
|
||||||
codegen_state gs(ts);
|
|
||||||
gs.code.reserve(64);
|
|
||||||
gs.gen_main(p_astack->val_s.get_str());
|
|
||||||
/* i wish i could steal the memory somehow */
|
|
||||||
uint32_t *code = bcode_alloc(ts.istate, gs.code.size());
|
|
||||||
memcpy(code, gs.code.data(), gs.code.size() * sizeof(uint32_t));
|
|
||||||
p_astack->code = bcode_ref{reinterpret_cast<bcode *>(code + 1)};
|
|
||||||
}
|
|
||||||
return p_astack->code;
|
|
||||||
}
|
|
||||||
|
|
||||||
command_impl::command_impl(
|
command_impl::command_impl(
|
||||||
string_ref name, string_ref args, int nargs, command_func f
|
string_ref name, string_ref args, int nargs, command_func f
|
||||||
):
|
):
|
||||||
|
@ -190,6 +140,25 @@ bool ident_is_used_arg(ident *id, thread_state &ts) {
|
||||||
return ts.callstack->usedargs[id->get_index()];
|
return ts.callstack->usedargs[id->get_index()];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void alias_stack::set_arg(alias *a, thread_state &ts, any_value &v) {
|
||||||
|
if (ident_is_used_arg(a, ts)) {
|
||||||
|
node->code = bcode_ref{};
|
||||||
|
} else {
|
||||||
|
auto &st = ts.idstack.emplace_back(*ts.pstate);
|
||||||
|
st.next = node;
|
||||||
|
node = &st;
|
||||||
|
ts.callstack->usedargs[a->get_index()] = true;
|
||||||
|
}
|
||||||
|
node->val_s = std::move(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
void alias_stack::set_alias(alias *a, thread_state &ts, any_value &v) {
|
||||||
|
node->val_s = std::move(v);
|
||||||
|
node->code = bcode_ref{};
|
||||||
|
auto *ai = static_cast<alias_impl *>(a);
|
||||||
|
ai->p_flags = (ai->p_flags & ts.pstate->identflags) | ts.pstate->identflags;
|
||||||
|
}
|
||||||
|
|
||||||
/* public interface */
|
/* public interface */
|
||||||
|
|
||||||
LIBCUBESCRIPT_EXPORT int ident::get_raw_type() const {
|
LIBCUBESCRIPT_EXPORT int ident::get_raw_type() const {
|
||||||
|
@ -390,23 +359,28 @@ LIBCUBESCRIPT_EXPORT alias_local::alias_local(state &cs, ident *a) {
|
||||||
p_alias = nullptr;
|
p_alias = nullptr;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto *aimp = static_cast<alias_impl *>(p_alias);
|
auto &ts = *cs.thread_pointer();
|
||||||
p_alias = aimp;
|
p_alias = static_cast<alias *>(a);
|
||||||
aimp->push_arg(
|
auto &ast = ts.get_astack(p_alias);
|
||||||
cs.thread_pointer()->idstack.emplace_back(cs)
|
auto &st = ts.idstack.emplace_back(cs);
|
||||||
);
|
st.next = ast.node;
|
||||||
aimp->p_flags &= ~IDENT_FLAG_UNKNOWN;
|
ast.node = &st;
|
||||||
|
p_sp = *
|
||||||
|
static_cast<alias_impl *>(p_alias)->p_flags &= ~IDENT_FLAG_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
LIBCUBESCRIPT_EXPORT alias_local::~alias_local() {
|
LIBCUBESCRIPT_EXPORT alias_local::~alias_local() {
|
||||||
static_cast<alias_impl *>(p_alias)->pop_arg();
|
if (p_alias) {
|
||||||
|
auto &st = *static_cast<alias_stack *>(p_sp);
|
||||||
|
st.node = st.node->next;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LIBCUBESCRIPT_EXPORT bool alias_local::set(any_value val) {
|
LIBCUBESCRIPT_EXPORT bool alias_local::set(any_value val) {
|
||||||
if (!p_alias) {
|
if (!p_alias) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
static_cast<alias_impl *>(p_alias)->p_astack->val_s = std::move(val);
|
static_cast<alias_stack *>(p_sp)->node->val_s = std::move(val);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,13 @@ struct ident_stack {
|
||||||
ident_stack(state &cs): val_s{cs}, code{}, next{nullptr} {}
|
ident_stack(state &cs): val_s{cs}, code{}, next{nullptr} {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct alias_stack {
|
||||||
|
ident_stack *node;
|
||||||
|
|
||||||
|
void set_arg(alias *a, thread_state &ts, any_value &v);
|
||||||
|
void set_alias(alias *a, thread_state &ts, any_value &v);
|
||||||
|
};
|
||||||
|
|
||||||
struct ident_link {
|
struct ident_link {
|
||||||
ident *id;
|
ident *id;
|
||||||
ident_link *next;
|
ident_link *next;
|
||||||
|
@ -96,17 +103,8 @@ struct alias_impl: ident_impl, alias {
|
||||||
alias_impl(state &cs, string_ref n, int flags);
|
alias_impl(state &cs, string_ref n, int flags);
|
||||||
alias_impl(state &cs, string_ref n, any_value v, int flags);
|
alias_impl(state &cs, string_ref n, any_value v, int flags);
|
||||||
|
|
||||||
void push_arg(ident_stack &st);
|
|
||||||
void pop_arg();
|
|
||||||
void undo_arg(ident_stack &st);
|
|
||||||
void redo_arg(ident_stack &st);
|
|
||||||
void set_arg(thread_state &ts, any_value &v);
|
|
||||||
void set_alias(thread_state &ts, any_value &v);
|
|
||||||
|
|
||||||
bcode_ref const &compile_code(thread_state &ts);
|
|
||||||
|
|
||||||
ident_stack p_initial;
|
ident_stack p_initial;
|
||||||
ident_stack *p_astack;
|
alias_stack p_astack;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct command_impl: ident_impl, command {
|
struct command_impl: ident_impl, command {
|
||||||
|
|
|
@ -365,11 +365,12 @@ LIBCUBESCRIPT_EXPORT void state::set_alias(
|
||||||
if (id) {
|
if (id) {
|
||||||
switch (id->get_type()) {
|
switch (id->get_type()) {
|
||||||
case ident_type::ALIAS: {
|
case ident_type::ALIAS: {
|
||||||
alias_impl *a = static_cast<alias_impl *>(id);
|
alias *a = static_cast<alias *>(id);
|
||||||
|
auto &ast = p_tstate->get_astack(a);
|
||||||
if (a->get_flags() & IDENT_FLAG_ARG) {
|
if (a->get_flags() & IDENT_FLAG_ARG) {
|
||||||
a->set_arg(*p_tstate, v);
|
ast.set_arg(a, *p_tstate, v);
|
||||||
} else {
|
} else {
|
||||||
a->set_alias(*p_tstate, v);
|
ast.set_alias(a, *p_tstate, v);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -459,9 +460,9 @@ LIBCUBESCRIPT_EXPORT void state::clear_override(ident &id) {
|
||||||
}
|
}
|
||||||
switch (id.get_type()) {
|
switch (id.get_type()) {
|
||||||
case ident_type::ALIAS: {
|
case ident_type::ALIAS: {
|
||||||
alias_impl &a = static_cast<alias_impl &>(id);
|
auto &ast = p_tstate->get_astack(static_cast<alias *>(&id));
|
||||||
a.p_astack->val_s.set_str("");
|
ast.node->val_s.set_str("");
|
||||||
a.p_astack->code = bcode_ref{};
|
ast.node->code = bcode_ref{};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ident_type::IVAR: {
|
case ident_type::IVAR: {
|
||||||
|
@ -650,7 +651,7 @@ state::get_alias_val(std::string_view name) {
|
||||||
if ((a->get_flags() & IDENT_FLAG_ARG) && !ident_is_used_arg(a, *p_tstate)) {
|
if ((a->get_flags() & IDENT_FLAG_ARG) && !ident_is_used_arg(a, *p_tstate)) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
return static_cast<alias_impl *>(a)->p_astack->val_s.get_str();
|
return p_tstate->get_astack(a).node->val_s.get_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
integer_type clamp_var(state &cs, integer_var *iv, integer_type v) {
|
integer_type clamp_var(state &cs, integer_var *iv, integer_type v) {
|
||||||
|
@ -871,14 +872,9 @@ LIBCUBESCRIPT_EXPORT void state::run(
|
||||||
) {
|
) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (
|
|
||||||
static_cast<alias_impl *>(a)->p_astack->val_s.get_type() ==
|
|
||||||
value_type::NONE
|
|
||||||
) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
exec_alias(
|
exec_alias(
|
||||||
*p_tstate, a, &args[0], ret, nargs, nargs, 0, 0, BC_RET_NULL
|
*p_tstate, a, &args[0], ret, nargs, nargs, 0, 0,
|
||||||
|
BC_RET_NULL, true
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,4 +17,8 @@ hook_func thread_state::set_hook(hook_func f) {
|
||||||
return hk;
|
return hk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
alias_stack &thread_state::get_astack(alias *a) {
|
||||||
|
return static_cast<alias_impl *>(a)->p_astack;
|
||||||
|
}
|
||||||
|
|
||||||
} /* namespace cubescript */
|
} /* namespace cubescript */
|
||||||
|
|
|
@ -41,6 +41,8 @@ struct thread_state {
|
||||||
|
|
||||||
hook_func &get_hook() { return call_hook; }
|
hook_func &get_hook() { return call_hook; }
|
||||||
hook_func const &get_hook() const { return call_hook; }
|
hook_func const &get_hook() const { return call_hook; }
|
||||||
|
|
||||||
|
alias_stack &get_astack(alias *a);
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace cubescript */
|
} /* namespace cubescript */
|
||||||
|
|
129
src/cs_vm.cc
129
src/cs_vm.cc
|
@ -9,17 +9,21 @@
|
||||||
|
|
||||||
namespace cubescript {
|
namespace cubescript {
|
||||||
|
|
||||||
static inline void push_alias(ident *id, ident_stack &st) {
|
static inline void push_alias(thread_state &ts, ident *id, ident_stack &st) {
|
||||||
if (id->is_alias() && !(id->get_flags() & IDENT_FLAG_ARG)) {
|
if (id->is_alias() && !(id->get_flags() & IDENT_FLAG_ARG)) {
|
||||||
auto *aimp = static_cast<alias_impl *>(id);
|
auto *aimp = static_cast<alias_impl *>(id);
|
||||||
aimp->push_arg(st);
|
auto &ast = ts.get_astack(aimp);
|
||||||
|
st.next = ast.node;
|
||||||
|
ast.node = &st;
|
||||||
aimp->p_flags &= ~IDENT_FLAG_UNKNOWN;
|
aimp->p_flags &= ~IDENT_FLAG_UNKNOWN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void pop_alias(ident *id) {
|
static inline void pop_alias(thread_state &ts, ident *id) {
|
||||||
if (id->is_alias() && !(id->get_flags() & IDENT_FLAG_ARG)) {
|
if (id->is_alias() && !(id->get_flags() & IDENT_FLAG_ARG)) {
|
||||||
static_cast<alias_impl *>(id)->pop_arg();
|
auto *aimp = static_cast<alias_impl *>(id);
|
||||||
|
auto &ast = ts.get_astack(aimp);
|
||||||
|
ast.node = ast.node->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,11 +203,15 @@ void exec_command(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void exec_alias(
|
bool exec_alias(
|
||||||
thread_state &ts, 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, bool ncheck
|
||||||
) {
|
) {
|
||||||
|
auto &aast = ts.get_astack(a);
|
||||||
|
if (ncheck && aast.node->val_s.get_type() == value_type::NONE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
/* excess arguments get ignored (make error maybe?) */
|
/* excess arguments get ignored (make error maybe?) */
|
||||||
callargs = std::min(callargs, MAX_ARGUMENTS);
|
callargs = std::min(callargs, MAX_ARGUMENTS);
|
||||||
integer_var *anargs = static_cast<integer_var *>(
|
integer_var *anargs = static_cast<integer_var *>(
|
||||||
|
@ -212,9 +220,13 @@ void exec_alias(
|
||||||
argset uargs{};
|
argset uargs{};
|
||||||
std::size_t noff = ts.idstack.size();
|
std::size_t noff = ts.idstack.size();
|
||||||
for(std::size_t i = 0; i < callargs; i++) {
|
for(std::size_t i = 0; i < callargs; i++) {
|
||||||
auto &ap = *static_cast<alias_impl *>(ts.istate->identmap[i]);
|
auto &ast = ts.get_astack(
|
||||||
ap.push_arg(ts.idstack.emplace_back(*ts.pstate));
|
static_cast<alias *>(ts.istate->identmap[i])
|
||||||
ap.p_astack->val_s = std::move(args[offset + i]);
|
);
|
||||||
|
auto &st = ts.idstack.emplace_back(*ts.pstate);
|
||||||
|
st.next = ast.node;
|
||||||
|
ast.node = &st;
|
||||||
|
st.val_s = std::move(args[offset + i]);
|
||||||
uargs[i] = true;
|
uargs[i] = true;
|
||||||
}
|
}
|
||||||
auto oldargs = anargs->get_value();
|
auto oldargs = anargs->get_value();
|
||||||
|
@ -223,22 +235,33 @@ void exec_alias(
|
||||||
ts.pstate->identflags |= a->get_flags()&IDENT_FLAG_OVERRIDDEN;
|
ts.pstate->identflags |= a->get_flags()&IDENT_FLAG_OVERRIDDEN;
|
||||||
ident_link aliaslink = {a, ts.callstack, uargs};
|
ident_link aliaslink = {a, ts.callstack, uargs};
|
||||||
ts.callstack = &aliaslink;
|
ts.callstack = &aliaslink;
|
||||||
bcode_ref coderef = static_cast<
|
if (!aast.node->code) {
|
||||||
alias_impl *
|
codegen_state gs{ts};
|
||||||
>(a)->compile_code(ts);
|
gs.code.reserve(64);
|
||||||
|
gs.gen_main(aast.node->val_s.get_str());
|
||||||
|
/* i wish i could steal the memory somehow */
|
||||||
|
uint32_t *code = bcode_alloc(ts.istate, gs.code.size());
|
||||||
|
memcpy(code, gs.code.data(), gs.code.size() * sizeof(uint32_t));
|
||||||
|
aast.node->code = bcode_ref{reinterpret_cast<bcode *>(code + 1)};
|
||||||
|
}
|
||||||
|
bcode_ref coderef = aast.node->code;
|
||||||
auto cleanup = [&]() {
|
auto cleanup = [&]() {
|
||||||
ts.callstack = aliaslink.next;
|
ts.callstack = aliaslink.next;
|
||||||
ts.pstate->identflags = oldflags;
|
ts.pstate->identflags = oldflags;
|
||||||
auto amask = aliaslink.usedargs;
|
auto amask = aliaslink.usedargs;
|
||||||
for (std::size_t i = 0; i < callargs; i++) {
|
for (std::size_t i = 0; i < callargs; i++) {
|
||||||
static_cast<alias_impl *>(ts.istate->identmap[i])->pop_arg();
|
auto &ast = ts.get_astack(
|
||||||
|
static_cast<alias *>(ts.istate->identmap[i])
|
||||||
|
);
|
||||||
|
ast.node = ast.node->next;
|
||||||
amask[i] = false;
|
amask[i] = false;
|
||||||
}
|
}
|
||||||
for (; amask.any(); ++callargs) {
|
for (; amask.any(); ++callargs) {
|
||||||
if (amask[callargs]) {
|
if (amask[callargs]) {
|
||||||
static_cast<alias_impl *>(
|
auto &ast = ts.get_astack(
|
||||||
ts.istate->identmap[callargs]
|
static_cast<alias *>(ts.istate->identmap[callargs])
|
||||||
)->pop_arg();
|
);
|
||||||
|
ast.node = ast.node->next;
|
||||||
amask[callargs] = false;
|
amask[callargs] = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -255,6 +278,7 @@ void exec_alias(
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
cleanup();
|
cleanup();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr int MaxRunDepth = 255;
|
static constexpr int MaxRunDepth = 255;
|
||||||
|
@ -523,13 +547,13 @@ std::uint32_t *vm_exec(
|
||||||
std::size_t idstsz = ts.idstack.size();
|
std::size_t idstsz = ts.idstack.size();
|
||||||
for (std::size_t i = 0; i < numlocals; ++i) {
|
for (std::size_t i = 0; i < numlocals; ++i) {
|
||||||
push_alias(
|
push_alias(
|
||||||
args[offset + i].get_ident(),
|
ts, args[offset + i].get_ident(),
|
||||||
ts.idstack.emplace_back(*ts.pstate)
|
ts.idstack.emplace_back(*ts.pstate)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
auto cleanup = [&]() {
|
auto cleanup = [&]() {
|
||||||
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(ts, args[i].get_ident());
|
||||||
}
|
}
|
||||||
ts.idstack.resize(idstsz, ident_stack{*ts.pstate});
|
ts.idstack.resize(idstsz, ident_stack{*ts.pstate});
|
||||||
};
|
};
|
||||||
|
@ -739,9 +763,10 @@ std::uint32_t *vm_exec(
|
||||||
(a->get_flags() & IDENT_FLAG_ARG) &&
|
(a->get_flags() & IDENT_FLAG_ARG) &&
|
||||||
!ident_is_used_arg(a, ts)
|
!ident_is_used_arg(a, ts)
|
||||||
) {
|
) {
|
||||||
static_cast<alias_impl *>(a)->push_arg(
|
auto &ast = ts.get_astack(a);
|
||||||
ts.idstack.emplace_back(*ts.pstate)
|
auto &st = ts.idstack.emplace_back(*ts.pstate);
|
||||||
);
|
st.next = ast.node;
|
||||||
|
ast.node = &st;
|
||||||
ts.callstack->usedargs[a->get_index()] = true;
|
ts.callstack->usedargs[a->get_index()] = true;
|
||||||
}
|
}
|
||||||
args.emplace_back(cs).set_ident(a);
|
args.emplace_back(cs).set_ident(a);
|
||||||
|
@ -757,9 +782,11 @@ std::uint32_t *vm_exec(
|
||||||
(id->get_flags() & IDENT_FLAG_ARG) &&
|
(id->get_flags() & IDENT_FLAG_ARG) &&
|
||||||
!ident_is_used_arg(id, ts)
|
!ident_is_used_arg(id, ts)
|
||||||
) {
|
) {
|
||||||
static_cast<alias_impl *>(id)->push_arg(
|
auto *a = static_cast<alias *>(id);
|
||||||
ts.idstack.emplace_back(*ts.pstate)
|
auto &ast = ts.get_astack(a);
|
||||||
);
|
auto &st = ts.idstack.emplace_back(*ts.pstate);
|
||||||
|
st.next = ast.node;
|
||||||
|
ast.node = &st;
|
||||||
ts.callstack->usedargs[id->get_index()] = true;
|
ts.callstack->usedargs[id->get_index()] = true;
|
||||||
}
|
}
|
||||||
arg.set_ident(id);
|
arg.set_ident(id);
|
||||||
|
@ -771,7 +798,9 @@ std::uint32_t *vm_exec(
|
||||||
any_value &arg = args.back();
|
any_value &arg = args.back();
|
||||||
switch (get_lookupu_type(ts, arg, id, op)) {
|
switch (get_lookupu_type(ts, arg, id, op)) {
|
||||||
case ID_ALIAS:
|
case ID_ALIAS:
|
||||||
arg = static_cast<alias_impl *>(id)->p_astack->val_s;
|
arg = ts.get_astack(
|
||||||
|
static_cast<alias *>(id)
|
||||||
|
).node->val_s;
|
||||||
arg.force_str();
|
arg.force_str();
|
||||||
continue;
|
continue;
|
||||||
case ID_SVAR:
|
case ID_SVAR:
|
||||||
|
@ -799,7 +828,7 @@ std::uint32_t *vm_exec(
|
||||||
args.emplace_back(cs).set_str("");
|
args.emplace_back(cs).set_str("");
|
||||||
} else {
|
} else {
|
||||||
auto &v = args.emplace_back(cs);
|
auto &v = args.emplace_back(cs);
|
||||||
v = static_cast<alias_impl *>(a)->p_astack->val_s;
|
v = ts.get_astack(a).node->val_s;
|
||||||
v.force_str();
|
v.force_str();
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
@ -810,9 +839,9 @@ std::uint32_t *vm_exec(
|
||||||
any_value &arg = args.back();
|
any_value &arg = args.back();
|
||||||
switch (get_lookupu_type(ts, arg, id, op)) {
|
switch (get_lookupu_type(ts, arg, id, op)) {
|
||||||
case ID_ALIAS:
|
case ID_ALIAS:
|
||||||
arg.set_int(static_cast<alias_impl *>(
|
arg.set_int(ts.get_astack(static_cast<alias *>(
|
||||||
id
|
id
|
||||||
)->p_astack->val_s.get_int());
|
)).node->val_s.get_int());
|
||||||
continue;
|
continue;
|
||||||
case ID_SVAR:
|
case ID_SVAR:
|
||||||
arg.set_int(parse_int(
|
arg.set_int(parse_int(
|
||||||
|
@ -840,7 +869,7 @@ std::uint32_t *vm_exec(
|
||||||
args.emplace_back(cs).set_int(0);
|
args.emplace_back(cs).set_int(0);
|
||||||
} else {
|
} else {
|
||||||
args.emplace_back(cs).set_int(
|
args.emplace_back(cs).set_int(
|
||||||
static_cast<alias_impl *>(a)->p_astack->val_s.get_int()
|
ts.get_astack(a).node->val_s.get_int()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
@ -850,9 +879,9 @@ std::uint32_t *vm_exec(
|
||||||
any_value &arg = args.back();
|
any_value &arg = args.back();
|
||||||
switch (get_lookupu_type(ts, arg, id, op)) {
|
switch (get_lookupu_type(ts, arg, id, op)) {
|
||||||
case ID_ALIAS:
|
case ID_ALIAS:
|
||||||
arg.set_float(static_cast<alias_impl *>(
|
arg.set_float(ts.get_astack(static_cast<alias *>(
|
||||||
id
|
id
|
||||||
)->p_astack->val_s.get_float());
|
)).node->val_s.get_float());
|
||||||
continue;
|
continue;
|
||||||
case ID_SVAR:
|
case ID_SVAR:
|
||||||
arg.set_float(parse_float(
|
arg.set_float(parse_float(
|
||||||
|
@ -881,9 +910,9 @@ std::uint32_t *vm_exec(
|
||||||
if (!a) {
|
if (!a) {
|
||||||
args.emplace_back(cs).set_float(float_type(0));
|
args.emplace_back(cs).set_float(float_type(0));
|
||||||
} else {
|
} else {
|
||||||
args.emplace_back(cs).set_float(static_cast<alias_impl *>(
|
args.emplace_back(cs).set_float(
|
||||||
a
|
ts.get_astack(a).node->val_s.get_float()
|
||||||
)->p_astack->val_s.get_float());
|
);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -892,9 +921,9 @@ std::uint32_t *vm_exec(
|
||||||
any_value &arg = args.back();
|
any_value &arg = args.back();
|
||||||
switch (get_lookupu_type(ts, arg, id, op)) {
|
switch (get_lookupu_type(ts, arg, id, op)) {
|
||||||
case ID_ALIAS:
|
case ID_ALIAS:
|
||||||
static_cast<alias_impl *>(
|
ts.get_astack(
|
||||||
id
|
static_cast<alias *>(id)
|
||||||
)->p_astack->val_s.get_val(arg);
|
).node->val_s.get_val(arg);
|
||||||
continue;
|
continue;
|
||||||
case ID_SVAR:
|
case ID_SVAR:
|
||||||
arg.set_str(static_cast<string_var *>(id)->get_value());
|
arg.set_str(static_cast<string_var *>(id)->get_value());
|
||||||
|
@ -919,7 +948,7 @@ std::uint32_t *vm_exec(
|
||||||
if (!a) {
|
if (!a) {
|
||||||
args.emplace_back(cs).set_none();
|
args.emplace_back(cs).set_none();
|
||||||
} else {
|
} else {
|
||||||
static_cast<alias_impl *>(a)->p_astack->val_s.get_val(
|
ts.get_astack(a).node->val_s.get_val(
|
||||||
args.emplace_back(cs)
|
args.emplace_back(cs)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1055,13 +1084,14 @@ std::uint32_t *vm_exec(
|
||||||
}
|
}
|
||||||
|
|
||||||
case BC_INST_ALIAS: {
|
case BC_INST_ALIAS: {
|
||||||
auto *imp = static_cast<alias_impl *>(
|
auto *a = static_cast<alias *>(
|
||||||
ts.istate->identmap[op >> 8]
|
ts.istate->identmap[op >> 8]
|
||||||
);
|
);
|
||||||
if (imp->get_flags() & IDENT_FLAG_ARG) {
|
auto &ast = ts.get_astack(a);
|
||||||
imp->set_arg(ts, args.back());
|
if (a->get_flags() & IDENT_FLAG_ARG) {
|
||||||
|
ast.set_arg(a, ts, args.back());
|
||||||
} else {
|
} else {
|
||||||
imp->set_alias(ts, args.back());
|
ast.set_alias(a, ts, args.back());
|
||||||
}
|
}
|
||||||
args.pop_back();
|
args.pop_back();
|
||||||
continue;
|
continue;
|
||||||
|
@ -1154,13 +1184,13 @@ noid:
|
||||||
std::size_t idstsz = ts.idstack.size();
|
std::size_t idstsz = ts.idstack.size();
|
||||||
for (size_t j = 0; j < size_t(callargs); ++j) {
|
for (size_t j = 0; j < size_t(callargs); ++j) {
|
||||||
push_alias(
|
push_alias(
|
||||||
args[offset + j].force_ident(cs),
|
ts, args[offset + j].force_ident(cs),
|
||||||
ts.idstack.emplace_back(*ts.pstate)
|
ts.idstack.emplace_back(*ts.pstate)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
auto cleanup = [&]() {
|
auto cleanup = [&]() {
|
||||||
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(ts, args[offset + j].get_ident());
|
||||||
}
|
}
|
||||||
ts.idstack.resize(idstsz, ident_stack{*ts.pstate});
|
ts.idstack.resize(idstsz, ident_stack{*ts.pstate});
|
||||||
};
|
};
|
||||||
|
@ -1219,15 +1249,12 @@ noid:
|
||||||
force_arg(result, op & BC_INST_RET_MASK);
|
force_arg(result, op & BC_INST_RET_MASK);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (static_cast<alias_impl *>(
|
if (!exec_alias(
|
||||||
a
|
ts, a, &args[0], result, callargs, nnargs,
|
||||||
)->p_astack->val_s.get_type() == value_type::NONE) {
|
offset, 1, op, true
|
||||||
|
)) {
|
||||||
goto noid;
|
goto noid;
|
||||||
}
|
}
|
||||||
exec_alias(
|
|
||||||
ts, a, &args[0], result, callargs, nnargs,
|
|
||||||
offset, 1, op
|
|
||||||
);
|
|
||||||
args.resize(nnargs, any_value{cs});
|
args.resize(nnargs, any_value{cs});
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
19
src/cs_vm.hh
19
src/cs_vm.hh
|
@ -51,9 +51,12 @@ static void call_with_args(thread_state &ts, F body) {
|
||||||
std::size_t noff = ts.idstack.size();
|
std::size_t noff = ts.idstack.size();
|
||||||
for (std::size_t i = 0; mask.any(); ++i) {
|
for (std::size_t i = 0; mask.any(); ++i) {
|
||||||
if (mask[0]) {
|
if (mask[0]) {
|
||||||
static_cast<alias_impl *>(ts.istate->identmap[i])->undo_arg(
|
auto &ast = ts.get_astack(
|
||||||
ts.idstack.emplace_back(*ts.pstate)
|
static_cast<alias *>(ts.istate->identmap[i])
|
||||||
);
|
);
|
||||||
|
auto &st = ts.idstack.emplace_back(*ts.pstate);
|
||||||
|
st.next = ast.node;
|
||||||
|
ast.node = ast.node->next;
|
||||||
}
|
}
|
||||||
mask >>= 1;
|
mask >>= 1;
|
||||||
}
|
}
|
||||||
|
@ -74,9 +77,9 @@ static void call_with_args(thread_state &ts, F body) {
|
||||||
auto mask2 = ts.callstack->usedargs;
|
auto mask2 = ts.callstack->usedargs;
|
||||||
for (std::size_t i = 0, nredo = 0; mask2.any(); ++i) {
|
for (std::size_t i = 0, nredo = 0; mask2.any(); ++i) {
|
||||||
if (mask2[0]) {
|
if (mask2[0]) {
|
||||||
static_cast<alias_impl *>(ts.istate->identmap[i])->redo_arg(
|
ts.get_astack(
|
||||||
ts.idstack[noff + nredo++]
|
static_cast<alias *>(ts.istate->identmap[i])
|
||||||
);
|
).node = ts.idstack[noff + nredo++].next;
|
||||||
}
|
}
|
||||||
mask2 >>= 1;
|
mask2 >>= 1;
|
||||||
}
|
}
|
||||||
|
@ -96,10 +99,10 @@ void exec_command(
|
||||||
std::size_t nargs, bool lookup = false
|
std::size_t nargs, bool lookup = false
|
||||||
);
|
);
|
||||||
|
|
||||||
void exec_alias(
|
bool exec_alias(
|
||||||
thread_state &ts, 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 offset, std::size_t skip, std::uint32_t op
|
std::size_t skip, std::uint32_t op, bool ncheck = false
|
||||||
);
|
);
|
||||||
|
|
||||||
std::uint32_t *vm_exec(
|
std::uint32_t *vm_exec(
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#include "cs_std.hh"
|
#include "cs_std.hh"
|
||||||
#include "cs_ident.hh"
|
#include "cs_ident.hh"
|
||||||
|
#include "cs_thread.hh"
|
||||||
|
|
||||||
namespace cubescript {
|
namespace cubescript {
|
||||||
|
|
||||||
|
@ -90,12 +91,9 @@ void init_lib_base(state &gcs) {
|
||||||
rc = false;
|
rc = false;
|
||||||
}
|
}
|
||||||
ret.set_int(rc);
|
ret.set_int(rc);
|
||||||
static_cast<alias_impl *>(cret)->set_alias(
|
auto &ts = *cs.thread_pointer();
|
||||||
*cs.thread_pointer(), result
|
ts.get_astack(cret).set_alias(cret, ts, result);
|
||||||
);
|
ts.get_astack(css).set_alias(css, ts, tback);
|
||||||
static_cast<alias_impl *>(css)->set_alias(
|
|
||||||
*cs.thread_pointer(), tback
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
gcs.new_command("?", "ttt", [](auto &, auto args, auto &res) {
|
gcs.new_command("?", "ttt", [](auto &, auto args, auto &res) {
|
||||||
|
|
Loading…
Reference in New Issue