about summary refs log tree commit diff
path: root/src/libexpr/eval.cc
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2010-05-15T08·10+0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2010-05-15T08·10+0000
commitb2235d81d1b3733a93fdd1397a62d0f49409dcb0 (patch)
treec8e5ac8ceb4390f992e3972f595c5dde567d1b5f /src/libexpr/eval.cc
parent8032f26ca0bd2233de066ce5786ff976bbd641ae (diff)
* Restore the __overrides feature that was lost somewhere in the
  fast-eval branch.

Diffstat (limited to 'src/libexpr/eval.cc')
-rw-r--r--src/libexpr/eval.cc21
1 files changed, 19 insertions, 2 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index 26739faf69..14e5cab7de 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -108,6 +108,7 @@ EvalState::EvalState()
     , sMeta(symbols.create("meta"))
     , sName(symbols.create("name"))
     , sSystem(symbols.create("system"))
+    , sOverrides(symbols.create("__overrides"))
     , baseEnv(allocEnv(128))
     , baseEnvDispl(0)
     , staticBaseEnv(false, 0)
@@ -428,8 +429,8 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
            environment. */
         foreach (Attrs::iterator, i, attrs) {
             nix::Attr & a = (*v.attrs)[i->first];
-            mkCopy(a.value, env2.values[displ]);
-            mkThunk(env2.values[displ++], env2, i->second.first);
+            mkThunk(a.value, env2, i->second.first);
+            mkCopy(env2.values[displ++], a.value);
             a.pos = &i->second.second;
         }
 
@@ -443,6 +444,22 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
             a.pos = &i->second;
         }
 
+        /* If the rec contains an attribute called `__overrides', then
+           evaluate it, and add the attributes in that set to the rec.
+           This allows overriding of recursive attributes, which is
+           otherwise not possible.  (You can use the // operator to
+           replace an attribute, but other attributes in the rec will
+           still reference the original value, because that value has
+           been substituted into the bodies of the other attributes.
+           Hence we need __overrides.) */
+        Bindings::iterator overrides = v.attrs->find(state.sOverrides);
+        if (overrides != v.attrs->end()) {
+            state.forceAttrs(overrides->second.value);
+            foreach (Bindings::iterator, i, *overrides->second.value.attrs) {
+                nix::Attr & a = (*v.attrs)[i->first];
+                mkCopy(a.value, i->second.value);
+            }
+        }
     }
 
     else {