From 92281e88c1c85c6ec66a6a5d9490c886227bdc5a Mon Sep 17 00:00:00 2001 From: Daniel Kolesa Date: Mon, 26 Apr 2021 02:42:08 +0200 Subject: [PATCH] remove state::get_alias(), make get_ident() return an optional --- include/cubescript/cubescript/state.hh | 13 ++++---- src/cs_parser.cc | 4 +-- src/cs_state.cc | 44 +++++++++++--------------- src/cs_vm.cc | 26 +++++++++------ src/lib_base.cc | 12 ++++--- tools/repl.cc | 4 +-- 6 files changed, 55 insertions(+), 48 deletions(-) diff --git a/include/cubescript/cubescript/state.hh b/include/cubescript/cubescript/state.hh index 496bb4a..7557cbd 100644 --- a/include/cubescript/cubescript/state.hh +++ b/include/cubescript/cubescript/state.hh @@ -13,6 +13,8 @@ #include #include +#include +#include #include #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> 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); diff --git a/src/cs_parser.cc b/src/cs_parser.cc index 268d0e6..c759e94 100644 --- a/src/cs_parser.cc +++ b/src/cs_parser.cc @@ -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; } diff --git a/src/cs_state.cc b/src/cs_state.cc index 13d07f5..192e7cf 100644 --- a/src/cs_state.cc +++ b/src/cs_state.cc @@ -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 +> state::get_ident(std::string_view name) { + auto *id = p_tstate->istate->get_ident(name); + if (!id) { + return std::nullopt; } - return static_cast(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 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(*id).is_read_only()) { + if (id->get().is_var()) { + if (static_cast(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(id)->set_value(*this, std::move(v)); + static_cast(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{&v, 1}); + run(id->get(), span_type{&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)) { diff --git a/src/cs_vm.cc b/src/cs_vm.cc index f383196..84bbc70 100644 --- a/src/cs_vm.cc +++ b/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(id); + auto *cimp = static_cast(&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(id); + alias *a = static_cast(&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); diff --git a/src/lib_base.cc b/src/lib_base.cc index 34303c6..74596ab 100644 --- a/src/lib_base.cc +++ b/src/lib_base.cc @@ -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(id).get_value(cs); }); } diff --git a/tools/repl.cc b/tools/repl.cc index 99e9a8e..42ea5de 100644 --- a/tools/repl.cc +++ b/tools/repl.cc @@ -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(cmd); + if (cmd && cmd->get().is_command()) { + return static_cast(&cmd->get()); } } return nullptr;