From 3d94be61ea562dea2098b6570f711386179913ef Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 31 Mar 2010 15:38:03 +0000 Subject: [PATCH] * Implemented derivations. --- src/libexpr/eval.cc | 41 +++++-- src/libexpr/eval.hh | 9 +- src/libexpr/get-drvs.cc | 141 ++++++++++------------- src/libexpr/get-drvs.hh | 15 +-- src/libexpr/primops.cc | 150 +++++++++++-------------- src/nix-instantiate/nix-instantiate.cc | 19 +++- 6 files changed, 183 insertions(+), 192 deletions(-) diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 7f0adb2c4c..0296afe601 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -261,6 +261,14 @@ void EvalState::mkAttrs(Value & v) } +void EvalState::cloneAttrs(Value & src, Value & dst) +{ + mkAttrs(dst); + foreach (Bindings::iterator, i, *src.attrs) + (*dst.attrs)[i->first] = i->second; // !!! sharing? +} + + void EvalState::evalFile(const Path & path, Value & v) { startNest(nest, lvlTalkative, format("evaluating file `%1%'") % path); @@ -488,17 +496,14 @@ void EvalState::eval(Env & env, Expr e, Value & v) /* Attribute set update (//). */ else if (matchOpUpdate(e, e1, e2)) { - mkAttrs(v); - Value v2; + eval(env, e1, v2); + + cloneAttrs(v2, v); + eval(env, e2, v2); foreach (Bindings::iterator, i, *v2.attrs) - (*v.attrs)[i->first] = i->second; - - eval(env, e1, v2); - foreach (Bindings::iterator, i, *v2.attrs) - if (v.attrs->find(i->first) == v.attrs->end()) - (*v.attrs)[i->first] = i->second; + (*v.attrs)[i->first] = i->second; // !!! sharing } /* Attribute existence test (?). */ @@ -673,6 +678,15 @@ int EvalState::forceInt(Value & v) } +bool EvalState::forceBool(Value & v) +{ + forceValue(v); + if (v.type != tBool) + throw TypeError(format("value is %1% while a Boolean was expected") % showType(v)); + return v.boolean; +} + + void EvalState::forceAttrs(Value & v) { forceValue(v); @@ -697,15 +711,22 @@ void EvalState::forceFunction(Value & v) } -string EvalState::forceStringNoCtx(Value & v) +string EvalState::forceString(Value & v) { forceValue(v); if (v.type != tString) throw TypeError(format("value is %1% while a string was expected") % showType(v)); + return string(v.string.s); +} + + +string EvalState::forceStringNoCtx(Value & v) +{ + string s = forceString(v); if (v.string.context) throw EvalError(format("the string `%1%' is not allowed to refer to a store path (such as `%2%')") % v.string.s % v.string.context[0]); - return string(v.string.s); + return s; } diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index 198d936b97..eba97dd737 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -109,7 +109,6 @@ void mkString(Value & v, const string & s, const PathSet & context = PathSet()); void mkPath(Value & v, const char * s); -typedef std::map DrvRoots; typedef std::map DrvHashes; /* Cache for calls to addToStore(); maps source paths to the store @@ -124,8 +123,10 @@ std::ostream & operator << (std::ostream & str, Value & v); class EvalState { - DrvRoots drvRoots; +public: DrvHashes drvHashes; /* normalised derivation hashes */ + +private: SrcToStore srcToStore; unsigned long nrValues; @@ -164,9 +165,11 @@ public: /* Force `v', and then verify that it has the expected type. */ int forceInt(Value & v); + bool forceBool(Value & v); void forceAttrs(Value & v); void forceList(Value & v); void forceFunction(Value & v); // either lambda or primop + string forceString(Value & v); string forceStringNoCtx(Value & v); /* String coercion. Converts strings, paths and derivations to a @@ -209,6 +212,8 @@ public: void mkList(Value & v, unsigned int length); void mkAttrs(Value & v); + void cloneAttrs(Value & src, Value & dst); + /* Print statistics. */ void printStats(); }; diff --git a/src/libexpr/get-drvs.cc b/src/libexpr/get-drvs.cc index 26ce6e71cf..5ff77ff656 100644 --- a/src/libexpr/get-drvs.cc +++ b/src/libexpr/get-drvs.cc @@ -6,25 +6,18 @@ namespace nix { -#if 0 string DrvInfo::queryDrvPath(EvalState & state) const { if (drvPath == "") { - Expr a = attrs->get(toATerm("drvPath")); - - /* Backwards compatibility hack with user environments made by - Nix <= 0.10: these contain illegal Path("") expressions. */ - ATerm t; - if (a && matchPath(evalExpr(state, a), t)) - return aterm2String(t); - + Bindings::iterator i = attrs->find(toATerm("drvPath")); PathSet context; - (string &) drvPath = a ? coerceToPath(state, a, context) : ""; + (string &) drvPath = i != attrs->end() ? state.coerceToPath(i->second, context) : ""; } return drvPath; } +#if 0 string DrvInfo::queryOutPath(EvalState & state) const { if (outPath == "") { @@ -102,54 +95,47 @@ void DrvInfo::setMetaInfo(const MetaInfo & meta) } attrs->set(toATerm("meta"), makeAttrs(metaAttrs)); } +#endif -/* Cache for already evaluated derivations. Usually putting ATerms in - a STL container is unsafe (they're not scanning for GC roots), but - here it doesn't matter; everything in this set is reachable from - the stack as well. */ -typedef set Exprs; +/* Cache for already considered values. */ +typedef set Values; -/* Evaluate expression `e'. If it evaluates to an attribute set of - type `derivation', then put information about it in `drvs' (unless - it's already in `doneExprs'). The result boolean indicates whether - it makes sense for the caller to recursively search for derivations - in `e'. */ -static bool getDerivation(EvalState & state, Expr e, - const string & attrPath, DrvInfos & drvs, Exprs & doneExprs) +/* Evaluate value `v'. If it evaluates to an attribute set of type + `derivation', then put information about it in `drvs' (unless it's + already in `doneExprs'). The result boolean indicates whether it + makes sense for the caller to recursively search for derivations in + `v'. */ +static bool getDerivation(EvalState & state, Value & v, + const string & attrPath, DrvInfos & drvs, Values & doneValues) { try { - - ATermList es; - e = evalExpr(state, e); - if (!matchAttrs(e, es)) return true; + state.forceValue(v); + if (v.type != tAttrs) return true; - boost::shared_ptr attrs(new ATermMap()); - queryAllAttrs(e, *attrs, false); - - Expr a = attrs->get(toATerm("type")); - if (!a || evalStringNoCtx(state, a) != "derivation") return true; + Bindings::iterator i = v.attrs->find(toATerm("type")); + if (i == v.attrs->end() || state.forceStringNoCtx(i->second) != "derivation") return true; /* Remove spurious duplicates (e.g., an attribute set like `rec { x = derivation {...}; y = x;}'. */ - if (doneExprs.find(e) != doneExprs.end()) return false; - doneExprs.insert(e); + if (doneValues.find(&v) != doneValues.end()) return false; + doneValues.insert(&v); DrvInfo drv; - a = attrs->get(toATerm("name")); + i = v.attrs->find(toATerm("name")); /* !!! We really would like to have a decent back trace here. */ - if (!a) throw TypeError("derivation name missing"); - drv.name = evalStringNoCtx(state, a); + if (i == v.attrs->end()) throw TypeError("derivation name missing"); + drv.name = state.forceStringNoCtx(i->second); - a = attrs->get(toATerm("system")); - if (!a) + i = v.attrs->find(toATerm("system")); + if (i == v.attrs->end()) drv.system = "unknown"; else - drv.system = evalStringNoCtx(state, a); + drv.system = state.forceStringNoCtx(i->second); - drv.attrs = attrs; + drv.attrs = v.attrs; drv.attrPath = attrPath; @@ -162,11 +148,11 @@ static bool getDerivation(EvalState & state, Expr e, } -bool getDerivation(EvalState & state, Expr e, DrvInfo & drv) +bool getDerivation(EvalState & state, Value & v, DrvInfo & drv) { - Exprs doneExprs; + Values doneValues; DrvInfos drvs; - getDerivation(state, e, "", drvs, doneExprs); + getDerivation(state, v, "", drvs, doneValues); if (drvs.size() != 1) return false; drv = drvs.front(); return true; @@ -179,85 +165,72 @@ static string addToPath(const string & s1, const string & s2) } -static void getDerivations(EvalState & state, Expr e, +static void getDerivations(EvalState & state, Value & v, const string & pathPrefix, const ATermMap & autoArgs, - DrvInfos & drvs, Exprs & doneExprs) + DrvInfos & drvs, Values & doneValues) { - e = evalExpr(state, autoCallFunction(evalExpr(state, e), autoArgs)); - + // !!! autoCallFunction(evalExpr(state, e), autoArgs) + /* Process the expression. */ - ATermList es; DrvInfo drv; - if (!getDerivation(state, e, pathPrefix, drvs, doneExprs)) - return; + if (!getDerivation(state, v, pathPrefix, drvs, doneValues)) ; - if (matchAttrs(e, es)) { - ATermMap drvMap(ATgetLength(es)); - queryAllAttrs(e, drvMap); + else if (v.type == tAttrs) { /* !!! undocumented hackery to support combining channels in nix-env.cc. */ - bool combineChannels = drvMap.get(toATerm("_combineChannels")); + bool combineChannels = v.attrs->find(toATerm("_combineChannels")) != v.attrs->end(); /* Consider the attributes in sorted order to get more deterministic behaviour in nix-env operations (e.g. when there are names clashes between derivations, the derivation bound to the attribute with the "lower" name should take precedence). */ - typedef std::map AttrsSorted; - AttrsSorted attrsSorted; - foreach (ATermMap::const_iterator, i, drvMap) - attrsSorted[aterm2String(i->key)] = i->value; + StringSet attrs; + foreach (Bindings::iterator, i, *v.attrs) + attrs.insert(aterm2String(i->first)); - foreach (AttrsSorted::iterator, i, attrsSorted) { - startNest(nest, lvlDebug, format("evaluating attribute `%1%'") % i->first); - string pathPrefix2 = addToPath(pathPrefix, i->first); + foreach (StringSet::iterator, i, attrs) { + startNest(nest, lvlDebug, format("evaluating attribute `%1%'") % *i); + string pathPrefix2 = addToPath(pathPrefix, *i); + Value & v2((*v.attrs)[toATerm(*i)]); if (combineChannels) - getDerivations(state, i->second, pathPrefix2, autoArgs, drvs, doneExprs); - else if (getDerivation(state, i->second, pathPrefix2, drvs, doneExprs)) { + getDerivations(state, v2, pathPrefix2, autoArgs, drvs, doneValues); + else if (getDerivation(state, v2, pathPrefix2, drvs, doneValues)) { /* If the value of this attribute is itself an attribute set, should we recurse into it? => Only if it has a `recurseForDerivations = true' attribute. */ - ATermList es; - Expr e = evalExpr(state, i->second), e2; - if (matchAttrs(e, es)) { - ATermMap attrs(ATgetLength(es)); - queryAllAttrs(e, attrs, false); - if (((e2 = attrs.get(toATerm("recurseForDerivations"))) - && evalBool(state, e2))) - getDerivations(state, e, pathPrefix2, autoArgs, drvs, doneExprs); + if (v2.type == tAttrs) { + Bindings::iterator j = v2.attrs->find(toATerm("recurseForDerivations")); + if (j != v2.attrs->end() && state.forceBool(j->second)) + getDerivations(state, v2, pathPrefix2, autoArgs, drvs, doneValues); } } } - - return; } - if (matchList(e, es)) { - int n = 0; - for (ATermIterator i(es); i; ++i, ++n) { + else if (v.type == tList) { + for (unsigned int n = 0; n < v.list.length; ++n) { startNest(nest, lvlDebug, format("evaluating list element")); string pathPrefix2 = addToPath(pathPrefix, (format("%1%") % n).str()); - if (getDerivation(state, *i, pathPrefix2, drvs, doneExprs)) - getDerivations(state, *i, pathPrefix2, autoArgs, drvs, doneExprs); + if (getDerivation(state, v.list.elems[n], pathPrefix2, drvs, doneValues)) + getDerivations(state, v.list.elems[n], pathPrefix2, autoArgs, drvs, doneValues); } - return; } - throw TypeError("expression does not evaluate to a derivation (or a set or list of those)"); + else throw TypeError("expression does not evaluate to a derivation (or a set or list of those)"); } -void getDerivations(EvalState & state, Expr e, const string & pathPrefix, +void getDerivations(EvalState & state, Value & v, const string & pathPrefix, const ATermMap & autoArgs, DrvInfos & drvs) { - Exprs doneExprs; - getDerivations(state, e, pathPrefix, autoArgs, drvs, doneExprs); + Values doneValues; + getDerivations(state, v, pathPrefix, autoArgs, drvs, doneValues); } -#endif } diff --git a/src/libexpr/get-drvs.hh b/src/libexpr/get-drvs.hh index b56f547118..733f202012 100644 --- a/src/libexpr/get-drvs.hh +++ b/src/libexpr/get-drvs.hh @@ -35,10 +35,8 @@ public: string attrPath; /* path towards the derivation */ string system; - /* !!! these should really be hidden, and setMetaInfo() should - make a copy since the ATermMap can be shared between multiple - DrvInfos. */ - boost::shared_ptr attrs; + /* !!! make this private */ + Bindings * attrs; string queryDrvPath(EvalState & state) const; string queryOutPath(EvalState & state) const; @@ -62,12 +60,11 @@ public: typedef list DrvInfos; -/* Evaluate expression `e'. If it evaluates to a derivation, store - information about the derivation in `drv' and return true. - Otherwise, return false. */ -bool getDerivation(EvalState & state, Expr e, DrvInfo & drv); +/* If value `v' denotes a derivation, store information about the + derivation in `drv' and return true. Otherwise, return false. */ +bool getDerivation(EvalState & state, Value & v, DrvInfo & drv); -void getDerivations(EvalState & state, Expr e, const string & pathPrefix, +void getDerivations(EvalState & state, Value & v, const string & pathPrefix, const ATermMap & autoArgs, DrvInfos & drvs); diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 4b7e37e612..31914a65dd 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -207,6 +207,7 @@ static void prim_trace(EvalState & state, Value * * args, Value & v) printMsg(lvlError, format("trace: %1%") % e); return evalExpr(state, args[1]); } +#endif /************************************************************* @@ -282,24 +283,21 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v) { startNest(nest, lvlVomit, "evaluating derivation"); - ATermMap attrs; - queryAllAttrs(evalExpr(state, args[0]), attrs, true); + state.forceAttrs(*args[0]); - /* Figure out the name already (for stack backtraces). */ - ATerm posDrvName; - Expr eDrvName = attrs.get(toATerm("name")); - if (!eDrvName) + /* Figure out the name first (for stack backtraces). */ + Bindings::iterator attr = args[0]->attrs->find(toATerm("name")); + if (attr == args[0]->attrs->end()) throw EvalError("required attribute `name' missing"); - if (!matchAttrRHS(eDrvName, eDrvName, posDrvName)) abort(); string drvName; try { - drvName = evalStringNoCtx(state, eDrvName); + drvName = state.forceStringNoCtx(attr->second); } catch (Error & e) { - e.addPrefix(format("while evaluating the derivation attribute `name' at %1%:\n") - % showPos(posDrvName)); + e.addPrefix(format("while evaluating the derivation attribute `name' at :\n")); + // !!! % showPos(posDrvName)); throw; } - + /* Build the derivation expression by processing the attributes. */ Derivation drv; @@ -308,12 +306,8 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v) string outputHash, outputHashAlgo; bool outputHashRecursive = false; - for (ATermMap::const_iterator i = attrs.begin(); i != attrs.end(); ++i) { - string key = aterm2String(i->key); - ATerm value; - Expr pos; - ATerm rhs = i->value; - if (!matchAttrRHS(rhs, value, pos)) abort(); + foreach (Bindings::iterator, i, *args[0]->attrs) { + string key = aterm2String(i->first); startNest(nest, lvlVomit, format("processing attribute `%1%'") % key); try { @@ -321,15 +315,9 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v) /* The `args' attribute is special: it supplies the command-line arguments to the builder. */ if (key == "args") { - ATermList es; - value = evalExpr(state, value); - if (!matchList(value, es)) { - static bool haveWarned = false; - warnOnce(haveWarned, "the `args' attribute should evaluate to a list"); - es = flattenList(state, value); - } - for (ATermIterator i(es); i; ++i) { - string s = coerceToString(state, *i, context, true); + state.forceList(i->second); + for (unsigned int n = 0; n < i->second.list.length; ++n) { + string s = state.coerceToString(i->second.list.elems[n], context, true); drv.args.push_back(s); } } @@ -337,7 +325,7 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v) /* All other attributes are passed to the builder through the environment. */ else { - string s = coerceToString(state, value, context, true); + string s = state.coerceToString(i->second, context, true); drv.env[key] = s; if (key == "builder") drv.builder = s; else if (key == "system") drv.platform = s; @@ -352,13 +340,12 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v) } } catch (Error & e) { - e.addPrefix(format("while evaluating the derivation attribute `%1%' at %2%:\n") - % key % showPos(pos)); - e.addPrefix(format("while instantiating the derivation named `%1%' at %2%:\n") - % drvName % showPos(posDrvName)); + e.addPrefix(format("while evaluating the derivation attribute `%1%' at :\n") + % key /* !!! % showPos(pos) */); + e.addPrefix(format("while instantiating the derivation named `%1%' at :\n") + % drvName /* !!! % showPos(posDrvName) */); throw; } - } /* Everything in the context of the strings in the derivation @@ -466,25 +453,25 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v) state.drvHashes[drvPath] = hashDerivationModulo(state, drv); /* !!! assumes a single output */ - ATermMap outAttrs(2); - outAttrs.set(toATerm("outPath"), - makeAttrRHS(makeStr(outPath, singleton(drvPath)), makeNoPos())); - outAttrs.set(toATerm("drvPath"), - makeAttrRHS(makeStr(drvPath, singleton("=" + drvPath)), makeNoPos())); - - return makeAttrs(outAttrs); + //state.mkAttrs(v); + state.cloneAttrs(*args[0], v); + mkString((*v.attrs)[toATerm("outPath")], outPath, singleton(drvPath)); + mkString((*v.attrs)[toATerm("drvPath")], drvPath, singleton("=" + drvPath)); + mkString((*v.attrs)[toATerm("type")], "derivation"); // !!! remove } static void prim_derivationLazy(EvalState & state, Value * * args, Value & v) { - Expr eAttrs = evalExpr(state, args[0]); - ATermMap attrs; - queryAllAttrs(eAttrs, attrs, true); + state.forceAttrs(*args[0]); - attrs.set(toATerm("type"), - makeAttrRHS(makeStr("derivation"), makeNoPos())); + state.cloneAttrs(*args[0], v); + mkString((*v.attrs)[toATerm("type")], "derivation"); + + /* !!! */ + +#if 0 Expr drvStrict = makeCall(makeVar(toATerm("derivation!")), eAttrs); attrs.set(toATerm("outPath"), @@ -493,8 +480,8 @@ static void prim_derivationLazy(EvalState & state, Value * * args, Value & v) makeAttrRHS(makeSelect(drvStrict, toATerm("drvPath")), makeNoPos())); return makeAttrs(attrs); -} #endif +} /************************************************************* @@ -592,6 +579,7 @@ static void prim_toXML(EvalState & state, Value * * args, Value & v) printTermAsXML(strictEvalExpr(state, args[0]), out, context); return makeStr(out.str(), context); } +#endif /* Store a string in the Nix store as a source file that can be used @@ -599,12 +587,12 @@ static void prim_toXML(EvalState & state, Value * * args, Value & v) static void prim_toFile(EvalState & state, Value * * args, Value & v) { PathSet context; - string name = evalStringNoCtx(state, args[0]); - string contents = evalString(state, args[1], context); + string name = state.forceStringNoCtx(*args[0]); + string contents = state.forceString(*args[1]); // !!! context PathSet refs; - for (PathSet::iterator i = context.begin(); i != context.end(); ++i) { + foreach (PathSet::iterator, i, context) { Path path = *i; if (path.at(0) == '=') path = string(path, 1); if (isDerivation(path)) @@ -619,11 +607,12 @@ static void prim_toFile(EvalState & state, Value * * args, Value & v) /* Note: we don't need to add `context' to the context of the result, since `storePath' itself has references to the paths used in args[1]. */ - - return makeStr(storePath, singleton(storePath)); + + mkString(v, storePath, singleton(storePath)); } +#if 0 struct FilterFromExpr : PathFilter { EvalState & state; @@ -731,10 +720,7 @@ static void prim_removeAttrs(EvalState & state, Value * * args, Value & v) state.forceAttrs(*args[0]); state.forceList(*args[1]); - state.mkAttrs(v); - - foreach (Bindings::iterator, i, *args[0]->attrs) - (*v.attrs)[i->first] = i->second; + state.cloneAttrs(*args[0], v); for (unsigned int i = 0; i < args[1]->list.length; ++i) { state.forceStringNoCtx(args[1]->list.elems[i]); @@ -743,40 +729,32 @@ static void prim_removeAttrs(EvalState & state, Value * * args, Value & v) } -#if 0 /* Builds an attribute set from a list specifying (name, value) pairs. To be precise, a list [{name = "name1"; value = value1;} ... {name = "nameN"; value = valueN;}] is transformed to {name1 = value1; ... nameN = valueN;}. */ static void prim_listToAttrs(EvalState & state, Value * * args, Value & v) { - try { - ATermMap res = ATermMap(); - ATermList list; - list = evalList(state, args[0]); - for (ATermIterator i(list); i; ++i){ - // *i should now contain a pointer to the list item expression - ATermList attrs; - Expr evaledExpr = evalExpr(state, *i); - if (matchAttrs(evaledExpr, attrs)){ - Expr e = evalExpr(state, makeSelect(evaledExpr, toATerm("name"))); - string attr = evalStringNoCtx(state,e); - Expr r = makeSelect(evaledExpr, toATerm("value")); - res.set(toATerm(attr), makeAttrRHS(r, makeNoPos())); - } - else - throw TypeError(format("list element in `listToAttrs' is %s, expected a set { name = \"\"; value = ; }") - % showType(evaledExpr)); - } - - return makeAttrs(res); - - } catch (Error & e) { - e.addPrefix(format("in `listToAttrs':\n")); - throw; + state.forceList(*args[0]); + + state.mkAttrs(v); + + for (unsigned int i = 0; i < args[0]->list.length; ++i) { + Value & v2(args[0]->list.elems[i]); + state.forceAttrs(v2); + + Bindings::iterator j = v2.attrs->find(toATerm("name")); + if (j == v2.attrs->end()) + throw TypeError("`name' attribute missing in a call to `listToAttrs'"); + string name = state.forceStringNoCtx(j->second); + + j = v2.attrs->find(toATerm("value")); + if (j == v2.attrs->end()) + throw TypeError("`value' attribute missing in a call to `listToAttrs'"); + + (*v.attrs)[toATerm(name)] = j->second; // !!! sharing? } } -#endif #if 0 @@ -897,7 +875,7 @@ static void prim_map(EvalState & state, Value * * args, Value & v) static void prim_length(EvalState & state, Value * * args, Value & v) { state.forceList(*args[0]); - mkInt(v, v.list.length); + mkInt(v, args[0]->list.length); } @@ -1111,11 +1089,11 @@ void EvalState::createBaseEnv() // Expr <-> String addPrimOp("__exprToString", 1, prim_exprToString); addPrimOp("__stringToExpr", 1, prim_stringToExpr); +#endif // Derivations - addPrimOp("derivation!", 1, prim_derivationStrict); - addPrimOp("derivation", 1, prim_derivationLazy); -#endif + addPrimOp("derivation", 1, prim_derivationStrict); + //addPrimOp("derivation", 1, prim_derivationLazy); // Paths addPrimOp("__toPath", 1, prim_toPath); @@ -1130,7 +1108,9 @@ void EvalState::createBaseEnv() // Creating files #if 0 addPrimOp("__toXML", 1, prim_toXML); +#endif addPrimOp("__toFile", 2, prim_toFile); +#if 0 addPrimOp("__filterSource", 2, prim_filterSource); #endif @@ -1140,8 +1120,8 @@ void EvalState::createBaseEnv() addPrimOp("__hasAttr", 2, prim_hasAttr); addPrimOp("__isAttrs", 1, prim_isAttrs); addPrimOp("removeAttrs", 2, prim_removeAttrs); -#if 0 addPrimOp("__listToAttrs", 1, prim_listToAttrs); +#if 0 addPrimOp("__intersectAttrs", 2, prim_intersectAttrs); addPrimOp("__functionArgs", 1, prim_functionArgs); #endif diff --git a/src/nix-instantiate/nix-instantiate.cc b/src/nix-instantiate/nix-instantiate.cc index 86bb1841b9..a71998de24 100644 --- a/src/nix-instantiate/nix-instantiate.cc +++ b/src/nix-instantiate/nix-instantiate.cc @@ -75,8 +75,23 @@ void processExpr(EvalState & state, const Strings & attrPaths, std::cout << format("%1%\n") % canonicaliseExpr(e); else { Value v; - state.strictEval(e, v); - std::cout << v << std::endl; + if (strict) state.strictEval(e, v); else state.eval(e, v); + if (evalOnly) + std::cout << v << std::endl; + else { + DrvInfos drvs; + getDerivations(state, v, "", autoArgs, drvs); + foreach (DrvInfos::iterator, i, drvs) { + Path drvPath = i->queryDrvPath(state); + if (gcRoot == "") + printGCWarning(); + else + drvPath = addPermRoot(drvPath, + makeRootName(gcRoot, rootNr), + indirectRoot); + std::cout << format("%1%\n") % drvPath; + } + } } #if 0