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