diff --git a/lix/libexpr/eval-expr.cc b/lix/libexpr/eval-expr.cc index d4e6f6111..01c057479 100644 --- a/lix/libexpr/eval-expr.cc +++ b/lix/libexpr/eval-expr.cc @@ -1,4 +1,5 @@ #include "eval.hh" +#include "libexpr/nixexpr.hh" #include "primops.hh" #include "gc-small-vector.hh" @@ -10,14 +11,19 @@ namespace nix { +Value Expr::makeThunk(Evaluator & ctx, Env & env) +{ + ctx.stats.nrThunks++; + return {NewValueAs::thunk, ctx.mem, env, *this}; +} + /* Create a thunk for the delayed computation of the given expression in the given environment. But if the expression is a variable, then look it up right away. This significantly reduces the number of thunks allocated. */ Value Expr::maybeThunk(EvalState & state, Env & env) { - state.ctx.stats.nrThunks++; - return {NewValueAs::thunk, state.ctx.mem, env, *this}; + return makeThunk(state.ctx, env); } Value ExprVar::maybeThunk(EvalState & state, Env & env) @@ -99,18 +105,10 @@ Value ExprSet::eval(EvalState & state, Env & env) in the original environment. */ Displacement displ = 0; for (auto & i : attrs) { - Value vAttr; - if (hasOverrides && i.second.kind != ExprAttrs::AttrDef::Kind::Inherited) { - vAttr = { - NewValueAs::thunk, - state.ctx.mem, - *i.second.chooseByKind(&env2, &env, inheritEnv), - *i.second.e - }; - state.ctx.stats.nrThunks++; - } else { - vAttr = i.second.e->maybeThunk(state, *i.second.chooseByKind(&env2, &env, inheritEnv)); - } + Env & thunkEnv = *i.second.chooseByKind(&env2, &env, inheritEnv); + Value vAttr = hasOverrides && i.second.kind != ExprAttrs::AttrDef::Kind::Inherited + ? i.second.e->makeThunk(state.ctx, thunkEnv) + : i.second.e->maybeThunk(state, thunkEnv); env2.values[displ++] = vAttr; v.attrs()->push_back(Attr(i.first, vAttr, i.second.pos)); } diff --git a/lix/libexpr/eval-inline.hh b/lix/libexpr/eval-inline.hh index 58dcde35a..cfdb6427e 100644 --- a/lix/libexpr/eval-inline.hh +++ b/lix/libexpr/eval-inline.hh @@ -6,7 +6,6 @@ #include "lix/libexpr/eval-error.hh" #include "lix/libexpr/gc-alloc.hh" #include "value.hh" -#include namespace nix { diff --git a/lix/libexpr/eval.cc b/lix/libexpr/eval.cc index 7675f10c4..ab8e4f5ee 100644 --- a/lix/libexpr/eval.cc +++ b/lix/libexpr/eval.cc @@ -847,8 +847,7 @@ Value::List * EvalMemory::newList(size_t size) Value Evaluator::evalLazily(Expr & e) { - stats.nrThunks++; - return {NewValueAs::thunk, mem, builtins.env, e}; + return e.makeThunk(*this, builtins.env); } Value EvalState::mkPos(PosIdx p) diff --git a/lix/libexpr/nixexpr.hh b/lix/libexpr/nixexpr.hh index 8d7cabeef..a2f5bfbf3 100644 --- a/lix/libexpr/nixexpr.hh +++ b/lix/libexpr/nixexpr.hh @@ -129,6 +129,7 @@ public: virtual JSON toJSON(const SymbolTable & symbols) const; virtual void accept(ExprVisitor & ev, std::unique_ptr & ptr) = 0; virtual Value eval(EvalState & state, Env & env); + Value makeThunk(Evaluator & ctx, Env & env); virtual Value maybeThunk(EvalState & state, Env & env); /* Lambdas have a name associated with them, when they are declared in a binding: * `identity = x: x` will print the resulting value as `«lambda identity @ «string»:1:14»`.