Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor documentation of operators, document + for strings and paths #7498

Merged
merged 7 commits into from
Jan 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
191 changes: 165 additions & 26 deletions doc/manual/src/language/operators.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,167 @@
# Operators

The table below lists the operators in the Nix language, in
order of precedence (from strongest to weakest binding).

| Name | Syntax | Associativity | Description | Precedence |
| ------------------------ | ----------------------------------- | ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| Select | *e* `.` *attrpath* \[ `or` *def* \] | none | Select attribute denoted by the attribute path *attrpath* from set *e*. (An attribute path is a dot-separated list of attribute names.) If the attribute doesn’t exist, return *def* if provided, otherwise abort evaluation. | 1 |
| Application | *e1* *e2* | left | Call function *e1* with argument *e2*. | 2 |
| Arithmetic Negation | `-` *e* | none | Arithmetic negation. | 3 |
| Has Attribute | *e* `?` *attrpath* | none | Test whether set *e* contains the attribute denoted by *attrpath*; return `true` or `false`. | 4 |
| List Concatenation | *e1* `++` *e2* | right | List concatenation. | 5 |
| Multiplication | *e1* `*` *e2*, | left | Arithmetic multiplication. | 6 |
| Division | *e1* `/` *e2* | left | Arithmetic division. | 6 |
| Addition | *e1* `+` *e2* | left | Arithmetic addition. | 7 |
| Subtraction | *e1* `-` *e2* | left | Arithmetic subtraction. | 7 |
| String Concatenation | *string1* `+` *string2* | left | String concatenation. | 7 |
| Not | `!` *e* | none | Boolean negation. | 8 |
| Update | *e1* `//` *e2* | right | Return a set consisting of the attributes in *e1* and *e2* (with the latter taking precedence over the former in case of equally named attributes). | 9 |
| Less Than | *e1* `<` *e2*, | none | Arithmetic/lexicographic comparison. | 10 |
| Less Than or Equal To | *e1* `<=` *e2* | none | Arithmetic/lexicographic comparison. | 10 |
| Greater Than | *e1* `>` *e2* | none | Arithmetic/lexicographic comparison. | 10 |
| Greater Than or Equal To | *e1* `>=` *e2* | none | Arithmetic/lexicographic comparison. | 10 |
| Equality | *e1* `==` *e2* | none | Equality. | 11 |
| Inequality | *e1* `!=` *e2* | none | Inequality. | 11 |
| Logical AND | *e1* `&&` *e2* | left | Logical AND. | 12 |
| Logical OR | *e1* <code>&#124;&#124;</code> *e2* | left | Logical OR. | 13 |
| Logical Implication | *e1* `->` *e2* | none | Logical implication (equivalent to <code>!e1 &#124;&#124; e2</code>). | 14 |
| Name | Syntax | Associativity | Precedence |
|----------------------------------------|--------------------------------------------|---------------|------------|
| [Attribute selection] | *attrset* `.` *attrpath* \[ `or` *expr* \] | none | 1 |
| Function application | *func* *expr* | left | 2 |
| [Arithmetic negation][arithmetic] | `-` *number* | none | 3 |
| [Has attribute] | *attrset* `?` *attrpath* | none | 4 |
| List concatenation | *list* `++` *list* | right | 5 |
| [Multiplication][arithmetic] | *number* `*` *number* | left | 6 |
| [Division][arithmetic] | *number* `/` *number* | left | 6 |
| [Subtraction][arithmetic] | *number* `-` *number* | left | 7 |
| [Addition][arithmetic] | *number* `+` *number* | left | 7 |
| [String concatenation] | *string* `+` *string* | left | 7 |
| [Path concatenation] | *path* `+` *path* | left | 7 |
| [Path and string concatenation] | *path* `+` *string* | left | 7 |
| [String and path concatenation] | *string* `+` *path* | left | 7 |
| Logical negation (`NOT`) | `!` *bool* | none | 8 |
| [Update] | *attrset* `//` *attrset* | right | 9 |
| [Less than][Comparison] | *expr* `<` *expr* | none | 10 |
| [Less than or equal to][Comparison] | *expr* `<=` *expr* | none | 10 |
| [Greater than][Comparison] | *expr* `>` *expr* | none | 10 |
| [Greater than or equal to][Comparison] | *expr* `>=` *expr* | none | 10 |
| [Equality] | *expr* `==` *expr* | none | 11 |
| Inequality | *expr* `!=` *expr* | none | 11 |
| Logical conjunction (`AND`) | *bool* `&&` *bool* | left | 12 |
| Logical disjunction (`OR`) | *bool* `||` *bool* | left | 13 |
| [Logical implication] | *bool* `->` *bool* | none | 14 |

[string]: ./values.md#type-string
[path]: ./values.md#type-path
[number]: ./values.md#type-number
[list]: ./values.md#list
[attribute set]: ./values.md#attribute-set

## Attribute selection

Select the attribute denoted by attribute path *attrpath* from [attribute set] *attrset*.
If the attribute doesn’t exist, return *value* if provided, otherwise abort evaluation.

<!-- FIXME: the following should to into its own language syntax section, but that needs more work to fit in well -->

An attribute path is a dot-separated list of attribute names.
An attribute name can be an identifier or a string.

> *attrpath* = *name* [ `.` *name* ]...
> *name* = *identifier* | *string*
> *identifier* ~ `[a-zA-Z_][a-zA-Z0-9_'-]*`

[Attribute selection]: #attribute-selection

## Has attribute

> *attrset* `?` *attrpath*

Test whether [attribute set] *attrset* contains the attribute denoted by *attrpath*.
The result is a [Boolean] value.

[Boolean]: ./values.md#type-boolean

[Has attribute]: #has-attribute

## Arithmetic

Numbers are type-compatible:
Pure integer operations will always return integers, whereas any operation involving at least one floating point number return a floating point number.

See also [Comparison] and [Equality].

The `+` operator is overloaded to also work on strings and paths.

[arithmetic]: #arithmetic

## String concatenation

> *string* `+` *string*

Concatenate two [string]s and merge their string contexts.

[String concatenation]: #string-concatenation

## Path concatenation

> *path* `+` *path*

Concatenate two [path]s.
The result is a path.

[Path concatenation]: #path-concatenation

## Path and string concatenation

> *path* + *string*

Concatenate *[path]* with *[string]*.
The result is a path.

> **Note**
>
> The string must not have a string context that refers to a [store path].

[Path and string concatenation]: #path-and-string-concatenation

## String and path concatenation

> *string* + *path*

Concatenate *[string]* with *[path]*.
The result is a string.

> **Important**
>
> The file or directory at *path* must exist and is copied to the [store].
> The path appears in the result as the corresponding [store path].

[store path]: ../glossary.md#gloss-store-path
[store]: ../glossary.md#gloss-store

[Path and string concatenation]: #path-and-string-concatenation

## Update

> *attrset1* + *attrset2*

Update [attribute set] *attrset1* with names and values from *attrset2*.

The returned attribute set will have of all the attributes in *e1* and *e2*.
If an attribute name is present in both, the attribute value from the former is taken.

[Update]: #update

## Comparison

Comparison is

- [arithmetic] for [number]s
- lexicographic for [string]s and [path]s
- item-wise lexicographic for [list]s:
elements at the same index in both lists are compared according to their type and skipped if they are equal.

All comparison operators are implemented in terms of `<`, and the following equivalencies hold:

| comparison | implementation |
|--------------|-----------------------|
| *a* `<=` *b* | `! (` *b* `<` *a* `)` |
| *a* `>` *b* | *b* `<` *a* |
| *a* `>=` *b* | `! (` *a* `<` *b* `)` |

[Comparison]: #comparison-operators

## Equality

- [Attribute sets][attribute set] and [list]s are compared recursively, and therefore are fully evaluated.
- Comparison of [function]s always returns `false`.
- Numbers are type-compatible, see [arithmetic] operators.
- Floating point numbers only differ up to a limited precision.

[function]: ./constructs.md#functions

[Equality]: #equality

## Logical implication

Equivalent to `!`*b1* `||` *b2*.

[Logical implication]: #logical-implication

7 changes: 4 additions & 3 deletions doc/manual/src/language/values.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,10 @@
Numbers, which can be *integers* (like `123`) or *floating point*
(like `123.43` or `.27e13`).

Numbers are type-compatible: pure integer operations will always
return integers, whereas any operation involving at least one
floating point number will have a floating point number as a result.
See [arithmetic] and [comparison] operators for semantics.

[arithmetic]: ./operators.md#arithmetic
[comparison]: ./operators.md#comparison

- <a id="type-path" href="#type-path">Path</a>

Expand Down