diff --git a/include/cubescript/cubescript.hh b/include/cubescript/cubescript.hh index 7762ac7..832b695 100644 --- a/include/cubescript/cubescript.hh +++ b/include/cubescript/cubescript.hh @@ -260,8 +260,6 @@ protected: private: cs_var_cb cb_var; - virtual cs_string to_printable() const = 0; - void changed(cs_state &cs) { if (cb_var) { cb_var(cs, *this); @@ -279,8 +277,6 @@ struct OSTD_EXPORT cs_ivar: cs_var { cs_int get_value() const; void set_value(cs_int val); - cs_string to_printable() const final; - private: cs_ivar( cs_strref n, cs_int m, cs_int x, cs_int v, cs_var_cb f, int flags @@ -299,8 +295,6 @@ struct OSTD_EXPORT cs_fvar: cs_var { cs_float get_value() const; void set_value(cs_float val); - cs_string to_printable() const final; - private: cs_fvar( cs_strref n, cs_float m, cs_float x, cs_float v, @@ -317,8 +311,6 @@ struct OSTD_EXPORT cs_svar: cs_var { cs_strref get_value() const; void set_value(cs_strref val); - cs_string to_printable() const final; - private: cs_svar(cs_strref n, cs_strref v, cs_strref ov, cs_var_cb f, int flags); @@ -429,6 +421,9 @@ struct OSTD_EXPORT cs_state { cs_hook_cb const &get_call_hook() const; cs_hook_cb &get_call_hook(); + cs_vprint_cb set_var_printer(cs_vprint_cb func); + cs_vprint_cb const &get_var_printer() const; + void init_libs(int libs = CsLibAll); void clear_override(cs_ident &id); @@ -533,7 +528,7 @@ struct OSTD_EXPORT cs_state { std::optional get_alias_val(ostd::string_range name); - virtual void print_var(cs_var *v); + void print_var(cs_var const &v) const; private: OSTD_LOCAL cs_state(cs_shared_state *s); diff --git a/include/cubescript/cubescript_conf.hh b/include/cubescript/cubescript_conf.hh index e4b4149..2822447 100644 --- a/include/cubescript/cubescript_conf.hh +++ b/include/cubescript/cubescript_conf.hh @@ -10,6 +10,7 @@ namespace cscript { struct cs_state; struct cs_ident; struct cs_value; + struct cs_var; using cs_value_r = ostd::iterator_range; using cs_ident_r = ostd::iterator_range; @@ -31,6 +32,7 @@ namespace cscript { * need to make sure, override this with your own type */ using cs_var_cb = std::function; + using cs_vprint_cb = std::function; using cs_command_cb = std::function; using cs_hook_cb = std::function; using cs_alloc_cb = void *(*)(void *, void *, size_t, size_t); @@ -38,14 +40,6 @@ namespace cscript { constexpr auto const IntFormat = "%d"; constexpr auto const FloatFormat = "%.7g"; constexpr auto const RoundFloatFormat = "%.1f"; - - constexpr auto const IvarFormat = "%s = %d"; - constexpr auto const IvarHexFormat = "%s = 0x%X"; - constexpr auto const IvarHexColorFormat = "%s = 0x%.6X (%d, %d, %d)"; - constexpr auto const FvarFormat = "%s = %.7g"; - constexpr auto const FvarRoundFormat = "%s = %.1f"; - constexpr auto const SvarFormat = "%s = \"%s\""; - constexpr auto const SvarQuotedFormat = "%s = [%s]"; } /* namespace cscript */ #endif /* LIBCUBESCRIPT_CUBESCRIPT_CONF_HH */ \ No newline at end of file diff --git a/src/cs_vm.cc b/src/cs_vm.cc index e51eb08..d00a375 100644 --- a/src/cs_vm.cc +++ b/src/cs_vm.cc @@ -697,7 +697,7 @@ static uint32_t *runcode(cs_state &cs, uint32_t *code, cs_value &result) { args[numargs++] = std::move(result); continue; case CsCodePrint: - cs.print_var(static_cast(cs.p_state->identmap[op >> 8])); + cs.print_var(*static_cast(cs.p_state->identmap[op >> 8])); continue; case CsCodeLocal: { @@ -1545,7 +1545,7 @@ noid: } case CsIdIvar: if (callargs <= 0) { - cs.print_var(static_cast(id)); + cs.print_var(*static_cast(id)); } else { cs.set_var_int_checked( static_cast(id), @@ -1557,7 +1557,7 @@ noid: continue; case CsIdFvar: if (callargs <= 0) { - cs.print_var(static_cast(id)); + cs.print_var(*static_cast(id)); } else { cs.set_var_float_checked( static_cast(id), @@ -1569,7 +1569,7 @@ noid: continue; case CsIdSvar: if (callargs <= 0) { - cs.print_var(static_cast(id)); + cs.print_var(*static_cast(id)); } else { cs.set_var_str_checked( static_cast(id), @@ -1659,14 +1659,14 @@ void cs_state::run(cs_ident *id, cs_value_r args, cs_value &ret) { break; case cs_ident_type::Ivar: if (args.empty()) { - print_var(static_cast(id)); + print_var(*static_cast(id)); } else { set_var_int_checked(static_cast(id), args); } break; case cs_ident_type::Fvar: if (args.empty()) { - print_var(static_cast(id)); + print_var(*static_cast(id)); } else { set_var_float_checked( static_cast(id), args[0].force_float() @@ -1675,7 +1675,7 @@ void cs_state::run(cs_ident *id, cs_value_r args, cs_value &ret) { break; case cs_ident_type::Svar: if (args.empty()) { - print_var(static_cast(id)); + print_var(*static_cast(id)); } else { set_var_str_checked( static_cast(id), args[0].force_str() diff --git a/src/cs_vm.hh b/src/cs_vm.hh index 73af673..ddc6e56 100644 --- a/src/cs_vm.hh +++ b/src/cs_vm.hh @@ -116,6 +116,7 @@ struct cs_shared_state { cs_map idents; cs_vector identmap; cs_alloc_cb allocf; + cs_vprint_cb varprintf; cs_strman *strman; void *aptr; diff --git a/src/cubescript.cc b/src/cubescript.cc index da909bb..816bc4f 100644 --- a/src/cubescript.cc +++ b/src/cubescript.cc @@ -227,26 +227,6 @@ void cs_ivar::set_value(cs_int val) { p_storage = val; } -cs_string cs_ivar::to_printable() const { - cs_int i = p_storage; - auto app = ostd::appender(); - try { - if (!(get_flags() & CS_IDF_HEX) || (i < 0)) { - format(app, IvarFormat, get_name(), i); - } else if (p_maxval == 0xFFFFFF) { - format( - app, IvarHexColorFormat, get_name(), - i, (i >> 16) & 0xFF, (i >> 8) & 0xFF, i & 0xFF - ); - } else { - format(app, IvarHexFormat, get_name(), i); - } - } catch (ostd::format_error const &e) { - throw cs_internal_error{e.what()}; - } - return std::move(app.get()); -} - cs_float cs_fvar::get_val_min() const { return p_minval; } @@ -261,19 +241,6 @@ void cs_fvar::set_value(cs_float val) { p_storage = val; } -cs_string cs_fvar::to_printable() const { - cs_float f = p_storage; - auto app = ostd::appender(); - try { - format( - app, (f == cs_int(f)) ? FvarRoundFormat : FvarFormat, get_name(), f - ); - } catch (ostd::format_error const &e) { - throw cs_internal_error{e.what()}; - } - return std::move(app.get()); -} - cs_strref cs_svar::get_value() const { return p_storage; } @@ -281,21 +248,6 @@ void cs_svar::set_value(cs_strref val) { p_storage = val; } -cs_string cs_svar::to_printable() const { - ostd::string_range s = p_storage; - auto app = ostd::appender(); - try { - if (ostd::find(s, '"').empty()) { - format(app, SvarFormat, get_name(), s); - } else { - format(app, SvarQuotedFormat, get_name(), s); - } - } catch (ostd::format_error const &e) { - throw cs_internal_error{e.what()}; - } - return std::move(app.get()); -} - ostd::string_range cs_command::get_args() const { return p_cargs; } @@ -322,6 +274,7 @@ cs_state::cs_state(cs_alloc_cb func, void *data): p_state->allocf = func; p_state->aptr = data; p_state->strman = p_state->create(p_state); + p_state->varprintf = [](auto &, auto &) {}; for (int i = 0; i < MaxArguments; ++i) { char buf[32]; @@ -465,6 +418,16 @@ OSTD_EXPORT cs_hook_cb &cs_state::get_call_hook() { return p_callhook; } +OSTD_EXPORT cs_vprint_cb cs_state::set_var_printer(cs_vprint_cb func) { + auto fn = std::move(p_state->varprintf); + p_state->varprintf = std::move(func); + return fn; +} + +OSTD_EXPORT cs_vprint_cb const &cs_state::get_var_printer() const { + return p_state->varprintf; +} + void *cs_state::alloc(void *ptr, size_t os, size_t ns) { return p_state->alloc(ptr, os, ns); } @@ -663,8 +626,8 @@ OSTD_EXPORT void cs_state::set_alias(ostd::string_range name, cs_value v) { } } -OSTD_EXPORT void cs_state::print_var(cs_var *v) { - ostd::writeln(v->to_printable()); +OSTD_EXPORT void cs_state::print_var(cs_var const &v) const { + p_state->varprintf(*this, v); } void cs_alias::get_cval(cs_value &v) const { diff --git a/tools/repl.cc b/tools/repl.cc index e1707ff..7178010 100644 --- a/tools/repl.cc +++ b/tools/repl.cc @@ -187,6 +187,48 @@ static void do_sigint(int n) { }); } +/* an example of what var printer would look like in real usage */ +static void repl_print_var(cs_state const &cs, cs_var const &var) { + switch (var.get_type()) { + case cs_ident_type::Ivar: { + auto &iv = static_cast(var); + auto val = iv.get_value(); + if (!(iv.get_flags() & CS_IDF_HEX) || (val < 0)) { + ostd::writefln("%s = %d", iv.get_name(), val); + } else if (iv.get_val_max() == 0xFFFFFF) { + ostd::writefln( + "%s = 0x%.6X (%d, %d, %d)", iv.get_name(), + val, (val >> 16) & 0xFF, (val >> 8) & 0xFF, val & 0xFF + ); + } else { + ostd::writefln("%s = 0x%X", iv.get_name(), val); + } + break; + } + case cs_ident_type::Fvar: { + auto &fv = static_cast(var); + auto val = fv.get_value(); + ostd::writefln( + (floor(val) == val) ? "%s = %.1f" : "%s = %.7g", + fv.get_name(), val + ); + break; + } + case cs_ident_type::Svar: { + auto &sv = static_cast(var); + auto val = ostd::string_range{sv.get_value()}; + if (ostd::find(val, '"').empty()) { + ostd::writefln("%s = \"%s\"", sv.get_name(), val); + } else { + ostd::writefln("%s = [%s]", sv.get_name(), val); + } + break; + } + default: + break; + } +} + static bool do_call(cs_state &cs, ostd::string_range line, bool file = false) { cs_value ret{cs}; scs = &cs; @@ -272,6 +314,7 @@ static void do_tty(cs_state &cs) { int main(int argc, char **argv) { cs_state gcs; + gcs.set_var_printer(repl_print_var); gcs.init_libs(); gcs.new_command("exec", "s", [](auto &cs, auto args, auto &) {