aboutsummaryrefslogtreecommitdiff
path: root/src/libexpr/eval.cc
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2004-02-02 21:39:33 +0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2004-02-02 21:39:33 +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 77cab55d0..820e934a6 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) {