return refs for new_*var and new_ident (guarantee valid result)
parent
1a68dd1c25
commit
8c8aa26c20
|
@ -8,14 +8,17 @@
|
|||
|
||||
#include "callable.hh"
|
||||
#include "ident.hh"
|
||||
#include "value.hh"
|
||||
|
||||
namespace cubescript {
|
||||
|
||||
struct state;
|
||||
|
||||
using alloc_func = void *(*)(void *, void *, size_t, size_t);
|
||||
|
||||
using hook_func = internal::callable<void, struct state &>;
|
||||
using command_func = internal::callable<
|
||||
void, struct state &, std::span<struct any_value>, struct any_value &
|
||||
void, state &, std::span<any_value>, any_value &
|
||||
>;
|
||||
|
||||
enum {
|
||||
|
@ -68,19 +71,19 @@ struct LIBCUBESCRIPT_EXPORT state {
|
|||
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,
|
||||
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,
|
||||
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,
|
||||
var_type vtp = var_type::DEFAULT
|
||||
);
|
||||
ident *new_ident(std::string_view n);
|
||||
ident &new_ident(std::string_view n);
|
||||
|
||||
void reset_var(std::string_view name);
|
||||
void touch_var(std::string_view name);
|
||||
|
|
|
@ -114,7 +114,7 @@ struct LIBCUBESCRIPT_EXPORT any_value {
|
|||
integer_type force_int();
|
||||
std::string_view force_str();
|
||||
bcode_ref force_code(state &cs);
|
||||
ident *force_ident(state &cs);
|
||||
ident &force_ident(state &cs);
|
||||
|
||||
private:
|
||||
template<typename T>
|
||||
|
|
|
@ -238,15 +238,14 @@ static void compilelookup(codegen_state &gs, int ltype) {
|
|||
if (lookup.empty()) goto invalid;
|
||||
lookup.push_back('\0');
|
||||
lookupid:
|
||||
ident *id = gs.ts.istate->new_ident(
|
||||
ident &id = gs.ts.istate->new_ident(
|
||||
*gs.ts.pstate, lookup.str_term(), IDENT_FLAG_UNKNOWN
|
||||
);
|
||||
if (id) {
|
||||
switch (id->get_type()) {
|
||||
switch (id.get_type()) {
|
||||
case ident_type::IVAR:
|
||||
gs.code.push_back(
|
||||
BC_INST_IVAR | ret_code(ltype, BC_RET_INT) |
|
||||
(id->get_index() << 8)
|
||||
(id.get_index() << 8)
|
||||
);
|
||||
switch (ltype) {
|
||||
case VAL_POP:
|
||||
|
@ -263,7 +262,7 @@ lookupid:
|
|||
case ident_type::FVAR:
|
||||
gs.code.push_back(
|
||||
BC_INST_FVAR | ret_code(ltype, BC_RET_FLOAT) |
|
||||
(id->get_index() << 8)
|
||||
(id.get_index() << 8)
|
||||
);
|
||||
switch (ltype) {
|
||||
case VAL_POP:
|
||||
|
@ -284,7 +283,7 @@ lookupid:
|
|||
default:
|
||||
gs.code.push_back(
|
||||
BC_INST_SVAR | ret_code(ltype, BC_RET_STRING) |
|
||||
(id->get_index() << 8)
|
||||
(id.get_index() << 8)
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
@ -295,21 +294,21 @@ lookupid:
|
|||
return;
|
||||
case VAL_COND:
|
||||
gs.code.push_back(
|
||||
BC_INST_LOOKUP | (id->get_index() << 8)
|
||||
BC_INST_LOOKUP | (id.get_index() << 8)
|
||||
);
|
||||
break;
|
||||
default:
|
||||
gs.code.push_back(
|
||||
BC_INST_LOOKUP |
|
||||
ret_code(ltype, BC_RET_STRING) |
|
||||
(id->get_index() << 8)
|
||||
(id.get_index() << 8)
|
||||
);
|
||||
break;
|
||||
}
|
||||
goto done;
|
||||
case ident_type::COMMAND: {
|
||||
std::uint32_t comtype = BC_INST_COM, numargs = 0;
|
||||
auto fmt = static_cast<command_impl *>(id)->get_args();
|
||||
auto fmt = static_cast<command_impl &>(id).get_args();
|
||||
for (char c: fmt) {
|
||||
switch (c) {
|
||||
case 's':
|
||||
|
@ -367,7 +366,7 @@ lookupid:
|
|||
}
|
||||
}
|
||||
gs.code.push_back(
|
||||
comtype | ret_code(ltype) | (id->get_index() << 8)
|
||||
comtype | ret_code(ltype) | (id.get_index() << 8)
|
||||
);
|
||||
gs.code.push_back(
|
||||
BC_INST_RESULT_ARG | ret_code(ltype)
|
||||
|
@ -375,7 +374,7 @@ lookupid:
|
|||
goto done;
|
||||
compilecomv:
|
||||
gs.code.push_back(
|
||||
comtype | ret_code(ltype) | (id->get_index() << 8)
|
||||
comtype | ret_code(ltype) | (id.get_index() << 8)
|
||||
);
|
||||
gs.code.push_back(numargs);
|
||||
gs.code.push_back(
|
||||
|
@ -386,7 +385,6 @@ lookupid:
|
|||
default:
|
||||
goto invalid;
|
||||
}
|
||||
}
|
||||
gs.gen_str(lookup.str_term());
|
||||
break;
|
||||
}
|
||||
|
@ -512,29 +510,27 @@ static bool compileblocksub(codegen_state &gs) {
|
|||
}
|
||||
lookup.push_back('\0');
|
||||
lookupid:
|
||||
ident *id = gs.ts.istate->new_ident(
|
||||
ident &id = gs.ts.istate->new_ident(
|
||||
*gs.ts.pstate, lookup.str_term(), IDENT_FLAG_UNKNOWN
|
||||
);
|
||||
if (id) {
|
||||
switch (id->get_type()) {
|
||||
switch (id.get_type()) {
|
||||
case ident_type::IVAR:
|
||||
gs.code.push_back(BC_INST_IVAR | (id->get_index() << 8));
|
||||
gs.code.push_back(BC_INST_IVAR | (id.get_index() << 8));
|
||||
goto done;
|
||||
case ident_type::FVAR:
|
||||
gs.code.push_back(BC_INST_FVAR | (id->get_index() << 8));
|
||||
gs.code.push_back(BC_INST_FVAR | (id.get_index() << 8));
|
||||
goto done;
|
||||
case ident_type::SVAR:
|
||||
gs.code.push_back(BC_INST_SVAR | (id->get_index() << 8));
|
||||
gs.code.push_back(BC_INST_SVAR | (id.get_index() << 8));
|
||||
goto done;
|
||||
case ident_type::ALIAS:
|
||||
gs.code.push_back(
|
||||
BC_INST_LOOKUP | (id->get_index() << 8)
|
||||
BC_INST_LOOKUP | (id.get_index() << 8)
|
||||
);
|
||||
goto done;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
gs.gen_str(lookup.str_term());
|
||||
gs.code.push_back(BC_INST_LOOKUP_U);
|
||||
done:
|
||||
|
@ -800,7 +796,7 @@ static bool compilearg(
|
|||
}
|
||||
|
||||
static void compile_cmd(
|
||||
codegen_state &gs, command_impl *id, ident *self, bool &more, int rettype,
|
||||
codegen_state &gs, command_impl *id, ident &self, bool &more, int rettype,
|
||||
std::uint32_t limit = 0
|
||||
) {
|
||||
std::uint32_t comtype = BC_INST_COM, numargs = 0, numcargs = 0, fakeargs = 0;
|
||||
|
@ -1189,18 +1185,17 @@ static void compilestatements(codegen_state &gs, int rettype, int brak) {
|
|||
gs.next_char();
|
||||
if (!idname.empty()) {
|
||||
idname.push_back('\0');
|
||||
ident *id = gs.ts.istate->new_ident(
|
||||
ident &id = gs.ts.istate->new_ident(
|
||||
*gs.ts.pstate, idname.str_term(), IDENT_FLAG_UNKNOWN
|
||||
);
|
||||
if (id) {
|
||||
switch (id->get_type()) {
|
||||
switch (id.get_type()) {
|
||||
case ident_type::ALIAS:
|
||||
more = compilearg(gs, VAL_ANY);
|
||||
if (!more) {
|
||||
gs.gen_str();
|
||||
}
|
||||
gs.code.push_back(
|
||||
BC_INST_ALIAS | (id->get_index() << 8)
|
||||
BC_INST_ALIAS | (id.get_index() << 8)
|
||||
);
|
||||
goto endstatement;
|
||||
case ident_type::IVAR: {
|
||||
|
@ -1230,7 +1225,6 @@ static void compilestatements(codegen_state &gs, int rettype, int brak) {
|
|||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
gs.gen_str(idname.str_term());
|
||||
}
|
||||
more = compilearg(gs, VAL_ANY);
|
||||
|
@ -1285,7 +1279,7 @@ noid:
|
|||
break;
|
||||
case ID_COMMAND:
|
||||
compile_cmd(
|
||||
gs, static_cast<command_impl *>(id), id, more,
|
||||
gs, static_cast<command_impl *>(id), *id, more,
|
||||
rettype
|
||||
);
|
||||
break;
|
||||
|
@ -1332,7 +1326,7 @@ noid:
|
|||
auto *hid = gs.ts.istate->cmd_ivar;
|
||||
compile_cmd(
|
||||
gs, static_cast<command_impl *>(hid),
|
||||
id, more, rettype
|
||||
*id, more, rettype
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
@ -1340,7 +1334,7 @@ noid:
|
|||
auto *hid = gs.ts.istate->cmd_fvar;
|
||||
compile_cmd(
|
||||
gs, static_cast<command_impl *>(hid),
|
||||
id, more, rettype
|
||||
*id, more, rettype
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
@ -1348,7 +1342,7 @@ noid:
|
|||
auto *hid = gs.ts.istate->cmd_svar;
|
||||
compile_cmd(
|
||||
gs, static_cast<command_impl *>(hid),
|
||||
id, more, rettype
|
||||
*id, more, rettype
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -103,12 +103,12 @@ struct codegen_state {
|
|||
|
||||
void gen_float(std::string_view word);
|
||||
|
||||
void gen_ident(ident *id) {
|
||||
code.push_back(BC_INST_IDENT | (id->get_index() << 8));
|
||||
void gen_ident(ident &id) {
|
||||
code.push_back(BC_INST_IDENT | (id.get_index() << 8));
|
||||
}
|
||||
|
||||
void gen_ident() {
|
||||
gen_ident(ts.istate->id_dummy);
|
||||
gen_ident(*ts.istate->id_dummy);
|
||||
}
|
||||
|
||||
void gen_ident(std::string_view word) {
|
||||
|
|
|
@ -55,7 +55,7 @@ ident *internal_state::add_ident(ident *id, ident_impl *impl) {
|
|||
return identmap.back();
|
||||
}
|
||||
|
||||
ident *internal_state::new_ident(state &cs, std::string_view name, int flags) {
|
||||
ident &internal_state::new_ident(state &cs, std::string_view name, int flags) {
|
||||
ident *id = get_ident(name);
|
||||
if (!id) {
|
||||
if (!is_valid_name(name)) {
|
||||
|
@ -68,7 +68,7 @@ ident *internal_state::new_ident(state &cs, std::string_view name, int flags) {
|
|||
);
|
||||
id = add_ident(inst, inst);
|
||||
}
|
||||
return id;
|
||||
return *id;
|
||||
}
|
||||
|
||||
ident *internal_state::get_ident(std::string_view name) const {
|
||||
|
@ -120,10 +120,10 @@ state::state(alloc_func func, void *data) {
|
|||
);
|
||||
}
|
||||
|
||||
statep->id_dummy = statep->new_ident(*this, "//dummy", IDENT_FLAG_UNKNOWN);
|
||||
statep->id_dummy = &statep->new_ident(*this, "//dummy", IDENT_FLAG_UNKNOWN);
|
||||
|
||||
statep->ivar_numargs = new_ivar("numargs", 0, true);
|
||||
statep->ivar_dbgalias = new_ivar("dbgalias", 4);
|
||||
statep->ivar_numargs = &new_ivar("numargs", 0, true);
|
||||
statep->ivar_dbgalias = &new_ivar("dbgalias", 4);
|
||||
|
||||
/* default handlers for variables */
|
||||
|
||||
|
@ -415,7 +415,7 @@ static void var_name_check(
|
|||
}
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT integer_var *state::new_ivar(
|
||||
LIBCUBESCRIPT_EXPORT integer_var &state::new_ivar(
|
||||
std::string_view n, integer_type v, bool read_only, var_type vtp
|
||||
) {
|
||||
auto *iv = p_tstate->istate->create<ivar_impl>(
|
||||
|
@ -429,10 +429,10 @@ LIBCUBESCRIPT_EXPORT integer_var *state::new_ivar(
|
|||
throw;
|
||||
}
|
||||
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, var_type vtp
|
||||
) {
|
||||
auto *fv = p_tstate->istate->create<fvar_impl>(
|
||||
|
@ -446,10 +446,10 @@ LIBCUBESCRIPT_EXPORT float_var *state::new_fvar(
|
|||
throw;
|
||||
}
|
||||
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, var_type vtp
|
||||
) {
|
||||
auto *sv = p_tstate->istate->create<svar_impl>(
|
||||
|
@ -463,10 +463,10 @@ LIBCUBESCRIPT_EXPORT string_var *state::new_svar(
|
|||
throw;
|
||||
}
|
||||
p_tstate->istate->add_ident(sv, sv);
|
||||
return sv;
|
||||
return *sv;
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT ident *state::new_ident(std::string_view n) {
|
||||
LIBCUBESCRIPT_EXPORT ident &state::new_ident(std::string_view n) {
|
||||
return p_tstate->istate->new_ident(*this, n, IDENT_FLAG_UNKNOWN);
|
||||
}
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ struct internal_state {
|
|||
~internal_state();
|
||||
|
||||
ident *add_ident(ident *id, ident_impl *impl);
|
||||
ident *new_ident(state &cs, std::string_view name, int flags);
|
||||
ident &new_ident(state &cs, std::string_view name, int flags);
|
||||
ident *get_ident(std::string_view name) const;
|
||||
|
||||
void *alloc(void *ptr, size_t os, size_t ns);
|
||||
|
|
|
@ -269,17 +269,17 @@ bcode_ref any_value::force_code(state &cs) {
|
|||
return bcode_ref{bc};
|
||||
}
|
||||
|
||||
ident *any_value::force_ident(state &cs) {
|
||||
ident &any_value::force_ident(state &cs) {
|
||||
switch (get_type()) {
|
||||
case value_type::IDENT:
|
||||
return csv_get<ident *>(&p_stor);
|
||||
return *csv_get<ident *>(&p_stor);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
auto *id = state_p{cs}.ts().istate->new_ident(
|
||||
auto &id = state_p{cs}.ts().istate->new_ident(
|
||||
cs, get_str(), IDENT_FLAG_UNKNOWN
|
||||
);
|
||||
set_ident(id);
|
||||
set_ident(&id);
|
||||
return id;
|
||||
}
|
||||
|
||||
|
|
|
@ -768,7 +768,7 @@ std::uint32_t *vm_exec(
|
|||
any_value &arg = args.back();
|
||||
ident *id = ts.istate->id_dummy;
|
||||
if (arg.get_type() == value_type::STRING) {
|
||||
id = ts.istate->new_ident(
|
||||
id = &ts.istate->new_ident(
|
||||
cs, arg.get_str(), IDENT_FLAG_UNKNOWN
|
||||
);
|
||||
}
|
||||
|
@ -1121,7 +1121,7 @@ noid:
|
|||
std::size_t idstsz = ts.idstack.size();
|
||||
for (size_t j = 0; j < size_t(callargs); ++j) {
|
||||
push_alias(
|
||||
ts, args[offset + j].force_ident(cs),
|
||||
ts, &args[offset + j].force_ident(cs),
|
||||
ts.idstack.emplace_back(*ts.pstate)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -7,10 +7,10 @@
|
|||
inline void init_lineedit(cs::state &, std::string_view) {
|
||||
}
|
||||
|
||||
inline std::optional<std::string> read_line(cs::state &, cs::string_var *pr) {
|
||||
inline std::optional<std::string> read_line(cs::state &, cs::string_var &pr) {
|
||||
std::string lbuf;
|
||||
char buf[512];
|
||||
printf("%s", pr->get_value().data());
|
||||
printf("%s", pr.get_value().data());
|
||||
std::fflush(stdout);
|
||||
while (fgets(buf, sizeof(buf), stdin)) {
|
||||
lbuf += static_cast<char const *>(buf);
|
||||
|
|
|
@ -50,9 +50,9 @@ inline void init_lineedit(cs::state &cs, std::string_view) {
|
|||
linenoise::SetHintsCallback(ln_hint);
|
||||
}
|
||||
|
||||
inline std::optional<std::string> read_line(cs::state &, cs::string_var *pr) {
|
||||
inline std::optional<std::string> read_line(cs::state &, cs::string_var &pr) {
|
||||
std::string line;
|
||||
auto quit = linenoise::Readline(pr->get_value().data(), line);
|
||||
auto quit = linenoise::Readline(pr.get_value().data(), line);
|
||||
if (quit) {
|
||||
/* linenoise traps ctrl-c, detect it and let the user exit */
|
||||
if (errno == EAGAIN) {
|
||||
|
|
|
@ -65,8 +65,8 @@ inline void init_lineedit(cs::state &cs, std::string_view) {
|
|||
rl_redisplay_function = ln_hint;
|
||||
}
|
||||
|
||||
inline std::optional<std::string> read_line(cs::state &, cs::string_var *pr) {
|
||||
auto line = readline(pr->get_value().data());
|
||||
inline std::optional<std::string> read_line(cs::state &, cs::string_var &pr) {
|
||||
auto line = readline(pr.get_value().data());
|
||||
if (!line) {
|
||||
return std::string();
|
||||
}
|
||||
|
|
|
@ -277,8 +277,8 @@ static bool do_call(cs::state &cs, std::string_view line, bool file = false) {
|
|||
}
|
||||
|
||||
static void do_tty(cs::state &cs) {
|
||||
auto prompt = cs.new_svar("PROMPT", "> ");
|
||||
auto prompt2 = cs.new_svar("PROMPT2", ">> ");
|
||||
auto &prompt = cs.new_svar("PROMPT", "> ");
|
||||
auto &prompt2 = cs.new_svar("PROMPT2", ">> ");
|
||||
|
||||
bool do_exit = false;
|
||||
cs.new_command("quit", "", [&do_exit](auto &, auto, auto &) {
|
||||
|
|
Loading…
Reference in New Issue