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
namespace cscript {
using cs_int = int;
using cs_float = float;
using integer_type = int;
using float_type = float;
constexpr auto const CS_INT_FORMAT = "%d";
constexpr auto const CS_FLOAT_FORMAT = "%.7g";
constexpr auto const CS_ROUND_FLOAT_FORMAT = "%.1f";
constexpr auto const INT_FORMAT = "%d";
constexpr auto const FLOAT_FORMAT = "%.7g";
constexpr auto const ROUND_FLOAT_FORMAT = "%.1f";
} /* namespace cscript */
#endif /* LIBCUBESCRIPT_CUBESCRIPT_CONF_HH */

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

@ -7,8 +7,8 @@
namespace cscript {
cs_int parse_int(std::string_view input, std::string_view *end = nullptr);
cs_float parse_float(std::string_view input, std::string_view *end = nullptr);
integer_type parse_int(std::string_view input, std::string_view *end = nullptr);
float_type parse_float(std::string_view input, std::string_view *end = nullptr);
bool is_valid_name(std::string_view input);

View File

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

View File

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

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

View File

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

View File

@ -11,7 +11,7 @@
namespace cscript {
struct cs_strref_state;
struct string_ref_state;
/* string manager
*
@ -29,19 +29,19 @@ struct cs_strref_state;
* for now we don't bother...
*/
struct cs_strman {
using allocator_type = cs_allocator<
std::pair<std::string_view const, cs_strref_state *>
struct string_pool {
using allocator_type = std_allocator<
std::pair<std::string_view const, string_ref_state *>
>;
cs_strman() = delete;
cs_strman(cs_shared_state *cs): cstate{cs}, counts{allocator_type{cs}} {}
~cs_strman() {}
string_pool() = delete;
string_pool(internal_state *cs): cstate{cs}, counts{allocator_type{cs}} {}
~string_pool() {}
cs_strman(cs_strman const &) = delete;
cs_strman(cs_strman &&) = delete;
string_pool(string_pool const &) = delete;
string_pool(string_pool &&) = delete;
cs_strman &operator=(cs_strman const &) = delete;
cs_strman &operator=(cs_strman &&) = delete;
string_pool &operator=(string_pool const &) = delete;
string_pool &operator=(string_pool &&) = delete;
/* adds a string into the manager using any source, and returns a managed
* version; this is "slow" as it has to hash the string and potentially
@ -58,7 +58,7 @@ struct cs_strman {
/* this will use the provided memory, assuming it is a fresh string that
* is yet to be added; the memory must be allocated with alloc_buf()
*/
cs_strref steal(char *ptr);
string_ref steal(char *ptr);
/* decrements the reference count and removes it from the system if
* that reaches zero; likewise, only safe with pointers that are managed
@ -78,9 +78,9 @@ struct cs_strman {
*/
char *alloc_buf(std::size_t len) const;
cs_shared_state *cstate;
internal_state *cstate;
std::unordered_map<
std::string_view, cs_strref_state *,
std::string_view, string_ref_state *,
std::hash<std::string_view>,
std::equal_to<std::string_view>,
allocator_type

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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