remove state::get_alias(), make get_ident() return an optional
parent
fadee6ab6f
commit
92281e88c1
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)) {
|
||||
|
|
26
src/cs_vm.cc
26
src/cs_vm.cc
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue