eliminate type separation between IVAR/FVAR/SVAR

master
Daniel Kolesa 2021-05-07 00:07:13 +02:00
parent 6218adb78a
commit 9437e0951b
6 changed files with 60 additions and 174 deletions

View File

@ -23,9 +23,7 @@ namespace cubescript {
* Cubescript has a selection of idents. This represents the type of each.
*/
enum class ident_type {
IVAR = 0, /**< @brief Integer builtin variable. */
FVAR, /**< @brief Float builtin variable. */
SVAR, /**< @brief String builtin variable. */
VAR = 0, /**< @brief Builtin variable. */
COMMAND, /**< @brief Builtin command. */
ALIAS, /**< @brief User assigned variable. */
SPECIAL /**< @brief Other (internal unexposed type). */
@ -67,13 +65,6 @@ struct LIBCUBESCRIPT_EXPORT ident {
/** @brief Check if the idents are not the same. */
bool operator!=(ident &other) const;
/** @brief Check if the ident is a cubescript::builtin_var.
*
* This will return `true` if ident::type() returns either
* ident_type::IVAR, ident_type::FVAR or ident_type::SVAR.
*/
bool is_var() const;
/** @brief Get if the ident is overridden.
*
* This can be true for aliases or builtins. When an alias or a builtin

View File

@ -18,8 +18,8 @@ bool ident_is_callable(ident const *id) {
return !!static_cast<command_impl const *>(id)->p_cb_cftv;
}
var_impl::var_impl(ident_type tp, string_ref name, int fl):
ident_impl{tp, name, fl}
var_impl::var_impl(string_ref name, int fl):
ident_impl{ident_type::VAR, name, fl}
{}
alias_impl::alias_impl(
@ -69,24 +69,16 @@ command_impl::command_impl(
p_cargs{args}, p_cb_cftv{std::move(f)}, p_numargs{nargs}
{}
void var_changed(thread_state &ts, ident *id, any_value &oldval) {
void var_changed(thread_state &ts, builtin_var &id, any_value &oldval) {
auto *cid = ts.istate->cmd_var_changed;
if (!cid) {
return;
}
auto *cimp = static_cast<command_impl *>(cid);
any_value val[3] = {};
val[0].set_ident(*id);
val[0].set_ident(id);
val[1] = std::move(oldval);
switch (id->type()) {
case ident_type::IVAR:
case ident_type::FVAR:
case ident_type::SVAR:
val[2] = static_cast<builtin_var *>(id)->value();
break;
default:
return;
}
val[2] = id.value();
cimp->call(ts, span_type<any_value>{
static_cast<any_value *>(val), 3
}, val[0]);
@ -96,6 +88,21 @@ void var_impl::save_val() {
p_override = std::move(p_storage);
}
command *var_impl::get_setter(thread_state &ts) const {
switch (p_storage.type()) {
case value_type::INTEGER:
return ts.istate->cmd_ivar;
case value_type::FLOAT:
return ts.istate->cmd_fvar;
case value_type::STRING:
return ts.istate->cmd_svar;
default:
break;
}
abort();
return nullptr; /* not reached */
}
void command_impl::call(
thread_state &ts, span_type<any_value> args, any_value &ret
) const {
@ -172,23 +179,9 @@ LIBCUBESCRIPT_EXPORT bool ident::operator!=(ident &other) const {
return this != &other;
}
LIBCUBESCRIPT_EXPORT bool ident::is_var() const {
switch (type()) {
case ident_type::IVAR:
case ident_type::FVAR:
case ident_type::SVAR:
return true;
default:
break;
}
return false;
}
LIBCUBESCRIPT_EXPORT bool ident::is_overridden(state &cs) const {
switch (type()) {
case ident_type::IVAR:
case ident_type::FVAR:
case ident_type::SVAR:
case ident_type::VAR:
return (p_impl->p_flags & IDENT_FLAG_OVERRIDDEN);
case ident_type::ALIAS:
return (state_p{cs}.ts().get_astack(
@ -202,9 +195,7 @@ LIBCUBESCRIPT_EXPORT bool ident::is_overridden(state &cs) const {
LIBCUBESCRIPT_EXPORT bool ident::is_persistent(state &cs) const {
switch (type()) {
case ident_type::IVAR:
case ident_type::FVAR:
case ident_type::SVAR:
case ident_type::VAR:
return (p_impl->p_flags & IDENT_FLAG_PERSIST);
case ident_type::ALIAS:
return (state_p{cs}.ts().get_astack(
@ -259,21 +250,7 @@ LIBCUBESCRIPT_EXPORT void builtin_var::save(state &cs) {
LIBCUBESCRIPT_EXPORT any_value builtin_var::call(
span_type<any_value> args, state &cs
) {
command *hid;
switch (static_cast<var_impl *>(p_impl)->p_storage.type()) {
case value_type::INTEGER:
hid = state_p{cs}.ts().istate->cmd_ivar;
break;
case value_type::FLOAT:
hid = state_p{cs}.ts().istate->cmd_fvar;
break;
case value_type::STRING:
hid = state_p{cs}.ts().istate->cmd_svar;
break;
default:
abort(); /* unreachable unless we have a bug */
break;
}
command *hid = static_cast<var_impl *>(this)->get_setter(state_p{cs}.ts());
any_value ret{};
auto &ts = state_p{cs}.ts();
auto *cimp = static_cast<command_impl *>(hid);
@ -330,7 +307,7 @@ LIBCUBESCRIPT_EXPORT void builtin_var::set_value(
auto oldv = value();
set_raw_value(cs, std::move(val));
if (trigger) {
var_changed(state_p{cs}.ts(), this, oldv);
var_changed(state_p{cs}.ts(), *this, oldv);
}
}

View File

@ -11,7 +11,7 @@ static constexpr std::size_t MAX_ARGUMENTS = 32;
using argset = std::bitset<MAX_ARGUMENTS>;
enum {
ID_UNKNOWN = -1, ID_IVAR, ID_FVAR, ID_SVAR, ID_COMMAND, ID_ALIAS,
ID_UNKNOWN = -1, ID_VAR, ID_COMMAND, ID_ALIAS,
ID_LOCAL, ID_DO, ID_DOARGS, ID_IF, ID_BREAK, ID_CONTINUE, ID_RESULT,
ID_NOT, ID_AND, ID_OR
};
@ -74,17 +74,17 @@ struct ident_impl {
bool ident_is_callable(ident const *id);
struct var_impl: ident_impl, builtin_var {
var_impl(ident_type tp, string_ref name, int flags);
var_impl(string_ref name, int flags);
void save_val();
void changed(thread_state &ts);
command *get_setter(thread_state &ts) const;
any_value p_storage{};
any_value p_override{};
};
void var_changed(thread_state &ts, ident *id, any_value &oldval);
void var_changed(thread_state &ts, builtin_var &id, any_value &oldval);
struct alias_impl: ident_impl, alias {
alias_impl(state &cs, string_ref n, string_ref a, int flags);

View File

@ -480,31 +480,18 @@ lookup_id:
*ts.pstate, lookup.str_term(), IDENT_FLAG_UNKNOWN
);
switch (id.type()) {
case ident_type::IVAR:
case ident_type::FVAR:
case ident_type::VAR: {
if (ltype == VAL_POP) {
return;
}
gs.gen_lookup_var(id, ltype);
switch (ltype) {
case VAL_CODE:
case VAL_IDENT:
lookup_done(gs, ltype);
break;
default:
break;
}
return;
case ident_type::SVAR:
switch (ltype) {
case VAL_POP:
return;
default:
gs.gen_lookup_var(id, ltype);
break;
auto vt = static_cast<var_impl &>(id).p_storage.type();
if ((vt != value_type::STRING) && (ltype == VAL_COND)) {
return;
}
lookup_done(gs, ltype);
return;
}
case ident_type::ALIAS:
switch (ltype) {
case VAL_POP:
@ -591,9 +578,7 @@ lookup_id:
*ts.pstate, lookup.str_term(), IDENT_FLAG_UNKNOWN
);
switch (id.type()) {
case ident_type::IVAR:
case ident_type::FVAR:
case ident_type::SVAR:
case ident_type::VAR:
gs.gen_lookup_var(id);
return true;
case ident_type::ALIAS:
@ -1202,24 +1187,10 @@ bool parser_state::parse_call_id(ident &id, int ltype) {
case ID_AND:
case ID_OR:
return parse_id_and_or(id, ltype);
case ID_IVAR: {
auto *hid = ts.istate->cmd_ivar;
return parse_call_command(
static_cast<command_impl *>(hid), id, ltype
);
}
case ID_FVAR: {
auto *hid = ts.istate->cmd_fvar;
return parse_call_command(
static_cast<command_impl *>(hid), id, ltype
);
}
case ID_SVAR: {
auto *hid = ts.istate->cmd_svar;
return parse_call_command(
static_cast<command_impl *>(hid), id, ltype
);
}
case ID_VAR:
return parse_call_command(static_cast<command_impl *>(
static_cast<var_impl &>(id).get_setter(ts)
), id, ltype);
default:
/* unreachable */
break;
@ -1330,22 +1301,10 @@ bool parser_state::parse_assign(
gs.gen_assign_alias(id);
return finish_statement(*this, more, term);
}
case ident_type::IVAR: {
auto *hid = ts.istate->cmd_ivar;
bool more = parse_assign_var(
*this, static_cast<command_impl *>(hid), id, ltype
);
return finish_statement(*this, more, term);
}
case ident_type::FVAR: {
auto *hid = ts.istate->cmd_fvar;
bool more = parse_assign_var(
*this, static_cast<command_impl *>(hid), id, ltype
);
return finish_statement(*this, more, term);
}
case ident_type::SVAR: {
auto *hid = ts.istate->cmd_svar;
case ident_type::VAR: {
command *hid = static_cast<var_impl &>(
id
).get_setter(ts);
bool more = parse_assign_var(
*this, static_cast<command_impl *>(hid), id, ltype
);

View File

@ -349,13 +349,11 @@ LIBCUBESCRIPT_EXPORT void state::clear_override(ident &id) {
ast.flags &= ~IDENT_FLAG_OVERRIDDEN;
return;
}
case ident_type::IVAR:
case ident_type::FVAR:
case ident_type::SVAR: {
case ident_type::VAR: {
auto &v = static_cast<var_impl &>(id);
any_value oldv = v.value();
v.p_storage = std::move(v.p_override);
var_changed(*p_tstate, &id, oldv);
var_changed(*p_tstate, v, oldv);
static_cast<var_impl *>(
static_cast<builtin_var *>(&v)
)->p_flags &= ~IDENT_FLAG_OVERRIDDEN;
@ -409,7 +407,7 @@ LIBCUBESCRIPT_EXPORT builtin_var &state::new_var(
std::string_view n, integer_type v, bool read_only, var_type vtp
) {
auto *iv = p_tstate->istate->create<var_impl>(
ident_type::IVAR, string_ref{*this, n},var_flags(read_only, vtp)
string_ref{*this, n},var_flags(read_only, vtp)
);
iv->p_storage.set_integer(v);
try {
@ -426,7 +424,7 @@ LIBCUBESCRIPT_EXPORT builtin_var &state::new_var(
std::string_view n, float_type v, bool read_only, var_type vtp
) {
auto *fv = p_tstate->istate->create<var_impl>(
ident_type::FVAR, string_ref{*this, n}, var_flags(read_only, vtp)
string_ref{*this, n}, var_flags(read_only, vtp)
);
fv->p_storage.set_float(v);
try {
@ -443,7 +441,7 @@ LIBCUBESCRIPT_EXPORT builtin_var &state::new_var(
std::string_view n, std::string_view v, bool read_only, var_type vtp
) {
auto *sv = p_tstate->istate->create<var_impl>(
ident_type::SVAR, string_ref{*this, n}, var_flags(read_only, vtp)
string_ref{*this, n}, var_flags(read_only, vtp)
);
sv->p_storage.set_string(v, *this);
try {
@ -470,9 +468,7 @@ LIBCUBESCRIPT_EXPORT void state::assign_value(
static_cast<alias &>(id->get()).set_value(*this, std::move(v));
return;
}
case ident_type::IVAR:
case ident_type::FVAR:
case ident_type::SVAR:
case ident_type::VAR:
id->get().call(span_type<any_value>{&v, 1}, *this);
break;
default:
@ -514,9 +510,7 @@ LIBCUBESCRIPT_EXPORT any_value state::lookup_value(std::string_view name) {
}
return ast->node->val_s.get_plain();
}
case ident_type::SVAR:
case ident_type::IVAR:
case ident_type::FVAR:
case ident_type::VAR:
return static_cast<builtin_var *>(id)->value();
case ident_type::COMMAND: {
any_value val{};
@ -545,7 +539,7 @@ LIBCUBESCRIPT_EXPORT void state::reset_value(std::string_view name) {
if (!id) {
throw error{*this, "variable '%s' does not exist", name.data()};
}
if (id->get().is_var()) {
if (id->get().type() == ident_type::VAR) {
if (static_cast<builtin_var &>(id->get()).is_read_only()) {
throw error{*this, "variable '%s' is read only", name.data()};
}
@ -559,17 +553,12 @@ LIBCUBESCRIPT_EXPORT void state::touch_value(std::string_view name) {
return;
}
auto &idr = id->get();
any_value v;
switch (idr.type()) {
case ident_type::IVAR:
case ident_type::FVAR:
case ident_type::SVAR:
v = static_cast<builtin_var &>(idr).value();
break;
default:
return;
if (idr.type() != ident_type::VAR) {
return;
}
var_changed(*p_tstate, &idr, v);
auto &v = static_cast<builtin_var &>(idr);
auto vv = v.value();
var_changed(*p_tstate, v, vv);
}
static char const *allowed_builtins[] = {

View File

@ -847,40 +847,10 @@ noid:
cleanup();
return code;
}
case ID_IVAR: {
auto *hid = ts.istate->cmd_ivar;
auto *cimp = static_cast<command_impl *>(hid);
/* the $ argument */
args.insert(offset, any_value{});
args.resize(offset + std::max(
std::size_t(cimp->arg_count()), callargs
));
exec_command(
ts, cimp, &id->get(), &args[offset],
result, callargs
);
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{});
args.resize(offset + std::max(
std::size_t(cimp->arg_count()), callargs
));
exec_command(
ts, cimp, &id->get(), &args[offset],
result, callargs
);
force_arg(cs, result, op & BC_INST_RET_MASK);
args.resize(offset - 1);
continue;
}
case ID_SVAR: {
auto *hid = ts.istate->cmd_svar;
case ID_VAR: {
auto *hid = static_cast<var_impl &>(
id->get()
).get_setter(ts);
auto *cimp = static_cast<command_impl *>(hid);
/* the $ argument */
args.insert(offset, any_value{});