Browse Source

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 3 weeks ago
parent
commit
d358dd83e7
12 changed files with 343 additions and 371 deletions
  1. +8
    -23
      include/cubescript/cubescript/value.hh
  2. +17
    -17
      src/cs_ident.cc
  3. +1
    -1
      src/cs_ident.hh
  4. +10
    -10
      src/cs_state.cc
  5. +14
    -16
      src/cs_strman.cc
  6. +36
    -57
      src/cs_val.cc
  7. +120
    -115
      src/cs_vm.cc
  8. +3
    -3
      src/cs_vm.hh
  9. +15
    -15
      src/lib_base.cc
  10. +61
    -59
      src/lib_list.cc
  11. +52
    -49
      src/lib_str.cc
  12. +6
    -6
      tools/repl.cc

+ 8
- 23
include/cubescript/cubescript/value.hh 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;


+ 17
- 17
src/cs_ident.cc 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;
}


+ 1
- 1
src/cs_ident.hh 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 {


+ 10
- 10
src/cs_state.cc 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);
}


+ 14
- 16
src/cs_strman.cc 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 {


+ 36
- 57
src/cs_val.cc 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:


+ 120
- 115
src/cs_vm.cc 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;
}