1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-19 08:49:35 +01:00

Be even lazier for the build evaluation

Now we can not evaluate anything \o/
This commit is contained in:
regnat 2021-06-08 16:05:51 +02:00
parent 30d14b772f
commit c7a232e200
6 changed files with 61 additions and 42 deletions

View file

@ -429,7 +429,7 @@ Value * InstallableFlake::getFlakeOutputs(EvalState & state, const flake::Locked
callFlake(state, lockedFlake, *vFlake); callFlake(state, lockedFlake, *vFlake);
auto vRes = state.allocValue(); auto vRes = state.allocValue();
auto gotField = state.getAttrField(*vFlake, {state.symbols.create("outputs")}, noPos, *vRes); auto gotField = state.lazyGetAttrField(*vFlake, {state.symbols.create("outputs")}, noPos, *vRes);
assert(gotField); assert(gotField);
return vRes; return vRes;
} }

View file

@ -47,8 +47,10 @@ void EvalState::forceValue(Value & v, const Pos & pos)
else if (v.isApp()) else if (v.isApp())
callFunction(*v.app.left, *v.app.right, v, noPos); callFunction(*v.app.left, *v.app.right, v, noPos);
else if (v.isCachedThunk()) { else if (v.isCachedThunk()) {
auto evalCache = v.getEvalCache();
v.mkThunk(v.cachedThunk.thunk->env, v.cachedThunk.thunk->expr); v.mkThunk(v.cachedThunk.thunk->env, v.cachedThunk.thunk->expr);
forceValue(v, pos); forceValue(v, pos);
v.setEvalCache(evalCache);
} }
else if (v.isBlackhole()) else if (v.isBlackhole())
throwEvalError(pos, "infinite recursion encountered"); throwEvalError(pos, "infinite recursion encountered");

View file

