Author: eelco
Date: Wed Jul 13 12:19:57 2011
New Revision: 27756
URL: https://svn.nixos.org/websvn/nix/?rev=27756&sc=1
Log:
* Allow a default value in attribute selection by writing
x.y.z or default
(as originally proposed in
https://mail.cs.uu.nl/pipermail/nix-dev/2009-September/002989.html).
For instance, an expression like
stdenv.lib.attrByPath ["features" "ckSched"] false args
can now be written as
args.features.ckSched or false
Added:
nix/trunk/tests/lang/eval-okay-attrs5.exp
nix/trunk/tests/lang/eval-okay-attrs5.nix
Modified:
nix/trunk/doc/manual/release-notes.xml
nix/trunk/misc/emacs/nix-mode.el
nix/trunk/src/libexpr/eval.cc
nix/trunk/src/libexpr/lexer.l
nix/trunk/src/libexpr/nixexpr.cc
nix/trunk/src/libexpr/nixexpr.hh
nix/trunk/src/libexpr/parser.y
Modified: nix/trunk/doc/manual/release-notes.xml
==============================================================================
--- nix/trunk/doc/manual/release-notes.xml Wed Jul 13 12:18:25 2011
(r27755)
+++ nix/trunk/doc/manual/release-notes.xml Wed Jul 13 12:19:57 2011
(r27756)
@@ -32,6 +32,10 @@
<literal>--max-silent-time</literal> is ineffective.</para>
</listitem>
+ <listitem>
+ <para>TODO: “or” keyword.</para>
+ </listitem>
+
</itemizedlist>
</section>
Modified: nix/trunk/misc/emacs/nix-mode.el
==============================================================================
--- nix/trunk/misc/emacs/nix-mode.el Wed Jul 13 12:18:25 2011 (r27755)
+++ nix/trunk/misc/emacs/nix-mode.el Wed Jul 13 12:19:57 2011 (r27756)
@@ -67,7 +67,7 @@
(defvar nix-keywords
'("\\<if\\>" "\\<then\\>" "\\<else\\>" "\\<assert\\>" "\\<with\\>"
- "\\<let\\>" "\\<in\\>" "\\<rec\\>" "\\<inherit\\>"
+ "\\<let\\>" "\\<in\\>" "\\<rec\\>" "\\<inherit\\>" "\\<or\\>"
("\\<true\\>" . font-lock-builtin-face)
("\\<false\\>" . font-lock-builtin-face)
("\\<null\\>" . font-lock-builtin-face)
Modified: nix/trunk/src/libexpr/eval.cc
==============================================================================
--- nix/trunk/src/libexpr/eval.cc Wed Jul 13 12:18:25 2011 (r27755)
+++ nix/trunk/src/libexpr/eval.cc Wed Jul 13 12:19:57 2011 (r27756)
@@ -632,7 +632,6 @@
unsigned long nrLookups = 0;
-unsigned long nrLookupSize = 0;
void ExprSelect::eval(EvalState & state, Env & env, Value & v)
{
@@ -646,11 +645,20 @@
foreach (AttrPath::const_iterator, i, attrPath) {
nrLookups++;
- state.forceAttrs(*vAttrs);
- nrLookupSize += vAttrs->attrs->size();
Bindings::iterator j;
- if ((j = vAttrs->attrs->find(*i)) == vAttrs->attrs->end())
- throwEvalError("attribute `%1%' missing",
showAttrPath(attrPath));
+ if (def) {
+ state.forceValue(*vAttrs);
+ if (vAttrs->type != tAttrs ||
+ (j = vAttrs->attrs->find(*i)) == vAttrs->attrs->end())
+ {
+ state.eval(env, def, v);
+ return;
+ }
+ } else {
+ state.forceAttrs(*vAttrs);
+ if ((j = vAttrs->attrs->find(*i)) == vAttrs->attrs->end())
+ throwEvalError("attribute `%1%' missing",
showAttrPath(attrPath));
+ }
vAttrs = j->value;
pos = j->pos;
}
@@ -1270,7 +1278,6 @@
printMsg(v, format(" number of thunks: %1%") % nrThunks);
printMsg(v, format(" number of thunks avoided: %1%") % nrAvoided);
printMsg(v, format(" number of attr lookups: %1%") % nrLookups);
- printMsg(v, format(" attr lookup size: %1%") % nrLookupSize);
}
Modified: nix/trunk/src/libexpr/lexer.l
==============================================================================
--- nix/trunk/src/libexpr/lexer.l Wed Jul 13 12:18:25 2011 (r27755)
+++ nix/trunk/src/libexpr/lexer.l Wed Jul 13 12:19:57 2011 (r27756)
@@ -96,6 +96,7 @@
in { return IN; }
rec { return REC; }
inherit { return INHERIT; }
+or { return OR_KW; }
\.\.\. { return ELLIPSIS; }
\=\= { return EQ; }
Modified: nix/trunk/src/libexpr/nixexpr.cc
==============================================================================
--- nix/trunk/src/libexpr/nixexpr.cc Wed Jul 13 12:18:25 2011 (r27755)
+++ nix/trunk/src/libexpr/nixexpr.cc Wed Jul 13 12:19:57 2011 (r27756)
@@ -44,6 +44,7 @@
void ExprSelect::show(std::ostream & str)
{
str << "(" << *e << ")." << showAttrPath(attrPath);
+ if (def) str << " or " << *def;
}
void ExprOpHasAttr::show(std::ostream & str)
@@ -211,6 +212,7 @@
void ExprSelect::bindVars(const StaticEnv & env)
{
e->bindVars(env);
+ if (def) def->bindVars(env);
}
void ExprOpHasAttr::bindVars(const StaticEnv & env)
Modified: nix/trunk/src/libexpr/nixexpr.hh
==============================================================================
--- nix/trunk/src/libexpr/nixexpr.hh Wed Jul 13 12:18:25 2011 (r27755)
+++ nix/trunk/src/libexpr/nixexpr.hh Wed Jul 13 12:19:57 2011 (r27756)
@@ -121,10 +121,10 @@
struct ExprSelect : Expr
{
- Expr * e;
+ Expr * e, * def;
AttrPath attrPath;
- ExprSelect(Expr * e, const AttrPath & attrPath) : e(e), attrPath(attrPath)
{ };
- ExprSelect(Expr * e, const Symbol & name) : e(e) {
attrPath.push_back(name); };
+ ExprSelect(Expr * e, const AttrPath & attrPath, Expr * def) : e(e),
def(def), attrPath(attrPath) { };
+ ExprSelect(Expr * e, const Symbol & name) : e(e), def(0) {
attrPath.push_back(name); };
COMMON_METHODS
};
Modified: nix/trunk/src/libexpr/parser.y
==============================================================================
--- nix/trunk/src/libexpr/parser.y Wed Jul 13 12:18:25 2011 (r27755)
+++ nix/trunk/src/libexpr/parser.y Wed Jul 13 12:19:57 2011 (r27756)
@@ -237,7 +237,7 @@
char * id; // !!! -> Symbol
char * path;
char * uri;
- std::vector<nix::Symbol> * ids;
+ std::vector<nix::Symbol> * attrNames;
std::vector<nix::Expr *> * string_parts;
}
@@ -247,14 +247,15 @@
%type <attrs> binds
%type <formals> formals
%type <formal> formal
-%type <ids> ids attrpath
+%type <attrNames> attrs attrpath
%type <string_parts> string_parts ind_string_parts
+%type <id> attr
%token <id> ID ATTRPATH
%token <e> STR IND_STR
%token <n> INT
%token <path> PATH
%token <uri> URI
-%token IF THEN ELSE ASSERT WITH LET IN REC INHERIT EQ NEQ AND OR IMPL
+%token IF THEN ELSE ASSERT WITH LET IN REC INHERIT EQ NEQ AND OR IMPL OR_KW
%token DOLLAR_CURLY /* == ${ */
%token IND_STRING_OPEN IND_STRING_CLOSE
%token ELLIPSIS
@@ -326,7 +327,13 @@
expr_select
: expr_simple '.' attrpath
- { $$ = new ExprSelect($1, *$3); }
+ { $$ = new ExprSelect($1, *$3, 0); }
+ | expr_simple '.' attrpath OR_KW expr_select
+ { $$ = new ExprSelect($1, *$3, $5); }
+ | /* Backwards compatibility: because Nixpkgs has a rarely used
+ function named ‘or’, allow stuff like ‘map or [...]’. */
+ expr_simple OR_KW
+ { $$ = new ExprApp($1, new ExprVar(data->symbols.create("or"))); }
| expr_simple { $$ = $1; }
;
@@ -370,7 +377,7 @@
binds
: binds attrpath '=' expr ';' { $$ = $1; addAttr($$, *$2, $4, makeCurPos(@2,
data)); }
- | binds INHERIT ids ';'
+ | binds INHERIT attrs ';'
{ $$ = $1;
foreach (AttrPath::iterator, i, *$3) {
if ($$->attrs.find(*i) != $$->attrs.end())
@@ -379,26 +386,31 @@
$$->attrs[*i] = ExprAttrs::AttrDef(*i, pos);
}
}
- | binds INHERIT '(' expr ')' ids ';'
+ | binds INHERIT '(' expr ')' attrs ';'
{ $$ = $1;
/* !!! Should ensure sharing of the expression in $4. */
foreach (vector<Symbol>::iterator, i, *$6) {
if ($$->attrs.find(*i) != $$->attrs.end())
dupAttr(*i, makeCurPos(@6, data), $$->attrs[*i].pos);
$$->attrs[*i] = ExprAttrs::AttrDef(new ExprSelect($4, *i),
makeCurPos(@6, data));
- }}
-
+ }
+ }
| { $$ = new ExprAttrs; }
;
-ids
- : ids ID { $$ = $1; $1->push_back(data->symbols.create($2)); /* !!!
dangerous */ }
+attrs
+ : attrs attr { $$ = $1; $1->push_back(data->symbols.create($2)); /* !!!
dangerous */ }
| { $$ = new vector<Symbol>; }
;
attrpath
- : attrpath '.' ID { $$ = $1; $1->push_back(data->symbols.create($3)); }
- | ID { $$ = new vector<Symbol>; $$->push_back(data->symbols.create($1)); }
+ : attrpath '.' attr { $$ = $1; $1->push_back(data->symbols.create($3)); }
+ | attr { $$ = new vector<Symbol>; $$->push_back(data->symbols.create($1)); }
+ ;
+
+attr
+ : ID { $$ = $1; }
+ | OR_KW { $$ = "or"; }
;
expr_list
Added: nix/trunk/tests/lang/eval-okay-attrs5.exp
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ nix/trunk/tests/lang/eval-okay-attrs5.exp Wed Jul 13 12:19:57 2011
(r27756)
@@ -0,0 +1 @@
+[ 123 "foo" 456 456 "foo" "xyzzy" "xyzzy" true ]
Added: nix/trunk/tests/lang/eval-okay-attrs5.nix
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ nix/trunk/tests/lang/eval-okay-attrs5.nix Wed Jul 13 12:19:57 2011
(r27756)
@@ -0,0 +1,21 @@
+with import ./lib.nix;
+
+let
+
+ as = { x.y.z = 123; a.b.c = 456; };
+
+ bs = { foo.bar = "foo"; };
+
+ or = x: y: x || y;
+
+in
+ [ as.x.y.z
+ as.foo or "foo"
+ as.x.y.bla or as.a.b.c
+ as.a.b.c or as.x.y.z
+ as.x.y.bla or bs.foo.bar or "xyzzy"
+ as.x.y.bla or bs.bar.foo or "xyzzy"
+ 123.bla or null.foo or "xyzzy"
+ # Backwards compatibility test.
+ (fold or [] [true false false])
+ ]
_______________________________________________
nix-commits mailing list
[email protected]
http://mail.cs.uu.nl/mailman/listinfo/nix-commits