libexpr/eval: Factor out attrs updating code into dedicated helper function

The bytecode evaluator can use it 1:1

Change-Id: I9791a749231fe42e0e534853d3f3cce91913346c
This commit is contained in:
piegames
2026-03-23 14:47:39 +01:00
parent 4960a217fe
commit 93edf577b7
3 changed files with 44 additions and 39 deletions
+1 -39
View File
@@ -329,45 +329,7 @@ Value ExprOpUpdate::eval(EvalState & state, Env & env)
Value v2 = e2->eval(state, env);
state.checkAttrs(v2, env, *e2);
state.ctx.stats.nrOpUpdates++;
if (v1.attrs()->size() == 0) {
return v2;
}
if (v2.attrs()->size() == 0) {
return v1;
}
auto attrs = state.ctx.buildBindings(v1.attrs()->size() + v2.attrs()->size());
/* Merge the sets, preferring values from the second set. Make
sure to keep the resulting vector in sorted order. */
Bindings::iterator i = v1.attrs()->begin();
Bindings::iterator j = v2.attrs()->begin();
while (i != v1.attrs()->end() && j != v2.attrs()->end()) {
if (i->name == j->name) {
attrs.insert(*j);
++i;
++j;
} else if (i->name < j->name) {
attrs.insert(*i++);
} else {
attrs.insert(*j++);
}
}
while (i != v1.attrs()->end()) {
attrs.insert(*i++);
}
while (j != v2.attrs()->end()) {
attrs.insert(*j++);
}
Value v = {NewValueAs::attrs, attrs.alreadySorted()};
state.ctx.stats.nrOpUpdateValuesCopied += v.attrs()->size();
return v;
return state.updateAttrs(v1, v2);
}
Value ExprOpConcatLists::eval(EvalState & state, Env & env)
+42
View File
@@ -1358,6 +1358,48 @@ https://docs.lix.systems/manual/lix/stable/language/constructs.html#functions)",
return callFunction(fun, vAttrs, pos);
}
Value EvalState::updateAttrs(const Value & v1, const Value & v2)
{
ctx.stats.nrOpUpdates++;
if (v1.attrs()->size() == 0) {
return v2;
}
if (v2.attrs()->size() == 0) {
return v1;
}
auto attrs = ctx.buildBindings(v1.attrs()->size() + v2.attrs()->size());
/* Merge the sets, preferring values from the second set. Make
sure to keep the resulting vector in sorted order. */
Bindings::iterator i = v1.attrs()->begin();
Bindings::iterator j = v2.attrs()->begin();
while (i != v1.attrs()->end() && j != v2.attrs()->end()) {
if (i->name == j->name) {
attrs.insert(*j);
++i;
++j;
} else if (i->name < j->name) {
attrs.insert(*i++);
} else {
attrs.insert(*j++);
}
}
while (i != v1.attrs()->end()) {
attrs.insert(*i++);
}
while (j != v2.attrs()->end()) {
attrs.insert(*j++);
}
Value v = {NewValueAs::attrs, attrs.alreadySorted()};
ctx.stats.nrOpUpdateValuesCopied += v.attrs()->size();
return v;
}
void EvalState::concatLists(
Value & v, std::span<Value> lists, const PosIdx pos, std::string_view errorCtx
)
+1
View File
@@ -826,6 +826,7 @@ public:
const SingleDerivedPath & p,
Value & v);
Value updateAttrs(const Value & v1, const Value & v2);
void
concatLists(Value & v, std::span<Value> lists, const PosIdx pos, std::string_view errorCtx);