@ -1189,28 +1189,13 @@ void EvalState::updateCacheStats(ValueCache::CacheResult cacheResult)
}; };
} }
struct ExprCastedVar : Expr
{
Value * v;
ExprCastedVar(Value * v) : v(v) {};
void show(std::ostream & str) const override {
std::set<const Value*> active;
printValue(str, active, *v);
}
void bindVars(const StaticEnv & env) override {}
void eval(EvalState & state, Env & env, Value & v) override {
v = std::move(*this->v);
}
Value * maybeThunk(EvalState & state, Env & env) override {
return v;
}
};
bool EvalState::lazyGetAttrField(Value & attrs, const std::vector<Symbol> & selector, const Pos & pos, Value & dest) bool EvalState::lazyGetAttrField(Value & attrs, const std::vector<Symbol> & selector, const Pos & pos, Value & dest)
{ {
forceValue(attrs, pos);
auto eval_cache = attrs.getEvalCache(); auto eval_cache = attrs.getEvalCache();
if (eval_cache.isEmpty()) {
forceValue(attrs, pos);
eval_cache = attrs.getEvalCache();
}
auto [ cacheResult, resultingCursor ] = eval_cache.getValue(*this, selector, dest); auto [ cacheResult, resultingCursor ] = eval_cache.getValue(*this, selector, dest);
updateCacheStats(cacheResult); updateCacheStats(cacheResult);
switch (cacheResult.returnCode) { switch (cacheResult.returnCode) {
@ -1242,8 +1227,11 @@ bool EvalState::getAttrField(Value & attrs, const std::vector<Symbol> & selector
{ {
Pos * pos2 = 0; Pos * pos2 = 0;
forceValue(attrs, pos);
auto eval_cache = attrs.getEvalCache(); auto eval_cache = attrs.getEvalCache();
if (eval_cache.isEmpty()) {
forceValue(attrs, pos);
eval_cache = attrs.getEvalCache();
}
auto [ cacheResult, resultingCursor ] = eval_cache.getValue(*this, selector, dest); auto [ cacheResult, resultingCursor ] = eval_cache.getValue(*this, selector, dest);
updateCacheStats(cacheResult); updateCacheStats(cacheResult);
switch (cacheResult.returnCode) { switch (cacheResult.returnCode) {
@ -1260,6 +1248,7 @@ bool EvalState::getAttrField(Value & attrs, const std::vector<Symbol> & selector
; ;
} }
forceValue(attrs, pos);
Value * vAttrs = &attrs; Value * vAttrs = &attrs;
try { try {

View file

@ -596,36 +596,44 @@ void callFlake(EvalState & state,
const LockedFlake & lockedFlake, const LockedFlake & lockedFlake,
Value & vRes) Value & vRes)
{ {
auto vLocks = state.allocValue(); auto lockExpr = new ExprString(
state.symbols.create(lockedFlake.lockFile.to_string())
);
auto subdirExpr = new ExprString(
state.symbols.create(lockedFlake.flake.lockedRef.subdir)
);
auto vRootSrc = state.allocValue(); auto vRootSrc = state.allocValue();
auto vRootSubdir = state.allocValue();
auto vTmp1 = state.allocValue();
auto vTmp2 = state.allocValue();
mkString(*vLocks, lockedFlake.lockFile.to_string());
emitTreeAttrs(state, *lockedFlake.flake.sourceInfo, lockedFlake.flake.lockedRef.input, *vRootSrc); emitTreeAttrs(state, *lockedFlake.flake.sourceInfo, lockedFlake.flake.lockedRef.input, *vRootSrc);
mkString(*vRootSubdir, lockedFlake.flake.lockedRef.subdir); static Expr * callFlakeExpr = nullptr;
if (!callFlakeExpr) {
static RootValue vCallFlake = nullptr; callFlakeExpr = state.parseExprFromString(
if (!vCallFlake) {
vCallFlake = allocRootValue(state.allocValue());
state.eval(state.parseExprFromString(
#include "call-flake.nix.gen.hh" #include "call-flake.nix.gen.hh"
, "/"), **vCallFlake); , "/");
} }
state.callFunction(**vCallFlake, *vLocks, *vTmp1, noPos); auto resExpr = new ExprApp(
state.callFunction(*vTmp1, *vRootSrc, *vTmp2, noPos); new ExprApp(
state.callFunction(*vTmp2, *vRootSubdir, vRes, noPos); new ExprApp(
state.forceValue(vRes); callFlakeExpr,
lockExpr
),
new ExprCastedVar(vRootSrc)
),
subdirExpr
);
auto thunk = (Thunk*)allocBytes(sizeof(Thunk));
thunk->expr = resExpr;
thunk->env = &state.baseEnv;
auto fingerprint = lockedFlake.getFingerprint(); auto fingerprint = lockedFlake.getFingerprint();
auto treeCache = state.openTreeCache(fingerprint); auto treeCache = state.openTreeCache(fingerprint);
auto cacheRoot = treeCache ? treeCache->getRoot() : nullptr; auto cacheRoot = treeCache ? treeCache->getRoot() : nullptr;
auto evalCache = ValueCache(cacheRoot); auto evalCache = new ValueCache(cacheRoot);
vRes.setEvalCache(evalCache); vRes.mkCachedThunk(
thunk,
evalCache
);
} }
static void prim_getFlake(EvalState & state, const Pos & pos, Value * * args, Value & v) static void prim_getFlake(EvalState & state, const Pos & pos, Value * * args, Value & v)

View file

@ -440,6 +440,18 @@ string ExprLambda::showNamePos() const
return (format("%1% at %2%") % (name.set() ? "'" + (string) name + "'" : "anonymous function") % pos).str(); return (format("%1% at %2%") % (name.set() ? "'" + (string) name + "'" : "anonymous function") % pos).str();
} }
void ExprCastedVar::show(std::ostream & str) const {
std::set<const Value*> active;
printValue(str, active, *v);
}
void ExprCastedVar::bindVars(const StaticEnv & env) {}
void ExprCastedVar::eval(EvalState & state, Env & env, Value & v) {
v = std::move(*this->v);
}
Value * ExprCastedVar::maybeThunk(EvalState & state, Env & env) {
return v;
}
/* Symbol table. */ /* Symbol table. */

View file

@ -339,6 +339,14 @@ struct ExprPos : Expr
COMMON_METHODS COMMON_METHODS
}; };
struct ExprCastedVar : Expr
{
Value * v;
ExprCastedVar(Value * v) : v(v) {};
Value * maybeThunk(EvalState & state, Env & env);
COMMON_METHODS
};
/* Static environments are used to map variable names onto (level, /* Static environments are used to map variable names onto (level,
displacement) pairs used to obtain the value of the variable at displacement) pairs used to obtain the value of the variable at