Skip to content
This repository was archived by the owner on Dec 12, 2024. It is now read-only.

Commit 9bba642

Browse files
authored
feat: Update of the Book→Operators page (#205)
* feat: Update of the Book→Operators page * All precedences match Tact 1.3.0 * Added bitwise XOR operator `^` * Fixed minor typos and corrected some descriptions * Added a table of operators in decreasing order of their precedences Note, that the only link leading to Language section now has a proper link to the Reference section. This is intentional, as the Lang->Ref rename is almost there :) * chore: reset alignment * chore: corrected highlighting * fix/feat: applied suggestions from a code review * Property of division rounding down (division of real numbers without rounding them down won't have such property) * Rounding towards -∞ mentioned and explained * Bit masking example reference
1 parent 66631a0 commit 9bba642

File tree

2 files changed

+172
-66
lines changed

2 files changed

+172
-66
lines changed

pages/book/message-mode.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ $+32$ | `SendDestroyIfZero{:tact}` | Current account must be destroyed
2525

2626
## Combining modes with flags
2727

28-
To make the [`Int{:tact}`][int] value for `mode` field of SendParameters, you just have to combine base modes with optional flags by applying the [`bitwise OR{:tact}`](/book/operators#binary-bitwise-or) operation.
28+
To make the [`Int{:tact}`][int] value for `mode` field of `SendParameters{:tact}`, you just have to combine base modes with optional flags by applying the [`bitwise OR{:tact}`](/book/operators#binary-bitwise-or) operation.
2929

3030
For example, if you want to send a regular message and pay transfer fees separately, use the mode $0$ (default) and a flag $+1$ to get `mode` $= 1$, which is equal to using `SendPayGasSeparately{:tact}` constant.
3131

pages/book/operators.mdx

Lines changed: 171 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,67 @@ This page lists all the operators in Tact in decreasing order of their [preceden
88

99
<Callout>
1010

11-
Note, that there are no implicit type conversions in Tact, so operators can't be used to, say, add values of different type or compare them in terms of equality without explicitly casting to the same type. That's done with certain functions from the standard library. See [`Int.toString(){:tact}`](/language/ref/strings#inttostring) for an example of such function.
11+
Note, that there are no implicit type conversions in Tact, so operators can't be used to, say, add values of different type or compare them in terms of equality without explicitly casting to the same type. That's done with certain functions from the standard library. See [`Int.toString(){:tact}`](/ref/api-strings#inttostring) for an example of such function.
1212

1313
</Callout>
1414

15+
## Table of operators [#table]
16+
17+
The following table lists operators in order of decreasing [precedence](#precedence): from highest to lowest.
18+
19+
Brief description | Operators
20+
:---------------- | :--------------------------------------------------------------------
21+
Parentheses | [`(){:tact}`][paren]
22+
Unary postfix | [`!!{:tact}`][nna]
23+
Unary prefix | [`+{:tact}`][plus] &nbsp; [`-{:tact}`][neg] &nbsp; [`!{:tact}`][inv]
24+
Multiplicative | [`*{:tact}`][mul] &nbsp; [`/{:tact}`][div] &nbsp; [`%{:tact}`][mod]
25+
Additive | [`+{:tact}`][add] &nbsp; [`-{:tact}`][sub]
26+
Shift | [`>>{:tact}`][shr] &nbsp; [`<<{:tact}`][shl]
27+
Relation | [`>{:tact}`][gt] &nbsp; [`>={:tact}`][ge] &nbsp; [`<{:tact}`][lt] &nbsp; [`<={:tact}`][le]
28+
Equality | [`=={:tact}`][eq] &nbsp; [`!={:tact}`][eq]
29+
Bitwise AND | [`&{:tact}`][b-and]
30+
Bitwise XOR | [`^{:tact}`][b-xor]
31+
Bitwise OR | [`\|{:tact}`][b-or]
32+
Logical AND | [`&&{:tact}`][l-and]
33+
Logical OR | [`\|\|{:tact}`][l-or]
34+
Ternary | [`?:{:tact}`][ternary]
35+
Assignment | [`={:tact}`][assign]
36+
37+
[paren]: #parentheses
38+
39+
[nna]: #unary-non-null-assert
40+
[plus]: #unary-plus
41+
[neg]: #unary-negate
42+
[inv]: #unary-inverse
43+
44+
[mul]: #binary-multiply
45+
[div]: #binary-divide
46+
[mod]: #binary-modulo
47+
48+
[add]: #binary-add
49+
[sub]: #binary-subtract
50+
51+
[shr]: #binary-bitwise-shift-right
52+
[shl]: #binary-bitwise-shift-left
53+
54+
[gt]: #binary-greater
55+
[ge]: #binary-greater-equal
56+
[lt]: #binary-less
57+
[le]: #binary-less-equal
58+
59+
[eq]: #binary-equality
60+
61+
[b-and]: #binary-bitwise-and
62+
[b-xor]: #binary-bitwise-xor
63+
[b-or]: #binary-bitwise-or
64+
65+
[l-and]: #binary-logical-and
66+
[l-or]: #binary-logical-or
67+
68+
[ternary]: #ternary
69+
70+
[assign]: #assignment
71+
1572
## Precedence
1673

1774
All operators on this page are given in order of decreasing precedence, from highest to lowest. Precedence is used to choose which operator would be considered in a particular situation. Whenever any ambiguity arises, Tact would prefer operators with higher precedence over those with lower.
@@ -27,7 +84,7 @@ Consider the following code:
2784

2885
Even though this example may be simple, neglection of precedence rules can often lead to confusing situations with operators. The correct order of operations can be ensured by wrapping every operation in [parentheses](#parentheses), since parentheses have the highest precedence of all expressions and operators there is.
2986

30-
## Parentheses, `()`
87+
## Parentheses, `()` [#parentheses]
3188

3289
Parentheses (also can be called round brackets, `(){:tact}`) are more of a punctuation symbols than actual operators, but their [precedence](#precedence) is higher than precedence of any other operator. Use parentheses to override order of operations:
3390

@@ -107,17 +164,36 @@ pow(2, 255) * pow(2, 255); // build error: integer overflow!
107164

108165
#### Divide, `/` [#binary-divide]
109166

110-
Binary slash (_division_) operator `/{:tact}` is used for integer division of two values, which truncates towards zero. An attempt to divide by zero would result in an error with [exit code 4](/book/exit-codes#4): `Integer overflow`.
167+
Binary slash (_division_) operator `/{:tact}` is used for integer division of two values, which truncates towards zero if result is positive, and away from zero if result is negative. This is also called [rounding down](https://en.wikipedia.org/wiki/Rounding#Rounding_down) (or rounding towards $-∞$).
168+
169+
An attempt to divide by zero would result in an error with [exit code 4](/book/exit-codes#4): `Integer overflow`.
111170

112171
Can only be applied to values of type [`Int{:tact}`][int]:
113172

114173
```tact
115174
let two: Int = 2;
116175
two / 2; // 1
117-
two / 1; // 2
176+
two / 1; // 0
118177
-1 / 5; // -1
178+
-1 / -5; // 0
179+
1 / -5; // -1
180+
1 / 5; // 0
181+
6 / 5; // 1, rounding down
182+
-6 / 5; // -2, rounding down (towards -∞)
119183
```
120184

185+
<Callout>
186+
187+
Note that the following relationship between the division and modulo operators always holds for `Int{:tact}` type:
188+
189+
```tact
190+
a / b * b + a % b == a; // true for any Int values of `a` and `b`,
191+
// except when `b` is equal to 0 and we divide `a` by 0,
192+
// which is an attempt to divide by zero resulting in an error
193+
```
194+
195+
</Callout>
196+
121197
#### Modulo, `%` [#binary-modulo]
122198

123199
Binary percent sign (_modulo_) operator `%{:tact}` is used for getting the modulo of an integer division, which must not be confused with getting a remainder. For two values of the same sign, modulo and remainder operations are equivalent, but when the operands are of different signs, the modulo result always has the same sign as the _divisor_ (value on the right), while the remainder has the same sign as the _dividend_ (value on the left), which can make them differ by one unit of the _divisor_.
@@ -127,15 +203,15 @@ Can only be applied to values of type [`Int{:tact}`][int]:
127203
```tact
128204
let two: Int = 2;
129205
two % 2; // 0
130-
1 % two; // 1
206+
two % 1; // 1
131207
132208
1 % 5; // 1
133209
-1 % 5; // 4
134210
1 % -5; // -4
135211
-1 % -5; // -1
136212
```
137213

138-
The simplest way to avoid confusion between the two is to prefer using positive values via [`abs(x: Int){:tact}`](/language/ref/math#abs):
214+
The simplest way to avoid confusion between the two is to prefer using positive values via [`abs(x: Int){:tact}`](/ref/api-math#abs):
139215

140216
```tact
141217
abs(-1) % abs(-5); // 1
@@ -185,9 +261,9 @@ pow(2, 255) - pow(2, 255); // 0
185261
pow(2, 256) - pow(2, 256); // build error: integer overflow!
186262
```
187263

188-
### Bitwise [#binary-bitwise]
264+
### Bitwise shifts [#binary-bitwise-shifts]
189265

190-
Manipulate individual bits.
266+
Shift bits to the left or to the right.
191267

192268
#### Shift right, `>>` [#binary-bitwise-shift-right]
193269

@@ -213,7 +289,7 @@ pow(2, 254) >> 254; // 1
213289

214290
#### Shift left, `<<` [#binary-bitwise-shift-left]
215291

216-
Binary double greater than (_bitwise shift right_) operator `<<{:tact}` returns an integer which binary representation is the _left operand_ value shifted by the _right operand_ number of bits to the left. Excess bits shifted off to the left are discarded, and zero bits are shifted in from the right. This is a more effective way to multiply the _left operand_ by $2^n$, where $n$ is equal to the _right operand_. Going beyond the maximum value of an [`Int{:tact}`][int] will result in an error with [exit code 4](/book/exit-codes#4): `Integer overflow`.
292+
Binary double greater than (_bitwise shift left_) operator `<<{:tact}` returns an integer which binary representation is the _left operand_ value shifted by the _right operand_ number of bits to the left. Excess bits shifted off to the left are discarded, and zero bits are shifted in from the right. This is a more effective way to multiply the _left operand_ by $2^n$, where $n$ is equal to the _right operand_. Going beyond the maximum value of an [`Int{:tact}`][int] will result in an error with [exit code 4](/book/exit-codes#4): `Integer overflow`.
217293

218294
Can only be applied to values of type [`Int{:tact}`][int]:
219295

@@ -235,57 +311,51 @@ pow(2, 255) == 1 << 255; // true, but we're very close to overflow here!
235311

236312
</Callout>
237313

238-
#### Bitwise AND, `&` [#binary-bitwise-and]
314+
### Relation [#binary-relation]
239315

240-
Binary ampersand (_bitwise and_) operator `&{:tact}` applies a [bitwise AND](https://en.wikipedia.org/wiki/Bitwise_operation#AND), which performs the [logical AND](#binary-logical-and) operation on each pair of the corresponding bits of operands. This is useful when we want to clear selected bits off a number, where each bit represents an individual flag or a boolean state, which makes it possible to "store" up to $257$ boolean values per integer, as all integers in Tact are $257$-bit signed.
316+
Find bigger, smaller or equal values.
241317

242-
Can only be applied to values of type [`Int{:tact}`][int]:
318+
#### Greater than, `>` [#binary-greater]
319+
320+
Binary _greater than_ operator `>{:tact}` returns `true{:tact}` if the left operand is greater than the right operand, and `false{:tact}` otherwise. Can only be applied to values of type [`Int{:tact}`][int]:
243321

244322
```tact
245323
let two: Int = 2;
246-
two & 1; // 0
247-
4 & 1; // 0
248-
3 & 1; // 1
249-
1 & 1; // 1
250-
255 & 0b00001111; // 15
324+
two > 2; // false
325+
-1 > -3; // true
251326
```
252327

253-
<Callout>
254-
255-
[Bitwise AND - Wikipedia](https://en.wikipedia.org/wiki/Bitwise_operation#AND)\
256-
[Bit manipulation - Wikipedia](https://en.wikipedia.org/wiki/Bit_manipulation)
328+
#### Greater than or equal to, `>=` [#binary-greater-equal]
257329

258-
</Callout>
330+
Binary _greater than or equal to_ operator `>={:tact}` returns `true{:tact}` if the left operand is greater than or to the right operand, and `false{:tact}` otherwise. Can only be applied to values of type [`Int{:tact}`][int]:
259331

260-
#### Bitwise OR, `|` [#binary-bitwise-or]
332+
```tact
333+
let two: Int = 2;
334+
two >= 2; // true
335+
-1 >= -3; // true
336+
```
261337

262-
Binary bar (_bitwise or_) operator `|{:tact}` applies a [bitwise OR](https://en.wikipedia.org/wiki/Bitwise_operation#OR), which performs the [logical OR](#binary-logical-or) operation on each pair of the corresponding bits of operands. This is useful when we want to apply a specific [bitmask](https://en.wikipedia.org/wiki/Mask_(computing)).
338+
#### Less than, `<` [#binary-less]
263339

264-
Can only be applied to values of type [`Int{:tact}`][int]:
340+
Binary _less than_ operator `<{:tact}` returns `true{:tact}` if the left operand is less than the right operand, and `false{:tact}` otherwise. Can only be applied to values of type [`Int{:tact}`][int]:
265341

266342
```tact
267343
let two: Int = 2;
268-
two | 1; // 3
269-
4 | 1; // 5
270-
3 | 1; // 3
271-
1 | 1; // 1
272-
273-
255 | 0b00001111; // 255
274-
0b11110000 | 0b00001111; // 255
344+
two < 2; // false
345+
-1 < -3; // false
275346
```
276347

277-
<Callout>
278-
279-
[Bitwise OR - Wikipedia](https://en.wikipedia.org/wiki/Bitwise_operation#OR)\
280-
[Bit manipulation - Wikipedia](https://en.wikipedia.org/wiki/Bit_manipulation)
281-
282-
</Callout>
348+
#### Less than or equal to, `<=` [#binary-less-equal]
283349

284-
### Comparison [#binary-comparison]
350+
Binary _less than or equal to_ operator `<={:tact}` returns `true{:tact}` if the left operand is less than or equal to the right operand, and `false{:tact}` otherwise. Can only be applied to values of type [`Int{:tact}`][int]:
285351

286-
Perform inequality and equality checks, find bigger, smaller or equal values.
352+
```tact
353+
let two: Int = 2;
354+
two <= 2; // true
355+
-1 <= -3; // false
356+
```
287357

288-
#### Equal and not equal, `==` `!=` [#binary-equality]
358+
### Equality and inequality, `==` `!=` [#binary-equality]
289359

290360
Binary equality (_equal_) operator `=={:tact}` checks whether its two operands are _equal_, returning a result of type [`Bool{:tact}`][bool].
291361

@@ -347,46 +417,82 @@ nullable == anotherNullable; // false
347417
nullable != anotherNullable; // true
348418
```
349419

350-
#### Greater than, `>` [#binary-greater]
420+
### Bitwise AND, `&` [#binary-bitwise-and]
351421

352-
Binary _greater than_ operator `>{:tact}` returns `true{:tact}` if the left operand is greater than the right operand, and `false{:tact}` otherwise. Can only be applied to values of type [`Int{:tact}`][int]:
422+
Binary ampersand (_bitwise AND_) operator `&{:tact}` applies a [bitwise AND](https://en.wikipedia.org/wiki/Bitwise_operation#AND), which performs the [logical AND](#binary-logical-and) operation on each pair of the corresponding bits of operands. This is useful when we want to clear selected bits off a number, where each bit represents an individual flag or a boolean state, which makes it possible to "store" up to $257$ boolean values per integer, as all integers in Tact are $257$-bit signed.
423+
424+
Can only be applied to values of type [`Int{:tact}`][int]:
353425

354426
```tact
355427
let two: Int = 2;
356-
two > 2; // false
357-
-1 > -3; // true
428+
two & 1; // 0
429+
4 & 1; // 0
430+
3 & 1; // 1
431+
1 & 1; // 1
432+
433+
255 & 0b00001111; // 15
434+
0b11110000 & 0b00001111; // 15
358435
```
359436

360-
#### Greater than or equal to, `>=` [#binary-greater-equal]
437+
<Callout>
361438

362-
Binary _greater than or equal to_ operator `>={:tact}` returns `true{:tact}` if the left operand is greater than or to the right operand, and `false{:tact}` otherwise. Can only be applied to values of type [`Int{:tact}`][int]:
439+
[Bitwise AND - Wikipedia](https://en.wikipedia.org/wiki/Bitwise_operation#AND)\
440+
[Bit manipulation - Wikipedia](https://en.wikipedia.org/wiki/Bit_manipulation)
363441

364-
```tact
365-
let two: Int = 2;
366-
two >= 2; // true
367-
-1 >= -3; // true
368-
```
442+
</Callout>
369443

370-
#### Less than, `<` [#binary-less]
444+
### Bitwise XOR, `^` [#binary-bitwise-xor]
371445

372-
Binary _less than_ operator `<{:tact}` returns `true{:tact}` if the left operand is less than the right operand, and `false{:tact}` otherwise. Can only be applied to values of type [`Int{:tact}`][int]:
446+
Binary caret (_bitwise XOR_) operator `^{:tact}` applies a [bitwise XOR](https://en.wikipedia.org/wiki/Bitwise_operation#XOR), which performs the [logical exclusive OR](https://en.wikipedia.org/wiki/Exclusive_or) operation on each pair of the corresponding bits of operands. The result in each position is $1$ if only one of the bits is $1$, but will be $0$ if both are $0$ or both are $1$. In this it performs the comparison of two bits, giving $1$ if the two bits are different, and $0$ if they are the same.
447+
448+
It is useful for inverting selected bits of an operand (also called toggle or flip), as any bit may be toggled by "XORing" it with $1$.
449+
450+
Can only be applied to values of type [`Int{:tact}`][int]:
373451

374452
```tact
375453
let two: Int = 2;
376-
two < 2; // false
377-
-1 < -3; // false
454+
two ^ 3; // 1
455+
4 ^ 1; // 0
456+
3 ^ 1; // 3
457+
1 ^ 1; // 0
458+
459+
255 ^ 0b00001111; // 240
460+
0b11110000 ^ 0b00001111; // 240
378461
```
379462

380-
#### Less than or equal to, `<=` [#binary-less-equal]
463+
<Callout>
381464

382-
Binary _less than or equal to_ operator `<={:tact}` returns `true{:tact}` if the left operand is less than or equal to the right operand, and `false{:tact}` otherwise. Can only be applied to values of type [`Int{:tact}`][int]:
465+
[Bitwise XOR - Wikipedia](https://en.wikipedia.org/wiki/Bitwise_operation#XOR)\
466+
[Bit manipulation - Wikipedia](https://en.wikipedia.org/wiki/Bit_manipulation)
467+
468+
</Callout>
469+
470+
### Bitwise OR, `|` [#binary-bitwise-or]
471+
472+
Binary bar (_bitwise OR_) operator `|{:tact}` applies a [bitwise OR](https://en.wikipedia.org/wiki/Bitwise_operation#OR), which performs the [logical OR](#binary-logical-or) operation on each pair of the corresponding bits of operands. This is useful when we want to apply a specific [bitmask](https://en.wikipedia.org/wiki/Mask_(computing)).
473+
474+
For example, _bitwise OR_ is commonly used in Tact to [combine base modes with optional flags](http://localhost:3000/book/message-mode#combining-modes-with-flags) by masking specific bits to $1$ in order to construct a target [message `mode`](/book/message-mode).
475+
476+
Can only be applied to values of type [`Int{:tact}`][int]:
383477

384478
```tact
385479
let two: Int = 2;
386-
two <= 2; // true
387-
-1 <= -3; // false
480+
two | 1; // 3
481+
4 | 1; // 5
482+
3 | 1; // 3
483+
1 | 1; // 1
484+
485+
255 | 0b00001111; // 255
486+
0b11110000 | 0b00001111; // 255
388487
```
389488

489+
<Callout>
490+
491+
[Bitwise OR - Wikipedia](https://en.wikipedia.org/wiki/Bitwise_operation#OR)\
492+
[Bit manipulation - Wikipedia](https://en.wikipedia.org/wiki/Bit_manipulation)
493+
494+
</Callout>
495+
390496
### Logical AND, `&&` [#binary-logical-and]
391497

392498
Binary logical AND ([logical conjunction](https://en.wikipedia.org/wiki/Logical_conjunction)) operator `&&{:tact}` returns `true{:tact}` if both operands are `true{:tact}`, and `false{:tact}` otherwise. It's short-circuited, meaning that it would immediately evaluate the whole expression as `false{:tact}` if the left operand is `false{:tact}`, without evaluating the right one.
@@ -395,7 +501,7 @@ Can only be applied to values of type [`Bool{:tact}`][bool]:
395501

396502
```tact
397503
let iLikeTact: Bool = true;
398-
iLikeTact && true; // true
504+
iLikeTact && true; // true, evaluated both operands
399505
iLikeTact && false; // false, evaluated both operands
400506
false && iLikeTact; // false, didn't evaluate iLikeTact
401507
```
@@ -408,9 +514,9 @@ Can only be applied to values of type [`Bool{:tact}`][bool]:
408514

409515
```tact
410516
let iLikeSnails: Bool = false;
411-
iLikeSnails && true; // true
412-
iLikeSnails && false; // false, evaluated both operands
413-
true && iLikeSnails; // true, didn't evaluate iLikeSnails
517+
iLikeSnails || true; // true, evaluated both operands
518+
iLikeSnails || false; // false, evaluated both operands
519+
true || iLikeSnails; // true, didn't evaluate iLikeSnails
414520
```
415521

416522
## Ternary, `?:` [#ternary]
@@ -443,7 +549,7 @@ false ? 1 : true ? 2 : 3; // 2
443549
// need additional parentheses for consequence cases (parts in-between ? and :)
444550
false ? (false ? 1 : 2) : 3; // 3
445551
false ? false ? 1 : 2 : 3; // SYNTAX ERROR!
446-
true ? (false ? 1 : 2) : 3; // 2
552+
true ? (false ? 1 : 2) : 3; // 2
447553
```
448554

449555
## Assignment, `=` [#assignment]

0 commit comments

Comments
 (0)