diff --git a/include/cubescript/cubescript.hh b/include/cubescript/cubescript.hh index ceee42b..6caeb9e 100644 --- a/include/cubescript/cubescript.hh +++ b/include/cubescript/cubescript.hh @@ -345,15 +345,22 @@ struct LIBCUBESCRIPT_EXPORT state { void init_libs(int libs = LIB_ALL); + void clear_override(ident &id); + void clear_overrides(); + integer_var *new_ivar( - std::string_view n, integer_type v, bool read_only = false + std::string_view n, integer_type v, bool read_only = false, + var_type vtp = var_type::DEFAULT ); float_var *new_fvar( - std::string_view n, float_type v, bool read_only = false + std::string_view n, float_type v, bool read_only = false, + var_type vtp = var_type::DEFAULT ); string_var *new_svar( - std::string_view n, std::string_view v, bool read_only = false + std::string_view n, std::string_view v, bool read_only = false, + var_type vtp = var_type::DEFAULT ); + void reset_var(std::string_view name); template command *new_command( diff --git a/src/cs_state.cc b/src/cs_state.cc index 7be91a3..e714d73 100644 --- a/src/cs_state.cc +++ b/src/cs_state.cc @@ -288,39 +288,119 @@ LIBCUBESCRIPT_EXPORT std::span state::get_idents() const { return std::span{ptr, p_tstate->istate->identmap.size()}; } +LIBCUBESCRIPT_EXPORT void state::clear_override(ident &id) { + if (!id.is_overridden(*this)) { + return; + } + switch (id.get_type()) { + case ident_type::ALIAS: { + auto &ast = p_tstate->get_astack(static_cast(&id)); + ast.node->val_s.set_str(""); + ast.node->code = bcode_ref{}; + ast.flags &= ~IDENT_FLAG_OVERRIDDEN; + return; + } + case ident_type::IVAR: { + ivar_impl &iv = static_cast(id); + iv.set_value(iv.p_override); + //iv.changed(*this); + static_cast( + static_cast(&iv) + )->p_flags &= ~IDENT_FLAG_OVERRIDDEN; + return; + } + case ident_type::FVAR: { + fvar_impl &fv = static_cast(id); + fv.set_value(fv.p_override); + //fv.changed(*this); + static_cast( + static_cast(&fv) + )->p_flags &= ~IDENT_FLAG_OVERRIDDEN; + return; + } + case ident_type::SVAR: { + svar_impl &sv = static_cast(id); + sv.set_value(sv.p_override); + //sv.changed(*this); + static_cast( + static_cast(&sv) + )->p_flags &= ~IDENT_FLAG_OVERRIDDEN; + return; + } + default: + break; + } +} + +LIBCUBESCRIPT_EXPORT void state::clear_overrides() { + for (auto &p: p_tstate->istate->idents) { + clear_override(*(p.second)); + } +} + +inline int var_flags(bool read_only, var_type vtp) { + int ret = 0; + if (read_only) { + ret |= IDENT_FLAG_READONLY; + } + switch (vtp) { + case var_type::PERSISTENT: + ret |= IDENT_FLAG_PERSIST; + break; + case var_type::OVERRIDABLE: + ret |= IDENT_FLAG_OVERRIDE; + break; + default: + break; + } + return ret; +} + LIBCUBESCRIPT_EXPORT integer_var *state::new_ivar( - std::string_view n, integer_type v, bool read_only + std::string_view n, integer_type v, bool read_only, var_type vtp ) { auto *iv = p_tstate->istate->create( string_ref{p_tstate->istate, n}, v, - read_only ? IDENT_FLAG_READONLY : 0 + var_flags(read_only, vtp) ); p_tstate->istate->add_ident(iv, iv); return iv; } LIBCUBESCRIPT_EXPORT float_var *state::new_fvar( - std::string_view n, float_type v, bool read_only + std::string_view n, float_type v, bool read_only, var_type vtp ) { auto *fv = p_tstate->istate->create( string_ref{p_tstate->istate, n}, v, - read_only ? IDENT_FLAG_READONLY : 0 + var_flags(read_only, vtp) ); p_tstate->istate->add_ident(fv, fv); return fv; } LIBCUBESCRIPT_EXPORT string_var *state::new_svar( - std::string_view n, std::string_view v, bool read_only + std::string_view n, std::string_view v, bool read_only, var_type vtp ) { auto *sv = p_tstate->istate->create( string_ref{p_tstate->istate, n}, string_ref{p_tstate->istate, v}, - read_only ? IDENT_FLAG_READONLY : 0 + var_flags(read_only, vtp) ); p_tstate->istate->add_ident(sv, sv); return sv; } +LIBCUBESCRIPT_EXPORT void state::reset_var(std::string_view name) { + ident *id = get_ident(name); + if (!id) { + throw error{*this, "variable '%s' does not exist", name.data()}; + } + auto *var = id->get_var(); + if (var && var->is_read_only()) { + throw error{*this, "variable '%s' is read only", name.data()}; + } + clear_override(*id); +} + LIBCUBESCRIPT_EXPORT void state::set_alias( std::string_view name, any_value v ) { diff --git a/src/lib_base.cc b/src/lib_base.cc index c7a005b..c26e3ef 100644 --- a/src/lib_base.cc +++ b/src/lib_base.cc @@ -312,6 +312,10 @@ end: } }); + gcs.new_command("resetvar", "s", [](auto &cs, auto args, auto &) { + cs.reset_var(args[0].get_str()); + }); + gcs.new_command("alias", "st", [](auto &cs, auto args, auto &) { cs.set_alias(args[0].get_str(), args[1]); }); diff --git a/tools/repl.cc b/tools/repl.cc index 47c8704..cba5828 100644 --- a/tools/repl.cc +++ b/tools/repl.cc @@ -320,7 +320,7 @@ int main(int argc, char **argv) { cs::state gcs; gcs.init_libs(); - gcs.new_command("//ivar", "$iiiN", [](auto &, auto args, auto &) { + gcs.new_command("//ivar", "$iiiN", [](auto &css, auto args, auto &) { auto *iv = args[0].get_ident()->get_ivar(); auto nargs = args[4].get_int(); if (nargs <= 1) { @@ -334,7 +334,14 @@ int main(int argc, char **argv) { } else { std::printf("%s = %d\n", iv->get_name().data(), val); } - } else if (nargs == 2) { + return; + } + if (iv->is_read_only()) { + throw cs::error{ + css, "variable '%s' is read only", iv->get_name().data() + }; + } + if (nargs == 2) { iv->set_value(args[1].get_int()); } else if (nargs == 3) { iv->set_value( @@ -348,7 +355,7 @@ int main(int argc, char **argv) { } }); - gcs.new_command("//fvar", "$fN", [](auto &, auto args, auto &) { + gcs.new_command("//fvar", "$fN", [](auto &css, auto args, auto &) { auto *fv = args[0].get_ident()->get_fvar(); auto nargs = args[2].get_int(); if (nargs <= 1) { @@ -358,12 +365,16 @@ int main(int argc, char **argv) { } else { std::printf("%s = %.7g\n", fv->get_name().data(), val); } + } else if (fv->is_read_only()) { + throw cs::error{ + css, "variable '%s' is read only", fv->get_name().data() + }; } else { fv->set_value(args[1].get_float()); } }); - gcs.new_command("//svar", "$sN", [](auto &, auto args, auto &) { + gcs.new_command("//svar", "$sN", [](auto &css, auto args, auto &) { auto sv = args[0].get_ident()->get_svar(); auto nargs = args[2].get_int(); if (nargs <= 1) { @@ -373,6 +384,10 @@ int main(int argc, char **argv) { } else { std::printf("%s = [%s]\n", sv->get_name().data(), val.data()); } + } else if (sv->is_read_only()) { + throw cs::error{ + css, "variable '%s' is read only", sv->get_name().data() + }; } else { sv->set_value(args[1].get_str()); }