> ## Documentation Index
> Fetch the complete documentation index at: https://companyname-a7d5b98e-closes-94-guidebook-more.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# FunC functions

export const Aside = ({type = "note", title = "", icon = "", iconType = "regular", children}) => {
  const asideVariants = ["note", "tip", "caution", "danger"];
  const asideComponents = {
    note: {
      outerStyle: "border-sky-500/20 bg-sky-50/50 dark:border-sky-500/30 dark:bg-sky-500/10",
      innerStyle: "text-sky-900 dark:text-sky-200",
      calloutType: "note",
      icon: <svg width="14" height="14" viewBox="0 0 14 14" fill="currentColor" xmlns="http://www.w3.org/2000/svg" className="w-4 h-4 text-sky-500" aria-label="Note">
          <path fill-rule="evenodd" clip-rule="evenodd" d="M7 1.3C10.14 1.3 12.7 3.86 12.7 7C12.7 10.14 10.14 12.7 7 12.7C5.48908 12.6974 4.0408 12.096 2.97241 11.0276C1.90403 9.9592 1.30264 8.51092 1.3 7C1.3 3.86 3.86 1.3 7 1.3ZM7 0C3.14 0 0 3.14 0 7C0 10.86 3.14 14 7 14C10.86 14 14 10.86 14 7C14 3.14 10.86 0 7 0ZM8 3H6V8H8V3ZM8 9H6V11H8V9Z"></path>
        </svg>
    },
    tip: {
      outerStyle: "border-emerald-500/20 bg-emerald-50/50 dark:border-emerald-500/30 dark:bg-emerald-500/10",
      innerStyle: "text-emerald-900 dark:text-emerald-200",
      calloutType: "tip",
      icon: <svg width="11" height="14" viewBox="0 0 11 14" fill="currentColor" xmlns="http://www.w3.org/2000/svg" className="text-emerald-600 dark:text-emerald-400/80 w-3.5 h-auto" aria-label="Tip">
          <path d="M3.12794 12.4232C3.12794 12.5954 3.1776 12.7634 3.27244 12.907L3.74114 13.6095C3.88471 13.8248 4.21067 14 4.46964 14H6.15606C6.41415 14 6.74017 13.825 6.88373 13.6095L7.3508 12.9073C7.43114 12.7859 7.49705 12.569 7.49705 12.4232L7.50055 11.3513H3.12521L3.12794 12.4232ZM5.31288 0C2.52414 0.00875889 0.5 2.26889 0.5 4.78826C0.5 6.00188 0.949566 7.10829 1.69119 7.95492C2.14321 8.47011 2.84901 9.54727 3.11919 10.4557C3.12005 10.4625 3.12175 10.4698 3.12261 10.4771H7.50342C7.50427 10.4698 7.50598 10.463 7.50684 10.4557C7.77688 9.54727 8.48281 8.47011 8.93484 7.95492C9.67728 7.13181 10.1258 6.02703 10.1258 4.78826C10.1258 2.15486 7.9709 0.000106649 5.31288 0ZM7.94902 7.11267C7.52078 7.60079 6.99082 8.37878 6.6077 9.18794H4.02051C3.63739 8.37878 3.10743 7.60079 2.67947 7.11294C2.11997 6.47551 1.8126 5.63599 1.8126 4.78826C1.8126 3.09829 3.12794 1.31944 5.28827 1.3126C7.2435 1.3126 8.81315 2.88226 8.81315 4.78826C8.81315 5.63599 8.50688 6.47551 7.94902 7.11267ZM4.87534 2.18767C3.66939 2.18767 2.68767 3.16939 2.68767 4.37534C2.68767 4.61719 2.88336 4.81288 3.12521 4.81288C3.36705 4.81288 3.56274 4.61599 3.56274 4.37534C3.56274 3.6515 4.1515 3.06274 4.87534 3.06274C5.11719 3.06274 5.31288 2.86727 5.31288 2.62548C5.31288 2.38369 5.11599 2.18767 4.87534 2.18767Z"></path>
        </svg>
    },
    caution: {
      outerStyle: "border-amber-500/20 bg-amber-50/50 dark:border-amber-500/30 dark:bg-amber-500/10",
      innerStyle: "text-amber-900 dark:text-amber-200",
      calloutType: "warning",
      icon: <svg className="flex-none w-5 h-5 text-amber-400 dark:text-amber-300/80" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" aria-label="Warning">
          <path stroke-linecap="round" stroke-linejoin="round" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"></path>
        </svg>
    },
    danger: {
      outerStyle: "border-red-500/20 bg-red-50/50 dark:border-red-500/30 dark:bg-red-500/10",
      innerStyle: "text-red-900 dark:text-red-200",
      calloutType: "danger",
      icon: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor" className="text-red-600 dark:text-red-400/80 w-4 h-4" aria-label="Danger">
          <path d="M17.1 292c-12.9-22.3-12.9-49.7 0-72L105.4 67.1c12.9-22.3 36.6-36 62.4-36l176.6 0c25.7 0 49.5 13.7 62.4 36L494.9 220c12.9 22.3 12.9 49.7 0 72L406.6 444.9c-12.9 22.3-36.6 36-62.4 36l-176.6 0c-25.7 0-49.5-13.7-62.4-36L17.1 292zm41.6-48c-4.3 7.4-4.3 16.6 0 24l88.3 152.9c4.3 7.4 12.2 12 20.8 12l176.6 0c8.6 0 16.5-4.6 20.8-12L453.4 268c4.3-7.4 4.3-16.6 0-24L365.1 91.1c-4.3-7.4-12.2-12-20.8-12l-176.6 0c-8.6 0-16.5 4.6-20.8 12L58.6 244zM256 128c13.3 0 24 10.7 24 24l0 112c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-112c0-13.3 10.7-24 24-24zM224 352a32 32 0 1 1 64 0 32 32 0 1 1 -64 0z"></path>
        </svg>
    }
  };
  let variant = type;
  let gotInvalidVariant = false;
  if (!asideVariants.includes(type)) {
    gotInvalidVariant = true;
    variant = "danger";
  }
  const iconVariants = ["regular", "solid", "light", "thin", "sharp-solid", "duotone", "brands"];
  if (!iconVariants.includes(iconType)) {
    iconType = "regular";
  }
  return <>
      <div className={`callout my-4 px-5 py-4 overflow-hidden rounded-2xl flex gap-3 border ${asideComponents[variant].outerStyle}`} data-callout-type={asideComponents[variant].calloutType}>
        <div className="mt-0.5 w-4" data-component-part="callout-icon">
          {}
          {icon === "" ? asideComponents[variant].icon : <Icon icon={icon} iconType={iconType} size={14} />}
        </div>
        <div className={`text-sm prose min-w-0 w-full ${asideComponents[variant].innerStyle}`} data-component-part="callout-content">
          {gotInvalidVariant ? <p>
              <span className="font-bold">
                Invalid <code>type</code> passed!
              </span>
              <br />
              <span className="font-bold">Received: </span>
              {type}
              <br />
              <span className="font-bold">Expected one of: </span>
              {asideVariants.join(", ")}
            </p> : <>
              {title && <p className="font-bold">{title}</p>}
              {children}
            </>}
        </div>
      </div>
    </>;
};

