move everything to alias_stack and remove stacked_value

master
Daniel Kolesa 2021-03-30 20:55:50 +02:00
parent 1def48cf76
commit 89e5f5f004
3 changed files with 125 additions and 229 deletions

View File

@ -837,32 +837,6 @@ private:
alias *p_alias;
};
struct LIBCUBESCRIPT_EXPORT stacked_value: any_value {
stacked_value(state &cs, ident *id = nullptr);
~stacked_value();
stacked_value(stacked_value const &) = delete;
stacked_value(stacked_value &&) = delete;
stacked_value &operator=(stacked_value const &) = delete;
stacked_value &operator=(stacked_value &&v) = delete;
stacked_value &operator=(any_value const &v);
stacked_value &operator=(any_value &&v);
bool set_alias(ident *id);
alias *get_alias() const;
bool has_alias() const;
bool push();
bool pop();
private:
state &p_state;
alias *p_a;
bool p_pushed;
};
struct LIBCUBESCRIPT_EXPORT list_parser {
list_parser(state &cs, std::string_view s = std::string_view{}):
p_state{&cs}, p_input_beg{s.data()}, p_input_end{s.data() + s.size()}

View File

@ -408,68 +408,6 @@ bool any_value::get_bool() const {
}
}
/* stacked value for easy stack management */
stacked_value::stacked_value(state &cs, ident *id):
any_value{cs}, p_state{cs}, p_a{nullptr}, p_pushed{false}
{
set_alias(id);
}
stacked_value::~stacked_value() {
pop();
static_cast<any_value *>(this)->~any_value();
}
stacked_value &stacked_value::operator=(any_value const &v) {
*static_cast<any_value *>(this) = v;
return *this;
}
stacked_value &stacked_value::operator=(any_value &&v) {
*static_cast<any_value *>(this) = std::move(v);
return *this;
}
bool stacked_value::set_alias(ident *id) {
if (!id || !id->is_alias()) {
return false;
}
p_a = static_cast<alias *>(id);
return true;
}
alias *stacked_value::get_alias() const {
return p_a;
}
bool stacked_value::has_alias() const {
return p_a != nullptr;
}
bool stacked_value::push() {
if (!p_a) {
return false;
}
auto &ts = *p_state.thread_pointer();
auto &ap = *static_cast<alias_impl *>(p_a);
if (!p_pushed) {
ap.push_arg(ts.idstack.emplace_back(p_state));
p_pushed = true;
}
ap.p_val = std::move(*static_cast<any_value *>(this));
return true;
}
bool stacked_value::pop() {
if (!p_pushed || !p_a) {
return false;
}
static_cast<alias_impl *>(p_a)->pop_arg();
p_pushed = false;
return true;
}
/* public utilities */
LIBCUBESCRIPT_EXPORT string_ref concat_values(

View File

@ -76,31 +76,30 @@ static void loop_list_conc(
state &cs, any_value &res, ident *id, std::string_view list,
bcode *body, bool space
) {
stacked_value idv{cs, id};
if (!idv.has_alias()) {
return;
}
charbuf r{cs};
int n = 0;
for (list_parser p{cs, list}; p.parse(); ++n) {
idv.set_str(p.get_item());
idv.push();
if (n && space) {
r.push_back(' ');
if (alias_stack st{cs, id}; st) {
any_value idv{cs};
charbuf r{cs};
int n = 0;
for (list_parser p{cs, list}; p.parse(); ++n) {
idv.set_str(p.get_item());
st.set(std::move(idv));
if (n && space) {
r.push_back(' ');
}
any_value v{cs};
switch (cs.run_loop(body, v)) {
case loop_state::BREAK:
goto end;
case loop_state::CONTINUE:
continue;
default:
break;
}
r.append(v.get_str());
}
any_value v{cs};
switch (cs.run_loop(body, v)) {
case loop_state::BREAK:
goto end;
case loop_state::CONTINUE:
continue;
default:
break;
}
r.append(v.get_str());
}
end:
res.set_str(r.str());
res.set_str(r.str());
}
}
int list_includes(
@ -205,44 +204,41 @@ void init_lib_list(state &gcs) {
});
gcs.new_command("listfind", "rse", [](auto &cs, auto args, auto &res) {
stacked_value idv{cs, args[0].get_ident()};
if (!idv.has_alias()) {
res.set_int(-1);
return;
}
auto body = args[2].get_code();
int n = -1;
for (list_parser p{cs, args[1].get_str()}; p.parse();) {
++n;
idv.set_str(p.get_raw_item());
idv.push();
if (cs.run(body).get_bool()) {
res.set_int(integer_type(n));
return;
if (alias_stack st{cs, args[0].get_ident()}; st) {
any_value idv{cs};
auto body = args[2].get_code();
int n = -1;
for (list_parser p{cs, args[1].get_str()}; p.parse();) {
++n;
idv.set_str(p.get_raw_item());
st.set(std::move(idv));
if (cs.run(body).get_bool()) {
res.set_int(integer_type(n));
return;
}
}
}
res.set_int(-1);
});
gcs.new_command("listassoc", "rse", [](auto &cs, auto args, auto &res) {
stacked_value idv{cs, args[0].get_ident()};
if (!idv.has_alias()) {
return;
}
auto body = args[2].get_code();
int n = -1;
for (list_parser p{cs, args[1].get_str()}; p.parse();) {
++n;
idv.set_str(p.get_raw_item());
idv.push();
if (cs.run(body).get_bool()) {
if (p.parse()) {
res.set_str(p.get_item());
if (alias_stack st{cs, args[0].get_ident()}; st) {
any_value idv{cs};
auto body = args[2].get_code();
int n = -1;
for (list_parser p{cs, args[1].get_str()}; p.parse();) {
++n;
idv.set_str(p.get_raw_item());
st.set(std::move(idv));
if (cs.run(body).get_bool()) {
if (p.parse()) {
res.set_str(p.get_item());
}
break;
}
if (!p.parse()) {
break;
}
break;
}
if (!p.parse()) {
break;
}
}
});
@ -292,87 +288,82 @@ void init_lib_list(state &gcs) {
});
gcs.new_command("looplist", "rse", [](auto &cs, auto args, auto &) {
stacked_value idv{cs, args[0].get_ident()};
if (!idv.has_alias()) {
return;
}
auto body = args[2].get_code();
int n = 0;
for (list_parser p{cs, args[1].get_str()}; p.parse(); ++n) {
idv.set_str(p.get_item());
idv.push();
switch (cs.run_loop(body)) {
case loop_state::BREAK:
goto end;
default: /* continue and normal */
break;
if (alias_stack st{cs, args[0].get_ident()}; st) {
any_value idv{cs};
auto body = args[2].get_code();
int n = 0;
for (list_parser p{cs, args[1].get_str()}; p.parse(); ++n) {
idv.set_str(p.get_item());
st.set(std::move(idv));
switch (cs.run_loop(body)) {
case loop_state::BREAK:
return;
default: /* continue and normal */
break;
}
}
}
end:
return;
});
gcs.new_command("looplist2", "rrse", [](auto &cs, auto args, auto &) {
stacked_value idv1{cs, args[0].get_ident()};
stacked_value idv2{cs, args[1].get_ident()};
if (!idv1.has_alias() || !idv2.has_alias()) {
alias_stack st1{cs, args[0].get_ident()};
alias_stack st2{cs, args[1].get_ident()};
if (!st1 || !st2) {
return;
}
any_value idv{cs};
auto body = args[3].get_code();
int n = 0;
for (list_parser p{cs, args[2].get_str()}; p.parse(); n += 2) {
idv1.set_str(p.get_item());
idv.set_str(p.get_item());
st1.set(std::move(idv));
if (p.parse()) {
idv2.set_str(p.get_item());
idv.set_str(p.get_item());
} else {
idv2.set_str("");
idv.set_str("");
}
idv1.push();
idv2.push();
st2.set(std::move(idv));
switch (cs.run_loop(body)) {
case loop_state::BREAK:
goto end;
return;
default: /* continue and normal */
break;
}
}
end:
return;
});
gcs.new_command("looplist3", "rrrse", [](auto &cs, auto args, auto &) {
stacked_value idv1{cs, args[0].get_ident()};
stacked_value idv2{cs, args[1].get_ident()};
stacked_value idv3{cs, args[2].get_ident()};
if (!idv1.has_alias() || !idv2.has_alias() || !idv3.has_alias()) {
alias_stack st1{cs, args[0].get_ident()};
alias_stack st2{cs, args[1].get_ident()};
alias_stack st3{cs, args[2].get_ident()};
if (!st1 || !st2 || !st3) {
return;
}
any_value idv{cs};
auto body = args[4].get_code();
int n = 0;
for (list_parser p{cs, args[3].get_str()}; p.parse(); n += 3) {
idv1.set_str(p.get_item());
idv.set_str(p.get_item());
st1.set(std::move(idv));
if (p.parse()) {
idv2.set_str(p.get_item());
idv.set_str(p.get_item());
} else {
idv2.set_str("");
idv.set_str("");
}
st2.set(std::move(idv));
if (p.parse()) {
idv3.set_str(p.get_item());
idv.set_str(p.get_item());
} else {
idv3.set_str("");
idv.set_str("");
}
idv1.push();
idv2.push();
idv3.push();
st3.set(std::move(idv));
switch (cs.run_loop(body)) {
case loop_state::BREAK:
goto end;
return;
default: /* continue and normal */
break;
}
}
end:
return;
});
gcs.new_command("looplistconcat", "rse", [](auto &cs, auto args, auto &res) {
@ -392,41 +383,39 @@ end:
});
gcs.new_command("listfilter", "rse", [](auto &cs, auto args, auto &res) {
stacked_value idv{cs, args[0].get_ident()};
if (!idv.has_alias()) {
return;
}
auto body = args[2].get_code();
charbuf r{cs};
int n = 0;
for (list_parser p{cs, args[1].get_str()}; p.parse(); ++n) {
idv.set_str(p.get_raw_item());
idv.push();
if (cs.run(body).get_bool()) {
if (r.size()) {
r.push_back(' ');
if (alias_stack st{cs, args[0].get_ident()}; st) {
any_value idv{cs};
auto body = args[2].get_code();
charbuf r{cs};
int n = 0;
for (list_parser p{cs, args[1].get_str()}; p.parse(); ++n) {
idv.set_str(p.get_raw_item());
st.set(std::move(idv));
if (cs.run(body).get_bool()) {
if (r.size()) {
r.push_back(' ');
}
r.append(p.get_quoted_item());
}
r.append(p.get_quoted_item());
}
res.set_str(r.str());
}
res.set_str(r.str());
});
gcs.new_command("listcount", "rse", [](auto &cs, auto args, auto &res) {
stacked_value idv{cs, args[0].get_ident()};
if (!idv.has_alias()) {
return;
}
auto body = args[2].get_code();
int n = 0, r = 0;
for (list_parser p{cs, args[1].get_str()}; p.parse(); ++n) {
idv.set_str(p.get_raw_item());
idv.push();
if (cs.run(body).get_bool()) {
r++;
if (alias_stack st{cs, args[0].get_ident()}; st) {
any_value idv{cs};
auto body = args[2].get_code();
int n = 0, r = 0;
for (list_parser p{cs, args[1].get_str()}; p.parse(); ++n) {
idv.set_str(p.get_raw_item());
st.set(std::move(idv));
if (cs.run(body).get_bool()) {
r++;
}
}
res.set_int(r);
}
res.set_int(r);
});
gcs.new_command("prettylist", "ss", [](auto &cs, auto args, auto &res) {
@ -529,14 +518,15 @@ struct ListSortItem {
struct ListSortFun {
state &cs;
stacked_value &xv, &yv;
alias_stack &xst, &yst;
bcode *body;
bool operator()(ListSortItem const &xval, ListSortItem const &yval) {
xv.set_str(xval.str);
yv.set_str(yval.str);
xv.push();
yv.push();
any_value v{cs};
v.set_str(xval.str);
xst.set(std::move(v));
v.set_str(yval.str);
yst.set(std::move(v));
return cs.run(body).get_bool();
}
};
@ -545,11 +535,14 @@ static void list_sort(
state &cs, any_value &res, std::string_view list,
ident *x, ident *y, bcode *body, bcode *unique
) {
if (x == y || !x->is_alias() || !y->is_alias()) {
if (x == y) {
return;
}
alias *xa = static_cast<alias *>(x), *ya = static_cast<alias *>(y);
alias_stack xst{cs, x}, yst{cs, y};
if (!xst || !yst) {
return;
}
valbuf<ListSortItem> items{cs.thread_pointer()->istate};
size_t total = 0;
@ -565,16 +558,10 @@ static void list_sort(
return;
}
stacked_value xval{cs, xa}, yval{cs, ya};
xval.set_none();
yval.set_none();
xval.push();
yval.push();
size_t totaluniq = total;
size_t nuniq = items.size();
if (body) {
ListSortFun f = { cs, xval, yval, body };
ListSortFun f = { cs, xst, yst, body };
std::sort(items.buf.begin(), items.buf.end(), f);
if (!code_is_empty(unique)) {
f.body = unique;
@ -591,7 +578,7 @@ static void list_sort(
}
}
} else {
ListSortFun f = { cs, xval, yval, unique };
ListSortFun f = { cs, xst, yst, unique };
totaluniq = items[0].quote.size();
nuniq = 1;
for (size_t i = 1; i < items.size(); i++) {
@ -610,9 +597,6 @@ static void list_sort(
}
}
xval.pop();
yval.pop();
charbuf sorted{cs};
sorted.reserve(totaluniq + std::max(nuniq - 1, size_t(0)));
for (size_t i = 0; i < items.size(); ++i) {