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/parser.y | |
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/parser.y')
-rw-r--r-- | src/libexpr/parser.y | 20 |
1 files changed, 15 insertions, 5 deletions
diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y index dc03117bb..d97106fca 100644 --- a/src/libexpr/parser.y +++ b/src/libexpr/parser.y @@ -18,6 +18,7 @@ void setParseResult(void * data, ATerm t); void parseError(void * data, char * error, int line, int column); ATerm absParsedPath(void * data, ATerm t); +ATerm fixAttrs(int recursive, ATermList as); void yyerror(YYLTYPE * loc, yyscan_t scanner, void * data, char * s) { @@ -33,9 +34,9 @@ void yyerror(YYLTYPE * loc, yyscan_t scanner, void * data, char * s) %type <t> start expr expr_function expr_assert expr_op %type <t> expr_app expr_select expr_simple bind formal -%type <ts> binds expr_list formals +%type <ts> binds ids expr_list formals %token <t> ID INT STR PATH URI -%token IF THEN ELSE ASSERT LET REC EQ NEQ AND OR IMPL +%token IF THEN ELSE ASSERT LET REC INHERIT EQ NEQ AND OR IMPL %nonassoc IMPL %left OR @@ -90,9 +91,14 @@ expr_simple | PATH { $$ = ATmake("Path(<term>)", absParsedPath(data, $1)); } | URI { $$ = ATmake("Uri(<term>)", $1); } | '(' expr ')' { $$ = $2; } - | LET '{' binds '}' { $$ = ATmake("LetRec(<term>)", $3); } - | REC '{' binds '}' { $$ = ATmake("Rec(<term>)", $3); } - | '{' binds '}' { $$ = ATmake("Attrs(<term>)", $2); } + /* Let expressions `let {..., body = ...}' are just desugared + into `(rec {..., body = ...}).body'. */ + | LET '{' binds '}' + { $$ = ATmake("Select(<term>, \"body\")", fixAttrs(1, $3)); } + | REC '{' binds '}' + { $$ = fixAttrs(1, $3); } + | '{' binds '}' + { $$ = fixAttrs(0, $2); } | '[' expr_list ']' { $$ = ATmake("List(<term>)", $2); } | IF expr THEN expr ELSE expr { $$ = ATmake("If(<term>, <term>, <term>)", $2, $4, $6); } @@ -106,8 +112,12 @@ binds bind : ID '=' expr ';' { $$ = ATmake("Bind(<term>, <term>)", $1, $3); } + | INHERIT ids ';' + { $$ = ATmake("Inherit(<term>)", $2); } ; +ids: ids ID { $$ = ATinsert($1, $2); } | { $$ = ATempty; }; + expr_list : expr_select expr_list { $$ = ATinsert($2, $1); } /* yes, this is right-recursive, but it doesn't matter since |