diff --git a/include/cubescript/cubescript/ident.hh b/include/cubescript/cubescript/ident.hh index 29fef0a..11ba213 100644 --- a/include/cubescript/cubescript/ident.hh +++ b/include/cubescript/cubescript/ident.hh @@ -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 diff --git a/src/cs_ident.cc b/src/cs_ident.cc index c79a2df..13fdf77 100644 --- a/src/cs_ident.cc +++ b/src/cs_ident.cc @@ -18,8 +18,8 @@ bool ident_is_callable(ident const *id) { return !!static_cast(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(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(id)->value(); - break; - default: - return; - } + val[2] = id.value(); cimp->call(ts, span_type{ static_cast(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 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 args, state &cs ) { - command *hid; - switch (static_cast(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(this)->get_setter(state_p{cs}.ts()); any_value ret{}; auto &ts = state_p{cs}.ts(); auto *cimp = static_cast(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); } } diff --git a/src/cs_ident.hh b/src/cs_ident.hh index 9458651..852f407 100644 --- a/src/cs_ident.hh +++ b/src/cs_ident.hh @@ -11,7 +11,7 @@ static constexpr std::size_t MAX_ARGUMENTS = 32; using argset = std::bitset; 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); diff --git a/src/cs_parser.cc b/src/cs_parser.cc index 1fe104e..31fc5d9 100644 --- a/src/cs_parser.cc +++ b/src/cs_parser.cc @@ -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(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(hid), id, ltype - ); - } - case ID_FVAR: { - auto *hid = ts.istate->cmd_fvar; - return parse_call_command( - static_cast(hid), id, ltype - ); - } - case ID_SVAR: { - auto *hid = ts.istate->cmd_svar; - return parse_call_command( - static_cast(hid), id, ltype - ); - } + case ID_VAR: + return parse_call_command(static_cast( + static_cast(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(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(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( + id + ).get_setter(ts); bool more = parse_assign_var( *this, static_cast(hid), id, ltype ); diff --git a/src/cs_state.cc b/src/cs_state.cc index 3ae54b1..7296297 100644 --- a/src/cs_state.cc +++ b/src/cs_state.cc @@ -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(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( static_cast(&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( - 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( - 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( - 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(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{&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(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(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(idr).value(); - break; - default: - return; + if (idr.type() != ident_type::VAR) { + return; } - var_changed(*p_tstate, &idr, v); + auto &v = static_cast(idr); + auto vv = v.value(); + var_changed(*p_tstate, v, vv); } static char const *allowed_builtins[] = { diff --git a/src/cs_vm.cc b/src/cs_vm.cc index 6d1839d..1051389 100644 --- a/src/cs_vm.cc +++ b/src/cs_vm.cc @@ -847,40 +847,10 @@ noid: cleanup(); return code; } - case ID_IVAR: { - auto *hid = ts.istate->cmd_ivar; - auto *cimp = static_cast(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(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( + id->get() + ).get_setter(ts); auto *cimp = static_cast(hid); /* the $ argument */ args.insert(offset, any_value{});