A FunC program is a list of function declarations, function definitions, and global variable declarations. This section focuses on function declarations and definitions.

Every function declaration or definition follows a common pattern, after which one of three elements appears:

* A single semicolon `;` indicates that the function is declared but not yet defined. Its definition must appear later in the same file or a different file processed before the current one by the FunC compiler. For example:
  ```func theme={null}
  int add(int x, int y);
  ```
  This declares a function named `add` with the type `(int, int) → int` but does not define it.

* An assembler function body definition defines the function using low-level TVM primitives for use in a FunC program. For example:
  ```func theme={null}
  int add(int x, int y) asm "ADD";
  ```
  This defines the function `add` using the TVM opcode `ADD`, keeping its type as `(int, int) → int`.

* A standard function body uses a block statement, the most common way to define functions. For example:
  ```func theme={null}
  int add(int x, int y) {
    return x + y;
  }
  ```
  This is a standard definition of the `add` function.

## Function declaration

As mentioned earlier, every function declaration or definition follows a common pattern. The general form is:

```func theme={null}
[<forall declarator>] <return_type> <function_name>(<comma_separated_function_args>) <specifiers>
```

where `[ ... ]` represents an optional entry.

### Function name

A function name can be any valid [identifier](/languages/func/literals#identifiers). Additionally, it may start with the symbols `.` or `~`, which have specific meanings explained in the [Statements](/languages/func/statements#methods-calls) section.

For example, `udict_add_builder?`, `dict_set`, and `~dict_set` are all valid function names, and each is distinct. These functions are defined in [stdlib.fc](/languages/func/stdlib).

#### Special function names

FunC (specifically, the Fift assembler) reserves several function names with predefined [IDs](/languages/func/functions#method_id):

* `main` and `recv_internal` have `id = 0`
* `recv_external` has `id = -1`
* `run_ticktock` has `id = -2`

Every program must include a function with `id = 0`, meaning it must define either `main` or `recv_internal`.The `run_ticktock` function is used in ticktock transactions of special smart contracts.

#### Receive internal

The `recv_internal` function is invoked when a smart contract receives **an inbound internal message**. When the [TVM initializes](/tvm/initialization), certain variables are automatically placed on the stack. By specifying arguments in `recv_internal`, the smart contract can access some of these values. Any values not explicitly referenced in the function parameters will remain unused at the bottom of the stack.

The following `recv_internal` function declarations are all valid. Functions with fewer parameters consume slightly less gas, as each unused argument results in an additional `DROP` instruction:

```func theme={null}

() recv_internal(int balance, int msg_value, cell in_msg_cell, slice in_msg) {}
() recv_internal(int msg_value, cell in_msg_cell, slice in_msg) {}
() recv_internal(cell in_msg_cell, slice in_msg) {}
() recv_internal(slice in_msg) {}
```

#### Receive external

The `recv_external` function handles **inbound external messages**.

### Return type

The return type can be any atomic or composite type, as described in the [Types](/languages/func/types) section. For example, the following function declarations are valid:

```func theme={null}
int foo();
(int, int) foo'();
[int, int] foo''();
(int → int) foo'''();
() foo''''();
```

FunC also supports **type inference**. For example:

```func theme={null}
_ pyth(int m, int n) {
  return (m * m - n * n, 2 * m * n, m * m + n * n);
}
```

This is a valid definition of the function `pyth`, which has the inferred type `(int, int) → (int, int, int)`.
It computes Pythagorean triples based on the given input values.

### Function arguments

In function arguments, commas separate it. The following types of argument declarations are valid:

* Ordinary declaration: an argument is declared using **its type** followed by **its name**. Example: `int x` declares an argument named `x` of type `int` in the function declaration: `() foo(int x);`.

* Unused argument declaration: only its type needs to be specified. Example:
  ```func theme={null}
  int first(int x, int) {
    return x;
  }
  ```
  This is a valid function definition of type `(int, int) → int`.

* Argument with inferred type declaration: If an argument's type is not explicitly declared, it is inferred by the type-checker.
  For example,
  ```func theme={null}
  int inc(x) {
    return x + 1;
  }
  ```
  This defines a function `inc` with the inferred type `int → int`, meaning `x` is automatically recognized as an `int`.

**Argument tensor representation**

Even though a function may appear to take multiple arguments, it takes a single [tensor-type](/languages/func/types#tensor-types) argument. For more details on this distinction, refer to the [Function application](/languages/func/statements#function-application) section.
However, for convenience, the individual components of this tensor are conventionally referred to as "function arguments."

### Function calls

#### Non-modifying methods

<Aside>
  A non-modifying function supports a shorthand method call syntax using `.`
</Aside>

```func theme={null}
example(a);
a.example();
```

A function with at least **one argument**, it can be called a **non-modifying method**. For example, the function `store_uint` has the type `(builder, int, int) → builder`, where:

* The second argument is the value to store.
* The third argument is the bit length.

The function `begin_cell` creates a new `builder`. The following two code snippets are equivalent:

```func theme={null}
builder b = begin_cell();
b = store_uint(b, 239, 8);
```

```func theme={null}
builder b = begin_cell();
b = b.store_uint(239, 8);
```

So the first argument of a function can be passed to it being located before the function name, if separated by `.`. The code can be further simplified:

The function's first argument is passed before the function name, separated by `.`. The syntax can be further condensed into a single statement:

```func theme={null}
builder b = begin_cell().store_uint(239, 8);
```

It is also possible to chain multiple method calls:

```func theme={null}
builder b = begin_cell().store_uint(239, 8)
                        .store_int(-1, 16)
                        .store_uint(0xff, 10);
```

#### Modifying functions

<Aside>
  A modifying function supports a short form using the `~` and `.` operators.
</Aside>

If:

* The first argument of a function has type `A`.
* The function's return type is `(A, B)`, where `B` is any arbitrary type.

Then, the function can be called a modifying method.

Modifying functions change their first argument. They assign the first component of the returned value to the variable initially passed as the first argument.
The following calls are equivalent:

```func theme={null}
a~example(); ;;Modifying method syntax
a = example(a); ;;Standard function call
```

**Example:** `load_uint`

Suppose `cs` is a cell slice, and `load_uint` has type `(slice, int) → (slice, int)`. It means:

* `load_uint` takes a cell slice and several bits to load.
* It returns the remaining slice and the loaded value.

The following calls are equivalent:

```func theme={null}
(cs, int x) = load_uint(cs, 8); ;; Standard function call
```

```func theme={null}
(cs, int x) = cs.load_uint(8); ;; Method call syntax
```

```func theme={null}
int x = cs~load_uint(8); ;; Modifying method syntax
```

**Modifying methods with no return value**

Sometimes, a function only modifies its first argument without returning a meaningful value. To enable modifying method syntax, such functions should return a unit type () as the second component.

For example, suppose we want to define a function `inc` of type `int → int`, which increments an integer. To use it as a modifying method, we define it as follows:

```func theme={null}
(int, ()) inc(int x) {
  return (x + 1, ());
}
```

Now, the function can be used in modifying method syntax:

```func theme={null}
x~inc(); ;;Equivalent to x = inc(x);
```

This will increment `x` in place.

#### `.` and `~` in function names

Suppose we want to use `inc` as a non-modifying method. We can write:

```func theme={null}
(int y, _) = inc(x);
```

However, we can also define `inc` as a modifying method:

```func theme={null}
int inc(int x) {
  return x + 1;
}
(int, ()) ~inc(int x) {
  return (x + 1, ());
}
```

Now, we can call it in different ways:

```func theme={null}
x~inc(); ;; Modifies x
int y = inc(x); ;; Doesn't modify x
int z = x.inc(); ;; Also doesn't modify x
```

**How FunC resolves function calls**

* If a function is called with `.` (e.g., `x.foo()`), the compiler looks for a `.foo` definition.
* If a function is called with `~` (e.g., `x~foo()`), the compiler looks for a `~foo` definition.
* If neither `.foo` nor `~foo` is defined, the compiler falls back to the regular `foo` definition.

### Specifiers

In FunC, function specifiers modify the behavior of functions. There are three types:

1. `impure`
2. `inline`/ `inline_ref`
3. `method_id`

One, multiple, or none can be used in a function declaration. However, they must appear in a specific order (e.g., `impure` must come before `inline`).

#### `impure` specifier

The `impure` specifier indicates that a function has side effects, such as modifying contract storage, sending messages, or throwing exceptions.
If a function is not marked as `impure` and its result is unused, the FunC compiler may delete the function call for optimization.

For example, in the [stdlib.fc](/languages/func/stdlib) function:

```func theme={null}
int random() impure asm "RANDU256";
```

Here, `RANDU256` changes the internal state of the random number generator. The `impure` keyword prevents the compiler from removing this function call.

#### `inline` specifier

A function marked as `inline` is directly substituted into the code wherever it is called.
Recursive calls are not allowed for inline functions.

**Example**

```func theme={null}
(int) add(int a, int b) inline {
    return a + b;
}
```

Since the `add` function is marked with the `inline` specifier, the compiler substitutes `add(a, b)` with `a + b` directly in the code, eliminating the function call overhead.

Another example of using `inline` from [ICO-Minter.fc](https://github.com/ton-blockchain/token-contract/blob/f2253cb0f0e1ae0974d7dc0cef3a62cb6e19f806/ft/jetton-minter-ICO.fc#L16):

```func theme={null}
() save_data(int total_supply, slice admin_address, cell content, cell jetton_wallet_code) impure inline {
  set_data(begin_cell()
            .store_coins(total_supply)
            .store_slice(admin_address)
            .store_ref(content)
            .store_ref(jetton_wallet_code)
           .end_cell()
          );
}
```

#### `inline_ref` specifier

When a function is marked with the `inline_ref` specifier, its code is stored in a separate cell. Each time the function is called, TVM executes a `CALLREF` command. This works similarly to `inline`, but with a key difference—since the same cell can be reused multiple times without duplication, `inline_ref` is generally more efficient regarding code size. The only case where `inline` might be preferable is if the function is called just once. However, recursive calls to `inline_ref` functions remain impossible, as TVM cells do not support cyclic references.

#### `method_id`

In a TVM program, every function has an internal integer ID that determines how it can be called.
By default, ordinary functions are assigned sequential numbers starting from `1`, while contract get-methods use `crc16` hashes of their names.
The `method_id(<some_number>)` specifier allows you to set a function's ID to a specific value manually.
If no ID is specified, the default is calculated as `(crc16(<function_name>) & 0xffff) | 0x10000`.
If a function has the `method_id` specifier, it can be invoked by its name as a get-method in lite client or TON explorer.

<Aside type="caution" title="Important limitations and recommendations">
  **19-bit limitation**: Method IDs are limited to 19 bits by the TVM assembler, meaning the valid range is **0 to 524,287** (2^19 - 1).

  **Reserved ranges**:

  * **0-999**: Reserved for system functions (approximate range)
  * **Special functions**: `main`/`recv_internal` (id=0), `recv_external` (id=-1), `run_ticktock` (id=-2)
  * **65536+**: Default range for user functions when using automatic generation `(crc16() & 0xffff) | 0x10000`

  **Best practice**: It's recommended to **avoid setting method IDs manually** and rely on automatic generation instead. Manual assignment can lead to conflicts and unexpected behavior.
</Aside>

<details>
  <summary><b>Technical details regarding `method_id` parsing</b></summary>

  While the FunC compiler can initially accept larger hex values during parsing, the actual limitation comes from the TVM assembler which restricts method IDs to 19 bits (`@procdictkeylen = 19` in Asm.fif).

  The parsing of the hexadecimal string for `method_id` is handled by functions in `crypto/common/bigint.hpp` (specifically `AnyIntView::parse_hex_any` called via `td::string_to_int256` and `BigInt<257>::parse_hex`).

  `AnyIntView::parse_hex_any` first performs a basic check on the length of the hex string:

  ```cpp theme={null}
  if ((j - i - (p > 0)) * 4 > (max_size() - 1) * word_shift + word_bits - 2) {
    return 0; // Invalid if too long
  }
  ```

  For `BigInt<257>` (which is `td::BigIntG<257, td::BigIntInfo>`):

  * `Tr` is `BigIntInfo`.
  * `word_bits` (bits in a word) is 64.
  * `word_shift` (effective bits used per word in normalization) is 52. (Source: `crypto/common/bigint.hpp`)
  * `max_size()` (maximum words for `BigInt<257>`) is `(257 + 52 - 1) / 52 + 1 = 6` words.

  Let's plug these values into the length check formula:
  `(max_size() - 1) * word_shift + word_bits - 2`
  `(6 - 1) * 52 + 64 - 2 = 5 * 52 + 62 = 260 + 62 = 322` bits.

  A 65-character hex string represents ( 65 times 4 = 260 ) bits.
  The calculated bit limit for the quick check is 322 bits. Since `260` is not greater than `322`, such a number (65 hex digits) can *pass* this initial length check. This check is designed to quickly reject inputs that are grossly too large. The `-2` offers a slight margin.

  After this initial parsing into internal `digits_`, `parse_hex_any` calls `normalize_bool_any()`. This function converts the internal representation into a canonical signed form.
  If `normalize_bool_any()` returns `false`, it indicates an overflow during this canonicalization. This can happen even if the number passed the initial length check, for example, if a carry propagates such that it requires more than `max_size()` words to represent in the specific signed format, or if the most significant word itself overflows. In such a case, `parse_hex_any` invalidates the `BigInt` and returns `0`, leading to `td::string_to_int256` returning a `null RefInt256` and FunC reporting an "invalid integer constant".
</details>

**Example**

```func theme={null}
int get_counter() method_id {
  load_data();
  return ctx_counter;
}
```

### Polymorphism with forall

Before any function declaration or definition, there can be `forall` type variables declarator. It has the following syntax:

A function definition can include a `forall` type variable declaration before its declaration or implementation. The syntax is:

```func theme={null}
forall <comma_separated_type_variables_names> ->
```

Here, type variable names can be any [identifier](/languages/func/literals#identifiers) but are typically written in capital letters.

For example,

```func theme={null}
forall X, Y -> [Y, X] pair_swap([X, Y] pair) {
  [X p1, Y p2] = pair;
  return [p2, p1];
}
```

This function takes a tuple of exactly two elements, where each component can be of any type that fits in a single stack entry. It swaps the two values. For instance:

* `pair_swap([2, 3])` returns `[3, 2]`;
* `pair_swap([1, [2, 3, 4]])` returns `[[2, 3, 4], 1]`.

In this example, `X` and `Y` are [type variables](/languages/func/types#polymorphism-with-type-variables). When the function is called, these variables are replaced with actual types, and the function executes accordingly. Even though the function is polymorphic, the compiled assembly code remains the same for any type substitution. This is possible due to the polymorphic nature of stack manipulation operations. However, other forms of polymorphism, such as `ad-hoc` polymorphism with type classes, are not currently supported.

It is important to note that `X` and `Y` must each have a type width of 1, meaning they should fit within a single stack entry. This means you can't use `pair_swap` on a tuple like `[(int, int), int]` because type `(int, int)` has a width of 2, taking up two stack entries instead of one.

## Assembler function body definition

In FunC, functions can be defined directly using assembler code. This is done using the `asm` keyword, followed by one or more assembler commands written as strings.
For example, the following function increments an integer and then negates it:

```func theme={null}
int inc_then_negate(int x) asm "INC" "NEGATE";
```

– a function that increments an integer and then negates it. Calls to this function will be translated to 2 assembler commands `INC` and `NEGATE`. An alternative way to define the function is:

When called, this function is directly translated into the two assembler commands, `INC` and `NEGATE`.
Alternatively, the function can be written as:

```func theme={null}
int inc_then_negate'(int x) asm "INC NEGATE";
```

Here, `INC NEGATE` is treated as a single assembler command by FunC, but the Fift assembler correctly interprets it as two separate commands.

<Aside>
  The list of assembler commands can be found here: [TVM instructions](/tvm/instructions).
</Aside>

### Rearranging stack entries

Sometimes, the order in which function arguments are passed may not match the expected order of an assembler command. Similarly, the returned values may need to be arranged differently. While this can be done manually using stack manipulation primitives, FunC automatically handles it.

<Aside>
  When manually rearranging arguments, they are computed in the new order. To overwrite this behavior use [`#pragma compute-asm-ltr`](/languages/func/compiler-directives#pragma-compute-asm-ltr).
</Aside>

For instance, the assembler command `STUXQ` takes an integer, a builder, and another integer as input. It then returns the builder and an integer flag indicating whether the operation succeeded. We can define the corresponding function as follows:

```func theme={null}
(builder, int) store_uint_quite(int x, builder b, int len) asm "STUXQ";
```

However, if we need to rearrange the order of arguments, we can specify them explicitly in the `asm` declaration:

```func theme={null}
(builder, int) store_uint_quite(builder b, int x, int len) asm(x b len) "STUXQ";
```

So you can indicate the required order of arguments after the `asm` keyword.

This allows us to control the order in which arguments are passed to the assembler command.

Similarly, we can rearrange return values using the following notation:

```func theme={null}
(int, builder) store_uint_quite(int x, builder b, int len) asm( -> 1 0) "STUXQ";
```

Here, the numbers indicate the order of return values, where `0` represents the deepest stack entry.

Additionally, we can combine these techniques:

```func theme={null}
(int, builder) store_uint_quite(builder b, int x, int len) asm(x b len -> 1 0) "STUXQ";
```

### Multi-line asms

Multi-line assembler commands, including Fift code snippets, can be defined using triple-quoted strings `"""`.

```func theme={null}
slice hello_world() asm """
  "Hello"
  " "
  "World"
  $+ $+ $>s
  PUSHSLICE
""";
```
