remove cs_ namespace in all API

master
Daniel Kolesa 2021-03-23 23:29:32 +01:00
parent b3b4624af1
commit b9b344cba6
26 changed files with 2242 additions and 2238 deletions

File diff suppressed because it is too large Load Diff

View File

@ -2,12 +2,12 @@
#define LIBCUBESCRIPT_CUBESCRIPT_CONF_HH #define LIBCUBESCRIPT_CUBESCRIPT_CONF_HH
namespace cscript { namespace cscript {
using cs_int = int; using integer_type = int;
using cs_float = float; using float_type = float;
constexpr auto const CS_INT_FORMAT = "%d"; constexpr auto const INT_FORMAT = "%d";
constexpr auto const CS_FLOAT_FORMAT = "%.7g"; constexpr auto const FLOAT_FORMAT = "%.7g";
constexpr auto const CS_ROUND_FLOAT_FORMAT = "%.1f"; constexpr auto const ROUND_FLOAT_FORMAT = "%.1f";
} /* namespace cscript */ } /* namespace cscript */
#endif /* LIBCUBESCRIPT_CUBESCRIPT_CONF_HH */ #endif /* LIBCUBESCRIPT_CUBESCRIPT_CONF_HH */

View File

@ -5,29 +5,29 @@ namespace cscript {
/* public API impls */ /* public API impls */
LIBCUBESCRIPT_EXPORT cs_bcode_ref::cs_bcode_ref(cs_bcode *v): p_code(v) { LIBCUBESCRIPT_EXPORT bcode_ref::bcode_ref(bcode *v): p_code(v) {
bcode_ref(v->get_raw()); 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) 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()); bcode_unref(p_code->get_raw());
} }
LIBCUBESCRIPT_EXPORT cs_bcode_ref &cs_bcode_ref::operator=( LIBCUBESCRIPT_EXPORT bcode_ref &bcode_ref::operator=(
cs_bcode_ref const &v bcode_ref const &v
) { ) {
bcode_unref(p_code->get_raw()); bcode_unref(p_code->get_raw());
p_code = v.p_code; p_code = v.p_code;
bcode_ref(p_code->get_raw()); bcode_addref(p_code->get_raw());
return *this; 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()); bcode_unref(p_code->get_raw());
p_code = v.p_code; p_code = v.p_code;
v.p_code = nullptr; v.p_code = nullptr;
@ -37,18 +37,18 @@ LIBCUBESCRIPT_EXPORT cs_bcode_ref &cs_bcode_ref::operator=(cs_bcode_ref &&v) {
/* private funcs */ /* private funcs */
struct bcode_hdr { 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 */ 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 */ /* returned address is the 'init' member of the header */
std::uint32_t *bcode_alloc(cs_state &cs, std::size_t sz) { std::uint32_t *bcode_alloc(state &cs, std::size_t sz) {
auto a = cs_allocator<std::uint32_t>{cs}; auto a = std_allocator<std::uint32_t>{cs};
std::size_t hdrs = sizeof(bcode_hdr) / sizeof(std::uint32_t); std::size_t hdrs = sizeof(bcode_hdr) / sizeof(std::uint32_t);
auto p = a.allocate(sz + hdrs - 1); auto p = a.allocate(sz + hdrs - 1);
bcode_hdr *hdr = reinterpret_cast<bcode_hdr *>(p); 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; hdr->asize = sz + hdrs - 1;
return p + 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) { static inline void bcode_free(std::uint32_t *bc) {
auto *rp = bc + 1 - (sizeof(bcode_hdr) / sizeof(std::uint32_t)); auto *rp = bc + 1 - (sizeof(bcode_hdr) / sizeof(std::uint32_t));
bcode_hdr *hdr = reinterpret_cast<bcode_hdr *>(rp); 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) { 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) { if (!code) {
return; return;
} }
if ((*code & CS_CODE_OP_MASK) == CS_CODE_START) { if ((*code & BC_INST_OP_MASK) == BC_INST_START) {
bcode_incr(code); bcode_incr(code);
return; return;
} }
switch (code[-1]&CS_CODE_OP_MASK) { switch (code[-1]&BC_INST_OP_MASK) {
case CS_CODE_START: case BC_INST_START:
bcode_incr(&code[-1]); bcode_incr(&code[-1]);
break; break;
case CS_CODE_OFFSET: case BC_INST_OFFSET:
code -= std::ptrdiff_t(code[-1] >> 8); code -= std::ptrdiff_t(code[-1] >> 8);
bcode_incr(code); bcode_incr(code);
break; break;
@ -94,15 +94,15 @@ void bcode_unref(std::uint32_t *code) {
if (!code) { if (!code) {
return; return;
} }
if ((*code & CS_CODE_OP_MASK) == CS_CODE_START) { if ((*code & BC_INST_OP_MASK) == BC_INST_START) {
bcode_decr(code); bcode_decr(code);
return; return;
} }
switch (code[-1]&CS_CODE_OP_MASK) { switch (code[-1]&BC_INST_OP_MASK) {
case CS_CODE_START: case BC_INST_START:
bcode_decr(&code[-1]); bcode_decr(&code[-1]);
break; break;
case CS_CODE_OFFSET: case BC_INST_OFFSET:
code -= std::ptrdiff_t(code[-1] >> 8); code -= std::ptrdiff_t(code[-1] >> 8);
bcode_decr(code); bcode_decr(code);
break; break;
@ -111,25 +111,25 @@ void bcode_unref(std::uint32_t *code) {
/* empty fallbacks */ /* empty fallbacks */
static std::uint32_t emptyrets[CS_VAL_ANY] = { static std::uint32_t emptyrets[VAL_ANY] = {
CS_RET_NULL, CS_RET_INT, CS_RET_FLOAT, CS_RET_STRING BC_RET_NULL, BC_RET_INT, BC_RET_FLOAT, BC_RET_STRING
}; };
empty_block *bcode_init_empty(cs_shared_state *cs) { empty_block *bcode_init_empty(internal_state *cs) {
auto a = cs_allocator<empty_block>{cs}; auto a = std_allocator<empty_block>{cs};
auto *p = a.allocate(CS_VAL_ANY); auto *p = a.allocate(VAL_ANY);
for (std::size_t i = 0; i < CS_VAL_ANY; ++i) { for (std::size_t i = 0; i < VAL_ANY; ++i) {
p[i].init.init = CS_CODE_START + 0x100; p[i].init.init = BC_INST_START + 0x100;
p[i].code = CS_CODE_EXIT | emptyrets[i]; p[i].code = BC_INST_EXIT | emptyrets[i];
} }
return p; return p;
} }
void bcode_free_empty(cs_shared_state *cs, empty_block *empty) { void bcode_free_empty(internal_state *cs, empty_block *empty) {
cs_allocator<empty_block>{cs}.deallocate(empty, CS_VAL_ANY); 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; return &empty[val].init + 1;
} }

View File

@ -8,7 +8,7 @@
namespace cscript { namespace cscript {
struct cs_bcode { struct bcode {
std::uint32_t init; std::uint32_t init;
std::uint32_t *get_raw() { std::uint32_t *get_raw() {
@ -21,72 +21,72 @@ struct cs_bcode {
}; };
enum { enum {
CS_VAL_NULL = 0, CS_VAL_INT, CS_VAL_FLOAT, CS_VAL_STRING, VAL_NULL = 0, VAL_INT, VAL_FLOAT, VAL_STRING,
CS_VAL_ANY, CS_VAL_CODE, CS_VAL_IDENT, CS_VAL_WORD, VAL_ANY, VAL_CODE, VAL_IDENT, VAL_WORD,
CS_VAL_POP, CS_VAL_COND VAL_POP, VAL_COND
}; };
/* instruction: uint32 [length 24][retflag 2][opcode 6] */ /* instruction: uint32 [length 24][retflag 2][opcode 6] */
enum { enum {
CS_CODE_START = 0, BC_INST_START = 0,
CS_CODE_OFFSET, BC_INST_OFFSET,
CS_CODE_NULL, CS_CODE_TRUE, CS_CODE_FALSE, CS_CODE_NOT, BC_INST_NULL, BC_INST_TRUE, BC_INST_FALSE, BC_INST_NOT,
CS_CODE_POP, BC_INST_POP,
CS_CODE_ENTER, CS_CODE_ENTER_RESULT, BC_INST_ENTER, BC_INST_ENTER_RESULT,
CS_CODE_EXIT, CS_CODE_RESULT_ARG, BC_INST_EXIT, BC_INST_RESULT_ARG,
CS_CODE_VAL, CS_CODE_VAL_INT, BC_INST_VAL, BC_INST_VAL_INT,
CS_CODE_DUP, BC_INST_DUP,
CS_CODE_BOOL, BC_INST_BOOL,
CS_CODE_BLOCK, CS_CODE_EMPTY, BC_INST_BLOCK, BC_INST_EMPTY,
CS_CODE_COMPILE, CS_CODE_COND, BC_INST_COMPILE, BC_INST_COND,
CS_CODE_FORCE, BC_INST_FORCE,
CS_CODE_RESULT, BC_INST_RESULT,
CS_CODE_IDENT, CS_CODE_IDENT_U, CS_CODE_IDENT_ARG, BC_INST_IDENT, BC_INST_IDENT_U, BC_INST_IDENT_ARG,
CS_CODE_COM, CS_CODE_COM_C, CS_CODE_COM_V, BC_INST_COM, BC_INST_COM_C, BC_INST_COM_V,
CS_CODE_CONC, CS_CODE_CONC_W, CS_CODE_CONC_M, BC_INST_CONC, BC_INST_CONC_W, BC_INST_CONC_M,
CS_CODE_SVAR, CS_CODE_SVAR1, BC_INST_SVAR, BC_INST_SVAR1,
CS_CODE_IVAR, CS_CODE_IVAR1, CS_CODE_IVAR2, CS_CODE_IVAR3, BC_INST_IVAR, BC_INST_IVAR1, BC_INST_IVAR2, BC_INST_IVAR3,
CS_CODE_FVAR, CS_CODE_FVAR1, BC_INST_FVAR, BC_INST_FVAR1,
CS_CODE_LOOKUP, CS_CODE_LOOKUP_U, CS_CODE_LOOKUP_ARG, BC_INST_LOOKUP, BC_INST_LOOKUP_U, BC_INST_LOOKUP_ARG,
CS_CODE_LOOKUP_M, CS_CODE_LOOKUP_MU, CS_CODE_LOOKUP_MARG, BC_INST_LOOKUP_M, BC_INST_LOOKUP_MU, BC_INST_LOOKUP_MARG,
CS_CODE_ALIAS, CS_CODE_ALIAS_U, CS_CODE_ALIAS_ARG, BC_INST_ALIAS, BC_INST_ALIAS_U, BC_INST_ALIAS_ARG,
CS_CODE_CALL, CS_CODE_CALL_U, CS_CODE_CALL_ARG, BC_INST_CALL, BC_INST_CALL_U, BC_INST_CALL_ARG,
CS_CODE_PRINT, BC_INST_PRINT,
CS_CODE_LOCAL, BC_INST_LOCAL,
CS_CODE_DO, CS_CODE_DO_ARGS, BC_INST_DO, BC_INST_DO_ARGS,
CS_CODE_JUMP, CS_CODE_JUMP_B, CS_CODE_JUMP_RESULT, BC_INST_JUMP, BC_INST_JUMP_B, BC_INST_JUMP_RESULT,
CS_CODE_BREAK, BC_INST_BREAK,
CS_CODE_OP_MASK = 0x3F, BC_INST_OP_MASK = 0x3F,
CS_CODE_RET = 6, BC_INST_RET = 6,
CS_CODE_RET_MASK = 0xC0, BC_INST_RET_MASK = 0xC0,
/* return type flags */ /* return type flags */
CS_RET_NULL = CS_VAL_NULL << CS_CODE_RET, BC_RET_NULL = VAL_NULL << BC_INST_RET,
CS_RET_STRING = CS_VAL_STRING << CS_CODE_RET, BC_RET_STRING = VAL_STRING << BC_INST_RET,
CS_RET_INT = CS_VAL_INT << CS_CODE_RET, BC_RET_INT = VAL_INT << BC_INST_RET,
CS_RET_FLOAT = CS_VAL_FLOAT << CS_CODE_RET, BC_RET_FLOAT = VAL_FLOAT << BC_INST_RET,
/* CS_CODE_JUMP_B, CS_CODE_JUMP_RESULT */ /* BC_INST_JUMP_B, BC_INST_JUMP_RESULT */
CS_CODE_FLAG_TRUE = 1 << CS_CODE_RET, BC_INST_FLAG_TRUE = 1 << BC_INST_RET,
CS_CODE_FLAG_FALSE = 0 << CS_CODE_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_incr(std::uint32_t *code);
void bcode_decr(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); void bcode_unref(std::uint32_t *code);
struct empty_block { struct empty_block {
cs_bcode init; bcode init;
std::uint32_t code; std::uint32_t code;
}; };
empty_block *bcode_init_empty(cs_shared_state *cs); empty_block *bcode_init_empty(internal_state *cs);
void bcode_free_empty(cs_shared_state *cs, empty_block *empty); void bcode_free_empty(internal_state *cs, empty_block *empty);
cs_bcode *bcode_get_empty(empty_block *empty, std::size_t val); bcode *bcode_get_empty(empty_block *empty, std::size_t val);
} /* namespace cscript */ } /* namespace cscript */

View File

@ -4,11 +4,11 @@
namespace cscript { namespace cscript {
LIBCUBESCRIPT_EXPORT char *cs_error::request_buf( LIBCUBESCRIPT_EXPORT char *error::request_buf(
cs_state &cs, std::size_t bufs, char *&sp state &cs, std::size_t bufs, char *&sp
) { ) {
cs_charbuf &cb = *static_cast<cs_charbuf *>(cs.p_errbuf); charbuf &cb = *static_cast<charbuf *>(cs.p_errbuf);
cs_gen_state *gs = cs.p_pstate; codegen_state *gs = cs.p_pstate;
cb.clear(); cb.clear();
std::size_t sz = 0; std::size_t sz = 0;
if (gs) { if (gs) {
@ -30,7 +30,7 @@ LIBCUBESCRIPT_EXPORT char *cs_error::request_buf(
nsz = std::snprintf(cb.data(), sz, "%zu: ", gs->current_line); nsz = std::snprintf(cb.data(), sz, "%zu: ", gs->current_line);
} }
if (nsz <= 0) { if (nsz <= 0) {
throw cs_internal_error{"format error"}; throw internal_error{"format error"};
} else if (std::size_t(nsz) < sz) { } else if (std::size_t(nsz) < sz) {
sz = std::size_t(nsz); sz = std::size_t(nsz);
break; break;
@ -43,24 +43,24 @@ LIBCUBESCRIPT_EXPORT char *cs_error::request_buf(
return &cb[sz]; return &cb[sz];
} }
LIBCUBESCRIPT_EXPORT cs_stack_state cs_error::save_stack(cs_state &cs) { LIBCUBESCRIPT_EXPORT stack_state error::save_stack(state &cs) {
cs_ivar *dalias = static_cast<cs_ivar *>(cs.p_state->identmap[DbgaliasIdx]); integer_var *dalias = static_cast<integer_var *>(cs.p_state->identmap[DbgaliasIdx]);
if (!dalias->get_value()) { 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; 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++; total++;
} }
if (!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()) std::min(total, dalias->get_value())
); );
cs_stack_state_node *ret = st, *nd = st; stack_state_node *ret = st, *nd = st;
++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; ++depth;
if (depth < dalias->get_value()) { if (depth < dalias->get_value()) {
nd->id = l->id; nd->id = l->id;
@ -77,7 +77,7 @@ LIBCUBESCRIPT_EXPORT cs_stack_state cs_error::save_stack(cs_state &cs) {
nd->next = nullptr; nd->next = nullptr;
} }
} }
return cs_stack_state(cs, ret, total > dalias->get_value()); return stack_state(cs, ret, total > dalias->get_value());
} }
} /* namespace cscript */ } /* namespace cscript */

File diff suppressed because it is too large Load Diff

View File

@ -5,27 +5,27 @@
namespace cscript { 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} p_name{nm}, p_type{int(tp)}, p_flags{fl}
{} {}
cs_var_impl::cs_var_impl( var_impl::var_impl(
cs_ident_type tp, cs_strref name, cs_var_cb f, int fl 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) { if (cb_var) {
switch (p_type) { switch (p_type) {
case ID_IVAR: case ID_IVAR:
cb_var(cs, *static_cast<cs_ivar_impl *>(this)); cb_var(cs, *static_cast<ivar_impl *>(this));
break; break;
case ID_FVAR: case ID_FVAR:
cb_var(cs, *static_cast<cs_fvar_impl *>(this)); cb_var(cs, *static_cast<fvar_impl *>(this));
break; break;
case ID_SVAR: case ID_SVAR:
cb_var(cs, *static_cast<cs_svar_impl *>(this)); cb_var(cs, *static_cast<svar_impl *>(this));
break; break;
default: default:
break; break;
@ -33,80 +33,80 @@ void cs_var_impl::changed(cs_state &cs) {
} }
} }
cs_ivar_impl::cs_ivar_impl( ivar_impl::ivar_impl(
cs_strref name, cs_int m, cs_int x, cs_int v, cs_var_cb f, int fl string_ref name, integer_type m, integer_type x, integer_type v, var_cb_func f, int fl
): ):
cs_var_impl{ var_impl{
cs_ident_type::IVAR, name, std::move(f), ident_type::IVAR, name, std::move(f),
fl | ((m > x) ? CS_IDF_READONLY : 0) fl | ((m > x) ? IDENT_FLAG_READONLY : 0)
}, },
p_storage{v}, p_minval{m}, p_maxval{x}, p_overrideval{0} p_storage{v}, p_minval{m}, p_maxval{x}, p_overrideval{0}
{} {}
cs_fvar_impl::cs_fvar_impl( fvar_impl::fvar_impl(
cs_strref name, cs_float m, cs_float x, cs_float v, cs_var_cb f, int fl string_ref name, float_type m, float_type x, float_type v, var_cb_func f, int fl
): ):
cs_var_impl{ var_impl{
cs_ident_type::FVAR, name, std::move(f), ident_type::FVAR, name, std::move(f),
fl | ((m > x) ? CS_IDF_READONLY : 0) fl | ((m > x) ? IDENT_FLAG_READONLY : 0)
}, },
p_storage{v}, p_minval{m}, p_maxval{x}, p_overrideval{0} p_storage{v}, p_minval{m}, p_maxval{x}, p_overrideval{0}
{} {}
cs_svar_impl::cs_svar_impl( svar_impl::svar_impl(
cs_strref name, cs_strref v, cs_strref ov, cs_var_cb f, int fl 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} p_storage{v}, p_overrideval{ov}
{} {}
cs_alias_impl::cs_alias_impl( alias_impl::alias_impl(
cs_state &cs, cs_strref name, cs_strref a, int fl 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_acode{nullptr}, p_astack{nullptr}, p_val{cs}
{ {
p_val.set_str(a); p_val.set_str(a);
} }
cs_alias_impl::cs_alias_impl( alias_impl::alias_impl(
cs_state &cs, cs_strref name, std::string_view a, int fl 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_acode{nullptr}, p_astack{nullptr}, p_val{cs}
{ {
p_val.set_str(a); p_val.set_str(a);
} }
cs_alias_impl::cs_alias_impl(cs_state &cs, cs_strref name, cs_int a, int fl): alias_impl::alias_impl(state &cs, string_ref name, integer_type 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_acode{nullptr}, p_astack{nullptr}, p_val{cs}
{ {
p_val.set_int(a); p_val.set_int(a);
} }
cs_alias_impl::cs_alias_impl(cs_state &cs, cs_strref name, cs_float a, int fl): alias_impl::alias_impl(state &cs, string_ref name, float_type 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_acode{nullptr}, p_astack{nullptr}, p_val{cs}
{ {
p_val.set_float(a); p_val.set_float(a);
} }
cs_alias_impl::cs_alias_impl(cs_state &cs, cs_strref name, int fl): alias_impl::alias_impl(state &cs, string_ref name, 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_acode{nullptr}, p_astack{nullptr}, p_val{cs}
{ {
p_val.set_none(); p_val.set_none();
} }
cs_alias_impl::cs_alias_impl(cs_state &cs, cs_strref name, cs_value v, int fl): alias_impl::alias_impl(state &cs, string_ref name, any_value v, 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_acode{nullptr}, p_astack{nullptr}, p_val{cs}
{ {
p_val = v; 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) { if (p_astack == &st) {
/* prevent cycles and unnecessary code elsewhere */ /* prevent cycles and unnecessary code elsewhere */
p_val = std::move(v); 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); p_val = std::move(v);
clean_code(); clean_code();
if (um) { 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) { if (!p_astack) {
return; return;
} }
cs_ident_stack *st = p_astack; ident_stack *st = p_astack;
p_val = std::move(p_astack->val_s); p_val = std::move(p_astack->val_s);
clean_code(); clean_code();
p_astack = st->next; p_astack = st->next;
} }
void cs_alias_impl::undo_arg(cs_ident_stack &st) { void alias_impl::undo_arg(ident_stack &st) {
cs_ident_stack *prev = p_astack; ident_stack *prev = p_astack;
st.val_s = std::move(p_val); st.val_s = std::move(p_val);
st.next = prev; st.next = prev;
p_astack = prev->next; p_astack = prev->next;
@ -142,15 +142,15 @@ void cs_alias_impl::undo_arg(cs_ident_stack &st) {
clean_code(); clean_code();
} }
void cs_alias_impl::redo_arg(cs_ident_stack &st) { void alias_impl::redo_arg(ident_stack &st) {
cs_ident_stack *prev = st.next; ident_stack *prev = st.next;
prev->val_s = std::move(p_val); prev->val_s = std::move(p_val);
p_astack = prev; p_astack = prev;
p_val = std::move(st.val_s); p_val = std::move(st.val_s);
clean_code(); 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)) { if (ident_is_used_arg(this, cs)) {
p_val = std::move(v); p_val = std::move(v);
clean_code(); 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); p_val = std::move(v);
clean_code(); clean_code();
p_flags = (p_flags & cs.identflags) | cs.identflags; p_flags = (p_flags & cs.identflags) | cs.identflags;
} }
void cs_alias_impl::clean_code() { void alias_impl::clean_code() {
if (p_acode) { if (p_acode) {
bcode_decr(p_acode->get_raw()); bcode_decr(p_acode->get_raw());
p_acode = nullptr; p_acode = nullptr;
} }
} }
cs_bcode *cs_alias_impl::compile_code(cs_state &cs) { bcode *alias_impl::compile_code(state &cs) {
if (!p_acode) { if (!p_acode) {
cs_gen_state gs(cs); codegen_state gs(cs);
gs.code.reserve(64); gs.code.reserve(64);
gs.gen_main(get_value().get_str()); gs.gen_main(get_value().get_str());
/* i wish i could steal the memory somehow */ /* i wish i could steal the memory somehow */
uint32_t *code = bcode_alloc(cs, gs.code.size()); uint32_t *code = bcode_alloc(cs, gs.code.size());
memcpy(code, gs.code.data(), gs.code.size() * sizeof(uint32_t)); memcpy(code, gs.code.data(), gs.code.size() * sizeof(uint32_t));
bcode_incr(code); bcode_incr(code);
p_acode = reinterpret_cast<cs_bcode *>(code); p_acode = reinterpret_cast<bcode *>(code);
} }
return p_acode; return p_acode;
} }
cs_command_impl::cs_command_impl( command_impl::command_impl(
cs_strref name, cs_strref args, int nargs, cs_command_cb f 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} 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) { if (!cs.p_callstack) {
return true; return true;
} }
@ -203,74 +203,74 @@ bool ident_is_used_arg(cs_ident *id, cs_state &cs) {
/* public interface */ /* public interface */
LIBCUBESCRIPT_EXPORT int cs_ident::get_raw_type() const { LIBCUBESCRIPT_EXPORT int ident::get_raw_type() const {
return p_impl->p_type; 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) { 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; 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; 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; return p_impl->p_index;
} }
LIBCUBESCRIPT_EXPORT bool cs_ident::is_alias() const { LIBCUBESCRIPT_EXPORT bool ident::is_alias() const {
return get_type() == cs_ident_type::ALIAS; return get_type() == ident_type::ALIAS;
} }
LIBCUBESCRIPT_EXPORT cs_alias *cs_ident::get_alias() { LIBCUBESCRIPT_EXPORT alias *ident::get_alias() {
if (!is_alias()) { if (!is_alias()) {
return nullptr; 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()) { if (!is_alias()) {
return nullptr; return nullptr;
} }
return static_cast<cs_alias const *>(this); return static_cast<alias const *>(this);
} }
LIBCUBESCRIPT_EXPORT bool cs_ident::is_command() const { LIBCUBESCRIPT_EXPORT bool ident::is_command() const {
return get_type() == cs_ident_type::COMMAND; return get_type() == ident_type::COMMAND;
} }
LIBCUBESCRIPT_EXPORT cs_command *cs_ident::get_command() { LIBCUBESCRIPT_EXPORT command *ident::get_command() {
if (!is_command()) { if (!is_command()) {
return nullptr; 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()) { if (!is_command()) {
return nullptr; 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 { LIBCUBESCRIPT_EXPORT bool ident::is_special() const {
return get_type() == cs_ident_type::SPECIAL; return get_type() == ident_type::SPECIAL;
} }
LIBCUBESCRIPT_EXPORT bool cs_ident::is_var() const { LIBCUBESCRIPT_EXPORT bool ident::is_var() const {
switch (get_type()) { switch (get_type()) {
case cs_ident_type::IVAR: case ident_type::IVAR:
case cs_ident_type::FVAR: case ident_type::FVAR:
case cs_ident_type::SVAR: case ident_type::SVAR:
return true; return true;
default: default:
break; break;
@ -278,128 +278,128 @@ LIBCUBESCRIPT_EXPORT bool cs_ident::is_var() const {
return false; return false;
} }
LIBCUBESCRIPT_EXPORT cs_var *cs_ident::get_var() { LIBCUBESCRIPT_EXPORT global_var *ident::get_var() {
if (!is_var()) { if (!is_var()) {
return nullptr; 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()) { if (!is_var()) {
return nullptr; return nullptr;
} }
return static_cast<cs_var const *>(this); return static_cast<global_var const *>(this);
} }
LIBCUBESCRIPT_EXPORT bool cs_ident::is_ivar() const { LIBCUBESCRIPT_EXPORT bool ident::is_ivar() const {
return get_type() == cs_ident_type::IVAR; return get_type() == ident_type::IVAR;
} }
LIBCUBESCRIPT_EXPORT cs_ivar *cs_ident::get_ivar() { LIBCUBESCRIPT_EXPORT integer_var *ident::get_ivar() {
if (!is_ivar()) { if (!is_ivar()) {
return nullptr; 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()) { if (!is_ivar()) {
return nullptr; return nullptr;
} }
return static_cast<cs_ivar const *>(this); return static_cast<integer_var const *>(this);
} }
LIBCUBESCRIPT_EXPORT bool cs_ident::is_fvar() const { LIBCUBESCRIPT_EXPORT bool ident::is_fvar() const {
return get_type() == cs_ident_type::FVAR; return get_type() == ident_type::FVAR;
} }
LIBCUBESCRIPT_EXPORT cs_fvar *cs_ident::get_fvar() { LIBCUBESCRIPT_EXPORT float_var *ident::get_fvar() {
if (!is_fvar()) { if (!is_fvar()) {
return nullptr; 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()) { if (!is_fvar()) {
return nullptr; return nullptr;
} }
return static_cast<cs_fvar const *>(this); return static_cast<float_var const *>(this);
} }
LIBCUBESCRIPT_EXPORT bool cs_ident::is_svar() const { LIBCUBESCRIPT_EXPORT bool ident::is_svar() const {
return get_type() == cs_ident_type::SVAR; return get_type() == ident_type::SVAR;
} }
LIBCUBESCRIPT_EXPORT cs_svar *cs_ident::get_svar() { LIBCUBESCRIPT_EXPORT string_var *ident::get_svar() {
if (!is_svar()) { if (!is_svar()) {
return nullptr; 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()) { if (!is_svar()) {
return nullptr; 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 { LIBCUBESCRIPT_EXPORT integer_type integer_var::get_val_min() const {
return static_cast<cs_ivar_impl const *>(this)->p_minval; return static_cast<ivar_impl const *>(this)->p_minval;
} }
LIBCUBESCRIPT_EXPORT cs_int cs_ivar::get_val_max() const { LIBCUBESCRIPT_EXPORT integer_type integer_var::get_val_max() const {
return static_cast<cs_ivar_impl const *>(this)->p_maxval; return static_cast<ivar_impl const *>(this)->p_maxval;
} }
LIBCUBESCRIPT_EXPORT cs_int cs_ivar::get_value() const { LIBCUBESCRIPT_EXPORT integer_type integer_var::get_value() const {
return static_cast<cs_ivar_impl const *>(this)->p_storage; return static_cast<ivar_impl const *>(this)->p_storage;
} }
LIBCUBESCRIPT_EXPORT void cs_ivar::set_value(cs_int val) { LIBCUBESCRIPT_EXPORT void integer_var::set_value(integer_type val) {
static_cast<cs_ivar_impl *>(this)->p_storage = val; static_cast<ivar_impl *>(this)->p_storage = val;
} }
LIBCUBESCRIPT_EXPORT cs_float cs_fvar::get_val_min() const { LIBCUBESCRIPT_EXPORT float_type float_var::get_val_min() const {
return static_cast<cs_fvar_impl const *>(this)->p_minval; return static_cast<fvar_impl const *>(this)->p_minval;
} }
LIBCUBESCRIPT_EXPORT cs_float cs_fvar::get_val_max() const { LIBCUBESCRIPT_EXPORT float_type float_var::get_val_max() const {
return static_cast<cs_fvar_impl const *>(this)->p_maxval; return static_cast<fvar_impl const *>(this)->p_maxval;
} }
LIBCUBESCRIPT_EXPORT cs_float cs_fvar::get_value() const { LIBCUBESCRIPT_EXPORT float_type float_var::get_value() const {
return static_cast<cs_fvar_impl const *>(this)->p_storage; return static_cast<fvar_impl const *>(this)->p_storage;
} }
LIBCUBESCRIPT_EXPORT void cs_fvar::set_value(cs_float val) { LIBCUBESCRIPT_EXPORT void float_var::set_value(float_type val) {
static_cast<cs_fvar_impl *>(this)->p_storage = val; static_cast<fvar_impl *>(this)->p_storage = val;
} }
LIBCUBESCRIPT_EXPORT cs_strref cs_svar::get_value() const { LIBCUBESCRIPT_EXPORT string_ref string_var::get_value() const {
return static_cast<cs_svar_impl const *>(this)->p_storage; return static_cast<svar_impl const *>(this)->p_storage;
} }
LIBCUBESCRIPT_EXPORT void cs_svar::set_value(cs_strref val) { LIBCUBESCRIPT_EXPORT void string_var::set_value(string_ref val) {
static_cast<cs_svar_impl *>(this)->p_storage = val; static_cast<svar_impl *>(this)->p_storage = val;
} }
LIBCUBESCRIPT_EXPORT cs_value cs_alias::get_value() const { LIBCUBESCRIPT_EXPORT any_value alias::get_value() const {
return static_cast<cs_alias_impl const *>(this)->p_val; return static_cast<alias_impl const *>(this)->p_val;
} }
void cs_alias::get_cval(cs_value &v) const { void alias::get_cval(any_value &v) const {
auto *imp = static_cast<cs_alias_impl const *>(this); auto *imp = static_cast<alias_impl const *>(this);
switch (imp->p_val.get_type()) { switch (imp->p_val.get_type()) {
case cs_value_type::STRING: case value_type::STRING:
v = imp->p_val; v = imp->p_val;
break; break;
case cs_value_type::INT: case value_type::INT:
v.set_int(imp->p_val.get_int()); v.set_int(imp->p_val.get_int());
break; break;
case cs_value_type::FLOAT: case value_type::FLOAT:
v.set_float(imp->p_val.get_float()); v.set_float(imp->p_val.get_float());
break; break;
default: default:
@ -408,12 +408,12 @@ void cs_alias::get_cval(cs_value &v) const {
} }
} }
LIBCUBESCRIPT_EXPORT std::string_view cs_command::get_args() const { LIBCUBESCRIPT_EXPORT std::string_view command::get_args() const {
return static_cast<cs_command_impl const *>(this)->p_cargs; return static_cast<command_impl const *>(this)->p_cargs;
} }
LIBCUBESCRIPT_EXPORT int cs_command::get_num_args() const { LIBCUBESCRIPT_EXPORT int command::get_num_args() const {
return static_cast<cs_command_impl const *>(this)->p_numargs; return static_cast<command_impl const *>(this)->p_numargs;
} }
} /* namespace cscript */ } /* namespace cscript */

View File

@ -11,28 +11,28 @@ enum {
ID_NOT, ID_AND, ID_OR ID_NOT, ID_AND, ID_OR
}; };
struct cs_ident_link { struct ident_link {
cs_ident *id; ident *id;
cs_ident_link *next; ident_link *next;
int usedargs; int usedargs;
cs_ident_stack *argstack; ident_stack *argstack;
}; };
struct cs_ident_impl { struct ident_impl {
cs_ident_impl() = delete; ident_impl() = delete;
cs_ident_impl(cs_ident_impl const &) = delete; ident_impl(ident_impl const &) = delete;
cs_ident_impl(cs_ident_impl &&) = delete; ident_impl(ident_impl &&) = delete;
/* trigger destructors for all inherited members properly */ /* trigger destructors for all inherited members properly */
virtual ~cs_ident_impl() {}; virtual ~ident_impl() {};
cs_ident_impl &operator=(cs_ident_impl const &) = delete; ident_impl &operator=(ident_impl const &) = delete;
cs_ident_impl &operator=(cs_ident_impl &&) = 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; string_ref p_name;
/* represents the cs_ident_type above, but internally it has a wider /* 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) * variety of values, so it's an int here (maps to an internal enum)
*/ */
int p_type, p_flags; int p_type, p_flags;
@ -40,79 +40,79 @@ struct cs_ident_impl {
int p_index = -1; int p_index = -1;
}; };
struct cs_var_impl: cs_ident_impl { struct var_impl: ident_impl {
cs_var_impl( var_impl(
cs_ident_type tp, cs_strref name, cs_var_cb func, int flags = 0 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 { struct ivar_impl: var_impl, integer_var {
cs_ivar_impl( ivar_impl(
cs_strref n, cs_int m, cs_int x, cs_int v, cs_var_cb f, int flags 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 { struct fvar_impl: var_impl, float_var {
cs_fvar_impl( fvar_impl(
cs_strref n, cs_float m, cs_float x, cs_float v, string_ref n, float_type m, float_type x, float_type v,
cs_var_cb f, int flags 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 { struct svar_impl: var_impl, string_var {
cs_svar_impl( svar_impl(
cs_strref n, cs_strref v, cs_strref ov, cs_var_cb f, int flags 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 { struct alias_impl: ident_impl, alias {
cs_alias_impl(cs_state &cs, cs_strref n, cs_strref a, int flags); alias_impl(state &cs, string_ref n, string_ref a, int flags);
cs_alias_impl(cs_state &cs, cs_strref n, std::string_view a, int flags); alias_impl(state &cs, string_ref n, std::string_view a, int flags);
cs_alias_impl(cs_state &cs, cs_strref n, cs_int a, int flags); alias_impl(state &cs, string_ref n, integer_type a, int flags);
cs_alias_impl(cs_state &cs, cs_strref n, cs_float a, int flags); alias_impl(state &cs, string_ref n, float_type a, int flags);
cs_alias_impl(cs_state &cs, cs_strref n, int flags); alias_impl(state &cs, string_ref n, int flags);
cs_alias_impl(cs_state &cs, cs_strref n, cs_value v, 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 pop_arg();
void undo_arg(cs_ident_stack &st); void undo_arg(ident_stack &st);
void redo_arg(cs_ident_stack &st); void redo_arg(ident_stack &st);
void set_arg(cs_state &cs, cs_value &v); void set_arg(state &cs, any_value &v);
void set_alias(cs_state &cs, cs_value &v); void set_alias(state &cs, any_value &v);
void clean_code(); void clean_code();
cs_bcode *compile_code(cs_state &cs); bcode *compile_code(state &cs);
cs_bcode *p_acode; bcode *p_acode;
cs_ident_stack *p_astack; ident_stack *p_astack;
cs_value p_val; any_value p_val;
}; };
struct cs_command_impl: cs_ident_impl, cs_command { struct command_impl: ident_impl, command {
cs_command_impl( command_impl(
cs_strref name, cs_strref args, int numargs, cs_command_cb func 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); p_cb_cftv(cs, args, ret);
} }
cs_strref p_cargs; string_ref p_cargs;
cs_command_cb p_cb_cftv; command_func p_cb_cftv;
int p_numargs; 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 */ } /* namespace cscript */

View File

@ -9,8 +9,8 @@ namespace cscript {
/* string/word parsers are also useful to have public */ /* string/word parsers are also useful to have public */
LIBCUBESCRIPT_EXPORT char const *cs_parse_string( LIBCUBESCRIPT_EXPORT char const *parse_string(
cs_state &cs, std::string_view str, size_t &nlines state &cs, std::string_view str, size_t &nlines
) { ) {
size_t nl = 0; size_t nl = 0;
nlines = nl; nlines = nl;
@ -54,7 +54,7 @@ LIBCUBESCRIPT_EXPORT char const *cs_parse_string(
end: end:
nlines = nl; nlines = nl;
if ((beg == end) || (*beg != '\"')) { if ((beg == end) || (*beg != '\"')) {
throw cs_error{ throw error{
cs, "unfinished string '%s'", cs, "unfinished string '%s'",
std::string_view{orig, std::size_t(beg - orig)} std::string_view{orig, std::size_t(beg - orig)}
}; };
@ -62,8 +62,8 @@ end:
return ++beg; return ++beg;
} }
LIBCUBESCRIPT_EXPORT char const *cs_parse_word( LIBCUBESCRIPT_EXPORT char const *parse_word(
cs_state &cs, std::string_view str state &cs, std::string_view str
) { ) {
char const *it = str.begin(); char const *it = str.begin();
char const *end = str.end(); char const *end = str.end();
@ -88,20 +88,20 @@ LIBCUBESCRIPT_EXPORT char const *cs_parse_word(
break; break;
case '[': case '[':
++it; ++it;
it = cs_parse_word(cs, std::string_view{ it = parse_word(cs, std::string_view{
it, std::size_t(end - it) it, std::size_t(end - it)
}); });
if ((it == end) || (*it != ']')) { if ((it == end) || (*it != ']')) {
throw cs_error{cs, "missing \"]\""}; throw error{cs, "missing \"]\""};
} }
break; break;
case '(': case '(':
++it; ++it;
it = cs_parse_word(cs, std::string_view{ it = parse_word(cs, std::string_view{
it, std::size_t(end - it) it, std::size_t(end - it)
}); });
if ((it == end) || (*it != ')')) { if ((it == end) || (*it != ')')) {
throw cs_error{cs, "missing \")\""}; throw error{cs, "missing \")\""};
} }
break; break;
case ']': case ']':
@ -128,7 +128,7 @@ static inline void p_set_end(
*end = std::string_view{nbeg, nend}; *end = std::string_view{nbeg, nend};
} }
/* this function assumes the input is definitely a hex digit */ /* 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 */ if (c >= 97) { /* a-f */
return (c - 'a') + 10; return (c - 'a') + 10;
} else if (c >= 65) { /* A-F */ } else if (c >= 65) { /* A-F */
@ -146,17 +146,17 @@ static inline bool p_check_neg(char const *&input) {
return neg; 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 *beg = input.begin();
char const *end = input.end(); char const *end = input.end();
char const *orig = beg; char const *orig = beg;
beg = p_skip_white(beg, end); beg = p_skip_white(beg, end);
if (beg == end) { if (beg == end) {
p_set_end(orig, end, endstr); p_set_end(orig, end, endstr);
return cs_int(0); return integer_type(0);
} }
bool neg = p_check_neg(beg); bool neg = p_check_neg(beg);
cs_int ret = 0; integer_type ret = 0;
char const *past = beg; char const *past = beg;
if ((end - beg) >= 2) { if ((end - beg) >= 2) {
std::string_view pfx = std::string_view{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'> 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) { if (beg == end) {
return true; 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)) { if ((beg == end) || !std::isdigit(*beg)) {
return false; return false;
} }
cs_int exp = 0; integer_type exp = 0;
while ((beg != end) && std::isdigit(*beg)) { while ((beg != end) && std::isdigit(*beg)) {
exp = exp * 10 + (*beg++ - '0'); 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> template<bool Hex>
static inline bool parse_gen_float( 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 ( while (
(beg != end) && (beg != end) &&
(Hex ? std::isxdigit(*beg) : std::isdigit(*beg)) (Hex ? std::isxdigit(*beg) : std::isdigit(*beg))
@ -232,7 +232,7 @@ static inline bool parse_gen_float(
} }
return r; return r;
}; };
cs_int wn = 0, fn = 0; integer_type wn = 0, fn = 0;
double r = read_digits(0.0, wn); double r = read_digits(0.0, wn);
if ((beg != end) && (*beg == '.')) { if ((beg != end) && (*beg == '.')) {
++beg; ++beg;
@ -247,24 +247,24 @@ static inline bool parse_gen_float(
p_set_end(beg, end, endstr); p_set_end(beg, end, endstr);
} }
if (Hex) { if (Hex) {
ret = cs_float(ldexp(r, fn * 4)); ret = float_type(ldexp(r, fn * 4));
} else { } else {
ret = cs_float(r * pow(10, fn)); ret = float_type(r * pow(10, fn));
} }
return true; 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 *beg = input.begin();
char const *end = input.end(); char const *end = input.end();
char const *orig = beg; char const *orig = beg;
beg = p_skip_white(beg, end); beg = p_skip_white(beg, end);
if (beg == end) { if (beg == end) {
p_set_end(orig, end, endstr); p_set_end(orig, end, endstr);
return cs_float(0); return float_type(0);
} }
bool neg = p_check_neg(beg); bool neg = p_check_neg(beg);
cs_float ret = cs_float(0); float_type ret = float_type(0);
if ((end - beg) >= 2) { if ((end - beg) >= 2) {
std::string_view pfx = std::string_view{beg, 2}; std::string_view pfx = std::string_view{beg, 2};
if ((pfx == "0x") || (pfx == "0X")) { if ((pfx == "0x") || (pfx == "0X")) {
@ -307,7 +307,7 @@ bool is_valid_name(std::string_view s) {
/* list parser public implementation */ /* list parser public implementation */
LIBCUBESCRIPT_EXPORT bool cs_list_parser::parse() { LIBCUBESCRIPT_EXPORT bool list_parser::parse() {
skip_until_item(); skip_until_item();
if (p_input_beg == p_input_end) { if (p_input_beg == p_input_end) {
return false; return false;
@ -315,7 +315,7 @@ LIBCUBESCRIPT_EXPORT bool cs_list_parser::parse() {
switch (*p_input_beg) { switch (*p_input_beg) {
case '"': { case '"': {
char const *qi = p_input_beg; 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_quoted_item = std::string_view{qi, p_input_beg};
p_item = p_quoted_item.substr(1, p_quoted_item.size() - 2); p_item = p_quoted_item.substr(1, p_quoted_item.size() - 2);
break; break;
@ -338,7 +338,7 @@ LIBCUBESCRIPT_EXPORT bool cs_list_parser::parse() {
case '"': case '"':
/* the quote is needed in str parsing */ /* the quote is needed in str parsing */
--p_input_beg; --p_input_beg;
p_input_beg = cs_parse_string(*p_state, get_input()); p_input_beg = parse_string(*p_state, get_input());
break; break;
case '/': case '/':
if ( if (
@ -375,7 +375,7 @@ endblock:
case ']': case ']':
return false; return false;
default: { 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_quoted_item = p_item = std::string_view{p_input_beg, e};
p_input_beg = e; p_input_beg = e;
break; break;
@ -388,7 +388,7 @@ endblock:
return true; return true;
} }
LIBCUBESCRIPT_EXPORT std::size_t cs_list_parser::count() { LIBCUBESCRIPT_EXPORT std::size_t list_parser::count() {
size_t ret = 0; size_t ret = 0;
while (parse()) { while (parse()) {
++ret; ++ret;
@ -396,16 +396,16 @@ LIBCUBESCRIPT_EXPORT std::size_t cs_list_parser::count() {
return ret; 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() == '"')) { if (!p_quoted_item.empty() && (p_quoted_item.front() == '"')) {
cs_charbuf buf{*p_state}; charbuf buf{*p_state};
cs_unescape_string(std::back_inserter(buf), p_item); unescape_string(std::back_inserter(buf), p_item);
return cs_strref{*p_state, buf.str()}; 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 (;;) { for (;;) {
while (p_input_beg != p_input_end) { while (p_input_beg != p_input_end) {
char c = *p_input_beg; char c = *p_input_beg;

View File

@ -7,8 +7,8 @@
namespace cscript { namespace cscript {
cs_int parse_int(std::string_view input, std::string_view *end = nullptr); integer_type parse_int(std::string_view input, std::string_view *end = nullptr);
cs_float parse_float(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); bool is_valid_name(std::string_view input);

View File

@ -8,21 +8,21 @@
namespace cscript { 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}, allocf{af}, aptr{data},
idents{allocator_type{this}}, idents{allocator_type{this}},
identmap{allocator_type{this}}, identmap{allocator_type{this}},
varprintf{}, varprintf{},
strman{create<cs_strman>(this)}, strman{create<string_pool>(this)},
empty{bcode_init_empty(this)} empty{bcode_init_empty(this)}
{} {}
cs_shared_state::~cs_shared_state() { internal_state::~internal_state() {
bcode_free_empty(this, empty); bcode_free_empty(this, empty);
destroy(strman); 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); void *p = allocf(aptr, ptr, os, ns);
if (!p && ns) { if (!p && ns) {
throw std::bad_alloc{}; throw std::bad_alloc{};
@ -30,7 +30,7 @@ void *cs_shared_state::alloc(void *ptr, size_t os, size_t ns) {
return p; 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) { if (!ns) {
std::free(p); std::free(p);
return nullptr; return nullptr;
@ -38,88 +38,88 @@ static void *cs_default_alloc(void *, void *p, size_t, size_t ns) {
return std::realloc(p, ns); return std::realloc(p, ns);
} }
void cs_init_lib_base(cs_state &cs); void init_lib_base(state &cs);
void cs_init_lib_math(cs_state &cs); void init_lib_math(state &cs);
void cs_init_lib_string(cs_state &cs); void init_lib_string(state &cs);
void cs_init_lib_list(cs_state &cs); void init_lib_list(state &cs);
/* public interfaces */ /* 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{} p_state{nullptr}, p_callhook{}
{ {
cs_command *p; command *p;
if (!func) { if (!func) {
func = cs_default_alloc; func = default_alloc;
} }
/* allocator is not set up yet, use func directly */ /* allocator is not set up yet, use func directly */
p_state = static_cast<cs_shared_state *>( p_state = static_cast<internal_state *>(
func(data, nullptr, 0, sizeof(cs_shared_state)) func(data, nullptr, 0, sizeof(internal_state))
); );
/* allocator will be set up in the constructor */ /* 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; p_owner = true;
/* will be used as message storage for errors */ /* 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) { for (int i = 0; i < MaxArguments; ++i) {
char buf[32]; char buf[32];
snprintf(buf, sizeof(buf), "arg%d", i + 1); 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) { 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); id = new_ivar("numargs", MaxArguments, 0, 0);
if (id->get_index() != NumargsIdx) { 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); id = new_ivar("dbgalias", 0, 1000, 4);
if (id->get_index() != DbgaliasIdx) { 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) { p = new_command("do", "e", [](auto &cs, auto args, auto &res) {
cs.run(args[0].get_code(), 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) { 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); 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) { p = new_command("if", "tee", [](auto &cs, auto args, auto &res) {
cs.run((args[0].get_bool() ? args[1] : args[2]).get_code(), 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) { p = new_command("result", "t", [](auto &, auto args, auto &res) {
res = std::move(args[0]); 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) { p = new_command("!", "t", [](auto &, auto args, auto &res) {
res.set_int(!args[0].get_bool()); 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) { p = new_command("&&", "E1V", [](auto &cs, auto args, auto &res) {
if (args.empty()) { if (args.empty()) {
res.set_int(1); res.set_int(1);
} else { } else {
for (size_t i = 0; i < args.size(); ++i) { for (size_t i = 0; i < args.size(); ++i) {
cs_bcode *code = args[i].get_code(); bcode *code = args[i].get_code();
if (code) { if (code) {
cs.run(code, res); cs.run(code, res);
} else { } 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) { p = new_command("||", "E1V", [](auto &cs, auto args, auto &res) {
if (args.empty()) { if (args.empty()) {
res.set_int(0); res.set_int(0);
} else { } else {
for (size_t i = 0; i < args.size(); ++i) { for (size_t i = 0; i < args.size(); ++i) {
cs_bcode *code = args[i].get_code(); bcode *code = args[i].get_code();
if (code) { if (code) {
cs.run(code, res); cs.run(code, res);
} else { } 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); 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 &) { p = new_command("break", "", [](auto &cs, auto, auto &) {
if (cs.is_in_loop()) { if (cs.is_in_loop()) {
throw CsBreakException{}; throw CsBreakException{};
} else { } 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 &) { p = new_command("continue", "", [](auto &cs, auto, auto &) {
if (cs.is_in_loop()) { if (cs.is_in_loop()) {
throw CsContinueException{}; throw CsContinueException{};
} else { } 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(); destroy();
} }
LIBCUBESCRIPT_EXPORT void cs_state::destroy() { LIBCUBESCRIPT_EXPORT void state::destroy() {
if (!p_state || !p_owner) { if (!p_state || !p_owner) {
return; return;
} }
for (auto &p: p_state->idents) { for (auto &p: p_state->idents) {
cs_ident *i = p.second; ident *i = p.second;
cs_alias *a = i->get_alias(); alias *a = i->get_alias();
if (a) { if (a) {
a->get_value().force_none(); 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(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); p_state->destroy(p_state);
} }
cs_state::cs_state(cs_shared_state *s): state::state(internal_state *s):
p_state(s), p_owner(false) p_state(s), p_owner(false)
{} {}
LIBCUBESCRIPT_EXPORT cs_state cs_state::new_thread() { LIBCUBESCRIPT_EXPORT state state::new_thread() {
return cs_state{p_state}; 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); auto hk = std::move(p_callhook);
p_callhook = std::move(func); p_callhook = std::move(func);
return hk; 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; return p_callhook;
} }
LIBCUBESCRIPT_EXPORT cs_hook_cb &cs_state::get_call_hook() { LIBCUBESCRIPT_EXPORT hook_func &state::get_call_hook() {
return p_callhook; return p_callhook;
} }
LIBCUBESCRIPT_EXPORT cs_vprint_cb cs_state::set_var_printer( LIBCUBESCRIPT_EXPORT var_print_func state::set_var_printer(
cs_vprint_cb func var_print_func func
) { ) {
auto fn = std::move(p_state->varprintf); auto fn = std::move(p_state->varprintf);
p_state->varprintf = std::move(func); p_state->varprintf = std::move(func);
return fn; 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; 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) { if (p_state->varprintf) {
p_state->varprintf(*this, v); 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); return p_state->alloc(ptr, os, ns);
} }
LIBCUBESCRIPT_EXPORT cs_ident *cs_state::add_ident( LIBCUBESCRIPT_EXPORT ident *state::add_ident(
cs_ident *id, cs_ident_impl *impl ident *id, ident_impl *impl
) { ) {
if (!id) { if (!id) {
return nullptr; return nullptr;
} }
id->p_impl = impl; id->p_impl = impl;
p_state->idents[id->get_name()] = id; 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); p_state->identmap.push_back(id);
return p_state->identmap.back(); 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 std::string_view name, int flags
) { ) {
cs_ident *id = get_ident(name); ident *id = get_ident(name);
if (!id) { if (!id) {
if (!is_valid_name(name)) { if (!is_valid_name(name)) {
throw cs_error{ throw error{
*this, "number %s is not a valid identifier name", name.data() *this, "number %s is not a valid identifier name", name.data()
}; };
} }
auto *inst = p_state->create<cs_alias_impl>( auto *inst = p_state->create<alias_impl>(
*this, cs_strref{p_state, name}, flags *this, string_ref{p_state, name}, flags
); );
id = add_ident(inst, inst); id = add_ident(inst, inst);
} }
return id; 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()) { switch (v.get_type()) {
case cs_value_type::IDENT: case value_type::IDENT:
return v.get_ident(); return v.get_ident();
case cs_value_type::STRING: { case value_type::STRING: {
cs_ident *id = new_ident(v.get_str()); ident *id = new_ident(v.get_str());
v.set_ident(id); v.set_ident(id);
return id; return id;
} }
@ -288,7 +288,7 @@ LIBCUBESCRIPT_EXPORT cs_ident *cs_state::force_ident(cs_value &v) {
return p_state->identmap[DummyIdx]; 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); auto id = p_state->idents.find(name);
if (id != p_state->idents.end()) { if (id != p_state->idents.end()) {
return id->second; return id->second;
@ -296,88 +296,89 @@ LIBCUBESCRIPT_EXPORT cs_ident *cs_state::get_ident(std::string_view name) {
return nullptr; 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); auto id = get_ident(name);
if (!id || !id->is_alias()) { if (!id || !id->is_alias()) {
return nullptr; 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(); return p_state->idents.find(name) != p_state->idents.end();
} }
LIBCUBESCRIPT_EXPORT std::span<cs_ident *> cs_state::get_idents() { LIBCUBESCRIPT_EXPORT std::span<ident *> state::get_idents() {
return std::span<cs_ident *>{ return std::span<ident *>{
p_state->identmap.data(), p_state->identmap.data(),
p_state->identmap.size() p_state->identmap.size()
}; };
} }
LIBCUBESCRIPT_EXPORT std::span<cs_ident const *> cs_state::get_idents() const { LIBCUBESCRIPT_EXPORT std::span<ident const *> state::get_idents() const {
auto ptr = const_cast<cs_ident const **>(p_state->identmap.data()); auto ptr = const_cast<ident const **>(p_state->identmap.data());
return std::span<cs_ident const *>{ptr, p_state->identmap.size()}; return std::span<ident const *>{ptr, p_state->identmap.size()};
} }
LIBCUBESCRIPT_EXPORT cs_ivar *cs_state::new_ivar( LIBCUBESCRIPT_EXPORT integer_var *state::new_ivar(
std::string_view n, cs_int m, cs_int x, cs_int v, cs_var_cb f, int flags 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>( auto *iv = p_state->create<ivar_impl>(
cs_strref{p_state, n}, m, x, v, std::move(f), flags string_ref{p_state, n}, m, x, v, std::move(f), flags
); );
add_ident(iv, iv); add_ident(iv, iv);
return iv; return iv;
} }
LIBCUBESCRIPT_EXPORT cs_fvar *cs_state::new_fvar( LIBCUBESCRIPT_EXPORT float_var *state::new_fvar(
std::string_view n, cs_float m, cs_float x, cs_float v, std::string_view n, float_type m, float_type x, float_type v,
cs_var_cb f, int flags var_cb_func f, int flags
) { ) {
auto *fv = p_state->create<cs_fvar_impl>( auto *fv = p_state->create<fvar_impl>(
cs_strref{p_state, n}, m, x, v, std::move(f), flags string_ref{p_state, n}, m, x, v, std::move(f), flags
); );
add_ident(fv, fv); add_ident(fv, fv);
return fv; return fv;
} }
LIBCUBESCRIPT_EXPORT cs_svar *cs_state::new_svar( LIBCUBESCRIPT_EXPORT string_var *state::new_svar(
std::string_view n, std::string_view v, cs_var_cb f, int flags std::string_view n, std::string_view v, var_cb_func f, int flags
) { ) {
auto *sv = p_state->create<cs_svar_impl>( auto *sv = p_state->create<svar_impl>(
cs_strref{p_state, n}, cs_strref{p_state, v}, string_ref{p_state, n}, string_ref{p_state, v},
cs_strref{p_state, ""}, std::move(f), flags string_ref{p_state, ""}, std::move(f), flags
); );
add_ident(sv, sv); add_ident(sv, sv);
return sv; return sv;
} }
LIBCUBESCRIPT_EXPORT void cs_state::reset_var(std::string_view name) { LIBCUBESCRIPT_EXPORT void state::reset_var(std::string_view name) {
cs_ident *id = get_ident(name); ident *id = get_ident(name);
if (!id) { 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) { if (id->get_flags() & IDENT_FLAG_READONLY) {
throw cs_error{*this, "variable %s is read only", name.data()}; throw error{*this, "variable %s is read only", name.data()};
} }
clear_override(*id); clear_override(*id);
} }
LIBCUBESCRIPT_EXPORT void cs_state::touch_var(std::string_view name) { LIBCUBESCRIPT_EXPORT void state::touch_var(std::string_view name) {
cs_ident *id = get_ident(name); ident *id = get_ident(name);
if (id && id->is_var()) { 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( LIBCUBESCRIPT_EXPORT void state::set_alias(
std::string_view name, cs_value v std::string_view name, any_value v
) { ) {
cs_ident *id = get_ident(name); ident *id = get_ident(name);
if (id) { if (id) {
switch (id->get_type()) { switch (id->get_type()) {
case cs_ident_type::ALIAS: { case ident_type::ALIAS: {
cs_alias_impl *a = static_cast<cs_alias_impl *>(id); alias_impl *a = static_cast<alias_impl *>(id);
if (a->get_index() < MaxArguments) { if (a->get_index() < MaxArguments) {
a->set_arg(*this, v); a->set_arg(*this, v);
} else { } else {
@ -385,33 +386,33 @@ LIBCUBESCRIPT_EXPORT void cs_state::set_alias(
} }
return; return;
} }
case cs_ident_type::IVAR: case ident_type::IVAR:
set_var_int_checked(static_cast<cs_ivar *>(id), v.get_int()); set_var_int_checked(static_cast<integer_var *>(id), v.get_int());
break; break;
case cs_ident_type::FVAR: case ident_type::FVAR:
set_var_float_checked(static_cast<cs_fvar *>(id), v.get_float()); set_var_float_checked(static_cast<float_var *>(id), v.get_float());
break; break;
case cs_ident_type::SVAR: case ident_type::SVAR:
set_var_str_checked(static_cast<cs_svar *>(id), v.get_str()); set_var_str_checked(static_cast<string_var *>(id), v.get_str());
break; break;
default: default:
throw cs_error{ throw error{
*this, "cannot redefine builtin %s with an alias", *this, "cannot redefine builtin %s with an alias",
id->get_name().data() id->get_name().data()
}; };
} }
} else if (!is_valid_name(name)) { } 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 { } else {
auto *a = p_state->create<cs_alias_impl>( auto *a = p_state->create<alias_impl>(
*this, cs_strref{p_state, name}, std::move(v), identflags *this, string_ref{p_state, name}, std::move(v), identflags
); );
add_ident(a, a); add_ident(a, a);
} }
} }
LIBCUBESCRIPT_EXPORT cs_command *cs_state::new_command( LIBCUBESCRIPT_EXPORT command *state::new_command(
std::string_view name, std::string_view args, cs_command_cb func std::string_view name, std::string_view args, command_func func
) { ) {
int nargs = 0; int nargs = 0;
for (auto fmt = args.begin(); fmt != args.end(); ++fmt) { for (auto fmt = args.begin(); fmt != args.end(); ++fmt) {
@ -459,39 +460,39 @@ LIBCUBESCRIPT_EXPORT cs_command *cs_state::new_command(
return nullptr; return nullptr;
} }
} }
auto *cmd = p_state->create<cs_command_impl>( auto *cmd = p_state->create<command_impl>(
cs_strref{p_state, name}, cs_strref{p_state, args}, nargs, string_ref{p_state, name}, string_ref{p_state, args}, nargs,
std::move(func) std::move(func)
); );
add_ident(cmd, cmd); add_ident(cmd, cmd);
return cmd; return cmd;
} }
LIBCUBESCRIPT_EXPORT void cs_state::clear_override(cs_ident &id) { LIBCUBESCRIPT_EXPORT void state::clear_override(ident &id) {
if (!(id.get_flags() & CS_IDF_OVERRIDDEN)) { if (!(id.get_flags() & IDENT_FLAG_OVERRIDDEN)) {
return; return;
} }
switch (id.get_type()) { switch (id.get_type()) {
case cs_ident_type::ALIAS: { case ident_type::ALIAS: {
cs_alias_impl &a = static_cast<cs_alias_impl &>(id); alias_impl &a = static_cast<alias_impl &>(id);
a.clean_code(); a.clean_code();
a.get_value().set_str(""); a.get_value().set_str("");
break; break;
} }
case cs_ident_type::IVAR: { case ident_type::IVAR: {
cs_ivar_impl &iv = static_cast<cs_ivar_impl &>(id); ivar_impl &iv = static_cast<ivar_impl &>(id);
iv.set_value(iv.p_overrideval); iv.set_value(iv.p_overrideval);
iv.changed(*this); iv.changed(*this);
break; break;
} }
case cs_ident_type::FVAR: { case ident_type::FVAR: {
cs_fvar_impl &fv = static_cast<cs_fvar_impl &>(id); fvar_impl &fv = static_cast<fvar_impl &>(id);
fv.set_value(fv.p_overrideval); fv.set_value(fv.p_overrideval);
fv.changed(*this); fv.changed(*this);
break; break;
} }
case cs_ident_type::SVAR: { case ident_type::SVAR: {
cs_svar_impl &sv = static_cast<cs_svar_impl &>(id); svar_impl &sv = static_cast<svar_impl &>(id);
sv.set_value(sv.p_overrideval); sv.set_value(sv.p_overrideval);
sv.changed(*this); sv.changed(*this);
break; break;
@ -499,44 +500,44 @@ LIBCUBESCRIPT_EXPORT void cs_state::clear_override(cs_ident &id) {
default: default:
break; 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) { for (auto &p: p_state->idents) {
clear_override(*(p.second)); clear_override(*(p.second));
} }
} }
template<typename SF> template<typename SF>
inline void cs_override_var(cs_state &cs, cs_var *v, int &vflags, SF sf) { inline void override_var(state &cs, global_var *v, int &vflags, SF sf) {
if ((cs.identflags & CS_IDF_OVERRIDDEN) || (vflags & CS_IDF_OVERRIDE)) { if ((cs.identflags & IDENT_FLAG_OVERRIDDEN) || (vflags & IDENT_FLAG_OVERRIDE)) {
if (vflags & CS_IDF_PERSIST) { if (vflags & IDENT_FLAG_PERSIST) {
throw cs_error{ throw error{
cs, "cannot override persistent variable '%s'", cs, "cannot override persistent variable '%s'",
v->get_name().data() v->get_name().data()
}; };
} }
if (!(vflags & CS_IDF_OVERRIDDEN)) { if (!(vflags & IDENT_FLAG_OVERRIDDEN)) {
sf(); sf();
vflags |= CS_IDF_OVERRIDDEN; vflags |= IDENT_FLAG_OVERRIDDEN;
} }
} else { } else {
if (vflags & CS_IDF_OVERRIDDEN) { if (vflags & IDENT_FLAG_OVERRIDDEN) {
vflags &= ~CS_IDF_OVERRIDDEN; vflags &= ~IDENT_FLAG_OVERRIDDEN;
} }
} }
} }
LIBCUBESCRIPT_EXPORT void cs_state::set_var_int( LIBCUBESCRIPT_EXPORT void state::set_var_int(
std::string_view name, cs_int v, bool dofunc, bool doclamp 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()) { if (!id || id->is_ivar()) {
return; return;
} }
cs_ivar_impl *iv = static_cast<cs_ivar_impl *>(id); ivar_impl *iv = static_cast<ivar_impl *>(id);
cs_override_var( override_var(
*this, iv, iv->p_flags, *this, iv, iv->p_flags,
[&iv]() { iv->p_overrideval = iv->get_value(); } [&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( LIBCUBESCRIPT_EXPORT void state::set_var_float(
std::string_view name, cs_float v, bool dofunc, bool doclamp 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()) { if (!id || id->is_fvar()) {
return; return;
} }
cs_fvar_impl *fv = static_cast<cs_fvar_impl *>(id); fvar_impl *fv = static_cast<fvar_impl *>(id);
cs_override_var( override_var(
*this, fv, fv->p_flags, *this, fv, fv->p_flags,
[&fv]() { fv->p_overrideval = fv->get_value(); } [&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 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()) { if (!id || id->is_svar()) {
return; return;
} }
cs_svar_impl *sv = static_cast<cs_svar_impl *>(id); svar_impl *sv = static_cast<svar_impl *>(id);
cs_override_var( override_var(
*this, sv, sv->p_flags, *this, sv, sv->p_flags,
[&sv]() { sv->p_overrideval = sv->get_value(); } [&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) { if (dofunc) {
sv->changed(*this); sv->changed(*this);
} }
} }
LIBCUBESCRIPT_EXPORT std::optional<cs_int> LIBCUBESCRIPT_EXPORT std::optional<integer_type>
cs_state::get_var_int(std::string_view name) { state::get_var_int(std::string_view name) {
cs_ident *id = get_ident(name); ident *id = get_ident(name);
if (!id || id->is_ivar()) { if (!id || id->is_ivar()) {
return std::nullopt; 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> LIBCUBESCRIPT_EXPORT std::optional<float_type>
cs_state::get_var_float(std::string_view name) { state::get_var_float(std::string_view name) {
cs_ident *id = get_ident(name); ident *id = get_ident(name);
if (!id || id->is_fvar()) { if (!id || id->is_fvar()) {
return std::nullopt; 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> LIBCUBESCRIPT_EXPORT std::optional<string_ref>
cs_state::get_var_str(std::string_view name) { state::get_var_str(std::string_view name) {
cs_ident *id = get_ident(name); ident *id = get_ident(name);
if (!id || id->is_svar()) { if (!id || id->is_svar()) {
return std::nullopt; 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> LIBCUBESCRIPT_EXPORT std::optional<integer_type>
cs_state::get_var_min_int(std::string_view name) { state::get_var_min_int(std::string_view name) {
cs_ident *id = get_ident(name); ident *id = get_ident(name);
if (!id || id->is_ivar()) { if (!id || id->is_ivar()) {
return std::nullopt; 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> LIBCUBESCRIPT_EXPORT std::optional<integer_type>
cs_state::get_var_max_int(std::string_view name) { state::get_var_max_int(std::string_view name) {
cs_ident *id = get_ident(name); ident *id = get_ident(name);
if (!id || id->is_ivar()) { if (!id || id->is_ivar()) {
return std::nullopt; 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> LIBCUBESCRIPT_EXPORT std::optional<float_type>
cs_state::get_var_min_float(std::string_view name) { state::get_var_min_float(std::string_view name) {
cs_ident *id = get_ident(name); ident *id = get_ident(name);
if (!id || id->is_fvar()) { if (!id || id->is_fvar()) {
return std::nullopt; 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> LIBCUBESCRIPT_EXPORT std::optional<float_type>
cs_state::get_var_max_float(std::string_view name) { state::get_var_max_float(std::string_view name) {
cs_ident *id = get_ident(name); ident *id = get_ident(name);
if (!id || id->is_fvar()) { if (!id || id->is_fvar()) {
return std::nullopt; 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> LIBCUBESCRIPT_EXPORT std::optional<string_ref>
cs_state::get_alias_val(std::string_view name) { state::get_alias_val(std::string_view name) {
cs_alias *a = get_alias(name); alias *a = get_alias(name);
if (!a) { if (!a) {
return std::nullopt; return std::nullopt;
} }
@ -665,7 +666,7 @@ cs_state::get_alias_val(std::string_view name) {
return a->get_value().get_str(); 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()) { if (v < iv->get_val_min()) {
v = iv->get_val_min(); v = iv->get_val_min();
} else if (v > iv->get_val_max()) { } 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 { } else {
return v; return v;
} }
throw cs_error{ throw error{
cs, cs,
(iv->get_flags() & CS_IDF_HEX) (iv->get_flags() & IDENT_FLAG_HEX)
? ( ? (
(iv->get_val_min() <= 255) (iv->get_val_min() <= 255)
? "valid range for '%s' is %d..0x%X" ? "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) { LIBCUBESCRIPT_EXPORT void state::set_var_int_checked(
if (iv->get_flags() & CS_IDF_READONLY) { integer_var *iv, integer_type v
throw cs_error{ ) {
if (iv->get_flags() & IDENT_FLAG_READONLY) {
throw error{
*this, "variable '%s' is read only", iv->get_name().data() *this, "variable '%s' is read only", iv->get_name().data()
}; };
} }
cs_ivar_impl *ivp = static_cast<cs_ivar_impl *>(iv); ivar_impl *ivp = static_cast<ivar_impl *>(iv);
cs_override_var( override_var(
*this, iv, ivp->p_flags, *this, iv, ivp->p_flags,
[&ivp]() { ivp->p_overrideval = ivp->p_storage; } [&ivp]() { ivp->p_overrideval = ivp->p_storage; }
); );
if ((v < iv->get_val_min()) || (v > iv->get_val_max())) { 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); iv->set_value(v);
ivp->changed(*this); ivp->changed(*this);
} }
LIBCUBESCRIPT_EXPORT void cs_state::set_var_int_checked( LIBCUBESCRIPT_EXPORT void state::set_var_int_checked(
cs_ivar *iv, std::span<cs_value> args integer_var *iv, std::span<any_value> args
) { ) {
cs_int v = args[0].force_int(); integer_type v = args[0].force_int();
if ((iv->get_flags() & CS_IDF_HEX) && (args.size() > 1)) { if ((iv->get_flags() & IDENT_FLAG_HEX) && (args.size() > 1)) {
v = (v << 16) | (args[1].force_int() << 8); v = (v << 16) | (args[1].force_int() << 8);
if (args.size() > 2) { if (args.size() > 2) {
v |= args[2].force_int(); v |= args[2].force_int();
@ -717,7 +720,7 @@ LIBCUBESCRIPT_EXPORT void cs_state::set_var_int_checked(
set_var_int_checked(iv, v); 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()) { if (v < fv->get_val_min()) {
v = fv->get_val_min(); v = fv->get_val_min();
} else if (v > fv->get_val_max()) { } 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 { } else {
return v; return v;
} }
cs_value vmin{cs}, vmax{cs}; any_value vmin{cs}, vmax{cs};
vmin.set_float(fv->get_val_min()); vmin.set_float(fv->get_val_min());
vmax.set_float(fv->get_val_max()); vmax.set_float(fv->get_val_max());
throw cs_error{ throw error{
cs, "valid range for '%s' is %s..%s", fv->get_name().data(), cs, "valid range for '%s' is %s..%s", fv->get_name().data(),
vmin.force_str(), vmax.force_str() vmin.force_str(), vmax.force_str()
}; };
return v; return v;
} }
LIBCUBESCRIPT_EXPORT void cs_state::set_var_float_checked( LIBCUBESCRIPT_EXPORT void state::set_var_float_checked(
cs_fvar *fv, cs_float v float_var *fv, float_type v
) { ) {
if (fv->get_flags() & CS_IDF_READONLY) { if (fv->get_flags() & IDENT_FLAG_READONLY) {
throw cs_error{ throw error{
*this, "variable '%s' is read only", fv->get_name().data() *this, "variable '%s' is read only", fv->get_name().data()
}; };
} }
cs_fvar_impl *fvp = static_cast<cs_fvar_impl *>(fv); fvar_impl *fvp = static_cast<fvar_impl *>(fv);
cs_override_var( override_var(
*this, fv, fvp->p_flags, *this, fv, fvp->p_flags,
[&fvp]() { fvp->p_overrideval = fvp->p_storage; } [&fvp]() { fvp->p_overrideval = fvp->p_storage; }
); );
if ((v < fv->get_val_min()) || (v > fv->get_val_max())) { 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); fv->set_value(v);
fvp->changed(*this); fvp->changed(*this);
} }
LIBCUBESCRIPT_EXPORT void cs_state::set_var_str_checked( LIBCUBESCRIPT_EXPORT void state::set_var_str_checked(
cs_svar *sv, std::string_view v string_var *sv, std::string_view v
) { ) {
if (sv->get_flags() & CS_IDF_READONLY) { if (sv->get_flags() & IDENT_FLAG_READONLY) {
throw cs_error{ throw error{
*this, "variable '%s' is read only", sv->get_name().data() *this, "variable '%s' is read only", sv->get_name().data()
}; };
} }
cs_svar_impl *svp = static_cast<cs_svar_impl *>(sv); svar_impl *svp = static_cast<svar_impl *>(sv);
cs_override_var( override_var(
*this, sv, svp->p_flags, *this, sv, svp->p_flags,
[&svp]() { svp->p_overrideval = svp->p_storage; } [&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); svp->changed(*this);
} }
LIBCUBESCRIPT_EXPORT void cs_state::init_libs(int libs) { LIBCUBESCRIPT_EXPORT void state::init_libs(int libs) {
if (libs & CS_LIB_MATH) { if (libs & LIB_MATH) {
cs_init_lib_math(*this); init_lib_math(*this);
} }
if (libs & CS_LIB_STRING) { if (libs & LIB_STRING) {
cs_init_lib_string(*this); init_lib_string(*this);
} }
if (libs & CS_LIB_LIST) { if (libs & LIB_LIST) {
cs_init_lib_list(*this); init_lib_list(*this);
} }
} }

View File

@ -10,55 +10,55 @@
namespace cscript { namespace cscript {
struct cs_state; struct state;
struct cs_shared_state; struct internal_state;
struct cs_strman; struct string_pool;
template<typename T> template<typename T>
struct cs_allocator { struct std_allocator {
using value_type = T; using value_type = T;
inline cs_allocator(cs_shared_state *s); inline std_allocator(internal_state *s);
inline cs_allocator(cs_state &cs); inline std_allocator(state &cs);
template<typename U> 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 T *allocate(std::size_t n);
inline void deallocate(T *p, std::size_t n); inline void deallocate(T *p, std::size_t n);
template<typename U> template<typename U>
bool operator==(cs_allocator<U> const &a) { bool operator==(std_allocator<U> const &a) {
return state == a.state; return istate == a.istate;
} }
cs_shared_state *state; internal_state *istate;
}; };
struct cs_shared_state { struct internal_state {
using allocator_type = cs_allocator< using allocator_type = std_allocator<
std::pair<std::string_view const, cs_ident *> std::pair<std::string_view const, ident *>
>; >;
cs_alloc_cb allocf; alloc_func allocf;
void *aptr; void *aptr;
std::unordered_map< std::unordered_map<
std::string_view, cs_ident *, std::string_view, ident *,
std::hash<std::string_view>, std::hash<std::string_view>,
std::equal_to<std::string_view>, std::equal_to<std::string_view>,
allocator_type allocator_type
> idents; > idents;
std::vector<cs_ident *, cs_allocator<cs_ident *>> identmap; std::vector<ident *, std_allocator<ident *>> identmap;
cs_vprint_cb varprintf; var_print_func varprintf;
cs_strman *strman; string_pool *strman;
empty_block *empty; 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); 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; return cs.p_state;
} }
template<typename T> 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> 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> template<typename T>
inline T *cs_allocator<T>::allocate(std::size_t n) { inline T *std_allocator<T>::allocate(std::size_t n) {
return static_cast<T *>(state->alloc(nullptr, 0, n * sizeof(T))); return static_cast<T *>(istate->alloc(nullptr, 0, n * sizeof(T)));
} }
template<typename T> template<typename T>
inline void cs_allocator<T>::deallocate(T *p, std::size_t n) { inline void std_allocator<T>::deallocate(T *p, std::size_t n) {
state->alloc(p, n, 0); istate->alloc(p, n, 0);
} }
} /* namespace cscript */ } /* namespace cscript */

View File

@ -33,15 +33,15 @@ inline void call_with_cleanup(F1 &&dof, F2 &&clf) {
/* a simple static array with elements constructed using ctor args */ /* a simple static array with elements constructed using ctor args */
template<typename T, std::size_t N> template<typename T, std::size_t N>
struct cs_valarray { struct valarray {
template<typename ...A> template<typename ...A>
cs_valarray(A &&...args) { valarray(A &&...args) {
for (std::size_t i = 0; i < N; ++i) { for (std::size_t i = 0; i < N; ++i) {
new (&stor[i]) T{std::forward<A>(args)...}; new (&stor[i]) T{std::forward<A>(args)...};
} }
} }
~cs_valarray() { ~valarray() {
for (std::size_t i = 0; i < N; ++i) { for (std::size_t i = 0; i < N; ++i) {
reinterpret_cast<T *>(&stor[i])->~T(); reinterpret_cast<T *>(&stor[i])->~T();
} }
@ -57,11 +57,11 @@ struct cs_valarray {
/* a value buffer */ /* a value buffer */
template<typename T> template<typename T>
struct cs_valbuf { struct valbuf {
cs_valbuf() = delete; valbuf() = delete;
cs_valbuf(cs_shared_state *cs): buf{cs_allocator<T>{cs}} {} valbuf(internal_state *cs): buf{std_allocator<T>{cs}} {}
cs_valbuf(cs_state &cs): buf{cs_allocator<T>{cs}} {} valbuf(state &cs): buf{std_allocator<T>{cs}} {}
using size_type = std::size_t; using size_type = std::size_t;
using value_type = T; using value_type = T;
@ -94,17 +94,17 @@ struct cs_valbuf {
T *data() { return &buf[0]; } T *data() { return &buf[0]; }
T const *data() const { 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 */ /* specialization of value buffer for bytes */
struct cs_charbuf: cs_valbuf<char> { struct charbuf: valbuf<char> {
cs_charbuf(cs_shared_state *cs): cs_valbuf<char>{cs} {} charbuf(internal_state *cs): valbuf<char>{cs} {}
cs_charbuf(cs_state &cs): cs_valbuf<char>{cs} {} charbuf(state &cs): valbuf<char>{cs} {}
void append(char const *beg, char const *end) { 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) { void append(std::string_view v) {

View File

@ -4,18 +4,18 @@
namespace cscript { namespace cscript {
struct cs_strref_state { struct string_ref_state {
std::size_t length; std::size_t length;
std::size_t refcount; std::size_t refcount;
}; };
inline cs_strref_state *get_ref_state(char const *ptr) { inline string_ref_state *get_ref_state(char const *ptr) {
return const_cast<cs_strref_state *>( return const_cast<string_ref_state *>(
reinterpret_cast<cs_strref_state const *>(ptr) reinterpret_cast<string_ref_state const *>(ptr)
) - 1; ) - 1;
} }
char const *cs_strman::add(std::string_view str) { char const *string_pool::add(std::string_view str) {
auto it = counts.find(str); auto it = counts.find(str);
/* already present: just increment ref */ /* already present: just increment ref */
if (it != counts.end()) { if (it != counts.end()) {
@ -36,13 +36,13 @@ char const *cs_strman::add(std::string_view str) {
return strp; return strp;
} }
char const *cs_strman::ref(char const *ptr) { char const *string_pool::ref(char const *ptr) {
auto *ss = get_ref_state(ptr); auto *ss = get_ref_state(ptr);
++ss->refcount; ++ss->refcount;
return ptr; return ptr;
} }
cs_strref cs_strman::steal(char *ptr) { string_ref string_pool::steal(char *ptr) {
auto *ss = get_ref_state(ptr); auto *ss = get_ref_state(ptr);
auto sr = std::string_view{ptr, ss->length}; auto sr = std::string_view{ptr, ss->length};
/* much like add(), but we already have memory */ /* much like add(), but we already have memory */
@ -51,16 +51,16 @@ cs_strref cs_strman::steal(char *ptr) {
auto *st = it->second; auto *st = it->second;
if (st) { if (st) {
/* the buffer is superfluous now */ /* the buffer is superfluous now */
cstate->alloc(ss, ss->length + sizeof(cs_strref_state) + 1, 0); cstate->alloc(ss, ss->length + sizeof(string_ref_state) + 1, 0);
return cs_strref{reinterpret_cast<char const *>(st + 1), cstate}; 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); 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); auto *ss = get_ref_state(ptr);
if (!--ss->refcount) { if (!--ss->refcount) {
/* refcount zero, so ditch it /* refcount zero, so ditch it
@ -70,16 +70,16 @@ void cs_strman::unref(char const *ptr) {
auto it = counts.find(sr); auto it = counts.find(sr);
if (it == counts.end()) { if (it == counts.end()) {
/* internal error: this should *never* happen */ /* internal error: this should *never* happen */
throw cs_internal_error{"no refcount"}; throw internal_error{"no refcount"};
} }
/* we're freeing the key */ /* we're freeing the key */
counts.erase(it); counts.erase(it);
/* dealloc */ /* 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); auto it = counts.find(str);
if (it == counts.end()) { if (it == counts.end()) {
return nullptr; return nullptr;
@ -87,18 +87,18 @@ char const *cs_strman::find(std::string_view str) const {
return reinterpret_cast<char const *>(it->second + 1); 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); auto *ss = get_ref_state(ptr);
return std::string_view{ptr, ss->length}; return std::string_view{ptr, ss->length};
} }
char *cs_strman::alloc_buf(std::size_t len) const { char *string_pool::alloc_buf(std::size_t len) const {
auto mem = cstate->alloc(nullptr, 0, len + sizeof(cs_strref_state) + 1); auto mem = cstate->alloc(nullptr, 0, len + sizeof(string_ref_state) + 1);
if (!mem) { if (!mem) {
throw cs_internal_error{"allocation failed"}; throw internal_error{"allocation failed"};
} }
/* write length and initial refcount */ /* 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->length = len;
sst->refcount = 1; sst->refcount = 1;
/* pre-terminate */ /* pre-terminate */
@ -112,48 +112,48 @@ char *cs_strman::alloc_buf(std::size_t len) const {
/* strref */ /* strref */
LIBCUBESCRIPT_EXPORT cs_strref::cs_strref( LIBCUBESCRIPT_EXPORT string_ref::string_ref(
cs_shared_state *cs, std::string_view str internal_state *cs, std::string_view str
): p_state{cs} ): p_state{cs}
{ {
p_str = cs->strman->add(str); 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_state{cs.p_state}
{ {
p_str = p_state->strman->add(str); 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{ref.p_state}, p_str{ref.p_str}
{ {
p_state->strman->ref(p_str); p_state->strman->ref(p_str);
} }
/* this can be used by friends to do quick cs_strref creation */ /* this can be used by friends to do quick string_ref creation */
LIBCUBESCRIPT_EXPORT cs_strref::cs_strref(char const *p, cs_shared_state *cs): LIBCUBESCRIPT_EXPORT string_ref::string_ref(char const *p, internal_state *cs):
p_state{cs} p_state{cs}
{ {
p_str = p_state->strman->ref(p); 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); 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_str = ref.p_str;
p_state = ref.p_state; p_state = ref.p_state;
p_state->strman->ref(p_str); p_state->strman->ref(p_str);
return *this; 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); 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; return p_str == s.p_str;
} }

View File

@ -11,7 +11,7 @@
namespace cscript { namespace cscript {
struct cs_strref_state; struct string_ref_state;
/* string manager /* string manager
* *
@ -29,19 +29,19 @@ struct cs_strref_state;
* for now we don't bother... * for now we don't bother...
*/ */
struct cs_strman { struct string_pool {
using allocator_type = cs_allocator< using allocator_type = std_allocator<
std::pair<std::string_view const, cs_strref_state *> std::pair<std::string_view const, string_ref_state *>
>; >;
cs_strman() = delete; string_pool() = delete;
cs_strman(cs_shared_state *cs): cstate{cs}, counts{allocator_type{cs}} {} string_pool(internal_state *cs): cstate{cs}, counts{allocator_type{cs}} {}
~cs_strman() {} ~string_pool() {}
cs_strman(cs_strman const &) = delete; string_pool(string_pool const &) = delete;
cs_strman(cs_strman &&) = delete; string_pool(string_pool &&) = delete;
cs_strman &operator=(cs_strman const &) = delete; string_pool &operator=(string_pool const &) = delete;
cs_strman &operator=(cs_strman &&) = delete; string_pool &operator=(string_pool &&) = delete;
/* adds a string into the manager using any source, and returns a managed /* 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 * 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 /* 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() * 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 /* decrements the reference count and removes it from the system if
* that reaches zero; likewise, only safe with pointers that are managed * 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; char *alloc_buf(std::size_t len) const;
cs_shared_state *cstate; internal_state *cstate;
std::unordered_map< std::unordered_map<
std::string_view, cs_strref_state *, std::string_view, string_ref_state *,
std::hash<std::string_view>, std::hash<std::string_view>,
std::equal_to<std::string_view>, std::equal_to<std::string_view>,
allocator_type allocator_type

View File

@ -7,12 +7,12 @@
namespace cscript { 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); 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) { if (n > 32) {
buf.reserve(n + 1); 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)) { if ((nn > n) || (nn <= 0)) {
n = -1; n = -1;
} else { } else {
@ -20,26 +20,26 @@ static std::string_view intstr(cs_int v, cs_charbuf &buf) {
} }
} }
if (n <= 0) { if (n <= 0) {
throw cs_internal_error{"format error"}; throw internal_error{"format error"};
} }
return std::string_view{buf.data(), std::size_t(n)}; 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); buf.reserve(32);
int n; int n;
if (v == std::floor(v)) { 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 { } else {
n = snprintf(buf.data(), 32, CS_FLOAT_FORMAT, v); n = snprintf(buf.data(), 32, FLOAT_FORMAT, v);
} }
if (n > 32) { if (n > 32) {
buf.reserve(n + 1); buf.reserve(n + 1);
int nn; int nn;
if (v == std::floor(v)) { 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 { } 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)) { if ((nn > n) || (nn <= 0)) {
n = -1; n = -1;
@ -48,14 +48,14 @@ static std::string_view floatstr(cs_float v, cs_charbuf &buf) {
} }
} }
if (n <= 0) { if (n <= 0) {
throw cs_internal_error{"format error"}; throw internal_error{"format error"};
} }
return std::string_view{buf.data(), std::size_t(n)}; return std::string_view{buf.data(), std::size_t(n)};
} }
template<typename T> template<typename T>
struct stor_priv_t { struct stor_priv_t {
cs_shared_state *state; internal_state *state;
T val; T val;
}; };
@ -66,12 +66,12 @@ static inline T &csv_get(U &stor) {
} }
template<typename T> 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) { switch (tv) {
case cs_value_type::STRING: case value_type::STRING:
reinterpret_cast<cs_strref *>(&stor)->~cs_strref(); reinterpret_cast<string_ref *>(&stor)->~string_ref();
break; break;
case cs_value_type::CODE: { case value_type::CODE: {
bcode_unref(csv_get<uint32_t *>(stor)); bcode_unref(csv_get<uint32_t *>(stor));
break; 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): any_value::any_value(internal_state &st):
p_stor(), p_type(cs_value_type::NONE) p_stor(), p_type(value_type::NONE)
{ {
reinterpret_cast<stor_priv_t<void *> *>(&p_stor)->state = &st; reinterpret_cast<stor_priv_t<void *> *>(&p_stor)->state = &st;
} }
cs_value::~cs_value() { any_value::~any_value() {
csv_cleanup(p_type, p_stor); 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; *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); *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); csv_cleanup(p_type, p_stor);
p_type = cs_value_type::NONE; p_type = value_type::NONE;
switch (v.get_type()) { switch (v.get_type()) {
case cs_value_type::INT: case value_type::INT:
case cs_value_type::FLOAT: case value_type::FLOAT:
case cs_value_type::IDENT: case value_type::IDENT:
p_type = v.p_type; p_type = v.p_type;
p_stor = v.p_stor; p_stor = v.p_stor;
break; break;
case cs_value_type::STRING: case value_type::STRING:
p_type = cs_value_type::STRING; p_type = value_type::STRING;
new (&p_stor) cs_strref{ new (&p_stor) string_ref{
*reinterpret_cast<cs_strref const *>(&v.p_stor) *reinterpret_cast<string_ref const *>(&v.p_stor)
}; };
break; break;
case cs_value_type::CODE: case value_type::CODE:
set_code(v.get_code()); set_code(v.get_code());
break; break;
default: default:
@ -125,78 +125,78 @@ cs_value &cs_value::operator=(cs_value const &v) {
return *this; return *this;
} }
cs_value &cs_value::operator=(cs_value &&v) { any_value &any_value::operator=(any_value &&v) {
*this = v; *this = v;
v.set_none(); v.set_none();
return *this; return *this;
} }
cs_value_type cs_value::get_type() const { value_type any_value::get_type() const {
return p_type; 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); csv_cleanup(p_type, p_stor);
p_type = cs_value_type::INT; p_type = value_type::INT;
csv_get<cs_int>(p_stor) = val; 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); csv_cleanup(p_type, p_stor);
p_type = cs_value_type::FLOAT; p_type = value_type::FLOAT;
csv_get<cs_float>(p_stor) = val; 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); csv_cleanup(p_type, p_stor);
new (&p_stor) cs_strref{state(), val}; new (&p_stor) string_ref{get_state(), val};
p_type = cs_value_type::STRING; 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); csv_cleanup(p_type, p_stor);
new (&p_stor) cs_strref{val}; new (&p_stor) string_ref{val};
p_type = cs_value_type::STRING; p_type = value_type::STRING;
} }
void cs_value::set_none() { void any_value::set_none() {
csv_cleanup(p_type, p_stor); 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); csv_cleanup(p_type, p_stor);
p_type = cs_value_type::CODE; p_type = value_type::CODE;
bcode_ref(val->get_raw()); bcode_addref(val->get_raw());
csv_get<cs_bcode *>(p_stor) = val; 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); csv_cleanup(p_type, p_stor);
p_type = cs_value_type::IDENT; p_type = value_type::IDENT;
csv_get<cs_ident *>(p_stor) = val; csv_get<ident *>(p_stor) = val;
} }
void cs_value::force_none() { void any_value::force_none() {
if (get_type() == cs_value_type::NONE) { if (get_type() == value_type::NONE) {
return; return;
} }
set_none(); set_none();
} }
cs_float cs_value::force_float() { float_type any_value::force_float() {
cs_float rf = 0.0f; float_type rf = 0.0f;
switch (get_type()) { switch (get_type()) {
case cs_value_type::INT: case value_type::INT:
rf = csv_get<cs_int>(p_stor); rf = csv_get<integer_type>(p_stor);
break; break;
case cs_value_type::STRING: case value_type::STRING:
rf = parse_float( rf = parse_float(
*reinterpret_cast<cs_strref const *>(&p_stor) *reinterpret_cast<string_ref const *>(&p_stor)
); );
break; break;
case cs_value_type::FLOAT: case value_type::FLOAT:
return csv_get<cs_float>(p_stor); return csv_get<float_type>(p_stor);
default: default:
break; break;
} }
@ -204,19 +204,19 @@ cs_float cs_value::force_float() {
return rf; return rf;
} }
cs_int cs_value::force_int() { integer_type any_value::force_int() {
cs_int ri = 0; integer_type ri = 0;
switch (get_type()) { switch (get_type()) {
case cs_value_type::FLOAT: case value_type::FLOAT:
ri = csv_get<cs_float>(p_stor); ri = csv_get<float_type>(p_stor);
break; break;
case cs_value_type::STRING: case value_type::STRING:
ri = parse_int( ri = parse_int(
*reinterpret_cast<cs_strref const *>(&p_stor) *reinterpret_cast<string_ref const *>(&p_stor)
); );
break; break;
case cs_value_type::INT: case value_type::INT:
return csv_get<cs_int>(p_stor); return csv_get<integer_type>(p_stor);
default: default:
break; break;
} }
@ -224,35 +224,35 @@ cs_int cs_value::force_int() {
return ri; return ri;
} }
std::string_view cs_value::force_str() { std::string_view any_value::force_str() {
cs_charbuf rs{state()}; charbuf rs{get_state()};
std::string_view str; std::string_view str;
switch (get_type()) { switch (get_type()) {
case cs_value_type::FLOAT: case value_type::FLOAT:
str = floatstr(csv_get<cs_float>(p_stor), rs); str = floatstr(csv_get<float_type>(p_stor), rs);
break; break;
case cs_value_type::INT: case value_type::INT:
str = intstr(csv_get<cs_int>(p_stor), rs); str = intstr(csv_get<integer_type>(p_stor), rs);
break; break;
case cs_value_type::STRING: case value_type::STRING:
return *reinterpret_cast<cs_strref const *>(&p_stor); return *reinterpret_cast<string_ref const *>(&p_stor);
default: default:
str = rs.str(); str = rs.str();
break; break;
} }
set_str(str); 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()) { switch (get_type()) {
case cs_value_type::FLOAT: case value_type::FLOAT:
return cs_int(csv_get<cs_float>(p_stor)); return integer_type(csv_get<float_type>(p_stor));
case cs_value_type::INT: case value_type::INT:
return csv_get<cs_int>(p_stor); return csv_get<integer_type>(p_stor);
case cs_value_type::STRING: case value_type::STRING:
return parse_int( return parse_int(
*reinterpret_cast<cs_strref const *>(&p_stor) *reinterpret_cast<string_ref const *>(&p_stor)
); );
default: default:
break; break;
@ -260,15 +260,15 @@ cs_int cs_value::get_int() const {
return 0; return 0;
} }
cs_float cs_value::get_float() const { float_type any_value::get_float() const {
switch (get_type()) { switch (get_type()) {
case cs_value_type::FLOAT: case value_type::FLOAT:
return csv_get<cs_float>(p_stor); return csv_get<float_type>(p_stor);
case cs_value_type::INT: case value_type::INT:
return cs_float(csv_get<cs_int>(p_stor)); return float_type(csv_get<integer_type>(p_stor));
case cs_value_type::STRING: case value_type::STRING:
return parse_float( return parse_float(
*reinterpret_cast<cs_strref const *>(&p_stor) *reinterpret_cast<string_ref const *>(&p_stor)
); );
default: default:
break; break;
@ -276,48 +276,52 @@ cs_float cs_value::get_float() const {
return 0.0f; return 0.0f;
} }
cs_bcode *cs_value::get_code() const { bcode *any_value::get_code() const {
if (get_type() != cs_value_type::CODE) { if (get_type() != value_type::CODE) {
return nullptr; return nullptr;
} }
return csv_get<cs_bcode *>(p_stor); return csv_get<bcode *>(p_stor);
} }
cs_ident *cs_value::get_ident() const { ident *any_value::get_ident() const {
if (get_type() != cs_value_type::IDENT) { if (get_type() != value_type::IDENT) {
return nullptr; 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()) { switch (get_type()) {
case cs_value_type::STRING: case value_type::STRING:
return *reinterpret_cast<cs_strref const *>(&p_stor); return *reinterpret_cast<string_ref const *>(&p_stor);
case cs_value_type::INT: { case value_type::INT: {
cs_charbuf rs{state()}; charbuf rs{get_state()};
return cs_strref{state(), intstr(csv_get<cs_int>(p_stor), rs)}; return string_ref{
get_state(), intstr(csv_get<integer_type>(p_stor), rs)
};
} }
case cs_value_type::FLOAT: { case value_type::FLOAT: {
cs_charbuf rs{state()}; charbuf rs{get_state()};
return cs_strref{state(), floatstr(csv_get<cs_float>(p_stor), rs)}; return string_ref{
get_state(), floatstr(csv_get<float_type>(p_stor), rs)
};
} }
default: default:
break; 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()) { switch (get_type()) {
case cs_value_type::STRING: case value_type::STRING:
r = *this; r = *this;
break; break;
case cs_value_type::INT: case value_type::INT:
r.set_int(csv_get<cs_int>(p_stor)); r.set_int(csv_get<integer_type>(p_stor));
break; break;
case cs_value_type::FLOAT: case value_type::FLOAT:
r.set_float(csv_get<cs_float>(p_stor)); r.set_float(csv_get<float_type>(p_stor));
break; break;
default: default:
r.set_none(); 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) { if (!code) {
return true; 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 { bool any_value::code_is_empty() const {
if (get_type() != cs_value_type::CODE) { if (get_type() != value_type::CODE) {
return true; 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) { bool any_value::get_bool() const {
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 {
switch (get_type()) { switch (get_type()) {
case cs_value_type::FLOAT: case value_type::FLOAT:
return csv_get<cs_float>(p_stor) != 0; return csv_get<float_type>(p_stor) != 0;
case cs_value_type::INT: case value_type::INT:
return csv_get<cs_int>(p_stor) != 0; return csv_get<integer_type>(p_stor) != 0;
case cs_value_type::STRING: case value_type::STRING: {
return cs_get_bool( std::string_view s = *reinterpret_cast<string_ref const *>(&p_stor);
*reinterpret_cast<cs_strref 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: default:
return false; return false;
} }
@ -373,74 +373,74 @@ bool cs_value::get_bool() const {
/* stacked value for easy stack management */ /* stacked value for easy stack management */
cs_stacked_value::cs_stacked_value(cs_state &cs, cs_ident *id): stacked_value::stacked_value(state &cs, ident *id):
cs_value(cs), p_a(nullptr), p_stack{cs}, p_pushed(false) any_value(cs), p_a(nullptr), p_stack{cs}, p_pushed(false)
{ {
set_alias(id); set_alias(id);
} }
cs_stacked_value::~cs_stacked_value() { stacked_value::~stacked_value() {
pop(); 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) { stacked_value &stacked_value::operator=(any_value const &v) {
*static_cast<cs_value *>(this) = v; *static_cast<any_value *>(this) = v;
return *this; return *this;
} }
cs_stacked_value &cs_stacked_value::operator=(cs_value &&v) { stacked_value &stacked_value::operator=(any_value &&v) {
*static_cast<cs_value *>(this) = std::move(v); *static_cast<any_value *>(this) = std::move(v);
return *this; return *this;
} }
bool cs_stacked_value::set_alias(cs_ident *id) { bool stacked_value::set_alias(ident *id) {
if (!id || !id->is_alias()) { if (!id || !id->is_alias()) {
return false; return false;
} }
p_a = static_cast<cs_alias *>(id); p_a = static_cast<alias *>(id);
return true; return true;
} }
cs_alias *cs_stacked_value::get_alias() const { alias *stacked_value::get_alias() const {
return p_a; return p_a;
} }
bool cs_stacked_value::has_alias() const { bool stacked_value::has_alias() const {
return p_a != nullptr; return p_a != nullptr;
} }
bool cs_stacked_value::push() { bool stacked_value::push() {
if (!p_a) { if (!p_a) {
return false; 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; p_pushed = true;
return true; return true;
} }
bool cs_stacked_value::pop() { bool stacked_value::pop() {
if (!p_pushed || !p_a) { if (!p_pushed || !p_a) {
return false; return false;
} }
static_cast<cs_alias_impl *>(p_a)->pop_arg(); static_cast<alias_impl *>(p_a)->pop_arg();
p_pushed = false; p_pushed = false;
return true; return true;
} }
/* public utilities */ /* public utilities */
LIBCUBESCRIPT_EXPORT cs_strref cs_concat_values( LIBCUBESCRIPT_EXPORT string_ref concat_values(
cs_state &cs, std::span<cs_value> vals, std::string_view sep 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) { for (std::size_t i = 0; i < vals.size(); ++i) {
switch (vals[i].get_type()) { switch (vals[i].get_type()) {
case cs_value_type::INT: case value_type::INT:
case cs_value_type::FLOAT: case value_type::FLOAT:
case cs_value_type::STRING: case value_type::STRING:
std::ranges::copy( std::ranges::copy(
cs_value{vals[i]}.force_str(), std::back_inserter(buf) any_value{vals[i]}.force_str(), std::back_inserter(buf)
); );
break; break;
default: default:
@ -451,7 +451,7 @@ LIBCUBESCRIPT_EXPORT cs_strref cs_concat_values(
} }
std::ranges::copy(sep, std::back_inserter(buf)); std::ranges::copy(sep, std::back_inserter(buf));
} }
return cs_strref{cs, buf.str()}; return string_ref{cs, buf.str()};
} }
} /* namespace cscript */ } /* namespace cscript */

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
#ifndef LIBCUBESCRIPT_CS_VM_HH #ifndef LIBCUBESCRIPT_VM_HH
#define LIBCUBESCRIPT_CS_VM_HH #define LIBCUBESCRIPT_VM_HH
#include "cubescript/cubescript.hh" #include "cubescript/cubescript.hh"
@ -21,13 +21,13 @@ static constexpr int DummyIdx = MaxArguments;
static constexpr int NumargsIdx = MaxArguments + 1; static constexpr int NumargsIdx = MaxArguments + 1;
static constexpr int DbgaliasIdx = MaxArguments + 2; static constexpr int DbgaliasIdx = MaxArguments + 2;
static const int cs_valtypet[] = { static const int valtypet[] = {
CS_VAL_NULL, CS_VAL_INT, CS_VAL_FLOAT, CS_VAL_STRING, VAL_NULL, VAL_INT, VAL_FLOAT, VAL_STRING,
CS_VAL_CODE, CS_VAL_IDENT VAL_CODE, VAL_IDENT
}; };
static inline int cs_vtype_to_int(cs_value_type v) { static inline int vtype_to_int(value_type v) {
return cs_valtypet[int(v)]; return valtypet[int(v)];
} }
struct CsBreakException { struct CsBreakException {
@ -40,24 +40,24 @@ template<typename T>
constexpr size_t CsTypeStorageSize = constexpr size_t CsTypeStorageSize =
(sizeof(T) - 1) / sizeof(uint32_t) + 1; (sizeof(T) - 1) / sizeof(uint32_t) + 1;
struct cs_gen_state { struct codegen_state {
cs_state &cs; state &cs;
cs_gen_state *prevps; codegen_state *prevps;
bool parsing = true; bool parsing = true;
cs_valbuf<uint32_t> code; valbuf<uint32_t> code;
char const *source, *send; char const *source, *send;
size_t current_line; size_t current_line;
std::string_view src_name; std::string_view src_name;
cs_gen_state() = delete; codegen_state() = delete;
cs_gen_state(cs_state &csr): codegen_state(state &csr):
cs{csr}, prevps{csr.p_pstate}, code{cs}, cs{csr}, prevps{csr.p_pstate}, code{cs},
source{}, send{}, current_line{1}, src_name{} source{}, send{}, current_line{1}, src_name{}
{ {
csr.p_pstate = this; csr.p_pstate = this;
} }
~cs_gen_state() { ~codegen_state() {
done(); done();
} }
@ -70,13 +70,13 @@ struct cs_gen_state {
} }
std::string_view get_str(); std::string_view get_str();
cs_charbuf get_str_dup(); charbuf get_str_dup();
std::string_view get_word(); std::string_view get_word();
void gen_str(std::string_view word) { void gen_str(std::string_view word) {
if (word.size() <= 3) { 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) { for (size_t i = 0; i < word.size(); ++i) {
op |= uint32_t( op |= uint32_t(
static_cast<unsigned char>(word[i]) static_cast<unsigned char>(word[i])
@ -85,7 +85,7 @@ struct cs_gen_state {
code.push_back(op); code.push_back(op);
return; 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()); auto it = reinterpret_cast<uint32_t const *>(word.data());
code.append(it, it + (word.size() / sizeof(uint32_t))); code.append(it, it + (word.size() / sizeof(uint32_t)));
size_t esz = word.size() % sizeof(uint32_t); size_t esz = word.size() % sizeof(uint32_t);
@ -99,50 +99,50 @@ struct cs_gen_state {
} }
void gen_str() { 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() { 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) { 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 { } else {
union { union {
cs_int i; integer_type i;
uint32_t u[CsTypeStorageSize<cs_int>]; uint32_t u[CsTypeStorageSize<integer_type>];
} c; } c;
c.i = i; c.i = i;
code.push_back(CS_CODE_VAL | CS_RET_INT); code.push_back(BC_INST_VAL | BC_RET_INT);
code.append(c.u, c.u + CsTypeStorageSize<cs_int>); code.append(c.u, c.u + CsTypeStorageSize<integer_type>);
} }
} }
void gen_int(std::string_view word); void gen_int(std::string_view word);
void gen_float(cs_float f = 0.0f) { void gen_float(float_type f = 0.0f) {
if (cs_int(f) == f && f >= -0x800000 && f <= 0x7FFFFF) { if (integer_type(f) == f && f >= -0x800000 && f <= 0x7FFFFF) {
code.push_back(CS_CODE_VAL_INT | CS_RET_FLOAT | (cs_int(f) << 8)); code.push_back(BC_INST_VAL_INT | BC_RET_FLOAT | (integer_type(f) << 8));
} else { } else {
union { union {
cs_float f; float_type f;
uint32_t u[CsTypeStorageSize<cs_float>]; uint32_t u[CsTypeStorageSize<float_type>];
} c; } c;
c.f = f; c.f = f;
code.push_back(CS_CODE_VAL | CS_RET_FLOAT); code.push_back(BC_INST_VAL | BC_RET_FLOAT);
code.append(c.u, c.u + CsTypeStorageSize<cs_float>); code.append(c.u, c.u + CsTypeStorageSize<float_type>);
} }
} }
void gen_float(std::string_view word); void gen_float(std::string_view word);
void gen_ident(cs_ident *id) { void gen_ident(ident *id) {
code.push_back( code.push_back(
((id->get_index() < MaxArguments) ((id->get_index() < MaxArguments)
? CS_CODE_IDENT_ARG ? BC_INST_IDENT_ARG
: CS_CODE_IDENT : BC_INST_IDENT
) | (id->get_index() << 8) ) | (id->get_index() << 8)
); );
} }
@ -160,7 +160,7 @@ struct cs_gen_state {
int line = 0 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() { void next_char() {
if (source == send) { if (source == send) {
@ -187,26 +187,23 @@ struct cs_gen_state {
void skip_comments(); void skip_comments();
}; };
void bcode_ref(uint32_t *code);
void bcode_unref(uint32_t *code);
template<typename F> 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) { if (!cs.p_callstack) {
body(); body();
return; return;
} }
cs_valarray<cs_ident_stack, MaxArguments> argstack{cs}; valarray<ident_stack, MaxArguments> argstack{cs};
int argmask1 = cs.p_callstack->usedargs; int argmask1 = cs.p_callstack->usedargs;
for (int i = 0; argmask1; argmask1 >>= 1, ++i) { for (int i = 0; argmask1; argmask1 >>= 1, ++i) {
if (argmask1 & 1) { 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] argstack[i]
); );
} }
} }
cs_ident_link *prevstack = cs.p_callstack->next; ident_link *prevstack = cs.p_callstack->next;
cs_ident_link aliaslink = { ident_link aliaslink = {
cs.p_callstack->id, cs.p_callstack, cs.p_callstack->id, cs.p_callstack,
prevstack ? prevstack->usedargs : ((1 << MaxArguments) - 1), prevstack ? prevstack->usedargs : ((1 << MaxArguments) - 1),
prevstack ? prevstack->argstack : nullptr prevstack ? prevstack->argstack : nullptr
@ -220,7 +217,7 @@ static void cs_do_args(cs_state &cs, F body) {
int argmask2 = cs.p_callstack->usedargs; int argmask2 = cs.p_callstack->usedargs;
for (int i = 0; argmask2; argmask2 >>= 1, ++i) { for (int i = 0; argmask2; argmask2 >>= 1, ++i) {
if (argmask2 & 1) { 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] argstack[i]
); );
} }
@ -230,4 +227,4 @@ static void cs_do_args(cs_state &cs, F body) {
} /* namespace cscript */ } /* namespace cscript */
#endif /* LIBCUBESCRIPT_CS_VM_HH */ #endif /* LIBCUBESCRIPT_VM_HH */

View File

@ -6,22 +6,22 @@
namespace cscript { namespace cscript {
static inline void cs_do_loop( static inline void do_loop(
cs_state &cs, cs_ident &id, cs_int offset, cs_int n, cs_int step, state &cs, ident &id, integer_type offset, integer_type n, integer_type step,
cs_bcode *cond, cs_bcode *body bcode *cond, bcode *body
) { ) {
cs_stacked_value idv{cs, &id}; stacked_value idv{cs, &id};
if (n <= 0 || !idv.has_alias()) { if (n <= 0 || !idv.has_alias()) {
return; return;
} }
for (cs_int i = 0; i < n; ++i) { for (integer_type i = 0; i < n; ++i) {
idv.set_int(offset + i * step); idv.set_int(offset + i * step);
idv.push(); idv.push();
if (cond && !cs.run(cond).get_bool()) { if (cond && !cs.run(cond).get_bool()) {
break; break;
} }
switch (cs.run_loop(body)) { switch (cs.run_loop(body)) {
case cs_loop_state::BREAK: case loop_state::BREAK:
goto end; goto end;
default: /* continue and normal */ default: /* continue and normal */
break; break;
@ -31,23 +31,23 @@ end:
return; return;
} }
static inline void cs_loop_conc( static inline void do_loop_conc(
cs_state &cs, cs_value &res, cs_ident &id, cs_int offset, cs_int n, state &cs, any_value &res, ident &id, integer_type offset, integer_type n,
cs_int step, cs_bcode *body, bool space integer_type step, bcode *body, bool space
) { ) {
cs_stacked_value idv{cs, &id}; stacked_value idv{cs, &id};
if (n <= 0 || !idv.has_alias()) { if (n <= 0 || !idv.has_alias()) {
return; return;
} }
cs_charbuf s{cs}; charbuf s{cs};
for (cs_int i = 0; i < n; ++i) { for (integer_type i = 0; i < n; ++i) {
idv.set_int(offset + i * step); idv.set_int(offset + i * step);
idv.push(); idv.push();
cs_value v{cs}; any_value v{cs};
switch (cs.run_loop(body, v)) { switch (cs.run_loop(body, v)) {
case cs_loop_state::BREAK: case loop_state::BREAK:
goto end; goto end;
case cs_loop_state::CONTINUE: case loop_state::CONTINUE:
continue; continue;
default: default:
break; break;
@ -61,34 +61,34 @@ end:
res.set_str(s.str()); 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 &) { 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) { 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(); *css = args[2].get_ident()->get_alias();
if (!cret || !css) { if (!cret || !css) {
ret.set_int(0); ret.set_int(0);
return; return;
} }
cs_value result{cs}, tback{cs}; any_value result{cs}, tback{cs};
bool rc = true; bool rc = true;
try { try {
cs.run(args[0].get_code(), result); cs.run(args[0].get_code(), result);
} catch (cs_error const &e) { } catch (error const &e) {
result.set_str(e.what()); result.set_str(e.what());
if (e.get_stack().get()) { if (e.get_stack().get()) {
cs_charbuf buf{cs}; charbuf buf{cs};
cs_print_stack(std::back_inserter(buf), e.get_stack()); print_stack(std::back_inserter(buf), e.get_stack());
tback.set_str(buf.str()); tback.set_str(buf.str());
} }
rc = false; rc = false;
} }
ret.set_int(rc); ret.set_int(rc);
static_cast<cs_alias_impl *>(cret)->set_alias(cs, result); static_cast<alias_impl *>(cret)->set_alias(cs, result);
static_cast<cs_alias_impl *>(css)->set_alias(cs, tback); static_cast<alias_impl *>(css)->set_alias(cs, tback);
}); });
gcs.new_command("?", "ttt", [](auto &, auto args, auto &res) { 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) { 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) { for (size_t i = 1; (i + 1) < args.size(); i += 2) {
if ( if (
(args[i].get_type() == cs_value_type::NONE) || (args[i].get_type() == value_type::NONE) ||
(args[i].get_int() == val) (args[i].get_int() == val)
) { ) {
cs.run(args[i + 1].get_code(), res); 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) { 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) { for (size_t i = 1; (i + 1) < args.size(); i += 2) {
if ( if (
(args[i].get_type() == cs_value_type::NONE) || (args[i].get_type() == value_type::NONE) ||
(args[i].get_float() == val) (args[i].get_float() == val)
) { ) {
cs.run(args[i + 1].get_code(), res); 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) { 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) { for (size_t i = 1; (i + 1) < args.size(); i += 2) {
if ( if (
(args[i].get_type() == cs_value_type::NONE) || (args[i].get_type() == value_type::NONE) ||
(args[i].get_str() == val) (args[i].get_str() == val)
) { ) {
cs.run(args[i + 1].get_code(), res); 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) { 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)) { if (!idv.has_alias() || (idv.get_alias()->get_index() < MaxArguments)) {
return; return;
} }
@ -165,66 +165,66 @@ void cs_init_lib_base(cs_state &gcs) {
}); });
gcs.new_command("loop", "rie", [](auto &cs, auto args, auto &) { 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, cs, *args[0].get_ident(), 0, args[1].get_int(), 1, nullptr,
args[2].get_code() args[2].get_code()
); );
}); });
gcs.new_command("loop+", "riie", [](auto &cs, auto args, auto &) { 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, cs, *args[0].get_ident(), args[1].get_int(), args[2].get_int(), 1,
nullptr, args[3].get_code() nullptr, args[3].get_code()
); );
}); });
gcs.new_command("loop*", "riie", [](auto &cs, auto args, auto &) { 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(), cs, *args[0].get_ident(), 0, args[1].get_int(), args[2].get_int(),
nullptr, args[3].get_code() nullptr, args[3].get_code()
); );
}); });
gcs.new_command("loop+*", "riiie", [](auto &cs, auto args, auto &) { 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(), cs, *args[0].get_ident(), args[1].get_int(), args[3].get_int(),
args[2].get_int(), nullptr, args[4].get_code() args[2].get_int(), nullptr, args[4].get_code()
); );
}); });
gcs.new_command("loopwhile", "riee", [](auto &cs, auto args, auto &) { 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, cs, *args[0].get_ident(), 0, args[1].get_int(), 1,
args[2].get_code(), args[3].get_code() args[2].get_code(), args[3].get_code()
); );
}); });
gcs.new_command("loopwhile+", "riiee", [](auto &cs, auto args, auto &) { 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, cs, *args[0].get_ident(), args[1].get_int(), args[2].get_int(), 1,
args[3].get_code(), args[4].get_code() args[3].get_code(), args[4].get_code()
); );
}); });
gcs.new_command("loopwhile*", "riiee", [](auto &cs, auto args, auto &) { 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(), cs, *args[0].get_ident(), 0, args[2].get_int(), args[1].get_int(),
args[3].get_code(), args[4].get_code() args[3].get_code(), args[4].get_code()
); );
}); });
gcs.new_command("loopwhile+*", "riiiee", [](auto &cs, auto args, auto &) { 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(), 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() args[2].get_int(), args[4].get_code(), args[5].get_code()
); );
}); });
gcs.new_command("while", "ee", [](auto &cs, auto args, auto &) { 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()) { while (cs.run(cond).get_bool()) {
switch (cs.run_loop(body)) { switch (cs.run_loop(body)) {
case cs_loop_state::BREAK: case loop_state::BREAK:
goto end; goto end;
default: /* continue and normal */ default: /* continue and normal */
break; break;
@ -235,35 +235,35 @@ end:
}); });
gcs.new_command("loopconcat", "rie", [](auto &cs, auto args, auto &res) { 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, cs, res, *args[0].get_ident(), 0, args[1].get_int(), 1,
args[2].get_code(), true args[2].get_code(), true
); );
}); });
gcs.new_command("loopconcat+", "riie", [](auto &cs, auto args, auto &res) { 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(), cs, res, *args[0].get_ident(), args[1].get_int(),
args[2].get_int(), 1, args[3].get_code(), true args[2].get_int(), 1, args[3].get_code(), true
); );
}); });
gcs.new_command("loopconcat*", "riie", [](auto &cs, auto args, auto &res) { 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(), cs, res, *args[0].get_ident(), 0, args[2].get_int(),
args[1].get_int(), args[3].get_code(), true args[1].get_int(), args[3].get_code(), true
); );
}); });
gcs.new_command("loopconcat+*", "riiie", [](auto &cs, auto args, auto &res) { 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(), cs, res, *args[0].get_ident(), args[1].get_int(),
args[3].get_int(), args[2].get_int(), args[4].get_code(), true args[3].get_int(), args[2].get_int(), args[4].get_code(), true
); );
}); });
gcs.new_command("loopconcatword", "rie", [](auto &cs, auto args, auto &res) { 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, cs, res, *args[0].get_ident(), 0, args[1].get_int(), 1,
args[2].get_code(), false args[2].get_code(), false
); );
@ -272,7 +272,7 @@ end:
gcs.new_command("loopconcatword+", "riie", []( gcs.new_command("loopconcatword+", "riie", [](
auto &cs, auto args, auto &res auto &cs, auto args, auto &res
) { ) {
cs_loop_conc( do_loop_conc(
cs, res, *args[0].get_ident(), args[1].get_int(), cs, res, *args[0].get_ident(), args[1].get_int(),
args[2].get_int(), 1, args[3].get_code(), false args[2].get_int(), 1, args[3].get_code(), false
); );
@ -281,7 +281,7 @@ end:
gcs.new_command("loopconcatword*", "riie", []( gcs.new_command("loopconcatword*", "riie", [](
auto &cs, auto args, auto &res auto &cs, auto args, auto &res
) { ) {
cs_loop_conc( do_loop_conc(
cs, res, *args[0].get_ident(), 0, args[2].get_int(), cs, res, *args[0].get_ident(), 0, args[2].get_int(),
args[1].get_int(), args[3].get_code(), false args[1].get_int(), args[3].get_code(), false
); );
@ -290,14 +290,14 @@ end:
gcs.new_command("loopconcatword+*", "riiie", []( gcs.new_command("loopconcatword+*", "riiie", [](
auto &cs, auto args, auto &res 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(), cs, res, *args[0].get_ident(), args[1].get_int(), args[3].get_int(),
args[2].get_int(), args[4].get_code(), false args[2].get_int(), args[4].get_code(), false
); );
}); });
gcs.new_command("push", "rte", [](auto &cs, auto args, auto &res) { 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)) { if (!idv.has_alias() || (idv.get_alias()->get_index() < MaxArguments)) {
return; return;
} }

View File

@ -8,36 +8,36 @@
namespace cscript { namespace cscript {
template<typename T> template<typename T>
struct cs_arg_val; struct arg_val;
template<> template<>
struct cs_arg_val<cs_int> { struct arg_val<integer_type> {
static cs_int get(cs_value &tv) { static integer_type get(any_value &tv) {
return tv.get_int(); return tv.get_int();
} }
}; };
template<> template<>
struct cs_arg_val<cs_float> { struct arg_val<float_type> {
static cs_float get(cs_value &tv) { static float_type get(any_value &tv) {
return tv.get_float(); return tv.get_float();
} }
}; };
template<> template<>
struct cs_arg_val<std::string_view> { struct arg_val<std::string_view> {
static std::string_view get(cs_value &tv) { static std::string_view get(any_value &tv) {
return tv.get_str(); return tv.get_str();
} }
}; };
template<typename T, typename F> template<typename T, typename F>
static inline void cs_list_find( static inline void list_find(
cs_state &cs, std::span<cs_value> args, cs_value &res, F cmp state &cs, std::span<any_value> args, any_value &res, F cmp
) { ) {
cs_int n = 0, skip = args[2].get_int(); integer_type n = 0, skip = args[2].get_int();
T val = cs_arg_val<T>::get(args[1]); T val = arg_val<T>::get(args[1]);
for (cs_list_parser p{cs, args[0].get_str()}; p.parse(); ++n) { for (list_parser p{cs, args[0].get_str()}; p.parse(); ++n) {
if (cmp(p, val)) { if (cmp(p, val)) {
res.set_int(n); res.set_int(n);
return; return;
@ -54,11 +54,11 @@ notfound:
} }
template<typename T, typename F> template<typename T, typename F>
static inline void cs_list_assoc( static inline void list_assoc(
cs_state &cs, std::span<cs_value> args, cs_value &res, F cmp state &cs, std::span<any_value> args, any_value &res, F cmp
) { ) {
T val = cs_arg_val<T>::get(args[1]); T val = arg_val<T>::get(args[1]);
for (cs_list_parser p{cs, args[0].get_str()}; p.parse();) { for (list_parser p{cs, args[0].get_str()}; p.parse();) {
if (cmp(p, val)) { if (cmp(p, val)) {
if (p.parse()) { if (p.parse()) {
res.set_str(p.get_item()); res.set_str(p.get_item());
@ -71,27 +71,27 @@ static inline void cs_list_assoc(
} }
} }
static void cs_loop_list_conc( static void loop_list_conc(
cs_state &cs, cs_value &res, cs_ident *id, std::string_view list, state &cs, any_value &res, ident *id, std::string_view list,
cs_bcode *body, bool space bcode *body, bool space
) { ) {
cs_stacked_value idv{cs, id}; stacked_value idv{cs, id};
if (!idv.has_alias()) { if (!idv.has_alias()) {
return; return;
} }
cs_charbuf r{cs}; charbuf r{cs};
int n = 0; 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.set_str(p.get_item());
idv.push(); idv.push();
if (n && space) { if (n && space) {
r.push_back(' '); r.push_back(' ');
} }
cs_value v{cs}; any_value v{cs};
switch (cs.run_loop(body, v)) { switch (cs.run_loop(body, v)) {
case cs_loop_state::BREAK: case loop_state::BREAK:
goto end; goto end;
case cs_loop_state::CONTINUE: case loop_state::CONTINUE:
continue; continue;
default: default:
break; break;
@ -102,11 +102,11 @@ end:
res.set_str(r.str()); res.set_str(r.str());
} }
int cs_list_includes( int list_includes(
cs_state &cs, std::string_view list, std::string_view needle state &cs, std::string_view list, std::string_view needle
) { ) {
int offset = 0; 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) { if (p.get_raw_item() == needle) {
return offset; return offset;
} }
@ -116,20 +116,20 @@ int cs_list_includes(
} }
template<bool PushList, bool Swap, typename F> template<bool PushList, bool Swap, typename F>
static inline void cs_list_merge( static inline void list_merge(
cs_state &cs, std::span<cs_value> args, cs_value &res, F cmp state &cs, std::span<any_value> args, any_value &res, F cmp
) { ) {
std::string_view list = args[0].get_str(); std::string_view list = args[0].get_str();
std::string_view elems = args[1].get_str(); std::string_view elems = args[1].get_str();
cs_charbuf buf{cs}; charbuf buf{cs};
if (PushList) { if (PushList) {
buf.append(list); buf.append(list);
} }
if (Swap) { if (Swap) {
std::swap(list, elems); std::swap(list, elems);
} }
for (cs_list_parser p{cs, list}; p.parse();) { for (list_parser p{cs, list}; p.parse();) {
if (cmp(cs_list_includes(cs, elems, p.get_raw_item()), 0)) { if (cmp(list_includes(cs, elems, p.get_raw_item()), 0)) {
if (!buf.empty()) { if (!buf.empty()) {
buf.push_back(' '); buf.push_back(' ');
} }
@ -139,11 +139,11 @@ static inline void cs_list_merge(
res.set_str(buf.str()); 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) { 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) { gcs.new_command("at", "si1V", [](auto &cs, auto args, auto &res) {
@ -155,10 +155,10 @@ void cs_init_lib_list(cs_state &gcs) {
return; return;
} }
auto str = args[0].get_str(); 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) { for (size_t i = 1; i < args.size(); ++i) {
p.set_input(str); p.set_input(str);
cs_int pos = args[i].get_int(); integer_type pos = args[i].get_int();
for (; pos > 0; --pos) { for (; pos > 0; --pos) {
if (!p.parse()) { if (!p.parse()) {
break; break;
@ -172,15 +172,15 @@ void cs_init_lib_list(cs_state &gcs) {
}); });
gcs.new_command("sublist", "siiN", [](auto &cs, auto args, auto &res) { 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(), count = args[2].get_int(),
numargs = args[3].get_int(); numargs = args[3].get_int();
cs_int offset = std::max(skip, cs_int(0)), integer_type offset = std::max(skip, integer_type(0)),
len = (numargs >= 3) ? std::max(count, cs_int(0)) : -1; len = (numargs >= 3) ? std::max(count, integer_type(0)) : -1;
cs_list_parser p{cs, args[0].get_str()}; list_parser p{cs, args[0].get_str()};
for (cs_int i = 0; i < offset; ++i) { for (integer_type i = 0; i < offset; ++i) {
if (!p.parse()) break; if (!p.parse()) break;
} }
if (len < 0) { 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) { 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()) { if (!idv.has_alias()) {
res.set_int(-1); res.set_int(-1);
return; return;
} }
auto body = args[2].get_code(); auto body = args[2].get_code();
int n = -1; 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; ++n;
idv.set_str(p.get_raw_item()); idv.set_str(p.get_raw_item());
idv.push(); idv.push();
if (cs.run(body).get_bool()) { if (cs.run(body).get_bool()) {
res.set_int(cs_int(n)); res.set_int(integer_type(n));
return; return;
} }
} }
@ -224,13 +224,13 @@ void cs_init_lib_list(cs_state &gcs) {
}); });
gcs.new_command("listassoc", "rse", [](auto &cs, auto args, auto &res) { 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()) { if (!idv.has_alias()) {
return; return;
} }
auto body = args[2].get_code(); auto body = args[2].get_code();
int n = -1; 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; ++n;
idv.set_str(p.get_raw_item()); idv.set_str(p.get_raw_item());
idv.push(); 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) { gcs.new_command("listfind=", "i", [](auto &cs, auto args, auto &res) {
cs_list_find<cs_int>( list_find<integer_type>(
cs, args, res, [](cs_list_parser const &p, cs_int val) { cs, args, res, [](list_parser const &p, integer_type val) {
return parse_int(p.get_raw_item()) == val; return parse_int(p.get_raw_item()) == val;
} }
); );
}); });
gcs.new_command("listfind=f", "f", [](auto &cs, auto args, auto &res) { gcs.new_command("listfind=f", "f", [](auto &cs, auto args, auto &res) {
cs_list_find<cs_float>( list_find<float_type>(
cs, args, res, [](cs_list_parser const &p, cs_float val) { cs, args, res, [](list_parser const &p, float_type val) {
return parse_float(p.get_raw_item()) == val; return parse_float(p.get_raw_item()) == val;
} }
); );
}); });
gcs.new_command("listfind=s", "s", [](auto &cs, auto args, auto &res) { gcs.new_command("listfind=s", "s", [](auto &cs, auto args, auto &res) {
cs_list_find<std::string_view>( list_find<std::string_view>(
cs, args, res, [](cs_list_parser const &p, std::string_view val) { cs, args, res, [](list_parser const &p, std::string_view val) {
return p.get_raw_item() == val; return p.get_raw_item() == val;
} }
); );
}); });
gcs.new_command("listassoc=", "i", [](auto &cs, auto args, auto &res) { gcs.new_command("listassoc=", "i", [](auto &cs, auto args, auto &res) {
cs_list_assoc<cs_int>( list_assoc<integer_type>(
cs, args, res, [](cs_list_parser const &p, cs_int val) { cs, args, res, [](list_parser const &p, integer_type val) {
return parse_int(p.get_raw_item()) == val; return parse_int(p.get_raw_item()) == val;
} }
); );
}); });
gcs.new_command("listassoc=f", "f", [](auto &cs, auto args, auto &res) { gcs.new_command("listassoc=f", "f", [](auto &cs, auto args, auto &res) {
cs_list_assoc<cs_float>( list_assoc<float_type>(
cs, args, res, [](cs_list_parser const &p, cs_float val) { cs, args, res, [](list_parser const &p, float_type val) {
return parse_float(p.get_raw_item()) == val; return parse_float(p.get_raw_item()) == val;
} }
); );
}); });
gcs.new_command("listassoc=s", "s", [](auto &cs, auto args, auto &res) { gcs.new_command("listassoc=s", "s", [](auto &cs, auto args, auto &res) {
cs_list_assoc<std::string_view>( list_assoc<std::string_view>(
cs, args, res, [](cs_list_parser const &p, std::string_view val) { cs, args, res, [](list_parser const &p, std::string_view val) {
return p.get_raw_item() == val; return p.get_raw_item() == val;
} }
); );
}); });
gcs.new_command("looplist", "rse", [](auto &cs, auto args, auto &) { 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()) { if (!idv.has_alias()) {
return; return;
} }
auto body = args[2].get_code(); auto body = args[2].get_code();
int n = 0; 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.set_str(p.get_item());
idv.push(); idv.push();
switch (cs.run_loop(body)) { switch (cs.run_loop(body)) {
case cs_loop_state::BREAK: case loop_state::BREAK:
goto end; goto end;
default: /* continue and normal */ default: /* continue and normal */
break; break;
@ -312,14 +312,14 @@ end:
}); });
gcs.new_command("looplist2", "rrse", [](auto &cs, auto args, auto &) { gcs.new_command("looplist2", "rrse", [](auto &cs, auto args, auto &) {
cs_stacked_value idv1{cs, args[0].get_ident()}; stacked_value idv1{cs, args[0].get_ident()};
cs_stacked_value idv2{cs, args[1].get_ident()}; stacked_value idv2{cs, args[1].get_ident()};
if (!idv1.has_alias() || !idv2.has_alias()) { if (!idv1.has_alias() || !idv2.has_alias()) {
return; return;
} }
auto body = args[3].get_code(); auto body = args[3].get_code();
int n = 0; 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()); idv1.set_str(p.get_item());
if (p.parse()) { if (p.parse()) {
idv2.set_str(p.get_item()); idv2.set_str(p.get_item());
@ -329,7 +329,7 @@ end:
idv1.push(); idv1.push();
idv2.push(); idv2.push();
switch (cs.run_loop(body)) { switch (cs.run_loop(body)) {
case cs_loop_state::BREAK: case loop_state::BREAK:
goto end; goto end;
default: /* continue and normal */ default: /* continue and normal */
break; break;
@ -340,15 +340,15 @@ end:
}); });
gcs.new_command("looplist3", "rrrse", [](auto &cs, auto args, auto &) { gcs.new_command("looplist3", "rrrse", [](auto &cs, auto args, auto &) {
cs_stacked_value idv1{cs, args[0].get_ident()}; stacked_value idv1{cs, args[0].get_ident()};
cs_stacked_value idv2{cs, args[1].get_ident()}; stacked_value idv2{cs, args[1].get_ident()};
cs_stacked_value idv3{cs, args[2].get_ident()}; stacked_value idv3{cs, args[2].get_ident()};
if (!idv1.has_alias() || !idv2.has_alias() || !idv3.has_alias()) { if (!idv1.has_alias() || !idv2.has_alias() || !idv3.has_alias()) {
return; return;
} }
auto body = args[4].get_code(); auto body = args[4].get_code();
int n = 0; 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()); idv1.set_str(p.get_item());
if (p.parse()) { if (p.parse()) {
idv2.set_str(p.get_item()); idv2.set_str(p.get_item());
@ -364,7 +364,7 @@ end:
idv2.push(); idv2.push();
idv3.push(); idv3.push();
switch (cs.run_loop(body)) { switch (cs.run_loop(body)) {
case cs_loop_state::BREAK: case loop_state::BREAK:
goto end; goto end;
default: /* continue and normal */ default: /* continue and normal */
break; break;
@ -375,7 +375,7 @@ end:
}); });
gcs.new_command("looplistconcat", "rse", [](auto &cs, auto args, auto &res) { 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(), cs, res, args[0].get_ident(), args[1].get_str(),
args[2].get_code(), true args[2].get_code(), true
); );
@ -384,21 +384,21 @@ end:
gcs.new_command("looplistconcatword", "rse", []( gcs.new_command("looplistconcatword", "rse", [](
auto &cs, auto args, auto &res auto &cs, auto args, auto &res
) { ) {
cs_loop_list_conc( loop_list_conc(
cs, res, args[0].get_ident(), args[1].get_str(), cs, res, args[0].get_ident(), args[1].get_str(),
args[2].get_code(), false args[2].get_code(), false
); );
}); });
gcs.new_command("listfilter", "rse", [](auto &cs, auto args, auto &res) { 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()) { if (!idv.has_alias()) {
return; return;
} }
auto body = args[2].get_code(); auto body = args[2].get_code();
cs_charbuf r{cs}; charbuf r{cs};
int n = 0; 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.set_str(p.get_raw_item());
idv.push(); idv.push();
if (cs.run(body).get_bool()) { if (cs.run(body).get_bool()) {
@ -412,13 +412,13 @@ end:
}); });
gcs.new_command("listcount", "rse", [](auto &cs, auto args, auto &res) { 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()) { if (!idv.has_alias()) {
return; return;
} }
auto body = args[2].get_code(); auto body = args[2].get_code();
int n = 0, r = 0; 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.set_str(p.get_raw_item());
idv.push(); idv.push();
if (cs.run(body).get_bool()) { if (cs.run(body).get_bool()) {
@ -429,16 +429,16 @@ end:
}); });
gcs.new_command("prettylist", "ss", [](auto &cs, auto args, auto &res) { 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 s = args[0].get_str();
std::string_view conj = args[1].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 len = p.count();
size_t n = 0; size_t n = 0;
for (p.set_input(s); p.parse(); ++n) { for (p.set_input(s); p.parse(); ++n) {
auto qi = p.get_quoted_item(); auto qi = p.get_quoted_item();
if (!qi.empty() && (qi.front() == '"')) { 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 { } else {
buf.append(p.get_raw_item()); buf.append(p.get_raw_item());
} }
@ -458,35 +458,35 @@ end:
gcs.new_command("indexof", "ss", [](auto &cs, auto args, auto &res) { gcs.new_command("indexof", "ss", [](auto &cs, auto args, auto &res) {
res.set_int( 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) { 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) { 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) { 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) { gcs.new_command("listsplice", "ssii", [](auto &cs, auto args, auto &res) {
cs_int offset = std::max(args[2].get_int(), cs_int(0)); integer_type offset = std::max(args[2].get_int(), integer_type(0));
cs_int len = std::max(args[3].get_int(), cs_int(0)); integer_type len = std::max(args[3].get_int(), integer_type(0));
std::string_view s = args[0].get_str(); std::string_view s = args[0].get_str();
std::string_view vals = args[1].get_str(); std::string_view vals = args[1].get_str();
char const *list = s.data(); char const *list = s.data();
cs_list_parser p{cs, s}; list_parser p{cs, s};
for (cs_int i = 0; i < offset; ++i) { for (integer_type i = 0; i < offset; ++i) {
if (!p.parse()) { if (!p.parse()) {
break; break;
} }
} }
std::string_view quote = p.get_quoted_item(); std::string_view quote = p.get_quoted_item();
char const *qend = !quote.empty() ? &quote[quote.size()] : list; char const *qend = !quote.empty() ? &quote[quote.size()] : list;
cs_charbuf buf{cs}; charbuf buf{cs};
if (qend > list) { if (qend > list) {
buf.append(list, qend); buf.append(list, qend);
} }
@ -496,7 +496,7 @@ end:
} }
buf.append(vals); buf.append(vals);
} }
for (cs_int i = 0; i < len; ++i) { for (integer_type i = 0; i < len; ++i) {
if (!p.parse()) { if (!p.parse()) {
break; break;
} }
@ -518,7 +518,7 @@ end:
res.set_str(buf.str()); res.set_str(buf.str());
}); });
cs_init_lib_list_sort(gcs); init_lib_list_sort(gcs);
} }
struct ListSortItem { struct ListSortItem {
@ -527,9 +527,9 @@ struct ListSortItem {
}; };
struct ListSortFun { struct ListSortFun {
cs_state &cs; state &cs;
cs_stacked_value &xv, &yv; stacked_value &xv, &yv;
cs_bcode *body; bcode *body;
bool operator()(ListSortItem const &xval, ListSortItem const &yval) { bool operator()(ListSortItem const &xval, ListSortItem const &yval) {
xv.set_str(xval.str); xv.set_str(xval.str);
@ -540,20 +540,20 @@ struct ListSortFun {
} }
}; };
static void cs_list_sort( static void list_sort(
cs_state &cs, cs_value &res, std::string_view list, state &cs, any_value &res, std::string_view list,
cs_ident *x, cs_ident *y, cs_bcode *body, cs_bcode *unique ident *x, ident *y, bcode *body, bcode *unique
) { ) {
if (x == y || !x->is_alias() || !y->is_alias()) { if (x == y || !x->is_alias() || !y->is_alias()) {
return; 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; 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() }; ListSortItem item = { p.get_raw_item(), p.get_quoted_item() };
items.push_back(item); items.push_back(item);
total += item.quote.size(); total += item.quote.size();
@ -564,7 +564,7 @@ static void cs_list_sort(
return; return;
} }
cs_stacked_value xval{cs, xa}, yval{cs, ya}; stacked_value xval{cs, xa}, yval{cs, ya};
xval.set_none(); xval.set_none();
yval.set_none(); yval.set_none();
xval.push(); xval.push();
@ -575,7 +575,7 @@ static void cs_list_sort(
if (body) { if (body) {
ListSortFun f = { cs, xval, yval, body }; ListSortFun f = { cs, xval, yval, body };
std::sort(items.buf.begin(), items.buf.end(), f); std::sort(items.buf.begin(), items.buf.end(), f);
if (!cs_code_is_empty(unique)) { if (!code_is_empty(unique)) {
f.body = unique; f.body = unique;
totaluniq = items[0].quote.size(); totaluniq = items[0].quote.size();
nuniq = 1; nuniq = 1;
@ -612,7 +612,7 @@ static void cs_list_sort(
xval.pop(); xval.pop();
yval.pop(); yval.pop();
cs_charbuf sorted{cs}; charbuf sorted{cs};
sorted.reserve(totaluniq + std::max(nuniq - 1, size_t(0))); sorted.reserve(totaluniq + std::max(nuniq - 1, size_t(0)));
for (size_t i = 0; i < items.size(); ++i) { for (size_t i = 0; i < items.size(); ++i) {
ListSortItem &item = items[i]; ListSortItem &item = items[i];
@ -627,15 +627,15 @@ static void cs_list_sort(
res.set_str(sorted.str()); 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) { 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(), cs, res, args[0].get_str(), args[1].get_ident(),
args[2].get_ident(), args[3].get_code(), args[4].get_code() args[2].get_ident(), args[3].get_code(), args[4].get_code()
); );
}); });
gcs.new_command("uniquelist", "srre", [](auto &cs, auto args, auto &res) { 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(), cs, res, args[0].get_str(), args[1].get_ident(),
args[2].get_ident(), nullptr, args[3].get_code() args[2].get_ident(), nullptr, args[3].get_code()
); );

View File

@ -8,71 +8,71 @@
namespace cscript { namespace cscript {
static constexpr cs_float PI = 3.14159265358979f; static constexpr float_type PI = 3.14159265358979f;
static constexpr cs_float RAD = PI / 180.0f; static constexpr float_type RAD = PI / 180.0f;
template<typename T> template<typename T>
struct cs_math_val; struct math_val;
template<> template<>
struct cs_math_val<cs_int> { struct math_val<integer_type> {
static cs_int get(cs_value &tv) { static integer_type get(any_value &tv) {
return tv.get_int(); 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); res.set_int(val);
} }
}; };
template<> template<>
struct cs_math_val<cs_float> { struct math_val<float_type> {
static cs_float get(cs_value &tv) { static float_type get(any_value &tv) {
return tv.get_float(); 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); res.set_float(val);
} }
}; };
template<typename T> template<typename T>
struct cs_math_noop { struct math_noop {
T operator()(T arg) { T operator()(T arg) {
return arg; return arg;
} }
}; };
template<typename T, typename F1, typename F2> template<typename T, typename F1, typename F2>
static inline void cs_mathop( static inline void math_op(
std::span<cs_value> args, cs_value &res, T initval, std::span<any_value> args, any_value &res, T initval,
F1 binop, F2 unop F1 binop, F2 unop
) { ) {
T val; T val;
if (args.size() >= 2) { 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) { 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 { } 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> 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; bool val;
if (args.size() >= 2) { 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) { 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 { } 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) { cs.new_command("sin", "f", [](auto &, auto args, auto &res) {
res.set_float(std::sin(args[0].get_float() * RAD)); 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.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) { for (size_t i = 1; i < args.size(); ++i) {
v = std::min(v, args[i].get_int()); v = std::min(v, args[i].get_int());
} }
res.set_int(v); res.set_int(v);
}); });
cs.new_command("max", "i1V", [](auto &, auto args, auto &res) { 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) { for (size_t i = 1; i < args.size(); ++i) {
v = std::max(v, args[i].get_int()); v = std::max(v, args[i].get_int());
} }
res.set_int(v); res.set_int(v);
}); });
cs.new_command("minf", "f1V", [](auto &, auto args, auto &res) { 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) { for (size_t i = 1; i < args.size(); ++i) {
v = std::min(v, args[i].get_float()); v = std::min(v, args[i].get_float());
} }
res.set_float(v); res.set_float(v);
}); });
cs.new_command("maxf", "f1V", [](auto &, auto args, auto &res) { 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) { for (size_t i = 1; i < args.size(); ++i) {
v = std::max(v, args[i].get_float()); 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.new_command("round", "ff", [](auto &, auto args, auto &res) {
cs_float step = args[1].get_float(); float_type step = args[1].get_float();
cs_float r = args[0].get_float(); float_type r = args[0].get_float();
if (step > 0) { if (step > 0) {
r += step * ((r < 0) ? -0.5 : 0.5); r += step * ((r < 0) ? -0.5 : 0.5);
r -= std::fmod(r, step); 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.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.new_command("*", "i1V", [](auto &, auto args, auto &res) {
cs_mathop<cs_int>( math_op<integer_type>(
args, res, 1, std::multiplies<cs_int>(), cs_math_noop<cs_int>() args, res, 1, std::multiplies<integer_type>(), math_noop<integer_type>()
); );
}); });
cs.new_command("-", "i1V", [](auto &, auto args, auto &res) { cs.new_command("-", "i1V", [](auto &, auto args, auto &res) {
cs_mathop<cs_int>( math_op<integer_type>(
args, res, 0, std::minus<cs_int>(), std::negate<cs_int>() args, res, 0, std::minus<integer_type>(), std::negate<integer_type>()
); );
}); });
cs.new_command("^", "i1V", [](auto &, auto args, auto &res) { cs.new_command("^", "i1V", [](auto &, auto args, auto &res) {
cs_mathop<cs_int>( math_op<integer_type>(
args, res, 0, std::bit_xor<cs_int>(), [](cs_int val) { return ~val; } args, res, 0, std::bit_xor<integer_type>(), [](integer_type val) { return ~val; }
); );
}); });
cs.new_command("~", "i1V", [](auto &, auto args, auto &res) { cs.new_command("~", "i1V", [](auto &, auto args, auto &res) {
cs_mathop<cs_int>( math_op<integer_type>(
args, res, 0, std::bit_xor<cs_int>(), [](cs_int val) { return ~val; } args, res, 0, std::bit_xor<integer_type>(), [](integer_type val) { return ~val; }
); );
}); });
cs.new_command("&", "i1V", [](auto &, auto args, auto &res) { cs.new_command("&", "i1V", [](auto &, auto args, auto &res) {
cs_mathop<cs_int>( math_op<integer_type>(
args, res, 0, std::bit_and<cs_int>(), cs_math_noop<cs_int>() args, res, 0, std::bit_and<integer_type>(), math_noop<integer_type>()
); );
}); });
cs.new_command("|", "i1V", [](auto &, auto args, auto &res) { cs.new_command("|", "i1V", [](auto &, auto args, auto &res) {
cs_mathop<cs_int>( math_op<integer_type>(
args, res, 0, std::bit_or<cs_int>(), cs_math_noop<cs_int>() args, res, 0, std::bit_or<integer_type>(), math_noop<integer_type>()
); );
}); });
/* special combined cases */ /* special combined cases */
cs.new_command("^~", "i1V", [](auto &, auto args, auto &res) { cs.new_command("^~", "i1V", [](auto &, auto args, auto &res) {
cs_int val; integer_type val;
if (args.size() >= 2) { if (args.size() >= 2) {
val = args[0].get_int() ^ ~args[1].get_int(); val = args[0].get_int() ^ ~args[1].get_int();
for (size_t i = 2; i < args.size(); ++i) { 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); res.set_int(val);
}); });
cs.new_command("&~", "i1V", [](auto &, auto args, auto &res) { cs.new_command("&~", "i1V", [](auto &, auto args, auto &res) {
cs_int val; integer_type val;
if (args.size() >= 2) { if (args.size() >= 2) {
val = args[0].get_int() & ~args[1].get_int(); val = args[0].get_int() & ~args[1].get_int();
for (size_t i = 2; i < args.size(); ++i) { 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); res.set_int(val);
}); });
cs.new_command("|~", "i1V", [](auto &, auto args, auto &res) { cs.new_command("|~", "i1V", [](auto &, auto args, auto &res) {
cs_int val; integer_type val;
if (args.size() >= 2) { if (args.size() >= 2) {
val = args[0].get_int() | ~args[1].get_int(); val = args[0].get_int() | ~args[1].get_int();
for (size_t i = 2; i < args.size(); ++i) { 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.new_command("<<", "i1V", [](auto &, auto args, auto &res) {
cs_mathop<cs_int>( math_op<integer_type>(
args, res, 0, [](cs_int val1, cs_int val2) { args, res, 0, [](integer_type val1, integer_type val2) {
return (val2 < cs_int(sizeof(cs_int) * CHAR_BIT)) return (val2 < integer_type(sizeof(integer_type) * CHAR_BIT))
? (val1 << std::max(val2, cs_int(0))) ? (val1 << std::max(val2, integer_type(0)))
: 0; : 0;
}, cs_math_noop<cs_int>() }, math_noop<integer_type>()
); );
}); });
cs.new_command(">>", "i1V", [](auto &, auto args, auto &res) { cs.new_command(">>", "i1V", [](auto &, auto args, auto &res) {
cs_mathop<cs_int>( math_op<integer_type>(
args, res, 0, [](cs_int val1, cs_int val2) { args, res, 0, [](integer_type val1, integer_type val2) {
return val1 >> std::clamp( 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.new_command("+f", "f1V", [](auto &, auto args, auto &res) {
cs_mathop<cs_float>( math_op<float_type>(
args, res, 0, std::plus<cs_float>(), cs_math_noop<cs_float>() args, res, 0, std::plus<float_type>(), math_noop<float_type>()
); );
}); });
cs.new_command("*f", "f1V", [](auto &, auto args, auto &res) { cs.new_command("*f", "f1V", [](auto &, auto args, auto &res) {
cs_mathop<cs_float>( math_op<float_type>(
args, res, 1, std::multiplies<cs_float>(), cs_math_noop<cs_float>() args, res, 1, std::multiplies<float_type>(), math_noop<float_type>()
); );
}); });
cs.new_command("-f", "f1V", [](auto &, auto args, auto &res) { cs.new_command("-f", "f1V", [](auto &, auto args, auto &res) {
cs_mathop<cs_float>( math_op<float_type>(
args, res, 0, std::minus<cs_float>(), std::negate<cs_float>() args, res, 0, std::minus<float_type>(), std::negate<float_type>()
); );
}); });
cs.new_command("div", "i1V", [](auto &, auto args, auto &res) { cs.new_command("div", "i1V", [](auto &, auto args, auto &res) {
cs_mathop<cs_int>( math_op<integer_type>(
args, res, 0, [](cs_int val1, cs_int val2) { args, res, 0, [](integer_type val1, integer_type val2) {
if (val2) { if (val2) {
return val1 / val2; return val1 / val2;
} }
return cs_int(0); return integer_type(0);
}, cs_math_noop<cs_int>() }, math_noop<integer_type>()
); );
}); });
cs.new_command("mod", "i1V", [](auto &, auto args, auto &res) { cs.new_command("mod", "i1V", [](auto &, auto args, auto &res) {
cs_mathop<cs_int>( math_op<integer_type>(
args, res, 0, [](cs_int val1, cs_int val2) { args, res, 0, [](integer_type val1, integer_type val2) {
if (val2) { if (val2) {
return val1 % val2; return val1 % val2;
} }
return cs_int(0); return integer_type(0);
}, cs_math_noop<cs_int>() }, math_noop<integer_type>()
); );
}); });
cs.new_command("divf", "f1V", [](auto &, auto args, auto &res) { cs.new_command("divf", "f1V", [](auto &, auto args, auto &res) {
cs_mathop<cs_float>( math_op<float_type>(
args, res, 0, [](cs_float val1, cs_float val2) { args, res, 0, [](float_type val1, float_type val2) {
if (val2) { if (val2) {
return val1 / val2; return val1 / val2;
} }
return cs_float(0); return float_type(0);
}, cs_math_noop<cs_float>() }, math_noop<float_type>()
); );
}); });
cs.new_command("modf", "f1V", [](auto &, auto args, auto &res) { cs.new_command("modf", "f1V", [](auto &, auto args, auto &res) {
cs_mathop<cs_float>( math_op<float_type>(
args, res, 0, [](cs_float val1, cs_float val2) { args, res, 0, [](float_type val1, float_type val2) {
if (val2) { if (val2) {
return cs_float(fmod(val1, val2)); return float_type(fmod(val1, val2));
} }
return cs_float(0); return float_type(0);
}, cs_math_noop<cs_float>() }, math_noop<float_type>()
); );
}); });
cs.new_command("pow", "f1V", [](auto &, auto args, auto &res) { cs.new_command("pow", "f1V", [](auto &, auto args, auto &res) {
cs_mathop<cs_float>( math_op<float_type>(
args, res, 0, [](cs_float val1, cs_float val2) { args, res, 0, [](float_type val1, float_type val2) {
return cs_float(pow(val1, val2)); return float_type(pow(val1, val2));
}, cs_math_noop<cs_float>() }, math_noop<float_type>()
); );
}); });
cs.new_command("=", "i1V", [](auto &, auto args, auto &res) { 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.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.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.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.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.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.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.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.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.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.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.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>());
}); });
} }

View File

@ -9,8 +9,8 @@
namespace cscript { namespace cscript {
template<typename F> template<typename F>
static inline void cs_strgcmp( static inline void str_cmp_by(
std::span<cs_value> args, cs_value &res, F cfunc std::span<any_value> args, any_value &res, F cfunc
) { ) {
bool val; bool val;
if (args.size() >= 2) { if (args.size() >= 2) {
@ -24,28 +24,28 @@ static inline void cs_strgcmp(
std::string_view() 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) { cs.new_command("strstr", "ss", [](auto &, auto args, auto &res) {
std::string_view a = args[0].get_str(), b = args[1].get_str(); std::string_view a = args[0].get_str(), b = args[1].get_str();
auto pos = a.find(b); auto pos = a.find(b);
if (pos == a.npos) { if (pos == a.npos) {
res.set_int(-1); res.set_int(-1);
} else { } else {
res.set_int(cs_int(pos)); res.set_int(integer_type(pos));
} }
}); });
cs.new_command("strlen", "s", [](auto &, auto args, auto &res) { 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) { cs.new_command("strcode", "si", [](auto &, auto args, auto &res) {
std::string_view str = args[0].get_str(); std::string_view str = args[0].get_str();
cs_int i = args[1].get_int(); integer_type i = args[1].get_int();
if (i >= cs_int(str.size())) { if (i >= integer_type(str.size())) {
res.set_int(0); res.set_int(0);
} else { } else {
res.set_int(static_cast<unsigned char>(str[i])); 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) { cs.new_command("strlower", "s", [](auto &ccs, auto args, auto &res) {
auto inps = std::string_view{args[0].get_str()}; 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()); auto *buf = ics->strman->alloc_buf(inps.size());
for (std::size_t i = 0; i < inps.size(); ++i) { for (std::size_t i = 0; i < inps.size(); ++i) {
buf[i] = tolower(inps[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) { cs.new_command("strupper", "s", [](auto &ccs, auto args, auto &res) {
auto inps = std::string_view{args[0].get_str()}; 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()); auto *buf = ics->strman->alloc_buf(inps.size());
for (std::size_t i = 0; i < inps.size(); ++i) { for (std::size_t i = 0; i < inps.size(); ++i) {
buf[i] = toupper(inps[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.new_command("escape", "s", [](auto &ccs, auto args, auto &res) {
cs_charbuf s{ccs}; charbuf s{ccs};
cs_escape_string(std::back_inserter(s), args[0].get_str()); escape_string(std::back_inserter(s), args[0].get_str());
res.set_str(s.str()); res.set_str(s.str());
}); });
cs.new_command("unescape", "s", [](auto &ccs, auto args, auto &res) { cs.new_command("unescape", "s", [](auto &ccs, auto args, auto &res) {
cs_charbuf s{ccs}; charbuf s{ccs};
cs_unescape_string(std::back_inserter(s), args[0].get_str()); unescape_string(std::back_inserter(s), args[0].get_str());
res.set_str(s.str()); res.set_str(s.str());
}); });
cs.new_command("concat", "V", [](auto &ccs, auto args, auto &res) { 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) { 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) { cs.new_command("format", "V", [](auto &ccs, auto args, auto &res) {
if (args.empty()) { if (args.empty()) {
return; return;
} }
cs_charbuf s{ccs}; charbuf s{ccs};
cs_strref fs = args[0].get_str(); string_ref fs = args[0].get_str();
std::string_view f{fs}; std::string_view f{fs};
for (auto it = f.begin(); it != f.end(); ++it) { for (auto it = f.begin(); it != f.end(); ++it) {
char c = *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 prec = std::max(int(args[1].get_int()), 1);
int n = snprintf(buf, sizeof(buf), "0x%.*llX", prec, val); int n = snprintf(buf, sizeof(buf), "0x%.*llX", prec, val);
if (n >= int(sizeof(buf))) { if (n >= int(sizeof(buf))) {
cs_charbuf s{ccs}; charbuf s{ccs};
s.reserve(n + 1); s.reserve(n + 1);
s.data()[0] = '\0'; s.data()[0] = '\0';
int nn = snprintf(s.data(), n + 1, "0x%.*llX", prec, val); int nn = snprintf(s.data(), n + 1, "0x%.*llX", prec, val);
@ -145,42 +145,42 @@ void cs_init_lib_string(cs_state &cs) {
return; return;
} }
/* should pretty much be unreachable */ /* 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) { cs.new_command("substr", "siiN", [](auto &, auto args, auto &res) {
std::string_view s = args[0].get_str(); std::string_view s = args[0].get_str();
cs_int start = args[1].get_int(), count = args[2].get_int(); integer_type start = args[1].get_int(), count = args[2].get_int();
cs_int numargs = args[3].get_int(); integer_type numargs = args[3].get_int();
cs_int len = cs_int(s.size()), offset = std::clamp(start, cs_int(0), len); integer_type len = integer_type(s.size()), offset = std::clamp(start, integer_type(0), len);
res.set_str(std::string_view{ res.set_str(std::string_view{
&s[offset], &s[offset],
((numargs >= 3) ((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)) : size_t(len - offset))
}); });
}); });
cs.new_command("strcmp", "s1V", [](auto &, auto args, auto &res) { 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.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.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.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.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.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.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) { 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); res.set_str(s);
return; return;
} }
cs_charbuf buf{ccs}; charbuf buf{ccs};
for (size_t i = 0;; ++i) { for (size_t i = 0;; ++i) {
std::string_view found; std::string_view found;
auto p = s.find(oldval); 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) { cs.new_command("strsplice", "ssii", [](auto &ccs, auto args, auto &res) {
std::string_view s = args[0].get_str(); std::string_view s = args[0].get_str();
std::string_view vals = args[1].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(); count = args[3].get_int();
cs_int offset = std::clamp(skip, cs_int(0), cs_int(s.size())), integer_type offset = std::clamp(skip, integer_type(0), integer_type(s.size())),
len = std::clamp(count, cs_int(0), cs_int(s.size()) - offset); len = std::clamp(count, integer_type(0), integer_type(s.size()) - offset);
cs_charbuf p{ccs}; charbuf p{ccs};
p.reserve(s.size() - len + vals.size()); p.reserve(s.size() - len + vals.size());
if (offset) { if (offset) {
p.append(s.substr(0, offset)); p.append(s.substr(0, offset));
} }
p.append(vals); 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)); p.append(s.substr(offset + len, s.size() - offset - len));
} }
res.set_str(p.str()); res.set_str(p.str());

View File

@ -4,10 +4,10 @@
#include <optional> #include <optional>
#include <string> #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; std::string lbuf;
char buf[512]; char buf[512];
printf("%s", pr->get_value().data()); 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); return std::move(lbuf);
} }
inline void add_history(cs_state &, std::string_view) { inline void add_history(cs::state &, std::string_view) {
} }
#endif #endif

View File

@ -12,7 +12,7 @@
#include "linenoise.hh" #include "linenoise.hh"
static cs_state *ln_cs = nullptr; static cs::state *ln_cs = nullptr;
inline void ln_complete(char const *buf, linenoiseCompletions *lc) { inline void ln_complete(char const *buf, linenoiseCompletions *lc) {
std::string_view cmd = get_complete_cmd(buf); 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) { 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) { if (!cmd) {
return nullptr; return nullptr;
} }
@ -49,7 +49,7 @@ inline void ln_hint_free(void *hint) {
delete[] static_cast<char *>(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 */ /* sensible default history size */
linenoiseHistorySetMaxLen(1000); linenoiseHistorySetMaxLen(1000);
ln_cs = &cs; ln_cs = &cs;
@ -58,7 +58,7 @@ inline void init_lineedit(cs_state &cs, std::string_view) {
linenoiseSetFreeHintsCallback(ln_hint_free); 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()); auto line = linenoise(pr->get_value().data());
if (!line) { if (!line) {
/* linenoise traps ctrl-c, detect it and let the user exit */ /* 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; 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 */ /* backed by std::string so it's terminated */
linenoiseHistoryAdd(line.data()); linenoiseHistoryAdd(line.data());
} }

View File

@ -9,18 +9,18 @@
#include <readline/readline.h> #include <readline/readline.h>
#include <readline/history.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) { inline char *ln_complete_list(char const *buf, int state) {
static std::string_view cmd; static std::string_view cmd;
static std::span<cs_ident *> itr; static std::span<cs::ident *> itr;
if (!state) { if (!state) {
cmd = get_complete_cmd(buf); cmd = get_complete_cmd(buf);
itr = rd_cs->get_idents(); itr = rd_cs->get_idents();
} }
for (cs_ident *id: itr) { for (cs::ident *id: itr) {
if (!id->is_command()) { if (!id->is_command()) {
continue; continue;
} }
@ -43,7 +43,7 @@ inline char **ln_complete(char const *buf, int, int) {
} }
inline void ln_hint() { 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) { if (!cmd) {
rl_redisplay(); rl_redisplay();
return; return;
@ -59,13 +59,13 @@ inline void ln_hint() {
rl_replace_line(old.data(), 0); 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; rd_cs = &cs;
rl_attempted_completion_function = ln_complete; rl_attempted_completion_function = ln_complete;
rl_redisplay_function = ln_hint; 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()); auto line = readline(pr->get_value().data());
if (!line) { if (!line) {
return std::string(); return std::string();
@ -75,7 +75,7 @@ inline std::optional<std::string> read_line(cs_state &, cs_svar *pr) {
return ret; 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 */ /* backed by std::string so it's terminated */
add_history(line.data()); add_history(line.data());
} }

View File

@ -9,7 +9,7 @@
#include <cubescript/cubescript.hh> #include <cubescript/cubescript.hh>
using namespace cscript; namespace cs = cscript;
std::string_view version = "CubeScript 0.0.1"; 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 = "([;"; std::string_view nextchars = "([;";
auto lp = buf.find_first_of(nextchars); auto lp = buf.find_first_of(nextchars);
if (lp != buf.npos) { 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) { if (cmd) {
return cmd; return cmd;
} }
@ -179,23 +179,23 @@ void print_version() {
printf("%s\n", version.data()); printf("%s\n", version.data());
} }
static cs_state *scs = nullptr; static cs::state *scs = nullptr;
static void do_sigint(int n) { static void do_sigint(int n) {
/* in case another SIGINT happens, terminate normally */ /* in case another SIGINT happens, terminate normally */
signal(n, SIG_DFL); signal(n, SIG_DFL);
scs->set_call_hook([](cs_state &cs) { scs->set_call_hook([](cs::state &cs) {
cs.set_call_hook(nullptr); 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 */ /* 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()) { switch (var.get_type()) {
case cs_ident_type::IVAR: { case cs::ident_type::IVAR: {
auto &iv = static_cast<cs_ivar const &>(var); auto &iv = static_cast<cs::integer_var const &>(var);
auto val = iv.get_value(); 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); std::printf("%s = %d\n", iv.get_name().data(), val);
} else if (iv.get_val_max() == 0xFFFFFF) { } else if (iv.get_val_max() == 0xFFFFFF) {
std::printf( std::printf(
@ -208,8 +208,8 @@ static void repl_print_var(cs_state const &cs, cs_var const &var) {
} }
break; break;
} }
case cs_ident_type::FVAR: { case cs::ident_type::FVAR: {
auto &fv = static_cast<cs_fvar const &>(var); auto &fv = static_cast<cs::float_var const &>(var);
auto val = fv.get_value(); auto val = fv.get_value();
if (std::floor(val) == val) { if (std::floor(val) == val) {
std::printf("%s = %.1f", fv.get_name().data(), 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; break;
} }
case cs_ident_type::SVAR: { case cs::ident_type::SVAR: {
auto &sv = static_cast<cs_svar const &>(var); auto &sv = static_cast<cs::string_var const &>(var);
auto val = std::string_view{sv.get_value()}; auto val = std::string_view{sv.get_value()};
if (val.find('"') == val.npos) { if (val.find('"') == val.npos) {
std::printf("%s = \"%s\"", sv.get_name().data(), val.data()); 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"); FILE *f = std::fopen(fname.data(), "rb");
if (!f) { if (!f) {
return false; return false;
@ -260,8 +262,8 @@ static bool do_run_file(cs_state &cs, std::string_view fname, cs_value &ret) {
return true; return true;
} }
static bool do_call(cs_state &cs, std::string_view line, bool file = false) { static bool do_call(cs::state &cs, std::string_view line, bool file = false) {
cs_value ret{cs}; cs::any_value ret{cs};
scs = &cs; scs = &cs;
signal(SIGINT, do_sigint); signal(SIGINT, do_sigint);
try { try {
@ -272,7 +274,7 @@ static bool do_call(cs_state &cs, std::string_view line, bool file = false) {
} else { } else {
cs.run(line, ret); cs.run(line, ret);
} }
} catch (cscript::cs_error const &e) { } catch (cs::error const &e) {
signal(SIGINT, SIG_DFL); signal(SIGINT, SIG_DFL);
scs = nullptr; scs = nullptr;
std::string_view terr = e.what(); 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()) { if (e.get_stack().get()) {
std::string str; 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()); std::printf("%s\n", str.data());
} }
return false; return false;
} }
signal(SIGINT, SIG_DFL); signal(SIGINT, SIG_DFL);
scs = nullptr; 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()); std::printf("%s\n", std::string_view{ret.get_str()}.data());
} }
return false; return false;
} }
static void do_tty(cs_state &cs) { static void do_tty(cs::state &cs) {
auto prompt = cs.new_svar("PROMPT", "> "); auto prompt = cs.new_svar("PROMPT", "> ");
auto prompt2 = cs.new_svar("PROMPT2", ">> "); auto prompt2 = cs.new_svar("PROMPT2", ">> ");
@ -349,16 +351,16 @@ static void do_tty(cs_state &cs) {
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
cs_state gcs; cs::state gcs;
gcs.set_var_printer(repl_print_var); gcs.set_var_printer(repl_print_var);
gcs.init_libs(); gcs.init_libs();
gcs.new_command("exec", "s", [](auto &cs, auto args, auto &) { gcs.new_command("exec", "s", [](auto &cs, auto args, auto &) {
auto file = args[0].get_str(); auto file = args[0].get_str();
cs_value val{cs}; cs::any_value val{cs};
bool ret = do_run_file(cs, file, val); bool ret = do_run_file(cs, file, val);
if (!ret) { if (!ret) {
throw cscript::cs_error( throw cs::error(
cs, "could not run file \"%s\"", file cs, "could not run file \"%s\"", file
); );
} }