Skip to content

Commit 6218aff

Browse files
jonmeowzygoloid
andauthored
Document and, or, and not from #680 (#1032)
Co-authored-by: Chandler Carruth <[email protected]> Co-authored-by: Richard Smith <[email protected]>
1 parent 2d567f5 commit 6218aff

File tree

2 files changed

+164
-0
lines changed

2 files changed

+164
-0
lines changed

docs/design/expressions/README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
1111
## Table of contents
1212

1313
- [Overview](#overview)
14+
- [Operators](#operators)
1415
- [Conversions and casts](#conversions-and-casts)
1516

1617
<!-- tocstop -->
@@ -29,6 +30,17 @@ fn Foo(a: i32*) -> i32 {
2930
Here, the parameter type `i32*`, the return type `i32`, and the operand `*a` of
3031
the `return` statement are all expressions.
3132

33+
## Operators
34+
35+
Most expressions are modeled as operators:
36+
37+
| Category | Operator | Syntax | Function |
38+
| ---------- | ----------------------------- | --------- | ------------------------------------------------------------------- |
39+
| Conversion | [`as`](as_expressions.md) | `x as T` | Converts the value `x` to the type `T`. |
40+
| Logical | [`and`](logical_operators.md) | `x and y` | A short-circuiting logical AND: `true` if both operands are `true`. |
41+
| Logical | [`or`](logical_operators.md) | `x or y` | A short-circuiting logical OR: `true` if either operand is `true`. |
42+
| Logical | [`not`](logical_operators.md) | `not x` | Logical NOT: `true` if the operand is `false`. |
43+
3244
## Conversions and casts
3345

3446
When an expression appears in a context in which an expression of a specific
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
# Logical operators
2+
3+
<!--
4+
Part of the Carbon Language project, under the Apache License v2.0 with LLVM
5+
Exceptions. See /LICENSE for license information.
6+
SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
-->
8+
9+
<!-- toc -->
10+
11+
## Table of contents
12+
13+
- [Overview](#overview)
14+
- [Details](#details)
15+
- [Precedence](#precedence)
16+
- [Associativity](#associativity)
17+
- [Conversions](#conversions)
18+
- [Overloading](#overloading)
19+
- [Alternatives considered](#alternatives-considered)
20+
- [References](#references)
21+
22+
<!-- tocstop -->
23+
24+
## Overview
25+
26+
Carbon provides three operators to support logical operations on `bool` values:
27+
28+
- `and` provides a logical AND operation.
29+
- `x and y` evaluates to `true` if both operands are `true`.
30+
- `or` provides a logical OR operation.
31+
- `x or y` evaluates to `true` if either operand is `true`.
32+
- `not` provides a logical NOT operation.
33+
- `not x` evaluates to `true` if the operand is `false`.
34+
35+
`and` and `or` are infix binary operators, and use
36+
[short-circuit evaluation](https://en.wikipedia.org/wiki/Short-circuit_evaluation).
37+
`not` is a prefix unary operator.
38+
39+
## Details
40+
41+
### Precedence
42+
43+
`and` and `or` have very low precedence. When an expression appearing as the
44+
condition of an `if` uses these operators unparenthesized, they are always the
45+
lowest precedence operators in that expression.
46+
47+
These operators permit any reasonable operator that might be used to form a
48+
`bool` value as a subexpression. In particular, comparison operators such as `<`
49+
and `==` have higher precedence than `and` and `or`. However, the precedence of
50+
`and` and `or` is not directly comparable with each other, so they cannot both
51+
be used directly in an expression without parentheses.
52+
53+
`not` is higher precedence than `and` and `or`, but its precedence is
54+
incomparable with most other operators, including comparison operators.
55+
56+
For example:
57+
58+
```carbon
59+
// ✅ Valid: `and` is lower precedence than the `<` or `==` operators.
60+
if (n + m == 3 and not n < m) {
61+
...
62+
}
63+
// The above is equivalent to:
64+
if (((n + m) == 3) and (not (n < m))) {
65+
...
66+
}
67+
68+
// ❌ Invalid: `and` and `or` precedence is incomparable.
69+
if (cond1 and cond2 or cond3) {
70+
...
71+
}
72+
// ✅ Valid: Parentheses avoid the precedence check.
73+
if (cond1 and (cond2 or cond3)) {
74+
...
75+
}
76+
77+
// ❌ Invalid: `not` precedence is incomparable with `==`.
78+
if (not cond1 == cond2) {
79+
...
80+
}
81+
// ❌ Invalid: `not` precedence is incomparable with `==`.
82+
if (cond1 == not cond2) {
83+
...
84+
}
85+
// ✅ Valid: Parentheses avoid the precedence check.
86+
if (cond1 == (not cond2)) {
87+
...
88+
}
89+
```
90+
91+
### Associativity
92+
93+
`and` and `or` are left-associative. A `not` expression cannot be the operand of
94+
another `not` expression; `not not b` is an error without parentheses.
95+
96+
```
97+
// ✅ Valid: `and` is left-associative, and precedence is fine.
98+
if (not a and not b and not c) {
99+
...
100+
}
101+
// The above is equivalent to:
102+
if ((not a) and ((not b) and (not c))) {
103+
...
104+
}
105+
// ✅ Valid: Parentheses avoid the `not` associativity error.
106+
if (not (not a)) {
107+
...
108+
}
109+
110+
// ❌ Invalid: `not not` associativity requires parentheses.
111+
if (not not a) {
112+
...
113+
}
114+
```
115+
116+
### Conversions
117+
118+
> TODO: This should be addressed through a standard `bool` conversion design.
119+
120+
The operand of `and`, `or`, or `not` is converted to a `bool` value in the same
121+
way as the condition of an `if` statement. In particular:
122+
123+
- If we decide that certain values, such as pointers or integers, should not
124+
be usable as the condition of an `if` without an explicit comparison against
125+
null or zero, then those values will also not be usable as the operand of
126+
`and`, `or`, or `not` without an explicit comparison.
127+
- If an extension point is provided to determine how to branch on the truth of
128+
a value in an `if` (such as by supplying a conversion to a `bool` type),
129+
that extension point will also apply to `and`, `or`, and `not`.
130+
131+
### Overloading
132+
133+
The logical operators `and`, `or`, and `not` are not overloadable. As noted
134+
above, any mechanism that allows types to customize how `if` treats them will
135+
also customize how `and`, `or`, and `not` treats them.
136+
137+
## Alternatives considered
138+
139+
- [Use punctuation spelling for all three operators](/proposals/p0680.md#use-punctuation-spelling-for-all-three-operators)
140+
- [Precedence of AND versus OR](/proposals/p0680.md#precedence-of-and-versus-or)
141+
- [Precedence of NOT](/proposals/p0680.md#precedence-of-not)
142+
- [Punctuation form of NOT](/proposals/p0680.md#punctuation-form-of-not)
143+
- [Two forms of NOT](/proposals/p0680.md#two-forms-of-not)
144+
- [Repeated NOT](/proposals/p0680.md#repeated-not)
145+
- [AND and OR produce the decisive value](/proposals/p0680.md#and-and-or-produce-the-decisive-value)
146+
147+
## References
148+
149+
- Proposal
150+
[#680: And, or, not](https://github.com/carbon-language/carbon-lang/pull/680).
151+
- Proposal
152+
[#702: Comparison operators](https://github.com/carbon-language/carbon-lang/pull/702).

0 commit comments

Comments
 (0)