use the value stack in more places

master
Daniel Kolesa 2021-03-24 23:30:30 +01:00
parent 4e8c3ee40f
commit 14cd90116d
1 changed files with 36 additions and 37 deletions

View File

@ -324,6 +324,23 @@ static inline alias *get_lookuparg_id(state &cs, std::uint32_t op) {
return static_cast<alias *>(id); return static_cast<alias *>(id);
} }
struct stack_guard {
state *csp;
std::size_t oldtop;
stack_guard() = delete;
stack_guard(state &cs):
csp{&cs}, oldtop{cs.p_tstate->vmstack.size()}
{}
~stack_guard() {
csp->p_tstate->vmstack.resize(oldtop, any_value{*csp});
}
stack_guard(stack_guard const &) = delete;
stack_guard(stack_guard &&) = delete;
};
static inline int get_lookupu_type( static inline int get_lookupu_type(
state &cs, any_value &arg, ident *&id, std::uint32_t op state &cs, any_value &arg, ident *&id, std::uint32_t op
) { ) {
@ -348,12 +365,14 @@ 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 */
auto *cimpl = static_cast<command_impl *>(id);
auto &args = cs.p_tstate->vmstack;
auto osz = args.size();
/* pad with as many empty values as we need */
args.resize(osz + cimpl->get_num_args(), any_value{cs});
arg.set_none(); arg.set_none();
valarray<any_value, MAX_ARGUMENTS> buf{cs}; callcommand(cs, cimpl, &args[osz], arg, 0, true);
callcommand(
cs, static_cast<command_impl *>(id),
&buf[0], 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 */
} }
@ -364,23 +383,6 @@ static inline int get_lookupu_type(
throw error(cs, "unknown alias lookup: %s", arg.get_str().data()); throw error(cs, "unknown alias lookup: %s", arg.get_str().data());
} }
struct stack_guard {
state *csp;
std::size_t oldtop;
stack_guard() = delete;
stack_guard(state &cs):
csp{&cs}, oldtop{cs.p_tstate->vmstack.size()}
{}
~stack_guard() {
csp->p_tstate->vmstack.resize(oldtop, any_value{*csp});
}
stack_guard(stack_guard const &) = delete;
stack_guard(stack_guard &&) = delete;
};
static std::uint32_t *runcode( static std::uint32_t *runcode(
state &cs, std::uint32_t *code, any_value &result state &cs, std::uint32_t *code, any_value &result
) { ) {
@ -1480,26 +1482,23 @@ void state::run(ident *id, std::span<any_value> args, any_value &ret) {
break; break;
} }
/* fallthrough */ /* fallthrough */
case ident_type::COMMAND: case ident_type::COMMAND: {
if (nargs < std::size_t( auto *cimpl = static_cast<command_impl *>(id);
static_cast<command_impl *>(id)->get_num_args() if (nargs < std::size_t(cimpl->get_num_args())) {
)) { stack_guard s{*this}; /* restore after call */
valarray<any_value, MAX_ARGUMENTS> buf{*this}; auto &targs = p_tstate->vmstack;
for (std::size_t i = 0; i < args.size(); ++i) { auto osz = targs.size();
buf[i] = args[i]; targs.resize(osz + cimpl->get_num_args(), any_value{*this});
for (std::size_t i = 0; i < nargs; ++i) {
targs[osz + i] = args[i];
} }
callcommand( callcommand(*this, cimpl, &targs[osz], ret, nargs, false);
*this, static_cast<command_impl *>(id), &buf[0], ret,
nargs, false
);
} else { } else {
callcommand( callcommand(*this, cimpl, &args[0], ret, nargs, false);
*this, static_cast<command_impl *>(id), &args[0],
ret, nargs, false
);
} }
nargs = 0; nargs = 0;
break; break;
}
case ident_type::IVAR: case ident_type::IVAR:
if (args.empty()) { if (args.empty()) {
print_var(*static_cast<global_var *>(id)); print_var(*static_cast<global_var *>(id));