From 03325af1e6421422696ab2a145cee68e24977c96 Mon Sep 17 00:00:00 2001 From: Daniel Kolesa Date: Wed, 5 May 2021 00:37:12 +0200 Subject: [PATCH] pass old and new values to var_changed --- include/cubescript/cubescript/state.hh | 6 ++-- src/cs_ident.cc | 39 +++++++++++++++++++++----- src/cs_ident.hh | 2 +- src/cs_state.cc | 32 +++++++++++++++++---- tools/repl.cc | 8 ++++-- 5 files changed, 69 insertions(+), 18 deletions(-) diff --git a/include/cubescript/cubescript/state.hh b/include/cubescript/cubescript/state.hh index 16e171b..e655dbf 100644 --- a/include/cubescript/cubescript/state.hh +++ b/include/cubescript/cubescript/state.hh @@ -343,8 +343,10 @@ struct LIBCUBESCRIPT_EXPORT state { * and `s`) which also print to standard output (`name = value`). * * For `//var_changed`, there is no default handler. The arg list must be - * just `$`. This will be called whenever a value of an integer, float - * or string builtin variable changes. + * `$aa`. This will be called whenever the value of a builtin variable of + * any type changes, and will be passed the variable as its first argument, + * the previous value as the second argument and the new value as the third + * argument (mainly for convenience). * * For these builtins, `$` will refer to the variable ident, not to the * builtin command. diff --git a/src/cs_ident.cc b/src/cs_ident.cc index d14f3a5..43d75b9 100644 --- a/src/cs_ident.cc +++ b/src/cs_ident.cc @@ -82,15 +82,31 @@ command_impl::command_impl( p_cargs{args}, p_cb_cftv{std::move(f)}, p_numargs{nargs} {} -void var_changed(thread_state &ts, ident *id) { +void var_changed(thread_state &ts, ident *id, any_value &oldval) { auto *cid = ts.istate->cmd_var_changed; if (!cid) { return; } auto *cimp = static_cast(cid); - any_value val{}; - val.set_ident(*id); - cimp->call(ts, span_type{&val, 1}, val); + any_value val[3] = {}; + val[0].set_ident(*id); + val[1] = std::move(oldval); + switch (id->get_type()) { + case ident_type::IVAR: + val[2].set_integer(static_cast(id)->get_value()); + break; + case ident_type::FVAR: + val[2].set_float(static_cast(id)->get_value()); + break; + case ident_type::SVAR: + val[2].set_string(static_cast(id)->get_value()); + break; + default: + return; + } + cimp->call(ts, span_type{ + static_cast(val), 3 + }, val[0]); } void ivar_impl::save_val() { @@ -311,9 +327,12 @@ LIBCUBESCRIPT_EXPORT void integer_var::set_value( return; } save(cs); + auto oldv = get_value(); set_raw_value(val); if (trigger) { - var_changed(state_p{cs}.ts(), this); + any_value v; + v.set_integer(oldv); + var_changed(state_p{cs}.ts(), this, v); } } @@ -363,9 +382,12 @@ LIBCUBESCRIPT_EXPORT void float_var::set_value( return; } save(cs); + auto oldv = get_value(); set_raw_value(val); if (trigger) { - var_changed(state_p{cs}.ts(), this); + any_value v; + v.set_float(oldv); + var_changed(state_p{cs}.ts(), this, v); } } @@ -395,9 +417,12 @@ LIBCUBESCRIPT_EXPORT void string_var::set_value( return; } save(cs); + auto oldv = get_value(); set_raw_value(std::move(val)); if (trigger) { - var_changed(state_p{cs}.ts(), this); + any_value v; + v.set_string(oldv); + var_changed(state_p{cs}.ts(), this, v); } } diff --git a/src/cs_ident.hh b/src/cs_ident.hh index eed5c1b..fd6cd82 100644 --- a/src/cs_ident.hh +++ b/src/cs_ident.hh @@ -81,7 +81,7 @@ struct var_impl: ident_impl { void changed(thread_state &ts); }; -void var_changed(thread_state &ts, ident *id); +void var_changed(thread_state &ts, ident *id, any_value &oldval); struct ivar_impl: var_impl, integer_var { ivar_impl(string_ref n, integer_type v, int flags); diff --git a/src/cs_state.cc b/src/cs_state.cc index bcfa0d1..907afc3 100644 --- a/src/cs_state.cc +++ b/src/cs_state.cc @@ -350,27 +350,33 @@ LIBCUBESCRIPT_EXPORT void state::clear_override(ident &id) { return; } case ident_type::IVAR: { + any_value oldv; ivar_impl &iv = static_cast(id); + oldv.set_integer(iv.get_value()); iv.set_raw_value(iv.p_override); - var_changed(*p_tstate, &id); + var_changed(*p_tstate, &id, oldv); static_cast( static_cast(&iv) )->p_flags &= ~IDENT_FLAG_OVERRIDDEN; return; } case ident_type::FVAR: { + any_value oldv; fvar_impl &fv = static_cast(id); + oldv.set_float(fv.get_value()); fv.set_raw_value(fv.p_override); - var_changed(*p_tstate, &id); + var_changed(*p_tstate, &id, oldv); static_cast( static_cast(&fv) )->p_flags &= ~IDENT_FLAG_OVERRIDDEN; return; } case ident_type::SVAR: { + any_value oldv; svar_impl &sv = static_cast(id); + oldv.set_string(sv.get_value()); sv.set_raw_value(sv.p_override); - var_changed(*p_tstate, &id); + var_changed(*p_tstate, &id, oldv); static_cast( static_cast(&sv) )->p_flags &= ~IDENT_FLAG_OVERRIDDEN; @@ -578,9 +584,25 @@ LIBCUBESCRIPT_EXPORT void state::reset_value(std::string_view name) { LIBCUBESCRIPT_EXPORT void state::touch_value(std::string_view name) { auto id = get_ident(name); - if (id && id->get().is_var()) { - var_changed(*p_tstate, &id->get()); + if (!id) { + return; } + auto &idr = id->get(); + any_value v; + switch (idr.get_type()) { + case ident_type::IVAR: + v.set_integer(static_cast(idr).get_value()); + break; + case ident_type::FVAR: + v.set_float(static_cast(idr).get_value()); + break; + case ident_type::SVAR: + v.set_string(static_cast(idr).get_value()); + break; + default: + return; + } + var_changed(*p_tstate, &idr, v); } static char const *allowed_builtins[] = { diff --git a/tools/repl.cc b/tools/repl.cc index 260c6c3..009374d 100644 --- a/tools/repl.cc +++ b/tools/repl.cc @@ -347,10 +347,12 @@ int main(int argc, char **argv) { } }); - gcs.new_command("//var_changed", "$", [](auto &css, auto args, auto &) { + gcs.new_command("//var_changed", "$aa", [](auto &css, auto args, auto &) { std::printf( - "changed var trigger: %s\n", - args[0].get_ident(css).get_name().data() + "changed var trigger: %s (was: '%s', now: '%s')\n", + args[0].get_ident(css).get_name().data(), + args[1].get_string(css).data(), + args[2].get_string(css).data() ); });