2021-03-23 23:29:32 +01:00
|
|
|
#ifndef LIBCUBESCRIPT_VM_HH
|
|
|
|
#define LIBCUBESCRIPT_VM_HH
|
2016-08-12 18:38:43 +02:00
|
|
|
|
2021-03-24 20:33:20 +01:00
|
|
|
#include <cubescript/cubescript.hh>
|
2016-08-12 18:38:43 +02:00
|
|
|
|
2021-03-23 01:11:21 +01:00
|
|
|
#include "cs_std.hh"
|
2021-03-22 22:33:01 +01:00
|
|
|
#include "cs_ident.hh"
|
2021-03-24 20:33:20 +01:00
|
|
|
#include "cs_thread.hh"
|
2016-09-08 23:42:14 +02:00
|
|
|
|
2021-03-23 23:32:25 +01:00
|
|
|
namespace cubescript {
|
2016-08-12 18:38:43 +02:00
|
|
|
|
2021-03-24 02:21:27 +01:00
|
|
|
struct break_exception {
|
2016-09-14 23:24:13 +02:00
|
|
|
};
|
|
|
|
|
2021-03-24 02:21:27 +01:00
|
|
|
struct continue_exception {
|
2016-08-12 18:38:43 +02:00
|
|
|
};
|
|
|
|
|
2021-03-27 00:26:59 +01:00
|
|
|
struct run_depth_guard {
|
|
|
|
run_depth_guard() = delete;
|
|
|
|
run_depth_guard(thread_state &ts);
|
|
|
|
run_depth_guard(run_depth_guard const &) = delete;
|
|
|
|
run_depth_guard(run_depth_guard &&) = delete;
|
|
|
|
~run_depth_guard();
|
2021-04-04 19:31:29 +02:00
|
|
|
|
|
|
|
thread_state *tsp;
|
2021-03-27 00:26:59 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
struct stack_guard {
|
|
|
|
thread_state *tsp;
|
|
|
|
std::size_t oldtop;
|
|
|
|
|
|
|
|
stack_guard() = delete;
|
|
|
|
stack_guard(thread_state &ts):
|
|
|
|
tsp{&ts}, oldtop{ts.vmstack.size()}
|
|
|
|
{}
|
|
|
|
|
|
|
|
~stack_guard() {
|
2021-04-11 03:32:14 +02:00
|
|
|
tsp->vmstack.resize(oldtop);
|
2021-03-27 00:26:59 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
stack_guard(stack_guard const &) = delete;
|
|
|
|
stack_guard(stack_guard &&) = delete;
|
|
|
|
};
|
|
|
|
|
2016-09-02 22:42:10 +02:00
|
|
|
template<typename F>
|
2021-03-25 01:37:13 +01:00
|
|
|
static void call_with_args(thread_state &ts, F body) {
|
|
|
|
if (!ts.callstack) {
|
2016-09-10 19:54:55 +02:00
|
|
|
body();
|
|
|
|
return;
|
|
|
|
}
|
2021-03-28 23:46:08 +02:00
|
|
|
auto mask = ts.callstack->usedargs;
|
2021-03-30 00:28:06 +02:00
|
|
|
std::size_t noff = ts.idstack.size();
|
2021-03-28 23:46:08 +02:00
|
|
|
for (std::size_t i = 0; mask.any(); ++i) {
|
|
|
|
if (mask[0]) {
|
2021-04-02 05:47:49 +02:00
|
|
|
auto &ast = ts.get_astack(
|
|
|
|
static_cast<alias *>(ts.istate->identmap[i])
|
2016-09-02 22:42:10 +02:00
|
|
|
);
|
2021-04-11 03:32:14 +02:00
|
|
|
auto &st = ts.idstack.emplace_back();
|
2021-04-02 05:47:49 +02:00
|
|
|
st.next = ast.node;
|
|
|
|
ast.node = ast.node->next;
|
2016-09-02 22:42:10 +02:00
|
|
|
}
|
2021-03-28 23:46:08 +02:00
|
|
|
mask >>= 1;
|
2016-09-02 22:42:10 +02:00
|
|
|
}
|
2021-03-25 01:37:13 +01:00
|
|
|
ident_link *prevstack = ts.callstack->next;
|
2021-03-23 23:29:32 +01:00
|
|
|
ident_link aliaslink = {
|
2021-03-25 01:37:13 +01:00
|
|
|
ts.callstack->id, ts.callstack,
|
2021-03-28 23:46:08 +02:00
|
|
|
prevstack ? prevstack->usedargs : argset{}
|
2016-09-02 22:42:10 +02:00
|
|
|
};
|
2021-03-28 23:46:08 +02:00
|
|
|
if (!prevstack) {
|
|
|
|
aliaslink.usedargs.set();
|
|
|
|
}
|
2021-03-25 01:37:13 +01:00
|
|
|
ts.callstack = &aliaslink;
|
2021-03-30 23:49:50 +02:00
|
|
|
auto cleanup = [&]() {
|
2016-09-15 04:30:37 +02:00
|
|
|
if (prevstack) {
|
|
|
|
prevstack->usedargs = aliaslink.usedargs;
|
|
|
|
}
|
2021-03-25 01:37:13 +01:00
|
|
|
ts.callstack = aliaslink.next;
|
2021-03-28 23:46:08 +02:00
|
|
|
auto mask2 = ts.callstack->usedargs;
|
2021-03-30 00:28:06 +02:00
|
|
|
for (std::size_t i = 0, nredo = 0; mask2.any(); ++i) {
|
2021-03-28 23:46:08 +02:00
|
|
|
if (mask2[0]) {
|
2021-04-02 05:47:49 +02:00
|
|
|
ts.get_astack(
|
|
|
|
static_cast<alias *>(ts.istate->identmap[i])
|
|
|
|
).node = ts.idstack[noff + nredo++].next;
|
2016-09-08 23:42:14 +02:00
|
|
|
}
|
2021-03-28 23:46:08 +02:00
|
|
|
mask2 >>= 1;
|
2016-09-02 22:42:10 +02:00
|
|
|
}
|
2021-04-11 03:32:14 +02:00
|
|
|
ts.idstack.resize(noff);
|
2021-03-30 23:49:50 +02:00
|
|
|
};
|
|
|
|
try {
|
|
|
|
body();
|
|
|
|
} catch (...) {
|
|
|
|
cleanup();
|
|
|
|
throw;
|
|
|
|
}
|
|
|
|
cleanup();
|
2016-09-02 22:42:10 +02:00
|
|
|
}
|
|
|
|
|
2021-03-27 00:26:59 +01:00
|
|
|
void exec_command(
|
2021-04-03 03:14:52 +02:00
|
|
|
thread_state &ts, command_impl *id, ident *self, any_value *args,
|
|
|
|
any_value &res, std::size_t nargs, bool lookup = false
|
2021-03-27 00:26:59 +01:00
|
|
|
);
|
|
|
|
|
2021-04-02 05:47:49 +02:00
|
|
|
bool exec_alias(
|
2021-03-27 00:26:59 +01:00
|
|
|
thread_state &ts, alias *a, any_value *args, any_value &result,
|
2021-04-02 05:47:49 +02:00
|
|
|
std::size_t callargs, std::size_t &nargs, std::size_t offset,
|
|
|
|
std::size_t skip, std::uint32_t op, bool ncheck = false
|
2021-03-27 00:26:59 +01:00
|
|
|
);
|
|
|
|
|
|
|
|
std::uint32_t *vm_exec(
|
|
|
|
thread_state &ts, std::uint32_t *code, any_value &result
|
|
|
|
);
|
|
|
|
|
2021-03-23 23:32:25 +01:00
|
|
|
} /* namespace cubescript */
|
2016-08-12 18:38:43 +02:00
|
|
|
|
2021-03-23 23:29:32 +01:00
|
|
|
#endif /* LIBCUBESCRIPT_VM_HH */
|