From 93edf577b7ab949cd0301bf18fa17a06a35573ad Mon Sep 17 00:00:00 2001 From: piegames Date: Tue, 6 Jan 2026 13:24:02 +0100 Subject: [PATCH] libexpr/eval: Factor out attrs updating code into dedicated helper function The bytecode evaluator can use it 1:1 Change-Id: I9791a749231fe42e0e534853d3f3cce91913346c --- lix/libexpr/eval-expr.cc | 40 +------------------------------------- lix/libexpr/eval.cc | 42 ++++++++++++++++++++++++++++++++++++++++ lix/libexpr/eval.hh | 1 + 3 files changed, 44 insertions(+), 39 deletions(-) diff --git a/lix/libexpr/eval-expr.cc b/lix/libexpr/eval-expr.cc index cd3a99f16..cc802098d 100644 --- a/lix/libexpr/eval-expr.cc +++ b/lix/libexpr/eval-expr.cc @@ -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) diff --git a/lix/libexpr/eval.cc b/lix/libexpr/eval.cc index 6a4f0b83d..4b77776bb 100644 --- a/lix/libexpr/eval.cc +++ b/lix/libexpr/eval.cc @@ -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 lists, const PosIdx pos, std::string_view errorCtx ) diff --git a/lix/libexpr/eval.hh b/lix/libexpr/eval.hh index dfc034767..ab8ed11b9 100644 --- a/lix/libexpr/eval.hh +++ b/lix/libexpr/eval.hh @@ -826,6 +826,7 @@ public: const SingleDerivedPath & p, Value & v); + Value updateAttrs(const Value & v1, const Value & v2); void concatLists(Value & v, std::span lists, const PosIdx pos, std::string_view errorCtx);