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

# FunC functions

export const Image = ({src, darkSrc, alt = '', darkAlt, href, target, height = 342, width = 608, noZoom = false, center = false}) => {
  const isSVG = src.match(/\.svg(?:[#?].*?)?$/i) !== null;
  const shouldInvert = isSVG && !darkSrc;
  const shouldCreateLink = href !== undefined;
  const minPx = 9;
  const maxPx = 608;
  const expectedPx = `a number or a string with a number that is greater than ${minPx - 1} and less than or equal to ${maxPx}`;
  const createInvalidPropCallout = (title, received, expected) => {
    return <Danger>
        <span className="font-bold">
          Invalid <code>{title.toString()}</code> passed!
        </span>
        <br />
        <span className="font-bold">Received: </span>
        {received.toString()}
        <br />
        <span className="font-bold">Expected: </span>
        {expected.toString()}
        {}
      </Danger>;
  };
  const checkValidDimensionValue = value => {
    switch (typeof value) {
      case "string":
      case "number":
        const num = Number(value);
        return Number.isSafeInteger(num) && num >= minPx && num <= maxPx;
      default:
        return false;
    }
  };
  let callouts = [];
  if (height && !checkValidDimensionValue(height)) {
    callouts.push(createInvalidPropCallout("height", height, expectedPx));
  }
  if (width && !checkValidDimensionValue(width)) {
    callouts.push(createInvalidPropCallout("width", width, expectedPx));
  }
  if (callouts.length !== 0) {
    return callouts;
  }
  const heightPx = Number(height);
  const widthPx = Number(width);
  const shouldCenter = center === "true" || center === true ? true : false;
  const shouldNotZoom = noZoom === "true" || noZoom === true ? true : false;
  const images = <>
      <img className="block dark:hidden" src={src} alt={alt} {...height && ({
    height: heightPx
  })} {...width && ({
    width: widthPx
  })} {...(shouldCreateLink || shouldInvert || shouldNotZoom) && ({
    noZoom: "true"
  })} />
      <img className={`hidden dark:block ${shouldInvert ? "invert" : ""}`} src={darkSrc ?? src} alt={darkAlt ?? alt} {...height && ({
    height: heightPx
  })} {...width && ({
    width: widthPx
  })} {...(shouldCreateLink || shouldInvert || shouldNotZoom) && ({
    noZoom: "true"
  })} />
    </>;
  if (shouldCreateLink) {
    if (shouldCenter) {
      return <div style={{
        display: "flex",
        justifyContent: "center"
      }}>
          <a href={href} target={target ?? "_self"}>
            {images}
          </a>
        </div>;
    }
    return <a href={href} target={target ?? "_self"}>
        {images}
      </a>;
  }
  if (shouldCenter) {
    return <div style={{
      display: "flex",
      justifyContent: "center"
    }}>{images}</div>;
  }
  return images;
};

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>
    </>;
};

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

  FunC pages will be moved down in the sidebar in mid-April 2026. Here is the preview of a possible future placement, right between "Blockchain foundations" and "Contribute" sections:

  <Image src="/resources/images/tmp-func-fift-light.png" darkSrc="/resources/images/tmp-func-fift-dark.png" alt="Preview of a possible future placement of FunC and Fift languages in the sidebar." width={294} height={190} noZoom={true} />

  Learn how to [migrate from FunC to Tolk](/tolk/from-func/tolk-vs-func).
</Aside>

Every function declaration or definition follows a common pattern. The general form is:

```func theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
[<forall declarator>] <return type> <function name>(<comma separated function args>) <specifiers> <function body>
```

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

* `<forall declarator>` is the [`forall` declarator](#forall-declarator), which declares that the function is [polymorphic](https://en.wikipedia.org/wiki/Parametric_polymorphism). This is optional.
* `<return type>` is the [return type](#return-type) of the function.
* `<function name>` is the [function name](#function-name).
* `<comma separated function args>` is a comma separated list of [function arguments](#function-arguments), each argument consisting on a type and the argument's name.
* `<specifiers>` are [specifiers](#specifiers) that instruct the compiler on how to process the function.
* `<function body>` is the actual [function body](#function-body), which can be of three kinds: an [empty body](#empty-body), an [assembler body](#assembler-body), or a [standard body](#standard-body).

## 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 functions are valid:

```func theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
int foo() { return 0; }
(int, int) foo'() { return (0, 0); }
[int, int] foo''() { return [0, 0]; }
(() -> int) foo'''() { return foo; }
() foo''''() { return (); }
```

FunC also supports **type inference** with the use of underscore `_` as the return type.

For example:

```func theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
_ divAndMod(int m, int n) {
  return (m /% n);
}
```

There, the function `divAndMod` has the inferred type `(int, int) -> (int, int)`. The function computes the division and modulo of the parameters `m` and `n` by using the [division and modulo](/languages/func/operators#division-and-modulo%2C-%2F%25) operator `/%`, which always returns a two-element tensor `(int, int)`.

## 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 [special function call notation](/languages/func/expressions#special-function-call-notation) section. Specifically, refer to this [section](/languages/func/expressions#and-in-function-names) to understand how the symbols `.` or `~` affect the function name.

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).

FunC reserves several function names. See the [reserved functions](/languages/func/special-functions) article for more details.

## Function arguments

A function can receive zero or more argument declarations, each declaration separated by a comma. The following kinds of argument declarations are allowed:

* Ordinary declaration: an argument is declared using **its type** followed by **its name**. Example:

  ```func theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
  int foo(int x) {
    return x + 2;
  }
  ```

  Here, `int x` declares an argument named `x` of type `int` in function `foo`.

  An example that declares multiple arguments:

  ```func theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
  int foo(int x, int y) {
    return x + y;
  }
  ```

  An example that declares no arguments:

  ```func theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
  int foo() {
    return 0;
  }

  ```

* Unused argument declaration: only its type needs to be specified. Example:

  ```func theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
  int first(int x, int) {
    return x;
  }
  ```

  This is a valid function of type `(int, int) -> int`, but the function does not use its second argument.

* 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={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
  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`.

<Aside>
  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 call](/languages/func/expressions#function-call) section.

  However, for convenience, the individual components of this tensor are conventionally referred to as function arguments.
</Aside>

## Specifiers

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

1. `impure`
2. Either `inline` or `inline_ref`, but not both
3. `method_id`

One, multiple, or none can be used in a function declaration. However, they must appear in the order of the above list, e.g., `impure` must come before `inline` and `method_id`, `inline_ref` must come before `method_id`, etc.

### `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, the [stdlib.fc](/languages/func/stdlib) function [`random`](/languages/func/stdlib#random) changes the internal state of the random number generator:

```func theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
int random() impure asm "RANDU256";
```

The `impure` keyword prevents the compiler from removing calls to this function:

```func theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
var n = 0;
random();     ;; Even though the result of random is not used,
              ;; the compiler will not remove this call
              ;; because random has the impure specifier.
```

### Inline specifier

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

For example:

```func theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
(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.

For instance, the compiler will replace the following code:

```func theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
var a = 1;
var b = 2;
var n = add(a, b);
```

with this code:

```func theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
var a = 1;
var b = 2;
var n = a + b;
```

### `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, the TVM executes a `CALLREF` command, which loads the code stored in the referenced cell and executes the function code.

To give you a very high level idea on how to visualize this, think how programs are stored in the blockchain. Anything in the blockchain is a cell. A program is a [directed acyclic graph (DAG)](/foundations/whitepapers/tblkch#1-1-1-tvm-cells) of cells. Each cell stores TVM instructions, and can have up to 4 references to other cells. Each one of those references represent code that the TVM can jump to.

So, you can picture a program like this:

```text theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
Cell 1

instruction 1
instruction 2
.....
call reference A
.....
instruction n
----------------------------------------
Reference to cell A | Reference to cell B |
```

where `Reference to cell A`, and `Reference to cell B` are references to other cells containing further code of the program. When the TVM executes the instruction `call reference A`, the TVM loads the cell referenced by `Reference to cell A` and executes the cell.

When a function is marked as `inline_ref`, its code is placed in a separate cell, name it `C`. Then, everywhere the function is called in the original program,
it is replaced with a `call reference C`. Then, the reference to `C` is added to the original program as a cell reference.

More concretely, imagine the following program:

```func theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
int foo() inline_ref {
  return 1;
}

int main() {
  return (foo() + foo());
}
```

Then, this would create two cells, one storing the code of the `main` function, call it cell `M`; and another cell storing the code of the `foo` function, because it is marked as `inline_ref`, call it cell `F`. The two calls to `foo` inside `main` will be replaced by reference calls to `F`.

And the reference to `F` is added as a reference in cell `M`:

```text theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
Cell M

call reference to F
call reference to F
ADD
----------------------------------------
Reference to F |


Cell F

1 PUSHINT
```

When `call reference to F` executes, the TVM loads the cell for `F` and executes it.

As the example suggests, contrary to the `inline` specifier, the code for `foo` is not duplicated, because the two calls for `foo` are loading the same cell. As such, `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, because loading cell references costs gas.

However, recursive calls to `inline_ref` functions remain impossible, as TVM cells do not support cyclic references.

### `method_id` specifier

In a TVM program, every function has an internal integer ID that identifies it uniquely. These IDs are necessary because of the way the TVM calls functions within a program: it uses a dictionary where each key is a function ID that maps to the corresponding function code. When the TVM needs to invoke a particular function, the TVM looks up the ID in the dictionary and executes the corresponding code.

By default, functions are assigned sequential numbers starting from `1`. If a function has the `method_id` specifier, the compiler will compute an ID using the formula `(crc16(<function_name>) & 0xffff) | 0x10000` instead. Additionally, such function becomes a get-method (or getter method), which are functions that can be invoked by its name in lite client or TON explorer.

The `method_id` specifier has the variant `method_id(<some_number>)`, which allows you to set a function's ID to a specific number manually.

For example, this defines a function whose ID is computed by the compiler and the function is available as a get-method in TON blockchain explorers:

```func theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
int get_counter() method_id {
  load_data();
  return ctx_counter;  ;; Some global variable
}
```

This other example defines the same function, but this time it sets the specific ID `65536`. Again, the function is available as a get-method in TON explorers.

```func theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
int get_counter() method_id(65536) {
  load_data();
  return ctx_counter;  ;; Some global variable
}
```

<Aside type="caution" title="Important limitations and recommendations">
  **19-bit limitation**: Method IDs are limited to signed 19-bit integers, meaning the valid range is from `-2^18` (inclusive) to `(2^18 - 1)` (inclusive),
  i.e., from `-262,144` to `262,143`.

  **Reserved ranges**:

  * -4 to 0 for [special functions](/languages/func/special-functions): `main` or `recv_internal` (ID = 0), `recv_external` (ID = -1), `run_ticktock` (ID = -2), `split_prepare` (ID = -3), `split_install` (ID = -4)
  * 1 to 999 for additional functions (approximate range).
  * 65536 and above: default range for user functions when using automatic generation: `(crc16(function_name) & 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>

## Function body

### Empty body

An empty body, marked with 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. A function with an empty body is also called a *function declaration*.

For example:

```func theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
 int add(int x, int y);
```

This declares a function named `add` with type `(int, int) -> int` but does not define it.

In FunC, all functions must be defined or declared before using them in other functions, which explains the need for function declarations.

For example, the following code calls function `foo` inside the `main` function, but `foo` is defined *after* `main`.

Hence, the compiler rejects the code:

```func theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
() main() {
  var a = foo();    ;; DOES NOT COMPILE
                    ;; foo is not declared nor
                    ;; defined before main
}

int foo() {
  return 0;
}
```

To fix the error, either declare `foo` before `main`:

```func theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
int foo();      ;; foo declared before main,
                ;; but defined after main

() main() {
  var a = foo();
}

int foo() {
  return 0;
}
```

Or move the definition of `foo` before main:

```func theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
int foo() {
  return 0;
}

() main() {
  var a = foo();
}
```

### Assembler body

An assembler body defines the function using low-level TVM primitives for use in a FunC program. The body consists on the keyword `asm`, followed a list of TVM instructions, and ending with symbol `;`.

For example:

```func theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
  int add(int x, int y) asm "ADD";
```

This defines the function `add` of type `(int, int) -> int`, using the TVM instruction `ADD`.

Refer to the [assembler functions](/languages/func/asm-functions) article for more details.

### Standard body

A standard body uses a [block statement](/languages/func/statements#block-statement), i.e., the body of the function is defined inside curly braces `{ }`.

For example:

```func theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
int add(int x, int y) {
  return x + y;
}
```

This defines a function that adds its two arguments and returns the result of the addition.

## `forall` declarator

The `forall` declarator has the following syntax:

```func theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
forall <comma separated list of type variables names> ->
```

The declarator starts with the `forall` keyword and finishes with the symbol `->`. Each element in the comma separated list must be a type variable name. A type variable name can be any [identifier](/languages/func/literals#identifiers), but capital letters are commonly used.

The `forall` declarator makes the function a [polymorphic function](https://en.wikipedia.org/wiki/Parametric_polymorphism), meaning that when the function is called, the type variables get replaced with actual types.

For example:

```func theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
forall X, Y -> [Y, X] pair_swap([X, Y] pair) {
  [X p1, Y p2] = pair;
  return [p2, p1];
}
```

This function declares two type variables `X` and `Y`. The function uses these two type variables to declare an argument `pair` of type `[X, Y]`, i.e., a [tuple](/languages/func/types#tuple-types) where the first component is of type `X` and the second component of type `Y`. The function then swaps the components of the tuple and returns a tuple of type `[Y, X]`.

That `pair_swap` is polymorphic means that it can be called with tuples of type `[int, int]`, `[int, cell]`, `[cell, slice]`, `[[int, int], cell]`, etc.

For instance:

* `pair_swap([2, 3])` returns `[3, 2]`. In this case, both type variables `X` and `Y` get substituted with `int`.
* `pair_swap([1, [2, 3, 4]])` returns `[[2, 3, 4], 1]`. In this case, type variable `X` gets substituted with `int`, and `Y` with `[int, int, int]`.

Even though the function is polymorphic, the compiled assembly code remains the same for any substitution of the type variables. This is possible due to the polymorphic nature of stack manipulation operations.

However, other forms of polymorphism, such as [`ad-hoc` polymorphism](https://en.wikipedia.org/wiki/Ad_hoc_polymorphism) with type classes, are not supported.

<Aside>
  At the moment, type variables in polymorphic functions cannot be instantiated with tensor types. There is only one exception: the tensor type `(a)`, where `a` is not a tensor type itself, since the compiler treats `(a)` as if it was `a`.

  This means you can't use `pair_swap` on a tuple of type `[(int, int), int]` because type `(int, int)` is a tensor type.
</Aside>
