add better api to deal with alias stack
parent
3dc6ad866f
commit
d1243c5cc3
|
@ -507,8 +507,6 @@ protected:
|
||||||
command() = default;
|
command() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ident_link;
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
LIB_MATH = 1 << 0,
|
LIB_MATH = 1 << 0,
|
||||||
LIB_STRING = 1 << 1,
|
LIB_STRING = 1 << 1,
|
||||||
|
@ -818,6 +816,31 @@ private:
|
||||||
stack_state p_stack;
|
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 {
|
struct LIBCUBESCRIPT_EXPORT stacked_value: any_value {
|
||||||
stacked_value(state &cs, ident *id = nullptr);
|
stacked_value(state &cs, ident *id = nullptr);
|
||||||
~stacked_value();
|
~stacked_value();
|
||||||
|
|
|
@ -412,4 +412,61 @@ LIBCUBESCRIPT_EXPORT int command::get_num_args() const {
|
||||||
return static_cast<command_impl const *>(this)->p_numargs;
|
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 */
|
} /* 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,
|
state &cs, ident &id, integer_type offset, integer_type n, integer_type step,
|
||||||
bcode *cond, bcode *body
|
bcode *cond, bcode *body
|
||||||
) {
|
) {
|
||||||
stacked_value idv{cs, &id};
|
if (n <= 0) {
|
||||||
if (n <= 0 || !idv.has_alias()) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (integer_type i = 0; i < n; ++i) {
|
if (alias_stack st{cs, &id}; st) {
|
||||||
idv.set_int(offset + i * step);
|
any_value idv{cs};
|
||||||
idv.push();
|
for (integer_type i = 0; i < n; ++i) {
|
||||||
if (cond && !cs.run(cond).get_bool()) {
|
idv.set_int(offset + i * step);
|
||||||
break;
|
st.push(idv);
|
||||||
}
|
if (cond && !cs.run(cond).get_bool()) {
|
||||||
switch (cs.run_loop(body)) {
|
|
||||||
case loop_state::BREAK:
|
|
||||||
goto end;
|
|
||||||
default: /* continue and normal */
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
switch (cs.run_loop(body)) {
|
||||||
|
case loop_state::BREAK:
|
||||||
|
return;
|
||||||
|
default: /* continue and normal */
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end:
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void do_loop_conc(
|
static inline void do_loop_conc(
|
||||||
state &cs, any_value &res, ident &id, integer_type offset, integer_type n,
|
state &cs, any_value &res, ident &id, integer_type offset, integer_type n,
|
||||||
integer_type step, bcode *body, bool space
|
integer_type step, bcode *body, bool space
|
||||||
) {
|
) {
|
||||||
stacked_value idv{cs, &id};
|
if (n <= 0) {
|
||||||
if (n <= 0 || !idv.has_alias()) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
charbuf s{cs};
|
if (alias_stack st{cs, &id}; st) {
|
||||||
for (integer_type i = 0; i < n; ++i) {
|
charbuf s{cs};
|
||||||
idv.set_int(offset + i * step);
|
any_value idv{cs};
|
||||||
idv.push();
|
for (integer_type i = 0; i < n; ++i) {
|
||||||
any_value v{cs};
|
idv.set_int(offset + i * step);
|
||||||
switch (cs.run_loop(body, v)) {
|
st.push(idv);
|
||||||
case loop_state::BREAK:
|
any_value v{cs};
|
||||||
goto end;
|
switch (cs.run_loop(body, v)) {
|
||||||
case loop_state::CONTINUE:
|
case loop_state::BREAK:
|
||||||
continue;
|
goto end;
|
||||||
default:
|
case loop_state::CONTINUE:
|
||||||
break;
|
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:
|
end:
|
||||||
res.set_str(s.str());
|
res.set_str(s.str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_lib_base(state &gcs) {
|
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) {
|
gcs.new_command("pcall", "err", [](auto &cs, auto args, auto &ret) {
|
||||||
alias *cret = args[1].get_ident()->get_alias(),
|
alias *cret = args[1].get_ident()->get_alias();
|
||||||
*css = args[2].get_ident()->get_alias();
|
alias *css = args[2].get_ident()->get_alias();
|
||||||
if (!cret || !css) {
|
if (!cret || !css) {
|
||||||
ret.set_int(0);
|
ret.set_int(0);
|
||||||
return;
|
return;
|
||||||
|
@ -156,17 +158,14 @@ void init_lib_base(state &gcs) {
|
||||||
});
|
});
|
||||||
|
|
||||||
gcs.new_command("pushif", "rte", [](auto &cs, auto args, auto &res) {
|
gcs.new_command("pushif", "rte", [](auto &cs, auto args, auto &res) {
|
||||||
stacked_value idv{cs, args[0].get_ident()};
|
if (alias_stack st{cs, args[0].get_ident()}; st) {
|
||||||
if (!idv.has_alias()) {
|
if (st.get_alias()->get_flags() & IDENT_FLAG_ARG) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (idv.get_alias()->get_flags() & IDENT_FLAG_ARG) {
|
if (args[1].get_bool()) {
|
||||||
return;
|
st.push(args[1]);
|
||||||
}
|
cs.run(args[2].get_code(), res);
|
||||||
if (args[1].get_bool()) {
|
}
|
||||||
idv = args[1];
|
|
||||||
idv.push();
|
|
||||||
cs.run(args[2].get_code(), res);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -303,16 +302,13 @@ end:
|
||||||
});
|
});
|
||||||
|
|
||||||
gcs.new_command("push", "rte", [](auto &cs, auto args, auto &res) {
|
gcs.new_command("push", "rte", [](auto &cs, auto args, auto &res) {
|
||||||
stacked_value idv{cs, args[0].get_ident()};
|
if (alias_stack st{cs, args[0].get_ident()}; st) {
|
||||||
if (!idv.has_alias()) {
|
if (st.get_alias()->get_flags() & IDENT_FLAG_ARG) {
|
||||||
return;
|
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 &) {
|
gcs.new_command("resetvar", "s", [](auto &cs, auto args, auto &) {
|
||||||
|
|
Loading…
Reference in New Issue