# FunC compiler directives (https://docs-i0yym09dy-ton-core-docs.vercel.app/llms/languages/func/compiler-directives/content.md)



<Callout type="note">
  The official smart contract language of TON Blockchain is [Tolk](/llms/tolk/overview/content.md). FunC is now a **legacy** language, with its compiler no longer maintained.

  Learn how to [migrate from FunC to Tolk](/llms/tolk/from-func/tolk-vs-func/content.md). For new smart contract projects, use the [Acton toolchain](/llms/contract-dev/acton/content.md).
</Callout>

Compiler directives are keywords that begin with `#`, instructing the compiler to perform specific actions, enforce checks, or modify parameters.

These directives can only be used at the outermost level of a source file and cannot be placed inside function definitions.

## `#include` [#include]

The `#include` directive enables the inclusion of another FunC source file parsed in place of the directive.

**Syntax:**

```func
#include "<path_to_filename>";
```

where `<path_to_filename>` is the path to the FunC source file to include.

Files are automatically checked for multiple inclusions.
By default, the compiler will ignore redundant inclusions if the same file is included more than once.
This also applies to inclusions along a path of nested inclusions.
A warning will be issued if the verbosity level is 2 or higher.

For example, suppose that `main.fc` contains the `main` function. Suppose also that `main.fc` includes a file `A.fc`, which in turn includes a file `B.fc`,
which in turn includes `main.fc`. When `main.fc` is compiled, the inclusion of `main.fc` in `B.fc` will be ignored.

If an error occurs while parsing an included file, the compiler displays an inclusion stack, showing the locations of each file in the inclusion chain.

## `#pragma` [#pragma]

The `#pragma` directive provides additional information to the compiler beyond what the language conveys.

### `#pragma` version [#pragma-version]

The `#pragma` version directive enforces using a specific FunC compiler version when compiling the file.

**Syntax:**

```func
#pragma version <op><sem_version>;
```

