rea-add proper handling of variable overrides

master
Daniel Kolesa 2021-04-04 02:33:28 +02:00
parent 6777eb73d5
commit 3d91cf2ee7
4 changed files with 119 additions and 13 deletions

View File

@ -345,15 +345,22 @@ struct LIBCUBESCRIPT_EXPORT state {
void init_libs(int libs = LIB_ALL); void init_libs(int libs = LIB_ALL);
void clear_override(ident &id);
void clear_overrides();
integer_var *new_ivar( 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( 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( 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<typename F> template<typename F>
command *new_command( command *new_command(

View File

@ -288,39 +288,119 @@ LIBCUBESCRIPT_EXPORT std::span<ident const *> state::get_idents() const {
return std::span<ident const *>{ptr, p_tstate->istate->identmap.size()}; return std::span<ident const *>{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<alias *>(&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<ivar_impl &>(id);
iv.set_value(iv.p_override);
//iv.changed(*this);
static_cast<ivar_impl *>(
static_cast<integer_var *>(&iv)
)->p_flags &= ~IDENT_FLAG_OVERRIDDEN;
return;
}
case ident_type::FVAR: {
fvar_impl &fv = static_cast<fvar_impl &>(id);
fv.set_value(fv.p_override);
//fv.changed(*this);
static_cast<fvar_impl *>(
static_cast<float_var *>(&fv)
)->p_flags &= ~IDENT_FLAG_OVERRIDDEN;
return;
}
case ident_type::SVAR: {
svar_impl &sv = static_cast<svar_impl &>(id);
sv.set_value(sv.p_override);
//sv.changed(*this);
static_cast<svar_impl *>(
static_cast<string_var *>(&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( 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<ivar_impl>( auto *iv = p_tstate->istate->create<ivar_impl>(
string_ref{p_tstate->istate, n}, v, 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); p_tstate->istate->add_ident(iv, iv);
return iv; return iv;
} }
LIBCUBESCRIPT_EXPORT float_var *state::new_fvar( 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<fvar_impl>( auto *fv = p_tstate->istate->create<fvar_impl>(
string_ref{p_tstate->istate, n}, v, 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); p_tstate->istate->add_ident(fv, fv);
return fv; return fv;
} }
LIBCUBESCRIPT_EXPORT string_var *state::new_svar( 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<svar_impl>( auto *sv = p_tstate->istate->create<svar_impl>(
string_ref{p_tstate->istate, n}, string_ref{p_tstate->istate, v}, 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); p_tstate->istate->add_ident(sv, sv);
return 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( LIBCUBESCRIPT_EXPORT void state::set_alias(
std::string_view name, any_value v std::string_view name, any_value v
) { ) {

View File

@ -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 &) { gcs.new_command("alias", "st", [](auto &cs, auto args, auto &) {
cs.set_alias(args[0].get_str(), args[1]); cs.set_alias(args[0].get_str(), args[1]);
}); });

View File

@ -320,7 +320,7 @@ int main(int argc, char **argv) {
cs::state gcs; cs::state gcs;
gcs.init_libs(); 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 *iv = args[0].get_ident()->get_ivar();
auto nargs = args[4].get_int(); auto nargs = args[4].get_int();
if (nargs <= 1) { if (nargs <= 1) {
@ -334,7 +334,14 @@ int main(int argc, char **argv) {
} else { } else {
std::printf("%s = %d\n", iv->get_name().data(), val); 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()); iv->set_value(args[1].get_int());
} else if (nargs == 3) { } else if (nargs == 3) {
iv->set_value( 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 *fv = args[0].get_ident()->get_fvar();
auto nargs = args[2].get_int(); auto nargs = args[2].get_int();
if (nargs <= 1) { if (nargs <= 1) {
@ -358,12 +365,16 @@ int main(int argc, char **argv) {
} else { } else {
std::printf("%s = %.7g\n", fv->get_name().data(), val); 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 { } else {
fv->set_value(args[1].get_float()); 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 sv = args[0].get_ident()->get_svar();
auto nargs = args[2].get_int(); auto nargs = args[2].get_int();
if (nargs <= 1) { if (nargs <= 1) {
@ -373,6 +384,10 @@ int main(int argc, char **argv) {
} else { } else {
std::printf("%s = [%s]\n", sv->get_name().data(), val.data()); 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 { } else {
sv->set_value(args[1].get_str()); sv->set_value(args[1].get_str());
} }