about summary refs log tree commit diff
path: root/src/libexpr/attr-path.cc
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2013-09-03T13·17+0000
committerEelco Dolstra <eelco.dolstra@logicblox.com>2013-09-03T13·17+0000
commitef4f5ba85e487f567115d60e3cb4b53d81af6ea1 (patch)
treec3fe3050c1c9e5404298e72a30a36c0dd9e724ac /src/libexpr/attr-path.cc
parent06bb2d95b4d8232ef0cd0059d2609d2211d0e3e6 (diff)
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).
Diffstat (limited to 'src/libexpr/attr-path.cc')
-rw-r--r--src/libexpr/attr-path.cc35
1 files changed, 18 insertions, 17 deletions
diff --git a/src/libexpr/attr-path.cc b/src/libexpr/attr-path.cc
index 109001e601..d834dcae7a 100644
--- a/src/libexpr/attr-path.cc
+++ b/src/libexpr/attr-path.cc
@@ -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;
 }