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-04-13T13·42+0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2010-04-13T13·42+0000
commit7d47498b5ea1ad4685bad954e5407f628f7f5595 (patch)
tree0451c3cd9301030af94a805f476d8b5926edd4d6 /src/libexpr/eval.cc
parentac1e8f40d4a5c380d68bb6f1c7cef6f1e7987c1a (diff)
* Evaluate lets directly (i.e. without desugaring to `rec { attrs...;
  <let-body> = e; }.<let-body>).  This prevents the unnecessary
  allocation of an attribute set.

Diffstat (limited to 'src/libexpr/eval.cc')
-rw-r--r--src/libexpr/eval.cc25
1 files changed, 25 insertions, 0 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index ffeae8d731..fbd618d417 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -456,6 +456,31 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
 }
 
 
+void ExprLet::eval(EvalState & state, Env & env, Value & v)
+{
+    /* Create a new environment that contains the attributes in this
+       `let'. */
+    Env & env2(state.allocEnv());
+    env2.up = &env;
+        
+    /* The recursive attributes are evaluated in the new
+       environment. */
+    foreach (ExprAttrs::Attrs::iterator, i, attrs->attrs) {
+        Value & v2 = env2.bindings[i->first];
+        mkThunk(v2, env2, i->second);
+    }
+
+    /* The inherited attributes, on the other hand, are evaluated in
+       the original environment. */
+    foreach (list<Symbol>::iterator, i, attrs->inherited) {
+        Value & v2 = env2.bindings[*i];
+        mkCopy(v2, *state.lookupVar(&env, *i));
+    }
+
+    state.eval(env2, body, v);
+}
+
+
 void ExprList::eval(EvalState & state, Env & env, Value & v)
 {
     state.mkList(v, elems.size());