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 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<typename F>
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()};
}
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(
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>(
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<fvar_impl>(
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<svar_impl>(
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
) {

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 &) {
cs.set_alias(args[0].get_str(), args[1]);
});

View File

@ -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());
}