remove state::get_alias(), make get_ident() return an optional

master
Daniel Kolesa 2021-04-26 02:42:08 +02:00
parent fadee6ab6f
commit 92281e88c1
6 changed files with 55 additions and 48 deletions

View File

@ -13,6 +13,8 @@
#include <cstddef>
#include <utility>
#include <optional>
#include <functional>
#include <string_view>
#include "callable.hh"
@ -223,6 +225,11 @@ struct LIBCUBESCRIPT_EXPORT state {
*/
ident &new_ident(std::string_view n);
/** @brief Get a specific cubescript::ident */
std::optional<std::reference_wrapper<ident>> get_ident(
std::string_view name
);
/** @brief Reset a variable or alias
*
* This is like clear_override() except it works by name and performs
@ -319,12 +326,6 @@ struct LIBCUBESCRIPT_EXPORT state {
);
}
/** @brief Get a specific cubescript::ident (or `nullptr`) */
ident *get_ident(std::string_view name);
/** @brief Get a specific cubescript::alias (or `nullptr`) */
alias *get_alias(std::string_view name);
/** @brief Check if a cubescript::ident of the given name exists */
bool have_ident(std::string_view name);

View File

@ -1494,7 +1494,7 @@ void parser_state::parse_block(int ltype, int term) {
}
idname.push_back('\0');
auto idstr = idname.str_term();
ident *id = ts.pstate->get_ident(idstr);
auto id = ts.pstate->get_ident(idstr);
if (!id) {
/* no such ident exists but the name is valid, which means
* it's a syntactically ok call, make it the VM's problem
@ -1527,7 +1527,7 @@ void parser_state::parse_block(int ltype, int term) {
continue;
}
/* the ident exists; treat like a call according to its type */
more = parse_call_id(*id, ltype);
more = parse_call_id(id->get(), ltype);
if (!finish_statement(*this, more, term)) {
return;
}

View File

@ -315,20 +315,14 @@ LIBCUBESCRIPT_EXPORT void *state::alloc(void *ptr, size_t os, size_t ns) {
return p_tstate->istate->alloc(ptr, os, ns);
}
LIBCUBESCRIPT_EXPORT ident *state::get_ident(std::string_view name) {
return p_tstate->istate->get_ident(name);
}
LIBCUBESCRIPT_EXPORT alias *state::get_alias(std::string_view name) {
auto id = get_ident(name);
if (!id || !id->is_alias()) {
return nullptr;
LIBCUBESCRIPT_EXPORT std::optional<
std::reference_wrapper<ident>
> state::get_ident(std::string_view name) {
auto *id = p_tstate->istate->get_ident(name);
if (!id) {
return std::nullopt;
}
return static_cast<alias *>(id);
}
LIBCUBESCRIPT_EXPORT bool state::have_ident(std::string_view name) {
return p_tstate->istate->idents.find(name) != p_tstate->istate->idents.end();
return *id;
}
LIBCUBESCRIPT_EXPORT span_type<ident *> state::get_idents() {
@ -479,44 +473,44 @@ LIBCUBESCRIPT_EXPORT ident &state::new_ident(std::string_view n) {
}
LIBCUBESCRIPT_EXPORT void state::reset_var(std::string_view name) {
ident *id = get_ident(name);
auto id = get_ident(name);
if (!id) {
throw error{*this, "variable '%s' does not exist", name.data()};
}
if (id->is_var()) {
if (static_cast<global_var &>(*id).is_read_only()) {
if (id->get().is_var()) {
if (static_cast<global_var &>(id->get()).is_read_only()) {
throw error{*this, "variable '%s' is read only", name.data()};
}
}
clear_override(*id);
clear_override(id->get());
}
LIBCUBESCRIPT_EXPORT void state::touch_var(std::string_view name) {
ident *id = get_ident(name);
if (id && id->is_var()) {
var_changed(*p_tstate, id);
auto id = get_ident(name);
if (id && id->get().is_var()) {
var_changed(*p_tstate, &id->get());
}
}
LIBCUBESCRIPT_EXPORT void state::set_alias(
std::string_view name, any_value v
) {
ident *id = get_ident(name);
auto id = get_ident(name);
if (id) {
switch (id->get_type()) {
switch (id->get().get_type()) {
case ident_type::ALIAS: {
static_cast<alias *>(id)->set_value(*this, std::move(v));
static_cast<alias &>(id->get()).set_value(*this, std::move(v));
return;
}
case ident_type::IVAR:
case ident_type::FVAR:
case ident_type::SVAR:
run(*id, span_type<any_value>{&v, 1});
run(id->get(), span_type<any_value>{&v, 1});
break;
default:
throw error{
*this, "cannot redefine builtin %s with an alias",
id->get_name().data()
id->get().get_name().data()
};
}
} else if (!is_valid_name(name)) {

View File

@ -315,7 +315,12 @@ static inline int get_lookupu_type(
if (arg.get_type() != value_type::STRING) {
return -2; /* default case */
}
id = ts.pstate->get_ident(arg.get_string(*ts.pstate));
auto idopt = ts.pstate->get_ident(arg.get_string(*ts.pstate));
if (!idopt) {
id = nullptr;
} else {
id = &idopt->get();
}
if (id) {
switch(id->get_type()) {
case ident_type::ALIAS: {
@ -1073,7 +1078,7 @@ litval:
continue;
}
auto idn = idarg.get_string(cs);
ident *id = cs.get_ident(idn);
auto id = cs.get_ident(idn);
if (!id) {
noid:
if (!is_valid_name(idn)) {
@ -1087,16 +1092,16 @@ noid:
};
}
result.force_none();
switch (ident_p{*id}.impl().p_type) {
switch (ident_p{id->get()}.impl().p_type) {
default:
if (!ident_is_callable(id)) {
if (!ident_is_callable(&id->get())) {
args.resize(offset - 1);
force_arg(cs, result, op & BC_INST_RET_MASK);
continue;
}
/* fallthrough */
case ID_COMMAND: {
auto *cimp = static_cast<command_impl *>(id);
auto *cimp = static_cast<command_impl *>(&id->get());
args.resize(offset + std::max(
std::size_t(cimp->get_num_args()), callargs
));
@ -1139,7 +1144,8 @@ noid:
std::size_t(cimp->get_num_args()), callargs
));
exec_command(
ts, cimp, id, &args[offset], result, callargs
ts, cimp, &id->get(), &args[offset],
result, callargs
);
force_arg(cs, result, op & BC_INST_RET_MASK);
args.resize(offset - 1);
@ -1154,7 +1160,8 @@ noid:
std::size_t(cimp->get_num_args()), callargs
));
exec_command(
ts, cimp, id, &args[offset], result, callargs
ts, cimp, &id->get(), &args[offset],
result, callargs
);
force_arg(cs, result, op & BC_INST_RET_MASK);
args.resize(offset - 1);
@ -1169,14 +1176,15 @@ noid:
std::size_t(cimp->get_num_args()), callargs
));
exec_command(
ts, cimp, id, &args[offset], result, callargs
ts, cimp, &id->get(), &args[offset],
result, callargs
);
force_arg(cs, result, op & BC_INST_RET_MASK);
args.resize(offset - 1);
continue;
}
case ID_ALIAS: {
alias *a = static_cast<alias *>(id);
alias *a = static_cast<alias *>(&id->get());
if (a->is_arg() && !ident_is_used_arg(a, ts)) {
args.resize(offset - 1);
force_arg(cs, result, op & BC_INST_RET_MASK);

View File

@ -337,14 +337,18 @@ end:
});
new_cmd_quiet(gcs, "identexists", "s", [](auto &cs, auto args, auto &res) {
res.set_integer(cs.have_ident(args[0].get_string(cs)));
res.set_integer(cs.get_ident(args[0].get_string(cs)) != std::nullopt);
});
new_cmd_quiet(gcs, "getalias", "s", [](auto &cs, auto args, auto &res) {
auto *id = cs.get_alias(args[0].get_string(cs));
if (id) {
res = id->get_value(cs);
auto &id = cs.new_ident(args[0].get_string(cs));
if (id.get_type() != ident_type::ALIAS) {
throw error{cs, "'%s' is not an alias", id.get_name().data()};
}
if (ident_p{id}.impl().p_flags & IDENT_FLAG_UNKNOWN) {
return;
}
res = static_cast<alias &>(id).get_value(cs);
});
}

View File

@ -159,8 +159,8 @@ inline cs::command *get_hint_cmd(cs::state &cs, std::string_view buf) {
}
if (!buf.empty()) {
auto cmd = cs.get_ident(buf);
if (cmd && cmd->is_command()) {
return static_cast<cs::command *>(cmd);
if (cmd && cmd->get().is_command()) {
return static_cast<cs::command *>(&cmd->get());
}
}
return nullptr;