move everything to alias_stack and remove stacked_value
parent
1def48cf76
commit
89e5f5f004
|
@ -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()}
|
||||||
|
|
|
@ -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(
|
||||||
|
|
266
src/lib_list.cc
266
src/lib_list.cc
|
@ -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) {
|
||||||
|
|
Loading…
Reference in New Issue