where `<op>` is an optional [version operator](#operators) that allows to specify a constraint, and `<sem_version>` is specified
in [**semantic versioning (semver)** format](https://en.wikipedia.org/wiki/Software_versioning): *a.b.c*, where:

* *a* is the major version
* *b* is the minor version
* *c* is the patch version

Example:

```func
#pragma version 2.3.4;
#pragma version >2.3.4;
```

The first example does not use an operator and it means that the compiler must have exactly version `2.3.4`.
The second uses the greater than operator `>`, and it means that the compiler must have a version greater
than `2.3.4` (see [precedence](#equality-and-precedence) and [operators](#operators) below for details).

#### Equality and precedence [#equality-and-precedence]

Two versions are **equal** if their respective major, minor, and patch numbers are equal. Two versions are **not equal** if at least one of those numbers differ.

Example:

* *1.2.3* is equal to *1.2.3*
* *3.4.5* is not equal to *3.1.5*

**Precedence** of two versions *a.b.c* and *d.e.f* is determined the following way:

* If *a* is smaller than *d*, then *a.b.c* precedes *d.e.f*
* If *a* is equal to *d*, and *b* is smaller than *e*, then *a.b.c* precedes *d.e.f*
* If *a* is equal to *d*, and *b* is equal to *e*, and *c* is smaller than *f*, then *a.b.c* precedes *d.e.f*

If *a.b.c* precedes *d.e.f*, then it is said that *a.b.c* is smaller than *d.e.f*, or equivalently, that *d.e.f* is greater than *a.b.c*.

Example:

* *1.0.0* precedes *2.0.0*. Equivalently: *1.0.0* is smaller than *2.0.0* or *2.0.0* is greater than *1.0.0*.
* *2.0.0* precedes *2.1.0*. Equivalently: *2.0.0* is smaller than *2.1.0* or *2.1.0* is greater than *2.0.0*.
* *2.1.0* precedes *2.1.1*. Equivalently: *2.1.0* is smaller than *2.1.1* or *2.1.1* is greater than *2.1.0*.

#### Operators [#operators]

Developers can specify version constraints using the following operators:

* *a.b.c&#x2A; or *=a.b.c* - Requires **exactly** version *a.b.c* of the compiler
* *>a.b.c* - Requires the compiler version to be **greater** than &#x2A;a.b.c.*
* *>=a.b.c* - Requires the compiler version to be **greater** than or **equal** to *a.b.c*
* *\<a.b.c* - Requires the compiler version to be **less** than *a.b.c*
* *\<=a.b.c* - Requires the compiler version to be **less** than or **equal** to *a.b.c*
* *^a.b.c* - Requires the major part of the compiler version to be **equal** to the *a* part, the minor to be **equal** to the *b* part, and the patch to be **no lower** than the *c* part
* *^a.b* - Requires the major compiler version to be **equal** to the *a* part and the minor to be **no lower** than the *b* part
* *^a* - Requires the major compiler version to be **no lower** than the *a* part

For the comparison operators &#x2A;=&#x2A;, &#x2A;>&#x2A;, &#x2A;>=&#x2A;, &#x2A;\<&#x2A;, &#x2A;\<=*, omitted parts default to zero.
For example:

* *>a.b&#x2A; is equivalent to *>a.b.0*
* *\<=a&#x2A; is equivalent to *\<=a.0.0*

For the operator ^, omitted parts do **not** default to zero. For example:

* *^a.b&#x2A; is not equivalent to *^a.b.0*
* *^a&#x2A; is not equivalent to *^a.0.0*

Here are some examples of constraints:

* *^5.1.2* matches compiler version *5.1.3* because patch `3` is no lower than patch `2`.
* *^5.1.2* does not match compiler version *5.2.3* because minor `2` does not equal minor `1`.
* *^5.1.2* does not match compiler version *5.1.1* because patch `1` is lower than patch `2`.
* *^5.1* matches compiler version *5.1.3* because minor `1` is no lower than minor `1`.
* *^5.1* matches compiler version *5.2.3* because minor `2` is no lower than minor `1`.
* *^5.1* matches compiler version *5.1.0* because minor `1` is no lower than minor `1`.
* *^5.1* does not match compiler version *5.0.2* because minor `0` is lower than minor `1`.
* *^5* matches compiler version *5.1.0* because major `5` is no lower than major `5`.
* *^5* does not match compiler version *4.1.0* because major `4` is lower than major `5`.
* *>5.1.2* matches compiler version *5.1.3* because patch `3` is bigger than patch `2`.
* *>5.1.2* matches compiler version *5.2.0* because minor `2` is bigger than minor `1`.
* *>5.1.2* matches compiler version *6.0.0* because major `6` is bigger than major `5`.
* *=5.1.2* does not match compiler version *5.2.2* because minor `2` is not equal to minor `1`.

<Callout>
  The `#pragma` version directive can be used multiple times, and the compiler must satisfy all specified constraints.
</Callout>

### `#pragma not-version` [#pragma-not-version]

The `#pragma not-version` is similar to `#pragma version`, but it fails if the specified condition is met.

**Syntax:**

```func
#pragma not-version <op><sem_version>;
```

where `<op>` is an optional [version operator](#operators) that allows to specify a constraint, and `<sem_version>` is identical as
in [`#pragma version`](#%23pragma-version).

This directive is useful for blocking specific compiler versions known to have issues.

Here are some examples:

```func
#pragma not-version >2.1.3;
#pragma not-version ^3.4;
#pragma not-version 1.2.3;
```

In the first example, `not-version >2.1.3` matches any compiler version that is *not* bigger than *2.1.3*, like *2.1.2*, *2.0.5* and even *2.1.3* itself.

In the second example, `not-version ^3.4` matches any compiler version that does *not&#x2A; match *^3.4*, like *3.3.1*, *4.4.0*, and *3.3.9*

In the third example, `not-version 1.2.3` matches any compiler version different from *1.2.3*.

### `#pragma allow-post-modification` [#pragma-allow-post-modification]

*Introduced in FunC v0.4.1*

In Func, using a variable before it is modified within the same [expression](/llms/languages/func/expressions/content.md) is prohibited by default.

For example, the following code will **not** compile, because `ds` is used before it is modified in `ds~load_uint(8)`.
See [modifying notation](/llms/languages/func/expressions/content.md) for more details on using symbol `~`.

```func
(x, y) = (ds, ds~load_uint(8));
```

However, this version is **valid**, since `ds` is used after it is modified:

```func
(x, y) = (ds~load_uint(8), ds)
```

To override this restriction, use `#pragma allow-post-modification`.
This allows variables to be modified after usage in mass assignments and function calls while sub-expressions are still computed **left to right**.

In the following example, `x` will contain the initial value of `ds`, while `y` the modified value of `ds`:

```func
#pragma allow-post-modification
(x, y) = (ds, ds~load_bits(8));
```

<Callout>
  `#pragma allow-post-modification` works only for code after the pragma.
</Callout>

### `#pragma compute-asm-ltr` [#pragma-compute-asm-ltr]

*Introduced in FunC v0.4.1*

`asm` declarations can override the order of argument evaluation. For example, in the following expression:

```func
idict_set_ref(ds~load_dict(), ds~load_uint(8), ds~load_uint(256), ds~load_ref())
```

The evaluation order of the call arguments is:

1. `load_ref()`
2. `load_uint(256)`
3. `load_dict()`
4. `load_uint(8)`

This happens due to the corresponding `asm` declaration:

```func
cell idict_set_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTISETREF";
```

Here, the `asm(value index dict key_len)` notation dictates a [rearrangement of arguments](/llms/languages/func/asm-functions/content.md).

To ensure strict left-to-right computation order of the arguments, use `#pragma compute-asm-ltr`.
With this directive enabled, the same function call:

```func
#pragma compute-asm-ltr
;; ...
idict_set_ref(ds~load_dict(), ds~load_uint(8), ds~load_uint(256), ds~load_ref());
```

will evaluate its arguments in the following order:

1. `load_dict()`
2. `load_uint(8)`
3. `load_uint(256)`
4. `load_ref()`

and only *after* the evaluation of all these arguments, the `asm` rearrangement will occur.

<Callout>
  `#pragma compute-asm-ltr` works only for code after the pragma.
</Callout>
