From 77557a6f06500e0a464f54c7b4b4f5162d0359bc Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Sat, 7 May 2005 21:48:49 +0000 Subject: [PATCH] Commit 3000! * Make the `derivation' primitive much more lazy. The expression `derivation attrs' now evaluates to (essentially) attrs // { type = "derivation"; outPath = derivation! attrs; drvPath = derivation! attrs; } where `derivation!' is a primop that does the actual derivation instantiation (i.e., it does what `derivation' used to do). The advantage is that it allows commands such as `nix-env -qa' and `nix-env -i' to be much faster since they no longer need to instantiate all derivations, just the `name' attribute. (However, `nix-env' doesn't yet take advantage of this since it still always evaluates the `outPath' and `drvPath' attributes). Also, this allows derivations to cyclically reference each other, for example, webServer = derivation { ... hostName = "svn.cs.uu.nl"; services = [svnService]; }; svnService = derivation { ... hostName = webServer.hostName; }; Previously, this would yield a black hole (infinite recursion). --- src/libexpr/primops.cc | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index f3d4f3653..e3dd2db18 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -213,14 +213,12 @@ static string concatStrings(const Strings & ss) derivation; `drvPath' containing the path of the Nix expression; and `type' set to `derivation' to indicate that this is a derivation. */ -static Expr primDerivation(EvalState & state, const ATermVector & _args) +static Expr primDerivationStrict(EvalState & state, const ATermVector & args) { startNest(nest, lvlVomit, "evaluating derivation"); ATermMap attrs; - Expr args = _args[0]; - args = evalExpr(state, args); - queryAllAttrs(args, attrs, true); + queryAllAttrs(evalExpr(state, args[0]), attrs, true); /* Build the derivation expression by processing the attributes. */ Derivation drv; @@ -341,10 +339,27 @@ static Expr primDerivation(EvalState & state, const ATermVector & _args) state.drvHashes[drvPath] = hashDerivationModulo(state, drv); /* !!! assumes a single output */ - attrs.set("outPath", makeAttrRHS(makePath(toATerm(outPath)), makeNoPos())); - attrs.set("drvPath", makeAttrRHS(makePath(toATerm(drvPath)), makeNoPos())); + ATermMap outAttrs; + outAttrs.set("outPath", makeAttrRHS(makePath(toATerm(outPath)), makeNoPos())); + outAttrs.set("drvPath", makeAttrRHS(makePath(toATerm(drvPath)), makeNoPos())); + + return makeAttrs(outAttrs); +} + + +static Expr primDerivationLazy(EvalState & state, const ATermVector & args) +{ + Expr eAttrs = evalExpr(state, args[0]); + ATermMap attrs; + queryAllAttrs(eAttrs, attrs, true); + attrs.set("type", makeAttrRHS(makeStr(toATerm("derivation")), makeNoPos())); + Expr drvStrict = makeCall(makeVar(toATerm("derivation!")), eAttrs); + + attrs.set("outPath", makeAttrRHS(makeSelect(drvStrict, toATerm("outPath")), makeNoPos())); + attrs.set("drvPath", makeAttrRHS(makeSelect(drvStrict, toATerm("drvPath")), makeNoPos())); + return makeAttrs(attrs); } @@ -438,7 +453,8 @@ void EvalState::addPrimOps() addPrimOp("__currentTime", 0, primCurrentTime); addPrimOp("import", 1, primImport); - addPrimOp("derivation", 1, primDerivation); + addPrimOp("derivation!", 1, primDerivationStrict); + addPrimOp("derivation", 1, primDerivationLazy); addPrimOp("baseNameOf", 1, primBaseNameOf); addPrimOp("toString", 1, primToString); addPrimOp("isNull", 1, primIsNull);