mirror of
https://github.com/NixOS/nix
synced 2025-06-24 22:11:15 +02:00
libexpr: don't allocate additional set in builtins.listToAttrs
This commit is contained in:
parent
46853c467d
commit
5c9cfa46fc
1 changed files with 27 additions and 10 deletions
|
@ -2961,25 +2961,42 @@ static void prim_listToAttrs(EvalState & state, const PosIdx pos, Value * * args
|
||||||
{
|
{
|
||||||
state.forceList(*args[0], pos, "while evaluating the argument passed to builtins.listToAttrs");
|
state.forceList(*args[0], pos, "while evaluating the argument passed to builtins.listToAttrs");
|
||||||
|
|
||||||
auto attrs = state.buildBindings(args[0]->listSize());
|
size_t listSize = args[0]->listSize();
|
||||||
|
auto & bindings = *state.allocBindings(listSize);
|
||||||
|
|
||||||
std::set<Symbol> seen;
|
for (const auto & [n, v2] : enumerate(args[0]->listItems())) {
|
||||||
|
|
||||||
for (auto v2 : args[0]->listItems()) {
|
|
||||||
state.forceAttrs(*v2, pos, "while evaluating an element of the list passed to builtins.listToAttrs");
|
state.forceAttrs(*v2, pos, "while evaluating an element of the list passed to builtins.listToAttrs");
|
||||||
|
|
||||||
auto j = state.getAttr(state.sName, v2->attrs(), "in a {name=...; value=...;} pair");
|
auto j = state.getAttr(state.sName, v2->attrs(), "in a {name=...; value=...;} pair");
|
||||||
|
|
||||||
auto name = state.forceStringNoCtx(*j->value, j->pos, "while evaluating the `name` attribute of an element of the list passed to builtins.listToAttrs");
|
auto name = state.forceStringNoCtx(*j->value, j->pos, "while evaluating the `name` attribute of an element of the list passed to builtins.listToAttrs");
|
||||||
|
|
||||||
auto sym = state.symbols.create(name);
|
auto sym = state.symbols.create(name);
|
||||||
if (seen.insert(sym).second) {
|
|
||||||
auto j2 = state.getAttr(state.sValue, v2->attrs(), "in a {name=...; value=...;} pair");
|
bindings[n] = Attr(sym, (Value *) &v2);
|
||||||
attrs.insert(sym, j2->value, j2->pos);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
v.mkAttrs(attrs);
|
std::sort(&bindings[0], &bindings[listSize], [](const Attr & a, const Attr & b) {
|
||||||
|
// a.value < b.value makes the sort stable because `value` points to an array item
|
||||||
|
return a < b || (!(a > b) && a.value < b.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
Symbol prev;
|
||||||
|
for (size_t n = 0; n < listSize; n++) {
|
||||||
|
auto attr = bindings[n];
|
||||||
|
if (prev == attr.name) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Value * v2 = *(Value * const *) attr.value;
|
||||||
|
|
||||||
|
auto j = state.getAttr(state.sValue, v2->attrs(), "in a {name=...; value=...;} pair");
|
||||||
|
prev = attr.name;
|
||||||
|
bindings.push_back({prev, j->value, j->pos});
|
||||||
|
}
|
||||||
|
// help GC and clear end of allocated array
|
||||||
|
for (size_t n = bindings.size(); n < listSize; n++) {
|
||||||
|
bindings[n] = Attr{};
|
||||||
|
}
|
||||||
|
v.mkAttrs(&bindings);
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_listToAttrs({
|
static RegisterPrimOp primop_listToAttrs({
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue