Rename "attribute sets" to "sets"

We don't have any other kind of sets so calling them attribute sets is
unnecessarily verbose.
This commit is contained in:
Eelco Dolstra 2013-10-24 16:41:04 +02:00
parent 9e4bb20455
commit 5bc41d78ff
13 changed files with 152 additions and 160 deletions

View File

@ -12,9 +12,9 @@ such as <function>derivation</function>, are always in scope of every
Nix expression; you can just access them right away. But to prevent Nix expression; you can just access them right away. But to prevent
polluting the namespace too much, most built-ins are not in scope. polluting the namespace too much, most built-ins are not in scope.
Instead, you can access them through the <varname>builtins</varname> Instead, you can access them through the <varname>builtins</varname>
built-in value, which is an attribute set that contains all built-in built-in value, which is a set that contains all built-in functions
functions and values. For instance, <function>derivation</function> and values. For instance, <function>derivation</function> is also
is also available as <function>builtins.derivation</function>.</para> available as <function>builtins.derivation</function>.</para>
<variablelist> <variablelist>
@ -39,14 +39,14 @@ is also available as <function>builtins.derivation</function>.</para>
<varlistentry><term><function>builtins.attrNames</function> <varlistentry><term><function>builtins.attrNames</function>
<replaceable>attrs</replaceable></term> <replaceable>set</replaceable></term>
<listitem><para>Return the names of the attributes in the <listitem><para>Return the names of the attributes in the set
attribute set <replaceable>attrs</replaceable> in a sorted list. <replaceable>set</replaceable> in a sorted list. For instance,
For instance, <literal>builtins.attrNames { y = 1; x = "foo"; <literal>builtins.attrNames { y = 1; x = "foo"; }</literal>
}</literal> evaluates to <literal>[ "x" "y" ]</literal>. There is evaluates to <literal>[ "x" "y" ]</literal>. There is no built-in
no built-in function <function>attrValues</function>, but you can function <function>attrValues</function>, but you can easily
easily define it yourself: define it yourself:
<programlisting> <programlisting>
attrValues = attrs: map (name: builtins.getAttr name attrs) (builtins.attrNames attrs);</programlisting> attrValues = attrs: map (name: builtins.getAttr name attrs) (builtins.attrNames attrs);</programlisting>
@ -68,8 +68,8 @@ attrValues = attrs: map (name: builtins.getAttr name attrs) (builtins.attrNames
<varlistentry><term><varname>builtins</varname></term> <varlistentry><term><varname>builtins</varname></term>
<listitem><para>The attribute set <varname>builtins</varname> <listitem><para>The set <varname>builtins</varname> contains all
contains all the built-in functions and values. You can use the built-in functions and values. You can use
<varname>builtins</varname> to test for the availability of <varname>builtins</varname> to test for the availability of
features in the Nix installation, e.g., features in the Nix installation, e.g.,
@ -258,11 +258,11 @@ stdenv.mkDerivation {
<varlistentry><term><function>builtins.getAttr</function> <varlistentry><term><function>builtins.getAttr</function>
<replaceable>s</replaceable> <replaceable>attrs</replaceable></term> <replaceable>s</replaceable> <replaceable>set</replaceable></term>
<listitem><para><function>getAttr</function> returns the attribute <listitem><para><function>getAttr</function> returns the attribute
named <replaceable>s</replaceable> from the attribute set named <replaceable>s</replaceable> from
<replaceable>attrs</replaceable>. Evaluation aborts if the <replaceable>set</replaceable>. Evaluation aborts if the
attribute doesnt exist. This is a dynamic version of the attribute doesnt exist. This is a dynamic version of the
<literal>.</literal> operator, since <replaceable>s</replaceable> <literal>.</literal> operator, since <replaceable>s</replaceable>
is an expression rather than an identifier.</para></listitem> is an expression rather than an identifier.</para></listitem>
@ -289,15 +289,15 @@ stdenv.mkDerivation {
<varlistentry><term><function>builtins.hasAttr</function> <varlistentry><term><function>builtins.hasAttr</function>
<replaceable>s</replaceable> <replaceable>attrs</replaceable></term> <replaceable>s</replaceable> <replaceable>set</replaceable></term>
<listitem><para><function>hasAttr</function> returns <listitem><para><function>hasAttr</function> returns
<literal>true</literal> if the attribute set <literal>true</literal> if <replaceable>set</replaceable> has an
<replaceable>attrs</replaceable> has an attribute named attribute named <replaceable>s</replaceable>, and
<replaceable>s</replaceable>, and <literal>false</literal> <literal>false</literal> otherwise. This is a dynamic version of
otherwise. This is a dynamic version of the <literal>?</literal> the <literal>?</literal> operator, since
operator, since <replaceable>s</replaceable> is an expression <replaceable>s</replaceable> is an expression rather than an
rather than an identifier.</para></listitem> identifier.</para></listitem>
</varlistentry> </varlistentry>
@ -331,12 +331,12 @@ stdenv.mkDerivation {
<listitem><para>Load, parse and return the Nix expression in the <listitem><para>Load, parse and return the Nix expression in the
file <replaceable>path</replaceable>. If <replaceable>path file <replaceable>path</replaceable>. If <replaceable>path
</replaceable> is a directory, the file <filename>default.nix </replaceable> is a directory, the file <filename>default.nix
</filename> in that directory is loaded. Evaluation aborts if </filename> in that directory is loaded. Evaluation aborts if the
the file doesnt exist or contains an incorrect Nix file doesnt exist or contains an incorrect Nix expression.
expression. <function>import</function> implements Nixs module <function>import</function> implements Nixs module system: you
system: you can put any Nix expression (such as an attribute set can put any Nix expression (such as a set or a function) in a
or a function) in a separate file, and use it from Nix expressions separate file, and use it from Nix expressions in other
in other files.</para> files.</para>
<para>A Nix expression loaded by <function>import</function> must <para>A Nix expression loaded by <function>import</function> must
not contain any <emphasis>free variables</emphasis> (identifiers not contain any <emphasis>free variables</emphasis> (identifiers
@ -383,9 +383,9 @@ x: x + 456</programlisting>
<varlistentry><term><function>builtins.intersectAttrs</function> <varlistentry><term><function>builtins.intersectAttrs</function>
<replaceable>e1</replaceable> <replaceable>e2</replaceable></term> <replaceable>e1</replaceable> <replaceable>e2</replaceable></term>
<listitem><para>Return an attribute set consisting of the <listitem><para>Return a set consisting of the attributes in the
attributes in the set <replaceable>e2</replaceable> that also set <replaceable>e2</replaceable> that also exist in the set
exist in the set <replaceable>e1</replaceable>.</para></listitem> <replaceable>e1</replaceable>.</para></listitem>
</varlistentry> </varlistentry>
@ -394,7 +394,7 @@ x: x + 456</programlisting>
<replaceable>e</replaceable></term> <replaceable>e</replaceable></term>
<listitem><para>Return <literal>true</literal> if <listitem><para>Return <literal>true</literal> if
<replaceable>e</replaceable> evaluates to an attribute set, and <replaceable>e</replaceable> evaluates to a set, and
<literal>false</literal> otherwise.</para></listitem> <literal>false</literal> otherwise.</para></listitem>
</varlistentry> </varlistentry>
@ -490,9 +490,9 @@ x: x + 456</programlisting>
<varlistentry><term><function>builtins.listToAttrs</function> <varlistentry><term><function>builtins.listToAttrs</function>
<replaceable>e</replaceable></term> <replaceable>e</replaceable></term>
<listitem><para>Construct an attribute set from a list specifying <listitem><para>Construct a set from a list specifying the names
the names and values of each attribute. Each element of the list and values of each attribute. Each element of the list should be
should be an attribute set consisting of a string-valued attribute a set consisting of a string-valued attribute
<varname>name</varname> specifying the name of the attribute, and <varname>name</varname> specifying the name of the attribute, and
an attribute <varname>value</varname> specifying its value. an attribute <varname>value</varname> specifying its value.
Example: Example:
@ -547,7 +547,7 @@ map (x: "foo" + x) [ "bar" "bla" "abc" ]</programlisting>
a package name and version. The package name is everything up to a package name and version. The package name is everything up to
but not including the first dash followed by a digit, and the but not including the first dash followed by a digit, and the
version is everything following that dash. The result is returned version is everything following that dash. The result is returned
in an attribute set <literal>{ name, version }</literal>. Thus, in a set <literal>{ name, version }</literal>. Thus,
<literal>builtins.parseDrvName "nix-0.12pre12876"</literal> <literal>builtins.parseDrvName "nix-0.12pre12876"</literal>
returns <literal>{ name = "nix"; version = "0.12pre12876"; returns <literal>{ name = "nix"; version = "0.12pre12876";
}</literal>.</para></listitem> }</literal>.</para></listitem>
@ -598,12 +598,12 @@ in config.someSetting</programlisting>
<varlistentry><term><function>removeAttrs</function> <varlistentry><term><function>removeAttrs</function>
<replaceable>attrs</replaceable> <replaceable>list</replaceable></term> <replaceable>set</replaceable> <replaceable>list</replaceable></term>
<listitem><para>Remove the attributes listed in <listitem><para>Remove the attributes listed in
<replaceable>list</replaceable> from the attribute set <replaceable>list</replaceable> from
<replaceable>attrs</replaceable>. The attributes dont have to <replaceable>set</replaceable>. The attributes dont have to
exist in <replaceable>attrs</replaceable>. For instance, exist in <replaceable>set</replaceable>. For instance,
<screen> <screen>
removeAttrs { x = 1; y = 2; z = 3; } [ "a" "x" "z" ]</screen> removeAttrs { x = 1; y = 2; z = 3; } [ "a" "x" "z" ]</screen>
@ -792,7 +792,7 @@ in foo</programlisting>
servlet container</link>. A servlet container contains a number servlet container</link>. A servlet container contains a number
of servlets (<filename>*.war</filename> files) each exported under of servlets (<filename>*.war</filename> files) each exported under
a specific URI prefix. So the servlet configuration is a list of a specific URI prefix. So the servlet configuration is a list of
attribute sets containing the <varname>path</varname> and sets containing the <varname>path</varname> and
<varname>war</varname> of the servlet (<xref <varname>war</varname> of the servlet (<xref
linkend='ex-toxml-co-servlets' />). This kind of information is linkend='ex-toxml-co-servlets' />). This kind of information is
difficult to communicate with the normal method of passing difficult to communicate with the normal method of passing

View File

@ -153,11 +153,10 @@ also <xref linkend="sec-common-options" />.</phrase></para>
default.</para> default.</para>
<para>The Nix expressions in this directory are combined into a <para>The Nix expressions in this directory are combined into a
single attribute set, with each file as an attribute that has the single set, with each file as an attribute that has the name of
name of the file. Thus, if <filename>~/.nix-defexpr</filename> the file. Thus, if <filename>~/.nix-defexpr</filename> contains
contains two files, <filename>foo</filename> and two files, <filename>foo</filename> and <filename>bar</filename>,
<filename>bar</filename>, then the default Nix expression will then the default Nix expression will essentially be
essentially be
<programlisting> <programlisting>
{ {
@ -405,7 +404,7 @@ $ nix-env -f ./foo.nix -i -E \
I.e., this evaluates to <literal>(f: (f {system = I.e., this evaluates to <literal>(f: (f {system =
"i686-linux";}).subversionWithJava) (import ./foo.nix)</literal>, thus "i686-linux";}).subversionWithJava) (import ./foo.nix)</literal>, thus
selecting the <literal>subversionWithJava</literal> attribute from the selecting the <literal>subversionWithJava</literal> attribute from the
attribute set returned by calling the function defined in set returned by calling the function defined in
<filename>./foo.nix</filename>.</para> <filename>./foo.nix</filename>.</para>
<para>A dry-run tells you which paths will be downloaded or built from <para>A dry-run tells you which paths will be downloaded or built from

View File

@ -118,10 +118,10 @@ the single Nix expression in that directory
<varname>stdenv.mkDerivation</varname>. <varname>stdenv.mkDerivation</varname>.
<varname>mkDerivation</varname> is a function provided by <varname>mkDerivation</varname> is a function provided by
<varname>stdenv</varname> that builds a package from a set of <varname>stdenv</varname> that builds a package from a set of
<emphasis>attributes</emphasis>. An attribute set is just a list <emphasis>attributes</emphasis>. A set is just a list of
of key/value pairs where each value is an arbitrary Nix key/value pairs where each key is a string and each value is an
expression. They take the general form arbitrary Nix expression. They take the general form <literal>{
<literal>{ <replaceable>name1</replaceable> = <replaceable>name1</replaceable> =
<replaceable>expr1</replaceable>; <replaceable>...</replaceable> <replaceable>expr1</replaceable>; <replaceable>...</replaceable>
<replaceable>nameN</replaceable> = <replaceable>nameN</replaceable> =
<replaceable>exprN</replaceable>; }</literal>.</para> <replaceable>exprN</replaceable>; }</literal>.</para>
@ -384,9 +384,9 @@ some fragments of
<para>This is where the actual composition takes place. Here we <para>This is where the actual composition takes place. Here we
<emphasis>call</emphasis> the function imported from <emphasis>call</emphasis> the function imported from
<filename>../applications/misc/hello/ex-1</filename> with an <filename>../applications/misc/hello/ex-1</filename> with a set
attribute set containing the things that the function expects, containing the things that the function expects, namely
namely <varname>fetchurl</varname>, <varname>stdenv</varname>, and <varname>fetchurl</varname>, <varname>stdenv</varname>, and
<varname>perl</varname>. We use inherit again to use the <varname>perl</varname>. We use inherit again to use the
attributes defined in the surrounding scope (we could also have attributes defined in the surrounding scope (we could also have
written <literal>fetchurl = fetchurl;</literal>, etc.).</para> written <literal>fetchurl = fetchurl;</literal>, etc.).</para>
@ -805,20 +805,21 @@ to be enclosed in parentheses. If they had been omitted, e.g.,
[ 123 ./foo.nix "abc" f { x = y; } ]</programlisting> [ 123 ./foo.nix "abc" f { x = y; } ]</programlisting>
the result would be a list of five elements, the fourth one being a the result would be a list of five elements, the fourth one being a
function and the fifth being an attribute set.</para> function and the fifth being a set.</para>
</simplesect> </simplesect>
<simplesect><title>Attribute sets</title> <simplesect><title>Sets</title>
<para>Attribute sets are really the core of the language, since <para>Sets are really the core of the language, since ultimately the
ultimately it's all about creating derivations, which are really just Nix language is all about creating derivations, which are really just
sets of attributes to be passed to build scripts.</para> sets of attributes to be passed to build scripts.</para>
<para>Attribute sets are just a list of name/value pairs enclosed in <para>Sets are just a list of name/value pairs (called
curly brackets, where each value is an arbitrary expression terminated <emphasis>attributes</emphasis>) enclosed in curly brackets, where
by a semicolon. For example: each value is an arbitrary expression terminated by a semicolon. For
example:
<programlisting> <programlisting>
{ x = 123; { x = 123;
@ -826,12 +827,12 @@ by a semicolon. For example:
y = f { bla = 456; }; y = f { bla = 456; };
}</programlisting> }</programlisting>
This defines an attribute set with attributes named This defines a set with attributes named <varname>x</varname>,
<varname>x</varname>, <varname>text</varname>, <varname>y</varname>. <varname>text</varname>, <varname>y</varname>. The order of the
The order of the attributes is irrelevant. An attribute name may only attributes is irrelevant. An attribute name may only occur
occur once.</para> once.</para>
<para>Attributes can be selected from an attribute set using the <para>Attributes can be selected from a set using the
<literal>.</literal> operator. For instance, <literal>.</literal> operator. For instance,
<programlisting> <programlisting>
@ -864,10 +865,10 @@ This will evaluate to <literal>123</literal>.</para>
<section><title>Language constructs</title> <section><title>Language constructs</title>
<simplesect><title>Recursive attribute sets</title> <simplesect><title>Recursive sets</title>
<para>Recursive attribute sets are just normal attribute sets, but the <para>Recursive sets are just normal sets, but the attributes can
attributes can refer to each other. For example, refer to each other. For example,
<programlisting> <programlisting>
rec { rec {
@ -880,11 +881,11 @@ evaluates to <literal>123</literal>. Note that without
<literal>rec</literal> the binding <literal>x = y;</literal> would <literal>rec</literal> the binding <literal>x = y;</literal> would
refer to the variable <varname>y</varname> in the surrounding scope, refer to the variable <varname>y</varname> in the surrounding scope,
if one exists, and would be invalid if no such variable exists. That if one exists, and would be invalid if no such variable exists. That
is, in a normal (non-recursive) attribute set, attributes are not is, in a normal (non-recursive) set, attributes are not added to the
added to the lexical scope; in a recursive set, they are.</para> lexical scope; in a recursive set, they are.</para>
<para>Recursive attribute sets of course introduce the danger of <para>Recursive sets of course introduce the danger of infinite
infinite recursion. For example, recursion. For example,
<programlisting> <programlisting>
rec { rec {
@ -918,16 +919,16 @@ evaluates to <literal>"foobar"</literal>.
<literal>let { <replaceable>attrs</replaceable> }</literal>, which is <literal>let { <replaceable>attrs</replaceable> }</literal>, which is
translated to <literal>rec { <replaceable>attrs</replaceable> translated to <literal>rec { <replaceable>attrs</replaceable>
}.body</literal>. That is, the body of the let-expression is the }.body</literal>. That is, the body of the let-expression is the
<literal>body</literal> attribute of the attribute set.</para></note> <literal>body</literal> attribute of the set.</para></note>
</simplesect> </simplesect>
<simplesect><title>Inheriting attributes</title> <simplesect><title>Inheriting attributes</title>
<para>When defining an attribute set it is often convenient to copy <para>When defining a set it is often convenient to copy variables
variables from the surrounding lexical scope (e.g., when you want to from the surrounding lexical scope (e.g., when you want to propagate
propagate attributes). This can be shortened using the attributes). This can be shortened using the
<literal>inherit</literal> keyword. For instance, <literal>inherit</literal> keyword. For instance,
<programlisting> <programlisting>
@ -936,10 +937,10 @@ let x = 123; in
y = 456; y = 456;
}</programlisting> }</programlisting>
evaluates to <literal>{ x = 123; y = 456; }</literal>. (Note that this evaluates to <literal>{ x = 123; y = 456; }</literal>. (Note that
works because <varname>x</varname> is added to the lexical scope by this works because <varname>x</varname> is added to the lexical scope
the <literal>let</literal> construct.) It is also possible to inherit by the <literal>let</literal> construct.) It is also possible to
attributes from another attribute set. For instance, in this fragment inherit attributes from another set. For instance, in this fragment
from <filename>all-packages.nix</filename>, from <filename>all-packages.nix</filename>,
<programlisting> <programlisting>
@ -958,13 +959,12 @@ from <filename>all-packages.nix</filename>,
libjpg = ...; libjpg = ...;
...</programlisting> ...</programlisting>
the attribute set used in the function call to the function defined in the set used in the function call to the function defined in
<filename>../tools/graphics/graphviz</filename> inherits a number of <filename>../tools/graphics/graphviz</filename> inherits a number of
variables from the surrounding scope (<varname>fetchurl</varname> variables from the surrounding scope (<varname>fetchurl</varname>
... <varname>yacc</varname>), but also inherits ... <varname>yacc</varname>), but also inherits
<varname>libXaw</varname> (the X Athena Widgets) from the <varname>libXaw</varname> (the X Athena Widgets) from the
<varname>xlibs</varname> (X11 client-side libraries) attribute <varname>xlibs</varname> (X11 client-side libraries) set.</para>
set.</para>
</simplesect> </simplesect>
@ -1003,11 +1003,11 @@ map (concat "foo") [ "bar" "bla" "abc" ]</programlisting>
"fooabc" ]</literal>.</para></listitem> "fooabc" ]</literal>.</para></listitem>
<listitem><para>An <emphasis>attribute set pattern</emphasis> of the <listitem><para>A <emphasis>set pattern</emphasis> of the form
form <literal>{ name1, name2, …, nameN }</literal> <literal>{ name1, name2, …, nameN }</literal> matches a set
matches an attribute set containing the listed attributes, and binds containing the listed attributes, and binds the values of those
the values of those attributes to variables in the function body. attributes to variables in the function body. For example, the
For example, the function function
<programlisting> <programlisting>
{ x, y, z }: z + y + x</programlisting> { x, y, z }: z + y + x</programlisting>
@ -1174,9 +1174,8 @@ used in the Nix expression for Subversion.</para>
<programlisting> <programlisting>
with <replaceable>e1</replaceable>; <replaceable>e2</replaceable></programlisting> with <replaceable>e1</replaceable>; <replaceable>e2</replaceable></programlisting>
introduces the attribute set <replaceable>e1</replaceable> into the introduces the set <replaceable>e1</replaceable> into the lexical
lexical scope of the expression <replaceable>e2</replaceable>. For scope of the expression <replaceable>e2</replaceable>. For instance,
instance,
<programlisting> <programlisting>
let as = { x = "foo"; y = "bar"; }; let as = { x = "foo"; y = "bar"; };
@ -1235,7 +1234,7 @@ weakest binding).</para>
</entry> </entry>
<entry>none</entry> <entry>none</entry>
<entry>Select attribute denoted by the attribute path <entry>Select attribute denoted by the attribute path
<replaceable>attrpath</replaceable> from attribute set <replaceable>attrpath</replaceable> from set
<replaceable>e</replaceable>. (An attribute path is a <replaceable>e</replaceable>. (An attribute path is a
dot-separated list of attribute names.) If the attribute dot-separated list of attribute names.) If the attribute
doesnt exist, return <replaceable>def</replaceable> if doesnt exist, return <replaceable>def</replaceable> if
@ -1251,8 +1250,8 @@ weakest binding).</para>
<entry><replaceable>e</replaceable> <literal>?</literal> <entry><replaceable>e</replaceable> <literal>?</literal>
<replaceable>attrpath</replaceable></entry> <replaceable>attrpath</replaceable></entry>
<entry>none</entry> <entry>none</entry>
<entry>Test whether attribute set <replaceable>e</replaceable> <entry>Test whether set <replaceable>e</replaceable> contains
contains the attribute denoted by <replaceable>attrpath</replaceable>; the attribute denoted by <replaceable>attrpath</replaceable>;
return <literal>true</literal> or return <literal>true</literal> or
<literal>false</literal>.</entry> <literal>false</literal>.</entry>
</row> </row>
@ -1275,10 +1274,11 @@ weakest binding).</para>
<entry><replaceable>e1</replaceable> <literal>//</literal> <entry><replaceable>e1</replaceable> <literal>//</literal>
<replaceable>e2</replaceable></entry> <replaceable>e2</replaceable></entry>
<entry>right</entry> <entry>right</entry>
<entry>Return an attribute set consisting of the attributes in <entry>Return a set consisting of the attributes in
<replaceable>e1</replaceable> and <replaceable>e1</replaceable> and
<replaceable>e2</replaceable> (with the latter taking <replaceable>e2</replaceable> (with the latter taking
precedence over the former in case of equally named attributes).</entry> precedence over the former in case of equally named
attributes).</entry>
</row> </row>
<row> <row>
<entry><replaceable>e1</replaceable> <literal>==</literal> <entry><replaceable>e1</replaceable> <literal>==</literal>
@ -1322,9 +1322,9 @@ weakest binding).</para>
<section xml:id="ssec-derivation"><title>Derivations</title> <section xml:id="ssec-derivation"><title>Derivations</title>
<para>The most important built-in function is <para>The most important built-in function is
<function>derivation</function>, which is used to describe a <function>derivation</function>, which is used to describe a single
single derivation (a build action). It takes as input an attribute derivation (a build action). It takes as input a set, the attributes
set, the attributes of which specify the inputs of the build.</para> of which specify the inputs of the build.</para>
<itemizedlist> <itemizedlist>

View File

@ -35,15 +35,14 @@ Value * findAlongAttrPath(EvalState & state, const string & attrPath,
v = vNew; v = vNew;
state.forceValue(*v); state.forceValue(*v);
/* It should evaluate to either an attribute set or an /* It should evaluate to either a set or an expression,
expression, according to what is specified in the according to what is specified in the attrPath. */
attrPath. */
if (apType == apAttr) { if (apType == apAttr) {
if (v->type != tAttrs) if (v->type != tAttrs)
throw TypeError( throw TypeError(
format("the expression selected by the selection path `%1%' should be an attribute set but is %2%") format("the expression selected by the selection path `%1%' should be a set but is %2%")
% curPath % showType(*v)); % curPath % showType(*v));
Bindings::iterator a = v->attrs->find(state.symbols.create(attr)); Bindings::iterator a = v->attrs->find(state.symbols.create(attr));

View File

@ -45,7 +45,7 @@ inline void EvalState::forceAttrs(Value & v)
{ {
forceValue(v); forceValue(v);
if (v.type != tAttrs) if (v.type != tAttrs)
throwTypeError("value is %1% while an attribute set was expected", showType(v)); throwTypeError("value is %1% while a set was expected", showType(v));
} }

View File

@ -116,7 +116,7 @@ string showType(const Value & v)
case tString: return "a string"; case tString: return "a string";
case tPath: return "a path"; case tPath: return "a path";
case tNull: return "null"; case tNull: return "null";
case tAttrs: return "an attribute set"; case tAttrs: return "a set";
case tList: return "a list"; case tList: return "a list";
case tThunk: return "a thunk"; case tThunk: return "a thunk";
case tApp: return "a function application"; case tApp: return "a function application";
@ -488,7 +488,7 @@ inline void EvalState::evalAttrs(Env & env, Expr * e, Value & v)
{ {
e->eval(*this, env, v); e->eval(*this, env, v);
if (v.type != tAttrs) if (v.type != tAttrs)
throwTypeError("value is %1% while an attribute set was expected", showType(v)); throwTypeError("value is %1% while a set was expected", showType(v));
} }
@ -898,9 +898,8 @@ void ExprOpUpdate::eval(EvalState & state, Env & env, Value & v)
state.mkAttrs(v, v1.attrs->size() + v2.attrs->size()); state.mkAttrs(v, v1.attrs->size() + v2.attrs->size());
/* Merge the attribute sets, preferring values from the second /* Merge the sets, preferring values from the second set. Make
set. Make sure to keep the resulting vector in sorted sure to keep the resulting vector in sorted order. */
order. */
Bindings::iterator i = v1.attrs->begin(); Bindings::iterator i = v1.attrs->begin();
Bindings::iterator j = v2.attrs->begin(); Bindings::iterator j = v2.attrs->begin();
@ -1125,8 +1124,7 @@ string EvalState::coerceToString(Value & v, PathSet & context,
if (v.type == tAttrs) { if (v.type == tAttrs) {
Bindings::iterator i = v.attrs->find(sOutPath); Bindings::iterator i = v.attrs->find(sOutPath);
if (i == v.attrs->end()) if (i == v.attrs->end()) throwTypeError("cannot coerce a set to a string");
throwTypeError("cannot coerce an attribute set (except a derivation) to a string");
return coerceToString(*i->value, context, coerceMore, copyToStore); return coerceToString(*i->value, context, coerceMore, copyToStore);
} }
@ -1172,9 +1170,8 @@ bool EvalState::eqValues(Value & v1, Value & v2)
forceValue(v2); forceValue(v2);
/* !!! Hack to support some old broken code that relies on pointer /* !!! Hack to support some old broken code that relies on pointer
equality tests between attribute sets. (Specifically, equality tests between sets. (Specifically, builderDefs calls
builderDefs calls uniqList on a list of attribute sets.) Will uniqList on a list of sets.) Will remove this eventually. */
remove this eventually. */
if (&v1 == &v2) return true; if (&v1 == &v2) return true;
if (v1.type != v2.type) return false; if (v1.type != v2.type) return false;
@ -1212,8 +1209,8 @@ bool EvalState::eqValues(Value & v1, Value & v2)
return true; return true;
case tAttrs: { case tAttrs: {
/* If both attribute sets denote a derivation (type = /* If both sets denote a derivation (type = "derivation"),
"derivation"), then compare their outPaths. */ then compare their outPaths. */
if (isDerivation(v1) && isDerivation(v2)) { if (isDerivation(v1) && isDerivation(v2)) {
Bindings::iterator i = v1.attrs->find(sOutPath); Bindings::iterator i = v1.attrs->find(sOutPath);
Bindings::iterator j = v2.attrs->find(sOutPath); Bindings::iterator j = v2.attrs->find(sOutPath);
@ -1263,7 +1260,7 @@ void EvalState::printStats()
printMsg(v, format(" list concatenations: %1%") % nrListConcats); printMsg(v, format(" list concatenations: %1%") % nrListConcats);
printMsg(v, format(" values allocated: %1% (%2% bytes)") printMsg(v, format(" values allocated: %1% (%2% bytes)")
% nrValues % (nrValues * sizeof(Value))); % nrValues % (nrValues * sizeof(Value)));
printMsg(v, format(" attribute sets allocated: %1%") % nrAttrsets); printMsg(v, format(" sets allocated: %1%") % nrAttrsets);
printMsg(v, format(" right-biased unions: %1%") % nrOpUpdates); printMsg(v, format(" right-biased unions: %1%") % nrOpUpdates);
printMsg(v, format(" values copied in right-biased unions: %1%") % nrOpUpdateValuesCopied); printMsg(v, format(" values copied in right-biased unions: %1%") % nrOpUpdateValuesCopied);
printMsg(v, format(" symbols in symbol table: %1%") % symbols.size()); printMsg(v, format(" symbols in symbol table: %1%") % symbols.size());

View File

@ -19,8 +19,8 @@ class EvalState;
struct Attr; struct Attr;
/* Attribute sets are represented as a vector of attributes, sorted by /* Sets are represented as a vector of attributes, sorted by symbol
symbol (i.e. pointer to the attribute name in the symbol table). */ (i.e. pointer to the attribute name in the symbol table). */
#if HAVE_BOEHMGC #if HAVE_BOEHMGC
typedef std::vector<Attr, gc_allocator<Attr> > BindingsBase; typedef std::vector<Attr, gc_allocator<Attr> > BindingsBase;
#else #else

View File

@ -41,7 +41,7 @@ DrvInfo::Outputs DrvInfo::queryOutputs(EvalState & state)
/* For each output... */ /* For each output... */
for (unsigned int j = 0; j < i->value->list.length; ++j) { for (unsigned int j = 0; j < i->value->list.length; ++j) {
/* Evaluate the corresponding attribute set. */ /* Evaluate the corresponding set. */
string name = state.forceStringNoCtx(*i->value->list.elems[j]); string name = state.forceStringNoCtx(*i->value->list.elems[j]);
Bindings::iterator out = attrs->find(state.symbols.create(name)); Bindings::iterator out = attrs->find(state.symbols.create(name));
if (out == attrs->end()) continue; // FIXME: throw error? if (out == attrs->end()) continue; // FIXME: throw error?
@ -119,11 +119,10 @@ void DrvInfo::setMetaInfo(const MetaInfo & meta)
typedef set<Bindings *> Done; typedef set<Bindings *> Done;
/* Evaluate value `v'. If it evaluates to an attribute set of type /* Evaluate value `v'. If it evaluates to a set of type `derivation',
`derivation', then put information about it in `drvs' (unless it's then put information about it in `drvs' (unless it's already in
already in `doneExprs'). The result boolean indicates whether it `doneExprs'). The result boolean indicates whether it makes sense
makes sense for the caller to recursively search for derivations in for the caller to recursively search for derivations in `v'. */
`v'. */
static bool getDerivation(EvalState & state, Value & v, static bool getDerivation(EvalState & state, Value & v,
const string & attrPath, DrvInfos & drvs, Done & done, const string & attrPath, DrvInfos & drvs, Done & done,
bool ignoreAssertionFailures) bool ignoreAssertionFailures)
@ -132,8 +131,8 @@ static bool getDerivation(EvalState & state, Value & v,
state.forceValue(v); state.forceValue(v);
if (!state.isDerivation(v)) return true; if (!state.isDerivation(v)) return true;
/* Remove spurious duplicates (e.g., an attribute set like /* Remove spurious duplicates (e.g., a set like `rec { x =
`rec { x = derivation {...}; y = x;}'. */ derivation {...}; y = x;}'. */
if (done.find(v.attrs) != done.end()) return false; if (done.find(v.attrs) != done.end()) return false;
done.insert(v.attrs); done.insert(v.attrs);
@ -218,10 +217,9 @@ static void getDerivations(EvalState & state, Value & vIn,
if (combineChannels) if (combineChannels)
getDerivations(state, v2, pathPrefix2, autoArgs, drvs, done, ignoreAssertionFailures); getDerivations(state, v2, pathPrefix2, autoArgs, drvs, done, ignoreAssertionFailures);
else if (getDerivation(state, v2, pathPrefix2, drvs, done, ignoreAssertionFailures)) { else if (getDerivation(state, v2, pathPrefix2, drvs, done, ignoreAssertionFailures)) {
/* If the value of this attribute is itself an /* If the value of this attribute is itself a set,
attribute set, should we recurse into it? => Only should we recurse into it? => Only if it has a
if it has a `recurseForDerivations = true' `recurseForDerivations = true' attribute. */
attribute. */
if (v2.type == tAttrs) { if (v2.type == tAttrs) {
Bindings::iterator j = v2.attrs->find(state.symbols.create("recurseForDerivations")); Bindings::iterator j = v2.attrs->find(state.symbols.create("recurseForDerivations"));
if (j != v2.attrs->end() && state.forceBool(*j->value)) if (j != v2.attrs->end() && state.forceBool(*j->value))

View File

@ -123,8 +123,8 @@ struct ExprVar : Expr
levels up from the current environment and getting the levels up from the current environment and getting the
`displ'th value in that environment. In the latter case, the `displ'th value in that environment. In the latter case, the
value is obtained by getting the attribute named `name' from value is obtained by getting the attribute named `name' from
the attribute set stored in the environment that is `level' the set stored in the environment that is `level' levels up
levels up from the current one.*/ from the current one.*/
unsigned int level; unsigned int level;
unsigned int displ; unsigned int displ;

View File

@ -103,7 +103,7 @@ static void prim_typeOf(EvalState & state, Value * * args, Value & v)
case tString: t = "string"; break; case tString: t = "string"; break;
case tPath: t = "path"; break; case tPath: t = "path"; break;
case tNull: t = "null"; break; case tNull: t = "null"; break;
case tAttrs: t = "attrs"; break; case tAttrs: t = "set"; break;
case tList: t = "list"; break; case tList: t = "list"; break;
case tLambda: case tLambda:
case tPrimOp: case tPrimOp:
@ -729,12 +729,12 @@ static void prim_filterSource(EvalState & state, Value * * args, Value & v)
/************************************************************* /*************************************************************
* Attribute sets * Sets
*************************************************************/ *************************************************************/
/* Return the names of the attributes in an attribute set as a sorted /* Return the names of the attributes in a set as a sorted list of
list of strings. */ strings. */
static void prim_attrNames(EvalState & state, Value * * args, Value & v) static void prim_attrNames(EvalState & state, Value * * args, Value & v)
{ {
state.forceAttrs(*args[0]); state.forceAttrs(*args[0]);
@ -776,7 +776,7 @@ static void prim_hasAttr(EvalState & state, Value * * args, Value & v)
} }
/* Determine whether the argument is an attribute set. */ /* Determine whether the argument is a set. */
static void prim_isAttrs(EvalState & state, Value * * args, Value & v) static void prim_isAttrs(EvalState & state, Value * * args, Value & v)
{ {
state.forceValue(*args[0]); state.forceValue(*args[0]);
@ -807,10 +807,10 @@ static void prim_removeAttrs(EvalState & state, Value * * args, Value & v)
} }
/* Builds an attribute set from a list specifying (name, value) /* Builds a set from a list specifying (name, value) pairs. To be
pairs. To be precise, a list [{name = "name1"; value = value1;} precise, a list [{name = "name1"; value = value1;} ... {name =
... {name = "nameN"; value = valueN;}] is transformed to {name1 = "nameN"; value = valueN;}] is transformed to {name1 = value1;
value1; ... nameN = valueN;}. */ ... nameN = valueN;}. */
static void prim_listToAttrs(EvalState & state, Value * * args, Value & v) static void prim_listToAttrs(EvalState & state, Value * * args, Value & v)
{ {
state.forceList(*args[0]); state.forceList(*args[0]);
@ -844,9 +844,9 @@ static void prim_listToAttrs(EvalState & state, Value * * args, Value & v)
} }
/* Return the right-biased intersection of two attribute sets as1 and /* Return the right-biased intersection of two sets as1 and as2,
as2, i.e. a set that contains every attribute from as2 that is also i.e. a set that contains every attribute from as2 that is also a
a member of as1. */ member of as1. */
static void prim_intersectAttrs(EvalState & state, Value * * args, Value & v) static void prim_intersectAttrs(EvalState & state, Value * * args, Value & v)
{ {
state.forceAttrs(*args[0]); state.forceAttrs(*args[0]);
@ -1240,7 +1240,7 @@ void EvalState::createBaseEnv()
addPrimOp("__toFile", 2, prim_toFile); addPrimOp("__toFile", 2, prim_toFile);
addPrimOp("__filterSource", 2, prim_filterSource); addPrimOp("__filterSource", 2, prim_filterSource);
// Attribute sets // Sets
addPrimOp("__attrNames", 1, prim_attrNames); addPrimOp("__attrNames", 1, prim_attrNames);
addPrimOp("__getAttr", 2, prim_getAttr); addPrimOp("__getAttr", 2, prim_getAttr);
addPrimOp("__hasAttr", 2, prim_hasAttr); addPrimOp("__hasAttr", 2, prim_hasAttr);
@ -1290,8 +1290,8 @@ void EvalState::createBaseEnv()
evalFile(path, v); evalFile(path, v);
addConstant("derivation", v); addConstant("derivation", v);
/* Now that we've added all primops, sort the `builtins' attribute /* Now that we've added all primops, sort the `builtins' set,
set, because attribute lookups expect it to be sorted. */ because attribute lookups expect it to be sorted. */
baseEnv.values[0]->attrs->sort(); baseEnv.values[0]->attrs->sort();
} }

View File

@ -13,11 +13,10 @@
namespace nix { namespace nix {
/* Symbol table used by the parser and evaluator to represent and look /* Symbol table used by the parser and evaluator to represent and look
up identifiers and attribute sets efficiently. up identifiers and attributes efficiently. SymbolTable::create()
SymbolTable::create() converts a string into a symbol. Symbols converts a string into a symbol. Symbols have the property that
have the property that they can be compared efficiently (using a they can be compared efficiently (using a pointer equality test),
pointer equality test), because the symbol table stores only one because the symbol table stores only one copy of each string. */
copy of each string. */
class Symbol class Symbol
{ {

View File

@ -159,11 +159,11 @@ static void loadSourceExpr(EvalState & state, const Path & path, Value & v)
} }
/* The path is a directory. Put the Nix expressions in the /* The path is a directory. Put the Nix expressions in the
directory in an attribute set, with the file name of each directory in a set, with the file name of each expression as
expression as the attribute name. Recurse into subdirectories the attribute name. Recurse into subdirectories (but keep the
(but keep the attribute set flat, not nested, to make it easier set flat, not nested, to make it easier for a user to have a
for a user to have a ~/.nix-defexpr directory that includes ~/.nix-defexpr directory that includes some system-wide
some system-wide directory). */ directory). */
if (S_ISDIR(st.st_mode)) { if (S_ISDIR(st.st_mode)) {
state.mkAttrs(v, 16); state.mkAttrs(v, 16);
state.mkList(*state.allocAttr(v, state.symbols.create("_combineChannels")), 0); state.mkList(*state.allocAttr(v, state.symbols.create("_combineChannels")), 0);

View File

@ -1 +1 @@
[ true false true false true false true false true false "int" "bool" "string" "null" "attrs" "list" "lambda" "lambda" "lambda" "lambda" ] [ true false true false true false true false true false "int" "bool" "string" "null" "set" "list" "lambda" "lambda" "lambda" "lambda" ]