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:
parent
9e4bb20455
commit
5bc41d78ff
|
@ -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 doesn’t exist. This is a dynamic version of the
|
attribute doesn’t 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 doesn’t exist or contains an incorrect Nix
|
file doesn’t exist or contains an incorrect Nix expression.
|
||||||
expression. <function>import</function> implements Nix’s module
|
<function>import</function> implements Nix’s 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 don’t have to
|
<replaceable>set</replaceable>. The attributes don’t 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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
doesn’t exist, return <replaceable>def</replaceable> if
|
doesn’t 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>
|
||||||
|
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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" ]
|
||||||
|
|
Loading…
Reference in a new issue