From 1c9c0a5a46822be60c999f0196567c9e17cf5fa3 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 2 Feb 2004 21:39:33 +0000 Subject: * 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}'. --- src/libexpr/eval.cc | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) (limited to 'src/libexpr/eval.cc') diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 77cab55d034c..820e934a635a 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(), \"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) { -- cgit 1.4.1