Skip to content

Commit

Permalink
feat(docs): asm functions (#1061)
Browse files Browse the repository at this point in the history
* fix(docs): correct function signatures

https://github.com/tact-lang/tact-docs/issues/368

* fix(docs): "mutable" -> "mutation" functions

https://github.com/tact-lang/tact-docs/issues/374

* feat(docs): rewrote the method ID section to remove logical jumps and make it more streamlined

* chore: retroactive CHANGELOG edit

* feat: described the stack, described Tact-flavored assembly

* fix: add note that Tact assembly will be available in v1.6
  • Loading branch information
novusnota authored Dec 20, 2024
1 parent cffb53f commit 70f5a70
Show file tree
Hide file tree
Showing 12 changed files with 2,199 additions and 1,527 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Fixed

- `asm` functions now support full range of Fift-asm syntax: PR [#855](https://github.com/tact-lang/tact/pull/855)
- `asm` functions now support full range of Fift-asm syntax: PR [#855](https://github.com/tact-lang/tact/pull/855), PR [#1061](https://github.com/tact-lang/tact/pull/1061)

- Fix `npm` installations of Tact compiler or any of the packages depending on it by hiding unnecessary post-install runs of `husky`: PR [#870](https://github.com/tact-lang/tact/pull/870)

Expand Down
1 change: 1 addition & 0 deletions docs/astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ export default defineConfig({
{ slug: 'book/statements' },
{ slug: 'book/constants' },
{ slug: 'book/functions' },
{ slug: 'book/assembly-functions' },
{
label: 'Communication',
translations: { 'zh-CN': '交流' },
Expand Down
44 changes: 4 additions & 40 deletions docs/cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,8 @@
],
"dictionaries": ["fift-words", "tvm-instructions"],
"words": [
"ADDRAND",
"BBITS",
"BREFS",
"Brujin",
"bocchi",
"Cheatsheet",
"Cheatsheets",
"Comptime",
Expand All @@ -37,76 +35,42 @@
"Komarov",
"Korshakov",
"Laika",
"MYADDR",
"Masterchain",
"Merkle",
"NEWC",
"Neovim",
"Nonterminal",
"Novus",
"Offchain",
"Offchain",
"PLDDICT",
"PLDIX",
"PLDREF",
"PLDSLICEX",
"PLDUX",
"POSIX",
"PUSHINT",
"PUSHREF",
"PUSHSLICE",
"Parens",
"RANDU",
"RAWRESERVE",
"RAWRESERVE",
"REWRITESTDADDR",
"REWRITEVARADDR",
"SBITS",
"SDBEGINSQ",
"SDEMPTY",
"SDSKIPFIRST",
"SEMPTY",
"SENDMSG",
"SENDRAWMSG",
"SETCONTARGS",
"SETINDEXVARQ",
"SETNUMARGS",
"SREFS",
"SREMPTY",
"STBR",
"STDICT",
"STIX",
"STON.fi",
"STOPTREF",
"STREF",
"STSLICER",
"STUX",
"STVARUINT",
"Satoshi",
"Seamus",
"Sedov",
"Stateinit",
"Ston",
"Stonfi",
"Sánchez",
"THROWIFNOT",
"TIMELOCK",
"Tactina",
"Tarjan",
"Timeouted",
"Toncoin",
"Toncoins",
"Topup",
"Trunov",
"UBITSIZE",
"Uninit",
"alnum",
"assgn",
"astrojs",
"augmentedassign",
"babecafe",
"basechain",
"basechain",
"bitcode",
"bitstring",
"bitstrings",
"blockstore",
"bounceable",
"bounceable",
Expand Down
2 changes: 1 addition & 1 deletion docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"dependencies": {
"@astrojs/check": "0.9.4",
"@astrojs/markdown-remark": "5.3.0",
"@astrojs/starlight": "0.28.4",
"@astrojs/starlight": "0.29.3",
"astro": "4.16.18",
"cspell": "^8.14.4",
"hast-util-to-string": "^3.0.0",
Expand Down
657 changes: 657 additions & 0 deletions docs/src/content/docs/book/assembly-functions.mdx

Large diffs are not rendered by default.

22 changes: 11 additions & 11 deletions docs/src/content/docs/book/exit-codes.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ This is an alternative exit code for the successful execution of the [compute ph

### 2: Stack underflow {#2}

If some operation consumed more elements than there were on the stacks, the error with exit code $2$ is thrown: `Stack underflow`.
If some operation consumed more elements than there were on the stack, the error with exit code $2$ is thrown: `Stack underflow`.

```tact
asm fun drop() { DROP }
Expand All @@ -153,17 +153,17 @@ contract Loot {

### 3: Stack overflow {#3}

If there are too many elements copied into a closure continuation or stored on the stack, an error with exit code $3$ is thrown: `Stack overflow`. Occurs rarely, unless you're deep in [Fift and TVM assembly](https://docs.ton.org/develop/fift/fift-and-tvm-assembly) trenches:
If there are too many elements copied into a closure continuation, an error with exit code $3$ is thrown: `Stack overflow`. Occurs rarely, unless you're deep in [Fift and TVM assembly](https://docs.ton.org/develop/fift/fift-and-tvm-assembly) trenches:

```tact
// Remember kids, don't try to overflow the stack at home!
asm fun stackOverflow() {
<{
}>CONT // c
0 SETNUMARGS // c'
2 PUSHINT // c' 2
SWAP // 2 c'
1 -1 SETCONTARGS // <- this blows up
x{} SLICE // s
BLESS // c
0 SETNUMARGS // c'
2 PUSHINT // c' 2
SWAP // 2 c'
1 -1 SETCONTARGS // this blows up
}
contract ItsSoOver {
Expand Down Expand Up @@ -242,11 +242,11 @@ try {

### 6: Invalid opcode {#6}

If you specify an instruction that is not defined in the current [TVM][tvm] version, an error with exit code $6$ is thrown: `Invalid opcode`.
If you specify an instruction that is not defined in the current [TVM][tvm] version or try to set an unsupported [code page](https://docs.ton.org/v3/documentation/tvm/tvm-overview#tvm-state), an error with exit code $6$ is thrown: `Invalid opcode`.

```tact
// No such thing
asm fun invalidOpcode() { x{D7FF} @addop }
// There's no such codepage, and attempt to set it fails
asm fun invalidOpcode() { 42 SETCP }
contract OpOp {
receive("I solemnly swear that I'm up to no good") {
Expand Down
42 changes: 25 additions & 17 deletions docs/src/content/docs/book/functions.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ Functions in Tact could be defined in different ways:

* Global static function
* Extension functions
* Mutable functions
* Mutation functions
* Native functions
* [Assembly functions](#asm)
* [Internal functions](/book/contracts#internal-functions)
* Receiver functions
* Getter functions

Expand Down Expand Up @@ -85,9 +87,9 @@ extends fun customPow(self: Int, c: Int): Int {
}
```

## Mutable functions
## Mutation functions

Mutable functions are performing mutation of a value replacing it with an execution result. To perform mutation, the function must change the `self` value.
Mutation functions are performing mutation of a value replacing it with an execution result. To perform mutation, the function must change the `self` value.

```tact
extends mutates fun customPow(self: Int, c: Int) {
Expand All @@ -104,7 +106,7 @@ extends mutates fun customPow(self: Int, c: Int) {
Native functions are direct bindings of FunC functions:

> **Note**
> Native functions could be also mutable and extension ones.
> Native functions could also be mutation and extension ones.
```tact
@name(store_uint)
Expand All @@ -114,6 +116,12 @@ native storeUint(s: Builder, value: Int, bits: Int): Builder;
extends mutates native loadInt(self: Slice, l: Int): Int;
```

## Assembly functions, `asm` {#asm}

<Badge text="Available since Tact 1.5" variant="tip" size="medium"/><p/>

Read more about them on their dedicated page: [Assembly functions](/book/assembly-functions).

## Receiver functions

Receiver functions are special functions that are responsible for receiving messages in contracts and could be defined only within a contract or trait.
Expand Down Expand Up @@ -144,32 +152,32 @@ contract Treasure {

<Badge text="Available since Tact 1.6" variant="tip" size="medium"/><p/>

As other functions in TVM contracts, getters have their *unique* associated function selectors which are some integers ids (called *method IDs*).
Some of those integers are reserved for internal purposes, e.g. -4, -3, -2, -1, 0 are reserved IDs and
regular functions (internal to a contract and not callable from outside) are usually numbered by subsequent (small) integers starting from 1.
By default, getters have associated method IDs that are derived from their names using the [CRC16](https://en.wikipedia.org/wiki/Cyclic_redundancy_check) algorithm as follows:
`crc16(<function_name>) & 0xffff) | 0x10000`.
Sometimes this can get you the same method ID for getters with different names.
If this happens, you can either rename some of the contract's getters or
specify the getter's method ID manually as a compile-time expression like so:
Like other functions in TON contracts, getters have their _unique_ associated function selectors, which are $19$-bit signed integer identifiers commonly called _method IDs_.

Method IDs of getters are derived from their names using the [CRC16](https://en.wikipedia.org/wiki/Cyclic_redundancy_check) algorithm as follows: `(crc16(<function_name>) & 0xffff) | 0x10000`. In addition, Tact compiler conditionally reserves some method IDs for use in [getters of supported interfaces](/book/contracts#interfaces), namely: $113617$ for `supported_interfaces`, $115390$ for `lazy_deployment_completed`, and $121275$ for `get_abi_ipfs`.

Sometimes, getters with different names end up with the same method ID. If this happens, you can either rename some of the getters or manually specify the method ID as a [compile-time](/ref/core-comptime) expression like so:

```tact
contract ManualMethodId {
const methodId: Int = 16384 + 42;
get(self.methodId) fun methodId1(): Int {
get(self.methodId)
fun methodId1(): Int {
return self.methodId;
}
get(crc32("crc32") + 42 & 0x3ffff | 0x4000)
fun methodId2(): Int {
return 0;
return crc32("crc32") + 42 & 0x3ffff | 0x4000;
}
}
```

Note that you *cannot* use method IDs that are reserved by TVM and you cannot use some initial positive integers because those will be used as function selectors by the compiler.
Unlike getters, method IDs for [internal functions](/book/contracts#internal-functions) and some special functions are obtained sequentially: integers in the inclusive range from $-4$ to $0$ are given to [certain message handlers](https://docs.ton.org/v3/documentation/smart-contracts/func/docs/functions#special-function-names), while internal functions are numbered with method IDs starting at $1$ and going up to $2^{14} - 1$ inclusive.

User-specified method IDs are 19-bit signed integers, so you can use integers from $-2^{18}$ to $-5$ and from $2^{14}$ to $2^{18} - 1$.
Since method IDs are $19$-bit signed integers and some of them are reserved, only the inclusive ranges from $-2^{18}$ to $-5$ and from $2^{14}$ to $2^{18} - 1$ are free to be used by users. To avoid collisions, it's recommended to specify method IDs only in these ranges, avoiding the method IDs of Tact-specific getters mentioned above.

Also, a few method IDs are reserved for the usage by the getters the Tact compiler can insert during compilation, those are 113617, 115390, 121275.
[p]: /book/types#primitive-types
[struct]: /book/structs-and-messages#structs
[slice]: /book/cells#slices
4 changes: 2 additions & 2 deletions docs/src/content/docs/book/import.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Additionally, Tact compiler has a versatile set of standard libraries, which com

:::caution

NOTE: All imported code is combined together with yours, so it's important to avoid name collisions and always double-check the sources!
All imported code is combined together with yours, so it's important to avoid name collisions and always double-check the sources!

:::

Expand Down Expand Up @@ -39,7 +39,7 @@ import "./relative/path/to/the/target/func/file.fc";
import "../subfolder/imported/func/file.fc";
```

But in order to use functions from such file, one has to declare them as `native` functions first. For example, when standard library [@stdlib/dns](/ref/stdlib-dns) uses a `dns.fc` FunC file, it maps FunC functions to Tact ones like so:
But in order to use functions from such file, one has to declare them as `native` functions first. For example, when standard library [`@stdlib/dns`](/ref/stdlib-dns) uses a `dns.fc` FunC file, it maps FunC functions to Tact ones like so:

```tact
// FunC code located in a file right next to the current Tact one:
Expand Down
6 changes: 3 additions & 3 deletions docs/src/content/docs/ref/core-cells.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ Usage example:

```tact
let b: Builder = beginCell();
let fizz: Builder = b.storeUint(42, 7);
let fizz: Builder = b.storeInt(42, 7);
```

## Builder.storeBool
Expand Down Expand Up @@ -960,7 +960,7 @@ fun cautiousParse(payload: Cell): GuessCoin? {
## Struct.fromSlice

```tact
extends fun fromSlice(self: Struct, cell: Slice): Struct;
extends fun fromSlice(self: Struct, slice: Slice): Struct;
```

Extension function for any structure type [Struct][struct].
Expand Down Expand Up @@ -1084,7 +1084,7 @@ fun cautiousParse(payload: Cell): TripleAxe? {


```tact
extends fun fromSlice(self: Message, cell: Slice): Message;
extends fun fromSlice(self: Message, slice: Slice): Message;
```

Extension function for any message type [Message][message].
Expand Down
2 changes: 1 addition & 1 deletion docs/src/content/docs/ref/core-comptime.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ description: "Various compile-time global functions from the Core library of Tac

import { Badge } from '@astrojs/starlight/components';

This page lists all the built-in [global static functions](/book/functions#global-static-functions), which are evaluated at the time of building the Tact project and cannot work with non-constant, run-time data. These functions are commonly referred to as "compile-time functions".
This page lists all the built-in [global static functions](/book/functions#global-static-functions), which are evaluated at the time of building the Tact project and cannot work with non-constant, run-time data. These functions are commonly referred to as "compile-time functions" or _comptime_ functions for short.

## address

Expand Down
25 changes: 9 additions & 16 deletions docs/src/content/docs/ref/core-debug.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,7 @@ description: "Various debugging functions from the Core library of Tact"

List of functions commonly used for debugging smart contracts in Tact.

:::note

Read more about debugging on the dedicated page: [Debugging](/book/debug).

:::
Read more about debugging on the dedicated page: [Debugging](/book/debug).

## require

Expand Down Expand Up @@ -110,24 +106,21 @@ dump(emit("msg".asComment())); // As emit() function doesn't return a value, dum
fun dumpStack();
```

Prints all the values of [persistent state variables](/book/contracts#variables) to the contract's debug console. Evaluated only if the `debug` option in the [configuration file](/book/config) is set to `true{:json}`, otherwise does nothing.
Prints the total stack depth and up to $255$ of its values from the top to the contract's debug console. The values are positioned bottom-up: from the deepest value on the left to the topmost value on the right. Evaluated only if the `debug` option in the [configuration file](/book/config) is set to `true{:json}`, otherwise does nothing.

Usage example:

```tact {6}
contract DumpsterFire {
var1: Int = 0;
var2: Int = 5;
receive() {
dumpStack(); // would print 0 5
}
}
```tact
dumpStack(); // prints:
// File filename.tact:1:1
// dumpStack()
// stack(3 values) : 100000000 C{96...C7} 0
```

:::note[Useful links:]

[Debug with `dump(){:tact}`](/book/debug#tests-dump)
[Debug with `dump(){:tact}`](/book/debug#tests-dump)\
[Assembly functions](/book/assembly-functions)

:::

Expand Down
Loading

0 comments on commit 70f5a70

Please sign in to comment.