From 13c2adc897b7f18e9a7784efbd46fabd995d2798 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 31 Mar 2010 11:05:39 +0000 Subject: [PATCH] * Implemented `rec { inherit ...; }'. --- src/libexpr/eval-test.cc | 3 +++ src/libexpr/eval.cc | 14 ++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/src/libexpr/eval-test.cc b/src/libexpr/eval-test.cc index ff94e3ce16..3399aedc4c 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 4624cbeaf1..7f0adb2c4c 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)) {