add better api to deal with alias stack
parent
3dc6ad866f
commit
d1243c5cc3
|
@ -507,8 +507,6 @@ protected:
|
|||
command() = default;
|
||||
};
|
||||
|
||||
struct ident_link;
|
||||
|
||||
enum {
|
||||
LIB_MATH = 1 << 0,
|
||||
LIB_STRING = 1 << 1,
|
||||
|
@ -818,6 +816,31 @@ private:
|
|||
stack_state p_stack;
|
||||
};
|
||||
|
||||
struct LIBCUBESCRIPT_EXPORT alias_stack {
|
||||
alias_stack(state &cs, ident *a);
|
||||
~alias_stack();
|
||||
|
||||
alias_stack(alias_stack const &) = delete;
|
||||
alias_stack(alias_stack &&) = delete;
|
||||
|
||||
alias_stack &operator=(alias_stack const &) = delete;
|
||||
alias_stack &operator=(alias_stack &&v) = delete;
|
||||
|
||||
bool set_alias(ident *id);
|
||||
alias *get_alias() const noexcept;
|
||||
bool has_alias() const noexcept;
|
||||
|
||||
bool push(any_value val);
|
||||
bool pop();
|
||||
|
||||
explicit operator bool() const noexcept;
|
||||
|
||||
private:
|
||||
state &p_state;
|
||||
alias *p_alias;
|
||||
bool p_pushed;
|
||||
};
|
||||
|
||||
struct LIBCUBESCRIPT_EXPORT stacked_value: any_value {
|
||||
stacked_value(state &cs, ident *id = nullptr);
|
||||
~stacked_value();
|
||||
|
|
|
@ -412,4 +412,61 @@ LIBCUBESCRIPT_EXPORT int command::get_num_args() const {
|
|||
return static_cast<command_impl const *>(this)->p_numargs;
|
||||
}
|
||||
|
||||
/* external API for alias stack management */
|
||||
|
||||
LIBCUBESCRIPT_EXPORT alias_stack::alias_stack(state &cs, ident *a):
|
||||
p_state{cs}, p_pushed{false}
|
||||
{
|
||||
set_alias(a);
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT alias_stack::~alias_stack() {
|
||||
pop();
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT bool alias_stack::set_alias(ident *id) {
|
||||
if (!id || !id->is_alias()) {
|
||||
return false;
|
||||
}
|
||||
p_alias = static_cast<alias *>(id);
|
||||
return true;
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT alias *alias_stack::get_alias() const noexcept {
|
||||
return p_alias;
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT bool alias_stack::has_alias() const noexcept {
|
||||
return !!p_alias;
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT bool alias_stack::push(any_value val) {
|
||||
if (!p_alias) {
|
||||
return false;
|
||||
}
|
||||
auto &ts = *p_state.thread_pointer();
|
||||
if (!p_pushed) {
|
||||
static_cast<alias_impl *>(p_alias)->push_arg(
|
||||
val, ts.idstack.emplace_back(p_state)
|
||||
);
|
||||
p_pushed = true;
|
||||
} else {
|
||||
static_cast<alias_impl *>(p_alias)->p_val = std::move(val);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT bool alias_stack::pop() {
|
||||
if (!p_pushed || !p_alias) {
|
||||
return false;
|
||||
}
|
||||
static_cast<alias_impl *>(p_alias)->pop_arg();
|
||||
p_pushed = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
LIBCUBESCRIPT_EXPORT alias_stack::operator bool() const noexcept {
|
||||
return has_alias();
|
||||
}
|
||||
|
||||
} /* namespace cubescript */
|
||||
|
|
108
src/lib_base.cc
108
src/lib_base.cc
|
@ -9,55 +9,57 @@ static inline void do_loop(
|
|||
state &cs, ident &id, integer_type offset, integer_type n, integer_type step,
|
||||
bcode *cond, bcode *body
|
||||
) {
|
||||
stacked_value idv{cs, &id};
|
||||
if (n <= 0 || !idv.has_alias()) {
|
||||
if (n <= 0) {
|
||||
return;
|
||||
}
|
||||
for (integer_type i = 0; i < n; ++i) {
|
||||
idv.set_int(offset + i * step);
|
||||
idv.push();
|
||||
if (cond && !cs.run(cond).get_bool()) {
|
||||
break;
|
||||
}
|
||||
switch (cs.run_loop(body)) {
|
||||
case loop_state::BREAK:
|
||||
goto end;
|
||||
default: /* continue and normal */
|
||||
if (alias_stack st{cs, &id}; st) {
|
||||
any_value idv{cs};
|
||||
for (integer_type i = 0; i < n; ++i) {
|
||||
idv.set_int(offset + i * step);
|
||||
st.push(idv);
|
||||
if (cond && !cs.run(cond).get_bool()) {
|
||||
break;
|
||||
}
|
||||
switch (cs.run_loop(body)) {
|
||||
case loop_state::BREAK:
|
||||
return;
|
||||
default: /* continue and normal */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
end:
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void do_loop_conc(
|
||||
state &cs, any_value &res, ident &id, integer_type offset, integer_type n,
|
||||
integer_type step, bcode *body, bool space
|
||||
) {
|
||||
stacked_value idv{cs, &id};
|
||||
if (n <= 0 || !idv.has_alias()) {
|
||||
if (n <= 0) {
|
||||
return;
|
||||
}
|
||||
charbuf s{cs};
|
||||
for (integer_type i = 0; i < n; ++i) {
|
||||
idv.set_int(offset + i * step);
|
||||
idv.push();
|
||||
any_value v{cs};
|
||||
switch (cs.run_loop(body, v)) {
|
||||
case loop_state::BREAK:
|
||||
goto end;
|
||||
case loop_state::CONTINUE:
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
if (alias_stack st{cs, &id}; st) {
|
||||
charbuf s{cs};
|
||||
any_value idv{cs};
|
||||
for (integer_type i = 0; i < n; ++i) {
|
||||
idv.set_int(offset + i * step);
|
||||
st.push(idv);
|
||||
any_value v{cs};
|
||||
switch (cs.run_loop(body, v)) {
|
||||
case loop_state::BREAK:
|
||||
goto end;
|
||||
case loop_state::CONTINUE:
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (space && i) {
|
||||
s.push_back(' ');
|
||||
}
|
||||
s.append(v.get_str());
|
||||
}
|
||||
if (space && i) {
|
||||
s.push_back(' ');
|
||||
}
|
||||
s.append(v.get_str());
|
||||
}
|
||||
end:
|
||||
res.set_str(s.str());
|
||||
res.set_str(s.str());
|
||||
}
|
||||
}
|
||||
|
||||
void init_lib_base(state &gcs) {
|
||||
|
@ -66,8 +68,8 @@ void init_lib_base(state &gcs) {
|
|||
});
|
||||
|
||||
gcs.new_command("pcall", "err", [](auto &cs, auto args, auto &ret) {
|
||||
alias *cret = args[1].get_ident()->get_alias(),
|
||||
*css = args[2].get_ident()->get_alias();
|
||||
alias *cret = args[1].get_ident()->get_alias();
|
||||
alias *css = args[2].get_ident()->get_alias();
|
||||
if (!cret || !css) {
|
||||
ret.set_int(0);
|
||||
return;
|
||||
|
@ -156,17 +158,14 @@ void init_lib_base(state &gcs) {
|
|||
});
|
||||
|
||||
gcs.new_command("pushif", "rte", [](auto &cs, auto args, auto &res) {
|
||||
stacked_value idv{cs, args[0].get_ident()};
|
||||
if (!idv.has_alias()) {
|
||||
return;
|
||||
}
|
||||
if (idv.get_alias()->get_flags() & IDENT_FLAG_ARG) {
|
||||
return;
|
||||
}
|
||||
if (args[1].get_bool()) {
|
||||
idv = args[1];
|
||||
idv.push();
|
||||
cs.run(args[2].get_code(), res);
|
||||
if (alias_stack st{cs, args[0].get_ident()}; st) {
|
||||
if (st.get_alias()->get_flags() & IDENT_FLAG_ARG) {
|
||||
return;
|
||||
}
|
||||
if (args[1].get_bool()) {
|
||||
st.push(args[1]);
|
||||
cs.run(args[2].get_code(), res);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -303,16 +302,13 @@ end:
|
|||
});
|
||||
|
||||
gcs.new_command("push", "rte", [](auto &cs, auto args, auto &res) {
|
||||
stacked_value idv{cs, args[0].get_ident()};
|
||||
if (!idv.has_alias()) {
|
||||
return;
|
||||
if (alias_stack st{cs, args[0].get_ident()}; st) {
|
||||
if (st.get_alias()->get_flags() & IDENT_FLAG_ARG) {
|
||||
return;
|
||||
}
|
||||
st.push(args[1]);
|
||||
cs.run(args[2].get_code(), res);
|
||||
}
|
||||
if (idv.get_alias()->get_flags() & IDENT_FLAG_ARG) {
|
||||
return;
|
||||
}
|
||||
idv = args[1];
|
||||
idv.push();
|
||||
cs.run(args[2].get_code(), res);
|
||||
});
|
||||
|
||||
gcs.new_command("resetvar", "s", [](auto &cs, auto args, auto &) {
|
||||
|
|
Loading…
Reference in New Issue