diff options
author | Eelco Dolstra <e.dolstra@tudelft.nl> | 2004-02-02 21:39:33 +0000 |
---|---|---|
committer | Eelco Dolstra <e.dolstra@tudelft.nl> | 2004-02-02 21:39:33 +0000 |
commit | 1c9c0a5a46822be60c999f0196567c9e17cf5fa3 (patch) | |
tree | 6783413d7fd353fdd7562f47a2dc0aac132cd04d /src/libexpr/eval.cc | |
parent | d9f30fe7c74ae8518a575c0d15ee00aa46a2229a (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.cc | 30 |
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) { |