about summary refs log tree commit diff
path: root/src/libexpr/eval.cc
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2004-02-02T21·39+0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2004-02-02T21·39+0000
commit1c9c0a5a46822be60c999f0196567c9e17cf5fa3 (patch)
tree6783413d7fd353fdd7562f47a2dc0aac132cd04d /src/libexpr/eval.cc
parentd9f30fe7c74ae8518a575c0d15ee00aa46a2229a (diff)
* Added syntactic sugar to the construction of attribute sets to
  `inherit' variables from the surrounding lexical scope.

  E.g.,

    {stdenv, libfoo}: derivation {
      builder = ./bla;
      inherit stdenv libfoo;
      xyzzy = 1;
    }

  is equivalent to

    {stdenv, libfoo}: derivation {
      builder = ./bla;
      stdenv = stdenv;
      libfoo = libfoo;
      xyzzy = 1;
    }

  Note that for mutually recursive attribute set definitions (`rec
  {...}'), this also works, that is, `rec {inherit x;}' is equivalent
  to `let {fresh = x; body = rec {x = fresh;};}', *not*
  `rec {x = x}'.

Diffstat (limited to 'src/libexpr/eval.cc')
-rw-r--r--src/libexpr/eval.cc30
1 files changed, 17 insertions, 13 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index 77cab55d03..820e934a63 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -55,15 +55,15 @@ static Expr substArgs(Expr body, ATermList formals, Expr arg)
 /* Transform a mutually recursive set into a non-recursive set.  Each
    attribute is transformed into an expression that has all references
    to attributes substituted with selection expressions on the
-   original set.  E.g., e = `rec {x = f x y, y = x}' becomes `{x = f
-   (e.x) (e.y), y = e.x}'. */
-ATerm expandRec(ATerm e, ATermList bnds)
+   original set.  E.g., e = `rec {x = f x y; y = x;}' becomes `{x = f
+   (e.x) (e.y); y = e.x;}'. */
+ATerm expandRec(ATerm e, ATermList rbnds, ATermList nrbnds)
 {
     ATMatcher m;
 
     /* Create the substitution list. */
     ATermMap subs;
-    for (ATermIterator i(bnds); i; ++i) {
+    for (ATermIterator i(rbnds); i; ++i) {
         string s;
         Expr e2;
         if (!(atMatch(m, *i) >> "Bind" >> s >> e2))
@@ -73,7 +73,7 @@ ATerm expandRec(ATerm e, ATermList bnds)
 
     /* Create the non-recursive set. */
     ATermMap as;
-    for (ATermIterator i(bnds); i; ++i) {
+    for (ATermIterator i(rbnds); i; ++i) {
         string s;
         Expr e2;
         if (!(atMatch(m, *i) >> "Bind" >> s >> e2))
@@ -81,6 +81,15 @@ ATerm expandRec(ATerm e, ATermList bnds)
         as.set(s, substitute(subs, e2));
     }
 
+    /* Copy the non-recursive bindings.  !!! inefficient */
+    for (ATermIterator i(nrbnds); i; ++i) {
+        string s;
+        Expr e2;
+        if (!(atMatch(m, *i) >> "Bind" >> s >> e2))
+            abort(); /* can't happen */
+        as.set(s, e2);
+    }
+
     return makeAttrs(as);
 }
 
@@ -175,14 +184,9 @@ Expr evalExpr2(EvalState & state, Expr e)
     }
 
     /* Mutually recursive sets. */
-    ATermList bnds;
-    if (atMatch(m, e) >> "Rec" >> bnds)
-        return expandRec(e, bnds);
-
-    /* Let expressions `let {..., body = ...}' are just desugared
-       into `(rec {..., body = ...}).body'. */
-    if (atMatch(m, e) >> "LetRec" >> bnds)
-        return evalExpr(state, ATmake("Select(Rec(<term>), \"body\")", bnds));
+    ATermList rbnds, nrbnds;
+    if (atMatch(m, e) >> "Rec" >> rbnds >> nrbnds)
+        return expandRec(e, rbnds, nrbnds);
 
     /* Conditionals. */
     if (atMatch(m, e) >> "If" >> e1 >> e2 >> e3) {