remove cs_ namespace in all API
parent
b3b4624af1
commit
b9b344cba6
File diff suppressed because it is too large
Load Diff
|
@ -2,12 +2,12 @@
|
|||
#define LIBCUBESCRIPT_CUBESCRIPT_CONF_HH
|
||||
|
||||
namespace cscript {
|
||||
using cs_int = int;
|
||||
using cs_float = float;
|
||||
using integer_type = int;
|
||||
using float_type = float;
|
||||
|
||||
constexpr auto const CS_INT_FORMAT = "%d";
|
||||
constexpr auto const CS_FLOAT_FORMAT = "%.7g";
|
||||
constexpr auto const CS_ROUND_FLOAT_FORMAT = "%.1f";
|
||||
constexpr auto const INT_FORMAT = "%d";
|
||||
constexpr auto const FLOAT_FORMAT = "%.7g";
|
||||
constexpr auto const ROUND_FLOAT_FORMAT = "%.1f";
|
||||
} /* namespace cscript */
|
||||
|
||||
#endif /* LIBCUBESCRIPT_CUBESCRIPT_CONF_HH */
|
||||
|
|
|
@ -5,29 +5,29 @@ namespace cscript {
|
|||
|
||||
/* public API impls */
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_bcode_ref::cs_bcode_ref(cs_bcode *v): p_code(v) {
|
||||
bcode_ref(v->get_raw());
|
||||
LIBCUBESCRIPT_EXPORT bcode_ref::bcode_ref(bcode *v): p_code(v) {
|
||||
bcode_addref(v->get_raw());
|
||||
}
|
||||
LIBCUBESCRIPT_EXPORT cs_bcode_ref::cs_bcode_ref(cs_bcode_ref const &v):
|
||||
LIBCUBESCRIPT_EXPORT bcode_ref::bcode_ref(bcode_ref const &v):
|
||||
p_code(v.p_code)
|
||||
{
|
||||
bcode_ref(p_code->get_raw());
|
||||
bcode_addref(p_code->get_raw());
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_bcode_ref::~cs_bcode_ref() {
|
||||
LIBCUBESCRIPT_EXPORT bcode_ref::~bcode_ref() {
|
||||
bcode_unref(p_code->get_raw());
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_bcode_ref &cs_bcode_ref::operator=(
|
||||
cs_bcode_ref const &v
|
||||
LIBCUBESCRIPT_EXPORT bcode_ref &bcode_ref::operator=(
|
||||
bcode_ref const &v
|
||||
) {
|
||||
bcode_unref(p_code->get_raw());
|
||||
p_code = v.p_code;
|
||||
bcode_ref(p_code->get_raw());
|
||||
bcode_addref(p_code->get_raw());
|
||||
return *this;
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_bcode_ref &cs_bcode_ref::operator=(cs_bcode_ref &&v) {
|
||||
LIBCUBESCRIPT_EXPORT bcode_ref &bcode_ref::operator=(bcode_ref &&v) {
|
||||
bcode_unref(p_code->get_raw());
|
||||
p_code = v.p_code;
|
||||
v.p_code = nullptr;
|
||||
|
@ -37,18 +37,18 @@ LIBCUBESCRIPT_EXPORT cs_bcode_ref &cs_bcode_ref::operator=(cs_bcode_ref &&v) {
|
|||
/* private funcs */
|
||||
|
||||
struct bcode_hdr {
|
||||
cs_shared_state *cs; /* needed to construct the allocator */
|
||||
internal_state *cs; /* needed to construct the allocator */
|
||||
std::size_t asize; /* alloc size of the bytecode block */
|
||||
cs_bcode bc; /* CS_CODE_START + refcount */
|
||||
bcode bc; /* BC_INST_START + refcount */
|
||||
};
|
||||
|
||||
/* returned address is the 'init' member of the header */
|
||||
std::uint32_t *bcode_alloc(cs_state &cs, std::size_t sz) {
|
||||
auto a = cs_allocator<std::uint32_t>{cs};
|
||||
std::uint32_t *bcode_alloc(state &cs, std::size_t sz) {
|
||||
auto a = std_allocator<std::uint32_t>{cs};
|
||||
std::size_t hdrs = sizeof(bcode_hdr) / sizeof(std::uint32_t);
|
||||
auto p = a.allocate(sz + hdrs - 1);
|
||||
bcode_hdr *hdr = reinterpret_cast<bcode_hdr *>(p);
|
||||
hdr->cs = cs_get_sstate(cs);
|
||||
hdr->cs = state_get_internal(cs);
|
||||
hdr->asize = sz + hdrs - 1;
|
||||
return p + hdrs - 1;
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ std::uint32_t *bcode_alloc(cs_state &cs, std::size_t sz) {
|
|||
static inline void bcode_free(std::uint32_t *bc) {
|
||||
auto *rp = bc + 1 - (sizeof(bcode_hdr) / sizeof(std::uint32_t));
|
||||
bcode_hdr *hdr = reinterpret_cast<bcode_hdr *>(rp);
|
||||
cs_allocator<std::uint32_t>{hdr->cs}.deallocate(rp, hdr->asize);
|
||||
std_allocator<std::uint32_t>{hdr->cs}.deallocate(rp, hdr->asize);
|
||||
}
|
||||
|
||||
void bcode_incr(std::uint32_t *bc) {
|
||||
|
@ -71,19 +71,19 @@ void bcode_decr(std::uint32_t *bc) {
|
|||
}
|
||||
}
|
||||
|
||||
void bcode_ref(std::uint32_t *code) {
|
||||
void bcode_addref(std::uint32_t *code) {
|
||||
if (!code) {
|
||||
return;
|
||||
}
|
||||
if ((*code & CS_CODE_OP_MASK) == CS_CODE_START) {
|
||||
if ((*code & BC_INST_OP_MASK) == BC_INST_START) {
|
||||
bcode_incr(code);
|
||||
return;
|
||||
}
|
||||
switch (code[-1]&CS_CODE_OP_MASK) {
|
||||
case CS_CODE_START:
|
||||
switch (code[-1]&BC_INST_OP_MASK) {
|
||||
case BC_INST_START:
|
||||
bcode_incr(&code[-1]);
|
||||
break;
|
||||
case CS_CODE_OFFSET:
|
||||
case BC_INST_OFFSET:
|
||||
code -= std::ptrdiff_t(code[-1] >> 8);
|
||||
bcode_incr(code);
|
||||
break;
|
||||
|
@ -94,15 +94,15 @@ void bcode_unref(std::uint32_t *code) {
|
|||
if (!code) {
|
||||
return;
|
||||
}
|
||||
if ((*code & CS_CODE_OP_MASK) == CS_CODE_START) {
|
||||
if ((*code & BC_INST_OP_MASK) == BC_INST_START) {
|
||||
bcode_decr(code);
|
||||
return;
|
||||
}
|
||||
switch (code[-1]&CS_CODE_OP_MASK) {
|
||||
case CS_CODE_START:
|
||||
switch (code[-1]&BC_INST_OP_MASK) {
|
||||
case BC_INST_START:
|
||||
bcode_decr(&code[-1]);
|
||||
break;
|
||||
case CS_CODE_OFFSET:
|
||||
case BC_INST_OFFSET:
|
||||
code -= std::ptrdiff_t(code[-1] >> 8);
|
||||
bcode_decr(code);
|
||||
break;
|
||||
|
@ -111,25 +111,25 @@ void bcode_unref(std::uint32_t *code) {
|
|||
|
||||
/* empty fallbacks */
|
||||
|
||||
static std::uint32_t emptyrets[CS_VAL_ANY] = {
|
||||
CS_RET_NULL, CS_RET_INT, CS_RET_FLOAT, CS_RET_STRING
|
||||
static std::uint32_t emptyrets[VAL_ANY] = {
|
||||
BC_RET_NULL, BC_RET_INT, BC_RET_FLOAT, BC_RET_STRING
|
||||
};
|
||||
|
||||
empty_block *bcode_init_empty(cs_shared_state *cs) {
|
||||
auto a = cs_allocator<empty_block>{cs};
|
||||
auto *p = a.allocate(CS_VAL_ANY);
|
||||
for (std::size_t i = 0; i < CS_VAL_ANY; ++i) {
|
||||
p[i].init.init = CS_CODE_START + 0x100;
|
||||
p[i].code = CS_CODE_EXIT | emptyrets[i];
|
||||
empty_block *bcode_init_empty(internal_state *cs) {
|
||||
auto a = std_allocator<empty_block>{cs};
|
||||
auto *p = a.allocate(VAL_ANY);
|
||||
for (std::size_t i = 0; i < VAL_ANY; ++i) {
|
||||
p[i].init.init = BC_INST_START + 0x100;
|
||||
p[i].code = BC_INST_EXIT | emptyrets[i];
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
void bcode_free_empty(cs_shared_state *cs, empty_block *empty) {
|
||||
cs_allocator<empty_block>{cs}.deallocate(empty, CS_VAL_ANY);
|
||||
void bcode_free_empty(internal_state *cs, empty_block *empty) {
|
||||
std_allocator<empty_block>{cs}.deallocate(empty, VAL_ANY);
|
||||
};
|
||||
|
||||
cs_bcode *bcode_get_empty(empty_block *empty, std::size_t val) {
|
||||
bcode *bcode_get_empty(empty_block *empty, std::size_t val) {
|
||||
return &empty[val].init + 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
namespace cscript {
|
||||
|
||||
struct cs_bcode {
|
||||
struct bcode {
|
||||
std::uint32_t init;
|
||||
|
||||
std::uint32_t *get_raw() {
|
||||
|
@ -21,72 +21,72 @@ struct cs_bcode {
|
|||
};
|
||||
|
||||
enum {
|
||||
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
|
||||
VAL_NULL = 0, VAL_INT, VAL_FLOAT, VAL_STRING,
|
||||
VAL_ANY, VAL_CODE, VAL_IDENT, VAL_WORD,
|
||||
VAL_POP, VAL_COND
|
||||
};
|
||||
|
||||
/* instruction: uint32 [length 24][retflag 2][opcode 6] */
|
||||
enum {
|
||||
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,
|
||||
BC_INST_START = 0,
|
||||
BC_INST_OFFSET,
|
||||
BC_INST_NULL, BC_INST_TRUE, BC_INST_FALSE, BC_INST_NOT,
|
||||
BC_INST_POP,
|
||||
BC_INST_ENTER, BC_INST_ENTER_RESULT,
|
||||
BC_INST_EXIT, BC_INST_RESULT_ARG,
|
||||
BC_INST_VAL, BC_INST_VAL_INT,
|
||||
BC_INST_DUP,
|
||||
BC_INST_BOOL,
|
||||
BC_INST_BLOCK, BC_INST_EMPTY,
|
||||
BC_INST_COMPILE, BC_INST_COND,
|
||||
BC_INST_FORCE,
|
||||
BC_INST_RESULT,
|
||||
BC_INST_IDENT, BC_INST_IDENT_U, BC_INST_IDENT_ARG,
|
||||
BC_INST_COM, BC_INST_COM_C, BC_INST_COM_V,
|
||||
BC_INST_CONC, BC_INST_CONC_W, BC_INST_CONC_M,
|
||||
BC_INST_SVAR, BC_INST_SVAR1,
|
||||
BC_INST_IVAR, BC_INST_IVAR1, BC_INST_IVAR2, BC_INST_IVAR3,
|
||||
BC_INST_FVAR, BC_INST_FVAR1,
|
||||
BC_INST_LOOKUP, BC_INST_LOOKUP_U, BC_INST_LOOKUP_ARG,
|
||||
BC_INST_LOOKUP_M, BC_INST_LOOKUP_MU, BC_INST_LOOKUP_MARG,
|
||||
BC_INST_ALIAS, BC_INST_ALIAS_U, BC_INST_ALIAS_ARG,
|
||||
BC_INST_CALL, BC_INST_CALL_U, BC_INST_CALL_ARG,
|
||||
BC_INST_PRINT,
|
||||
BC_INST_LOCAL,
|
||||
BC_INST_DO, BC_INST_DO_ARGS,
|
||||
BC_INST_JUMP, BC_INST_JUMP_B, BC_INST_JUMP_RESULT,
|
||||
BC_INST_BREAK,
|
||||
|
||||
CS_CODE_OP_MASK = 0x3F,
|
||||
CS_CODE_RET = 6,
|
||||
CS_CODE_RET_MASK = 0xC0,
|
||||
BC_INST_OP_MASK = 0x3F,
|
||||
BC_INST_RET = 6,
|
||||
BC_INST_RET_MASK = 0xC0,
|
||||
|
||||
/* return type flags */
|
||||
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,
|
||||
BC_RET_NULL = VAL_NULL << BC_INST_RET,
|
||||
BC_RET_STRING = VAL_STRING << BC_INST_RET,
|
||||
BC_RET_INT = VAL_INT << BC_INST_RET,
|
||||
BC_RET_FLOAT = VAL_FLOAT << BC_INST_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
|
||||
/* BC_INST_JUMP_B, BC_INST_JUMP_RESULT */
|
||||
BC_INST_FLAG_TRUE = 1 << BC_INST_RET,
|
||||
BC_INST_FLAG_FALSE = 0 << BC_INST_RET
|
||||
};
|
||||
|
||||
std::uint32_t *bcode_alloc(cs_state &cs, std::size_t sz);
|
||||
std::uint32_t *bcode_alloc(state &cs, std::size_t sz);
|
||||
|
||||
void bcode_incr(std::uint32_t *code);
|
||||
void bcode_decr(std::uint32_t *code);
|
||||
void bcode_ref(std::uint32_t *code);
|
||||
void bcode_addref(std::uint32_t *code);
|
||||
void bcode_unref(std::uint32_t *code);
|
||||
|
||||
struct empty_block {
|
||||
cs_bcode init;
|
||||
bcode init;
|
||||
std::uint32_t code;
|
||||
};
|
||||
|
||||
empty_block *bcode_init_empty(cs_shared_state *cs);
|
||||
void bcode_free_empty(cs_shared_state *cs, empty_block *empty);
|
||||
cs_bcode *bcode_get_empty(empty_block *empty, std::size_t val);
|
||||
empty_block *bcode_init_empty(internal_state *cs);
|
||||
void bcode_free_empty(internal_state *cs, empty_block *empty);
|
||||
bcode *bcode_get_empty(empty_block *empty, std::size_t val);
|
||||
|
||||
} /* namespace cscript */
|
||||
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
|
||||
namespace cscript {
|
||||
|
||||
LIBCUBESCRIPT_EXPORT char *cs_error::request_buf(
|
||||
cs_state &cs, std::size_t bufs, char *&sp
|
||||
LIBCUBESCRIPT_EXPORT char *error::request_buf(
|
||||
state &cs, std::size_t bufs, char *&sp
|
||||
) {
|
||||
cs_charbuf &cb = *static_cast<cs_charbuf *>(cs.p_errbuf);
|
||||
cs_gen_state *gs = cs.p_pstate;
|
||||
charbuf &cb = *static_cast<charbuf *>(cs.p_errbuf);
|
||||
codegen_state *gs = cs.p_pstate;
|
||||
cb.clear();
|
||||
std::size_t sz = 0;
|
||||
if (gs) {
|
||||
|
@ -30,7 +30,7 @@ LIBCUBESCRIPT_EXPORT char *cs_error::request_buf(
|
|||
nsz = std::snprintf(cb.data(), sz, "%zu: ", gs->current_line);
|
||||
}
|
||||
if (nsz <= 0) {
|
||||
throw cs_internal_error{"format error"};
|
||||
throw internal_error{"format error"};
|
||||
} else if (std::size_t(nsz) < sz) {
|
||||
sz = std::size_t(nsz);
|
||||
break;
|
||||
|
@ -43,24 +43,24 @@ LIBCUBESCRIPT_EXPORT char *cs_error::request_buf(
|
|||
return &cb[sz];
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_stack_state cs_error::save_stack(cs_state &cs) {
|
||||
cs_ivar *dalias = static_cast<cs_ivar *>(cs.p_state->identmap[DbgaliasIdx]);
|
||||
LIBCUBESCRIPT_EXPORT stack_state error::save_stack(state &cs) {
|
||||
integer_var *dalias = static_cast<integer_var *>(cs.p_state->identmap[DbgaliasIdx]);
|
||||
if (!dalias->get_value()) {
|
||||
return cs_stack_state(cs, nullptr, !!cs.p_callstack);
|
||||
return stack_state(cs, nullptr, !!cs.p_callstack);
|
||||
}
|
||||
int total = 0, depth = 0;
|
||||
for (cs_ident_link *l = cs.p_callstack; l; l = l->next) {
|
||||
for (ident_link *l = cs.p_callstack; l; l = l->next) {
|
||||
total++;
|
||||
}
|
||||
if (!total) {
|
||||
return cs_stack_state(cs, nullptr, false);
|
||||
return stack_state(cs, nullptr, false);
|
||||
}
|
||||
cs_stack_state_node *st = cs.p_state->create_array<cs_stack_state_node>(
|
||||
stack_state_node *st = cs.p_state->create_array<stack_state_node>(
|
||||
std::min(total, dalias->get_value())
|
||||
);
|
||||
cs_stack_state_node *ret = st, *nd = st;
|
||||
stack_state_node *ret = st, *nd = st;
|
||||
++st;
|
||||
for (cs_ident_link *l = cs.p_callstack; l; l = l->next) {
|
||||
for (ident_link *l = cs.p_callstack; l; l = l->next) {
|
||||
++depth;
|
||||
if (depth < dalias->get_value()) {
|
||||
nd->id = l->id;
|
||||
|
@ -77,7 +77,7 @@ LIBCUBESCRIPT_EXPORT cs_stack_state cs_error::save_stack(cs_state &cs) {
|
|||
nd->next = nullptr;
|
||||
}
|
||||
}
|
||||
return cs_stack_state(cs, ret, total > dalias->get_value());
|
||||
return stack_state(cs, ret, total > dalias->get_value());
|
||||
}
|
||||
|
||||
} /* namespace cscript */
|
||||
|
|
640
src/cs_gen.cc
640
src/cs_gen.cc
File diff suppressed because it is too large
Load Diff
262
src/cs_ident.cc
262
src/cs_ident.cc
|
@ -5,27 +5,27 @@
|
|||
|
||||
namespace cscript {
|
||||
|
||||
cs_ident_impl::cs_ident_impl(cs_ident_type tp, cs_strref nm, int fl):
|
||||
ident_impl::ident_impl(ident_type tp, string_ref nm, int fl):
|
||||
p_name{nm}, p_type{int(tp)}, p_flags{fl}
|
||||
{}
|
||||
|
||||
cs_var_impl::cs_var_impl(
|
||||
cs_ident_type tp, cs_strref name, cs_var_cb f, int fl
|
||||
var_impl::var_impl(
|
||||
ident_type tp, string_ref name, var_cb_func f, int fl
|
||||
):
|
||||
cs_ident_impl{tp, name, fl}, cb_var{std::move(f)}
|
||||
ident_impl{tp, name, fl}, cb_var{std::move(f)}
|
||||
{}
|
||||
|
||||
void cs_var_impl::changed(cs_state &cs) {
|
||||
void var_impl::changed(state &cs) {
|
||||
if (cb_var) {
|
||||
switch (p_type) {
|
||||
case ID_IVAR:
|
||||
cb_var(cs, *static_cast<cs_ivar_impl *>(this));
|
||||
cb_var(cs, *static_cast<ivar_impl *>(this));
|
||||
break;
|
||||
case ID_FVAR:
|
||||
cb_var(cs, *static_cast<cs_fvar_impl *>(this));
|
||||
cb_var(cs, *static_cast<fvar_impl *>(this));
|
||||
break;
|
||||
case ID_SVAR:
|
||||
cb_var(cs, *static_cast<cs_svar_impl *>(this));
|
||||
cb_var(cs, *static_cast<svar_impl *>(this));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -33,80 +33,80 @@ void cs_var_impl::changed(cs_state &cs) {
|
|||
}
|
||||
}
|
||||
|
||||
cs_ivar_impl::cs_ivar_impl(
|
||||
cs_strref name, cs_int m, cs_int x, cs_int v, cs_var_cb f, int fl
|
||||
ivar_impl::ivar_impl(
|
||||
string_ref name, integer_type m, integer_type x, integer_type v, var_cb_func f, int fl
|
||||
):
|
||||
cs_var_impl{
|
||||
cs_ident_type::IVAR, name, std::move(f),
|
||||
fl | ((m > x) ? CS_IDF_READONLY : 0)
|
||||
var_impl{
|
||||
ident_type::IVAR, name, std::move(f),
|
||||
fl | ((m > x) ? IDENT_FLAG_READONLY : 0)
|
||||
},
|
||||
p_storage{v}, p_minval{m}, p_maxval{x}, p_overrideval{0}
|
||||
{}
|
||||
|
||||
cs_fvar_impl::cs_fvar_impl(
|
||||
cs_strref name, cs_float m, cs_float x, cs_float v, cs_var_cb f, int fl
|
||||
fvar_impl::fvar_impl(
|
||||
string_ref name, float_type m, float_type x, float_type v, var_cb_func f, int fl
|
||||
):
|
||||
cs_var_impl{
|
||||
cs_ident_type::FVAR, name, std::move(f),
|
||||
fl | ((m > x) ? CS_IDF_READONLY : 0)
|
||||
var_impl{
|
||||
ident_type::FVAR, name, std::move(f),
|
||||
fl | ((m > x) ? IDENT_FLAG_READONLY : 0)
|
||||
},
|
||||
p_storage{v}, p_minval{m}, p_maxval{x}, p_overrideval{0}
|
||||
{}
|
||||
|
||||
cs_svar_impl::cs_svar_impl(
|
||||
cs_strref name, cs_strref v, cs_strref ov, cs_var_cb f, int fl
|
||||
svar_impl::svar_impl(
|
||||
string_ref name, string_ref v, string_ref ov, var_cb_func f, int fl
|
||||
):
|
||||
cs_var_impl{cs_ident_type::SVAR, name, std::move(f), fl},
|
||||
var_impl{ident_type::SVAR, name, std::move(f), fl},
|
||||
p_storage{v}, p_overrideval{ov}
|
||||
{}
|
||||
|
||||
cs_alias_impl::cs_alias_impl(
|
||||
cs_state &cs, cs_strref name, cs_strref a, int fl
|
||||
alias_impl::alias_impl(
|
||||
state &cs, string_ref name, string_ref a, int fl
|
||||
):
|
||||
cs_ident_impl{cs_ident_type::ALIAS, name, fl},
|
||||
ident_impl{ident_type::ALIAS, name, fl},
|
||||
p_acode{nullptr}, p_astack{nullptr}, p_val{cs}
|
||||
{
|
||||
p_val.set_str(a);
|
||||
}
|
||||
|
||||
cs_alias_impl::cs_alias_impl(
|
||||
cs_state &cs, cs_strref name, std::string_view a, int fl
|
||||
alias_impl::alias_impl(
|
||||
state &cs, string_ref name, std::string_view a, int fl
|
||||
):
|
||||
cs_ident_impl{cs_ident_type::ALIAS, name, fl},
|
||||
ident_impl{ident_type::ALIAS, name, fl},
|
||||
p_acode{nullptr}, p_astack{nullptr}, p_val{cs}
|
||||
{
|
||||
p_val.set_str(a);
|
||||
}
|
||||
|
||||
cs_alias_impl::cs_alias_impl(cs_state &cs, cs_strref name, cs_int a, int fl):
|
||||
cs_ident_impl{cs_ident_type::ALIAS, name, fl},
|
||||
alias_impl::alias_impl(state &cs, string_ref name, integer_type a, int fl):
|
||||
ident_impl{ident_type::ALIAS, name, fl},
|
||||
p_acode{nullptr}, p_astack{nullptr}, p_val{cs}
|
||||
{
|
||||
p_val.set_int(a);
|
||||
}
|
||||
|
||||
cs_alias_impl::cs_alias_impl(cs_state &cs, cs_strref name, cs_float a, int fl):
|
||||
cs_ident_impl{cs_ident_type::ALIAS, name, fl},
|
||||
alias_impl::alias_impl(state &cs, string_ref name, float_type a, int fl):
|
||||
ident_impl{ident_type::ALIAS, name, fl},
|
||||
p_acode{nullptr}, p_astack{nullptr}, p_val{cs}
|
||||
{
|
||||
p_val.set_float(a);
|
||||
}
|
||||
|
||||
cs_alias_impl::cs_alias_impl(cs_state &cs, cs_strref name, int fl):
|
||||
cs_ident_impl{cs_ident_type::ALIAS, name, fl},
|
||||
alias_impl::alias_impl(state &cs, string_ref name, int fl):
|
||||
ident_impl{ident_type::ALIAS, name, fl},
|
||||
p_acode{nullptr}, p_astack{nullptr}, p_val{cs}
|
||||
{
|
||||
p_val.set_none();
|
||||
}
|
||||
|
||||
cs_alias_impl::cs_alias_impl(cs_state &cs, cs_strref name, cs_value v, int fl):
|
||||
cs_ident_impl{cs_ident_type::ALIAS, name, fl},
|
||||
alias_impl::alias_impl(state &cs, string_ref name, any_value v, int fl):
|
||||
ident_impl{ident_type::ALIAS, name, fl},
|
||||
p_acode{nullptr}, p_astack{nullptr}, p_val{cs}
|
||||
{
|
||||
p_val = v;
|
||||
}
|
||||
|
||||
void cs_alias_impl::push_arg(cs_value &v, cs_ident_stack &st, bool um) {
|
||||
void alias_impl::push_arg(any_value &v, ident_stack &st, bool um) {
|
||||
if (p_astack == &st) {
|
||||
/* prevent cycles and unnecessary code elsewhere */
|
||||
p_val = std::move(v);
|
||||
|
@ -119,22 +119,22 @@ void cs_alias_impl::push_arg(cs_value &v, cs_ident_stack &st, bool um) {
|
|||
p_val = std::move(v);
|
||||
clean_code();
|
||||
if (um) {
|
||||
p_flags &= ~CS_IDF_UNKNOWN;
|
||||
p_flags &= ~IDENT_FLAG_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
void cs_alias_impl::pop_arg() {
|
||||
void alias_impl::pop_arg() {
|
||||
if (!p_astack) {
|
||||
return;
|
||||
}
|
||||
cs_ident_stack *st = p_astack;
|
||||
ident_stack *st = p_astack;
|
||||
p_val = std::move(p_astack->val_s);
|
||||
clean_code();
|
||||
p_astack = st->next;
|
||||
}
|
||||
|
||||
void cs_alias_impl::undo_arg(cs_ident_stack &st) {
|
||||
cs_ident_stack *prev = p_astack;
|
||||
void alias_impl::undo_arg(ident_stack &st) {
|
||||
ident_stack *prev = p_astack;
|
||||
st.val_s = std::move(p_val);
|
||||
st.next = prev;
|
||||
p_astack = prev->next;
|
||||
|
@ -142,15 +142,15 @@ void cs_alias_impl::undo_arg(cs_ident_stack &st) {
|
|||
clean_code();
|
||||
}
|
||||
|
||||
void cs_alias_impl::redo_arg(cs_ident_stack &st) {
|
||||
cs_ident_stack *prev = st.next;
|
||||
void alias_impl::redo_arg(ident_stack &st) {
|
||||
ident_stack *prev = st.next;
|
||||
prev->val_s = std::move(p_val);
|
||||
p_astack = prev;
|
||||
p_val = std::move(st.val_s);
|
||||
clean_code();
|
||||
}
|
||||
|
||||
void cs_alias_impl::set_arg(cs_state &cs, cs_value &v) {
|
||||
void alias_impl::set_arg(state &cs, any_value &v) {
|
||||
if (ident_is_used_arg(this, cs)) {
|
||||
p_val = std::move(v);
|
||||
clean_code();
|
||||
|
@ -160,41 +160,41 @@ void cs_alias_impl::set_arg(cs_state &cs, cs_value &v) {
|
|||
}
|
||||
}
|
||||
|
||||
void cs_alias_impl::set_alias(cs_state &cs, cs_value &v) {
|
||||
void alias_impl::set_alias(state &cs, any_value &v) {
|
||||
p_val = std::move(v);
|
||||
clean_code();
|
||||
p_flags = (p_flags & cs.identflags) | cs.identflags;
|
||||
}
|
||||
|
||||
void cs_alias_impl::clean_code() {
|
||||
void alias_impl::clean_code() {
|
||||
if (p_acode) {
|
||||
bcode_decr(p_acode->get_raw());
|
||||
p_acode = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
cs_bcode *cs_alias_impl::compile_code(cs_state &cs) {
|
||||
bcode *alias_impl::compile_code(state &cs) {
|
||||
if (!p_acode) {
|
||||
cs_gen_state gs(cs);
|
||||
codegen_state gs(cs);
|
||||
gs.code.reserve(64);
|
||||
gs.gen_main(get_value().get_str());
|
||||
/* i wish i could steal the memory somehow */
|
||||
uint32_t *code = bcode_alloc(cs, gs.code.size());
|
||||
memcpy(code, gs.code.data(), gs.code.size() * sizeof(uint32_t));
|
||||
bcode_incr(code);
|
||||
p_acode = reinterpret_cast<cs_bcode *>(code);
|
||||
p_acode = reinterpret_cast<bcode *>(code);
|
||||
}
|
||||
return p_acode;
|
||||
}
|
||||
|
||||
cs_command_impl::cs_command_impl(
|
||||
cs_strref name, cs_strref args, int nargs, cs_command_cb f
|
||||
command_impl::command_impl(
|
||||
string_ref name, string_ref args, int nargs, command_func f
|
||||
):
|
||||
cs_ident_impl{cs_ident_type::COMMAND, name, 0},
|
||||
ident_impl{ident_type::COMMAND, name, 0},
|
||||
p_cargs{args}, p_cb_cftv{std::move(f)}, p_numargs{nargs}
|
||||
{}
|
||||
|
||||
bool ident_is_used_arg(cs_ident *id, cs_state &cs) {
|
||||
bool ident_is_used_arg(ident *id, state &cs) {
|
||||
if (!cs.p_callstack) {
|
||||
return true;
|
||||
}
|
||||
|
@ -203,74 +203,74 @@ bool ident_is_used_arg(cs_ident *id, cs_state &cs) {
|
|||
|
||||
/* public interface */
|
||||
|
||||
LIBCUBESCRIPT_EXPORT int cs_ident::get_raw_type() const {
|
||||
LIBCUBESCRIPT_EXPORT int ident::get_raw_type() const {
|
||||
return p_impl->p_type;
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_ident_type cs_ident::get_type() const {
|
||||
LIBCUBESCRIPT_EXPORT ident_type ident::get_type() const {
|
||||
if (p_impl->p_type > ID_ALIAS) {
|
||||
return cs_ident_type::SPECIAL;
|
||||
return ident_type::SPECIAL;
|
||||
}
|
||||
return cs_ident_type(p_impl->p_type);
|
||||
return ident_type(p_impl->p_type);
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT std::string_view cs_ident::get_name() const {
|
||||
LIBCUBESCRIPT_EXPORT std::string_view ident::get_name() const {
|
||||
return p_impl->p_name;
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT int cs_ident::get_flags() const {
|
||||
LIBCUBESCRIPT_EXPORT int ident::get_flags() const {
|
||||
return p_impl->p_flags;
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT int cs_ident::get_index() const {
|
||||
LIBCUBESCRIPT_EXPORT int ident::get_index() const {
|
||||
return p_impl->p_index;
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT bool cs_ident::is_alias() const {
|
||||
return get_type() == cs_ident_type::ALIAS;
|
||||
LIBCUBESCRIPT_EXPORT bool ident::is_alias() const {
|
||||
return get_type() == ident_type::ALIAS;
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_alias *cs_ident::get_alias() {
|
||||
LIBCUBESCRIPT_EXPORT alias *ident::get_alias() {
|
||||
if (!is_alias()) {
|
||||
return nullptr;
|
||||
}
|
||||
return static_cast<cs_alias *>(this);
|
||||
return static_cast<alias *>(this);
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_alias const *cs_ident::get_alias() const {
|
||||
LIBCUBESCRIPT_EXPORT alias const *ident::get_alias() const {
|
||||
if (!is_alias()) {
|
||||
return nullptr;
|
||||
}
|
||||
return static_cast<cs_alias const *>(this);
|
||||
return static_cast<alias const *>(this);
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT bool cs_ident::is_command() const {
|
||||
return get_type() == cs_ident_type::COMMAND;
|
||||
LIBCUBESCRIPT_EXPORT bool ident::is_command() const {
|
||||
return get_type() == ident_type::COMMAND;
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_command *cs_ident::get_command() {
|
||||
LIBCUBESCRIPT_EXPORT command *ident::get_command() {
|
||||
if (!is_command()) {
|
||||
return nullptr;
|
||||
}
|
||||
return static_cast<cs_command_impl *>(this);
|
||||
return static_cast<command_impl *>(this);
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_command const *cs_ident::get_command() const {
|
||||
LIBCUBESCRIPT_EXPORT command const *ident::get_command() const {
|
||||
if (!is_command()) {
|
||||
return nullptr;
|
||||
}
|
||||
return static_cast<cs_command_impl const *>(this);
|
||||
return static_cast<command_impl const *>(this);
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT bool cs_ident::is_special() const {
|
||||
return get_type() == cs_ident_type::SPECIAL;
|
||||
LIBCUBESCRIPT_EXPORT bool ident::is_special() const {
|
||||
return get_type() == ident_type::SPECIAL;
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT bool cs_ident::is_var() const {
|
||||
LIBCUBESCRIPT_EXPORT bool ident::is_var() const {
|
||||
switch (get_type()) {
|
||||
case cs_ident_type::IVAR:
|
||||
case cs_ident_type::FVAR:
|
||||
case cs_ident_type::SVAR:
|
||||
case ident_type::IVAR:
|
||||
case ident_type::FVAR:
|
||||
case ident_type::SVAR:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
|
@ -278,128 +278,128 @@ LIBCUBESCRIPT_EXPORT bool cs_ident::is_var() const {
|
|||
return false;
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_var *cs_ident::get_var() {
|
||||
LIBCUBESCRIPT_EXPORT global_var *ident::get_var() {
|
||||
if (!is_var()) {
|
||||
return nullptr;
|
||||
}
|
||||
return static_cast<cs_var *>(this);
|
||||
return static_cast<global_var *>(this);
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_var const *cs_ident::get_var() const {
|
||||
LIBCUBESCRIPT_EXPORT global_var const *ident::get_var() const {
|
||||
if (!is_var()) {
|
||||
return nullptr;
|
||||
}
|
||||
return static_cast<cs_var const *>(this);
|
||||
return static_cast<global_var const *>(this);
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT bool cs_ident::is_ivar() const {
|
||||
return get_type() == cs_ident_type::IVAR;
|
||||
LIBCUBESCRIPT_EXPORT bool ident::is_ivar() const {
|
||||
return get_type() == ident_type::IVAR;
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_ivar *cs_ident::get_ivar() {
|
||||
LIBCUBESCRIPT_EXPORT integer_var *ident::get_ivar() {
|
||||
if (!is_ivar()) {
|
||||
return nullptr;
|
||||
}
|
||||
return static_cast<cs_ivar *>(this);
|
||||
return static_cast<integer_var *>(this);
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_ivar const *cs_ident::get_ivar() const {
|
||||
LIBCUBESCRIPT_EXPORT integer_var const *ident::get_ivar() const {
|
||||
if (!is_ivar()) {
|
||||
return nullptr;
|
||||
}
|
||||
return static_cast<cs_ivar const *>(this);
|
||||
return static_cast<integer_var const *>(this);
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT bool cs_ident::is_fvar() const {
|
||||
return get_type() == cs_ident_type::FVAR;
|
||||
LIBCUBESCRIPT_EXPORT bool ident::is_fvar() const {
|
||||
return get_type() == ident_type::FVAR;
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_fvar *cs_ident::get_fvar() {
|
||||
LIBCUBESCRIPT_EXPORT float_var *ident::get_fvar() {
|
||||
if (!is_fvar()) {
|
||||
return nullptr;
|
||||
}
|
||||
return static_cast<cs_fvar *>(this);
|
||||
return static_cast<float_var *>(this);
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_fvar const *cs_ident::get_fvar() const {
|
||||
LIBCUBESCRIPT_EXPORT float_var const *ident::get_fvar() const {
|
||||
if (!is_fvar()) {
|
||||
return nullptr;
|
||||
}
|
||||
return static_cast<cs_fvar const *>(this);
|
||||
return static_cast<float_var const *>(this);
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT bool cs_ident::is_svar() const {
|
||||
return get_type() == cs_ident_type::SVAR;
|
||||
LIBCUBESCRIPT_EXPORT bool ident::is_svar() const {
|
||||
return get_type() == ident_type::SVAR;
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_svar *cs_ident::get_svar() {
|
||||
LIBCUBESCRIPT_EXPORT string_var *ident::get_svar() {
|
||||
if (!is_svar()) {
|
||||
return nullptr;
|
||||
}
|
||||
return static_cast<cs_svar *>(this);
|
||||
return static_cast<string_var *>(this);
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_svar const *cs_ident::get_svar() const {
|
||||
LIBCUBESCRIPT_EXPORT string_var const *ident::get_svar() const {
|
||||
if (!is_svar()) {
|
||||
return nullptr;
|
||||
}
|
||||
return static_cast<cs_svar const *>(this);
|
||||
return static_cast<string_var const *>(this);
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_int cs_ivar::get_val_min() const {
|
||||
return static_cast<cs_ivar_impl const *>(this)->p_minval;
|
||||
LIBCUBESCRIPT_EXPORT integer_type integer_var::get_val_min() const {
|
||||
return static_cast<ivar_impl const *>(this)->p_minval;
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_int cs_ivar::get_val_max() const {
|
||||
return static_cast<cs_ivar_impl const *>(this)->p_maxval;
|
||||
LIBCUBESCRIPT_EXPORT integer_type integer_var::get_val_max() const {
|
||||
return static_cast<ivar_impl const *>(this)->p_maxval;
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_int cs_ivar::get_value() const {
|
||||
return static_cast<cs_ivar_impl const *>(this)->p_storage;
|
||||
LIBCUBESCRIPT_EXPORT integer_type integer_var::get_value() const {
|
||||
return static_cast<ivar_impl const *>(this)->p_storage;
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT void cs_ivar::set_value(cs_int val) {
|
||||
static_cast<cs_ivar_impl *>(this)->p_storage = val;
|
||||
LIBCUBESCRIPT_EXPORT void integer_var::set_value(integer_type val) {
|
||||
static_cast<ivar_impl *>(this)->p_storage = val;
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_float cs_fvar::get_val_min() const {
|
||||
return static_cast<cs_fvar_impl const *>(this)->p_minval;
|
||||
LIBCUBESCRIPT_EXPORT float_type float_var::get_val_min() const {
|
||||
return static_cast<fvar_impl const *>(this)->p_minval;
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_float cs_fvar::get_val_max() const {
|
||||
return static_cast<cs_fvar_impl const *>(this)->p_maxval;
|
||||
LIBCUBESCRIPT_EXPORT float_type float_var::get_val_max() const {
|
||||
return static_cast<fvar_impl const *>(this)->p_maxval;
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_float cs_fvar::get_value() const {
|
||||
return static_cast<cs_fvar_impl const *>(this)->p_storage;
|
||||
LIBCUBESCRIPT_EXPORT float_type float_var::get_value() const {
|
||||
return static_cast<fvar_impl const *>(this)->p_storage;
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT void cs_fvar::set_value(cs_float val) {
|
||||
static_cast<cs_fvar_impl *>(this)->p_storage = val;
|
||||
LIBCUBESCRIPT_EXPORT void float_var::set_value(float_type val) {
|
||||
static_cast<fvar_impl *>(this)->p_storage = val;
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_strref cs_svar::get_value() const {
|
||||
return static_cast<cs_svar_impl const *>(this)->p_storage;
|
||||
LIBCUBESCRIPT_EXPORT string_ref string_var::get_value() const {
|
||||
return static_cast<svar_impl const *>(this)->p_storage;
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT void cs_svar::set_value(cs_strref val) {
|
||||
static_cast<cs_svar_impl *>(this)->p_storage = val;
|
||||
LIBCUBESCRIPT_EXPORT void string_var::set_value(string_ref val) {
|
||||
static_cast<svar_impl *>(this)->p_storage = val;
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_value cs_alias::get_value() const {
|
||||
return static_cast<cs_alias_impl const *>(this)->p_val;
|
||||
LIBCUBESCRIPT_EXPORT any_value alias::get_value() const {
|
||||
return static_cast<alias_impl const *>(this)->p_val;
|
||||
}
|
||||
|
||||
void cs_alias::get_cval(cs_value &v) const {
|
||||
auto *imp = static_cast<cs_alias_impl const *>(this);
|
||||
void alias::get_cval(any_value &v) const {
|
||||
auto *imp = static_cast<alias_impl const *>(this);
|
||||
switch (imp->p_val.get_type()) {
|
||||
case cs_value_type::STRING:
|
||||
case value_type::STRING:
|
||||
v = imp->p_val;
|
||||
break;
|
||||
case cs_value_type::INT:
|
||||
case value_type::INT:
|
||||
v.set_int(imp->p_val.get_int());
|
||||
break;
|
||||
case cs_value_type::FLOAT:
|
||||
case value_type::FLOAT:
|
||||
v.set_float(imp->p_val.get_float());
|
||||
break;
|
||||
default:
|
||||
|
@ -408,12 +408,12 @@ void cs_alias::get_cval(cs_value &v) const {
|
|||
}
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT std::string_view cs_command::get_args() const {
|
||||
return static_cast<cs_command_impl const *>(this)->p_cargs;
|
||||
LIBCUBESCRIPT_EXPORT std::string_view command::get_args() const {
|
||||
return static_cast<command_impl const *>(this)->p_cargs;
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT int cs_command::get_num_args() const {
|
||||
return static_cast<cs_command_impl const *>(this)->p_numargs;
|
||||
LIBCUBESCRIPT_EXPORT int command::get_num_args() const {
|
||||
return static_cast<command_impl const *>(this)->p_numargs;
|
||||
}
|
||||
|
||||
} /* namespace cscript */
|
||||
|
|
110
src/cs_ident.hh
110
src/cs_ident.hh
|
@ -11,28 +11,28 @@ enum {
|
|||
ID_NOT, ID_AND, ID_OR
|
||||
};
|
||||
|
||||
struct cs_ident_link {
|
||||
cs_ident *id;
|
||||
cs_ident_link *next;
|
||||
struct ident_link {
|
||||
ident *id;
|
||||
ident_link *next;
|
||||
int usedargs;
|
||||
cs_ident_stack *argstack;
|
||||
ident_stack *argstack;
|
||||
};
|
||||
|
||||
struct cs_ident_impl {
|
||||
cs_ident_impl() = delete;
|
||||
cs_ident_impl(cs_ident_impl const &) = delete;
|
||||
cs_ident_impl(cs_ident_impl &&) = delete;
|
||||
struct ident_impl {
|
||||
ident_impl() = delete;
|
||||
ident_impl(ident_impl const &) = delete;
|
||||
ident_impl(ident_impl &&) = delete;
|
||||
|
||||
/* trigger destructors for all inherited members properly */
|
||||
virtual ~cs_ident_impl() {};
|
||||
virtual ~ident_impl() {};
|
||||
|
||||
cs_ident_impl &operator=(cs_ident_impl const &) = delete;
|
||||
cs_ident_impl &operator=(cs_ident_impl &&) = delete;
|
||||
ident_impl &operator=(ident_impl const &) = delete;
|
||||
ident_impl &operator=(ident_impl &&) = delete;
|
||||
|
||||
cs_ident_impl(cs_ident_type tp, cs_strref name, int flags = 0);
|
||||
ident_impl(ident_type tp, string_ref name, int flags = 0);
|
||||
|
||||
cs_strref p_name;
|
||||
/* represents the cs_ident_type above, but internally it has a wider
|
||||
string_ref p_name;
|
||||
/* represents the ident_type above, but internally it has a wider
|
||||
* variety of values, so it's an int here (maps to an internal enum)
|
||||
*/
|
||||
int p_type, p_flags;
|
||||
|
@ -40,79 +40,79 @@ struct cs_ident_impl {
|
|||
int p_index = -1;
|
||||
};
|
||||
|
||||
struct cs_var_impl: cs_ident_impl {
|
||||
cs_var_impl(
|
||||
cs_ident_type tp, cs_strref name, cs_var_cb func, int flags = 0
|
||||
struct var_impl: ident_impl {
|
||||
var_impl(
|
||||
ident_type tp, string_ref name, var_cb_func func, int flags = 0
|
||||
);
|
||||
|
||||
cs_var_cb cb_var;
|
||||
var_cb_func cb_var;
|
||||
|
||||
void changed(cs_state &cs);
|
||||
void changed(state &cs);
|
||||
};
|
||||
|
||||
struct cs_ivar_impl: cs_var_impl, cs_ivar {
|
||||
cs_ivar_impl(
|
||||
cs_strref n, cs_int m, cs_int x, cs_int v, cs_var_cb f, int flags
|
||||
struct ivar_impl: var_impl, integer_var {
|
||||
ivar_impl(
|
||||
string_ref n, integer_type m, integer_type x, integer_type v, var_cb_func f, int flags
|
||||
);
|
||||
|
||||
cs_int p_storage, p_minval, p_maxval, p_overrideval;
|
||||
integer_type p_storage, p_minval, p_maxval, p_overrideval;
|
||||
};
|
||||
|
||||
struct cs_fvar_impl: cs_var_impl, cs_fvar {
|
||||
cs_fvar_impl(
|
||||
cs_strref n, cs_float m, cs_float x, cs_float v,
|
||||
cs_var_cb f, int flags
|
||||
struct fvar_impl: var_impl, float_var {
|
||||
fvar_impl(
|
||||
string_ref n, float_type m, float_type x, float_type v,
|
||||
var_cb_func f, int flags
|
||||
);
|
||||
|
||||
cs_float p_storage, p_minval, p_maxval, p_overrideval;
|
||||
float_type p_storage, p_minval, p_maxval, p_overrideval;
|
||||
};
|
||||
|
||||
struct cs_svar_impl: cs_var_impl, cs_svar {
|
||||
cs_svar_impl(
|
||||
cs_strref n, cs_strref v, cs_strref ov, cs_var_cb f, int flags
|
||||
struct svar_impl: var_impl, string_var {
|
||||
svar_impl(
|
||||
string_ref n, string_ref v, string_ref ov, var_cb_func f, int flags
|
||||
);
|
||||
|
||||
cs_strref p_storage, p_overrideval;
|
||||
string_ref p_storage, p_overrideval;
|
||||
};
|
||||
|
||||
struct cs_alias_impl: cs_ident_impl, cs_alias {
|
||||
cs_alias_impl(cs_state &cs, cs_strref n, cs_strref a, int flags);
|
||||
cs_alias_impl(cs_state &cs, cs_strref n, std::string_view a, int flags);
|
||||
cs_alias_impl(cs_state &cs, cs_strref n, cs_int a, int flags);
|
||||
cs_alias_impl(cs_state &cs, cs_strref n, cs_float a, int flags);
|
||||
cs_alias_impl(cs_state &cs, cs_strref n, int flags);
|
||||
cs_alias_impl(cs_state &cs, cs_strref n, cs_value v, int flags);
|
||||
struct alias_impl: ident_impl, alias {
|
||||
alias_impl(state &cs, string_ref n, string_ref a, int flags);
|
||||
alias_impl(state &cs, string_ref n, std::string_view a, int flags);
|
||||
alias_impl(state &cs, string_ref n, integer_type a, int flags);
|
||||
alias_impl(state &cs, string_ref n, float_type a, int flags);
|
||||
alias_impl(state &cs, string_ref n, int flags);
|
||||
alias_impl(state &cs, string_ref n, any_value v, int flags);
|
||||
|
||||
void push_arg(cs_value &v, cs_ident_stack &st, bool um = true);
|
||||
void push_arg(any_value &v, ident_stack &st, bool um = true);
|
||||
void pop_arg();
|
||||
void undo_arg(cs_ident_stack &st);
|
||||
void redo_arg(cs_ident_stack &st);
|
||||
void set_arg(cs_state &cs, cs_value &v);
|
||||
void set_alias(cs_state &cs, cs_value &v);
|
||||
void undo_arg(ident_stack &st);
|
||||
void redo_arg(ident_stack &st);
|
||||
void set_arg(state &cs, any_value &v);
|
||||
void set_alias(state &cs, any_value &v);
|
||||
|
||||
void clean_code();
|
||||
cs_bcode *compile_code(cs_state &cs);
|
||||
bcode *compile_code(state &cs);
|
||||
|
||||
cs_bcode *p_acode;
|
||||
cs_ident_stack *p_astack;
|
||||
cs_value p_val;
|
||||
bcode *p_acode;
|
||||
ident_stack *p_astack;
|
||||
any_value p_val;
|
||||
};
|
||||
|
||||
struct cs_command_impl: cs_ident_impl, cs_command {
|
||||
cs_command_impl(
|
||||
cs_strref name, cs_strref args, int numargs, cs_command_cb func
|
||||
struct command_impl: ident_impl, command {
|
||||
command_impl(
|
||||
string_ref name, string_ref args, int numargs, command_func func
|
||||
);
|
||||
|
||||
void call(cs_state &cs, std::span<cs_value> args, cs_value &ret) {
|
||||
void call(state &cs, std::span<any_value> args, any_value &ret) {
|
||||
p_cb_cftv(cs, args, ret);
|
||||
}
|
||||
|
||||
cs_strref p_cargs;
|
||||
cs_command_cb p_cb_cftv;
|
||||
string_ref p_cargs;
|
||||
command_func p_cb_cftv;
|
||||
int p_numargs;
|
||||
};
|
||||
|
||||
bool ident_is_used_arg(cs_ident *id, cs_state &cs);
|
||||
bool ident_is_used_arg(ident *id, state &cs);
|
||||
|
||||
} /* namespace cscript */
|
||||
|
||||
|
|
|
@ -9,8 +9,8 @@ namespace cscript {
|
|||
|
||||
/* string/word parsers are also useful to have public */
|
||||
|
||||
LIBCUBESCRIPT_EXPORT char const *cs_parse_string(
|
||||
cs_state &cs, std::string_view str, size_t &nlines
|
||||
LIBCUBESCRIPT_EXPORT char const *parse_string(
|
||||
state &cs, std::string_view str, size_t &nlines
|
||||
) {
|
||||
size_t nl = 0;
|
||||
nlines = nl;
|
||||
|
@ -54,7 +54,7 @@ LIBCUBESCRIPT_EXPORT char const *cs_parse_string(
|
|||
end:
|
||||
nlines = nl;
|
||||
if ((beg == end) || (*beg != '\"')) {
|
||||
throw cs_error{
|
||||
throw error{
|
||||
cs, "unfinished string '%s'",
|
||||
std::string_view{orig, std::size_t(beg - orig)}
|
||||
};
|
||||
|
@ -62,8 +62,8 @@ end:
|
|||
return ++beg;
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT char const *cs_parse_word(
|
||||
cs_state &cs, std::string_view str
|
||||
LIBCUBESCRIPT_EXPORT char const *parse_word(
|
||||
state &cs, std::string_view str
|
||||
) {
|
||||
char const *it = str.begin();
|
||||
char const *end = str.end();
|
||||
|
@ -88,20 +88,20 @@ LIBCUBESCRIPT_EXPORT char const *cs_parse_word(
|
|||
break;
|
||||
case '[':
|
||||
++it;
|
||||
it = cs_parse_word(cs, std::string_view{
|
||||
it = parse_word(cs, std::string_view{
|
||||
it, std::size_t(end - it)
|
||||
});
|
||||
if ((it == end) || (*it != ']')) {
|
||||
throw cs_error{cs, "missing \"]\""};
|
||||
throw error{cs, "missing \"]\""};
|
||||
}
|
||||
break;
|
||||
case '(':
|
||||
++it;
|
||||
it = cs_parse_word(cs, std::string_view{
|
||||
it = parse_word(cs, std::string_view{
|
||||
it, std::size_t(end - it)
|
||||
});
|
||||
if ((it == end) || (*it != ')')) {
|
||||
throw cs_error{cs, "missing \")\""};
|
||||
throw error{cs, "missing \")\""};
|
||||
}
|
||||
break;
|
||||
case ']':
|
||||
|
@ -128,7 +128,7 @@ static inline void p_set_end(
|
|||
*end = std::string_view{nbeg, nend};
|
||||
}
|
||||
/* this function assumes the input is definitely a hex digit */
|
||||
static inline cs_int p_hexd_to_int(char c) {
|
||||
static inline integer_type p_hexd_to_int(char c) {
|
||||
if (c >= 97) { /* a-f */
|
||||
return (c - 'a') + 10;
|
||||
} else if (c >= 65) { /* A-F */
|
||||
|
@ -146,17 +146,17 @@ static inline bool p_check_neg(char const *&input) {
|
|||
return neg;
|
||||
}
|
||||
|
||||
cs_int parse_int(std::string_view input, std::string_view *endstr) {
|
||||
integer_type parse_int(std::string_view input, std::string_view *endstr) {
|
||||
char const *beg = input.begin();
|
||||
char const *end = input.end();
|
||||
char const *orig = beg;
|
||||
beg = p_skip_white(beg, end);
|
||||
if (beg == end) {
|
||||
p_set_end(orig, end, endstr);
|
||||
return cs_int(0);
|
||||
return integer_type(0);
|
||||
}
|
||||
bool neg = p_check_neg(beg);
|
||||
cs_int ret = 0;
|
||||
integer_type ret = 0;
|
||||
char const *past = beg;
|
||||
if ((end - beg) >= 2) {
|
||||
std::string_view pfx = std::string_view{beg, 2};
|
||||
|
@ -188,7 +188,7 @@ done:
|
|||
}
|
||||
|
||||
template<bool Hex, char e1 = Hex ? 'p' : 'e', char e2 = Hex ? 'P' : 'E'>
|
||||
static inline bool p_read_exp(char const *&beg, char const *end, cs_int &fn) {
|
||||
static inline bool p_read_exp(char const *&beg, char const *end, integer_type &fn) {
|
||||
if (beg == end) {
|
||||
return true;
|
||||
}
|
||||
|
@ -202,7 +202,7 @@ static inline bool p_read_exp(char const *&beg, char const *end, cs_int &fn) {
|
|||
if ((beg == end) || !std::isdigit(*beg)) {
|
||||
return false;
|
||||
}
|
||||
cs_int exp = 0;
|
||||
integer_type exp = 0;
|
||||
while ((beg != end) && std::isdigit(*beg)) {
|
||||
exp = exp * 10 + (*beg++ - '0');
|
||||
}
|
||||
|
@ -215,9 +215,9 @@ static inline bool p_read_exp(char const *&beg, char const *end, cs_int &fn) {
|
|||
|
||||
template<bool Hex>
|
||||
static inline bool parse_gen_float(
|
||||
char const *&beg, char const *end, std::string_view *endstr, cs_float &ret
|
||||
char const *&beg, char const *end, std::string_view *endstr, float_type &ret
|
||||
) {
|
||||
auto read_digits = [&beg, end](double r, cs_int &n) {
|
||||
auto read_digits = [&beg, end](double r, integer_type &n) {
|
||||
while (
|
||||
(beg != end) &&
|
||||
(Hex ? std::isxdigit(*beg) : std::isdigit(*beg))
|
||||
|
@ -232,7 +232,7 @@ static inline bool parse_gen_float(
|
|||
}
|
||||
return r;
|
||||
};
|
||||
cs_int wn = 0, fn = 0;
|
||||
integer_type wn = 0, fn = 0;
|
||||
double r = read_digits(0.0, wn);
|
||||
if ((beg != end) && (*beg == '.')) {
|
||||
++beg;
|
||||
|
@ -247,24 +247,24 @@ static inline bool parse_gen_float(
|
|||
p_set_end(beg, end, endstr);
|
||||
}
|
||||
if (Hex) {
|
||||
ret = cs_float(ldexp(r, fn * 4));
|
||||
ret = float_type(ldexp(r, fn * 4));
|
||||
} else {
|
||||
ret = cs_float(r * pow(10, fn));
|
||||
ret = float_type(r * pow(10, fn));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
cs_float parse_float(std::string_view input, std::string_view *endstr) {
|
||||
float_type parse_float(std::string_view input, std::string_view *endstr) {
|
||||
char const *beg = input.begin();
|
||||
char const *end = input.end();
|
||||
char const *orig = beg;
|
||||
beg = p_skip_white(beg, end);
|
||||
if (beg == end) {
|
||||
p_set_end(orig, end, endstr);
|
||||
return cs_float(0);
|
||||
return float_type(0);
|
||||
}
|
||||
bool neg = p_check_neg(beg);
|
||||
cs_float ret = cs_float(0);
|
||||
float_type ret = float_type(0);
|
||||
if ((end - beg) >= 2) {
|
||||
std::string_view pfx = std::string_view{beg, 2};
|
||||
if ((pfx == "0x") || (pfx == "0X")) {
|
||||
|
@ -307,7 +307,7 @@ bool is_valid_name(std::string_view s) {
|
|||
|
||||
/* list parser public implementation */
|
||||
|
||||
LIBCUBESCRIPT_EXPORT bool cs_list_parser::parse() {
|
||||
LIBCUBESCRIPT_EXPORT bool list_parser::parse() {
|
||||
skip_until_item();
|
||||
if (p_input_beg == p_input_end) {
|
||||
return false;
|
||||
|
@ -315,7 +315,7 @@ LIBCUBESCRIPT_EXPORT bool cs_list_parser::parse() {
|
|||
switch (*p_input_beg) {
|
||||
case '"': {
|
||||
char const *qi = p_input_beg;
|
||||
p_input_beg = cs_parse_string(*p_state, get_input());
|
||||
p_input_beg = parse_string(*p_state, get_input());
|
||||
p_quoted_item = std::string_view{qi, p_input_beg};
|
||||
p_item = p_quoted_item.substr(1, p_quoted_item.size() - 2);
|
||||
break;
|
||||
|
@ -338,7 +338,7 @@ LIBCUBESCRIPT_EXPORT bool cs_list_parser::parse() {
|
|||
case '"':
|
||||
/* the quote is needed in str parsing */
|
||||
--p_input_beg;
|
||||
p_input_beg = cs_parse_string(*p_state, get_input());
|
||||
p_input_beg = parse_string(*p_state, get_input());
|
||||
break;
|
||||
case '/':
|
||||
if (
|
||||
|
@ -375,7 +375,7 @@ endblock:
|
|||
case ']':
|
||||
return false;
|
||||
default: {
|
||||
char const *e = cs_parse_word(*p_state, get_input());
|
||||
char const *e = parse_word(*p_state, get_input());
|
||||
p_quoted_item = p_item = std::string_view{p_input_beg, e};
|
||||
p_input_beg = e;
|
||||
break;
|
||||
|
@ -388,7 +388,7 @@ endblock:
|
|||
return true;
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT std::size_t cs_list_parser::count() {
|
||||
LIBCUBESCRIPT_EXPORT std::size_t list_parser::count() {
|
||||
size_t ret = 0;
|
||||
while (parse()) {
|
||||
++ret;
|
||||
|
@ -396,16 +396,16 @@ LIBCUBESCRIPT_EXPORT std::size_t cs_list_parser::count() {
|
|||
return ret;
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_strref cs_list_parser::get_item() const {
|
||||
LIBCUBESCRIPT_EXPORT string_ref list_parser::get_item() const {
|
||||
if (!p_quoted_item.empty() && (p_quoted_item.front() == '"')) {
|
||||
cs_charbuf buf{*p_state};
|
||||
cs_unescape_string(std::back_inserter(buf), p_item);
|
||||
return cs_strref{*p_state, buf.str()};
|
||||
charbuf buf{*p_state};
|
||||
unescape_string(std::back_inserter(buf), p_item);
|
||||
return string_ref{*p_state, buf.str()};
|
||||
}
|
||||
return cs_strref{*p_state, p_item};
|
||||
return string_ref{*p_state, p_item};
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT void cs_list_parser::skip_until_item() {
|
||||
LIBCUBESCRIPT_EXPORT void list_parser::skip_until_item() {
|
||||
for (;;) {
|
||||
while (p_input_beg != p_input_end) {
|
||||
char c = *p_input_beg;
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
|
||||
namespace cscript {
|
||||
|
||||
cs_int parse_int(std::string_view input, std::string_view *end = nullptr);
|
||||
cs_float parse_float(std::string_view input, std::string_view *end = nullptr);
|
||||
integer_type parse_int(std::string_view input, std::string_view *end = nullptr);
|
||||
float_type parse_float(std::string_view input, std::string_view *end = nullptr);
|
||||
|
||||
bool is_valid_name(std::string_view input);
|
||||
|
||||
|
|
443
src/cs_state.cc
443
src/cs_state.cc
|
@ -8,21 +8,21 @@
|
|||
|
||||
namespace cscript {
|
||||
|
||||
cs_shared_state::cs_shared_state(cs_alloc_cb af, void *data):
|
||||
internal_state::internal_state(alloc_func af, void *data):
|
||||
allocf{af}, aptr{data},
|
||||
idents{allocator_type{this}},
|
||||
identmap{allocator_type{this}},
|
||||
varprintf{},
|
||||
strman{create<cs_strman>(this)},
|
||||
strman{create<string_pool>(this)},
|
||||
empty{bcode_init_empty(this)}
|
||||
{}
|
||||
|
||||
cs_shared_state::~cs_shared_state() {
|
||||
internal_state::~internal_state() {
|
||||
bcode_free_empty(this, empty);
|
||||
destroy(strman);
|
||||
}
|
||||
|
||||
void *cs_shared_state::alloc(void *ptr, size_t os, size_t ns) {
|
||||
void *internal_state::alloc(void *ptr, size_t os, size_t ns) {
|
||||
void *p = allocf(aptr, ptr, os, ns);
|
||||
if (!p && ns) {
|
||||
throw std::bad_alloc{};
|
||||
|
@ -30,7 +30,7 @@ void *cs_shared_state::alloc(void *ptr, size_t os, size_t ns) {
|
|||
return p;
|
||||
}
|
||||
|
||||
static void *cs_default_alloc(void *, void *p, size_t, size_t ns) {
|
||||
static void *default_alloc(void *, void *p, size_t, size_t ns) {
|
||||
if (!ns) {
|
||||
std::free(p);
|
||||
return nullptr;
|
||||
|
@ -38,88 +38,88 @@ static void *cs_default_alloc(void *, void *p, size_t, size_t ns) {
|
|||
return std::realloc(p, ns);
|
||||
}
|
||||
|
||||
void cs_init_lib_base(cs_state &cs);
|
||||
void cs_init_lib_math(cs_state &cs);
|
||||
void cs_init_lib_string(cs_state &cs);
|
||||
void cs_init_lib_list(cs_state &cs);
|
||||
void init_lib_base(state &cs);
|
||||
void init_lib_math(state &cs);
|
||||
void init_lib_string(state &cs);
|
||||
void init_lib_list(state &cs);
|
||||
|
||||
/* public interfaces */
|
||||
|
||||
cs_state::cs_state(): cs_state{cs_default_alloc, nullptr} {}
|
||||
state::state(): state{default_alloc, nullptr} {}
|
||||
|
||||
cs_state::cs_state(cs_alloc_cb func, void *data):
|
||||
state::state(alloc_func func, void *data):
|
||||
p_state{nullptr}, p_callhook{}
|
||||
{
|
||||
cs_command *p;
|
||||
command *p;
|
||||
|
||||
if (!func) {
|
||||
func = cs_default_alloc;
|
||||
func = default_alloc;
|
||||
}
|
||||
/* allocator is not set up yet, use func directly */
|
||||
p_state = static_cast<cs_shared_state *>(
|
||||
func(data, nullptr, 0, sizeof(cs_shared_state))
|
||||
p_state = static_cast<internal_state *>(
|
||||
func(data, nullptr, 0, sizeof(internal_state))
|
||||
);
|
||||
/* allocator will be set up in the constructor */
|
||||
new (p_state) cs_shared_state{func, data};
|
||||
new (p_state) internal_state{func, data};
|
||||
p_owner = true;
|
||||
|
||||
/* will be used as message storage for errors */
|
||||
p_errbuf = p_state->create<cs_charbuf>(*this);
|
||||
p_errbuf = p_state->create<charbuf>(*this);
|
||||
|
||||
for (int i = 0; i < MaxArguments; ++i) {
|
||||
char buf[32];
|
||||
snprintf(buf, sizeof(buf), "arg%d", i + 1);
|
||||
new_ident(static_cast<char const *>(buf), CS_IDF_ARG);
|
||||
new_ident(static_cast<char const *>(buf), IDENT_FLAG_ARG);
|
||||
}
|
||||
|
||||
cs_ident *id = new_ident("//dummy");
|
||||
ident *id = new_ident("//dummy");
|
||||
if (id->get_index() != DummyIdx) {
|
||||
throw cs_internal_error{"invalid dummy index"};
|
||||
throw internal_error{"invalid dummy index"};
|
||||
}
|
||||
|
||||
id = new_ivar("numargs", MaxArguments, 0, 0);
|
||||
if (id->get_index() != NumargsIdx) {
|
||||
throw cs_internal_error{"invalid numargs index"};
|
||||
throw internal_error{"invalid numargs index"};
|
||||
}
|
||||
|
||||
id = new_ivar("dbgalias", 0, 1000, 4);
|
||||
if (id->get_index() != DbgaliasIdx) {
|
||||
throw cs_internal_error{"invalid dbgalias index"};
|
||||
throw internal_error{"invalid dbgalias index"};
|
||||
}
|
||||
|
||||
p = new_command("do", "e", [](auto &cs, auto args, auto &res) {
|
||||
cs.run(args[0].get_code(), res);
|
||||
});
|
||||
static_cast<cs_command_impl *>(p)->p_type = ID_DO;
|
||||
static_cast<command_impl *>(p)->p_type = ID_DO;
|
||||
|
||||
p = new_command("doargs", "e", [](auto &cs, auto args, auto &res) {
|
||||
cs_do_args(cs, [&cs, &res, &args]() {
|
||||
call_with_args(cs, [&cs, &res, &args]() {
|
||||
cs.run(args[0].get_code(), res);
|
||||
});
|
||||
});
|
||||
static_cast<cs_command_impl *>(p)->p_type = ID_DOARGS;
|
||||
static_cast<command_impl *>(p)->p_type = ID_DOARGS;
|
||||
|
||||
p = new_command("if", "tee", [](auto &cs, auto args, auto &res) {
|
||||
cs.run((args[0].get_bool() ? args[1] : args[2]).get_code(), res);
|
||||
});
|
||||
static_cast<cs_command_impl *>(p)->p_type = ID_IF;
|
||||
static_cast<command_impl *>(p)->p_type = ID_IF;
|
||||
|
||||
p = new_command("result", "t", [](auto &, auto args, auto &res) {
|
||||
res = std::move(args[0]);
|
||||
});
|
||||
static_cast<cs_command_impl *>(p)->p_type = ID_RESULT;
|
||||
static_cast<command_impl *>(p)->p_type = ID_RESULT;
|
||||
|
||||
p = new_command("!", "t", [](auto &, auto args, auto &res) {
|
||||
res.set_int(!args[0].get_bool());
|
||||
});
|
||||
static_cast<cs_command_impl *>(p)->p_type = ID_NOT;
|
||||
static_cast<command_impl *>(p)->p_type = ID_NOT;
|
||||
|
||||
p = new_command("&&", "E1V", [](auto &cs, auto args, auto &res) {
|
||||
if (args.empty()) {
|
||||
res.set_int(1);
|
||||
} else {
|
||||
for (size_t i = 0; i < args.size(); ++i) {
|
||||
cs_bcode *code = args[i].get_code();
|
||||
bcode *code = args[i].get_code();
|
||||
if (code) {
|
||||
cs.run(code, res);
|
||||
} else {
|
||||
|
@ -131,14 +131,14 @@ cs_state::cs_state(cs_alloc_cb func, void *data):
|
|||
}
|
||||
}
|
||||
});
|
||||
static_cast<cs_command_impl *>(p)->p_type = ID_AND;
|
||||
static_cast<command_impl *>(p)->p_type = ID_AND;
|
||||
|
||||
p = new_command("||", "E1V", [](auto &cs, auto args, auto &res) {
|
||||
if (args.empty()) {
|
||||
res.set_int(0);
|
||||
} else {
|
||||
for (size_t i = 0; i < args.size(); ++i) {
|
||||
cs_bcode *code = args[i].get_code();
|
||||
bcode *code = args[i].get_code();
|
||||
if (code) {
|
||||
cs.run(code, res);
|
||||
} else {
|
||||
|
@ -150,134 +150,134 @@ cs_state::cs_state(cs_alloc_cb func, void *data):
|
|||
}
|
||||
}
|
||||
});
|
||||
static_cast<cs_command_impl *>(p)->p_type = ID_OR;
|
||||
static_cast<command_impl *>(p)->p_type = ID_OR;
|
||||
|
||||
p = new_command("local", "", nullptr);
|
||||
static_cast<cs_command_impl *>(p)->p_type = ID_LOCAL;
|
||||
static_cast<command_impl *>(p)->p_type = ID_LOCAL;
|
||||
|
||||
p = new_command("break", "", [](auto &cs, auto, auto &) {
|
||||
if (cs.is_in_loop()) {
|
||||
throw CsBreakException{};
|
||||
} else {
|
||||
throw cs_error{cs, "no loop to break"};
|
||||
throw error{cs, "no loop to break"};
|
||||
}
|
||||
});
|
||||
static_cast<cs_command_impl *>(p)->p_type = ID_BREAK;
|
||||
static_cast<command_impl *>(p)->p_type = ID_BREAK;
|
||||
|
||||
p = new_command("continue", "", [](auto &cs, auto, auto &) {
|
||||
if (cs.is_in_loop()) {
|
||||
throw CsContinueException{};
|
||||
} else {
|
||||
throw cs_error{cs, "no loop to continue"};
|
||||
throw error{cs, "no loop to continue"};
|
||||
}
|
||||
});
|
||||
static_cast<cs_command_impl *>(p)->p_type = ID_CONTINUE;
|
||||
static_cast<command_impl *>(p)->p_type = ID_CONTINUE;
|
||||
|
||||
cs_init_lib_base(*this);
|
||||
init_lib_base(*this);
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_state::~cs_state() {
|
||||
LIBCUBESCRIPT_EXPORT state::~state() {
|
||||
destroy();
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT void cs_state::destroy() {
|
||||
LIBCUBESCRIPT_EXPORT void state::destroy() {
|
||||
if (!p_state || !p_owner) {
|
||||
return;
|
||||
}
|
||||
for (auto &p: p_state->idents) {
|
||||
cs_ident *i = p.second;
|
||||
cs_alias *a = i->get_alias();
|
||||
ident *i = p.second;
|
||||
alias *a = i->get_alias();
|
||||
if (a) {
|
||||
a->get_value().force_none();
|
||||
static_cast<cs_alias_impl *>(a)->clean_code();
|
||||
static_cast<alias_impl *>(a)->clean_code();
|
||||
}
|
||||
p_state->destroy(i->p_impl);
|
||||
}
|
||||
p_state->destroy(static_cast<cs_charbuf *>(p_errbuf));
|
||||
p_state->destroy(static_cast<charbuf *>(p_errbuf));
|
||||
p_state->destroy(p_state);
|
||||
}
|
||||
|
||||
cs_state::cs_state(cs_shared_state *s):
|
||||
state::state(internal_state *s):
|
||||
p_state(s), p_owner(false)
|
||||
{}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_state cs_state::new_thread() {
|
||||
return cs_state{p_state};
|
||||
LIBCUBESCRIPT_EXPORT state state::new_thread() {
|
||||
return state{p_state};
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_hook_cb cs_state::set_call_hook(cs_hook_cb func) {
|
||||
LIBCUBESCRIPT_EXPORT hook_func state::set_call_hook(hook_func func) {
|
||||
auto hk = std::move(p_callhook);
|
||||
p_callhook = std::move(func);
|
||||
return hk;
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_hook_cb const &cs_state::get_call_hook() const {
|
||||
LIBCUBESCRIPT_EXPORT hook_func const &state::get_call_hook() const {
|
||||
return p_callhook;
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_hook_cb &cs_state::get_call_hook() {
|
||||
LIBCUBESCRIPT_EXPORT hook_func &state::get_call_hook() {
|
||||
return p_callhook;
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_vprint_cb cs_state::set_var_printer(
|
||||
cs_vprint_cb func
|
||||
LIBCUBESCRIPT_EXPORT var_print_func state::set_var_printer(
|
||||
var_print_func func
|
||||
) {
|
||||
auto fn = std::move(p_state->varprintf);
|
||||
p_state->varprintf = std::move(func);
|
||||
return fn;
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_vprint_cb const &cs_state::get_var_printer() const {
|
||||
LIBCUBESCRIPT_EXPORT var_print_func const &state::get_var_printer() const {
|
||||
return p_state->varprintf;
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT void cs_state::print_var(cs_var const &v) const {
|
||||
LIBCUBESCRIPT_EXPORT void state::print_var(global_var const &v) const {
|
||||
if (p_state->varprintf) {
|
||||
p_state->varprintf(*this, v);
|
||||
}
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT void *cs_state::alloc(void *ptr, size_t os, size_t ns) {
|
||||
LIBCUBESCRIPT_EXPORT void *state::alloc(void *ptr, size_t os, size_t ns) {
|
||||
return p_state->alloc(ptr, os, ns);
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_ident *cs_state::add_ident(
|
||||
cs_ident *id, cs_ident_impl *impl
|
||||
LIBCUBESCRIPT_EXPORT ident *state::add_ident(
|
||||
ident *id, ident_impl *impl
|
||||
) {
|
||||
if (!id) {
|
||||
return nullptr;
|
||||
}
|
||||
id->p_impl = impl;
|
||||
p_state->idents[id->get_name()] = id;
|
||||
static_cast<cs_ident_impl *>(impl)->p_index = p_state->identmap.size();
|
||||
static_cast<ident_impl *>(impl)->p_index = p_state->identmap.size();
|
||||
p_state->identmap.push_back(id);
|
||||
return p_state->identmap.back();
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_ident *cs_state::new_ident(
|
||||
LIBCUBESCRIPT_EXPORT ident *state::new_ident(
|
||||
std::string_view name, int flags
|
||||
) {
|
||||
cs_ident *id = get_ident(name);
|
||||
ident *id = get_ident(name);
|
||||
if (!id) {
|
||||
if (!is_valid_name(name)) {
|
||||
throw cs_error{
|
||||
throw error{
|
||||
*this, "number %s is not a valid identifier name", name.data()
|
||||
};
|
||||
}
|
||||
auto *inst = p_state->create<cs_alias_impl>(
|
||||
*this, cs_strref{p_state, name}, flags
|
||||
auto *inst = p_state->create<alias_impl>(
|
||||
*this, string_ref{p_state, name}, flags
|
||||
);
|
||||
id = add_ident(inst, inst);
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_ident *cs_state::force_ident(cs_value &v) {
|
||||
LIBCUBESCRIPT_EXPORT ident *state::force_ident(any_value &v) {
|
||||
switch (v.get_type()) {
|
||||
case cs_value_type::IDENT:
|
||||
case value_type::IDENT:
|
||||
return v.get_ident();
|
||||
case cs_value_type::STRING: {
|
||||
cs_ident *id = new_ident(v.get_str());
|
||||
case value_type::STRING: {
|
||||
ident *id = new_ident(v.get_str());
|
||||
v.set_ident(id);
|
||||
return id;
|
||||
}
|
||||
|
@ -288,7 +288,7 @@ LIBCUBESCRIPT_EXPORT cs_ident *cs_state::force_ident(cs_value &v) {
|
|||
return p_state->identmap[DummyIdx];
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_ident *cs_state::get_ident(std::string_view name) {
|
||||
LIBCUBESCRIPT_EXPORT ident *state::get_ident(std::string_view name) {
|
||||
auto id = p_state->idents.find(name);
|
||||
if (id != p_state->idents.end()) {
|
||||
return id->second;
|
||||
|
@ -296,88 +296,89 @@ LIBCUBESCRIPT_EXPORT cs_ident *cs_state::get_ident(std::string_view name) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_alias *cs_state::get_alias(std::string_view name) {
|
||||
LIBCUBESCRIPT_EXPORT alias *state::get_alias(std::string_view name) {
|
||||
auto id = get_ident(name);
|
||||
if (!id || !id->is_alias()) {
|
||||
return nullptr;
|
||||
}
|
||||
return static_cast<cs_alias *>(id);
|
||||
return static_cast<alias *>(id);
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT bool cs_state::have_ident(std::string_view name) {
|
||||
LIBCUBESCRIPT_EXPORT bool state::have_ident(std::string_view name) {
|
||||
return p_state->idents.find(name) != p_state->idents.end();
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT std::span<cs_ident *> cs_state::get_idents() {
|
||||
return std::span<cs_ident *>{
|
||||
LIBCUBESCRIPT_EXPORT std::span<ident *> state::get_idents() {
|
||||
return std::span<ident *>{
|
||||
p_state->identmap.data(),
|
||||
p_state->identmap.size()
|
||||
};
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT std::span<cs_ident const *> cs_state::get_idents() const {
|
||||
auto ptr = const_cast<cs_ident const **>(p_state->identmap.data());
|
||||
return std::span<cs_ident const *>{ptr, p_state->identmap.size()};
|
||||
LIBCUBESCRIPT_EXPORT std::span<ident const *> state::get_idents() const {
|
||||
auto ptr = const_cast<ident const **>(p_state->identmap.data());
|
||||
return std::span<ident const *>{ptr, p_state->identmap.size()};
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_ivar *cs_state::new_ivar(
|
||||
std::string_view n, cs_int m, cs_int x, cs_int v, cs_var_cb f, int flags
|
||||
LIBCUBESCRIPT_EXPORT integer_var *state::new_ivar(
|
||||
std::string_view n, integer_type m, integer_type x, integer_type v,
|
||||
var_cb_func f, int flags
|
||||
) {
|
||||
auto *iv = p_state->create<cs_ivar_impl>(
|
||||
cs_strref{p_state, n}, m, x, v, std::move(f), flags
|
||||
auto *iv = p_state->create<ivar_impl>(
|
||||
string_ref{p_state, n}, m, x, v, std::move(f), flags
|
||||
);
|
||||
add_ident(iv, iv);
|
||||
return iv;
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_fvar *cs_state::new_fvar(
|
||||
std::string_view n, cs_float m, cs_float x, cs_float v,
|
||||
cs_var_cb f, int flags
|
||||
LIBCUBESCRIPT_EXPORT float_var *state::new_fvar(
|
||||
std::string_view n, float_type m, float_type x, float_type v,
|
||||
var_cb_func f, int flags
|
||||
) {
|
||||
auto *fv = p_state->create<cs_fvar_impl>(
|
||||
cs_strref{p_state, n}, m, x, v, std::move(f), flags
|
||||
auto *fv = p_state->create<fvar_impl>(
|
||||
string_ref{p_state, n}, m, x, v, std::move(f), flags
|
||||
);
|
||||
add_ident(fv, fv);
|
||||
return fv;
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_svar *cs_state::new_svar(
|
||||
std::string_view n, std::string_view v, cs_var_cb f, int flags
|
||||
LIBCUBESCRIPT_EXPORT string_var *state::new_svar(
|
||||
std::string_view n, std::string_view v, var_cb_func f, int flags
|
||||
) {
|
||||
auto *sv = p_state->create<cs_svar_impl>(
|
||||
cs_strref{p_state, n}, cs_strref{p_state, v},
|
||||
cs_strref{p_state, ""}, std::move(f), flags
|
||||
auto *sv = p_state->create<svar_impl>(
|
||||
string_ref{p_state, n}, string_ref{p_state, v},
|
||||
string_ref{p_state, ""}, std::move(f), flags
|
||||
);
|
||||
add_ident(sv, sv);
|
||||
return sv;
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT void cs_state::reset_var(std::string_view name) {
|
||||
cs_ident *id = get_ident(name);
|
||||
LIBCUBESCRIPT_EXPORT void state::reset_var(std::string_view name) {
|
||||
ident *id = get_ident(name);
|
||||
if (!id) {
|
||||
throw cs_error{*this, "variable %s does not exist", name.data()};
|
||||
throw error{*this, "variable %s does not exist", name.data()};
|
||||
}
|
||||
if (id->get_flags() & CS_IDF_READONLY) {
|
||||
throw cs_error{*this, "variable %s is read only", name.data()};
|
||||
if (id->get_flags() & IDENT_FLAG_READONLY) {
|
||||
throw error{*this, "variable %s is read only", name.data()};
|
||||
}
|
||||
clear_override(*id);
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT void cs_state::touch_var(std::string_view name) {
|
||||
cs_ident *id = get_ident(name);
|
||||
LIBCUBESCRIPT_EXPORT void state::touch_var(std::string_view name) {
|
||||
ident *id = get_ident(name);
|
||||
if (id && id->is_var()) {
|
||||
static_cast<cs_var_impl *>(id->p_impl)->changed(*this);
|
||||
static_cast<var_impl *>(id->p_impl)->changed(*this);
|
||||
}
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT void cs_state::set_alias(
|
||||
std::string_view name, cs_value v
|
||||
LIBCUBESCRIPT_EXPORT void state::set_alias(
|
||||
std::string_view name, any_value v
|
||||
) {
|
||||
cs_ident *id = get_ident(name);
|
||||
ident *id = get_ident(name);
|
||||
if (id) {
|
||||
switch (id->get_type()) {
|
||||
case cs_ident_type::ALIAS: {
|
||||
cs_alias_impl *a = static_cast<cs_alias_impl *>(id);
|
||||
case ident_type::ALIAS: {
|
||||
alias_impl *a = static_cast<alias_impl *>(id);
|
||||
if (a->get_index() < MaxArguments) {
|
||||
a->set_arg(*this, v);
|
||||
} else {
|
||||
|
@ -385,33 +386,33 @@ LIBCUBESCRIPT_EXPORT void cs_state::set_alias(
|
|||
}
|
||||
return;
|
||||
}
|
||||
case cs_ident_type::IVAR:
|
||||
set_var_int_checked(static_cast<cs_ivar *>(id), v.get_int());
|
||||
case ident_type::IVAR:
|
||||
set_var_int_checked(static_cast<integer_var *>(id), v.get_int());
|
||||
break;
|
||||
case cs_ident_type::FVAR:
|
||||
set_var_float_checked(static_cast<cs_fvar *>(id), v.get_float());
|
||||
case ident_type::FVAR:
|
||||
set_var_float_checked(static_cast<float_var *>(id), v.get_float());
|
||||
break;
|
||||
case cs_ident_type::SVAR:
|
||||
set_var_str_checked(static_cast<cs_svar *>(id), v.get_str());
|
||||
case ident_type::SVAR:
|
||||
set_var_str_checked(static_cast<string_var *>(id), v.get_str());
|
||||
break;
|
||||
default:
|
||||
throw cs_error{
|
||||
throw error{
|
||||
*this, "cannot redefine builtin %s with an alias",
|
||||
id->get_name().data()
|
||||
};
|
||||
}
|
||||
} else if (!is_valid_name(name)) {
|
||||
throw cs_error{*this, "cannot alias invalid name '%s'", name.data()};
|
||||
throw error{*this, "cannot alias invalid name '%s'", name.data()};
|
||||
} else {
|
||||
auto *a = p_state->create<cs_alias_impl>(
|
||||
*this, cs_strref{p_state, name}, std::move(v), identflags
|
||||
auto *a = p_state->create<alias_impl>(
|
||||
*this, string_ref{p_state, name}, std::move(v), identflags
|
||||
);
|
||||
add_ident(a, a);
|
||||
}
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_command *cs_state::new_command(
|
||||
std::string_view name, std::string_view args, cs_command_cb func
|
||||
LIBCUBESCRIPT_EXPORT command *state::new_command(
|
||||
std::string_view name, std::string_view args, command_func func
|
||||
) {
|
||||
int nargs = 0;
|
||||
for (auto fmt = args.begin(); fmt != args.end(); ++fmt) {
|
||||
|
@ -459,39 +460,39 @@ LIBCUBESCRIPT_EXPORT cs_command *cs_state::new_command(
|
|||
return nullptr;
|
||||
}
|
||||
}
|
||||
auto *cmd = p_state->create<cs_command_impl>(
|
||||
cs_strref{p_state, name}, cs_strref{p_state, args}, nargs,
|
||||
auto *cmd = p_state->create<command_impl>(
|
||||
string_ref{p_state, name}, string_ref{p_state, args}, nargs,
|
||||
std::move(func)
|
||||
);
|
||||
add_ident(cmd, cmd);
|
||||
return cmd;
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT void cs_state::clear_override(cs_ident &id) {
|
||||
if (!(id.get_flags() & CS_IDF_OVERRIDDEN)) {
|
||||
LIBCUBESCRIPT_EXPORT void state::clear_override(ident &id) {
|
||||
if (!(id.get_flags() & IDENT_FLAG_OVERRIDDEN)) {
|
||||
return;
|
||||
}
|
||||
switch (id.get_type()) {
|
||||
case cs_ident_type::ALIAS: {
|
||||
cs_alias_impl &a = static_cast<cs_alias_impl &>(id);
|
||||
case ident_type::ALIAS: {
|
||||
alias_impl &a = static_cast<alias_impl &>(id);
|
||||
a.clean_code();
|
||||
a.get_value().set_str("");
|
||||
break;
|
||||
}
|
||||
case cs_ident_type::IVAR: {
|
||||
cs_ivar_impl &iv = static_cast<cs_ivar_impl &>(id);
|
||||
case ident_type::IVAR: {
|
||||
ivar_impl &iv = static_cast<ivar_impl &>(id);
|
||||
iv.set_value(iv.p_overrideval);
|
||||
iv.changed(*this);
|
||||
break;
|
||||
}
|
||||
case cs_ident_type::FVAR: {
|
||||
cs_fvar_impl &fv = static_cast<cs_fvar_impl &>(id);
|
||||
case ident_type::FVAR: {
|
||||
fvar_impl &fv = static_cast<fvar_impl &>(id);
|
||||
fv.set_value(fv.p_overrideval);
|
||||
fv.changed(*this);
|
||||
break;
|
||||
}
|
||||
case cs_ident_type::SVAR: {
|
||||
cs_svar_impl &sv = static_cast<cs_svar_impl &>(id);
|
||||
case ident_type::SVAR: {
|
||||
svar_impl &sv = static_cast<svar_impl &>(id);
|
||||
sv.set_value(sv.p_overrideval);
|
||||
sv.changed(*this);
|
||||
break;
|
||||
|
@ -499,44 +500,44 @@ LIBCUBESCRIPT_EXPORT void cs_state::clear_override(cs_ident &id) {
|
|||
default:
|
||||
break;
|
||||
}
|
||||
id.p_impl->p_flags &= ~CS_IDF_OVERRIDDEN;
|
||||
id.p_impl->p_flags &= ~IDENT_FLAG_OVERRIDDEN;
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT void cs_state::clear_overrides() {
|
||||
LIBCUBESCRIPT_EXPORT void state::clear_overrides() {
|
||||
for (auto &p: p_state->idents) {
|
||||
clear_override(*(p.second));
|
||||
}
|
||||
}
|
||||
|
||||
template<typename SF>
|
||||
inline void cs_override_var(cs_state &cs, cs_var *v, int &vflags, SF sf) {
|
||||
if ((cs.identflags & CS_IDF_OVERRIDDEN) || (vflags & CS_IDF_OVERRIDE)) {
|
||||
if (vflags & CS_IDF_PERSIST) {
|
||||
throw cs_error{
|
||||
inline void override_var(state &cs, global_var *v, int &vflags, SF sf) {
|
||||
if ((cs.identflags & IDENT_FLAG_OVERRIDDEN) || (vflags & IDENT_FLAG_OVERRIDE)) {
|
||||
if (vflags & IDENT_FLAG_PERSIST) {
|
||||
throw error{
|
||||
cs, "cannot override persistent variable '%s'",
|
||||
v->get_name().data()
|
||||
};
|
||||
}
|
||||
if (!(vflags & CS_IDF_OVERRIDDEN)) {
|
||||
if (!(vflags & IDENT_FLAG_OVERRIDDEN)) {
|
||||
sf();
|
||||
vflags |= CS_IDF_OVERRIDDEN;
|
||||
vflags |= IDENT_FLAG_OVERRIDDEN;
|
||||
}
|
||||
} else {
|
||||
if (vflags & CS_IDF_OVERRIDDEN) {
|
||||
vflags &= ~CS_IDF_OVERRIDDEN;
|
||||
if (vflags & IDENT_FLAG_OVERRIDDEN) {
|
||||
vflags &= ~IDENT_FLAG_OVERRIDDEN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT void cs_state::set_var_int(
|
||||
std::string_view name, cs_int v, bool dofunc, bool doclamp
|
||||
LIBCUBESCRIPT_EXPORT void state::set_var_int(
|
||||
std::string_view name, integer_type v, bool dofunc, bool doclamp
|
||||
) {
|
||||
cs_ident *id = get_ident(name);
|
||||
ident *id = get_ident(name);
|
||||
if (!id || id->is_ivar()) {
|
||||
return;
|
||||
}
|
||||
cs_ivar_impl *iv = static_cast<cs_ivar_impl *>(id);
|
||||
cs_override_var(
|
||||
ivar_impl *iv = static_cast<ivar_impl *>(id);
|
||||
override_var(
|
||||
*this, iv, iv->p_flags,
|
||||
[&iv]() { iv->p_overrideval = iv->get_value(); }
|
||||
);
|
||||
|
@ -550,15 +551,15 @@ LIBCUBESCRIPT_EXPORT void cs_state::set_var_int(
|
|||
}
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT void cs_state::set_var_float(
|
||||
std::string_view name, cs_float v, bool dofunc, bool doclamp
|
||||
LIBCUBESCRIPT_EXPORT void state::set_var_float(
|
||||
std::string_view name, float_type v, bool dofunc, bool doclamp
|
||||
) {
|
||||
cs_ident *id = get_ident(name);
|
||||
ident *id = get_ident(name);
|
||||
if (!id || id->is_fvar()) {
|
||||
return;
|
||||
}
|
||||
cs_fvar_impl *fv = static_cast<cs_fvar_impl *>(id);
|
||||
cs_override_var(
|
||||
fvar_impl *fv = static_cast<fvar_impl *>(id);
|
||||
override_var(
|
||||
*this, fv, fv->p_flags,
|
||||
[&fv]() { fv->p_overrideval = fv->get_value(); }
|
||||
);
|
||||
|
@ -572,90 +573,90 @@ LIBCUBESCRIPT_EXPORT void cs_state::set_var_float(
|
|||
}
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT void cs_state::set_var_str(
|
||||
LIBCUBESCRIPT_EXPORT void state::set_var_str(
|
||||
std::string_view name, std::string_view v, bool dofunc
|
||||
) {
|
||||
cs_ident *id = get_ident(name);
|
||||
ident *id = get_ident(name);
|
||||
if (!id || id->is_svar()) {
|
||||
return;
|
||||
}
|
||||
cs_svar_impl *sv = static_cast<cs_svar_impl *>(id);
|
||||
cs_override_var(
|
||||
svar_impl *sv = static_cast<svar_impl *>(id);
|
||||
override_var(
|
||||
*this, sv, sv->p_flags,
|
||||
[&sv]() { sv->p_overrideval = sv->get_value(); }
|
||||
);
|
||||
sv->set_value(cs_strref{p_state, v});
|
||||
sv->set_value(string_ref{p_state, v});
|
||||
if (dofunc) {
|
||||
sv->changed(*this);
|
||||
}
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT std::optional<cs_int>
|
||||
cs_state::get_var_int(std::string_view name) {
|
||||
cs_ident *id = get_ident(name);
|
||||
LIBCUBESCRIPT_EXPORT std::optional<integer_type>
|
||||
state::get_var_int(std::string_view name) {
|
||||
ident *id = get_ident(name);
|
||||
if (!id || id->is_ivar()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return static_cast<cs_ivar *>(id)->get_value();
|
||||
return static_cast<integer_var *>(id)->get_value();
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT std::optional<cs_float>
|
||||
cs_state::get_var_float(std::string_view name) {
|
||||
cs_ident *id = get_ident(name);
|
||||
LIBCUBESCRIPT_EXPORT std::optional<float_type>
|
||||
state::get_var_float(std::string_view name) {
|
||||
ident *id = get_ident(name);
|
||||
if (!id || id->is_fvar()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return static_cast<cs_fvar *>(id)->get_value();
|
||||
return static_cast<float_var *>(id)->get_value();
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT std::optional<cs_strref>
|
||||
cs_state::get_var_str(std::string_view name) {
|
||||
cs_ident *id = get_ident(name);
|
||||
LIBCUBESCRIPT_EXPORT std::optional<string_ref>
|
||||
state::get_var_str(std::string_view name) {
|
||||
ident *id = get_ident(name);
|
||||
if (!id || id->is_svar()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return cs_strref{p_state, static_cast<cs_svar *>(id)->get_value()};
|
||||
return string_ref{p_state, static_cast<string_var *>(id)->get_value()};
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT std::optional<cs_int>
|
||||
cs_state::get_var_min_int(std::string_view name) {
|
||||
cs_ident *id = get_ident(name);
|
||||
LIBCUBESCRIPT_EXPORT std::optional<integer_type>
|
||||
state::get_var_min_int(std::string_view name) {
|
||||
ident *id = get_ident(name);
|
||||
if (!id || id->is_ivar()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return static_cast<cs_ivar *>(id)->get_val_min();
|
||||
return static_cast<integer_var *>(id)->get_val_min();
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT std::optional<cs_int>
|
||||
cs_state::get_var_max_int(std::string_view name) {
|
||||
cs_ident *id = get_ident(name);
|
||||
LIBCUBESCRIPT_EXPORT std::optional<integer_type>
|
||||
state::get_var_max_int(std::string_view name) {
|
||||
ident *id = get_ident(name);
|
||||
if (!id || id->is_ivar()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return static_cast<cs_ivar *>(id)->get_val_max();
|
||||
return static_cast<integer_var *>(id)->get_val_max();
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT std::optional<cs_float>
|
||||
cs_state::get_var_min_float(std::string_view name) {
|
||||
cs_ident *id = get_ident(name);
|
||||
LIBCUBESCRIPT_EXPORT std::optional<float_type>
|
||||
state::get_var_min_float(std::string_view name) {
|
||||
ident *id = get_ident(name);
|
||||
if (!id || id->is_fvar()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return static_cast<cs_fvar *>(id)->get_val_min();
|
||||
return static_cast<float_var *>(id)->get_val_min();
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT std::optional<cs_float>
|
||||
cs_state::get_var_max_float(std::string_view name) {
|
||||
cs_ident *id = get_ident(name);
|
||||
LIBCUBESCRIPT_EXPORT std::optional<float_type>
|
||||
state::get_var_max_float(std::string_view name) {
|
||||
ident *id = get_ident(name);
|
||||
if (!id || id->is_fvar()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return static_cast<cs_fvar *>(id)->get_val_max();
|
||||
return static_cast<float_var *>(id)->get_val_max();
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT std::optional<cs_strref>
|
||||
cs_state::get_alias_val(std::string_view name) {
|
||||
cs_alias *a = get_alias(name);
|
||||
LIBCUBESCRIPT_EXPORT std::optional<string_ref>
|
||||
state::get_alias_val(std::string_view name) {
|
||||
alias *a = get_alias(name);
|
||||
if (!a) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
@ -665,7 +666,7 @@ cs_state::get_alias_val(std::string_view name) {
|
|||
return a->get_value().get_str();
|
||||
}
|
||||
|
||||
cs_int cs_clamp_var(cs_state &cs, cs_ivar *iv, cs_int v) {
|
||||
integer_type clamp_var(state &cs, integer_var *iv, integer_type v) {
|
||||
if (v < iv->get_val_min()) {
|
||||
v = iv->get_val_min();
|
||||
} else if (v > iv->get_val_max()) {
|
||||
|
@ -673,9 +674,9 @@ cs_int cs_clamp_var(cs_state &cs, cs_ivar *iv, cs_int v) {
|
|||
} else {
|
||||
return v;
|
||||
}
|
||||
throw cs_error{
|
||||
throw error{
|
||||
cs,
|
||||
(iv->get_flags() & CS_IDF_HEX)
|
||||
(iv->get_flags() & IDENT_FLAG_HEX)
|
||||
? (
|
||||
(iv->get_val_min() <= 255)
|
||||
? "valid range for '%s' is %d..0x%X"
|
||||
|
@ -686,29 +687,31 @@ cs_int cs_clamp_var(cs_state &cs, cs_ivar *iv, cs_int v) {
|
|||
};
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT void cs_state::set_var_int_checked(cs_ivar *iv, cs_int v) {
|
||||
if (iv->get_flags() & CS_IDF_READONLY) {
|
||||
throw cs_error{
|
||||
LIBCUBESCRIPT_EXPORT void state::set_var_int_checked(
|
||||
integer_var *iv, integer_type v
|
||||
) {
|
||||
if (iv->get_flags() & IDENT_FLAG_READONLY) {
|
||||
throw error{
|
||||
*this, "variable '%s' is read only", iv->get_name().data()
|
||||
};
|
||||
}
|
||||
cs_ivar_impl *ivp = static_cast<cs_ivar_impl *>(iv);
|
||||
cs_override_var(
|
||||
ivar_impl *ivp = static_cast<ivar_impl *>(iv);
|
||||
override_var(
|
||||
*this, iv, ivp->p_flags,
|
||||
[&ivp]() { ivp->p_overrideval = ivp->p_storage; }
|
||||
);
|
||||
if ((v < iv->get_val_min()) || (v > iv->get_val_max())) {
|
||||
v = cs_clamp_var(*this, iv, v);
|
||||
v = clamp_var(*this, iv, v);
|
||||
}
|
||||
iv->set_value(v);
|
||||
ivp->changed(*this);
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT void cs_state::set_var_int_checked(
|
||||
cs_ivar *iv, std::span<cs_value> args
|
||||
LIBCUBESCRIPT_EXPORT void state::set_var_int_checked(
|
||||
integer_var *iv, std::span<any_value> args
|
||||
) {
|
||||
cs_int v = args[0].force_int();
|
||||
if ((iv->get_flags() & CS_IDF_HEX) && (args.size() > 1)) {
|
||||
integer_type v = args[0].force_int();
|
||||
if ((iv->get_flags() & IDENT_FLAG_HEX) && (args.size() > 1)) {
|
||||
v = (v << 16) | (args[1].force_int() << 8);
|
||||
if (args.size() > 2) {
|
||||
v |= args[2].force_int();
|
||||
|
@ -717,7 +720,7 @@ LIBCUBESCRIPT_EXPORT void cs_state::set_var_int_checked(
|
|||
set_var_int_checked(iv, v);
|
||||
}
|
||||
|
||||
cs_float cs_clamp_fvar(cs_state &cs, cs_fvar *fv, cs_float v) {
|
||||
float_type clamp_fvar(state &cs, float_var *fv, float_type v) {
|
||||
if (v < fv->get_val_min()) {
|
||||
v = fv->get_val_min();
|
||||
} else if (v > fv->get_val_max()) {
|
||||
|
@ -725,62 +728,62 @@ cs_float cs_clamp_fvar(cs_state &cs, cs_fvar *fv, cs_float v) {
|
|||
} else {
|
||||
return v;
|
||||
}
|
||||
cs_value vmin{cs}, vmax{cs};
|
||||
any_value vmin{cs}, vmax{cs};
|
||||
vmin.set_float(fv->get_val_min());
|
||||
vmax.set_float(fv->get_val_max());
|
||||
throw cs_error{
|
||||
throw error{
|
||||
cs, "valid range for '%s' is %s..%s", fv->get_name().data(),
|
||||
vmin.force_str(), vmax.force_str()
|
||||
};
|
||||
return v;
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT void cs_state::set_var_float_checked(
|
||||
cs_fvar *fv, cs_float v
|
||||
LIBCUBESCRIPT_EXPORT void state::set_var_float_checked(
|
||||
float_var *fv, float_type v
|
||||
) {
|
||||
if (fv->get_flags() & CS_IDF_READONLY) {
|
||||
throw cs_error{
|
||||
if (fv->get_flags() & IDENT_FLAG_READONLY) {
|
||||
throw error{
|
||||
*this, "variable '%s' is read only", fv->get_name().data()
|
||||
};
|
||||
}
|
||||
cs_fvar_impl *fvp = static_cast<cs_fvar_impl *>(fv);
|
||||
cs_override_var(
|
||||
fvar_impl *fvp = static_cast<fvar_impl *>(fv);
|
||||
override_var(
|
||||
*this, fv, fvp->p_flags,
|
||||
[&fvp]() { fvp->p_overrideval = fvp->p_storage; }
|
||||
);
|
||||
if ((v < fv->get_val_min()) || (v > fv->get_val_max())) {
|
||||
v = cs_clamp_fvar(*this, fv, v);
|
||||
v = clamp_fvar(*this, fv, v);
|
||||
}
|
||||
fv->set_value(v);
|
||||
fvp->changed(*this);
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT void cs_state::set_var_str_checked(
|
||||
cs_svar *sv, std::string_view v
|
||||
LIBCUBESCRIPT_EXPORT void state::set_var_str_checked(
|
||||
string_var *sv, std::string_view v
|
||||
) {
|
||||
if (sv->get_flags() & CS_IDF_READONLY) {
|
||||
throw cs_error{
|
||||
if (sv->get_flags() & IDENT_FLAG_READONLY) {
|
||||
throw error{
|
||||
*this, "variable '%s' is read only", sv->get_name().data()
|
||||
};
|
||||
}
|
||||
cs_svar_impl *svp = static_cast<cs_svar_impl *>(sv);
|
||||
cs_override_var(
|
||||
svar_impl *svp = static_cast<svar_impl *>(sv);
|
||||
override_var(
|
||||
*this, sv, svp->p_flags,
|
||||
[&svp]() { svp->p_overrideval = svp->p_storage; }
|
||||
);
|
||||
sv->set_value(cs_strref{p_state, v});
|
||||
sv->set_value(string_ref{p_state, v});
|
||||
svp->changed(*this);
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT void cs_state::init_libs(int libs) {
|
||||
if (libs & CS_LIB_MATH) {
|
||||
cs_init_lib_math(*this);
|
||||
LIBCUBESCRIPT_EXPORT void state::init_libs(int libs) {
|
||||
if (libs & LIB_MATH) {
|
||||
init_lib_math(*this);
|
||||
}
|
||||
if (libs & CS_LIB_STRING) {
|
||||
cs_init_lib_string(*this);
|
||||
if (libs & LIB_STRING) {
|
||||
init_lib_string(*this);
|
||||
}
|
||||
if (libs & CS_LIB_LIST) {
|
||||
cs_init_lib_list(*this);
|
||||
if (libs & LIB_LIST) {
|
||||
init_lib_list(*this);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,55 +10,55 @@
|
|||
|
||||
namespace cscript {
|
||||
|
||||
struct cs_state;
|
||||
struct cs_shared_state;
|
||||
struct cs_strman;
|
||||
struct state;
|
||||
struct internal_state;
|
||||
struct string_pool;
|
||||
|
||||
template<typename T>
|
||||
struct cs_allocator {
|
||||
struct std_allocator {
|
||||
using value_type = T;
|
||||
|
||||
inline cs_allocator(cs_shared_state *s);
|
||||
inline cs_allocator(cs_state &cs);
|
||||
inline std_allocator(internal_state *s);
|
||||
inline std_allocator(state &cs);
|
||||
|
||||
template<typename U>
|
||||
cs_allocator(cs_allocator<U> const &a): state{a.state} {};
|
||||
std_allocator(std_allocator<U> const &a): istate{a.istate} {};
|
||||
|
||||
inline T *allocate(std::size_t n);
|
||||
inline void deallocate(T *p, std::size_t n);
|
||||
|
||||
template<typename U>
|
||||
bool operator==(cs_allocator<U> const &a) {
|
||||
return state == a.state;
|
||||
bool operator==(std_allocator<U> const &a) {
|
||||
return istate == a.istate;
|
||||
}
|
||||
|
||||
cs_shared_state *state;
|
||||
internal_state *istate;
|
||||
};
|
||||
|
||||
struct cs_shared_state {
|
||||
using allocator_type = cs_allocator<
|
||||
std::pair<std::string_view const, cs_ident *>
|
||||
struct internal_state {
|
||||
using allocator_type = std_allocator<
|
||||
std::pair<std::string_view const, ident *>
|
||||
>;
|
||||
cs_alloc_cb allocf;
|
||||
alloc_func allocf;
|
||||
void *aptr;
|
||||
|
||||
std::unordered_map<
|
||||
std::string_view, cs_ident *,
|
||||
std::string_view, ident *,
|
||||
std::hash<std::string_view>,
|
||||
std::equal_to<std::string_view>,
|
||||
allocator_type
|
||||
> idents;
|
||||
std::vector<cs_ident *, cs_allocator<cs_ident *>> identmap;
|
||||
std::vector<ident *, std_allocator<ident *>> identmap;
|
||||
|
||||
cs_vprint_cb varprintf;
|
||||
cs_strman *strman;
|
||||
var_print_func varprintf;
|
||||
string_pool *strman;
|
||||
empty_block *empty;
|
||||
|
||||
cs_shared_state() = delete;
|
||||
internal_state() = delete;
|
||||
|
||||
cs_shared_state(cs_alloc_cb af, void *data);
|
||||
internal_state(alloc_func af, void *data);
|
||||
|
||||
~cs_shared_state();
|
||||
~internal_state();
|
||||
|
||||
void *alloc(void *ptr, size_t os, size_t ns);
|
||||
|
||||
|
@ -91,24 +91,24 @@ struct cs_shared_state {
|
|||
}
|
||||
};
|
||||
|
||||
inline cs_shared_state *cs_get_sstate(cs_state &cs) {
|
||||
inline internal_state *state_get_internal(state &cs) {
|
||||
return cs.p_state;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline cs_allocator<T>::cs_allocator(cs_shared_state *s): state{s} {}
|
||||
inline std_allocator<T>::std_allocator(internal_state *s): istate{s} {}
|
||||
|
||||
template<typename T>
|
||||
inline cs_allocator<T>::cs_allocator(cs_state &s): state{cs_get_sstate(s)} {}
|
||||
inline std_allocator<T>::std_allocator(state &s): istate{state_get_internal(s)} {}
|
||||
|
||||
template<typename T>
|
||||
inline T *cs_allocator<T>::allocate(std::size_t n) {
|
||||
return static_cast<T *>(state->alloc(nullptr, 0, n * sizeof(T)));
|
||||
inline T *std_allocator<T>::allocate(std::size_t n) {
|
||||
return static_cast<T *>(istate->alloc(nullptr, 0, n * sizeof(T)));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline void cs_allocator<T>::deallocate(T *p, std::size_t n) {
|
||||
state->alloc(p, n, 0);
|
||||
inline void std_allocator<T>::deallocate(T *p, std::size_t n) {
|
||||
istate->alloc(p, n, 0);
|
||||
}
|
||||
|
||||
} /* namespace cscript */
|
||||
|
|
|
@ -33,15 +33,15 @@ inline void call_with_cleanup(F1 &&dof, F2 &&clf) {
|
|||
/* a simple static array with elements constructed using ctor args */
|
||||
|
||||
template<typename T, std::size_t N>
|
||||
struct cs_valarray {
|
||||
struct valarray {
|
||||
template<typename ...A>
|
||||
cs_valarray(A &&...args) {
|
||||
valarray(A &&...args) {
|
||||
for (std::size_t i = 0; i < N; ++i) {
|
||||
new (&stor[i]) T{std::forward<A>(args)...};
|
||||
}
|
||||
}
|
||||
|
||||
~cs_valarray() {
|
||||
~valarray() {
|
||||
for (std::size_t i = 0; i < N; ++i) {
|
||||
reinterpret_cast<T *>(&stor[i])->~T();
|
||||
}
|
||||
|
@ -57,11 +57,11 @@ struct cs_valarray {
|
|||
/* a value buffer */
|
||||
|
||||
template<typename T>
|
||||
struct cs_valbuf {
|
||||
cs_valbuf() = delete;
|
||||
struct valbuf {
|
||||
valbuf() = delete;
|
||||
|
||||
cs_valbuf(cs_shared_state *cs): buf{cs_allocator<T>{cs}} {}
|
||||
cs_valbuf(cs_state &cs): buf{cs_allocator<T>{cs}} {}
|
||||
valbuf(internal_state *cs): buf{std_allocator<T>{cs}} {}
|
||||
valbuf(state &cs): buf{std_allocator<T>{cs}} {}
|
||||
|
||||
using size_type = std::size_t;
|
||||
using value_type = T;
|
||||
|
@ -94,17 +94,17 @@ struct cs_valbuf {
|
|||
T *data() { return &buf[0]; }
|
||||
T const *data() const { return &buf[0]; }
|
||||
|
||||
std::vector<T, cs_allocator<T>> buf;
|
||||
std::vector<T, std_allocator<T>> buf;
|
||||
};
|
||||
|
||||
/* specialization of value buffer for bytes */
|
||||
|
||||
struct cs_charbuf: cs_valbuf<char> {
|
||||
cs_charbuf(cs_shared_state *cs): cs_valbuf<char>{cs} {}
|
||||
cs_charbuf(cs_state &cs): cs_valbuf<char>{cs} {}
|
||||
struct charbuf: valbuf<char> {
|
||||
charbuf(internal_state *cs): valbuf<char>{cs} {}
|
||||
charbuf(state &cs): valbuf<char>{cs} {}
|
||||
|
||||
void append(char const *beg, char const *end) {
|
||||
cs_valbuf<char>::append(beg, end);
|
||||
valbuf<char>::append(beg, end);
|
||||
}
|
||||
|
||||
void append(std::string_view v) {
|
||||
|
|
|
@ -4,18 +4,18 @@
|
|||
|
||||
namespace cscript {
|
||||
|
||||
struct cs_strref_state {
|
||||
struct string_ref_state {
|
||||
std::size_t length;
|
||||
std::size_t refcount;
|
||||
};
|
||||
|
||||
inline cs_strref_state *get_ref_state(char const *ptr) {
|
||||
return const_cast<cs_strref_state *>(
|
||||
reinterpret_cast<cs_strref_state const *>(ptr)
|
||||
inline string_ref_state *get_ref_state(char const *ptr) {
|
||||
return const_cast<string_ref_state *>(
|
||||
reinterpret_cast<string_ref_state const *>(ptr)
|
||||
) - 1;
|
||||
}
|
||||
|
||||
char const *cs_strman::add(std::string_view str) {
|
||||
char const *string_pool::add(std::string_view str) {
|
||||
auto it = counts.find(str);
|
||||
/* already present: just increment ref */
|
||||
if (it != counts.end()) {
|
||||
|
@ -36,13 +36,13 @@ char const *cs_strman::add(std::string_view str) {
|
|||
return strp;
|
||||
}
|
||||
|
||||
char const *cs_strman::ref(char const *ptr) {
|
||||
char const *string_pool::ref(char const *ptr) {
|
||||
auto *ss = get_ref_state(ptr);
|
||||
++ss->refcount;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
cs_strref cs_strman::steal(char *ptr) {
|
||||
string_ref string_pool::steal(char *ptr) {
|
||||
auto *ss = get_ref_state(ptr);
|
||||
auto sr = std::string_view{ptr, ss->length};
|
||||
/* much like add(), but we already have memory */
|
||||
|
@ -51,16 +51,16 @@ cs_strref cs_strman::steal(char *ptr) {
|
|||
auto *st = it->second;
|
||||
if (st) {
|
||||
/* the buffer is superfluous now */
|
||||
cstate->alloc(ss, ss->length + sizeof(cs_strref_state) + 1, 0);
|
||||
return cs_strref{reinterpret_cast<char const *>(st + 1), cstate};
|
||||
cstate->alloc(ss, ss->length + sizeof(string_ref_state) + 1, 0);
|
||||
return string_ref{reinterpret_cast<char const *>(st + 1), cstate};
|
||||
}
|
||||
}
|
||||
ss->refcount = 0; /* cs_strref will increment it */
|
||||
ss->refcount = 0; /* string_ref will increment it */
|
||||
counts.emplace(sr, ss);
|
||||
return cs_strref{ptr, cstate};
|
||||
return string_ref{ptr, cstate};
|
||||
}
|
||||
|
||||
void cs_strman::unref(char const *ptr) {
|
||||
void string_pool::unref(char const *ptr) {
|
||||
auto *ss = get_ref_state(ptr);
|
||||
if (!--ss->refcount) {
|
||||
/* refcount zero, so ditch it
|
||||
|
@ -70,16 +70,16 @@ void cs_strman::unref(char const *ptr) {
|
|||
auto it = counts.find(sr);
|
||||
if (it == counts.end()) {
|
||||
/* internal error: this should *never* happen */
|
||||
throw cs_internal_error{"no refcount"};
|
||||
throw internal_error{"no refcount"};
|
||||
}
|
||||
/* we're freeing the key */
|
||||
counts.erase(it);
|
||||
/* dealloc */
|
||||
cstate->alloc(ss, ss->length + sizeof(cs_strref_state) + 1, 0);
|
||||
cstate->alloc(ss, ss->length + sizeof(string_ref_state) + 1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
char const *cs_strman::find(std::string_view str) const {
|
||||
char const *string_pool::find(std::string_view str) const {
|
||||
auto it = counts.find(str);
|
||||
if (it == counts.end()) {
|
||||
return nullptr;
|
||||
|
@ -87,18 +87,18 @@ char const *cs_strman::find(std::string_view str) const {
|
|||
return reinterpret_cast<char const *>(it->second + 1);
|
||||
}
|
||||
|
||||
std::string_view cs_strman::get(char const *ptr) const {
|
||||
std::string_view string_pool::get(char const *ptr) const {
|
||||
auto *ss = get_ref_state(ptr);
|
||||
return std::string_view{ptr, ss->length};
|
||||
}
|
||||
|
||||
char *cs_strman::alloc_buf(std::size_t len) const {
|
||||
auto mem = cstate->alloc(nullptr, 0, len + sizeof(cs_strref_state) + 1);
|
||||
char *string_pool::alloc_buf(std::size_t len) const {
|
||||
auto mem = cstate->alloc(nullptr, 0, len + sizeof(string_ref_state) + 1);
|
||||
if (!mem) {
|
||||
throw cs_internal_error{"allocation failed"};
|
||||
throw internal_error{"allocation failed"};
|
||||
}
|
||||
/* write length and initial refcount */
|
||||
auto *sst = static_cast<cs_strref_state *>(mem);
|
||||
auto *sst = static_cast<string_ref_state *>(mem);
|
||||
sst->length = len;
|
||||
sst->refcount = 1;
|
||||
/* pre-terminate */
|
||||
|
@ -112,48 +112,48 @@ char *cs_strman::alloc_buf(std::size_t len) const {
|
|||
|
||||
/* strref */
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_strref::cs_strref(
|
||||
cs_shared_state *cs, std::string_view str
|
||||
LIBCUBESCRIPT_EXPORT string_ref::string_ref(
|
||||
internal_state *cs, std::string_view str
|
||||
): p_state{cs}
|
||||
{
|
||||
p_str = cs->strman->add(str);
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_strref::cs_strref(cs_state &cs, std::string_view str):
|
||||
LIBCUBESCRIPT_EXPORT string_ref::string_ref(state &cs, std::string_view str):
|
||||
p_state{cs.p_state}
|
||||
{
|
||||
p_str = p_state->strman->add(str);
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_strref::cs_strref(cs_strref const &ref):
|
||||
LIBCUBESCRIPT_EXPORT string_ref::string_ref(string_ref const &ref):
|
||||
p_state{ref.p_state}, p_str{ref.p_str}
|
||||
{
|
||||
p_state->strman->ref(p_str);
|
||||
}
|
||||
|
||||
/* this can be used by friends to do quick cs_strref creation */
|
||||
LIBCUBESCRIPT_EXPORT cs_strref::cs_strref(char const *p, cs_shared_state *cs):
|
||||
/* this can be used by friends to do quick string_ref creation */
|
||||
LIBCUBESCRIPT_EXPORT string_ref::string_ref(char const *p, internal_state *cs):
|
||||
p_state{cs}
|
||||
{
|
||||
p_str = p_state->strman->ref(p);
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_strref::~cs_strref() {
|
||||
LIBCUBESCRIPT_EXPORT string_ref::~string_ref() {
|
||||
p_state->strman->unref(p_str);
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_strref &cs_strref::operator=(cs_strref const &ref) {
|
||||
LIBCUBESCRIPT_EXPORT string_ref &string_ref::operator=(string_ref const &ref) {
|
||||
p_str = ref.p_str;
|
||||
p_state = ref.p_state;
|
||||
p_state->strman->ref(p_str);
|
||||
return *this;
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_strref::operator std::string_view() const {
|
||||
LIBCUBESCRIPT_EXPORT string_ref::operator std::string_view() const {
|
||||
return p_state->strman->get(p_str);
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT bool cs_strref::operator==(cs_strref const &s) const {
|
||||
LIBCUBESCRIPT_EXPORT bool string_ref::operator==(string_ref const &s) const {
|
||||
return p_str == s.p_str;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
namespace cscript {
|
||||
|
||||
struct cs_strref_state;
|
||||
struct string_ref_state;
|
||||
|
||||
/* string manager
|
||||
*
|
||||
|
@ -29,19 +29,19 @@ struct cs_strref_state;
|
|||
* for now we don't bother...
|
||||
*/
|
||||
|
||||
struct cs_strman {
|
||||
using allocator_type = cs_allocator<
|
||||
std::pair<std::string_view const, cs_strref_state *>
|
||||
struct string_pool {
|
||||
using allocator_type = std_allocator<
|
||||
std::pair<std::string_view const, string_ref_state *>
|
||||
>;
|
||||
cs_strman() = delete;
|
||||
cs_strman(cs_shared_state *cs): cstate{cs}, counts{allocator_type{cs}} {}
|
||||
~cs_strman() {}
|
||||
string_pool() = delete;
|
||||
string_pool(internal_state *cs): cstate{cs}, counts{allocator_type{cs}} {}
|
||||
~string_pool() {}
|
||||
|
||||
cs_strman(cs_strman const &) = delete;
|
||||
cs_strman(cs_strman &&) = delete;
|
||||
string_pool(string_pool const &) = delete;
|
||||
string_pool(string_pool &&) = delete;
|
||||
|
||||
cs_strman &operator=(cs_strman const &) = delete;
|
||||
cs_strman &operator=(cs_strman &&) = delete;
|
||||
string_pool &operator=(string_pool const &) = delete;
|
||||
string_pool &operator=(string_pool &&) = delete;
|
||||
|
||||
/* adds a string into the manager using any source, and returns a managed
|
||||
* version; this is "slow" as it has to hash the string and potentially
|
||||
|
@ -58,7 +58,7 @@ struct cs_strman {
|
|||
/* this will use the provided memory, assuming it is a fresh string that
|
||||
* is yet to be added; the memory must be allocated with alloc_buf()
|
||||
*/
|
||||
cs_strref steal(char *ptr);
|
||||
string_ref steal(char *ptr);
|
||||
|
||||
/* decrements the reference count and removes it from the system if
|
||||
* that reaches zero; likewise, only safe with pointers that are managed
|
||||
|
@ -78,9 +78,9 @@ struct cs_strman {
|
|||
*/
|
||||
char *alloc_buf(std::size_t len) const;
|
||||
|
||||
cs_shared_state *cstate;
|
||||
internal_state *cstate;
|
||||
std::unordered_map<
|
||||
std::string_view, cs_strref_state *,
|
||||
std::string_view, string_ref_state *,
|
||||
std::hash<std::string_view>,
|
||||
std::equal_to<std::string_view>,
|
||||
allocator_type
|
||||
|
|
344
src/cs_val.cc
344
src/cs_val.cc
|
@ -7,12 +7,12 @@
|
|||
|
||||
namespace cscript {
|
||||
|
||||
static std::string_view intstr(cs_int v, cs_charbuf &buf) {
|
||||
static std::string_view intstr(integer_type v, charbuf &buf) {
|
||||
buf.reserve(32);
|
||||
int n = snprintf(buf.data(), 32, CS_INT_FORMAT, v);
|
||||
int n = snprintf(buf.data(), 32, INT_FORMAT, v);
|
||||
if (n > 32) {
|
||||
buf.reserve(n + 1);
|
||||
int nn = snprintf(buf.data(), n + 1, CS_INT_FORMAT, v);
|
||||
int nn = snprintf(buf.data(), n + 1, INT_FORMAT, v);
|
||||
if ((nn > n) || (nn <= 0)) {
|
||||
n = -1;
|
||||
} else {
|
||||
|
@ -20,26 +20,26 @@ static std::string_view intstr(cs_int v, cs_charbuf &buf) {
|
|||
}
|
||||
}
|
||||
if (n <= 0) {
|
||||
throw cs_internal_error{"format error"};
|
||||
throw internal_error{"format error"};
|
||||
}
|
||||
return std::string_view{buf.data(), std::size_t(n)};
|
||||
}
|
||||
|
||||
static std::string_view floatstr(cs_float v, cs_charbuf &buf) {
|
||||
static std::string_view floatstr(float_type v, charbuf &buf) {
|
||||
buf.reserve(32);
|
||||
int n;
|
||||
if (v == std::floor(v)) {
|
||||
n = snprintf(buf.data(), 32, CS_ROUND_FLOAT_FORMAT, v);
|
||||
n = snprintf(buf.data(), 32, ROUND_FLOAT_FORMAT, v);
|
||||
} else {
|
||||
n = snprintf(buf.data(), 32, CS_FLOAT_FORMAT, v);
|
||||
n = snprintf(buf.data(), 32, FLOAT_FORMAT, v);
|
||||
}
|
||||
if (n > 32) {
|
||||
buf.reserve(n + 1);
|
||||
int nn;
|
||||
if (v == std::floor(v)) {
|
||||
nn = snprintf(buf.data(), n + 1, CS_ROUND_FLOAT_FORMAT, v);
|
||||
nn = snprintf(buf.data(), n + 1, ROUND_FLOAT_FORMAT, v);
|
||||
} else {
|
||||
nn = snprintf(buf.data(), n + 1, CS_FLOAT_FORMAT, v);
|
||||
nn = snprintf(buf.data(), n + 1, FLOAT_FORMAT, v);
|
||||
}
|
||||
if ((nn > n) || (nn <= 0)) {
|
||||
n = -1;
|
||||
|
@ -48,14 +48,14 @@ static std::string_view floatstr(cs_float v, cs_charbuf &buf) {
|
|||
}
|
||||
}
|
||||
if (n <= 0) {
|
||||
throw cs_internal_error{"format error"};
|
||||
throw internal_error{"format error"};
|
||||
}
|
||||
return std::string_view{buf.data(), std::size_t(n)};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct stor_priv_t {
|
||||
cs_shared_state *state;
|
||||
internal_state *state;
|
||||
T val;
|
||||
};
|
||||
|
||||
|
@ -66,12 +66,12 @@ static inline T &csv_get(U &stor) {
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
static inline void csv_cleanup(cs_value_type tv, T &stor) {
|
||||
static inline void csv_cleanup(value_type tv, T &stor) {
|
||||
switch (tv) {
|
||||
case cs_value_type::STRING:
|
||||
reinterpret_cast<cs_strref *>(&stor)->~cs_strref();
|
||||
case value_type::STRING:
|
||||
reinterpret_cast<string_ref *>(&stor)->~string_ref();
|
||||
break;
|
||||
case cs_value_type::CODE: {
|
||||
case value_type::CODE: {
|
||||
bcode_unref(csv_get<uint32_t *>(stor));
|
||||
break;
|
||||
}
|
||||
|
@ -80,43 +80,43 @@ static inline void csv_cleanup(cs_value_type tv, T &stor) {
|
|||
}
|
||||
}
|
||||
|
||||
cs_value::cs_value(cs_state &st): cs_value(*st.p_state) {}
|
||||
any_value::any_value(state &st): any_value(*st.p_state) {}
|
||||
|
||||
cs_value::cs_value(cs_shared_state &st):
|
||||
p_stor(), p_type(cs_value_type::NONE)
|
||||
any_value::any_value(internal_state &st):
|
||||
p_stor(), p_type(value_type::NONE)
|
||||
{
|
||||
reinterpret_cast<stor_priv_t<void *> *>(&p_stor)->state = &st;
|
||||
}
|
||||
|
||||
cs_value::~cs_value() {
|
||||
any_value::~any_value() {
|
||||
csv_cleanup(p_type, p_stor);
|
||||
}
|
||||
|
||||
cs_value::cs_value(cs_value const &v): cs_value(*v.state()) {
|
||||
any_value::any_value(any_value const &v): any_value(*v.get_state()) {
|
||||
*this = v;
|
||||
}
|
||||
|
||||
cs_value::cs_value(cs_value &&v): cs_value(*v.state()) {
|
||||
any_value::any_value(any_value &&v): any_value(*v.get_state()) {
|
||||
*this = std::move(v);
|
||||
}
|
||||
|
||||
cs_value &cs_value::operator=(cs_value const &v) {
|
||||
any_value &any_value::operator=(any_value const &v) {
|
||||
csv_cleanup(p_type, p_stor);
|
||||
p_type = cs_value_type::NONE;
|
||||
p_type = value_type::NONE;
|
||||
switch (v.get_type()) {
|
||||
case cs_value_type::INT:
|
||||
case cs_value_type::FLOAT:
|
||||
case cs_value_type::IDENT:
|
||||
case value_type::INT:
|
||||
case value_type::FLOAT:
|
||||
case value_type::IDENT:
|
||||
p_type = v.p_type;
|
||||
p_stor = v.p_stor;
|
||||
break;
|
||||
case cs_value_type::STRING:
|
||||
p_type = cs_value_type::STRING;
|
||||
new (&p_stor) cs_strref{
|
||||
*reinterpret_cast<cs_strref const *>(&v.p_stor)
|
||||
case value_type::STRING:
|
||||
p_type = value_type::STRING;
|
||||
new (&p_stor) string_ref{
|
||||
*reinterpret_cast<string_ref const *>(&v.p_stor)
|
||||
};
|
||||
break;
|
||||
case cs_value_type::CODE:
|
||||
case value_type::CODE:
|
||||
set_code(v.get_code());
|
||||
break;
|
||||
default:
|
||||
|
@ -125,78 +125,78 @@ cs_value &cs_value::operator=(cs_value const &v) {
|
|||
return *this;
|
||||
}
|
||||
|
||||
cs_value &cs_value::operator=(cs_value &&v) {
|
||||
any_value &any_value::operator=(any_value &&v) {
|
||||
*this = v;
|
||||
v.set_none();
|
||||
return *this;
|
||||
}
|
||||
|
||||
cs_value_type cs_value::get_type() const {
|
||||
value_type any_value::get_type() const {
|
||||
return p_type;
|
||||
}
|
||||
|
||||
void cs_value::set_int(cs_int val) {
|
||||
void any_value::set_int(integer_type val) {
|
||||
csv_cleanup(p_type, p_stor);
|
||||
p_type = cs_value_type::INT;
|
||||
csv_get<cs_int>(p_stor) = val;
|
||||
p_type = value_type::INT;
|
||||
csv_get<integer_type>(p_stor) = val;
|
||||
}
|
||||
|
||||
void cs_value::set_float(cs_float val) {
|
||||
void any_value::set_float(float_type val) {
|
||||
csv_cleanup(p_type, p_stor);
|
||||
p_type = cs_value_type::FLOAT;
|
||||
csv_get<cs_float>(p_stor) = val;
|
||||
p_type = value_type::FLOAT;
|
||||
csv_get<float_type>(p_stor) = val;
|
||||
}
|
||||
|
||||
void cs_value::set_str(std::string_view val) {
|
||||
void any_value::set_str(std::string_view val) {
|
||||
csv_cleanup(p_type, p_stor);
|
||||
new (&p_stor) cs_strref{state(), val};
|
||||
p_type = cs_value_type::STRING;
|
||||
new (&p_stor) string_ref{get_state(), val};
|
||||
p_type = value_type::STRING;
|
||||
}
|
||||
|
||||
void cs_value::set_str(cs_strref const &val) {
|
||||
void any_value::set_str(string_ref const &val) {
|
||||
csv_cleanup(p_type, p_stor);
|
||||
new (&p_stor) cs_strref{val};
|
||||
p_type = cs_value_type::STRING;
|
||||
new (&p_stor) string_ref{val};
|
||||
p_type = value_type::STRING;
|
||||
}
|
||||
|
||||
void cs_value::set_none() {
|
||||
void any_value::set_none() {
|
||||
csv_cleanup(p_type, p_stor);
|
||||
p_type = cs_value_type::NONE;
|
||||
p_type = value_type::NONE;
|
||||
}
|
||||
|
||||
void cs_value::set_code(cs_bcode *val) {
|
||||
void any_value::set_code(bcode *val) {
|
||||
csv_cleanup(p_type, p_stor);
|
||||
p_type = cs_value_type::CODE;
|
||||
bcode_ref(val->get_raw());
|
||||
csv_get<cs_bcode *>(p_stor) = val;
|
||||
p_type = value_type::CODE;
|
||||
bcode_addref(val->get_raw());
|
||||
csv_get<bcode *>(p_stor) = val;
|
||||
}
|
||||
|
||||
void cs_value::set_ident(cs_ident *val) {
|
||||
void any_value::set_ident(ident *val) {
|
||||
csv_cleanup(p_type, p_stor);
|
||||
p_type = cs_value_type::IDENT;
|
||||
csv_get<cs_ident *>(p_stor) = val;
|
||||
p_type = value_type::IDENT;
|
||||
csv_get<ident *>(p_stor) = val;
|
||||
}
|
||||
|
||||
void cs_value::force_none() {
|
||||
if (get_type() == cs_value_type::NONE) {
|
||||
void any_value::force_none() {
|
||||
if (get_type() == value_type::NONE) {
|
||||
return;
|
||||
}
|
||||
set_none();
|
||||
}
|
||||
|
||||
cs_float cs_value::force_float() {
|
||||
cs_float rf = 0.0f;
|
||||
float_type any_value::force_float() {
|
||||
float_type rf = 0.0f;
|
||||
switch (get_type()) {
|
||||
case cs_value_type::INT:
|
||||
rf = csv_get<cs_int>(p_stor);
|
||||
case value_type::INT:
|
||||
rf = csv_get<integer_type>(p_stor);
|
||||
break;
|
||||
case cs_value_type::STRING:
|
||||
case value_type::STRING:
|
||||
rf = parse_float(
|
||||
*reinterpret_cast<cs_strref const *>(&p_stor)
|
||||
*reinterpret_cast<string_ref const *>(&p_stor)
|
||||
);
|
||||
break;
|
||||
case cs_value_type::FLOAT:
|
||||
return csv_get<cs_float>(p_stor);
|
||||
case value_type::FLOAT:
|
||||
return csv_get<float_type>(p_stor);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -204,19 +204,19 @@ cs_float cs_value::force_float() {
|
|||
return rf;
|
||||
}
|
||||
|
||||
cs_int cs_value::force_int() {
|
||||
cs_int ri = 0;
|
||||
integer_type any_value::force_int() {
|
||||
integer_type ri = 0;
|
||||
switch (get_type()) {
|
||||
case cs_value_type::FLOAT:
|
||||
ri = csv_get<cs_float>(p_stor);
|
||||
case value_type::FLOAT:
|
||||
ri = csv_get<float_type>(p_stor);
|
||||
break;
|
||||
case cs_value_type::STRING:
|
||||
case value_type::STRING:
|
||||
ri = parse_int(
|
||||
*reinterpret_cast<cs_strref const *>(&p_stor)
|
||||
*reinterpret_cast<string_ref const *>(&p_stor)
|
||||
);
|
||||
break;
|
||||
case cs_value_type::INT:
|
||||
return csv_get<cs_int>(p_stor);
|
||||
case value_type::INT:
|
||||
return csv_get<integer_type>(p_stor);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -224,35 +224,35 @@ cs_int cs_value::force_int() {
|
|||
return ri;
|
||||
}
|
||||
|
||||
std::string_view cs_value::force_str() {
|
||||
cs_charbuf rs{state()};
|
||||
std::string_view any_value::force_str() {
|
||||
charbuf rs{get_state()};
|
||||
std::string_view str;
|
||||
switch (get_type()) {
|
||||
case cs_value_type::FLOAT:
|
||||
str = floatstr(csv_get<cs_float>(p_stor), rs);
|
||||
case value_type::FLOAT:
|
||||
str = floatstr(csv_get<float_type>(p_stor), rs);
|
||||
break;
|
||||
case cs_value_type::INT:
|
||||
str = intstr(csv_get<cs_int>(p_stor), rs);
|
||||
case value_type::INT:
|
||||
str = intstr(csv_get<integer_type>(p_stor), rs);
|
||||
break;
|
||||
case cs_value_type::STRING:
|
||||
return *reinterpret_cast<cs_strref const *>(&p_stor);
|
||||
case value_type::STRING:
|
||||
return *reinterpret_cast<string_ref const *>(&p_stor);
|
||||
default:
|
||||
str = rs.str();
|
||||
break;
|
||||
}
|
||||
set_str(str);
|
||||
return std::string_view(*reinterpret_cast<cs_strref const *>(&p_stor));
|
||||
return std::string_view(*reinterpret_cast<string_ref const *>(&p_stor));
|
||||
}
|
||||
|
||||
cs_int cs_value::get_int() const {
|
||||
integer_type any_value::get_int() const {
|
||||
switch (get_type()) {
|
||||
case cs_value_type::FLOAT:
|
||||
return cs_int(csv_get<cs_float>(p_stor));
|
||||
case cs_value_type::INT:
|
||||
return csv_get<cs_int>(p_stor);
|
||||
case cs_value_type::STRING:
|
||||
case value_type::FLOAT:
|
||||
return integer_type(csv_get<float_type>(p_stor));
|
||||
case value_type::INT:
|
||||
return csv_get<integer_type>(p_stor);
|
||||
case value_type::STRING:
|
||||
return parse_int(
|
||||
*reinterpret_cast<cs_strref const *>(&p_stor)
|
||||
*reinterpret_cast<string_ref const *>(&p_stor)
|
||||
);
|
||||
default:
|
||||
break;
|
||||
|
@ -260,15 +260,15 @@ cs_int cs_value::get_int() const {
|
|||
return 0;
|
||||
}
|
||||
|
||||
cs_float cs_value::get_float() const {
|
||||
float_type any_value::get_float() const {
|
||||
switch (get_type()) {
|
||||
case cs_value_type::FLOAT:
|
||||
return csv_get<cs_float>(p_stor);
|
||||
case cs_value_type::INT:
|
||||
return cs_float(csv_get<cs_int>(p_stor));
|
||||
case cs_value_type::STRING:
|
||||
case value_type::FLOAT:
|
||||
return csv_get<float_type>(p_stor);
|
||||
case value_type::INT:
|
||||
return float_type(csv_get<integer_type>(p_stor));
|
||||
case value_type::STRING:
|
||||
return parse_float(
|
||||
*reinterpret_cast<cs_strref const *>(&p_stor)
|
||||
*reinterpret_cast<string_ref const *>(&p_stor)
|
||||
);
|
||||
default:
|
||||
break;
|
||||
|
@ -276,48 +276,52 @@ cs_float cs_value::get_float() const {
|
|||
return 0.0f;
|
||||
}
|
||||
|
||||
cs_bcode *cs_value::get_code() const {
|
||||
if (get_type() != cs_value_type::CODE) {
|
||||
bcode *any_value::get_code() const {
|
||||
if (get_type() != value_type::CODE) {
|
||||
return nullptr;
|
||||
}
|
||||
return csv_get<cs_bcode *>(p_stor);
|
||||
return csv_get<bcode *>(p_stor);
|
||||
}
|
||||
|
||||
cs_ident *cs_value::get_ident() const {
|
||||
if (get_type() != cs_value_type::IDENT) {
|
||||
ident *any_value::get_ident() const {
|
||||
if (get_type() != value_type::IDENT) {
|
||||
return nullptr;
|
||||
}
|
||||
return csv_get<cs_ident *>(p_stor);
|
||||
return csv_get<ident *>(p_stor);
|
||||
}
|
||||
|
||||
cs_strref cs_value::get_str() const {
|
||||
string_ref any_value::get_str() const {
|
||||
switch (get_type()) {
|
||||
case cs_value_type::STRING:
|
||||
return *reinterpret_cast<cs_strref const *>(&p_stor);
|
||||
case cs_value_type::INT: {
|
||||
cs_charbuf rs{state()};
|
||||
return cs_strref{state(), intstr(csv_get<cs_int>(p_stor), rs)};
|
||||
case value_type::STRING:
|
||||
return *reinterpret_cast<string_ref const *>(&p_stor);
|
||||
case value_type::INT: {
|
||||
charbuf rs{get_state()};
|
||||
return string_ref{
|
||||
get_state(), intstr(csv_get<integer_type>(p_stor), rs)
|
||||
};
|
||||
}
|
||||
case cs_value_type::FLOAT: {
|
||||
cs_charbuf rs{state()};
|
||||
return cs_strref{state(), floatstr(csv_get<cs_float>(p_stor), rs)};
|
||||
case value_type::FLOAT: {
|
||||
charbuf rs{get_state()};
|
||||
return string_ref{
|
||||
get_state(), floatstr(csv_get<float_type>(p_stor), rs)
|
||||
};
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return cs_strref{state(), ""};
|
||||
return string_ref{get_state(), ""};
|
||||
}
|
||||
|
||||
void cs_value::get_val(cs_value &r) const {
|
||||
void any_value::get_val(any_value &r) const {
|
||||
switch (get_type()) {
|
||||
case cs_value_type::STRING:
|
||||
case value_type::STRING:
|
||||
r = *this;
|
||||
break;
|
||||
case cs_value_type::INT:
|
||||
r.set_int(csv_get<cs_int>(p_stor));
|
||||
case value_type::INT:
|
||||
r.set_int(csv_get<integer_type>(p_stor));
|
||||
break;
|
||||
case cs_value_type::FLOAT:
|
||||
r.set_float(csv_get<cs_float>(p_stor));
|
||||
case value_type::FLOAT:
|
||||
r.set_float(csv_get<float_type>(p_stor));
|
||||
break;
|
||||
default:
|
||||
r.set_none();
|
||||
|
@ -325,47 +329,43 @@ void cs_value::get_val(cs_value &r) const {
|
|||
}
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT bool cs_code_is_empty(cs_bcode *code) {
|
||||
LIBCUBESCRIPT_EXPORT bool code_is_empty(bcode *code) {
|
||||
if (!code) {
|
||||
return true;
|
||||
}
|
||||
return (*code->get_raw() & CS_CODE_OP_MASK) == CS_CODE_EXIT;
|
||||
return (*code->get_raw() & BC_INST_OP_MASK) == BC_INST_EXIT;
|
||||
}
|
||||
|
||||
bool cs_value::code_is_empty() const {
|
||||
if (get_type() != cs_value_type::CODE) {
|
||||
bool any_value::code_is_empty() const {
|
||||
if (get_type() != value_type::CODE) {
|
||||
return true;
|
||||
}
|
||||
return cscript::cs_code_is_empty(csv_get<cs_bcode *>(p_stor));
|
||||
return cscript::code_is_empty(csv_get<bcode *>(p_stor));
|
||||
}
|
||||
|
||||
static inline bool cs_get_bool(std::string_view s) {
|
||||
if (s.empty()) {
|
||||
return false;
|
||||
}
|
||||
std::string_view end = s;
|
||||
cs_int ival = parse_int(end, &end);
|
||||
if (end.empty()) {
|
||||
return !!ival;
|
||||
}
|
||||
end = s;
|
||||
cs_float fval = parse_float(end, &end);
|
||||
if (end.empty()) {
|
||||
return !!fval;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cs_value::get_bool() const {
|
||||
bool any_value::get_bool() const {
|
||||
switch (get_type()) {
|
||||
case cs_value_type::FLOAT:
|
||||
return csv_get<cs_float>(p_stor) != 0;
|
||||
case cs_value_type::INT:
|
||||
return csv_get<cs_int>(p_stor) != 0;
|
||||
case cs_value_type::STRING:
|
||||
return cs_get_bool(
|
||||
*reinterpret_cast<cs_strref const *>(&p_stor)
|
||||
);
|
||||
case value_type::FLOAT:
|
||||
return csv_get<float_type>(p_stor) != 0;
|
||||
case value_type::INT:
|
||||
return csv_get<integer_type>(p_stor) != 0;
|
||||
case value_type::STRING: {
|
||||
std::string_view s = *reinterpret_cast<string_ref const *>(&p_stor);
|
||||
if (s.empty()) {
|
||||
return false;
|
||||
}
|
||||
std::string_view end = s;
|
||||
integer_type ival = parse_int(end, &end);
|
||||
if (end.empty()) {
|
||||
return !!ival;
|
||||
}
|
||||
end = s;
|
||||
float_type fval = parse_float(end, &end);
|
||||
if (end.empty()) {
|
||||
return !!fval;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@ -373,74 +373,74 @@ bool cs_value::get_bool() const {
|
|||
|
||||
/* stacked value for easy stack management */
|
||||
|
||||
cs_stacked_value::cs_stacked_value(cs_state &cs, cs_ident *id):
|
||||
cs_value(cs), p_a(nullptr), p_stack{cs}, p_pushed(false)
|
||||
stacked_value::stacked_value(state &cs, ident *id):
|
||||
any_value(cs), p_a(nullptr), p_stack{cs}, p_pushed(false)
|
||||
{
|
||||
set_alias(id);
|
||||
}
|
||||
|
||||
cs_stacked_value::~cs_stacked_value() {
|
||||
stacked_value::~stacked_value() {
|
||||
pop();
|
||||
static_cast<cs_value *>(this)->~cs_value();
|
||||
static_cast<any_value *>(this)->~any_value();
|
||||
}
|
||||
|
||||
cs_stacked_value &cs_stacked_value::operator=(cs_value const &v) {
|
||||
*static_cast<cs_value *>(this) = v;
|
||||
stacked_value &stacked_value::operator=(any_value const &v) {
|
||||
*static_cast<any_value *>(this) = v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
cs_stacked_value &cs_stacked_value::operator=(cs_value &&v) {
|
||||
*static_cast<cs_value *>(this) = std::move(v);
|
||||
stacked_value &stacked_value::operator=(any_value &&v) {
|
||||
*static_cast<any_value *>(this) = std::move(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool cs_stacked_value::set_alias(cs_ident *id) {
|
||||
bool stacked_value::set_alias(ident *id) {
|
||||
if (!id || !id->is_alias()) {
|
||||
return false;
|
||||
}
|
||||
p_a = static_cast<cs_alias *>(id);
|
||||
p_a = static_cast<alias *>(id);
|
||||
return true;
|
||||
}
|
||||
|
||||
cs_alias *cs_stacked_value::get_alias() const {
|
||||
alias *stacked_value::get_alias() const {
|
||||
return p_a;
|
||||
}
|
||||
|
||||
bool cs_stacked_value::has_alias() const {
|
||||
bool stacked_value::has_alias() const {
|
||||
return p_a != nullptr;
|
||||
}
|
||||
|
||||
bool cs_stacked_value::push() {
|
||||
bool stacked_value::push() {
|
||||
if (!p_a) {
|
||||
return false;
|
||||
}
|
||||
static_cast<cs_alias_impl *>(p_a)->push_arg(*this, p_stack);
|
||||
static_cast<alias_impl *>(p_a)->push_arg(*this, p_stack);
|
||||
p_pushed = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cs_stacked_value::pop() {
|
||||
bool stacked_value::pop() {
|
||||
if (!p_pushed || !p_a) {
|
||||
return false;
|
||||
}
|
||||
static_cast<cs_alias_impl *>(p_a)->pop_arg();
|
||||
static_cast<alias_impl *>(p_a)->pop_arg();
|
||||
p_pushed = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* public utilities */
|
||||
|
||||
LIBCUBESCRIPT_EXPORT cs_strref cs_concat_values(
|
||||
cs_state &cs, std::span<cs_value> vals, std::string_view sep
|
||||
LIBCUBESCRIPT_EXPORT string_ref concat_values(
|
||||
state &cs, std::span<any_value> vals, std::string_view sep
|
||||
) {
|
||||
cs_charbuf buf{cs};
|
||||
charbuf buf{cs};
|
||||
for (std::size_t i = 0; i < vals.size(); ++i) {
|
||||
switch (vals[i].get_type()) {
|
||||
case cs_value_type::INT:
|
||||
case cs_value_type::FLOAT:
|
||||
case cs_value_type::STRING:
|
||||
case value_type::INT:
|
||||
case value_type::FLOAT:
|
||||
case value_type::STRING:
|
||||
std::ranges::copy(
|
||||
cs_value{vals[i]}.force_str(), std::back_inserter(buf)
|
||||
any_value{vals[i]}.force_str(), std::back_inserter(buf)
|
||||
);
|
||||
break;
|
||||
default:
|
||||
|
@ -451,7 +451,7 @@ LIBCUBESCRIPT_EXPORT cs_strref cs_concat_values(
|
|||
}
|
||||
std::ranges::copy(sep, std::back_inserter(buf));
|
||||
}
|
||||
return cs_strref{cs, buf.str()};
|
||||
return string_ref{cs, buf.str()};
|
||||
}
|
||||
|
||||
} /* namespace cscript */
|
||||
|
|
892
src/cs_vm.cc
892
src/cs_vm.cc
File diff suppressed because it is too large
Load Diff
89
src/cs_vm.hh
89
src/cs_vm.hh
|
@ -1,5 +1,5 @@
|
|||
#ifndef LIBCUBESCRIPT_CS_VM_HH
|
||||
#define LIBCUBESCRIPT_CS_VM_HH
|
||||
#ifndef LIBCUBESCRIPT_VM_HH
|
||||
#define LIBCUBESCRIPT_VM_HH
|
||||
|
||||
#include "cubescript/cubescript.hh"
|
||||
|
||||
|
@ -21,13 +21,13 @@ static constexpr int DummyIdx = MaxArguments;
|
|||
static constexpr int NumargsIdx = MaxArguments + 1;
|
||||
static constexpr int DbgaliasIdx = MaxArguments + 2;
|
||||
|
||||
static const int cs_valtypet[] = {
|
||||
CS_VAL_NULL, CS_VAL_INT, CS_VAL_FLOAT, CS_VAL_STRING,
|
||||
CS_VAL_CODE, CS_VAL_IDENT
|
||||
static const int valtypet[] = {
|
||||
VAL_NULL, VAL_INT, VAL_FLOAT, VAL_STRING,
|
||||
VAL_CODE, VAL_IDENT
|
||||
};
|
||||
|
||||
static inline int cs_vtype_to_int(cs_value_type v) {
|
||||
return cs_valtypet[int(v)];
|
||||
static inline int vtype_to_int(value_type v) {
|
||||
return valtypet[int(v)];
|
||||
}
|
||||
|
||||
struct CsBreakException {
|
||||
|
@ -40,24 +40,24 @@ template<typename T>
|
|||
constexpr size_t CsTypeStorageSize =
|
||||
(sizeof(T) - 1) / sizeof(uint32_t) + 1;
|
||||
|
||||
struct cs_gen_state {
|
||||
cs_state &cs;
|
||||
cs_gen_state *prevps;
|
||||
struct codegen_state {
|
||||
state &cs;
|
||||
codegen_state *prevps;
|
||||
bool parsing = true;
|
||||
cs_valbuf<uint32_t> code;
|
||||
valbuf<uint32_t> code;
|
||||
char const *source, *send;
|
||||
size_t current_line;
|
||||
std::string_view src_name;
|
||||
|
||||
cs_gen_state() = delete;
|
||||
cs_gen_state(cs_state &csr):
|
||||
codegen_state() = delete;
|
||||
codegen_state(state &csr):
|
||||
cs{csr}, prevps{csr.p_pstate}, code{cs},
|
||||
source{}, send{}, current_line{1}, src_name{}
|
||||
{
|
||||
csr.p_pstate = this;
|
||||
}
|
||||
|
||||
~cs_gen_state() {
|
||||
~codegen_state() {
|
||||
done();
|
||||
}
|
||||
|
||||
|
@ -70,13 +70,13 @@ struct cs_gen_state {
|
|||
}
|
||||
|
||||
std::string_view get_str();
|
||||
cs_charbuf get_str_dup();
|
||||
charbuf get_str_dup();
|
||||
|
||||
std::string_view get_word();
|
||||
|
||||
void gen_str(std::string_view word) {
|
||||
if (word.size() <= 3) {
|
||||
uint32_t op = CS_CODE_VAL_INT | CS_RET_STRING;
|
||||
uint32_t op = BC_INST_VAL_INT | BC_RET_STRING;
|
||||
for (size_t i = 0; i < word.size(); ++i) {
|
||||
op |= uint32_t(
|
||||
static_cast<unsigned char>(word[i])
|
||||
|
@ -85,7 +85,7 @@ struct cs_gen_state {
|
|||
code.push_back(op);
|
||||
return;
|
||||
}
|
||||
code.push_back(CS_CODE_VAL | CS_RET_STRING | (word.size() << 8));
|
||||
code.push_back(BC_INST_VAL | BC_RET_STRING | (word.size() << 8));
|
||||
auto it = reinterpret_cast<uint32_t const *>(word.data());
|
||||
code.append(it, it + (word.size() / sizeof(uint32_t)));
|
||||
size_t esz = word.size() % sizeof(uint32_t);
|
||||
|
@ -99,50 +99,50 @@ struct cs_gen_state {
|
|||
}
|
||||
|
||||
void gen_str() {
|
||||
code.push_back(CS_CODE_VAL_INT | CS_RET_STRING);
|
||||
code.push_back(BC_INST_VAL_INT | BC_RET_STRING);
|
||||
}
|
||||
|
||||
void gen_null() {
|
||||
code.push_back(CS_CODE_VAL_INT | CS_RET_NULL);
|
||||
code.push_back(BC_INST_VAL_INT | BC_RET_NULL);
|
||||
}
|
||||
|
||||
void gen_int(cs_int i = 0) {
|
||||
void gen_int(integer_type i = 0) {
|
||||
if (i >= -0x800000 && i <= 0x7FFFFF) {
|
||||
code.push_back(CS_CODE_VAL_INT | CS_RET_INT | (i << 8));
|
||||
code.push_back(BC_INST_VAL_INT | BC_RET_INT | (i << 8));
|
||||
} else {
|
||||
union {
|
||||
cs_int i;
|
||||
uint32_t u[CsTypeStorageSize<cs_int>];
|
||||
integer_type i;
|
||||
uint32_t u[CsTypeStorageSize<integer_type>];
|
||||
} c;
|
||||
c.i = i;
|
||||
code.push_back(CS_CODE_VAL | CS_RET_INT);
|
||||
code.append(c.u, c.u + CsTypeStorageSize<cs_int>);
|
||||
code.push_back(BC_INST_VAL | BC_RET_INT);
|
||||
code.append(c.u, c.u + CsTypeStorageSize<integer_type>);
|
||||
}
|
||||
}
|
||||
|
||||
void gen_int(std::string_view word);
|
||||
|
||||
void gen_float(cs_float f = 0.0f) {
|
||||
if (cs_int(f) == f && f >= -0x800000 && f <= 0x7FFFFF) {
|
||||
code.push_back(CS_CODE_VAL_INT | CS_RET_FLOAT | (cs_int(f) << 8));
|
||||
void gen_float(float_type f = 0.0f) {
|
||||
if (integer_type(f) == f && f >= -0x800000 && f <= 0x7FFFFF) {
|
||||
code.push_back(BC_INST_VAL_INT | BC_RET_FLOAT | (integer_type(f) << 8));
|
||||
} else {
|
||||
union {
|
||||
cs_float f;
|
||||
uint32_t u[CsTypeStorageSize<cs_float>];
|
||||
float_type f;
|
||||
uint32_t u[CsTypeStorageSize<float_type>];
|
||||
} c;
|
||||
c.f = f;
|
||||
code.push_back(CS_CODE_VAL | CS_RET_FLOAT);
|
||||
code.append(c.u, c.u + CsTypeStorageSize<cs_float>);
|
||||
code.push_back(BC_INST_VAL | BC_RET_FLOAT);
|
||||
code.append(c.u, c.u + CsTypeStorageSize<float_type>);
|
||||
}
|
||||
}
|
||||
|
||||
void gen_float(std::string_view word);
|
||||
|
||||
void gen_ident(cs_ident *id) {
|
||||
void gen_ident(ident *id) {
|
||||
code.push_back(
|
||||
((id->get_index() < MaxArguments)
|
||||
? CS_CODE_IDENT_ARG
|
||||
: CS_CODE_IDENT
|
||||
? BC_INST_IDENT_ARG
|
||||
: BC_INST_IDENT
|
||||
) | (id->get_index() << 8)
|
||||
);
|
||||
}
|
||||
|
@ -160,7 +160,7 @@ struct cs_gen_state {
|
|||
int line = 0
|
||||
);
|
||||
|
||||
void gen_main(std::string_view s, int ret_type = CS_VAL_ANY);
|
||||
void gen_main(std::string_view s, int ret_type = VAL_ANY);
|
||||
|
||||
void next_char() {
|
||||
if (source == send) {
|
||||
|
@ -187,26 +187,23 @@ struct cs_gen_state {
|
|||
void skip_comments();
|
||||
};
|
||||
|
||||
void bcode_ref(uint32_t *code);
|
||||
void bcode_unref(uint32_t *code);
|
||||
|
||||
template<typename F>
|
||||
static void cs_do_args(cs_state &cs, F body) {
|
||||
static void call_with_args(state &cs, F body) {
|
||||
if (!cs.p_callstack) {
|
||||
body();
|
||||
return;
|
||||
}
|
||||
cs_valarray<cs_ident_stack, MaxArguments> argstack{cs};
|
||||
valarray<ident_stack, MaxArguments> argstack{cs};
|
||||
int argmask1 = cs.p_callstack->usedargs;
|
||||
for (int i = 0; argmask1; argmask1 >>= 1, ++i) {
|
||||
if (argmask1 & 1) {
|
||||
static_cast<cs_alias_impl *>(cs.p_state->identmap[i])->undo_arg(
|
||||
static_cast<alias_impl *>(cs.p_state->identmap[i])->undo_arg(
|
||||
argstack[i]
|
||||
);
|
||||
}
|
||||
}
|
||||
cs_ident_link *prevstack = cs.p_callstack->next;
|
||||
cs_ident_link aliaslink = {
|
||||
ident_link *prevstack = cs.p_callstack->next;
|
||||
ident_link aliaslink = {
|
||||
cs.p_callstack->id, cs.p_callstack,
|
||||
prevstack ? prevstack->usedargs : ((1 << MaxArguments) - 1),
|
||||
prevstack ? prevstack->argstack : nullptr
|
||||
|
@ -220,7 +217,7 @@ static void cs_do_args(cs_state &cs, F body) {
|
|||
int argmask2 = cs.p_callstack->usedargs;
|
||||
for (int i = 0; argmask2; argmask2 >>= 1, ++i) {
|
||||
if (argmask2 & 1) {
|
||||
static_cast<cs_alias_impl *>(cs.p_state->identmap[i])->redo_arg(
|
||||
static_cast<alias_impl *>(cs.p_state->identmap[i])->redo_arg(
|
||||
argstack[i]
|
||||
);
|
||||
}
|
||||
|
@ -230,4 +227,4 @@ static void cs_do_args(cs_state &cs, F body) {
|
|||
|
||||
} /* namespace cscript */
|
||||
|
||||
#endif /* LIBCUBESCRIPT_CS_VM_HH */
|
||||
#endif /* LIBCUBESCRIPT_VM_HH */
|
||||
|
|
100
src/lib_base.cc
100
src/lib_base.cc
|
@ -6,22 +6,22 @@
|
|||
|
||||
namespace cscript {
|
||||
|
||||
static inline void cs_do_loop(
|
||||
cs_state &cs, cs_ident &id, cs_int offset, cs_int n, cs_int step,
|
||||
cs_bcode *cond, cs_bcode *body
|
||||
static inline void do_loop(
|
||||
state &cs, ident &id, integer_type offset, integer_type n, integer_type step,
|
||||
bcode *cond, bcode *body
|
||||
) {
|
||||
cs_stacked_value idv{cs, &id};
|
||||
stacked_value idv{cs, &id};
|
||||
if (n <= 0 || !idv.has_alias()) {
|
||||
return;
|
||||
}
|
||||
for (cs_int i = 0; i < n; ++i) {
|
||||
for (integer_type i = 0; i < n; ++i) {
|
||||
idv.set_int(offset + i * step);
|
||||
idv.push();
|
||||
if (cond && !cs.run(cond).get_bool()) {
|
||||
break;
|
||||
}
|
||||
switch (cs.run_loop(body)) {
|
||||
case cs_loop_state::BREAK:
|
||||
case loop_state::BREAK:
|
||||
goto end;
|
||||
default: /* continue and normal */
|
||||
break;
|
||||
|
@ -31,23 +31,23 @@ end:
|
|||
return;
|
||||
}
|
||||
|
||||
static inline void cs_loop_conc(
|
||||
cs_state &cs, cs_value &res, cs_ident &id, cs_int offset, cs_int n,
|
||||
cs_int step, cs_bcode *body, bool space
|
||||
static inline void do_loop_conc(
|
||||
state &cs, any_value &res, ident &id, integer_type offset, integer_type n,
|
||||
integer_type step, bcode *body, bool space
|
||||
) {
|
||||
cs_stacked_value idv{cs, &id};
|
||||
stacked_value idv{cs, &id};
|
||||
if (n <= 0 || !idv.has_alias()) {
|
||||
return;
|
||||
}
|
||||
cs_charbuf s{cs};
|
||||
for (cs_int i = 0; i < n; ++i) {
|
||||
charbuf s{cs};
|
||||
for (integer_type i = 0; i < n; ++i) {
|
||||
idv.set_int(offset + i * step);
|
||||
idv.push();
|
||||
cs_value v{cs};
|
||||
any_value v{cs};
|
||||
switch (cs.run_loop(body, v)) {
|
||||
case cs_loop_state::BREAK:
|
||||
case loop_state::BREAK:
|
||||
goto end;
|
||||
case cs_loop_state::CONTINUE:
|
||||
case loop_state::CONTINUE:
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
|
@ -61,34 +61,34 @@ end:
|
|||
res.set_str(s.str());
|
||||
}
|
||||
|
||||
void cs_init_lib_base(cs_state &gcs) {
|
||||
void init_lib_base(state &gcs) {
|
||||
gcs.new_command("error", "s", [](auto &cs, auto args, auto &) {
|
||||
throw cs_error(cs, args[0].get_str());
|
||||
throw error(cs, args[0].get_str());
|
||||
});
|
||||
|
||||
gcs.new_command("pcall", "err", [](auto &cs, auto args, auto &ret) {
|
||||
cs_alias *cret = args[1].get_ident()->get_alias(),
|
||||
alias *cret = args[1].get_ident()->get_alias(),
|
||||
*css = args[2].get_ident()->get_alias();
|
||||
if (!cret || !css) {
|
||||
ret.set_int(0);
|
||||
return;
|
||||
}
|
||||
cs_value result{cs}, tback{cs};
|
||||
any_value result{cs}, tback{cs};
|
||||
bool rc = true;
|
||||
try {
|
||||
cs.run(args[0].get_code(), result);
|
||||
} catch (cs_error const &e) {
|
||||
} catch (error const &e) {
|
||||
result.set_str(e.what());
|
||||
if (e.get_stack().get()) {
|
||||
cs_charbuf buf{cs};
|
||||
cs_print_stack(std::back_inserter(buf), e.get_stack());
|
||||
charbuf buf{cs};
|
||||
print_stack(std::back_inserter(buf), e.get_stack());
|
||||
tback.set_str(buf.str());
|
||||
}
|
||||
rc = false;
|
||||
}
|
||||
ret.set_int(rc);
|
||||
static_cast<cs_alias_impl *>(cret)->set_alias(cs, result);
|
||||
static_cast<cs_alias_impl *>(css)->set_alias(cs, tback);
|
||||
static_cast<alias_impl *>(cret)->set_alias(cs, result);
|
||||
static_cast<alias_impl *>(css)->set_alias(cs, tback);
|
||||
});
|
||||
|
||||
gcs.new_command("?", "ttt", [](auto &, auto args, auto &res) {
|
||||
|
@ -114,10 +114,10 @@ void cs_init_lib_base(cs_state &gcs) {
|
|||
});
|
||||
|
||||
gcs.new_command("case", "ite2V", [](auto &cs, auto args, auto &res) {
|
||||
cs_int val = args[0].get_int();
|
||||
integer_type val = args[0].get_int();
|
||||
for (size_t i = 1; (i + 1) < args.size(); i += 2) {
|
||||
if (
|
||||
(args[i].get_type() == cs_value_type::NONE) ||
|
||||
(args[i].get_type() == value_type::NONE) ||
|
||||
(args[i].get_int() == val)
|
||||
) {
|
||||
cs.run(args[i + 1].get_code(), res);
|
||||
|
@ -127,10 +127,10 @@ void cs_init_lib_base(cs_state &gcs) {
|
|||
});
|
||||
|
||||
gcs.new_command("casef", "fte2V", [](auto &cs, auto args, auto &res) {
|
||||
cs_float val = args[0].get_float();
|
||||
float_type val = args[0].get_float();
|
||||
for (size_t i = 1; (i + 1) < args.size(); i += 2) {
|
||||
if (
|
||||
(args[i].get_type() == cs_value_type::NONE) ||
|
||||
(args[i].get_type() == value_type::NONE) ||
|
||||
(args[i].get_float() == val)
|
||||
) {
|
||||
cs.run(args[i + 1].get_code(), res);
|
||||
|
@ -140,10 +140,10 @@ void cs_init_lib_base(cs_state &gcs) {
|
|||
});
|
||||
|
||||
gcs.new_command("cases", "ste2V", [](auto &cs, auto args, auto &res) {
|
||||
cs_strref val = args[0].get_str();
|
||||
string_ref val = args[0].get_str();
|
||||
for (size_t i = 1; (i + 1) < args.size(); i += 2) {
|
||||
if (
|
||||
(args[i].get_type() == cs_value_type::NONE) ||
|
||||
(args[i].get_type() == value_type::NONE) ||
|
||||
(args[i].get_str() == val)
|
||||
) {
|
||||
cs.run(args[i + 1].get_code(), res);
|
||||
|
@ -153,7 +153,7 @@ void cs_init_lib_base(cs_state &gcs) {
|
|||
});
|
||||
|
||||
gcs.new_command("pushif", "rte", [](auto &cs, auto args, auto &res) {
|
||||
cs_stacked_value idv{cs, args[0].get_ident()};
|
||||
stacked_value idv{cs, args[0].get_ident()};
|
||||
if (!idv.has_alias() || (idv.get_alias()->get_index() < MaxArguments)) {
|
||||
return;
|
||||
}
|
||||
|
@ -165,66 +165,66 @@ void cs_init_lib_base(cs_state &gcs) {
|
|||
});
|
||||
|
||||
gcs.new_command("loop", "rie", [](auto &cs, auto args, auto &) {
|
||||
cs_do_loop(
|
||||
do_loop(
|
||||
cs, *args[0].get_ident(), 0, args[1].get_int(), 1, nullptr,
|
||||
args[2].get_code()
|
||||
);
|
||||
});
|
||||
|
||||
gcs.new_command("loop+", "riie", [](auto &cs, auto args, auto &) {
|
||||
cs_do_loop(
|
||||
do_loop(
|
||||
cs, *args[0].get_ident(), args[1].get_int(), args[2].get_int(), 1,
|
||||
nullptr, args[3].get_code()
|
||||
);
|
||||
});
|
||||
|
||||
gcs.new_command("loop*", "riie", [](auto &cs, auto args, auto &) {
|
||||
cs_do_loop(
|
||||
do_loop(
|
||||
cs, *args[0].get_ident(), 0, args[1].get_int(), args[2].get_int(),
|
||||
nullptr, args[3].get_code()
|
||||
);
|
||||
});
|
||||
|
||||
gcs.new_command("loop+*", "riiie", [](auto &cs, auto args, auto &) {
|
||||
cs_do_loop(
|
||||
do_loop(
|
||||
cs, *args[0].get_ident(), args[1].get_int(), args[3].get_int(),
|
||||
args[2].get_int(), nullptr, args[4].get_code()
|
||||
);
|
||||
});
|
||||
|
||||
gcs.new_command("loopwhile", "riee", [](auto &cs, auto args, auto &) {
|
||||
cs_do_loop(
|
||||
do_loop(
|
||||
cs, *args[0].get_ident(), 0, args[1].get_int(), 1,
|
||||
args[2].get_code(), args[3].get_code()
|
||||
);
|
||||
});
|
||||
|
||||
gcs.new_command("loopwhile+", "riiee", [](auto &cs, auto args, auto &) {
|
||||
cs_do_loop(
|
||||
do_loop(
|
||||
cs, *args[0].get_ident(), args[1].get_int(), args[2].get_int(), 1,
|
||||
args[3].get_code(), args[4].get_code()
|
||||
);
|
||||
});
|
||||
|
||||
gcs.new_command("loopwhile*", "riiee", [](auto &cs, auto args, auto &) {
|
||||
cs_do_loop(
|
||||
do_loop(
|
||||
cs, *args[0].get_ident(), 0, args[2].get_int(), args[1].get_int(),
|
||||
args[3].get_code(), args[4].get_code()
|
||||
);
|
||||
});
|
||||
|
||||
gcs.new_command("loopwhile+*", "riiiee", [](auto &cs, auto args, auto &) {
|
||||
cs_do_loop(
|
||||
do_loop(
|
||||
cs, *args[0].get_ident(), args[1].get_int(), args[3].get_int(),
|
||||
args[2].get_int(), args[4].get_code(), args[5].get_code()
|
||||
);
|
||||
});
|
||||
|
||||
gcs.new_command("while", "ee", [](auto &cs, auto args, auto &) {
|
||||
cs_bcode *cond = args[0].get_code(), *body = args[1].get_code();
|
||||
bcode *cond = args[0].get_code(), *body = args[1].get_code();
|
||||
while (cs.run(cond).get_bool()) {
|
||||
switch (cs.run_loop(body)) {
|
||||
case cs_loop_state::BREAK:
|
||||
case loop_state::BREAK:
|
||||
goto end;
|
||||
default: /* continue and normal */
|
||||
break;
|
||||
|
@ -235,35 +235,35 @@ end:
|
|||
});
|
||||
|
||||
gcs.new_command("loopconcat", "rie", [](auto &cs, auto args, auto &res) {
|
||||
cs_loop_conc(
|
||||
do_loop_conc(
|
||||
cs, res, *args[0].get_ident(), 0, args[1].get_int(), 1,
|
||||
args[2].get_code(), true
|
||||
);
|
||||
});
|
||||
|
||||
gcs.new_command("loopconcat+", "riie", [](auto &cs, auto args, auto &res) {
|
||||
cs_loop_conc(
|
||||
do_loop_conc(
|
||||
cs, res, *args[0].get_ident(), args[1].get_int(),
|
||||
args[2].get_int(), 1, args[3].get_code(), true
|
||||
);
|
||||
});
|
||||
|
||||
gcs.new_command("loopconcat*", "riie", [](auto &cs, auto args, auto &res) {
|
||||
cs_loop_conc(
|
||||
do_loop_conc(
|
||||
cs, res, *args[0].get_ident(), 0, args[2].get_int(),
|
||||
args[1].get_int(), args[3].get_code(), true
|
||||
);
|
||||
});
|
||||
|
||||
gcs.new_command("loopconcat+*", "riiie", [](auto &cs, auto args, auto &res) {
|
||||
cs_loop_conc(
|
||||
do_loop_conc(
|
||||
cs, res, *args[0].get_ident(), args[1].get_int(),
|
||||
args[3].get_int(), args[2].get_int(), args[4].get_code(), true
|
||||
);
|
||||
});
|
||||
|
||||
gcs.new_command("loopconcatword", "rie", [](auto &cs, auto args, auto &res) {
|
||||
cs_loop_conc(
|
||||
do_loop_conc(
|
||||
cs, res, *args[0].get_ident(), 0, args[1].get_int(), 1,
|
||||
args[2].get_code(), false
|
||||
);
|
||||
|
@ -272,7 +272,7 @@ end:
|
|||
gcs.new_command("loopconcatword+", "riie", [](
|
||||
auto &cs, auto args, auto &res
|
||||
) {
|
||||
cs_loop_conc(
|
||||
do_loop_conc(
|
||||
cs, res, *args[0].get_ident(), args[1].get_int(),
|
||||
args[2].get_int(), 1, args[3].get_code(), false
|
||||
);
|
||||
|
@ -281,7 +281,7 @@ end:
|
|||
gcs.new_command("loopconcatword*", "riie", [](
|
||||
auto &cs, auto args, auto &res
|
||||
) {
|
||||
cs_loop_conc(
|
||||
do_loop_conc(
|
||||
cs, res, *args[0].get_ident(), 0, args[2].get_int(),
|
||||
args[1].get_int(), args[3].get_code(), false
|
||||
);
|
||||
|
@ -290,14 +290,14 @@ end:
|
|||
gcs.new_command("loopconcatword+*", "riiie", [](
|
||||
auto &cs, auto args, auto &res
|
||||
) {
|
||||
cs_loop_conc(
|
||||
do_loop_conc(
|
||||
cs, res, *args[0].get_ident(), args[1].get_int(), args[3].get_int(),
|
||||
args[2].get_int(), args[4].get_code(), false
|
||||
);
|
||||
});
|
||||
|
||||
gcs.new_command("push", "rte", [](auto &cs, auto args, auto &res) {
|
||||
cs_stacked_value idv{cs, args[0].get_ident()};
|
||||
stacked_value idv{cs, args[0].get_ident()};
|
||||
if (!idv.has_alias() || (idv.get_alias()->get_index() < MaxArguments)) {
|
||||
return;
|
||||
}
|
||||
|
|
216
src/lib_list.cc
216
src/lib_list.cc
|
@ -8,36 +8,36 @@
|
|||
namespace cscript {
|
||||
|
||||
template<typename T>
|
||||
struct cs_arg_val;
|
||||
struct arg_val;
|
||||
|
||||
template<>
|
||||
struct cs_arg_val<cs_int> {
|
||||
static cs_int get(cs_value &tv) {
|
||||
struct arg_val<integer_type> {
|
||||
static integer_type get(any_value &tv) {
|
||||
return tv.get_int();
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct cs_arg_val<cs_float> {
|
||||
static cs_float get(cs_value &tv) {
|
||||
struct arg_val<float_type> {
|
||||
static float_type get(any_value &tv) {
|
||||
return tv.get_float();
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct cs_arg_val<std::string_view> {
|
||||
static std::string_view get(cs_value &tv) {
|
||||
struct arg_val<std::string_view> {
|
||||
static std::string_view get(any_value &tv) {
|
||||
return tv.get_str();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename F>
|
||||
static inline void cs_list_find(
|
||||
cs_state &cs, std::span<cs_value> args, cs_value &res, F cmp
|
||||
static inline void list_find(
|
||||
state &cs, std::span<any_value> args, any_value &res, F cmp
|
||||
) {
|
||||
cs_int n = 0, skip = args[2].get_int();
|
||||
T val = cs_arg_val<T>::get(args[1]);
|
||||
for (cs_list_parser p{cs, args[0].get_str()}; p.parse(); ++n) {
|
||||
integer_type n = 0, skip = args[2].get_int();
|
||||
T val = arg_val<T>::get(args[1]);
|
||||
for (list_parser p{cs, args[0].get_str()}; p.parse(); ++n) {
|
||||
if (cmp(p, val)) {
|
||||
res.set_int(n);
|
||||
return;
|
||||
|
@ -54,11 +54,11 @@ notfound:
|
|||
}
|
||||
|
||||
template<typename T, typename F>
|
||||
static inline void cs_list_assoc(
|
||||
cs_state &cs, std::span<cs_value> args, cs_value &res, F cmp
|
||||
static inline void list_assoc(
|
||||
state &cs, std::span<any_value> args, any_value &res, F cmp
|
||||
) {
|
||||
T val = cs_arg_val<T>::get(args[1]);
|
||||
for (cs_list_parser p{cs, args[0].get_str()}; p.parse();) {
|
||||
T val = arg_val<T>::get(args[1]);
|
||||
for (list_parser p{cs, args[0].get_str()}; p.parse();) {
|
||||
if (cmp(p, val)) {
|
||||
if (p.parse()) {
|
||||
res.set_str(p.get_item());
|
||||
|
@ -71,27 +71,27 @@ static inline void cs_list_assoc(
|
|||
}
|
||||
}
|
||||
|
||||
static void cs_loop_list_conc(
|
||||
cs_state &cs, cs_value &res, cs_ident *id, std::string_view list,
|
||||
cs_bcode *body, bool space
|
||||
static void loop_list_conc(
|
||||
state &cs, any_value &res, ident *id, std::string_view list,
|
||||
bcode *body, bool space
|
||||
) {
|
||||
cs_stacked_value idv{cs, id};
|
||||
stacked_value idv{cs, id};
|
||||
if (!idv.has_alias()) {
|
||||
return;
|
||||
}
|
||||
cs_charbuf r{cs};
|
||||
charbuf r{cs};
|
||||
int n = 0;
|
||||
for (cs_list_parser p{cs, list}; p.parse(); ++n) {
|
||||
for (list_parser p{cs, list}; p.parse(); ++n) {
|
||||
idv.set_str(p.get_item());
|
||||
idv.push();
|
||||
if (n && space) {
|
||||
r.push_back(' ');
|
||||
}
|
||||
cs_value v{cs};
|
||||
any_value v{cs};
|
||||
switch (cs.run_loop(body, v)) {
|
||||
case cs_loop_state::BREAK:
|
||||
case loop_state::BREAK:
|
||||
goto end;
|
||||
case cs_loop_state::CONTINUE:
|
||||
case loop_state::CONTINUE:
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
|
@ -102,11 +102,11 @@ end:
|
|||
res.set_str(r.str());
|
||||
}
|
||||
|
||||
int cs_list_includes(
|
||||
cs_state &cs, std::string_view list, std::string_view needle
|
||||
int list_includes(
|
||||
state &cs, std::string_view list, std::string_view needle
|
||||
) {
|
||||
int offset = 0;
|
||||
for (cs_list_parser p{cs, list}; p.parse();) {
|
||||
for (list_parser p{cs, list}; p.parse();) {
|
||||
if (p.get_raw_item() == needle) {
|
||||
return offset;
|
||||
}
|
||||
|
@ -116,20 +116,20 @@ int cs_list_includes(
|
|||
}
|
||||
|
||||
template<bool PushList, bool Swap, typename F>
|
||||
static inline void cs_list_merge(
|
||||
cs_state &cs, std::span<cs_value> args, cs_value &res, F cmp
|
||||
static inline void list_merge(
|
||||
state &cs, std::span<any_value> args, any_value &res, F cmp
|
||||
) {
|
||||
std::string_view list = args[0].get_str();
|
||||
std::string_view elems = args[1].get_str();
|
||||
cs_charbuf buf{cs};
|
||||
charbuf buf{cs};
|
||||
if (PushList) {
|
||||
buf.append(list);
|
||||
}
|
||||
if (Swap) {
|
||||
std::swap(list, elems);
|
||||
}
|
||||
for (cs_list_parser p{cs, list}; p.parse();) {
|
||||
if (cmp(cs_list_includes(cs, elems, p.get_raw_item()), 0)) {
|
||||
for (list_parser p{cs, list}; p.parse();) {
|
||||
if (cmp(list_includes(cs, elems, p.get_raw_item()), 0)) {
|
||||
if (!buf.empty()) {
|
||||
buf.push_back(' ');
|
||||
}
|
||||
|
@ -139,11 +139,11 @@ static inline void cs_list_merge(
|
|||
res.set_str(buf.str());
|
||||
}
|
||||
|
||||
static void cs_init_lib_list_sort(cs_state &cs);
|
||||
static void init_lib_list_sort(state &cs);
|
||||
|
||||
void cs_init_lib_list(cs_state &gcs) {
|
||||
void init_lib_list(state &gcs) {
|
||||
gcs.new_command("listlen", "s", [](auto &cs, auto args, auto &res) {
|
||||
res.set_int(cs_int(cs_list_parser{cs, args[0].get_str()}.count()));
|
||||
res.set_int(integer_type(list_parser{cs, args[0].get_str()}.count()));
|
||||
});
|
||||
|
||||
gcs.new_command("at", "si1V", [](auto &cs, auto args, auto &res) {
|
||||
|
@ -155,10 +155,10 @@ void cs_init_lib_list(cs_state &gcs) {
|
|||
return;
|
||||
}
|
||||
auto str = args[0].get_str();
|
||||
cs_list_parser p{cs, str};
|
||||
list_parser p{cs, str};
|
||||
for (size_t i = 1; i < args.size(); ++i) {
|
||||
p.set_input(str);
|
||||
cs_int pos = args[i].get_int();
|
||||
integer_type pos = args[i].get_int();
|
||||
for (; pos > 0; --pos) {
|
||||
if (!p.parse()) {
|
||||
break;
|
||||
|
@ -172,15 +172,15 @@ void cs_init_lib_list(cs_state &gcs) {
|
|||
});
|
||||
|
||||
gcs.new_command("sublist", "siiN", [](auto &cs, auto args, auto &res) {
|
||||
cs_int skip = args[1].get_int(),
|
||||
integer_type skip = args[1].get_int(),
|
||||
count = args[2].get_int(),
|
||||
numargs = args[3].get_int();
|
||||
|
||||
cs_int offset = std::max(skip, cs_int(0)),
|
||||
len = (numargs >= 3) ? std::max(count, cs_int(0)) : -1;
|
||||
integer_type offset = std::max(skip, integer_type(0)),
|
||||
len = (numargs >= 3) ? std::max(count, integer_type(0)) : -1;
|
||||
|
||||
cs_list_parser p{cs, args[0].get_str()};
|
||||
for (cs_int i = 0; i < offset; ++i) {
|
||||
list_parser p{cs, args[0].get_str()};
|
||||
for (integer_type i = 0; i < offset; ++i) {
|
||||
if (!p.parse()) break;
|
||||
}
|
||||
if (len < 0) {
|
||||
|
@ -204,19 +204,19 @@ void cs_init_lib_list(cs_state &gcs) {
|
|||
});
|
||||
|
||||
gcs.new_command("listfind", "rse", [](auto &cs, auto args, auto &res) {
|
||||
cs_stacked_value idv{cs, args[0].get_ident()};
|
||||
stacked_value idv{cs, args[0].get_ident()};
|
||||
if (!idv.has_alias()) {
|
||||
res.set_int(-1);
|
||||
return;
|
||||
}
|
||||
auto body = args[2].get_code();
|
||||
int n = -1;
|
||||
for (cs_list_parser p{cs, args[1].get_str()}; p.parse();) {
|
||||
for (list_parser p{cs, args[1].get_str()}; p.parse();) {
|
||||
++n;
|
||||
idv.set_str(p.get_raw_item());
|
||||
idv.push();
|
||||
if (cs.run(body).get_bool()) {
|
||||
res.set_int(cs_int(n));
|
||||
res.set_int(integer_type(n));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -224,13 +224,13 @@ void cs_init_lib_list(cs_state &gcs) {
|
|||
});
|
||||
|
||||
gcs.new_command("listassoc", "rse", [](auto &cs, auto args, auto &res) {
|
||||
cs_stacked_value idv{cs, args[0].get_ident()};
|
||||
stacked_value idv{cs, args[0].get_ident()};
|
||||
if (!idv.has_alias()) {
|
||||
return;
|
||||
}
|
||||
auto body = args[2].get_code();
|
||||
int n = -1;
|
||||
for (cs_list_parser p{cs, args[1].get_str()}; p.parse();) {
|
||||
for (list_parser p{cs, args[1].get_str()}; p.parse();) {
|
||||
++n;
|
||||
idv.set_str(p.get_raw_item());
|
||||
idv.push();
|
||||
|
@ -247,61 +247,61 @@ void cs_init_lib_list(cs_state &gcs) {
|
|||
});
|
||||
|
||||
gcs.new_command("listfind=", "i", [](auto &cs, auto args, auto &res) {
|
||||
cs_list_find<cs_int>(
|
||||
cs, args, res, [](cs_list_parser const &p, cs_int val) {
|
||||
list_find<integer_type>(
|
||||
cs, args, res, [](list_parser const &p, integer_type val) {
|
||||
return parse_int(p.get_raw_item()) == val;
|
||||
}
|
||||
);
|
||||
});
|
||||
gcs.new_command("listfind=f", "f", [](auto &cs, auto args, auto &res) {
|
||||
cs_list_find<cs_float>(
|
||||
cs, args, res, [](cs_list_parser const &p, cs_float val) {
|
||||
list_find<float_type>(
|
||||
cs, args, res, [](list_parser const &p, float_type val) {
|
||||
return parse_float(p.get_raw_item()) == val;
|
||||
}
|
||||
);
|
||||
});
|
||||
gcs.new_command("listfind=s", "s", [](auto &cs, auto args, auto &res) {
|
||||
cs_list_find<std::string_view>(
|
||||
cs, args, res, [](cs_list_parser const &p, std::string_view val) {
|
||||
list_find<std::string_view>(
|
||||
cs, args, res, [](list_parser const &p, std::string_view val) {
|
||||
return p.get_raw_item() == val;
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
gcs.new_command("listassoc=", "i", [](auto &cs, auto args, auto &res) {
|
||||
cs_list_assoc<cs_int>(
|
||||
cs, args, res, [](cs_list_parser const &p, cs_int val) {
|
||||
list_assoc<integer_type>(
|
||||
cs, args, res, [](list_parser const &p, integer_type val) {
|
||||
return parse_int(p.get_raw_item()) == val;
|
||||
}
|
||||
);
|
||||
});
|
||||
gcs.new_command("listassoc=f", "f", [](auto &cs, auto args, auto &res) {
|
||||
cs_list_assoc<cs_float>(
|
||||
cs, args, res, [](cs_list_parser const &p, cs_float val) {
|
||||
list_assoc<float_type>(
|
||||
cs, args, res, [](list_parser const &p, float_type val) {
|
||||
return parse_float(p.get_raw_item()) == val;
|
||||
}
|
||||
);
|
||||
});
|
||||
gcs.new_command("listassoc=s", "s", [](auto &cs, auto args, auto &res) {
|
||||
cs_list_assoc<std::string_view>(
|
||||
cs, args, res, [](cs_list_parser const &p, std::string_view val) {
|
||||
list_assoc<std::string_view>(
|
||||
cs, args, res, [](list_parser const &p, std::string_view val) {
|
||||
return p.get_raw_item() == val;
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
gcs.new_command("looplist", "rse", [](auto &cs, auto args, auto &) {
|
||||
cs_stacked_value idv{cs, args[0].get_ident()};
|
||||
stacked_value idv{cs, args[0].get_ident()};
|
||||
if (!idv.has_alias()) {
|
||||
return;
|
||||
}
|
||||
auto body = args[2].get_code();
|
||||
int n = 0;
|
||||
for (cs_list_parser p{cs, args[1].get_str()}; p.parse(); ++n) {
|
||||
for (list_parser p{cs, args[1].get_str()}; p.parse(); ++n) {
|
||||
idv.set_str(p.get_item());
|
||||
idv.push();
|
||||
switch (cs.run_loop(body)) {
|
||||
case cs_loop_state::BREAK:
|
||||
case loop_state::BREAK:
|
||||
goto end;
|
||||
default: /* continue and normal */
|
||||
break;
|
||||
|
@ -312,14 +312,14 @@ end:
|
|||
});
|
||||
|
||||
gcs.new_command("looplist2", "rrse", [](auto &cs, auto args, auto &) {
|
||||
cs_stacked_value idv1{cs, args[0].get_ident()};
|
||||
cs_stacked_value idv2{cs, args[1].get_ident()};
|
||||
stacked_value idv1{cs, args[0].get_ident()};
|
||||
stacked_value idv2{cs, args[1].get_ident()};
|
||||
if (!idv1.has_alias() || !idv2.has_alias()) {
|
||||
return;
|
||||
}
|
||||
auto body = args[3].get_code();
|
||||
int n = 0;
|
||||
for (cs_list_parser p{cs, args[2].get_str()}; p.parse(); n += 2) {
|
||||
for (list_parser p{cs, args[2].get_str()}; p.parse(); n += 2) {
|
||||
idv1.set_str(p.get_item());
|
||||
if (p.parse()) {
|
||||
idv2.set_str(p.get_item());
|
||||
|
@ -329,7 +329,7 @@ end:
|
|||
idv1.push();
|
||||
idv2.push();
|
||||
switch (cs.run_loop(body)) {
|
||||
case cs_loop_state::BREAK:
|
||||
case loop_state::BREAK:
|
||||
goto end;
|
||||
default: /* continue and normal */
|
||||
break;
|
||||
|
@ -340,15 +340,15 @@ end:
|
|||
});
|
||||
|
||||
gcs.new_command("looplist3", "rrrse", [](auto &cs, auto args, auto &) {
|
||||
cs_stacked_value idv1{cs, args[0].get_ident()};
|
||||
cs_stacked_value idv2{cs, args[1].get_ident()};
|
||||
cs_stacked_value idv3{cs, args[2].get_ident()};
|
||||
stacked_value idv1{cs, args[0].get_ident()};
|
||||
stacked_value idv2{cs, args[1].get_ident()};
|
||||
stacked_value idv3{cs, args[2].get_ident()};
|
||||
if (!idv1.has_alias() || !idv2.has_alias() || !idv3.has_alias()) {
|
||||
return;
|
||||
}
|
||||
auto body = args[4].get_code();
|
||||
int n = 0;
|
||||
for (cs_list_parser p{cs, args[3].get_str()}; p.parse(); n += 3) {
|
||||
for (list_parser p{cs, args[3].get_str()}; p.parse(); n += 3) {
|
||||
idv1.set_str(p.get_item());
|
||||
if (p.parse()) {
|
||||
idv2.set_str(p.get_item());
|
||||
|
@ -364,7 +364,7 @@ end:
|
|||
idv2.push();
|
||||
idv3.push();
|
||||
switch (cs.run_loop(body)) {
|
||||
case cs_loop_state::BREAK:
|
||||
case loop_state::BREAK:
|
||||
goto end;
|
||||
default: /* continue and normal */
|
||||
break;
|
||||
|
@ -375,7 +375,7 @@ end:
|
|||
});
|
||||
|
||||
gcs.new_command("looplistconcat", "rse", [](auto &cs, auto args, auto &res) {
|
||||
cs_loop_list_conc(
|
||||
loop_list_conc(
|
||||
cs, res, args[0].get_ident(), args[1].get_str(),
|
||||
args[2].get_code(), true
|
||||
);
|
||||
|
@ -384,21 +384,21 @@ end:
|
|||
gcs.new_command("looplistconcatword", "rse", [](
|
||||
auto &cs, auto args, auto &res
|
||||
) {
|
||||
cs_loop_list_conc(
|
||||
loop_list_conc(
|
||||
cs, res, args[0].get_ident(), args[1].get_str(),
|
||||
args[2].get_code(), false
|
||||
);
|
||||
});
|
||||
|
||||
gcs.new_command("listfilter", "rse", [](auto &cs, auto args, auto &res) {
|
||||
cs_stacked_value idv{cs, args[0].get_ident()};
|
||||
stacked_value idv{cs, args[0].get_ident()};
|
||||
if (!idv.has_alias()) {
|
||||
return;
|
||||
}
|
||||
auto body = args[2].get_code();
|
||||
cs_charbuf r{cs};
|
||||
charbuf r{cs};
|
||||
int n = 0;
|
||||
for (cs_list_parser p{cs, args[1].get_str()}; p.parse(); ++n) {
|
||||
for (list_parser p{cs, args[1].get_str()}; p.parse(); ++n) {
|
||||
idv.set_str(p.get_raw_item());
|
||||
idv.push();
|
||||
if (cs.run(body).get_bool()) {
|
||||
|
@ -412,13 +412,13 @@ end:
|
|||
});
|
||||
|
||||
gcs.new_command("listcount", "rse", [](auto &cs, auto args, auto &res) {
|
||||
cs_stacked_value idv{cs, args[0].get_ident()};
|
||||
stacked_value idv{cs, args[0].get_ident()};
|
||||
if (!idv.has_alias()) {
|
||||
return;
|
||||
}
|
||||
auto body = args[2].get_code();
|
||||
int n = 0, r = 0;
|
||||
for (cs_list_parser p{cs, args[1].get_str()}; p.parse(); ++n) {
|
||||
for (list_parser p{cs, args[1].get_str()}; p.parse(); ++n) {
|
||||
idv.set_str(p.get_raw_item());
|
||||
idv.push();
|
||||
if (cs.run(body).get_bool()) {
|
||||
|
@ -429,16 +429,16 @@ end:
|
|||
});
|
||||
|
||||
gcs.new_command("prettylist", "ss", [](auto &cs, auto args, auto &res) {
|
||||
cs_charbuf buf{cs};
|
||||
charbuf buf{cs};
|
||||
std::string_view s = args[0].get_str();
|
||||
std::string_view conj = args[1].get_str();
|
||||
cs_list_parser p{cs, s};
|
||||
list_parser p{cs, s};
|
||||
size_t len = p.count();
|
||||
size_t n = 0;
|
||||
for (p.set_input(s); p.parse(); ++n) {
|
||||
auto qi = p.get_quoted_item();
|
||||
if (!qi.empty() && (qi.front() == '"')) {
|
||||
cs_unescape_string(std::back_inserter(buf), p.get_raw_item());
|
||||
unescape_string(std::back_inserter(buf), p.get_raw_item());
|
||||
} else {
|
||||
buf.append(p.get_raw_item());
|
||||
}
|
||||
|
@ -458,35 +458,35 @@ end:
|
|||
|
||||
gcs.new_command("indexof", "ss", [](auto &cs, auto args, auto &res) {
|
||||
res.set_int(
|
||||
cs_list_includes(cs, args[0].get_str(), args[1].get_str())
|
||||
list_includes(cs, args[0].get_str(), args[1].get_str())
|
||||
);
|
||||
});
|
||||
|
||||
gcs.new_command("listdel", "ss", [](auto &cs, auto args, auto &res) {
|
||||
cs_list_merge<false, false>(cs, args, res, std::less<int>());
|
||||
list_merge<false, false>(cs, args, res, std::less<int>());
|
||||
});
|
||||
gcs.new_command("listintersect", "ss", [](auto &cs, auto args, auto &res) {
|
||||
cs_list_merge<false, false>(cs, args, res, std::greater_equal<int>());
|
||||
list_merge<false, false>(cs, args, res, std::greater_equal<int>());
|
||||
});
|
||||
gcs.new_command("listunion", "ss", [](auto &cs, auto args, auto &res) {
|
||||
cs_list_merge<true, true>(cs, args, res, std::less<int>());
|
||||
list_merge<true, true>(cs, args, res, std::less<int>());
|
||||
});
|
||||
|
||||
gcs.new_command("listsplice", "ssii", [](auto &cs, auto args, auto &res) {
|
||||
cs_int offset = std::max(args[2].get_int(), cs_int(0));
|
||||
cs_int len = std::max(args[3].get_int(), cs_int(0));
|
||||
integer_type offset = std::max(args[2].get_int(), integer_type(0));
|
||||
integer_type len = std::max(args[3].get_int(), integer_type(0));
|
||||
std::string_view s = args[0].get_str();
|
||||
std::string_view vals = args[1].get_str();
|
||||
char const *list = s.data();
|
||||
cs_list_parser p{cs, s};
|
||||
for (cs_int i = 0; i < offset; ++i) {
|
||||
list_parser p{cs, s};
|
||||
for (integer_type i = 0; i < offset; ++i) {
|
||||
if (!p.parse()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
std::string_view quote = p.get_quoted_item();
|
||||
char const *qend = !quote.empty() ? "e[quote.size()] : list;
|
||||
cs_charbuf buf{cs};
|
||||
charbuf buf{cs};
|
||||
if (qend > list) {
|
||||
buf.append(list, qend);
|
||||
}
|
||||
|
@ -496,7 +496,7 @@ end:
|
|||
}
|
||||
buf.append(vals);
|
||||
}
|
||||
for (cs_int i = 0; i < len; ++i) {
|
||||
for (integer_type i = 0; i < len; ++i) {
|
||||
if (!p.parse()) {
|
||||
break;
|
||||
}
|
||||
|
@ -518,7 +518,7 @@ end:
|
|||
res.set_str(buf.str());
|
||||
});
|
||||
|
||||
cs_init_lib_list_sort(gcs);
|
||||
init_lib_list_sort(gcs);
|
||||
}
|
||||
|
||||
struct ListSortItem {
|
||||
|
@ -527,9 +527,9 @@ struct ListSortItem {
|
|||
};
|
||||
|
||||
struct ListSortFun {
|
||||
cs_state &cs;
|
||||
cs_stacked_value &xv, &yv;
|
||||
cs_bcode *body;
|
||||
state &cs;
|
||||
stacked_value &xv, &yv;
|
||||
bcode *body;
|
||||
|
||||
bool operator()(ListSortItem const &xval, ListSortItem const &yval) {
|
||||
xv.set_str(xval.str);
|
||||
|
@ -540,20 +540,20 @@ struct ListSortFun {
|
|||
}
|
||||
};
|
||||
|
||||
static void cs_list_sort(
|
||||
cs_state &cs, cs_value &res, std::string_view list,
|
||||
cs_ident *x, cs_ident *y, cs_bcode *body, cs_bcode *unique
|
||||
static void list_sort(
|
||||
state &cs, any_value &res, std::string_view list,
|
||||
ident *x, ident *y, bcode *body, bcode *unique
|
||||
) {
|
||||
if (x == y || !x->is_alias() || !y->is_alias()) {
|
||||
return;
|
||||
}
|
||||
|
||||
cs_alias *xa = static_cast<cs_alias *>(x), *ya = static_cast<cs_alias *>(y);
|
||||
alias *xa = static_cast<alias *>(x), *ya = static_cast<alias *>(y);
|
||||
|
||||
cs_valbuf<ListSortItem> items{cs};
|
||||
valbuf<ListSortItem> items{cs};
|
||||
size_t total = 0;
|
||||
|
||||
for (cs_list_parser p{cs, list}; p.parse();) {
|
||||
for (list_parser p{cs, list}; p.parse();) {
|
||||
ListSortItem item = { p.get_raw_item(), p.get_quoted_item() };
|
||||
items.push_back(item);
|
||||
total += item.quote.size();
|
||||
|
@ -564,7 +564,7 @@ static void cs_list_sort(
|
|||
return;
|
||||
}
|
||||
|
||||
cs_stacked_value xval{cs, xa}, yval{cs, ya};
|
||||
stacked_value xval{cs, xa}, yval{cs, ya};
|
||||
xval.set_none();
|
||||
yval.set_none();
|
||||
xval.push();
|
||||
|
@ -575,7 +575,7 @@ static void cs_list_sort(
|
|||
if (body) {
|
||||
ListSortFun f = { cs, xval, yval, body };
|
||||
std::sort(items.buf.begin(), items.buf.end(), f);
|
||||
if (!cs_code_is_empty(unique)) {
|
||||
if (!code_is_empty(unique)) {
|
||||
f.body = unique;
|
||||
totaluniq = items[0].quote.size();
|
||||
nuniq = 1;
|
||||
|
@ -612,7 +612,7 @@ static void cs_list_sort(
|
|||
xval.pop();
|
||||
yval.pop();
|
||||
|
||||
cs_charbuf sorted{cs};
|
||||
charbuf sorted{cs};
|
||||
sorted.reserve(totaluniq + std::max(nuniq - 1, size_t(0)));
|
||||
for (size_t i = 0; i < items.size(); ++i) {
|
||||
ListSortItem &item = items[i];
|
||||
|
@ -627,15 +627,15 @@ static void cs_list_sort(
|
|||
res.set_str(sorted.str());
|
||||
}
|
||||
|
||||
static void cs_init_lib_list_sort(cs_state &gcs) {
|
||||
static void init_lib_list_sort(state &gcs) {
|
||||
gcs.new_command("sortlist", "srree", [](auto &cs, auto args, auto &res) {
|
||||
cs_list_sort(
|
||||
list_sort(
|
||||
cs, res, args[0].get_str(), args[1].get_ident(),
|
||||
args[2].get_ident(), args[3].get_code(), args[4].get_code()
|
||||
);
|
||||
});
|
||||
gcs.new_command("uniquelist", "srre", [](auto &cs, auto args, auto &res) {
|
||||
cs_list_sort(
|
||||
list_sort(
|
||||
cs, res, args[0].get_str(), args[1].get_ident(),
|
||||
args[2].get_ident(), nullptr, args[3].get_code()
|
||||
);
|
||||
|
|
184
src/lib_math.cc
184
src/lib_math.cc
|
@ -8,71 +8,71 @@
|
|||
|
||||
namespace cscript {
|
||||
|
||||
static constexpr cs_float PI = 3.14159265358979f;
|
||||
static constexpr cs_float RAD = PI / 180.0f;
|
||||
static constexpr float_type PI = 3.14159265358979f;
|
||||
static constexpr float_type RAD = PI / 180.0f;
|
||||
|
||||
template<typename T>
|
||||
struct cs_math_val;
|
||||
struct math_val;
|
||||
|
||||
template<>
|
||||
struct cs_math_val<cs_int> {
|
||||
static cs_int get(cs_value &tv) {
|
||||
struct math_val<integer_type> {
|
||||
static integer_type get(any_value &tv) {
|
||||
return tv.get_int();
|
||||
}
|
||||
static void set(cs_value &res, cs_int val) {
|
||||
static void set(any_value &res, integer_type val) {
|
||||
res.set_int(val);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct cs_math_val<cs_float> {
|
||||
static cs_float get(cs_value &tv) {
|
||||
struct math_val<float_type> {
|
||||
static float_type get(any_value &tv) {
|
||||
return tv.get_float();
|
||||
}
|
||||
static void set(cs_value &res, cs_float val) {
|
||||
static void set(any_value &res, float_type val) {
|
||||
res.set_float(val);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct cs_math_noop {
|
||||
struct math_noop {
|
||||
T operator()(T arg) {
|
||||
return arg;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename F1, typename F2>
|
||||
static inline void cs_mathop(
|
||||
std::span<cs_value> args, cs_value &res, T initval,
|
||||
static inline void math_op(
|
||||
std::span<any_value> args, any_value &res, T initval,
|
||||
F1 binop, F2 unop
|
||||
) {
|
||||
T val;
|
||||
if (args.size() >= 2) {
|
||||
val = binop(cs_math_val<T>::get(args[0]), cs_math_val<T>::get(args[1]));
|
||||
val = binop(math_val<T>::get(args[0]), math_val<T>::get(args[1]));
|
||||
for (size_t i = 2; i < args.size(); ++i) {
|
||||
val = binop(val, cs_math_val<T>::get(args[i]));
|
||||
val = binop(val, math_val<T>::get(args[i]));
|
||||
}
|
||||
} else {
|
||||
val = unop(!args.empty() ? cs_math_val<T>::get(args[0]) : initval);
|
||||
val = unop(!args.empty() ? math_val<T>::get(args[0]) : initval);
|
||||
}
|
||||
cs_math_val<T>::set(res, val);
|
||||
math_val<T>::set(res, val);
|
||||
}
|
||||
|
||||
template<typename T, typename F>
|
||||
static inline void cs_cmpop(std::span<cs_value> args, cs_value &res, F cmp) {
|
||||
static inline void cmp_op(std::span<any_value> args, any_value &res, F cmp) {
|
||||
bool val;
|
||||
if (args.size() >= 2) {
|
||||
val = cmp(cs_math_val<T>::get(args[0]), cs_math_val<T>::get(args[1]));
|
||||
val = cmp(math_val<T>::get(args[0]), math_val<T>::get(args[1]));
|
||||
for (size_t i = 2; (i < args.size()) && val; ++i) {
|
||||
val = cmp(cs_math_val<T>::get(args[i - 1]), cs_math_val<T>::get(args[i]));
|
||||
val = cmp(math_val<T>::get(args[i - 1]), math_val<T>::get(args[i]));
|
||||
}
|
||||
} else {
|
||||
val = cmp(!args.empty() ? cs_math_val<T>::get(args[0]) : T(0), T(0));
|
||||
val = cmp(!args.empty() ? math_val<T>::get(args[0]) : T(0), T(0));
|
||||
}
|
||||
res.set_int(cs_int(val));
|
||||
res.set_int(integer_type(val));
|
||||
}
|
||||
|
||||
void cs_init_lib_math(cs_state &cs) {
|
||||
void init_lib_math(state &cs) {
|
||||
cs.new_command("sin", "f", [](auto &, auto args, auto &res) {
|
||||
res.set_float(std::sin(args[0].get_float() * RAD));
|
||||
});
|
||||
|
@ -114,28 +114,28 @@ void cs_init_lib_math(cs_state &cs) {
|
|||
});
|
||||
|
||||
cs.new_command("min", "i1V", [](auto &, auto args, auto &res) {
|
||||
cs_int v = (!args.empty() ? args[0].get_int() : 0);
|
||||
integer_type v = (!args.empty() ? args[0].get_int() : 0);
|
||||
for (size_t i = 1; i < args.size(); ++i) {
|
||||
v = std::min(v, args[i].get_int());
|
||||
}
|
||||
res.set_int(v);
|
||||
});
|
||||
cs.new_command("max", "i1V", [](auto &, auto args, auto &res) {
|
||||
cs_int v = (!args.empty() ? args[0].get_int() : 0);
|
||||
integer_type v = (!args.empty() ? args[0].get_int() : 0);
|
||||
for (size_t i = 1; i < args.size(); ++i) {
|
||||
v = std::max(v, args[i].get_int());
|
||||
}
|
||||
res.set_int(v);
|
||||
});
|
||||
cs.new_command("minf", "f1V", [](auto &, auto args, auto &res) {
|
||||
cs_float v = (!args.empty() ? args[0].get_float() : 0);
|
||||
float_type v = (!args.empty() ? args[0].get_float() : 0);
|
||||
for (size_t i = 1; i < args.size(); ++i) {
|
||||
v = std::min(v, args[i].get_float());
|
||||
}
|
||||
res.set_float(v);
|
||||
});
|
||||
cs.new_command("maxf", "f1V", [](auto &, auto args, auto &res) {
|
||||
cs_float v = (!args.empty() ? args[0].get_float() : 0);
|
||||
float_type v = (!args.empty() ? args[0].get_float() : 0);
|
||||
for (size_t i = 1; i < args.size(); ++i) {
|
||||
v = std::max(v, args[i].get_float());
|
||||
}
|
||||
|
@ -157,8 +157,8 @@ void cs_init_lib_math(cs_state &cs) {
|
|||
});
|
||||
|
||||
cs.new_command("round", "ff", [](auto &, auto args, auto &res) {
|
||||
cs_float step = args[1].get_float();
|
||||
cs_float r = args[0].get_float();
|
||||
float_type step = args[1].get_float();
|
||||
float_type r = args[0].get_float();
|
||||
if (step > 0) {
|
||||
r += step * ((r < 0) ? -0.5 : 0.5);
|
||||
r -= std::fmod(r, step);
|
||||
|
@ -169,43 +169,43 @@ void cs_init_lib_math(cs_state &cs) {
|
|||
});
|
||||
|
||||
cs.new_command("+", "i1V", [](auto &, auto args, auto &res) {
|
||||
cs_mathop<cs_int>(args, res, 0, std::plus<cs_int>(), cs_math_noop<cs_int>());
|
||||
math_op<integer_type>(args, res, 0, std::plus<integer_type>(), math_noop<integer_type>());
|
||||
});
|
||||
cs.new_command("*", "i1V", [](auto &, auto args, auto &res) {
|
||||
cs_mathop<cs_int>(
|
||||
args, res, 1, std::multiplies<cs_int>(), cs_math_noop<cs_int>()
|
||||
math_op<integer_type>(
|
||||
args, res, 1, std::multiplies<integer_type>(), math_noop<integer_type>()
|
||||
);
|
||||
});
|
||||
cs.new_command("-", "i1V", [](auto &, auto args, auto &res) {
|
||||
cs_mathop<cs_int>(
|
||||
args, res, 0, std::minus<cs_int>(), std::negate<cs_int>()
|
||||
math_op<integer_type>(
|
||||
args, res, 0, std::minus<integer_type>(), std::negate<integer_type>()
|
||||
);
|
||||
});
|
||||
|
||||
cs.new_command("^", "i1V", [](auto &, auto args, auto &res) {
|
||||
cs_mathop<cs_int>(
|
||||
args, res, 0, std::bit_xor<cs_int>(), [](cs_int val) { return ~val; }
|
||||
math_op<integer_type>(
|
||||
args, res, 0, std::bit_xor<integer_type>(), [](integer_type val) { return ~val; }
|
||||
);
|
||||
});
|
||||
cs.new_command("~", "i1V", [](auto &, auto args, auto &res) {
|
||||
cs_mathop<cs_int>(
|
||||
args, res, 0, std::bit_xor<cs_int>(), [](cs_int val) { return ~val; }
|
||||
math_op<integer_type>(
|
||||
args, res, 0, std::bit_xor<integer_type>(), [](integer_type val) { return ~val; }
|
||||
);
|
||||
});
|
||||
cs.new_command("&", "i1V", [](auto &, auto args, auto &res) {
|
||||
cs_mathop<cs_int>(
|
||||
args, res, 0, std::bit_and<cs_int>(), cs_math_noop<cs_int>()
|
||||
math_op<integer_type>(
|
||||
args, res, 0, std::bit_and<integer_type>(), math_noop<integer_type>()
|
||||
);
|
||||
});
|
||||
cs.new_command("|", "i1V", [](auto &, auto args, auto &res) {
|
||||
cs_mathop<cs_int>(
|
||||
args, res, 0, std::bit_or<cs_int>(), cs_math_noop<cs_int>()
|
||||
math_op<integer_type>(
|
||||
args, res, 0, std::bit_or<integer_type>(), math_noop<integer_type>()
|
||||
);
|
||||
});
|
||||
|
||||
/* special combined cases */
|
||||
cs.new_command("^~", "i1V", [](auto &, auto args, auto &res) {
|
||||
cs_int val;
|
||||
integer_type val;
|
||||
if (args.size() >= 2) {
|
||||
val = args[0].get_int() ^ ~args[1].get_int();
|
||||
for (size_t i = 2; i < args.size(); ++i) {
|
||||
|
@ -217,7 +217,7 @@ void cs_init_lib_math(cs_state &cs) {
|
|||
res.set_int(val);
|
||||
});
|
||||
cs.new_command("&~", "i1V", [](auto &, auto args, auto &res) {
|
||||
cs_int val;
|
||||
integer_type val;
|
||||
if (args.size() >= 2) {
|
||||
val = args[0].get_int() & ~args[1].get_int();
|
||||
for (size_t i = 2; i < args.size(); ++i) {
|
||||
|
@ -229,7 +229,7 @@ void cs_init_lib_math(cs_state &cs) {
|
|||
res.set_int(val);
|
||||
});
|
||||
cs.new_command("|~", "i1V", [](auto &, auto args, auto &res) {
|
||||
cs_int val;
|
||||
integer_type val;
|
||||
if (args.size() >= 2) {
|
||||
val = args[0].get_int() | ~args[1].get_int();
|
||||
for (size_t i = 2; i < args.size(); ++i) {
|
||||
|
@ -242,125 +242,125 @@ void cs_init_lib_math(cs_state &cs) {
|
|||
});
|
||||
|
||||
cs.new_command("<<", "i1V", [](auto &, auto args, auto &res) {
|
||||
cs_mathop<cs_int>(
|
||||
args, res, 0, [](cs_int val1, cs_int val2) {
|
||||
return (val2 < cs_int(sizeof(cs_int) * CHAR_BIT))
|
||||
? (val1 << std::max(val2, cs_int(0)))
|
||||
math_op<integer_type>(
|
||||
args, res, 0, [](integer_type val1, integer_type val2) {
|
||||
return (val2 < integer_type(sizeof(integer_type) * CHAR_BIT))
|
||||
? (val1 << std::max(val2, integer_type(0)))
|
||||
: 0;
|
||||
}, cs_math_noop<cs_int>()
|
||||
}, math_noop<integer_type>()
|
||||
);
|
||||
});
|
||||
cs.new_command(">>", "i1V", [](auto &, auto args, auto &res) {
|
||||
cs_mathop<cs_int>(
|
||||
args, res, 0, [](cs_int val1, cs_int val2) {
|
||||
math_op<integer_type>(
|
||||
args, res, 0, [](integer_type val1, integer_type val2) {
|
||||
return val1 >> std::clamp(
|
||||
val2, cs_int(0), cs_int(sizeof(cs_int) * CHAR_BIT)
|
||||
val2, integer_type(0), integer_type(sizeof(integer_type) * CHAR_BIT)
|
||||
);
|
||||
}, cs_math_noop<cs_int>()
|
||||
}, math_noop<integer_type>()
|
||||
);
|
||||
});
|
||||
|
||||
cs.new_command("+f", "f1V", [](auto &, auto args, auto &res) {
|
||||
cs_mathop<cs_float>(
|
||||
args, res, 0, std::plus<cs_float>(), cs_math_noop<cs_float>()
|
||||
math_op<float_type>(
|
||||
args, res, 0, std::plus<float_type>(), math_noop<float_type>()
|
||||
);
|
||||
});
|
||||
cs.new_command("*f", "f1V", [](auto &, auto args, auto &res) {
|
||||
cs_mathop<cs_float>(
|
||||
args, res, 1, std::multiplies<cs_float>(), cs_math_noop<cs_float>()
|
||||
math_op<float_type>(
|
||||
args, res, 1, std::multiplies<float_type>(), math_noop<float_type>()
|
||||
);
|
||||
});
|
||||
cs.new_command("-f", "f1V", [](auto &, auto args, auto &res) {
|
||||
cs_mathop<cs_float>(
|
||||
args, res, 0, std::minus<cs_float>(), std::negate<cs_float>()
|
||||
math_op<float_type>(
|
||||
args, res, 0, std::minus<float_type>(), std::negate<float_type>()
|
||||
);
|
||||
});
|
||||
|
||||
cs.new_command("div", "i1V", [](auto &, auto args, auto &res) {
|
||||
cs_mathop<cs_int>(
|
||||
args, res, 0, [](cs_int val1, cs_int val2) {
|
||||
math_op<integer_type>(
|
||||
args, res, 0, [](integer_type val1, integer_type val2) {
|
||||
if (val2) {
|
||||
return val1 / val2;
|
||||
}
|
||||
return cs_int(0);
|
||||
}, cs_math_noop<cs_int>()
|
||||
return integer_type(0);
|
||||
}, math_noop<integer_type>()
|
||||
);
|
||||
});
|
||||
cs.new_command("mod", "i1V", [](auto &, auto args, auto &res) {
|
||||
cs_mathop<cs_int>(
|
||||
args, res, 0, [](cs_int val1, cs_int val2) {
|
||||
math_op<integer_type>(
|
||||
args, res, 0, [](integer_type val1, integer_type val2) {
|
||||
if (val2) {
|
||||
return val1 % val2;
|
||||
}
|
||||
return cs_int(0);
|
||||
}, cs_math_noop<cs_int>()
|
||||
return integer_type(0);
|
||||
}, math_noop<integer_type>()
|
||||
);
|
||||
});
|
||||
cs.new_command("divf", "f1V", [](auto &, auto args, auto &res) {
|
||||
cs_mathop<cs_float>(
|
||||
args, res, 0, [](cs_float val1, cs_float val2) {
|
||||
math_op<float_type>(
|
||||
args, res, 0, [](float_type val1, float_type val2) {
|
||||
if (val2) {
|
||||
return val1 / val2;
|
||||
}
|
||||
return cs_float(0);
|
||||
}, cs_math_noop<cs_float>()
|
||||
return float_type(0);
|
||||
}, math_noop<float_type>()
|
||||
);
|
||||
});
|
||||
cs.new_command("modf", "f1V", [](auto &, auto args, auto &res) {
|
||||
cs_mathop<cs_float>(
|
||||
args, res, 0, [](cs_float val1, cs_float val2) {
|
||||
math_op<float_type>(
|
||||
args, res, 0, [](float_type val1, float_type val2) {
|
||||
if (val2) {
|
||||
return cs_float(fmod(val1, val2));
|
||||
return float_type(fmod(val1, val2));
|
||||
}
|
||||
return cs_float(0);
|
||||
}, cs_math_noop<cs_float>()
|
||||
return float_type(0);
|
||||
}, math_noop<float_type>()
|
||||
);
|
||||
});
|
||||
|
||||
cs.new_command("pow", "f1V", [](auto &, auto args, auto &res) {
|
||||
cs_mathop<cs_float>(
|
||||
args, res, 0, [](cs_float val1, cs_float val2) {
|
||||
return cs_float(pow(val1, val2));
|
||||
}, cs_math_noop<cs_float>()
|
||||
math_op<float_type>(
|
||||
args, res, 0, [](float_type val1, float_type val2) {
|
||||
return float_type(pow(val1, val2));
|
||||
}, math_noop<float_type>()
|
||||
);
|
||||
});
|
||||
|
||||
cs.new_command("=", "i1V", [](auto &, auto args, auto &res) {
|
||||
cs_cmpop<cs_int>(args, res, std::equal_to<cs_int>());
|
||||
cmp_op<integer_type>(args, res, std::equal_to<integer_type>());
|
||||
});
|
||||
cs.new_command("!=", "i1V", [](auto &, auto args, auto &res) {
|
||||
cs_cmpop<cs_int>(args, res, std::not_equal_to<cs_int>());
|
||||
cmp_op<integer_type>(args, res, std::not_equal_to<integer_type>());
|
||||
});
|
||||
cs.new_command("<", "i1V", [](auto &, auto args, auto &res) {
|
||||
cs_cmpop<cs_int>(args, res, std::less<cs_int>());
|
||||
cmp_op<integer_type>(args, res, std::less<integer_type>());
|
||||
});
|
||||
cs.new_command(">", "i1V", [](auto &, auto args, auto &res) {
|
||||
cs_cmpop<cs_int>(args, res, std::greater<cs_int>());
|
||||
cmp_op<integer_type>(args, res, std::greater<integer_type>());
|
||||
});
|
||||
cs.new_command("<=", "i1V", [](auto &, auto args, auto &res) {
|
||||
cs_cmpop<cs_int>(args, res, std::less_equal<cs_int>());
|
||||
cmp_op<integer_type>(args, res, std::less_equal<integer_type>());
|
||||
});
|
||||
cs.new_command(">=", "i1V", [](auto &, auto args, auto &res) {
|
||||
cs_cmpop<cs_int>(args, res, std::greater_equal<cs_int>());
|
||||
cmp_op<integer_type>(args, res, std::greater_equal<integer_type>());
|
||||
});
|
||||
|
||||
cs.new_command("=f", "f1V", [](auto &, auto args, auto &res) {
|
||||
cs_cmpop<cs_float>(args, res, std::equal_to<cs_float>());
|
||||
cmp_op<float_type>(args, res, std::equal_to<float_type>());
|
||||
});
|
||||
cs.new_command("!=f", "f1V", [](auto &, auto args, auto &res) {
|
||||
cs_cmpop<cs_float>(args, res, std::not_equal_to<cs_float>());
|
||||
cmp_op<float_type>(args, res, std::not_equal_to<float_type>());
|
||||
});
|
||||
cs.new_command("<f", "f1V", [](auto &, auto args, auto &res) {
|
||||
cs_cmpop<cs_float>(args, res, std::less<cs_float>());
|
||||
cmp_op<float_type>(args, res, std::less<float_type>());
|
||||
});
|
||||
cs.new_command(">f", "f1V", [](auto &, auto args, auto &res) {
|
||||
cs_cmpop<cs_float>(args, res, std::greater<cs_float>());
|
||||
cmp_op<float_type>(args, res, std::greater<float_type>());
|
||||
});
|
||||
cs.new_command("<=f", "f1V", [](auto &, auto args, auto &res) {
|
||||
cs_cmpop<cs_float>(args, res, std::less_equal<cs_float>());
|
||||
cmp_op<float_type>(args, res, std::less_equal<float_type>());
|
||||
});
|
||||
cs.new_command(">=f", "f1V", [](auto &, auto args, auto &res) {
|
||||
cs_cmpop<cs_float>(args, res, std::greater_equal<cs_float>());
|
||||
cmp_op<float_type>(args, res, std::greater_equal<float_type>());
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
namespace cscript {
|
||||
|
||||
template<typename F>
|
||||
static inline void cs_strgcmp(
|
||||
std::span<cs_value> args, cs_value &res, F cfunc
|
||||
static inline void str_cmp_by(
|
||||
std::span<any_value> args, any_value &res, F cfunc
|
||||
) {
|
||||
bool val;
|
||||
if (args.size() >= 2) {
|
||||
|
@ -24,28 +24,28 @@ static inline void cs_strgcmp(
|
|||
std::string_view()
|
||||
);
|
||||
}
|
||||
res.set_int(cs_int(val));
|
||||
res.set_int(integer_type(val));
|
||||
};
|
||||
|
||||
void cs_init_lib_string(cs_state &cs) {
|
||||
void init_lib_string(state &cs) {
|
||||
cs.new_command("strstr", "ss", [](auto &, auto args, auto &res) {
|
||||
std::string_view a = args[0].get_str(), b = args[1].get_str();
|
||||
auto pos = a.find(b);
|
||||
if (pos == a.npos) {
|
||||
res.set_int(-1);
|
||||
} else {
|
||||
res.set_int(cs_int(pos));
|
||||
res.set_int(integer_type(pos));
|
||||
}
|
||||
});
|
||||
|
||||
cs.new_command("strlen", "s", [](auto &, auto args, auto &res) {
|
||||
res.set_int(cs_int(args[0].get_str().size()));
|
||||
res.set_int(integer_type(args[0].get_str().size()));
|
||||
});
|
||||
|
||||
cs.new_command("strcode", "si", [](auto &, auto args, auto &res) {
|
||||
std::string_view str = args[0].get_str();
|
||||
cs_int i = args[1].get_int();
|
||||
if (i >= cs_int(str.size())) {
|
||||
integer_type i = args[1].get_int();
|
||||
if (i >= integer_type(str.size())) {
|
||||
res.set_int(0);
|
||||
} else {
|
||||
res.set_int(static_cast<unsigned char>(str[i]));
|
||||
|
@ -59,7 +59,7 @@ void cs_init_lib_string(cs_state &cs) {
|
|||
|
||||
cs.new_command("strlower", "s", [](auto &ccs, auto args, auto &res) {
|
||||
auto inps = std::string_view{args[0].get_str()};
|
||||
auto *ics = cs_get_sstate(ccs);
|
||||
auto *ics = state_get_internal(ccs);
|
||||
auto *buf = ics->strman->alloc_buf(inps.size());
|
||||
for (std::size_t i = 0; i < inps.size(); ++i) {
|
||||
buf[i] = tolower(inps[i]);
|
||||
|
@ -69,7 +69,7 @@ void cs_init_lib_string(cs_state &cs) {
|
|||
|
||||
cs.new_command("strupper", "s", [](auto &ccs, auto args, auto &res) {
|
||||
auto inps = std::string_view{args[0].get_str()};
|
||||
auto *ics = cs_get_sstate(ccs);
|
||||
auto *ics = state_get_internal(ccs);
|
||||
auto *buf = ics->strman->alloc_buf(inps.size());
|
||||
for (std::size_t i = 0; i < inps.size(); ++i) {
|
||||
buf[i] = toupper(inps[i]);
|
||||
|
@ -78,31 +78,31 @@ void cs_init_lib_string(cs_state &cs) {
|
|||
});
|
||||
|
||||
cs.new_command("escape", "s", [](auto &ccs, auto args, auto &res) {
|
||||
cs_charbuf s{ccs};
|
||||
cs_escape_string(std::back_inserter(s), args[0].get_str());
|
||||
charbuf s{ccs};
|
||||
escape_string(std::back_inserter(s), args[0].get_str());
|
||||
res.set_str(s.str());
|
||||
});
|
||||
|
||||
cs.new_command("unescape", "s", [](auto &ccs, auto args, auto &res) {
|
||||
cs_charbuf s{ccs};
|
||||
cs_unescape_string(std::back_inserter(s), args[0].get_str());
|
||||
charbuf s{ccs};
|
||||
unescape_string(std::back_inserter(s), args[0].get_str());
|
||||
res.set_str(s.str());
|
||||
});
|
||||
|
||||
cs.new_command("concat", "V", [](auto &ccs, auto args, auto &res) {
|
||||
res.set_str(cs_concat_values(ccs, args, " "));
|
||||
res.set_str(concat_values(ccs, args, " "));
|
||||
});
|
||||
|
||||
cs.new_command("concatword", "V", [](auto &ccs, auto args, auto &res) {
|
||||
res.set_str(cs_concat_values(ccs, args));
|
||||
res.set_str(concat_values(ccs, args));
|
||||
});
|
||||
|
||||
cs.new_command("format", "V", [](auto &ccs, auto args, auto &res) {
|
||||
if (args.empty()) {
|
||||
return;
|
||||
}
|
||||
cs_charbuf s{ccs};
|
||||
cs_strref fs = args[0].get_str();
|
||||
charbuf s{ccs};
|
||||
string_ref fs = args[0].get_str();
|
||||
std::string_view f{fs};
|
||||
for (auto it = f.begin(); it != f.end(); ++it) {
|
||||
char c = *it;
|
||||
|
@ -132,7 +132,7 @@ void cs_init_lib_string(cs_state &cs) {
|
|||
int prec = std::max(int(args[1].get_int()), 1);
|
||||
int n = snprintf(buf, sizeof(buf), "0x%.*llX", prec, val);
|
||||
if (n >= int(sizeof(buf))) {
|
||||
cs_charbuf s{ccs};
|
||||
charbuf s{ccs};
|
||||
s.reserve(n + 1);
|
||||
s.data()[0] = '\0';
|
||||
int nn = snprintf(s.data(), n + 1, "0x%.*llX", prec, val);
|
||||
|
@ -145,42 +145,42 @@ void cs_init_lib_string(cs_state &cs) {
|
|||
return;
|
||||
}
|
||||
/* should pretty much be unreachable */
|
||||
throw cs_internal_error{"format error"};
|
||||
throw internal_error{"format error"};
|
||||
});
|
||||
|
||||
cs.new_command("substr", "siiN", [](auto &, auto args, auto &res) {
|
||||
std::string_view s = args[0].get_str();
|
||||
cs_int start = args[1].get_int(), count = args[2].get_int();
|
||||
cs_int numargs = args[3].get_int();
|
||||
cs_int len = cs_int(s.size()), offset = std::clamp(start, cs_int(0), len);
|
||||
integer_type start = args[1].get_int(), count = args[2].get_int();
|
||||
integer_type numargs = args[3].get_int();
|
||||
integer_type len = integer_type(s.size()), offset = std::clamp(start, integer_type(0), len);
|
||||
res.set_str(std::string_view{
|
||||
&s[offset],
|
||||
((numargs >= 3)
|
||||
? size_t(std::clamp(count, cs_int(0), len - offset))
|
||||
? size_t(std::clamp(count, integer_type(0), len - offset))
|
||||
: size_t(len - offset))
|
||||
});
|
||||
});
|
||||
|
||||
cs.new_command("strcmp", "s1V", [](auto &, auto args, auto &res) {
|
||||
cs_strgcmp(args, res, std::equal_to<std::string_view>());
|
||||
str_cmp_by(args, res, std::equal_to<std::string_view>());
|
||||
});
|
||||
cs.new_command("=s", "s1V", [](auto &, auto args, auto &res) {
|
||||
cs_strgcmp(args, res, std::equal_to<std::string_view>());
|
||||
str_cmp_by(args, res, std::equal_to<std::string_view>());
|
||||
});
|
||||
cs.new_command("!=s", "s1V", [](auto &, auto args, auto &res) {
|
||||
cs_strgcmp(args, res, std::not_equal_to<std::string_view>());
|
||||
str_cmp_by(args, res, std::not_equal_to<std::string_view>());
|
||||
});
|
||||
cs.new_command("<s", "s1V", [](auto &, auto args, auto &res) {
|
||||
cs_strgcmp(args, res, std::less<std::string_view>());
|
||||
str_cmp_by(args, res, std::less<std::string_view>());
|
||||
});
|
||||
cs.new_command(">s", "s1V", [](auto &, auto args, auto &res) {
|
||||
cs_strgcmp(args, res, std::greater<std::string_view>());
|
||||
str_cmp_by(args, res, std::greater<std::string_view>());
|
||||
});
|
||||
cs.new_command("<=s", "s1V", [](auto &, auto args, auto &res) {
|
||||
cs_strgcmp(args, res, std::less_equal<std::string_view>());
|
||||
str_cmp_by(args, res, std::less_equal<std::string_view>());
|
||||
});
|
||||
cs.new_command(">=s", "s1V", [](auto &, auto args, auto &res) {
|
||||
cs_strgcmp(args, res, std::greater_equal<std::string_view>());
|
||||
str_cmp_by(args, res, std::greater_equal<std::string_view>());
|
||||
});
|
||||
|
||||
cs.new_command("strreplace", "ssss", [](auto &ccs, auto args, auto &res) {
|
||||
|
@ -195,7 +195,7 @@ void cs_init_lib_string(cs_state &cs) {
|
|||
res.set_str(s);
|
||||
return;
|
||||
}
|
||||
cs_charbuf buf{ccs};
|
||||
charbuf buf{ccs};
|
||||
for (size_t i = 0;; ++i) {
|
||||
std::string_view found;
|
||||
auto p = s.find(oldval);
|
||||
|
@ -216,17 +216,17 @@ void cs_init_lib_string(cs_state &cs) {
|
|||
cs.new_command("strsplice", "ssii", [](auto &ccs, auto args, auto &res) {
|
||||
std::string_view s = args[0].get_str();
|
||||
std::string_view vals = args[1].get_str();
|
||||
cs_int skip = args[2].get_int(),
|
||||
integer_type skip = args[2].get_int(),
|
||||
count = args[3].get_int();
|
||||
cs_int offset = std::clamp(skip, cs_int(0), cs_int(s.size())),
|
||||
len = std::clamp(count, cs_int(0), cs_int(s.size()) - offset);
|
||||
cs_charbuf p{ccs};
|
||||
integer_type offset = std::clamp(skip, integer_type(0), integer_type(s.size())),
|
||||
len = std::clamp(count, integer_type(0), integer_type(s.size()) - offset);
|
||||
charbuf p{ccs};
|
||||
p.reserve(s.size() - len + vals.size());
|
||||
if (offset) {
|
||||
p.append(s.substr(0, offset));
|
||||
}
|
||||
p.append(vals);
|
||||
if ((offset + len) < cs_int(s.size())) {
|
||||
if ((offset + len) < integer_type(s.size())) {
|
||||
p.append(s.substr(offset + len, s.size() - offset - len));
|
||||
}
|
||||
res.set_str(p.str());
|
||||
|
|
|
@ -4,10 +4,10 @@
|
|||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
inline void init_lineedit(cs_state &, std::string_view) {
|
||||
inline void init_lineedit(cs::state &, std::string_view) {
|
||||
}
|
||||
|
||||
inline std::optional<std::string> read_line(cs_state &, cs_svar *pr) {
|
||||
inline std::optional<std::string> read_line(cs::state &, cs::string_var *pr) {
|
||||
std::string lbuf;
|
||||
char buf[512];
|
||||
printf("%s", pr->get_value().data());
|
||||
|
@ -21,7 +21,7 @@ inline std::optional<std::string> read_line(cs_state &, cs_svar *pr) {
|
|||
return std::move(lbuf);
|
||||
}
|
||||
|
||||
inline void add_history(cs_state &, std::string_view) {
|
||||
inline void add_history(cs::state &, std::string_view) {
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
#include "linenoise.hh"
|
||||
|
||||
static cs_state *ln_cs = nullptr;
|
||||
static cs::state *ln_cs = nullptr;
|
||||
|
||||
inline void ln_complete(char const *buf, linenoiseCompletions *lc) {
|
||||
std::string_view cmd = get_complete_cmd(buf);
|
||||
|
@ -31,7 +31,7 @@ inline void ln_complete(char const *buf, linenoiseCompletions *lc) {
|
|||
}
|
||||
|
||||
inline char *ln_hint(char const *buf, int *color, int *bold) {
|
||||
cs_command *cmd = get_hint_cmd(*ln_cs, buf);
|
||||
cs::command *cmd = get_hint_cmd(*ln_cs, buf);
|
||||
if (!cmd) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ inline void ln_hint_free(void *hint) {
|
|||
delete[] static_cast<char *>(hint);
|
||||
}
|
||||
|
||||
inline void init_lineedit(cs_state &cs, std::string_view) {
|
||||
inline void init_lineedit(cs::state &cs, std::string_view) {
|
||||
/* sensible default history size */
|
||||
linenoiseHistorySetMaxLen(1000);
|
||||
ln_cs = &cs;
|
||||
|
@ -58,7 +58,7 @@ inline void init_lineedit(cs_state &cs, std::string_view) {
|
|||
linenoiseSetFreeHintsCallback(ln_hint_free);
|
||||
}
|
||||
|
||||
inline std::optional<std::string> read_line(cs_state &, cs_svar *pr) {
|
||||
inline std::optional<std::string> read_line(cs::state &, cs::string_var *pr) {
|
||||
auto line = linenoise(pr->get_value().data());
|
||||
if (!line) {
|
||||
/* linenoise traps ctrl-c, detect it and let the user exit */
|
||||
|
@ -73,7 +73,7 @@ inline std::optional<std::string> read_line(cs_state &, cs_svar *pr) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
inline void add_history(cs_state &, std::string_view line) {
|
||||
inline void add_history(cs::state &, std::string_view line) {
|
||||
/* backed by std::string so it's terminated */
|
||||
linenoiseHistoryAdd(line.data());
|
||||
}
|
||||
|
|
|
@ -9,18 +9,18 @@
|
|||
#include <readline/readline.h>
|
||||
#include <readline/history.h>
|
||||
|
||||
static cs_state *rd_cs = nullptr;
|
||||
static cs::state *rd_cs = nullptr;
|
||||
|
||||
inline char *ln_complete_list(char const *buf, int state) {
|
||||
static std::string_view cmd;
|
||||
static std::span<cs_ident *> itr;
|
||||
static std::span<cs::ident *> itr;
|
||||
|
||||
if (!state) {
|
||||
cmd = get_complete_cmd(buf);
|
||||
itr = rd_cs->get_idents();
|
||||
}
|
||||
|
||||
for (cs_ident *id: itr) {
|
||||
for (cs::ident *id: itr) {
|
||||
if (!id->is_command()) {
|
||||
continue;
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ inline char **ln_complete(char const *buf, int, int) {
|
|||
}
|
||||
|
||||
inline void ln_hint() {
|
||||
cs_command *cmd = get_hint_cmd(*rd_cs, rl_line_buffer);
|
||||
cs::command *cmd = get_hint_cmd(*rd_cs, rl_line_buffer);
|
||||
if (!cmd) {
|
||||
rl_redisplay();
|
||||
return;
|
||||
|
@ -59,13 +59,13 @@ inline void ln_hint() {
|
|||
rl_replace_line(old.data(), 0);
|
||||
}
|
||||
|
||||
inline void init_lineedit(cs_state &cs, std::string_view) {
|
||||
inline void init_lineedit(cs::state &cs, std::string_view) {
|
||||
rd_cs = &cs;
|
||||
rl_attempted_completion_function = ln_complete;
|
||||
rl_redisplay_function = ln_hint;
|
||||
}
|
||||
|
||||
inline std::optional<std::string> read_line(cs_state &, cs_svar *pr) {
|
||||
inline std::optional<std::string> read_line(cs::state &, cs::string_var *pr) {
|
||||
auto line = readline(pr->get_value().data());
|
||||
if (!line) {
|
||||
return std::string();
|
||||
|
@ -75,7 +75,7 @@ inline std::optional<std::string> read_line(cs_state &, cs_svar *pr) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
inline void add_history(cs_state &, std::string_view line) {
|
||||
inline void add_history(cs::state &, std::string_view line) {
|
||||
/* backed by std::string so it's terminated */
|
||||
add_history(line.data());
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
#include <cubescript/cubescript.hh>
|
||||
|
||||
using namespace cscript;
|
||||
namespace cs = cscript;
|
||||
|
||||
std::string_view version = "CubeScript 0.0.1";
|
||||
|
||||
|
@ -124,11 +124,11 @@ inline void fill_cmd_args(std::string &writer, std::string_view args) {
|
|||
}
|
||||
}
|
||||
|
||||
inline cs_command *get_hint_cmd(cs_state &cs, std::string_view buf) {
|
||||
inline cs::command *get_hint_cmd(cs::state &cs, std::string_view buf) {
|
||||
std::string_view nextchars = "([;";
|
||||
auto lp = buf.find_first_of(nextchars);
|
||||
if (lp != buf.npos) {
|
||||
cs_command *cmd = get_hint_cmd(cs, buf.substr(1, buf.size() - 1));
|
||||
cs::command *cmd = get_hint_cmd(cs, buf.substr(1, buf.size() - 1));
|
||||
if (cmd) {
|
||||
return cmd;
|
||||
}
|
||||
|
@ -179,23 +179,23 @@ void print_version() {
|
|||
printf("%s\n", version.data());
|
||||
}
|
||||
|
||||
static cs_state *scs = nullptr;
|
||||
static cs::state *scs = nullptr;
|
||||
static void do_sigint(int n) {
|
||||
/* in case another SIGINT happens, terminate normally */
|
||||
signal(n, SIG_DFL);
|
||||
scs->set_call_hook([](cs_state &cs) {
|
||||
scs->set_call_hook([](cs::state &cs) {
|
||||
cs.set_call_hook(nullptr);
|
||||
throw cscript::cs_error(cs, "<execution interrupted>");
|
||||
throw cs::error{cs, "<execution interrupted>"};
|
||||
});
|
||||
}
|
||||
|
||||
/* an example of what var printer would look like in real usage */
|
||||
static void repl_print_var(cs_state const &cs, cs_var const &var) {
|
||||
static void repl_print_var(cs::state const &cs, cs::global_var const &var) {
|
||||
switch (var.get_type()) {
|
||||
case cs_ident_type::IVAR: {
|
||||
auto &iv = static_cast<cs_ivar const &>(var);
|
||||
case cs::ident_type::IVAR: {
|
||||
auto &iv = static_cast<cs::integer_var const &>(var);
|
||||
auto val = iv.get_value();
|
||||
if (!(iv.get_flags() & CS_IDF_HEX) || (val < 0)) {
|
||||
if (!(iv.get_flags() & cs::IDENT_FLAG_HEX) || (val < 0)) {
|
||||
std::printf("%s = %d\n", iv.get_name().data(), val);
|
||||
} else if (iv.get_val_max() == 0xFFFFFF) {
|
||||
std::printf(
|
||||
|
@ -208,8 +208,8 @@ static void repl_print_var(cs_state const &cs, cs_var const &var) {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case cs_ident_type::FVAR: {
|
||||
auto &fv = static_cast<cs_fvar const &>(var);
|
||||
case cs::ident_type::FVAR: {
|
||||
auto &fv = static_cast<cs::float_var const &>(var);
|
||||
auto val = fv.get_value();
|
||||
if (std::floor(val) == val) {
|
||||
std::printf("%s = %.1f", fv.get_name().data(), val);
|
||||
|
@ -218,8 +218,8 @@ static void repl_print_var(cs_state const &cs, cs_var const &var) {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case cs_ident_type::SVAR: {
|
||||
auto &sv = static_cast<cs_svar const &>(var);
|
||||
case cs::ident_type::SVAR: {
|
||||
auto &sv = static_cast<cs::string_var const &>(var);
|
||||
auto val = std::string_view{sv.get_value()};
|
||||
if (val.find('"') == val.npos) {
|
||||
std::printf("%s = \"%s\"", sv.get_name().data(), val.data());
|
||||
|
@ -233,7 +233,9 @@ static void repl_print_var(cs_state const &cs, cs_var const &var) {
|
|||
}
|
||||
}
|
||||
|
||||
static bool do_run_file(cs_state &cs, std::string_view fname, cs_value &ret) {
|
||||
static bool do_run_file(
|
||||
cs::state &cs, std::string_view fname, cs::any_value &ret
|
||||
) {
|
||||
FILE *f = std::fopen(fname.data(), "rb");
|
||||
if (!f) {
|
||||
return false;
|
||||
|
@ -260,8 +262,8 @@ static bool do_run_file(cs_state &cs, std::string_view fname, cs_value &ret) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool do_call(cs_state &cs, std::string_view line, bool file = false) {
|
||||
cs_value ret{cs};
|
||||
static bool do_call(cs::state &cs, std::string_view line, bool file = false) {
|
||||
cs::any_value ret{cs};
|
||||
scs = &cs;
|
||||
signal(SIGINT, do_sigint);
|
||||
try {
|
||||
|
@ -272,7 +274,7 @@ static bool do_call(cs_state &cs, std::string_view line, bool file = false) {
|
|||
} else {
|
||||
cs.run(line, ret);
|
||||
}
|
||||
} catch (cscript::cs_error const &e) {
|
||||
} catch (cs::error const &e) {
|
||||
signal(SIGINT, SIG_DFL);
|
||||
scs = nullptr;
|
||||
std::string_view terr = e.what();
|
||||
|
@ -295,20 +297,20 @@ static bool do_call(cs_state &cs, std::string_view line, bool file = false) {
|
|||
);
|
||||
if (e.get_stack().get()) {
|
||||
std::string str;
|
||||
cscript::cs_print_stack(std::back_inserter(str), e.get_stack());
|
||||
cs::print_stack(std::back_inserter(str), e.get_stack());
|
||||
std::printf("%s\n", str.data());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
signal(SIGINT, SIG_DFL);
|
||||
scs = nullptr;
|
||||
if (ret.get_type() != cs_value_type::NONE) {
|
||||
if (ret.get_type() != cs::value_type::NONE) {
|
||||
std::printf("%s\n", std::string_view{ret.get_str()}.data());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void do_tty(cs_state &cs) {
|
||||
static void do_tty(cs::state &cs) {
|
||||
auto prompt = cs.new_svar("PROMPT", "> ");
|
||||
auto prompt2 = cs.new_svar("PROMPT2", ">> ");
|
||||
|
||||
|
@ -349,16 +351,16 @@ static void do_tty(cs_state &cs) {
|
|||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
cs_state gcs;
|
||||
cs::state gcs;
|
||||
gcs.set_var_printer(repl_print_var);
|
||||
gcs.init_libs();
|
||||
|
||||
gcs.new_command("exec", "s", [](auto &cs, auto args, auto &) {
|
||||
auto file = args[0].get_str();
|
||||
cs_value val{cs};
|
||||
cs::any_value val{cs};
|
||||
bool ret = do_run_file(cs, file, val);
|
||||
if (!ret) {
|
||||
throw cscript::cs_error(
|
||||
throw cs::error(
|
||||
cs, "could not run file \"%s\"", file
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue