redo alias_stack for robustness (guarantee order of push/pop)

master
Daniel Kolesa 2021-03-30 20:37:50 +02:00
parent 970e37f318
commit 1def48cf76
3 changed files with 20 additions and 50 deletions

View File

@ -826,19 +826,15 @@ struct LIBCUBESCRIPT_EXPORT alias_stack {
alias_stack &operator=(alias_stack const &) = delete; alias_stack &operator=(alias_stack const &) = delete;
alias_stack &operator=(alias_stack &&v) = delete; alias_stack &operator=(alias_stack &&v) = delete;
bool set_alias(ident *id); alias *get_alias() noexcept { return p_alias; }
alias *get_alias() const noexcept; alias const *get_alias() const noexcept { return p_alias; }
bool has_alias() const noexcept;
bool push(any_value val); bool set(any_value val);
bool pop();
explicit operator bool() const noexcept; explicit operator bool() const noexcept;
private: private:
state &p_state;
alias *p_alias; alias *p_alias;
bool p_pushed;
}; };
struct LIBCUBESCRIPT_EXPORT stacked_value: any_value { struct LIBCUBESCRIPT_EXPORT stacked_value: any_value {

View File

@ -413,57 +413,31 @@ LIBCUBESCRIPT_EXPORT int command::get_num_args() const {
/* external API for alias stack management */ /* external API for alias stack management */
LIBCUBESCRIPT_EXPORT alias_stack::alias_stack(state &cs, ident *a): LIBCUBESCRIPT_EXPORT alias_stack::alias_stack(state &cs, ident *a) {
p_state{cs}, p_pushed{false} if (!a || !a->is_alias()) {
{ p_alias = nullptr;
set_alias(a); return;
}
p_alias = static_cast<alias *>(a);
static_cast<alias_impl *>(p_alias)->push_arg(
cs.thread_pointer()->idstack.emplace_back(cs)
);
} }
LIBCUBESCRIPT_EXPORT alias_stack::~alias_stack() { LIBCUBESCRIPT_EXPORT alias_stack::~alias_stack() {
pop(); static_cast<alias_impl *>(p_alias)->pop_arg();
} }
LIBCUBESCRIPT_EXPORT bool alias_stack::set_alias(ident *id) { LIBCUBESCRIPT_EXPORT bool alias_stack::set(any_value val) {
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) { if (!p_alias) {
return false; return false;
} }
auto &ts = *p_state.thread_pointer(); static_cast<alias_impl *>(p_alias)->p_val = std::move(val);
auto &ap = *static_cast<alias_impl *>(p_alias);
if (!p_pushed) {
ap.push_arg(ts.idstack.emplace_back(p_state));
p_pushed = true;
}
ap.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; return true;
} }
LIBCUBESCRIPT_EXPORT alias_stack::operator bool() const noexcept { LIBCUBESCRIPT_EXPORT alias_stack::operator bool() const noexcept {
return has_alias(); return !!p_alias;
} }
} /* namespace cubescript */ } /* namespace cubescript */

View File

@ -16,7 +16,7 @@ static inline void do_loop(
any_value idv{cs}; any_value idv{cs};
for (integer_type i = 0; i < n; ++i) { for (integer_type i = 0; i < n; ++i) {
idv.set_int(offset + i * step); idv.set_int(offset + i * step);
st.push(idv); st.set(idv);
if (cond && !cs.run(cond).get_bool()) { if (cond && !cs.run(cond).get_bool()) {
break; break;
} }
@ -42,7 +42,7 @@ static inline void do_loop_conc(
any_value idv{cs}; any_value idv{cs};
for (integer_type i = 0; i < n; ++i) { for (integer_type i = 0; i < n; ++i) {
idv.set_int(offset + i * step); idv.set_int(offset + i * step);
st.push(idv); st.set(idv);
any_value v{cs}; any_value v{cs};
switch (cs.run_loop(body, v)) { switch (cs.run_loop(body, v)) {
case loop_state::BREAK: case loop_state::BREAK:
@ -163,7 +163,7 @@ void init_lib_base(state &gcs) {
return; return;
} }
if (args[1].get_bool()) { if (args[1].get_bool()) {
st.push(args[1]); st.set(args[1]);
cs.run(args[2].get_code(), res); cs.run(args[2].get_code(), res);
} }
} }
@ -306,7 +306,7 @@ end:
if (st.get_alias()->get_flags() & IDENT_FLAG_ARG) { if (st.get_alias()->get_flags() & IDENT_FLAG_ARG) {
return; return;
} }
st.push(args[1]); st.set(args[1]);
cs.run(args[2].get_code(), res); cs.run(args[2].get_code(), res);
} }
}); });