kill call_with_args template
parent
8b04bd1488
commit
036362683c
|
@ -6,7 +6,7 @@
|
||||||
#include "cs_state.hh"
|
#include "cs_state.hh"
|
||||||
#include "cs_thread.hh"
|
#include "cs_thread.hh"
|
||||||
#include "cs_strman.hh"
|
#include "cs_strman.hh"
|
||||||
#include "cs_vm.hh" // break/continue, call_with_args
|
#include "cs_vm.hh"
|
||||||
#include "cs_parser.hh"
|
#include "cs_parser.hh"
|
||||||
#include "cs_error.hh"
|
#include "cs_error.hh"
|
||||||
|
|
||||||
|
@ -179,9 +179,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", "b", [](auto &cs, auto args, auto &res) {
|
p = &new_command("doargs", "b", [](auto &cs, auto args, auto &res) {
|
||||||
call_with_args(*cs.p_tstate, [&cs, &res, &args]() {
|
res = exec_code_with_args(*cs.p_tstate, args[0].get_code());
|
||||||
res = args[0].get_code().call(cs);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
static_cast<command_impl *>(p)->p_type = ID_DOARGS;
|
static_cast<command_impl *>(p)->p_type = ID_DOARGS;
|
||||||
|
|
||||||
|
|
71
src/cs_vm.cc
71
src/cs_vm.cc
|
@ -216,6 +216,62 @@ bool exec_alias(
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
any_value exec_code_with_args(thread_state &ts, bcode_ref const &body) {
|
||||||
|
if (!ts.callstack) {
|
||||||
|
return body.call(*ts.pstate);
|
||||||
|
}
|
||||||
|
auto mask = ts.callstack->usedargs;
|
||||||
|
std::size_t noff = ts.idstack.size();
|
||||||
|
for (std::size_t i = 0; mask.any(); ++i) {
|
||||||
|
if (mask[0]) {
|
||||||
|
auto &ast = ts.get_astack(
|
||||||
|
static_cast<alias *>(ts.istate->identmap[i])
|
||||||
|
);
|
||||||
|
auto &st = ts.idstack.emplace_back();
|
||||||
|
st.next = ast.node;
|
||||||
|
ast.node = ast.node->next;
|
||||||
|
}
|
||||||
|
mask >>= 1;
|
||||||
|
}
|
||||||
|
ident_link *prevstack = ts.callstack->next;
|
||||||
|
ident_link aliaslink = {
|
||||||
|
ts.callstack->id, ts.callstack,
|
||||||
|
prevstack ? prevstack->usedargs : argset{}
|
||||||
|
};
|
||||||
|
if (!prevstack) {
|
||||||
|
aliaslink.usedargs.set();
|
||||||
|
}
|
||||||
|
ts.callstack = &aliaslink;
|
||||||
|
auto cleanup = [](
|
||||||
|
auto &tss, ident_link *pstack, ident_link &alink, std::size_t offn
|
||||||
|
) {
|
||||||
|
if (pstack) {
|
||||||
|
pstack->usedargs = alink.usedargs;
|
||||||
|
}
|
||||||
|
tss.callstack = alink.next;
|
||||||
|
auto mask2 = tss.callstack->usedargs;
|
||||||
|
for (std::size_t i = 0, nredo = 0; mask2.any(); ++i) {
|
||||||
|
if (mask2[0]) {
|
||||||
|
tss.get_astack(
|
||||||
|
static_cast<alias *>(tss.istate->identmap[i])
|
||||||
|
).node = tss.idstack[offn + nredo++].next;
|
||||||
|
}
|
||||||
|
mask2 >>= 1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
any_value ret;
|
||||||
|
try {
|
||||||
|
ret = body.call(*ts.pstate);
|
||||||
|
} catch (...) {
|
||||||
|
cleanup(ts, prevstack, aliaslink, noff);
|
||||||
|
ts.idstack.resize(noff);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
cleanup(ts, prevstack, aliaslink, noff);
|
||||||
|
ts.idstack.resize(noff);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static inline alias *get_lookup_id(
|
static inline alias *get_lookup_id(
|
||||||
thread_state &ts, std::uint32_t op, alias_stack *&ast
|
thread_state &ts, std::uint32_t op, alias_stack *&ast
|
||||||
) {
|
) {
|
||||||
|
@ -412,16 +468,13 @@ std::uint32_t *vm_exec(
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
case BC_INST_DO_ARGS:
|
case BC_INST_DO_ARGS: {
|
||||||
call_with_args(ts, [](
|
auto v = std::move(args.back());
|
||||||
auto &css, std::uint32_t inst, auto &av, any_value &ret
|
args.pop_back();
|
||||||
) {
|
result = exec_code_with_args(ts, v.get_code());
|
||||||
auto v = std::move(av.back());
|
force_arg(cs, result, op & BC_INST_RET_MASK);
|
||||||
av.pop_back();
|
|
||||||
ret = v.get_code().call(css);
|
|
||||||
force_arg(css, ret, inst & BC_INST_RET_MASK);
|
|
||||||
}, cs, op, args, result);
|
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
case BC_INST_DO: {
|
case BC_INST_DO: {
|
||||||
auto v = std::move(args.back());
|
auto v = std::move(args.back());
|
||||||
|
|
58
src/cs_vm.hh
58
src/cs_vm.hh
|
@ -17,62 +17,6 @@ struct break_exception {
|
||||||
struct continue_exception {
|
struct continue_exception {
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename F, typename ...A>
|
|
||||||
static void call_with_args(thread_state &ts, F body, A &&...args) {
|
|
||||||
if (!ts.callstack) {
|
|
||||||
body(std::forward<A>(args)...);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto mask = ts.callstack->usedargs;
|
|
||||||
std::size_t noff = ts.idstack.size();
|
|
||||||
for (std::size_t i = 0; mask.any(); ++i) {
|
|
||||||
if (mask[0]) {
|
|
||||||
auto &ast = ts.get_astack(
|
|
||||||
static_cast<alias *>(ts.istate->identmap[i])
|
|
||||||
);
|
|
||||||
auto &st = ts.idstack.emplace_back();
|
|
||||||
st.next = ast.node;
|
|
||||||
ast.node = ast.node->next;
|
|
||||||
}
|
|
||||||
mask >>= 1;
|
|
||||||
}
|
|
||||||
ident_link *prevstack = ts.callstack->next;
|
|
||||||
ident_link aliaslink = {
|
|
||||||
ts.callstack->id, ts.callstack,
|
|
||||||
prevstack ? prevstack->usedargs : argset{}
|
|
||||||
};
|
|
||||||
if (!prevstack) {
|
|
||||||
aliaslink.usedargs.set();
|
|
||||||
}
|
|
||||||
ts.callstack = &aliaslink;
|
|
||||||
auto cleanup = [](
|
|
||||||
auto &tss, ident_link *pstack, ident_link &alink, std::size_t offn
|
|
||||||
) {
|
|
||||||
if (pstack) {
|
|
||||||
pstack->usedargs = alink.usedargs;
|
|
||||||
}
|
|
||||||
tss.callstack = alink.next;
|
|
||||||
auto mask2 = tss.callstack->usedargs;
|
|
||||||
for (std::size_t i = 0, nredo = 0; mask2.any(); ++i) {
|
|
||||||
if (mask2[0]) {
|
|
||||||
tss.get_astack(
|
|
||||||
static_cast<alias *>(tss.istate->identmap[i])
|
|
||||||
).node = tss.idstack[offn + nredo++].next;
|
|
||||||
}
|
|
||||||
mask2 >>= 1;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
try {
|
|
||||||
body(std::forward<A>(args)...);
|
|
||||||
} catch (...) {
|
|
||||||
cleanup(ts, prevstack, aliaslink, noff);
|
|
||||||
ts.idstack.resize(noff);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
cleanup(ts, prevstack, aliaslink, noff);
|
|
||||||
ts.idstack.resize(noff);
|
|
||||||
}
|
|
||||||
|
|
||||||
void exec_command(
|
void exec_command(
|
||||||
thread_state &ts, command_impl *id, ident *self, any_value *args,
|
thread_state &ts, command_impl *id, ident *self, any_value *args,
|
||||||
any_value &res, std::size_t nargs, bool lookup = false
|
any_value &res, std::size_t nargs, bool lookup = false
|
||||||
|
@ -84,6 +28,8 @@ bool exec_alias(
|
||||||
std::size_t skip, std::uint32_t op, bool ncheck = false
|
std::size_t skip, std::uint32_t op, bool ncheck = false
|
||||||
);
|
);
|
||||||
|
|
||||||
|
any_value exec_code_with_args(thread_state &ts, bcode_ref const &body);
|
||||||
|
|
||||||
std::uint32_t *vm_exec(
|
std::uint32_t *vm_exec(
|
||||||
thread_state &ts, std::uint32_t *code, any_value &result
|
thread_state &ts, std::uint32_t *code, any_value &result
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue