about summary refs log tree commit diff
path: root/src/libexpr
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2010-03-31T11·05+0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2010-03-31T11·05+0000
commit13c2adc897b7f18e9a7784efbd46fabd995d2798 (patch)
tree634ee052f78cd49b18981038fddaae7b09fad445 /src/libexpr
parent4c53ca2692f0a1325ec2d085ac3a6ee313b3cdb2 (diff)
* Implemented `rec { inherit ...; }'.
Diffstat (limited to 'src/libexpr')
-rw-r--r--src/libexpr/eval-test.cc3
-rw-r--r--src/libexpr/eval.cc14
2 files changed, 17 insertions, 0 deletions
diff --git a/src/libexpr/eval-test.cc b/src/libexpr/eval-test.cc
index ff94e3ce1612..3399aedc4c8c 100644
--- a/src/libexpr/eval-test.cc
+++ b/src/libexpr/eval-test.cc
@@ -73,6 +73,9 @@ void run(Strings args)
     doTest("map (x: __add 1 x) [ 1 2 3 ]");
     doTest("map (builtins.add 1) [ 1 2 3 ]");
     doTest("builtins.hasAttr \"x\" { x = 1; }");
+    doTest("let x = 1; as = rec { inherit x; y = as.x; }; in as.y");
+    doTest("let as = { x = 1; }; bs = rec { inherit (as) x; y = x; }; in bs.y");
+    doTest("let as = rec { inherit (y) x; y = { x = 1; }; }; in as.x");
 }
 
 
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index 4624cbeaf114..7f0adb2c4cad 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -326,11 +326,16 @@ void EvalState::eval(Env & env, Expr e, Value & v)
     }
 
     else if (matchRec(e, rbnds, nrbnds)) {
+        /* Create a new environment that contains the attributes in
+           this `rec'. */
         Env & env2(allocEnv());
         env2.up = &env;
         
         v.type = tAttrs;
         v.attrs = &env2.bindings;
+
+        /* The recursive attributes are evaluated in the new
+           environment. */
         ATerm name, e2, pos;
         for (ATermIterator i(rbnds); i; ++i) {
             if (!matchBind(*i, name, e2, pos)) abort(); /* can't happen */
@@ -338,6 +343,15 @@ void EvalState::eval(Env & env, Expr e, Value & v)
             nrValues++;
             mkThunk(v2, env2, e2);
         }
+
+        /* The non-recursive attributes, on the other hand, are
+           evaluated in the original environment. */
+        for (ATermIterator i(nrbnds); i; ++i) {
+            if (!matchBind(*i, name, e2, pos)) abort(); /* can't happen */
+            Value & v2 = env2.bindings[name];
+            nrValues++;
+            mkThunk(v2, env, e2);
+        }
     }
 
     else if (matchSelect(e, e2, name)) {