mirror of
https://github.com/NixOS/nix
synced 2025-06-25 14:51:16 +02:00
Work on Values instead of Exprs
This prevents some duplicate evaluation in nix-env and nix-instantiate. Also, when traversing ~/.nix-defexpr, only read regular files with the extension .nix. Previously it was reading files like .../channels/binary-caches/<name>. The only reason this didn't cause problems is pure luck (namely, <name> shadows an actual Nix expression, the binary-caches files happen to be syntactically valid Nix expressions, and we iterate over the directory contents in just the right order).
This commit is contained in:
parent
06bb2d95b4
commit
ef4f5ba85e
4 changed files with 62 additions and 50 deletions
|
@ -6,9 +6,8 @@
|
|||
namespace nix {
|
||||
|
||||
|
||||
// !!! Shouldn't we return a pointer to a Value?
|
||||
void findAlongAttrPath(EvalState & state, const string & attrPath,
|
||||
Bindings & autoArgs, Expr * e, Value & v)
|
||||
Value * findAlongAttrPath(EvalState & state, const string & attrPath,
|
||||
Bindings & autoArgs, Value & vIn)
|
||||
{
|
||||
Strings tokens = tokenizeString<Strings>(attrPath, ".");
|
||||
|
||||
|
@ -17,7 +16,7 @@ void findAlongAttrPath(EvalState & state, const string & attrPath,
|
|||
|
||||
string curPath;
|
||||
|
||||
state.mkThunk_(v, e);
|
||||
Value * v = &vIn;
|
||||
|
||||
foreach (Strings::iterator, i, tokens) {
|
||||
|
||||
|
@ -31,10 +30,10 @@ void findAlongAttrPath(EvalState & state, const string & attrPath,
|
|||
if (string2Int(attr, attrIndex)) apType = apIndex;
|
||||
|
||||
/* Evaluate the expression. */
|
||||
Value vTmp;
|
||||
state.autoCallFunction(autoArgs, v, vTmp);
|
||||
v = vTmp;
|
||||
state.forceValue(v);
|
||||
Value * vNew = state.allocValue();
|
||||
state.autoCallFunction(autoArgs, *v, *vNew);
|
||||
v = vNew;
|
||||
state.forceValue(*v);
|
||||
|
||||
/* It should evaluate to either an attribute set or an
|
||||
expression, according to what is specified in the
|
||||
|
@ -42,31 +41,33 @@ void findAlongAttrPath(EvalState & state, const string & attrPath,
|
|||
|
||||
if (apType == apAttr) {
|
||||
|
||||
if (v.type != tAttrs)
|
||||
if (v->type != tAttrs)
|
||||
throw TypeError(
|
||||
format("the expression selected by the selection path `%1%' should be an attribute set but is %2%")
|
||||
% curPath % showType(v));
|
||||
% curPath % showType(*v));
|
||||
|
||||
Bindings::iterator a = v.attrs->find(state.symbols.create(attr));
|
||||
if (a == v.attrs->end())
|
||||
Bindings::iterator a = v->attrs->find(state.symbols.create(attr));
|
||||
if (a == v->attrs->end())
|
||||
throw Error(format("attribute `%1%' in selection path `%2%' not found") % attr % curPath);
|
||||
v = *a->value;
|
||||
v = &*a->value;
|
||||
}
|
||||
|
||||
else if (apType == apIndex) {
|
||||
|
||||
if (v.type != tList)
|
||||
if (v->type != tList)
|
||||
throw TypeError(
|
||||
format("the expression selected by the selection path `%1%' should be a list but is %2%")
|
||||
% curPath % showType(v));
|
||||
% curPath % showType(*v));
|
||||
|
||||
if (attrIndex >= v.list.length)
|
||||
if (attrIndex >= v->list.length)
|
||||
throw Error(format("list index %1% in selection path `%2%' is out of range") % attrIndex % curPath);
|
||||
|
||||
v = *v.list.elems[attrIndex];
|
||||
v = v->list.elems[attrIndex];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue