2016-08-12 18:38:43 +02:00
|
|
|
#ifndef LIBCUBESCRIPT_CS_VM_HH
|
|
|
|
#define LIBCUBESCRIPT_CS_VM_HH
|
|
|
|
|
2016-09-07 22:57:28 +02:00
|
|
|
#include "cubescript/cubescript.hh"
|
2016-08-12 18:38:43 +02:00
|
|
|
|
2017-02-14 18:33:45 +01:00
|
|
|
#include <cstdlib>
|
|
|
|
#include <array>
|
2017-04-23 15:34:45 +02:00
|
|
|
#include <vector>
|
2021-03-17 01:26:16 +01:00
|
|
|
#include <type_traits>
|
2016-08-12 18:38:43 +02:00
|
|
|
|
2016-09-08 23:42:14 +02:00
|
|
|
#include "cs_util.hh"
|
|
|
|
|
2016-08-12 18:38:43 +02:00
|
|
|
namespace cscript {
|
|
|
|
|
|
|
|
static constexpr int MaxArguments = 25;
|
|
|
|
static constexpr int MaxResults = 7;
|
|
|
|
|
2016-08-24 19:54:24 +02:00
|
|
|
static constexpr int DummyIdx = MaxArguments;
|
|
|
|
static constexpr int NumargsIdx = MaxArguments + 1;
|
|
|
|
static constexpr int DbgaliasIdx = MaxArguments + 2;
|
|
|
|
|
2016-08-12 18:38:43 +02:00
|
|
|
enum {
|
2016-09-07 20:20:36 +02:00
|
|
|
CsIdUnknown = -1, CsIdIvar, CsIdFvar, CsIdSvar, CsIdCommand, CsIdAlias,
|
2016-09-15 02:12:22 +02:00
|
|
|
CsIdLocal, CsIdDo, CsIdDoArgs, CsIdIf, CsIdBreak, CsIdContinue, CsIdResult,
|
|
|
|
CsIdNot, CsIdAnd, CsIdOr
|
2016-08-12 18:38:43 +02:00
|
|
|
};
|
|
|
|
|
2021-03-18 20:55:14 +01:00
|
|
|
struct cs_ident_link {
|
2017-02-13 18:10:40 +01:00
|
|
|
cs_ident *id;
|
2021-03-18 20:55:14 +01:00
|
|
|
cs_ident_link *next;
|
2016-09-10 20:03:58 +02:00
|
|
|
int usedargs;
|
2017-02-13 18:10:40 +01:00
|
|
|
cs_ident_stack *argstack;
|
2016-09-10 20:03:58 +02:00
|
|
|
};
|
|
|
|
|
2021-03-17 01:26:16 +01:00
|
|
|
template<typename T, std::size_t N>
|
|
|
|
struct cs_valarray {
|
|
|
|
cs_valarray(cs_state &cs) {
|
|
|
|
for (std::size_t i = 0; i < N; ++i) {
|
|
|
|
new (&stor[i]) T{cs};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
~cs_valarray() {
|
|
|
|
for (std::size_t i = 0; i < N; ++i) {
|
|
|
|
reinterpret_cast<T *>(&stor[i])->~T();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
T &operator[](std::size_t i) {
|
|
|
|
return *reinterpret_cast<T *>(&stor[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::aligned_storage_t<sizeof(T), alignof(T)> stor[N];
|
|
|
|
};
|
|
|
|
|
2016-08-30 23:30:40 +02:00
|
|
|
enum {
|
2021-03-18 20:55:14 +01:00
|
|
|
CS_VAL_NULL = 0, CS_VAL_INT, CS_VAL_FLOAT, CS_VAL_STRING,
|
|
|
|
CS_VAL_ANY, CS_VAL_CODE, CS_VAL_IDENT, CS_VAL_WORD,
|
|
|
|
CS_VAL_POP, CS_VAL_COND
|
2016-08-30 23:30:40 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
static const int cs_valtypet[] = {
|
2021-03-18 20:55:14 +01:00
|
|
|
CS_VAL_NULL, CS_VAL_INT, CS_VAL_FLOAT, CS_VAL_STRING,
|
|
|
|
CS_VAL_CODE, CS_VAL_IDENT
|
2016-08-30 23:30:40 +02:00
|
|
|
};
|
|
|
|
|
2017-02-13 18:10:40 +01:00
|
|
|
static inline int cs_vtype_to_int(cs_value_type v) {
|
2016-08-30 23:30:40 +02:00
|
|
|
return cs_valtypet[int(v)];
|
|
|
|
}
|
|
|
|
|
2016-09-07 18:58:56 +02:00
|
|
|
/* instruction: uint32 [length 24][retflag 2][opcode 6] */
|
2016-08-12 18:38:43 +02:00
|
|
|
enum {
|
2021-03-18 20:55:14 +01:00
|
|
|
CS_CODE_START = 0,
|
|
|
|
CS_CODE_OFFSET,
|
|
|
|
CS_CODE_NULL, CS_CODE_TRUE, CS_CODE_FALSE, CS_CODE_NOT,
|
|
|
|
CS_CODE_POP,
|
|
|
|
CS_CODE_ENTER, CS_CODE_ENTER_RESULT,
|
|
|
|
CS_CODE_EXIT, CS_CODE_RESULT_ARG,
|
|
|
|
CS_CODE_VAL, CS_CODE_VAL_INT,
|
|
|
|
CS_CODE_DUP,
|
|
|
|
CS_CODE_BOOL,
|
|
|
|
CS_CODE_BLOCK, CS_CODE_EMPTY,
|
|
|
|
CS_CODE_COMPILE, CS_CODE_COND,
|
|
|
|
CS_CODE_FORCE,
|
|
|
|
CS_CODE_RESULT,
|
|
|
|
CS_CODE_IDENT, CS_CODE_IDENT_U, CS_CODE_IDENT_ARG,
|
|
|
|
CS_CODE_COM, CS_CODE_COM_C, CS_CODE_COM_V,
|
|
|
|
CS_CODE_CONC, CS_CODE_CONC_W, CS_CODE_CONC_M,
|
|
|
|
CS_CODE_SVAR, CS_CODE_SVAR1,
|
|
|
|
CS_CODE_IVAR, CS_CODE_IVAR1, CS_CODE_IVAR2, CS_CODE_IVAR3,
|
|
|
|
CS_CODE_FVAR, CS_CODE_FVAR1,
|
|
|
|
CS_CODE_LOOKUP, CS_CODE_LOOKUP_U, CS_CODE_LOOKUP_ARG,
|
|
|
|
CS_CODE_LOOKUP_M, CS_CODE_LOOKUP_MU, CS_CODE_LOOKUP_MARG,
|
|
|
|
CS_CODE_ALIAS, CS_CODE_ALIAS_U, CS_CODE_ALIAS_ARG,
|
|
|
|
CS_CODE_CALL, CS_CODE_CALL_U, CS_CODE_CALL_ARG,
|
|
|
|
CS_CODE_PRINT,
|
|
|
|
CS_CODE_LOCAL,
|
|
|
|
CS_CODE_DO, CS_CODE_DO_ARGS,
|
|
|
|
CS_CODE_JUMP, CS_CODE_JUMP_B, CS_CODE_JUMP_RESULT,
|
|
|
|
CS_CODE_BREAK,
|
|
|
|
|
|
|
|
CS_CODE_OP_MASK = 0x3F,
|
|
|
|
CS_CODE_RET = 6,
|
|
|
|
CS_CODE_RET_MASK = 0xC0,
|
2016-08-12 18:38:43 +02:00
|
|
|
|
|
|
|
/* return type flags */
|
2021-03-18 20:55:14 +01:00
|
|
|
CS_RET_NULL = CS_VAL_NULL << CS_CODE_RET,
|
|
|
|
CS_RET_STRING = CS_VAL_STRING << CS_CODE_RET,
|
|
|
|
CS_RET_INT = CS_VAL_INT << CS_CODE_RET,
|
|
|
|
CS_RET_FLOAT = CS_VAL_FLOAT << CS_CODE_RET,
|
|
|
|
|
|
|
|
/* CS_CODE_JUMP_B, CS_CODE_JUMP_RESULT */
|
|
|
|
CS_CODE_FLAG_TRUE = 1 << CS_CODE_RET,
|
|
|
|
CS_CODE_FLAG_FALSE = 0 << CS_CODE_RET
|
2016-08-12 18:38:43 +02:00
|
|
|
};
|
|
|
|
|
2016-09-14 23:24:13 +02:00
|
|
|
struct CsBreakException {
|
|
|
|
};
|
|
|
|
|
|
|
|
struct CsContinueException {
|
|
|
|
};
|
|
|
|
|
2016-09-09 17:43:23 +02:00
|
|
|
template<typename T>
|
2017-01-25 02:09:50 +01:00
|
|
|
constexpr size_t CsTypeStorageSize =
|
2017-01-25 02:10:17 +01:00
|
|
|
(sizeof(T) - 1) / sizeof(uint32_t) + 1;
|
2016-09-09 17:43:23 +02:00
|
|
|
|
2017-02-13 18:10:40 +01:00
|
|
|
struct cs_gen_state {
|
|
|
|
cs_state &cs;
|
|
|
|
cs_gen_state *prevps;
|
2016-09-29 21:21:21 +02:00
|
|
|
bool parsing = true;
|
2021-03-19 22:49:29 +01:00
|
|
|
cs_valbuf<uint32_t> code;
|
2017-02-16 19:07:22 +01:00
|
|
|
ostd::string_range source;
|
2017-01-25 02:09:50 +01:00
|
|
|
size_t current_line;
|
2017-02-16 19:07:22 +01:00
|
|
|
ostd::string_range src_name;
|
2016-08-12 18:38:43 +02:00
|
|
|
|
2017-02-13 18:10:40 +01:00
|
|
|
cs_gen_state() = delete;
|
|
|
|
cs_gen_state(cs_state &csr):
|
2021-03-19 22:49:29 +01:00
|
|
|
cs(csr), prevps(csr.p_pstate), code{cs},
|
2016-09-29 21:21:21 +02:00
|
|
|
source(nullptr), current_line(1), src_name()
|
|
|
|
{
|
|
|
|
csr.p_pstate = this;
|
|
|
|
}
|
|
|
|
|
2017-02-13 18:10:40 +01:00
|
|
|
~cs_gen_state() {
|
2016-09-29 21:21:21 +02:00
|
|
|
done();
|
|
|
|
}
|
|
|
|
|
|
|
|
void done() {
|
|
|
|
if (!parsing) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
cs.p_pstate = prevps;
|
|
|
|
parsing = false;
|
|
|
|
}
|
2016-08-12 18:38:43 +02:00
|
|
|
|
2017-02-16 19:07:22 +01:00
|
|
|
ostd::string_range get_str();
|
2021-03-19 22:25:38 +01:00
|
|
|
cs_charbuf get_str_dup();
|
2016-09-20 22:11:40 +02:00
|
|
|
|
2017-02-16 19:07:22 +01:00
|
|
|
ostd::string_range get_word();
|
2016-09-20 22:11:40 +02:00
|
|
|
|
2021-03-17 20:40:32 +01:00
|
|
|
void gen_str(ostd::string_range word) {
|
|
|
|
if (word.size() <= 3) {
|
2021-03-18 20:55:14 +01:00
|
|
|
uint32_t op = CS_CODE_VAL_INT | CS_RET_STRING;
|
2017-01-25 02:09:50 +01:00
|
|
|
for (size_t i = 0; i < word.size(); ++i) {
|
2017-04-04 00:28:56 +02:00
|
|
|
op |= uint32_t(
|
|
|
|
static_cast<unsigned char>(word[i])
|
|
|
|
) << ((i + 1) * 8);
|
2016-08-17 05:02:53 +02:00
|
|
|
}
|
2017-01-25 01:18:29 +01:00
|
|
|
code.push_back(op);
|
2016-08-12 18:38:43 +02:00
|
|
|
return;
|
|
|
|
}
|
2021-03-18 20:55:14 +01:00
|
|
|
code.push_back(CS_CODE_VAL | CS_RET_STRING | (word.size() << 8));
|
2017-01-25 02:10:17 +01:00
|
|
|
auto it = reinterpret_cast<uint32_t const *>(word.data());
|
2021-03-19 22:49:29 +01:00
|
|
|
code.append(it, it + (word.size() / sizeof(uint32_t)));
|
2017-01-25 02:10:17 +01:00
|
|
|
size_t esz = word.size() % sizeof(uint32_t);
|
2016-08-12 18:38:43 +02:00
|
|
|
union {
|
2017-01-25 02:10:17 +01:00
|
|
|
char c[sizeof(uint32_t)];
|
|
|
|
uint32_t u;
|
2016-08-12 18:38:43 +02:00
|
|
|
} end;
|
|
|
|
end.u = 0;
|
|
|
|
memcpy(end.c, word.data() + word.size() - esz, esz);
|
2017-01-25 01:18:29 +01:00
|
|
|
code.push_back(end.u);
|
2016-08-12 18:38:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void gen_str() {
|
2021-03-18 20:55:14 +01:00
|
|
|
code.push_back(CS_CODE_VAL_INT | CS_RET_STRING);
|
2016-08-12 18:38:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void gen_null() {
|
2021-03-18 20:55:14 +01:00
|
|
|
code.push_back(CS_CODE_VAL_INT | CS_RET_NULL);
|
2016-08-12 18:38:43 +02:00
|
|
|
}
|
|
|
|
|
2017-02-13 18:10:40 +01:00
|
|
|
void gen_int(cs_int i = 0) {
|
2016-08-17 05:02:53 +02:00
|
|
|
if (i >= -0x800000 && i <= 0x7FFFFF) {
|
2021-03-18 20:55:14 +01:00
|
|
|
code.push_back(CS_CODE_VAL_INT | CS_RET_INT | (i << 8));
|
2016-08-17 05:02:53 +02:00
|
|
|
} else {
|
2016-09-09 17:43:23 +02:00
|
|
|
union {
|
2017-02-13 18:10:40 +01:00
|
|
|
cs_int i;
|
|
|
|
uint32_t u[CsTypeStorageSize<cs_int>];
|
2016-09-09 17:43:23 +02:00
|
|
|
} c;
|
|
|
|
c.i = i;
|
2021-03-18 20:55:14 +01:00
|
|
|
code.push_back(CS_CODE_VAL | CS_RET_INT);
|
2021-03-19 22:49:29 +01:00
|
|
|
code.append(c.u, c.u + CsTypeStorageSize<cs_int>);
|
2016-08-12 18:38:43 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-16 19:07:22 +01:00
|
|
|
void gen_int(ostd::string_range word);
|
2016-08-12 18:38:43 +02:00
|
|
|
|
2017-02-13 18:10:40 +01:00
|
|
|
void gen_float(cs_float f = 0.0f) {
|
|
|
|
if (cs_int(f) == f && f >= -0x800000 && f <= 0x7FFFFF) {
|
2021-03-18 20:55:14 +01:00
|
|
|
code.push_back(CS_CODE_VAL_INT | CS_RET_FLOAT | (cs_int(f) << 8));
|
2016-08-17 05:02:53 +02:00
|
|
|
} else {
|
2016-08-12 18:38:43 +02:00
|
|
|
union {
|
2017-02-13 18:10:40 +01:00
|
|
|
cs_float f;
|
|
|
|
uint32_t u[CsTypeStorageSize<cs_float>];
|
2016-08-12 18:38:43 +02:00
|
|
|
} c;
|
|
|
|
c.f = f;
|
2021-03-18 20:55:14 +01:00
|
|
|
code.push_back(CS_CODE_VAL | CS_RET_FLOAT);
|
2021-03-19 22:49:29 +01:00
|
|
|
code.append(c.u, c.u + CsTypeStorageSize<cs_float>);
|
2016-08-12 18:38:43 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-16 19:07:22 +01:00
|
|
|
void gen_float(ostd::string_range word);
|
2016-08-12 18:38:43 +02:00
|
|
|
|
2017-02-13 18:10:40 +01:00
|
|
|
void gen_ident(cs_ident *id) {
|
2017-01-25 01:18:29 +01:00
|
|
|
code.push_back(
|
2016-08-18 03:53:51 +02:00
|
|
|
((id->get_index() < MaxArguments)
|
2021-03-18 20:55:14 +01:00
|
|
|
? CS_CODE_IDENT_ARG
|
|
|
|
: CS_CODE_IDENT
|
2016-08-18 03:53:51 +02:00
|
|
|
) | (id->get_index() << 8)
|
2016-08-17 05:02:53 +02:00
|
|
|
);
|
2016-08-12 18:38:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void gen_ident() {
|
2016-09-12 20:04:59 +02:00
|
|
|
gen_ident(cs.p_state->identmap[DummyIdx]);
|
2016-08-12 18:38:43 +02:00
|
|
|
}
|
|
|
|
|
2017-02-16 19:07:22 +01:00
|
|
|
void gen_ident(ostd::string_range word) {
|
2016-08-12 18:38:43 +02:00
|
|
|
gen_ident(cs.new_ident(word));
|
|
|
|
}
|
|
|
|
|
2016-08-17 05:02:53 +02:00
|
|
|
void gen_value(
|
2017-02-16 19:07:22 +01:00
|
|
|
int wordtype, ostd::string_range word = ostd::string_range(),
|
2016-09-22 01:44:35 +02:00
|
|
|
int line = 0
|
2016-08-17 05:02:53 +02:00
|
|
|
);
|
2016-08-12 18:38:43 +02:00
|
|
|
|
2021-03-18 20:55:14 +01:00
|
|
|
void gen_main(ostd::string_range s, int ret_type = CS_VAL_ANY);
|
2016-08-12 18:38:43 +02:00
|
|
|
|
2016-09-22 01:19:29 +02:00
|
|
|
void next_char() {
|
|
|
|
if (source.empty()) {
|
|
|
|
return;
|
|
|
|
}
|
2016-09-22 01:44:35 +02:00
|
|
|
if (*source == '\n') {
|
|
|
|
++current_line;
|
|
|
|
}
|
2016-09-22 01:19:29 +02:00
|
|
|
source.pop_front();
|
2016-08-12 18:38:43 +02:00
|
|
|
}
|
|
|
|
|
2017-01-25 02:09:50 +01:00
|
|
|
char current(size_t ahead = 0) {
|
2016-09-22 01:15:51 +02:00
|
|
|
if (source.size() <= ahead) {
|
|
|
|
return '\0';
|
|
|
|
}
|
2016-09-22 00:20:23 +02:00
|
|
|
return source[ahead];
|
2016-08-12 18:38:43 +02:00
|
|
|
}
|
2016-09-22 00:20:23 +02:00
|
|
|
|
2017-02-16 19:07:22 +01:00
|
|
|
ostd::string_range read_macro_name();
|
2016-09-22 00:20:23 +02:00
|
|
|
|
2017-02-16 19:07:22 +01:00
|
|
|
char skip_until(ostd::string_range chars);
|
2016-09-22 00:20:23 +02:00
|
|
|
char skip_until(char cf);
|
|
|
|
|
|
|
|
void skip_comments();
|
2016-08-12 18:38:43 +02:00
|
|
|
};
|
|
|
|
|
2017-02-16 19:07:22 +01:00
|
|
|
bool cs_check_num(ostd::string_range s);
|
2016-08-12 18:38:43 +02:00
|
|
|
|
2017-01-25 02:10:17 +01:00
|
|
|
static inline void bcode_incr(uint32_t *bc) {
|
2016-08-13 01:26:16 +02:00
|
|
|
*bc += 0x100;
|
|
|
|
}
|
|
|
|
|
2017-01-25 02:10:17 +01:00
|
|
|
static inline void bcode_decr(uint32_t *bc) {
|
2016-08-13 01:26:16 +02:00
|
|
|
*bc -= 0x100;
|
2017-01-30 19:38:11 +01:00
|
|
|
if (std::int32_t(*bc) < 0x100) {
|
2016-08-13 01:26:16 +02:00
|
|
|
delete[] bc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-13 18:10:40 +01:00
|
|
|
static inline bool cs_is_arg_used(cs_state &cs, cs_ident *id) {
|
2016-09-10 19:54:55 +02:00
|
|
|
if (!cs.p_callstack) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return cs.p_callstack->usedargs & (1 << id->get_index());
|
|
|
|
}
|
|
|
|
|
2018-04-27 23:53:55 +02:00
|
|
|
struct cs_alias_internal {
|
2016-09-02 22:42:10 +02:00
|
|
|
static void push_arg(
|
2017-02-13 18:10:40 +01:00
|
|
|
cs_alias *a, cs_value &v, cs_ident_stack &st, bool um = true
|
2016-09-02 22:42:10 +02:00
|
|
|
) {
|
|
|
|
if (a->p_astack == &st) {
|
|
|
|
/* prevent cycles and unnecessary code elsewhere */
|
2017-01-25 01:57:33 +01:00
|
|
|
a->p_val = std::move(v);
|
2016-09-02 22:42:10 +02:00
|
|
|
clean_code(a);
|
|
|
|
return;
|
|
|
|
}
|
2017-01-25 01:57:33 +01:00
|
|
|
st.val_s = std::move(a->p_val);
|
2016-09-02 22:42:10 +02:00
|
|
|
st.next = a->p_astack;
|
|
|
|
a->p_astack = &st;
|
2017-01-25 01:57:33 +01:00
|
|
|
a->p_val = std::move(v);
|
2016-09-02 22:42:10 +02:00
|
|
|
clean_code(a);
|
|
|
|
if (um) {
|
2017-02-13 18:10:40 +01:00
|
|
|
a->p_flags &= ~CS_IDF_UNKNOWN;
|
2016-09-02 22:42:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-13 18:10:40 +01:00
|
|
|
static void pop_arg(cs_alias *a) {
|
2016-09-02 22:42:10 +02:00
|
|
|
if (!a->p_astack) {
|
|
|
|
return;
|
|
|
|
}
|
2017-02-13 18:10:40 +01:00
|
|
|
cs_ident_stack *st = a->p_astack;
|
2017-01-25 01:57:33 +01:00
|
|
|
a->p_val = std::move(a->p_astack->val_s);
|
2016-09-02 22:42:10 +02:00
|
|
|
clean_code(a);
|
|
|
|
a->p_astack = st->next;
|
|
|
|
}
|
|
|
|
|
2017-02-13 18:10:40 +01:00
|
|
|
static void undo_arg(cs_alias *a, cs_ident_stack &st) {
|
|
|
|
cs_ident_stack *prev = a->p_astack;
|
2017-01-25 01:57:33 +01:00
|
|
|
st.val_s = std::move(a->p_val);
|
2016-09-02 22:42:10 +02:00
|
|
|
st.next = prev;
|
|
|
|
a->p_astack = prev->next;
|
2017-01-25 01:57:33 +01:00
|
|
|
a->p_val = std::move(prev->val_s);
|
2016-09-02 22:42:10 +02:00
|
|
|
clean_code(a);
|
|
|
|
}
|
|
|
|
|
2017-02-13 18:10:40 +01:00
|
|
|
static void redo_arg(cs_alias *a, cs_ident_stack &st) {
|
|
|
|
cs_ident_stack *prev = st.next;
|
2017-01-25 01:57:33 +01:00
|
|
|
prev->val_s = std::move(a->p_val);
|
2016-09-02 22:42:10 +02:00
|
|
|
a->p_astack = prev;
|
2017-01-25 01:57:33 +01:00
|
|
|
a->p_val = std::move(st.val_s);
|
2016-09-02 22:42:10 +02:00
|
|
|
clean_code(a);
|
|
|
|
}
|
|
|
|
|
2017-02-13 18:10:40 +01:00
|
|
|
static void set_arg(cs_alias *a, cs_state &cs, cs_value &v) {
|
2016-09-10 19:54:55 +02:00
|
|
|
if (cs_is_arg_used(cs, a)) {
|
2017-01-25 01:57:33 +01:00
|
|
|
a->p_val = std::move(v);
|
2016-09-02 22:42:10 +02:00
|
|
|
clean_code(a);
|
|
|
|
} else {
|
2016-09-08 21:30:08 +02:00
|
|
|
push_arg(a, v, cs.p_callstack->argstack[a->get_index()], false);
|
|
|
|
cs.p_callstack->usedargs |= 1 << a->get_index();
|
2016-09-02 22:42:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-13 18:10:40 +01:00
|
|
|
static void set_alias(cs_alias *a, cs_state &cs, cs_value &v) {
|
2017-01-25 01:57:33 +01:00
|
|
|
a->p_val = std::move(v);
|
2016-09-02 22:42:10 +02:00
|
|
|
clean_code(a);
|
|
|
|
a->p_flags = (a->p_flags & cs.identflags) | cs.identflags;
|
|
|
|
}
|
|
|
|
|
2017-02-13 18:10:40 +01:00
|
|
|
static void clean_code(cs_alias *a) {
|
2017-01-25 02:10:17 +01:00
|
|
|
uint32_t *bcode = reinterpret_cast<uint32_t *>(a->p_acode);
|
2016-09-02 22:42:10 +02:00
|
|
|
if (bcode) {
|
|
|
|
bcode_decr(bcode);
|
|
|
|
a->p_acode = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-13 18:10:40 +01:00
|
|
|
static cs_bcode *compile_code(cs_alias *a, cs_state &cs) {
|
2016-09-02 22:42:10 +02:00
|
|
|
if (!a->p_acode) {
|
2017-02-13 18:10:40 +01:00
|
|
|
cs_gen_state gs(cs);
|
2016-09-02 22:42:10 +02:00
|
|
|
gs.code.reserve(64);
|
|
|
|
gs.gen_main(a->get_value().get_str());
|
2017-01-25 01:18:29 +01:00
|
|
|
/* i wish i could steal the memory somehow */
|
2017-01-25 02:10:17 +01:00
|
|
|
uint32_t *code = new uint32_t[gs.code.size()];
|
2017-01-25 01:18:29 +01:00
|
|
|
memcpy(code, gs.code.data(), gs.code.size() * sizeof(uint32_t));
|
2016-09-02 22:42:10 +02:00
|
|
|
bcode_incr(code);
|
2017-02-13 18:10:40 +01:00
|
|
|
a->p_acode = reinterpret_cast<cs_bcode *>(code);
|
2016-09-02 22:42:10 +02:00
|
|
|
}
|
|
|
|
return a->p_acode;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename F>
|
2017-02-13 18:10:40 +01:00
|
|
|
static void cs_do_args(cs_state &cs, F body) {
|
2016-09-10 19:54:55 +02:00
|
|
|
if (!cs.p_callstack) {
|
|
|
|
body();
|
|
|
|
return;
|
|
|
|
}
|
2021-03-17 01:26:16 +01:00
|
|
|
cs_valarray<cs_ident_stack, MaxArguments> argstack{cs};
|
2016-09-08 21:30:08 +02:00
|
|
|
int argmask1 = cs.p_callstack->usedargs;
|
2016-09-02 22:42:10 +02:00
|
|
|
for (int i = 0; argmask1; argmask1 >>= 1, ++i) {
|
|
|
|
if (argmask1 & 1) {
|
2018-04-27 23:53:55 +02:00
|
|
|
cs_alias_internal::undo_arg(
|
2017-02-13 18:10:40 +01:00
|
|
|
static_cast<cs_alias *>(cs.p_state->identmap[i]), argstack[i]
|
2016-09-02 22:42:10 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2021-03-18 20:55:14 +01:00
|
|
|
cs_ident_link *prevstack = cs.p_callstack->next;
|
|
|
|
cs_ident_link aliaslink = {
|
2016-09-15 04:30:37 +02:00
|
|
|
cs.p_callstack->id, cs.p_callstack,
|
|
|
|
prevstack ? prevstack->usedargs : ((1 << MaxArguments) - 1),
|
|
|
|
prevstack ? prevstack->argstack : nullptr
|
2016-09-02 22:42:10 +02:00
|
|
|
};
|
2016-09-08 21:30:08 +02:00
|
|
|
cs.p_callstack = &aliaslink;
|
2017-01-25 01:57:33 +01:00
|
|
|
cs_do_and_cleanup(std::move(body), [&]() {
|
2016-09-15 04:30:37 +02:00
|
|
|
if (prevstack) {
|
|
|
|
prevstack->usedargs = aliaslink.usedargs;
|
|
|
|
}
|
2016-09-08 23:42:14 +02:00
|
|
|
cs.p_callstack = aliaslink.next;
|
|
|
|
int argmask2 = cs.p_callstack->usedargs;
|
|
|
|
for (int i = 0; argmask2; argmask2 >>= 1, ++i) {
|
|
|
|
if (argmask2 & 1) {
|
2018-04-27 23:53:55 +02:00
|
|
|
cs_alias_internal::redo_arg(
|
2017-02-13 18:10:40 +01:00
|
|
|
static_cast<cs_alias *>(cs.p_state->identmap[i]), argstack[i]
|
2016-09-08 23:42:14 +02:00
|
|
|
);
|
|
|
|
}
|
2016-09-02 22:42:10 +02:00
|
|
|
}
|
2016-09-08 23:42:14 +02:00
|
|
|
});
|
2016-09-02 22:42:10 +02:00
|
|
|
}
|
|
|
|
|
2017-02-13 18:10:40 +01:00
|
|
|
cs_bcode *cs_copy_code(cs_bcode *c);
|
2016-09-06 20:06:49 +02:00
|
|
|
|
2016-08-12 18:38:43 +02:00
|
|
|
} /* namespace cscript */
|
|
|
|
|
|
|
|
#endif /* LIBCUBESCRIPT_CS_VM_HH */
|