* Added an experimental feature suggested by Andres: ellipses ("...")

in attribute set pattern matches.  This allows defining a function
  that takes *at least* the listed attributes, while ignoring
  additional attributes.  For instance,

    {stdenv, fetchurl, fuse, ...}:
    
    stdenv.mkDerivation {
      ...
    };
    
  defines a function that requires an attribute set that contains the 
  specified attributes but ignores others.  The main advantage is that
  we can then write in all-packages.nix

    aefs = import ../bla/aefs pkgs;

  instead of

    aefs = import ../bla/aefs {
      inherit stdenv fetchurl fuse;
    };

  This saves a lot of typing (not to mention not having to update
  all-packages.nix with purely mechanical changes).  It saves as much
  typing as the "args: with args;" style, but has the advantage that
  the function arguments are properly declared (not implicit in what
  the body of the "with" uses).
This commit is contained in:
Eelco Dolstra 2008-08-14 14:00:44 +00:00
parent db4f4a8425
commit 9279174dde
14 changed files with 57 additions and 23 deletions

View file

@ -208,16 +208,22 @@ static void freeAndUnprotect(void * p)
%union {
ATerm t;
ATermList ts;
struct {
ATermList formals;
bool ellipsis;
} formals;
}
%type <t> start expr expr_function expr_if expr_op
%type <t> expr_app expr_select expr_simple bind inheritsrc formal
%type <t> pattern pattern2
%type <ts> binds ids expr_list formals string_parts ind_string_parts
%type <ts> binds ids expr_list string_parts ind_string_parts
%type <formals> formals
%token <t> ID INT STR IND_STR PATH URI
%token IF THEN ELSE ASSERT WITH LET IN REC INHERIT EQ NEQ AND OR IMPL
%token DOLLAR_CURLY /* == ${ */
%token IND_STRING_OPEN IND_STRING_CLOSE
%token ELLIPSIS
%nonassoc IMPL
%left OR
@ -326,7 +332,7 @@ pattern
pattern2
: ID { $$ = makeVarPat($1); }
| '{' formals '}' { $$ = makeAttrsPat($2); }
| '{' formals '}' { $$ = makeAttrsPat($2.formals, $2.ellipsis ? eTrue : eFalse); }
;
binds
@ -357,9 +363,14 @@ expr_list
;
formals
: formal ',' formals { $$ = ATinsert($3, $1); } /* idem - right recursive */
| formal { $$ = ATinsert(ATempty, $1); }
| { $$ = ATempty; }
: formal ',' formals /* idem - right recursive */
{ $$.formals = ATinsert($3.formals, $1); $$.ellipsis = $3.ellipsis; }
| formal
{ $$.formals = ATinsert(ATempty, $1); $$.ellipsis = false; }
|
{ $$.formals = ATempty; $$.ellipsis = false; }
| ELLIPSIS
{ $$.formals = ATempty; $$.ellipsis = true; }
;
formal
@ -401,13 +412,14 @@ static void checkPatternVars(ATerm pos, ATermMap & map, Pattern pat)
ATerm name;
ATermList formals;
Pattern pat1, pat2;
ATermBool ellipsis;
if (matchVarPat(pat, name)) {
if (map.get(name))
throw EvalError(format("duplicate formal function argument `%1%' at %2%")
% aterm2String(name) % showPos(pos));
map.set(name, name);
}
else if (matchAttrsPat(pat, formals)) {
else if (matchAttrsPat(pat, formals, ellipsis)) {
for (ATermIterator i(formals); i; ++i) {
ATerm d1;
if (!matchFormal(*i, name, d1)) abort();