halve the size of any_value by removing state pointer from it

this brings more advantages too like actually being default
constructible, so it can be used more easily in data structures etc
master
Daniel Kolesa 2021-04-11 03:32:14 +02:00
parent 7229672f56
commit d358dd83e7
12 changed files with 343 additions and 371 deletions

View File

@ -78,7 +78,6 @@ private:
/* for internal use only */
string_ref(char const *p, internal_state *cs);
internal_state *p_state;
char const *p_str;
};
@ -87,11 +86,9 @@ enum class value_type {
};
struct LIBCUBESCRIPT_EXPORT any_value {
any_value() = delete;
~any_value();
any_value();
any_value(state &);
any_value(internal_state &);
~any_value();
any_value(any_value const &);
any_value(any_value &&v);
@ -103,13 +100,13 @@ struct LIBCUBESCRIPT_EXPORT any_value {
void set_integer(integer_type val);
void set_float(float_type val);
void set_string(std::string_view val);
void set_string(std::string_view val, state &cs);
void set_string(string_ref const &val);
void set_none();
void set_code(bcode_ref const &val);
void set_ident(ident *val);
string_ref get_string() const;
string_ref get_string(state &cs) const;
integer_type get_integer() const;
float_type get_float() const;
bcode_ref get_code() const;
@ -122,27 +119,15 @@ struct LIBCUBESCRIPT_EXPORT any_value {
void force_plain();
float_type force_float();
integer_type force_integer();
std::string_view force_string();
std::string_view force_string(state &cs);
bcode_ref force_code(state &cs);
ident &force_ident(state &cs);
private:
template<typename T>
struct stor_t {
internal_state *state;
T val;
};
internal_state *get_state() const {
return std::launder(
reinterpret_cast<stor_t<void *> const *>(&p_stor)
)->state;
}
std::aligned_union_t<1,
stor_t<integer_type>,
stor_t<float_type>,
stor_t<void *>,
integer_type,
float_type,
void *,
string_ref
> p_stor;
value_type p_type;

View File

@ -35,9 +35,9 @@ svar_impl::svar_impl(string_ref name, string_ref v, int fl):
{}
alias_impl::alias_impl(
state &cs, string_ref name, string_ref a, int fl
state &, string_ref name, string_ref a, int fl
):
ident_impl{ident_type::ALIAS, name, fl}, p_initial{cs}
ident_impl{ident_type::ALIAS, name, fl}, p_initial{}
{
p_initial.val_s.set_string(a);
}
@ -45,31 +45,31 @@ alias_impl::alias_impl(
alias_impl::alias_impl(
state &cs, string_ref name, std::string_view a, int fl
):
ident_impl{ident_type::ALIAS, name, fl}, p_initial{cs}
ident_impl{ident_type::ALIAS, name, fl}, p_initial{}
{
p_initial.val_s.set_string(a);
p_initial.val_s.set_string(a, cs);
}
alias_impl::alias_impl(state &cs, string_ref name, integer_type a, int fl):
ident_impl{ident_type::ALIAS, name, fl}, p_initial{cs}
alias_impl::alias_impl(state &, string_ref name, integer_type a, int fl):
ident_impl{ident_type::ALIAS, name, fl}, p_initial{}
{
p_initial.val_s.set_integer(a);
}
alias_impl::alias_impl(state &cs, string_ref name, float_type a, int fl):
ident_impl{ident_type::ALIAS, name, fl}, p_initial{cs}
alias_impl::alias_impl(state &, string_ref name, float_type a, int fl):
ident_impl{ident_type::ALIAS, name, fl}, p_initial{}
{
p_initial.val_s.set_float(a);
}
alias_impl::alias_impl(state &cs, string_ref name, int fl):
ident_impl{ident_type::ALIAS, name, fl}, p_initial{cs}
alias_impl::alias_impl(state &, string_ref name, int fl):
ident_impl{ident_type::ALIAS, name, fl}, p_initial{}
{
p_initial.val_s.set_none();
}
alias_impl::alias_impl(state &cs, string_ref name, any_value v, int fl):
ident_impl{ident_type::ALIAS, name, fl}, p_initial{cs}
alias_impl::alias_impl(state &, string_ref name, any_value v, int fl):
ident_impl{ident_type::ALIAS, name, fl}, p_initial{}
{
p_initial.val_s = v.get_plain();
}
@ -87,7 +87,7 @@ void var_changed(thread_state &ts, ident *id) {
return;
}
auto *cimp = static_cast<command_impl *>(cid);
any_value val{*ts.pstate};
any_value val{};
val.set_ident(id);
cimp->call(ts, std::span<any_value>{&val, 1}, val);
}
@ -111,10 +111,10 @@ void command_impl::call(
try {
p_cb_cftv(*ts.pstate, args, ret);
} catch (...) {
ts.idstack.resize(idstsz, ident_stack{*ts.pstate});
ts.idstack.resize(idstsz);
throw;
}
ts.idstack.resize(idstsz, ident_stack{*ts.pstate});
ts.idstack.resize(idstsz);
}
bool ident_is_used_arg(ident *id, thread_state &ts) {
@ -137,7 +137,7 @@ void alias_stack::set_arg(alias *a, thread_state &ts, any_value &v) {
if (ident_is_used_arg(a, ts)) {
node->code = bcode_ref{};
} else {
push(ts.idstack.emplace_back(*ts.pstate));
push(ts.idstack.emplace_back());
ts.callstack->usedargs[a->get_index()] = true;
}
node->val_s = std::move(v);
@ -470,7 +470,7 @@ LIBCUBESCRIPT_EXPORT alias_local::alias_local(state &cs, ident *a) {
auto &ts = state_p{cs}.ts();
p_alias = static_cast<alias *>(a);
auto &ast = ts.get_astack(p_alias);
ast.push(ts.idstack.emplace_back(cs));
ast.push(ts.idstack.emplace_back());
p_sp = &ast;
ast.flags &= ~IDENT_FLAG_UNKNOWN;
}

View File

@ -29,7 +29,7 @@ struct ident_stack {
any_value val_s;
bcode_ref code;
ident_stack *next;
ident_stack(state &cs): val_s{cs}, code{}, next{nullptr} {}
ident_stack(): val_s{}, code{}, next{nullptr} {}
};
struct alias_stack {

View File

@ -169,7 +169,7 @@ state::state(alloc_func func, void *data) {
std::printf("%s = [%s]\n", sv->get_name().data(), val.data());
}
} else {
sv->set_value(cs, args[1].get_string());
sv->set_value(cs, args[1].get_string(cs));
}
});
@ -342,7 +342,7 @@ LIBCUBESCRIPT_EXPORT void state::clear_override(ident &id) {
switch (id.get_type()) {
case ident_type::ALIAS: {
auto &ast = p_tstate->get_astack(static_cast<alias *>(&id));
ast.node->val_s.set_string("");
ast.node->val_s.set_string("", *this);
ast.node->code = bcode_ref{};
ast.flags &= ~IDENT_FLAG_OVERRIDDEN;
return;
@ -645,7 +645,7 @@ LIBCUBESCRIPT_EXPORT void state::init_libs(int libs) {
}
LIBCUBESCRIPT_EXPORT any_value state::run(bcode_ref const &code) {
any_value ret{*this};
any_value ret{};
vm_exec(*p_tstate, bcode_p{code}.get()->get_raw(), ret);
return ret;
}
@ -653,7 +653,7 @@ LIBCUBESCRIPT_EXPORT any_value state::run(bcode_ref const &code) {
static any_value do_run(
thread_state &ts, std::string_view file, std::string_view code
) {
any_value ret{*ts.pstate};
any_value ret{};
gen_state gs{ts};
gs.gen_main(code, file);
auto cref = gs.steal_ref();
@ -674,7 +674,7 @@ LIBCUBESCRIPT_EXPORT any_value state::run(
LIBCUBESCRIPT_EXPORT any_value state::run(
ident &id, std::span<any_value> args
) {
any_value ret{*this};
any_value ret{};
std::size_t nargs = args.size();
run_depth_guard level{*p_tstate}; /* incr and decr on scope exit */
switch (id.get_type()) {
@ -689,7 +689,7 @@ LIBCUBESCRIPT_EXPORT any_value state::run(
stack_guard s{*p_tstate}; /* restore after call */
auto &targs = p_tstate->vmstack;
auto osz = targs.size();
targs.resize(osz + cimpl.get_num_args(), any_value{*this});
targs.resize(osz + cimpl.get_num_args());
for (std::size_t i = 0; i < nargs; ++i) {
targs[osz + i] = args[i];
}
@ -711,7 +711,7 @@ LIBCUBESCRIPT_EXPORT any_value state::run(
auto osz = targs.size();
auto anargs = std::size_t(cimp->get_num_args());
targs.resize(
osz + std::max(args.size(), anargs + 1), any_value{*this}
osz + std::max(args.size(), anargs + 1)
);
for (std::size_t i = 0; i < nargs; ++i) {
targs[osz + i + 1] = args[i];
@ -728,7 +728,7 @@ LIBCUBESCRIPT_EXPORT any_value state::run(
auto osz = targs.size();
auto anargs = std::size_t(cimp->get_num_args());
targs.resize(
osz + std::max(args.size(), anargs + 1), any_value{*this}
osz + std::max(args.size(), anargs + 1)
);
for (std::size_t i = 0; i < nargs; ++i) {
targs[osz + i + 1] = args[i];
@ -745,7 +745,7 @@ LIBCUBESCRIPT_EXPORT any_value state::run(
auto osz = targs.size();
auto anargs = std::size_t(cimp->get_num_args());
targs.resize(
osz + std::max(args.size(), anargs + 1), any_value{*this}
osz + std::max(args.size(), anargs + 1)
);
for (std::size_t i = 0; i < nargs; ++i) {
targs[osz + i + 1] = args[i];
@ -790,7 +790,7 @@ LIBCUBESCRIPT_EXPORT loop_state state::run_loop(
}
LIBCUBESCRIPT_EXPORT loop_state state::run_loop(bcode_ref const &code) {
any_value ret{*this};
any_value ret{};
return run_loop(code, ret);
}

View File

@ -6,6 +6,7 @@
namespace cubescript {
struct string_ref_state {
internal_state *state;
std::size_t length;
std::size_t refcount;
};
@ -97,6 +98,7 @@ char *string_pool::alloc_buf(std::size_t len) const {
auto mem = cstate->alloc(nullptr, 0, len + sizeof(string_ref_state) + 1);
/* write length and initial refcount */
auto *sst = static_cast<string_ref_state *>(mem);
sst->state = cstate;
sst->length = len;
sst->refcount = 1;
/* pre-terminate */
@ -112,43 +114,39 @@ char *string_pool::alloc_buf(std::size_t len) const {
LIBCUBESCRIPT_EXPORT string_ref::string_ref(
internal_state *cs, std::string_view str
): p_state{cs}
{
) {
p_str = cs->strman->add(str);
}
LIBCUBESCRIPT_EXPORT string_ref::string_ref(state &cs, std::string_view str):
p_state{state_p{cs}.ts().istate}
{
p_str = p_state->strman->add(str);
LIBCUBESCRIPT_EXPORT string_ref::string_ref(state &cs, std::string_view str) {
p_str = state_p{cs}.ts().istate->strman->add(str);
}
LIBCUBESCRIPT_EXPORT string_ref::string_ref(string_ref const &ref):
p_state{ref.p_state}, p_str{ref.p_str}
p_str{ref.p_str}
{
p_state->strman->ref(p_str);
get_ref_state(p_str)->state->strman->ref(p_str);
}
/* 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 string_ref::string_ref(
char const *p, internal_state *cs
) {
p_str = cs->strman->ref(p);
}
LIBCUBESCRIPT_EXPORT string_ref::~string_ref() {
p_state->strman->unref(p_str);
get_ref_state(p_str)->state->strman->unref(p_str);
}
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);
get_ref_state(p_str)->state->strman->ref(p_str);
return *this;
}
LIBCUBESCRIPT_EXPORT string_ref::operator std::string_view() const {
return p_state->strman->get(p_str);
return get_ref_state(p_str)->state->strman->get(p_str);
}
LIBCUBESCRIPT_EXPORT bool string_ref::operator==(string_ref const &s) const {

View File

@ -54,25 +54,19 @@ static std::string_view floatstr(float_type v, charbuf &buf) {
return std::string_view{buf.data(), std::size_t(n)};
}
template<typename T>
struct stor_priv_t {
internal_state *state;
T val;
};
template<typename T, typename U>
static inline T &csv_get(U *stor) {
/* ugly, but internal and unlikely to cause bugs */
return const_cast<T &>(std::launder(
reinterpret_cast<stor_priv_t<T> const *>(stor)
)->val);
return const_cast<T &>(*std::launder(
reinterpret_cast<T const *>(stor)
));
}
template<typename T>
static inline void csv_cleanup(value_type tv, T *stor) {
switch (tv) {
case value_type::STRING:
std::launder(reinterpret_cast<string_ref *>(stor))->~string_ref();
csv_get<string_ref>(stor).~string_ref();
break;
case value_type::CODE: {
bcode_unref(csv_get<uint32_t *>(stor));
@ -83,23 +77,19 @@ static inline void csv_cleanup(value_type tv, T *stor) {
}
}
any_value::any_value(state &st): any_value(*state_p{st}.ts().istate) {}
any_value::any_value(internal_state &st):
p_stor(), p_type(value_type::NONE)
{
std::launder(reinterpret_cast<stor_priv_t<void *> *>(&p_stor))->state = &st;
}
any_value::any_value():
p_stor{}, p_type{value_type::NONE}
{}
any_value::~any_value() {
csv_cleanup(p_type, &p_stor);
}
any_value::any_value(any_value const &v): any_value(*v.get_state()) {
any_value::any_value(any_value const &v): any_value{} {
*this = v;
}
any_value::any_value(any_value &&v): any_value(*v.get_state()) {
any_value::any_value(any_value &&v): any_value{} {
*this = std::move(v);
}
@ -115,8 +105,8 @@ any_value &any_value::operator=(any_value const &v) {
break;
case value_type::STRING:
p_type = value_type::STRING;
new (&p_stor) string_ref{
*std::launder(reinterpret_cast<string_ref const *>(&v.p_stor))
new (&csv_get<string_ref>(&p_stor)) string_ref{
csv_get<string_ref>(&v.p_stor)
};
break;
case value_type::CODE:
@ -150,15 +140,15 @@ void any_value::set_float(float_type val) {
csv_get<float_type>(&p_stor) = val;
}
void any_value::set_string(std::string_view val) {
void any_value::set_string(std::string_view val, state &cs) {
csv_cleanup(p_type, &p_stor);
new (&p_stor) string_ref{get_state(), val};
new (&csv_get<string_ref>(&p_stor)) string_ref{cs, val};
p_type = value_type::STRING;
}
void any_value::set_string(string_ref const &val) {
csv_cleanup(p_type, &p_stor);
new (&p_stor) string_ref{val};
new (&csv_get<string_ref>(&p_stor)) string_ref{val};
p_type = value_type::STRING;
}
@ -207,9 +197,7 @@ float_type any_value::force_float() {
rf = float_type(csv_get<integer_type>(&p_stor));
break;
case value_type::STRING:
rf = parse_float(
*std::launder(reinterpret_cast<string_ref const *>(&p_stor))
);
rf = parse_float(csv_get<string_ref>(&p_stor));
break;
case value_type::FLOAT:
return csv_get<float_type>(&p_stor);
@ -227,9 +215,7 @@ integer_type any_value::force_integer() {
ri = integer_type(std::floor(csv_get<float_type>(&p_stor)));
break;
case value_type::STRING:
ri = parse_int(
*std::launder(reinterpret_cast<string_ref const *>(&p_stor))
);
ri = parse_int(csv_get<string_ref>(&p_stor));
break;
case value_type::INTEGER:
return csv_get<integer_type>(&p_stor);
@ -240,8 +226,8 @@ integer_type any_value::force_integer() {
return ri;
}
std::string_view any_value::force_string() {
charbuf rs{get_state()};
std::string_view any_value::force_string(state &cs) {
charbuf rs{cs};
std::string_view str;
switch (get_type()) {
case value_type::FLOAT:
@ -251,15 +237,13 @@ std::string_view any_value::force_string() {
str = intstr(csv_get<integer_type>(&p_stor), rs);
break;
case value_type::STRING:
return *std::launder(reinterpret_cast<string_ref const *>(&p_stor));
return csv_get<string_ref>(&p_stor);
default:
str = rs.str();
break;
}
set_string(str);
return std::string_view(*std::launder(
reinterpret_cast<string_ref const *>(&p_stor)
));
set_string(str, cs);
return csv_get<string_ref>(&p_stor);
}
bcode_ref any_value::force_code(state &cs) {
@ -270,7 +254,7 @@ bcode_ref any_value::force_code(state &cs) {
break;
}
gen_state gs{state_p{cs}.ts()};
gs.gen_main(get_string());
gs.gen_main(get_string(cs));
auto bc = gs.steal_ref();
set_code(bc);
return bc;
@ -284,7 +268,7 @@ ident &any_value::force_ident(state &cs) {
break;
}
auto &id = state_p{cs}.ts().istate->new_ident(
cs, get_string(), IDENT_FLAG_UNKNOWN
cs, get_string(cs), IDENT_FLAG_UNKNOWN
);
set_ident(&id);
return id;
@ -297,9 +281,7 @@ integer_type any_value::get_integer() const {
case value_type::INTEGER:
return csv_get<integer_type>(&p_stor);
case value_type::STRING:
return parse_int(
*std::launder(reinterpret_cast<string_ref const *>(&p_stor))
);
return parse_int(csv_get<string_ref>(&p_stor));
default:
break;
}
@ -313,9 +295,7 @@ float_type any_value::get_float() const {
case value_type::INTEGER:
return float_type(csv_get<integer_type>(&p_stor));
case value_type::STRING:
return parse_float(
*std::launder(reinterpret_cast<string_ref const *>(&p_stor))
);
return parse_float(csv_get<string_ref>(&p_stor));
default:
break;
}
@ -336,26 +316,26 @@ ident *any_value::get_ident() const {
return csv_get<ident *>(&p_stor);
}
string_ref any_value::get_string() const {
string_ref any_value::get_string(state &cs) const {
switch (get_type()) {
case value_type::STRING:
return *std::launder(reinterpret_cast<string_ref const *>(&p_stor));
return csv_get<string_ref>(&p_stor);
case value_type::INTEGER: {
charbuf rs{get_state()};
charbuf rs{cs};
return string_ref{
get_state(), intstr(csv_get<integer_type>(&p_stor), rs)
cs, intstr(csv_get<integer_type>(&p_stor), rs)
};
}
case value_type::FLOAT: {
charbuf rs{get_state()};
charbuf rs{cs};
return string_ref{
get_state(), floatstr(csv_get<float_type>(&p_stor), rs)
cs, floatstr(csv_get<float_type>(&p_stor), rs)
};
}
default:
break;
}
return string_ref{get_state(), ""};
return string_ref{cs, ""};
}
any_value any_value::get_plain() const {
@ -367,7 +347,7 @@ any_value any_value::get_plain() const {
default:
break;
}
return any_value{*get_state()};
return any_value{};
}
bool any_value::get_bool() const {
@ -377,9 +357,7 @@ bool any_value::get_bool() const {
case value_type::INTEGER:
return csv_get<integer_type>(&p_stor) != 0;
case value_type::STRING: {
std::string_view s = *std::launder(
reinterpret_cast<string_ref const *>(&p_stor)
);
std::string_view s = csv_get<string_ref>(&p_stor);
if (s.empty()) {
return false;
}
@ -412,7 +390,8 @@ LIBCUBESCRIPT_EXPORT string_ref concat_values(
case value_type::FLOAT:
case value_type::STRING:
std::ranges::copy(
any_value{vals[i]}.force_string(), std::back_inserter(buf)
any_value{vals[i]}.force_string(cs),
std::back_inserter(buf)
);
break;
default:

View File

@ -24,11 +24,11 @@ static inline void pop_alias(thread_state &ts, ident *id) {
}
}
static inline void force_arg(any_value &v, int type) {
static inline void force_arg(state &cs, any_value &v, int type) {
switch (type) {
case BC_RET_STRING:
if (v.get_type() != value_type::STRING) {
v.force_string();
v.force_string(cs);
}
break;
case BC_RET_INT:
@ -104,10 +104,10 @@ void exec_command(
if (rep) {
break;
}
args[i].set_string("");
args[i].set_string("", *ts.pstate);
fakeargs++;
} else {
args[i].force_string();
args[i].force_string(*ts.pstate);
}
break;
case 'T':
@ -128,7 +128,7 @@ void exec_command(
args[i].set_none();
fakeargs++;
} else if (args[i].get_type() == value_type::STRING) {
auto str = args[i].get_string();
auto str = args[i].get_string(*ts.pstate);
if (str.empty()) {
args[i].set_integer(0);
} else {
@ -170,7 +170,7 @@ void exec_command(
break;
case 'C': {
i = std::max(i + 1, numargs);
any_value tv{*ts.pstate};
any_value tv{};
tv.set_string(concat_values(
*ts.pstate, std::span{args, std::size_t(i)}, " "
));
@ -227,7 +227,7 @@ bool exec_alias(
auto &ast = ts.get_astack(
static_cast<alias *>(ts.istate->identmap[i])
);
auto &st = ts.idstack.emplace_back(*ts.pstate);
auto &st = ts.idstack.emplace_back();
ast.push(st);
st.val_s = std::move(args[offset + i]);
uargs[i] = true;
@ -240,7 +240,7 @@ bool exec_alias(
ts.callstack = &aliaslink;
if (!aast.node->code) {
gen_state gs{ts};
gs.gen_main(aast.node->val_s.get_string());
gs.gen_main(aast.node->val_s.get_string(*ts.pstate));
aast.node->code = gs.steal_ref();
}
bcode_ref coderef = aast.node->code;
@ -262,8 +262,8 @@ bool exec_alias(
amask[callargs] = false;
}
}
ts.idstack.resize(noff, ident_stack{*ts.pstate});
force_arg(result, op & BC_INST_RET_MASK);
ts.idstack.resize(noff);
force_arg(*ts.pstate, result, op & BC_INST_RET_MASK);
anargs->set_raw_value(integer_type(oldargs));
nargs = offset - skip;
};
@ -315,7 +315,7 @@ static inline int get_lookupu_type(
if (arg.get_type() != value_type::STRING) {
return -2; /* default case */
}
id = ts.pstate->get_ident(arg.get_string());
id = ts.pstate->get_ident(arg.get_string(*ts.pstate));
if (id) {
switch(id->get_type()) {
case ident_type::ALIAS: {
@ -342,17 +342,20 @@ static inline int get_lookupu_type(
auto &args = ts.vmstack;
auto osz = args.size();
/* pad with as many empty values as we need */
args.resize(osz + cimpl->get_num_args(), any_value{*ts.pstate});
args.resize(osz + cimpl->get_num_args());
arg.set_none();
exec_command(ts, cimpl, cimpl, &args[osz], arg, 0, true);
force_arg(arg, op & BC_INST_RET_MASK);
force_arg(*ts.pstate, arg, op & BC_INST_RET_MASK);
return -2; /* ignore */
}
default:
return ID_UNKNOWN;
}
}
throw error{*ts.pstate, "unknown alias lookup: %s", arg.get_string().data()};
throw error{
*ts.pstate, "unknown alias lookup: %s",
arg.get_string(*ts.pstate).data()
};
}
std::uint32_t *vm_exec(
@ -378,7 +381,7 @@ std::uint32_t *vm_exec(
result.set_none();
continue;
case BC_INST_NULL | BC_RET_STRING:
result.set_string("");
result.set_string("", cs);
continue;
case BC_INST_NULL | BC_RET_INT:
result.set_integer(0);
@ -388,7 +391,7 @@ std::uint32_t *vm_exec(
continue;
case BC_INST_FALSE | BC_RET_STRING:
result.set_string("0");
result.set_string("0", cs);
continue;
case BC_INST_FALSE | BC_RET_NULL:
case BC_INST_FALSE | BC_RET_INT:
@ -399,7 +402,7 @@ std::uint32_t *vm_exec(
continue;
case BC_INST_TRUE | BC_RET_STRING:
result.set_string("1");
result.set_string("1", cs);
continue;
case BC_INST_TRUE | BC_RET_NULL:
case BC_INST_TRUE | BC_RET_INT:
@ -410,7 +413,7 @@ std::uint32_t *vm_exec(
continue;
case BC_INST_NOT | BC_RET_STRING:
result.set_string(args.back().get_bool() ? "0" : "1");
result.set_string(args.back().get_bool() ? "0" : "1", cs);
args.pop_back();
continue;
case BC_INST_NOT | BC_RET_NULL:
@ -427,7 +430,7 @@ std::uint32_t *vm_exec(
args.pop_back();
continue;
case BC_INST_ENTER:
code = vm_exec(ts, code, args.emplace_back(cs));
code = vm_exec(ts, code, args.emplace_back());
continue;
case BC_INST_ENTER_RESULT:
code = vm_exec(ts, code, result);
@ -435,7 +438,7 @@ std::uint32_t *vm_exec(
case BC_INST_EXIT | BC_RET_STRING:
case BC_INST_EXIT | BC_RET_INT:
case BC_INST_EXIT | BC_RET_FLOAT:
force_arg(result, op & BC_INST_RET_MASK);
force_arg(cs, result, op & BC_INST_RET_MASK);
/* fallthrough */
case BC_INST_EXIT | BC_RET_NULL:
return code;
@ -449,20 +452,20 @@ std::uint32_t *vm_exec(
case BC_INST_RESULT | BC_RET_FLOAT:
result = std::move(args.back());
args.pop_back();
force_arg(result, op & BC_INST_RET_MASK);
force_arg(cs, result, op & BC_INST_RET_MASK);
continue;
case BC_INST_RESULT_ARG | BC_RET_STRING:
case BC_INST_RESULT_ARG | BC_RET_INT:
case BC_INST_RESULT_ARG | BC_RET_FLOAT:
force_arg(result, op & BC_INST_RET_MASK);
force_arg(cs, result, op & BC_INST_RET_MASK);
/* fallthrough */
case BC_INST_RESULT_ARG | BC_RET_NULL:
args.emplace_back(std::move(result));
continue;
case BC_INST_FORCE | BC_RET_STRING:
args.back().force_string();
args.back().force_string(cs);
continue;
case BC_INST_FORCE | BC_RET_INT:
args.back().force_integer();
@ -473,32 +476,32 @@ std::uint32_t *vm_exec(
case BC_INST_DUP | BC_RET_NULL: {
auto &v = args.back();
args.emplace_back(cs) = v.get_plain();
args.emplace_back() = v.get_plain();
continue;
}
case BC_INST_DUP | BC_RET_INT: {
auto &v = args.back();
args.emplace_back(cs).set_integer(v.get_integer());
args.emplace_back().set_integer(v.get_integer());
continue;
}
case BC_INST_DUP | BC_RET_FLOAT: {
auto &v = args.back();
args.emplace_back(cs).set_float(v.get_float());
args.emplace_back().set_float(v.get_float());
continue;
}
case BC_INST_DUP | BC_RET_STRING: {
auto &v = args.back();
auto &nv = args.emplace_back(cs);
auto &nv = args.emplace_back();
nv = v;
nv.force_string();
nv.force_string(cs);
continue;
}
case BC_INST_VAL | BC_RET_STRING: {
std::uint32_t len = op >> 8;
args.emplace_back(cs).set_string(std::string_view{
args.emplace_back().set_string(std::string_view{
reinterpret_cast<char const *>(code), len
});
}, cs);
code += len / sizeof(std::uint32_t) + 1;
continue;
}
@ -509,30 +512,32 @@ std::uint32_t *vm_exec(
char((op >> 24) & 0xFF), '\0'
};
/* gotta cast or r.size() == potentially 3 */
args.emplace_back(cs).set_string(static_cast<char const *>(s));
args.emplace_back().set_string(
static_cast<char const *>(s), cs
);
continue;
}
case BC_INST_VAL | BC_RET_NULL:
case BC_INST_VAL_INT | BC_RET_NULL:
args.emplace_back(cs).set_none();
args.emplace_back().set_none();
continue;
case BC_INST_VAL | BC_RET_INT:
args.emplace_back(cs).set_integer(
args.emplace_back().set_integer(
*reinterpret_cast<integer_type const *>(code)
);
code += bc_store_size<integer_type>;
continue;
case BC_INST_VAL_INT | BC_RET_INT:
args.emplace_back(cs).set_integer(integer_type(op) >> 8);
args.emplace_back().set_integer(integer_type(op) >> 8);
continue;
case BC_INST_VAL | BC_RET_FLOAT:
args.emplace_back(cs).set_float(
args.emplace_back().set_float(
*reinterpret_cast<float_type const *>(code)
);
code += bc_store_size<float_type>;
continue;
case BC_INST_VAL_INT | BC_RET_FLOAT:
args.emplace_back(cs).set_float(
args.emplace_back().set_float(
float_type(integer_type(op) >> 8)
);
continue;
@ -544,14 +549,14 @@ std::uint32_t *vm_exec(
for (std::size_t i = 0; i < numlocals; ++i) {
push_alias(
ts, args[offset + i].get_ident(),
ts.idstack.emplace_back(*ts.pstate)
ts.idstack.emplace_back()
);
}
auto cleanup = [&]() {
for (std::size_t i = offset; i < args.size(); ++i) {
pop_alias(ts, args[i].get_ident());
}
ts.idstack.resize(idstsz, ident_stack{*ts.pstate});
ts.idstack.resize(idstsz);
};
try {
code = vm_exec(ts, code, result);
@ -571,7 +576,7 @@ std::uint32_t *vm_exec(
auto v = std::move(args.back());
args.pop_back();
result = cs.run(v.get_code());
force_arg(result, op & BC_INST_RET_MASK);
force_arg(cs, result, op & BC_INST_RET_MASK);
});
continue;
/* fallthrough */
@ -582,7 +587,7 @@ std::uint32_t *vm_exec(
auto v = std::move(args.back());
args.pop_back();
result = cs.run(v.get_code());
force_arg(result, op & BC_INST_RET_MASK);
force_arg(cs, result, op & BC_INST_RET_MASK);
continue;
}
@ -652,7 +657,7 @@ std::uint32_t *vm_exec(
case BC_INST_BLOCK: {
std::uint32_t len = op >> 8;
args.emplace_back(cs).set_code(bcode_p::make_ref(
args.emplace_back().set_code(bcode_p::make_ref(
reinterpret_cast<bcode *>(code + 1)
));
code += len;
@ -660,22 +665,22 @@ std::uint32_t *vm_exec(
}
case BC_INST_EMPTY | BC_RET_NULL:
args.emplace_back(cs).set_code(bcode_p::make_ref(
args.emplace_back().set_code(bcode_p::make_ref(
bcode_get_empty(ts.istate->empty, VAL_NULL)
));
break;
case BC_INST_EMPTY | BC_RET_STRING:
args.emplace_back(cs).set_code(bcode_p::make_ref(
args.emplace_back().set_code(bcode_p::make_ref(
bcode_get_empty(ts.istate->empty, VAL_STRING)
));
break;
case BC_INST_EMPTY | BC_RET_INT:
args.emplace_back(cs).set_code(bcode_p::make_ref(
args.emplace_back().set_code(bcode_p::make_ref(
bcode_get_empty(ts.istate->empty, VAL_INT)
));
break;
case BC_INST_EMPTY | BC_RET_FLOAT:
args.emplace_back(cs).set_code(bcode_p::make_ref(
args.emplace_back().set_code(bcode_p::make_ref(
bcode_get_empty(ts.istate->empty, VAL_FLOAT)
));
break;
@ -691,7 +696,7 @@ std::uint32_t *vm_exec(
gs.gen_main_float(arg.get_float());
break;
case value_type::STRING:
gs.gen_main(arg.get_string());
gs.gen_main(arg.get_string(cs));
break;
default:
gs.gen_main_null();
@ -705,7 +710,7 @@ std::uint32_t *vm_exec(
any_value &arg = args.back();
switch (arg.get_type()) {
case value_type::STRING: {
std::string_view s = arg.get_string();
std::string_view s = arg.get_string(cs);
if (!s.empty()) {
gen_state gs{ts};
gs.gen_main(s);
@ -726,10 +731,10 @@ std::uint32_t *vm_exec(
ts.istate->identmap[op >> 8]
);
if (a->is_arg() && !ident_is_used_arg(a, ts)) {
ts.get_astack(a).push(ts.idstack.emplace_back(*ts.pstate));
ts.get_astack(a).push(ts.idstack.emplace_back());
ts.callstack->usedargs[a->get_index()] = true;
}
args.emplace_back(cs).set_ident(a);
args.emplace_back().set_ident(a);
continue;
}
case BC_INST_IDENT_U: {
@ -737,12 +742,12 @@ std::uint32_t *vm_exec(
ident *id = ts.istate->id_dummy;
if (arg.get_type() == value_type::STRING) {
id = &ts.istate->new_ident(
cs, arg.get_string(), IDENT_FLAG_UNKNOWN
cs, arg.get_string(cs), IDENT_FLAG_UNKNOWN
);
}
alias *a = static_cast<alias *>(id);
if (a->is_arg() && !ident_is_used_arg(id, ts)) {
ts.get_astack(a).push(ts.idstack.emplace_back(*ts.pstate));
ts.get_astack(a).push(ts.idstack.emplace_back());
ts.callstack->usedargs[id->get_index()] = true;
}
arg.set_ident(id);
@ -756,7 +761,7 @@ std::uint32_t *vm_exec(
switch (get_lookupu_type(ts, arg, id, op, ast)) {
case ID_ALIAS:
arg = ast->node->val_s;
arg.force_string();
arg.force_string(cs);
continue;
case ID_SVAR:
arg.set_string(
@ -767,16 +772,16 @@ std::uint32_t *vm_exec(
arg.set_integer(
static_cast<integer_var *>(id)->get_value()
);
arg.force_string();
arg.force_string(cs);
continue;
case ID_FVAR:
arg.set_float(
static_cast<float_var *>(id)->get_value()
);
arg.force_string();
arg.force_string(cs);
continue;
case ID_UNKNOWN:
arg.set_string("");
arg.set_string("", cs);
continue;
default:
continue;
@ -787,11 +792,11 @@ std::uint32_t *vm_exec(
alias_stack *ast;
alias *a = get_lookup_id(ts, op, ast);
if (!a) {
args.emplace_back(cs).set_string("");
args.emplace_back().set_string("", cs);
} else {
auto &v = args.emplace_back(cs);
auto &v = args.emplace_back();
v = ast->node->val_s;
v.force_string();
v.force_string(cs);
}
continue;
}
@ -830,9 +835,9 @@ std::uint32_t *vm_exec(
alias_stack *ast;
alias *a = get_lookup_id(ts, op, ast);
if (!a) {
args.emplace_back(cs).set_integer(0);
args.emplace_back().set_integer(0);
} else {
args.emplace_back(cs).set_integer(
args.emplace_back().set_integer(
ast->node->val_s.get_integer()
);
}
@ -872,9 +877,9 @@ std::uint32_t *vm_exec(
alias_stack *ast;
alias *a = get_lookup_id(ts, op, ast);
if (!a) {
args.emplace_back(cs).set_float(float_type(0));
args.emplace_back().set_float(float_type(0));
} else {
args.emplace_back(cs).set_float(
args.emplace_back().set_float(
ast->node->val_s.get_float()
);
}
@ -914,9 +919,9 @@ std::uint32_t *vm_exec(
alias_stack *ast;
alias *a = get_lookup_id(ts, op, ast);
if (!a) {
args.emplace_back(cs).set_none();
args.emplace_back().set_none();
} else {
args.emplace_back(cs) = ast->node->val_s.get_plain();
args.emplace_back() = ast->node->val_s.get_plain();
}
continue;
}
@ -934,27 +939,27 @@ std::uint32_t *vm_exec(
cs, std::span{&args[args.size() - numconc], numconc},
((op & BC_INST_OP_MASK) == BC_INST_CONC) ? " " : ""
);
args.resize(args.size() - numconc, any_value{cs});
args.emplace_back(cs).set_string(buf);
force_arg(args.back(), op & BC_INST_RET_MASK);
args.resize(args.size() - numconc);
args.emplace_back().set_string(buf);
force_arg(cs, args.back(), op & BC_INST_RET_MASK);
continue;
}
case BC_INST_SVAR | BC_RET_STRING:
case BC_INST_SVAR | BC_RET_NULL:
args.emplace_back(cs).set_string(static_cast<string_var *>(
args.emplace_back().set_string(static_cast<string_var *>(
ts.istate->identmap[op >> 8]
)->get_value());
continue;
case BC_INST_SVAR | BC_RET_INT:
args.emplace_back(cs).set_integer(parse_int(
args.emplace_back().set_integer(parse_int(
static_cast<string_var *>(
ts.istate->identmap[op >> 8]
)->get_value()
));
continue;
case BC_INST_SVAR | BC_RET_FLOAT:
args.emplace_back(cs).set_float(parse_float(
args.emplace_back().set_float(parse_float(
static_cast<string_var *>(
ts.istate->identmap[op >> 8]
)->get_value()
@ -963,20 +968,20 @@ std::uint32_t *vm_exec(
case BC_INST_IVAR | BC_RET_INT:
case BC_INST_IVAR | BC_RET_NULL:
args.emplace_back(cs).set_integer(static_cast<integer_var *>(
args.emplace_back().set_integer(static_cast<integer_var *>(
ts.istate->identmap[op >> 8]
)->get_value());
continue;
case BC_INST_IVAR | BC_RET_STRING: {
auto &v = args.emplace_back(cs);
auto &v = args.emplace_back();
v.set_integer(static_cast<integer_var *>(
ts.istate->identmap[op >> 8]
)->get_value());
v.force_string();
v.force_string(cs);
continue;
}
case BC_INST_IVAR | BC_RET_FLOAT:
args.emplace_back(cs).set_float(float_type(
args.emplace_back().set_float(float_type(
static_cast<integer_var *>(
ts.istate->identmap[op >> 8]
)->get_value()
@ -985,20 +990,20 @@ std::uint32_t *vm_exec(
case BC_INST_FVAR | BC_RET_FLOAT:
case BC_INST_FVAR | BC_RET_NULL:
args.emplace_back(cs).set_float(static_cast<float_var *>(
args.emplace_back().set_float(static_cast<float_var *>(
ts.istate->identmap[op >> 8]
)->get_value());
continue;
case BC_INST_FVAR | BC_RET_STRING: {
auto &v = args.emplace_back(cs);
auto &v = args.emplace_back();
v.set_float(static_cast<float_var *>(
ts.istate->identmap[op >> 8]
)->get_value());
v.force_string();
v.force_string(cs);
continue;
}
case BC_INST_FVAR | BC_RET_INT:
args.emplace_back(cs).set_integer(
args.emplace_back().set_integer(
integer_type(std::floor(static_cast<float_var *>(
ts.istate->identmap[op >> 8]
)->get_value()))
@ -1021,7 +1026,7 @@ std::uint32_t *vm_exec(
case BC_INST_ALIAS_U: {
auto v = std::move(args.back());
args.pop_back();
cs.set_alias(args.back().get_string(), std::move(v));
cs.set_alias(args.back().get_string(cs), std::move(v));
args.pop_back();
continue;
}
@ -1038,8 +1043,8 @@ std::uint32_t *vm_exec(
auto *imp = static_cast<alias_impl *>(id);
if (imp->is_arg()) {
if (!ident_is_used_arg(id, ts)) {
args.resize(offset, any_value{cs});
force_arg(result, op & BC_INST_RET_MASK);
args.resize(offset);
force_arg(cs, result, op & BC_INST_RET_MASK);
continue;
}
}
@ -1047,7 +1052,7 @@ std::uint32_t *vm_exec(
ts, imp, &args[0], result, callargs,
nnargs, offset, 0, op
);
args.resize(nnargs, any_value{cs});
args.resize(nnargs);
continue;
}
@ -1062,11 +1067,11 @@ std::uint32_t *vm_exec(
if (idarg.get_type() != value_type::STRING) {
litval:
result = std::move(idarg);
force_arg(result, op & BC_INST_RET_MASK);
args.resize(offset - 1, any_value{cs});
force_arg(cs, result, op & BC_INST_RET_MASK);
args.resize(offset - 1);
continue;
}
auto idn = idarg.get_string();
auto idn = idarg.get_string(cs);
ident *id = cs.get_ident(idn);
if (!id) {
noid:
@ -1074,7 +1079,7 @@ noid:
goto litval;
}
result.force_none();
force_arg(result, op & BC_INST_RET_MASK);
force_arg(cs, result, op & BC_INST_RET_MASK);
std::string_view ids{idn};
throw error{
cs, "unknown command: %s", ids.data()
@ -1084,8 +1089,8 @@ noid:
switch (ident_p{*id}.impl().p_type) {
default:
if (!ident_is_callable(id)) {
args.resize(offset - 1, any_value{cs});
force_arg(result, op & BC_INST_RET_MASK);
args.resize(offset - 1);
force_arg(cs, result, op & BC_INST_RET_MASK);
continue;
}
/* fallthrough */
@ -1093,12 +1098,12 @@ noid:
auto *cimp = static_cast<command_impl *>(id);
args.resize(offset + std::max(
std::size_t(cimp->get_num_args()), callargs
), any_value{cs});
));
exec_command(
ts, cimp, cimp, &args[offset], result, callargs
);
force_arg(result, op & BC_INST_RET_MASK);
args.resize(offset - 1, any_value{cs});
force_arg(cs, result, op & BC_INST_RET_MASK);
args.resize(offset - 1);
continue;
}
case ID_LOCAL: {
@ -1106,14 +1111,14 @@ noid:
for (size_t j = 0; j < size_t(callargs); ++j) {
push_alias(
ts, &args[offset + j].force_ident(cs),
ts.idstack.emplace_back(*ts.pstate)
ts.idstack.emplace_back()
);
}
auto cleanup = [&]() {
for (size_t j = 0; j < size_t(callargs); ++j) {
pop_alias(ts, args[offset + j].get_ident());
}
ts.idstack.resize(idstsz, ident_stack{*ts.pstate});
ts.idstack.resize(idstsz);
};
try {
code = vm_exec(ts, code, result);
@ -1128,52 +1133,52 @@ noid:
auto *hid = ts.istate->cmd_ivar;
auto *cimp = static_cast<command_impl *>(hid);
/* the $ argument */
args.insert(offset, any_value{cs});
args.insert(offset, any_value{});
args.resize(offset + std::max(
std::size_t(cimp->get_num_args()), callargs
), any_value{cs});
));
exec_command(
ts, cimp, id, &args[offset], result, callargs
);
force_arg(result, op & BC_INST_RET_MASK);
args.resize(offset - 1, any_value{cs});
force_arg(cs, result, op & BC_INST_RET_MASK);
args.resize(offset - 1);
continue;
}
case ID_FVAR: {
auto *hid = ts.istate->cmd_fvar;
auto *cimp = static_cast<command_impl *>(hid);
/* the $ argument */
args.insert(offset, any_value{cs});
args.insert(offset, any_value{});
args.resize(offset + std::max(
std::size_t(cimp->get_num_args()), callargs
), any_value{cs});
));
exec_command(
ts, cimp, id, &args[offset], result, callargs
);
force_arg(result, op & BC_INST_RET_MASK);
args.resize(offset - 1, any_value{cs});
force_arg(cs, result, op & BC_INST_RET_MASK);
args.resize(offset - 1);
continue;
}
case ID_SVAR: {
auto *hid = ts.istate->cmd_svar;
auto *cimp = static_cast<command_impl *>(hid);
/* the $ argument */
args.insert(offset, any_value{cs});
args.insert(offset, any_value{});
args.resize(offset + std::max(
std::size_t(cimp->get_num_args()), callargs
), any_value{cs});
));
exec_command(
ts, cimp, id, &args[offset], result, callargs
);
force_arg(result, op & BC_INST_RET_MASK);
args.resize(offset - 1, any_value{cs});
force_arg(cs, result, op & BC_INST_RET_MASK);
args.resize(offset - 1);
continue;
}
case ID_ALIAS: {
alias *a = static_cast<alias *>(id);
if (a->is_arg() && !ident_is_used_arg(a, ts)) {
args.resize(offset - 1, any_value{cs});
force_arg(result, op & BC_INST_RET_MASK);
args.resize(offset - 1);
force_arg(cs, result, op & BC_INST_RET_MASK);
continue;
}
if (!exec_alias(
@ -1182,7 +1187,7 @@ noid:
)) {
goto noid;
}
args.resize(nnargs, any_value{cs});
args.resize(nnargs);
continue;
}
}
@ -1200,8 +1205,8 @@ noid:
id->call(ts, std::span<any_value>{
&args[offset], std::size_t(id->get_num_args())
}, result);
force_arg(result, op & BC_INST_RET_MASK);
args.resize(offset, any_value{cs});
force_arg(cs, result, op & BC_INST_RET_MASK);
args.resize(offset);
continue;
}
@ -1216,8 +1221,8 @@ noid:
std::size_t offset = args.size() - callargs;
result.force_none();
id->call(ts, std::span{&args[offset], callargs}, result);
force_arg(result, op & BC_INST_RET_MASK);
args.resize(offset, any_value{cs});
force_arg(cs, result, op & BC_INST_RET_MASK);
args.resize(offset);
continue;
}
case BC_INST_COM_C | BC_RET_NULL:
@ -1231,14 +1236,14 @@ noid:
std::size_t offset = args.size() - callargs;
result.force_none();
{
any_value tv{cs};
any_value tv{};
tv.set_string(concat_values(cs, std::span{
&args[offset], callargs
}, " "));
id->call(ts, std::span<any_value>{&tv, 1}, result);
}
force_arg(result, op & BC_INST_RET_MASK);
args.resize(offset, any_value{cs});
force_arg(cs, result, op & BC_INST_RET_MASK);
args.resize(offset);
continue;
}
}

View File

@ -35,7 +35,7 @@ struct stack_guard {
{}
~stack_guard() {
tsp->vmstack.resize(oldtop, any_value{*tsp->pstate});
tsp->vmstack.resize(oldtop);
}
stack_guard(stack_guard const &) = delete;
@ -55,7 +55,7 @@ static void call_with_args(thread_state &ts, F body) {
auto &ast = ts.get_astack(
static_cast<alias *>(ts.istate->identmap[i])
);
auto &st = ts.idstack.emplace_back(*ts.pstate);
auto &st = ts.idstack.emplace_back();
st.next = ast.node;
ast.node = ast.node->next;
}
@ -84,7 +84,7 @@ static void call_with_args(thread_state &ts, F body) {
}
mask2 >>= 1;
}
ts.idstack.resize(noff, ident_stack{*ts.pstate});
ts.idstack.resize(noff);
};
try {
body();

View File

@ -16,7 +16,7 @@ static inline void do_loop(
return;
}
if (alias_local st{cs, &id}; st) {
any_value idv{cs};
any_value idv{};
for (integer_type i = 0; i < n; ++i) {
idv.set_integer(offset + i * step);
st.set(idv);
@ -42,11 +42,11 @@ static inline void do_loop_conc(
}
if (alias_local st{cs, &id}; st) {
charbuf s{cs};
any_value idv{cs};
any_value idv{};
for (integer_type i = 0; i < n; ++i) {
idv.set_integer(offset + i * step);
st.set(idv);
any_value v{cs};
any_value v{};
switch (cs.run_loop(body, v)) {
case loop_state::BREAK:
goto end;
@ -58,16 +58,16 @@ static inline void do_loop_conc(
if (space && i) {
s.push_back(' ');
}
s.append(v.get_string());
s.append(v.get_string(cs));
}
end:
res.set_string(s.str());
res.set_string(s.str(), cs);
}
}
void init_lib_base(state &gcs) {
gcs.new_command("error", "s", [](auto &cs, auto args, auto &) {
throw error{cs, args[0].get_string()};
throw error{cs, args[0].get_string(cs)};
});
gcs.new_command("pcall", "err", [](auto &cs, auto args, auto &ret) {
@ -77,16 +77,16 @@ void init_lib_base(state &gcs) {
ret.set_integer(0);
return;
}
any_value result{cs}, tback{cs};
any_value result{}, tback{};
bool rc = true;
try {
result = cs.run(args[0].get_code());
} catch (error const &e) {
result.set_string(e.what());
result.set_string(e.what(), cs);
if (e.get_stack().get()) {
charbuf buf{cs};
print_stack(std::back_inserter(buf), e.get_stack());
tback.set_string(buf.str());
tback.set_string(buf.str(), cs);
}
rc = false;
}
@ -145,11 +145,11 @@ void init_lib_base(state &gcs) {
});
gcs.new_command("cases", "ste2V", [](auto &cs, auto args, auto &res) {
string_ref val = args[0].get_string();
string_ref val = args[0].get_string(cs);
for (size_t i = 1; (i + 1) < args.size(); i += 2) {
if (
(args[i].get_type() == value_type::NONE) ||
(args[i].get_string() == val)
(args[i].get_string(cs) == val)
) {
res = cs.run(args[i + 1].get_code());
return;
@ -317,19 +317,19 @@ end:
});
gcs.new_command("resetvar", "s", [](auto &cs, auto args, auto &) {
cs.reset_var(args[0].get_string());
cs.reset_var(args[0].get_string(cs));
});
gcs.new_command("alias", "st", [](auto &cs, auto args, auto &) {
cs.set_alias(args[0].get_string(), args[1]);
cs.set_alias(args[0].get_string(cs), args[1]);
});
gcs.new_command("identexists", "s", [](auto &cs, auto args, auto &res) {
res.set_integer(cs.have_ident(args[0].get_string()));
res.set_integer(cs.have_ident(args[0].get_string(cs)));
});
gcs.new_command("getalias", "s", [](auto &cs, auto args, auto &res) {
auto *id = cs.get_alias(args[0].get_string());
auto *id = cs.get_alias(args[0].get_string(cs));
if (id) {
res = id->get_value(cs);
}

View File

@ -13,22 +13,22 @@ struct arg_val;
template<>
struct arg_val<integer_type> {
static integer_type get(any_value &tv) {
static integer_type get(any_value &tv, state &) {
return tv.get_integer();
}
};
template<>
struct arg_val<float_type> {
static float_type get(any_value &tv) {
static float_type get(any_value &tv, state &) {
return tv.get_float();
}
};
template<>
struct arg_val<std::string_view> {
static std::string_view get(any_value &tv) {
return tv.get_string();
static std::string_view get(any_value &tv, state &cs) {
return tv.get_string(cs);
}
};
@ -37,8 +37,8 @@ static inline void list_find(
state &cs, std::span<any_value> args, any_value &res, F cmp
) {
integer_type n = 0, skip = args[2].get_integer();
T val = arg_val<T>::get(args[1]);
for (list_parser p{cs, args[0].get_string()}; p.parse(); ++n) {
T val = arg_val<T>::get(args[1], cs);
for (list_parser p{cs, args[0].get_string(cs)}; p.parse(); ++n) {
if (cmp(p, val)) {
res.set_integer(n);
return;
@ -58,8 +58,8 @@ template<typename T, typename F>
static inline void list_assoc(
state &cs, std::span<any_value> args, any_value &res, F cmp
) {
T val = arg_val<T>::get(args[1]);
for (list_parser p{cs, args[0].get_string()}; p.parse();) {
T val = arg_val<T>::get(args[1], cs);
for (list_parser p{cs, args[0].get_string(cs)}; p.parse();) {
if (cmp(p, val)) {
if (p.parse()) {
res.set_string(p.get_item());
@ -77,7 +77,7 @@ static void loop_list_conc(
bcode_ref &&body, bool space
) {
if (alias_local st{cs, id}; st) {
any_value idv{cs};
any_value idv{};
charbuf r{cs};
int n = 0;
for (list_parser p{cs, list}; p.parse(); ++n) {
@ -86,7 +86,7 @@ static void loop_list_conc(
if (n && space) {
r.push_back(' ');
}
any_value v{cs};
any_value v{};
switch (cs.run_loop(body, v)) {
case loop_state::BREAK:
goto end;
@ -95,10 +95,10 @@ static void loop_list_conc(
default:
break;
}
r.append(v.get_string());
r.append(v.get_string(cs));
}
end:
res.set_string(r.str());
res.set_string(r.str(), cs);
}
}
@ -119,8 +119,8 @@ template<bool PushList, bool Swap, typename F>
static inline void list_merge(
state &cs, std::span<any_value> args, any_value &res, F cmp
) {
std::string_view list = args[0].get_string();
std::string_view elems = args[1].get_string();
std::string_view list = args[0].get_string(cs);
std::string_view elems = args[1].get_string(cs);
charbuf buf{cs};
if (PushList) {
buf.append(list);
@ -136,14 +136,16 @@ static inline void list_merge(
buf.append(p.get_quoted_item());
}
}
res.set_string(buf.str());
res.set_string(buf.str(), cs);
}
static void init_lib_list_sort(state &cs);
void init_lib_list(state &gcs) {
gcs.new_command("listlen", "s", [](auto &cs, auto args, auto &res) {
res.set_integer(integer_type(list_parser{cs, args[0].get_string()}.count()));
res.set_integer(
integer_type(list_parser{cs, args[0].get_string(cs)}.count())
);
});
gcs.new_command("at", "si1V", [](auto &cs, auto args, auto &res) {
@ -154,7 +156,7 @@ void init_lib_list(state &gcs) {
res = args[0];
return;
}
auto str = args[0].get_string();
auto str = args[0].get_string(cs);
list_parser p{cs, str};
for (size_t i = 1; i < args.size(); ++i) {
p.set_input(str);
@ -179,7 +181,7 @@ void init_lib_list(state &gcs) {
integer_type offset = std::max(skip, integer_type(0)),
len = (numargs >= 3) ? std::max(count, integer_type(0)) : -1;
list_parser p{cs, args[0].get_string()};
list_parser p{cs, args[0].get_string(cs)};
for (integer_type i = 0; i < offset; ++i) {
if (!p.parse()) break;
}
@ -187,7 +189,7 @@ void init_lib_list(state &gcs) {
if (offset > 0) {
p.skip_until_item();
}
res.set_string(p.get_input());
res.set_string(p.get_input(), cs);
return;
}
@ -195,22 +197,22 @@ void init_lib_list(state &gcs) {
if (len > 0 && p.parse()) {
while (--len > 0 && p.parse());
} else {
res.set_string("");
res.set_string("", cs);
return;
}
auto quote = p.get_quoted_item();
auto *qend = &quote[quote.size()];
res.set_string(std::string_view{list, qend});
res.set_string(std::string_view{list, qend}, cs);
});
gcs.new_command("listfind", "rse", [](auto &cs, auto args, auto &res) {
if (alias_local st{cs, args[0].get_ident()}; st) {
any_value idv{cs};
any_value idv{};
auto body = args[2].get_code();
int n = -1;
for (list_parser p{cs, args[1].get_string()}; p.parse();) {
for (list_parser p{cs, args[1].get_string(cs)}; p.parse();) {
++n;
idv.set_string(p.get_raw_item());
idv.set_string(p.get_raw_item(), cs);
st.set(std::move(idv));
if (cs.run(body).get_bool()) {
res.set_integer(integer_type(n));
@ -223,12 +225,12 @@ void init_lib_list(state &gcs) {
gcs.new_command("listassoc", "rse", [](auto &cs, auto args, auto &res) {
if (alias_local st{cs, args[0].get_ident()}; st) {
any_value idv{cs};
any_value idv{};
auto body = args[2].get_code();
int n = -1;
for (list_parser p{cs, args[1].get_string()}; p.parse();) {
for (list_parser p{cs, args[1].get_string(cs)}; p.parse();) {
++n;
idv.set_string(p.get_raw_item());
idv.set_string(p.get_raw_item(), cs);
st.set(std::move(idv));
if (cs.run(body).get_bool()) {
if (p.parse()) {
@ -289,10 +291,10 @@ void init_lib_list(state &gcs) {
gcs.new_command("looplist", "rse", [](auto &cs, auto args, auto &) {
if (alias_local st{cs, args[0].get_ident()}; st) {
any_value idv{cs};
any_value idv{};
auto body = args[2].get_code();
int n = 0;
for (list_parser p{cs, args[1].get_string()}; p.parse(); ++n) {
for (list_parser p{cs, args[1].get_string(cs)}; p.parse(); ++n) {
idv.set_string(p.get_item());
st.set(std::move(idv));
switch (cs.run_loop(body)) {
@ -311,16 +313,16 @@ void init_lib_list(state &gcs) {
if (!st1 || !st2) {
return;
}
any_value idv{cs};
any_value idv{};
auto body = args[3].get_code();
int n = 0;
for (list_parser p{cs, args[2].get_string()}; p.parse(); n += 2) {
for (list_parser p{cs, args[2].get_string(cs)}; p.parse(); n += 2) {
idv.set_string(p.get_item());
st1.set(std::move(idv));
if (p.parse()) {
idv.set_string(p.get_item());
} else {
idv.set_string("");
idv.set_string("", cs);
}
st2.set(std::move(idv));
switch (cs.run_loop(body)) {
@ -339,22 +341,22 @@ void init_lib_list(state &gcs) {
if (!st1 || !st2 || !st3) {
return;
}
any_value idv{cs};
any_value idv{};
auto body = args[4].get_code();
int n = 0;
for (list_parser p{cs, args[3].get_string()}; p.parse(); n += 3) {
for (list_parser p{cs, args[3].get_string(cs)}; p.parse(); n += 3) {
idv.set_string(p.get_item());
st1.set(std::move(idv));
if (p.parse()) {
idv.set_string(p.get_item());
} else {
idv.set_string("");
idv.set_string("", cs);
}
st2.set(std::move(idv));
if (p.parse()) {
idv.set_string(p.get_item());
} else {
idv.set_string("");
idv.set_string("", cs);
}
st3.set(std::move(idv));
switch (cs.run_loop(body)) {
@ -368,7 +370,7 @@ void init_lib_list(state &gcs) {
gcs.new_command("looplistconcat", "rse", [](auto &cs, auto args, auto &res) {
loop_list_conc(
cs, res, args[0].get_ident(), args[1].get_string(),
cs, res, args[0].get_ident(), args[1].get_string(cs),
args[2].get_code(), true
);
});
@ -377,19 +379,19 @@ void init_lib_list(state &gcs) {
auto &cs, auto args, auto &res
) {
loop_list_conc(
cs, res, args[0].get_ident(), args[1].get_string(),
cs, res, args[0].get_ident(), args[1].get_string(cs),
args[2].get_code(), false
);
});
gcs.new_command("listfilter", "rse", [](auto &cs, auto args, auto &res) {
if (alias_local st{cs, args[0].get_ident()}; st) {
any_value idv{cs};
any_value idv{};
auto body = args[2].get_code();
charbuf r{cs};
int n = 0;
for (list_parser p{cs, args[1].get_string()}; p.parse(); ++n) {
idv.set_string(p.get_raw_item());
for (list_parser p{cs, args[1].get_string(cs)}; p.parse(); ++n) {
idv.set_string(p.get_raw_item(), cs);
st.set(std::move(idv));
if (cs.run(body).get_bool()) {
if (r.size()) {
@ -398,17 +400,17 @@ void init_lib_list(state &gcs) {
r.append(p.get_quoted_item());
}
}
res.set_string(r.str());
res.set_string(r.str(), cs);
}
});
gcs.new_command("listcount", "rse", [](auto &cs, auto args, auto &res) {
if (alias_local st{cs, args[0].get_ident()}; st) {
any_value idv{cs};
any_value idv{};
auto body = args[2].get_code();
int n = 0, r = 0;
for (list_parser p{cs, args[1].get_string()}; p.parse(); ++n) {
idv.set_string(p.get_raw_item());
for (list_parser p{cs, args[1].get_string(cs)}; p.parse(); ++n) {
idv.set_string(p.get_raw_item(), cs);
st.set(std::move(idv));
if (cs.run(body).get_bool()) {
r++;
@ -420,8 +422,8 @@ void init_lib_list(state &gcs) {
gcs.new_command("prettylist", "ss", [](auto &cs, auto args, auto &res) {
charbuf buf{cs};
std::string_view s = args[0].get_string();
std::string_view conj = args[1].get_string();
std::string_view s = args[0].get_string(cs);
std::string_view conj = args[1].get_string(cs);
list_parser p{cs, s};
size_t len = p.count();
size_t n = 0;
@ -443,12 +445,12 @@ void init_lib_list(state &gcs) {
buf.push_back(' ');
}
}
res.set_string(buf.str());
res.set_string(buf.str(), cs);
});
gcs.new_command("indexof", "ss", [](auto &cs, auto args, auto &res) {
res.set_integer(
list_includes(cs, args[0].get_string(), args[1].get_string())
list_includes(cs, args[0].get_string(cs), args[1].get_string(cs))
);
});
@ -465,8 +467,8 @@ void init_lib_list(state &gcs) {
gcs.new_command("listsplice", "ssii", [](auto &cs, auto args, auto &res) {
integer_type offset = std::max(args[2].get_integer(), integer_type(0));
integer_type len = std::max(args[3].get_integer(), integer_type(0));
std::string_view s = args[0].get_string();
std::string_view vals = args[1].get_string();
std::string_view s = args[0].get_string(cs);
std::string_view vals = args[1].get_string(cs);
char const *list = s.data();
list_parser p{cs, s};
for (integer_type i = 0; i < offset; ++i) {
@ -505,7 +507,7 @@ void init_lib_list(state &gcs) {
break;
}
}
res.set_string(buf.str());
res.set_string(buf.str(), cs);
});
init_lib_list_sort(gcs);
@ -522,10 +524,10 @@ struct ListSortFun {
bcode_ref const *body;
bool operator()(ListSortItem const &xval, ListSortItem const &yval) {
any_value v{cs};
v.set_string(xval.str);
any_value v{};
v.set_string(xval.str, cs);
xst.set(std::move(v));
v.set_string(yval.str);
v.set_string(yval.str, cs);
yst.set(std::move(v));
return cs.run(*body).get_bool();
}
@ -554,7 +556,7 @@ static void list_sort(
}
if (items.empty()) {
res.set_string(list);
res.set_string(list, cs);
return;
}
@ -609,19 +611,19 @@ static void list_sort(
}
sorted.append(item.quote);
}
res.set_string(sorted.str());
res.set_string(sorted.str(), cs);
}
static void init_lib_list_sort(state &gcs) {
gcs.new_command("sortlist", "srree", [](auto &cs, auto args, auto &res) {
list_sort(
cs, res, args[0].get_string(), args[1].get_ident(),
cs, res, args[0].get_string(cs), 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) {
list_sort(
cs, res, args[0].get_string(), args[1].get_ident(),
cs, res, args[0].get_string(cs), args[1].get_ident(),
args[2].get_ident(), bcode_ref{}, args[3].get_code()
);
});

View File

@ -11,17 +11,17 @@ namespace cubescript {
template<typename F>
static inline void str_cmp_by(
std::span<any_value> args, any_value &res, F cfunc
state &cs, std::span<any_value> args, any_value &res, F cfunc
) {
bool val;
if (args.size() >= 2) {
val = cfunc(args[0].get_string(), args[1].get_string());
val = cfunc(args[0].get_string(cs), args[1].get_string(cs));
for (size_t i = 2; (i < args.size()) && val; ++i) {
val = cfunc(args[i - 1].get_string(), args[i].get_string());
val = cfunc(args[i - 1].get_string(cs), args[i].get_string(cs));
}
} else {
val = cfunc(
!args.empty() ? args[0].get_string() : std::string_view(),
!args.empty() ? args[0].get_string(cs) : std::string_view(),
std::string_view()
);
}
@ -29,8 +29,9 @@ static inline void str_cmp_by(
}
void init_lib_string(state &cs) {
cs.new_command("strstr", "ss", [](auto &, auto args, auto &res) {
std::string_view a = args[0].get_string(), b = args[1].get_string();
cs.new_command("strstr", "ss", [](auto &ccs, auto args, auto &res) {
std::string_view a = args[0].get_string(ccs);
std::string_view b = args[1].get_string(ccs);
auto pos = a.find(b);
if (pos == a.npos) {
res.set_integer(-1);
@ -39,12 +40,12 @@ void init_lib_string(state &cs) {
}
});
cs.new_command("strlen", "s", [](auto &, auto args, auto &res) {
res.set_integer(integer_type(args[0].get_string().size()));
cs.new_command("strlen", "s", [](auto &ccs, auto args, auto &res) {
res.set_integer(integer_type(args[0].get_string(ccs).size()));
});
cs.new_command("strcode", "si", [](auto &, auto args, auto &res) {
std::string_view str = args[0].get_string();
cs.new_command("strcode", "si", [](auto &ccs, auto args, auto &res) {
std::string_view str = args[0].get_string(ccs);
integer_type i = args[1].get_integer();
if (i >= integer_type(str.size())) {
res.set_integer(0);
@ -53,13 +54,13 @@ void init_lib_string(state &cs) {
}
});
cs.new_command("codestr", "i", [](auto &, auto args, auto &res) {
cs.new_command("codestr", "i", [](auto &ccs, auto args, auto &res) {
char const p[2] = { char(args[0].get_integer()), '\0' };
res.set_string(std::string_view{static_cast<char const *>(p)});
res.set_string(std::string_view{static_cast<char const *>(p)}, ccs);
});
cs.new_command("strlower", "s", [](auto &ccs, auto args, auto &res) {
auto inps = args[0].get_string();
auto inps = args[0].get_string(ccs);
auto *ics = state_p{ccs}.ts().istate;
auto *buf = ics->strman->alloc_buf(inps.size());
for (std::size_t i = 0; i < inps.size(); ++i) {
@ -69,7 +70,7 @@ void init_lib_string(state &cs) {
});
cs.new_command("strupper", "s", [](auto &ccs, auto args, auto &res) {
auto inps = args[0].get_string();
auto inps = args[0].get_string(ccs);
auto *ics = state_p{ccs}.ts().istate;
auto *buf = ics->strman->alloc_buf(inps.size());
for (std::size_t i = 0; i < inps.size(); ++i) {
@ -80,14 +81,14 @@ void init_lib_string(state &cs) {
cs.new_command("escape", "s", [](auto &ccs, auto args, auto &res) {
charbuf s{ccs};
escape_string(std::back_inserter(s), args[0].get_string());
res.set_string(s.str());
escape_string(std::back_inserter(s), args[0].get_string(ccs));
res.set_string(s.str(), ccs);
});
cs.new_command("unescape", "s", [](auto &ccs, auto args, auto &res) {
charbuf s{ccs};
unescape_string(std::back_inserter(s), args[0].get_string());
res.set_string(s.str());
unescape_string(std::back_inserter(s), args[0].get_string(ccs));
res.set_string(s.str(), ccs);
});
cs.new_command("concat", "V", [](auto &ccs, auto args, auto &res) {
@ -103,7 +104,7 @@ void init_lib_string(state &cs) {
return;
}
charbuf s{ccs};
string_ref fs = args[0].get_string();
string_ref fs = args[0].get_string(ccs);
std::string_view f{fs};
for (auto it = f.begin(); it != f.end(); ++it) {
char c = *it;
@ -114,7 +115,7 @@ void init_lib_string(state &cs) {
if ((ic >= '1') && (ic <= '9')) {
int i = ic - '0';
if (std::size_t(i) < args.size()) {
s.append(args[i].get_string());
s.append(args[i].get_string(ccs));
}
} else {
s.push_back(ic);
@ -123,7 +124,7 @@ void init_lib_string(state &cs) {
s.push_back(c);
}
}
res.set_string(s.str());
res.set_string(s.str(), ccs);
});
cs.new_command("tohex", "ii", [](auto &ccs, auto args, auto &res) {
@ -138,19 +139,21 @@ void init_lib_string(state &cs) {
s.data()[0] = '\0';
int nn = snprintf(s.data(), n + 1, "0x%.*llX", prec, val);
if ((nn > 0) && (nn <= n)) {
res.set_string(std::string_view{s.data(), std::size_t(nn)});
res.set_string(
std::string_view{s.data(), std::size_t(nn)}, ccs
);
return;
}
} else if (n > 0) {
res.set_string(static_cast<char const *>(buf));
res.set_string(static_cast<char const *>(buf), ccs);
return;
}
/* should pretty much be unreachable */
throw internal_error{"format error"};
});
cs.new_command("substr", "siiN", [](auto &, auto args, auto &res) {
std::string_view s = args[0].get_string();
cs.new_command("substr", "siiN", [](auto &ccs, auto args, auto &res) {
std::string_view s = args[0].get_string(ccs);
auto start = args[1].get_integer(), count = args[2].get_integer();
auto numargs = args[3].get_integer();
auto len = integer_type(s.size());
@ -160,41 +163,41 @@ void init_lib_string(state &cs) {
((numargs >= 3)
? size_t(std::clamp(count, integer_type(0), len - offset))
: size_t(len - offset))
});
}, ccs);
});
cs.new_command("strcmp", "s1V", [](auto &, auto args, auto &res) {
str_cmp_by(args, res, std::equal_to<std::string_view>());
cs.new_command("strcmp", "s1V", [](auto &ccs, auto args, auto &res) {
str_cmp_by(ccs, args, res, std::equal_to<std::string_view>());
});
cs.new_command("=s", "s1V", [](auto &, auto args, auto &res) {
str_cmp_by(args, res, std::equal_to<std::string_view>());
cs.new_command("=s", "s1V", [](auto &ccs, auto args, auto &res) {
str_cmp_by(ccs, args, res, std::equal_to<std::string_view>());
});
cs.new_command("!=s", "s1V", [](auto &, auto args, auto &res) {
str_cmp_by(args, res, std::not_equal_to<std::string_view>());
cs.new_command("!=s", "s1V", [](auto &ccs, auto args, auto &res) {
str_cmp_by(ccs, args, res, std::not_equal_to<std::string_view>());
});
cs.new_command("<s", "s1V", [](auto &, auto args, auto &res) {
str_cmp_by(args, res, std::less<std::string_view>());
cs.new_command("<s", "s1V", [](auto &ccs, auto args, auto &res) {
str_cmp_by(ccs, args, res, std::less<std::string_view>());
});
cs.new_command(">s", "s1V", [](auto &, auto args, auto &res) {
str_cmp_by(args, res, std::greater<std::string_view>());
cs.new_command(">s", "s1V", [](auto &ccs, auto args, auto &res) {
str_cmp_by(ccs, args, res, std::greater<std::string_view>());
});
cs.new_command("<=s", "s1V", [](auto &, auto args, auto &res) {
str_cmp_by(args, res, std::less_equal<std::string_view>());
cs.new_command("<=s", "s1V", [](auto &ccs, auto args, auto &res) {
str_cmp_by(ccs, args, res, std::less_equal<std::string_view>());
});
cs.new_command(">=s", "s1V", [](auto &, auto args, auto &res) {
str_cmp_by(args, res, std::greater_equal<std::string_view>());
cs.new_command(">=s", "s1V", [](auto &ccs, auto args, auto &res) {
str_cmp_by(ccs, args, res, std::greater_equal<std::string_view>());
});
cs.new_command("strreplace", "ssss", [](auto &ccs, auto args, auto &res) {
std::string_view s = args[0].get_string();
std::string_view oldval = args[1].get_string(),
newval = args[2].get_string(),
newval2 = args[3].get_string();
std::string_view s = args[0].get_string(ccs);
std::string_view oldval = args[1].get_string(ccs),
newval = args[2].get_string(ccs),
newval2 = args[3].get_string(ccs);
if (newval2.empty()) {
newval2 = newval;
}
if (oldval.empty()) {
res.set_string(s);
res.set_string(s, ccs);
return;
}
charbuf buf{ccs};
@ -202,7 +205,7 @@ void init_lib_string(state &cs) {
auto p = s.find(oldval);
if (p == s.npos) {
buf.append(s);
res.set_string(s);
res.set_string(s, ccs);
return;
}
buf.append(s.substr(0, p));
@ -215,8 +218,8 @@ void init_lib_string(state &cs) {
});
cs.new_command("strsplice", "ssii", [](auto &ccs, auto args, auto &res) {
std::string_view s = args[0].get_string();
std::string_view vals = args[1].get_string();
std::string_view s = args[0].get_string(ccs);
std::string_view vals = args[1].get_string(ccs);
integer_type skip = args[2].get_integer(),
count = args[3].get_integer();
integer_type offset = std::clamp(skip, integer_type(0), integer_type(s.size())),
@ -230,7 +233,7 @@ void init_lib_string(state &cs) {
if ((offset + len) < integer_type(s.size())) {
p.append(s.substr(offset + len, s.size() - offset - len));
}
res.set_string(p.str());
res.set_string(p.str(), ccs);
});
}

View File

@ -229,7 +229,7 @@ static bool do_run_file(
}
static bool do_call(cs::state &cs, std::string_view line, bool file = false) {
cs::any_value ret{cs};
cs::any_value ret{};
scs = &cs;
signal(SIGINT, do_sigint);
try {
@ -271,7 +271,7 @@ static bool do_call(cs::state &cs, std::string_view line, bool file = false) {
signal(SIGINT, SIG_DFL);
scs = nullptr;
if (ret.get_type() != cs::value_type::NONE) {
std::printf("%s\n", std::string_view{ret.get_string()}.data());
std::printf("%s\n", std::string_view{ret.get_string(cs)}.data());
}
return false;
}
@ -362,8 +362,8 @@ int main(int argc, char **argv) {
});
gcs.new_command("exec", "s", [](auto &css, auto args, auto &) {
auto file = args[0].get_string();
cs::any_value val{css};
auto file = args[0].get_string(css);
cs::any_value val{};
bool ret = do_run_file(css, file, val);
if (!ret) {
throw cs::error(
@ -372,8 +372,8 @@ int main(int argc, char **argv) {
}
});
gcs.new_command("echo", "C", [](auto &, auto args, auto &) {
std::printf("%s\n", std::string_view{args[0].get_string()}.data());
gcs.new_command("echo", "C", [](auto &css, auto args, auto &) {
std::printf("%s\n", std::string_view{args[0].get_string(css)}.data());
});
int firstarg = 0;