about summary refs log tree commit diff
path: root/src/libexpr/parser.y
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/parser.y
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/parser.y')
-rw-r--r--src/libexpr/parser.y20
1 files changed, 15 insertions, 5 deletions
diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y
index dc03117bb1..d97106fcae 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