Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
127 changes: 47 additions & 80 deletions languages/tolk/basic-syntax.mdx
Original file line number Diff line number Diff line change
@@ -1,35 +1,25 @@
---
title: "Tolk basic syntax"
title: "Basic syntax"
sidebarTitle: "Basic syntax"
---

import { Aside } from '/snippets/aside.jsx';

Syntax of Tolk is similar to TypeScript, Rust, and Kotlin. It is designed to be straightforward to read and write.

Below is a list of basic syntax elements with examples. Most sections end with a link to a detailed topic.

## Imports

Imports exist at the top of the file:
[Imports](/languages/tolk/syntax/imports) must appear at the top of the file:

```tolk
import "another-file"

// symbols from `another-file.tolk` can now be used
// Symbols from `another-file.tolk` become available in this file.
```

In typical workflows, an IDE inserts imports automatically (for example, when selecting an element from auto‑completion).

<Aside type="note">
The entire file is imported. There are no "modules" or "exports", all symbols must have unique names project-wise.
</Aside>
In most workflows, the IDE adds imports automatically. For example, when selecting an item from auto-completion.

See: [imports](/languages/tolk/syntax/imports).
The entire file is imported. There are no modules or exports; all symbols must have unique names within the project.

## Structures

A struct `Point` holding two 8-bit integers:
A [struct](/languages/tolk/syntax/structures-fields) `Point` holding two 8-bit integers:

```tolk
struct Point {
Expand All @@ -46,11 +36,11 @@ fun demo() {
}
```

- methods are declared like `fun Point.method(self)`, read below
- fields can be of any types: numeric, cell, union, etc. (see [type system](/languages/tolk/types/list-of-types))
- fields can have default values: `x: int8 = 0`
- fields can be `private` and `readonly`
- structs can be generic: `struct Wrapper<T> { ... }`
- Methods are declared as `fun Point.method(self)`.
- Fields can use any [types](/languages/tolk/types/list-of-types): numeric, cell, union, and others.
- Fields can define default values: `x: int8 = 0`.
- Fields can be `private` and `readonly`.
- Structs can be generic: `struct Wrapper<T> { ... }`.

If all fields are serializable, a struct can be [automatically serialized](/languages/tolk/features/auto-serialization):

Expand All @@ -61,33 +51,29 @@ val c = p1.toCell();
val p3 = Point.fromCell(c);
```

See: [structures](/languages/tolk/syntax/structures-fields).

## Functions

A function that calculates the sum of two integers:
A [function](/languages/tolk/syntax/functions-methods) that returns the sum of two integers:

```tolk
fun sum(a: int, b: int): int {
return a + b;
}
```

- parameter types are mandatory
- the return type can be omitted: it will be auto-inferred, like in TypeScript
- parameters can have a default value: `fun f(b: int = 0)`
- statements inside a block are separated by semicolons `;`
- generic functions: `fun f<T>(value: T) { ... }`
- assembler functions: `fun f(...): int asm "..."`

See: [functions and methods](/languages/tolk/syntax/functions-methods).
- Parameter types are mandatory.
- The return type can be omitted: it is auto-inferred.
- Parameters can define default values: `fun f(b: int = 0)`
- Statements in a block are separated by semicolons `;`.
- Generic functions are supported: `fun f<T>(value: T) { ... }`
- Assembler functions are supported: `fun f(...): int asm "..."`

## Methods

A function declared as `fun <receiver>.name(...)` is a method.
A function declared as `fun <receiver>.name(...)` is a [method](/languages/tolk/syntax/functions-methods).

- if the first parameter is `self`, it's an **instance method**
- if not `self`, it's a **static method**
- If the first parameter is `self`, it's an instance method.
- If the first parameter is not `self`, it's a static method.

```tolk
// `self` — instance method (invoked on a value)
Expand All @@ -106,60 +92,55 @@ fun demo() {
}
```

- by default, `self` is immutable, but `mutate self` allows modifying an object
- methods may be declared not only for a struct, but for any type, even a primitive:
By default, `self` is immutable; `mutate self` allows modifying the object.

Methods can be declared for any type, including primitives:

```tolk
fun int.isNegative(self) {
return self < 0
}
```

See: [functions and methods](/languages/tolk/syntax/functions-methods).

## Variables

Inside functions, variables are declared with `val` or `var` keywords.

The `val` keyword declares a variable that is assigned exactly once (immutable):
Within functions, [variables](/languages/tolk/syntax/variables) are declared with `val` or `var` keywords. The `val` keyword declares an immutable variable that can be assigned only once:

```tolk
val coeff = 5;
// cannot change its value, `coeff += 1` is an error
```

The `var` keyword declares a variable that may be reassigned:
The `var` keyword declares a variable that can be reassigned:

```tolk
var x = 5;
x += 1; // now 6
```

Variable's type can be specified after its name:
A variable’s type can be specified after its name:

```tolk
var x: int8 = 5;
```

Declaring variables at the top-level (not inside functions) is supported via `global` keyword.

See: [variables](/languages/tolk/syntax/variables).
Declaring variables at the top level, outside functions, is supported using the `global` keyword.

## Constants

Declaring constants is allowed at the top-level (not inside functions):
Constants can be declared only at the top level, not inside functions:

```tolk
const ONE = 1
const MAX_AMOUNT = ton("0.05")
const ADMIN_ADDRESS = address("EQ...")
```

To group integer constants, [enums](/languages/tolk/types/enums) are also useful.
To group integer constants, [enums](/languages/tolk/types/enums) are useful.

## Value semantics

Tolk follows value semantics: assignments create independent copies, and function calls do not mutate arguments unless explicitly specified.
Tolk follows value semantics: assignments create independent copies, and function calls do not [mutate](/languages/tolk/syntax/mutability) arguments unless explicitly specified.

```tolk
var a = Point { x: 1, y: 2 };
Expand All @@ -171,13 +152,11 @@ someFn(a); // pass a copy; `a` will not change
anotherFn(mutate a);
```

See: [mutability](/languages/tolk/syntax/mutability).

## Semicolons

- semicolons are **optional at the top-level** (after imports, aliases, etc.)
- **required between statements in a function**
- after the last statement in a block, it's also optional
- Semicolons are optional at the top level, after imports, aliases, etc.
- Semicolons are required between statements in a function.
- After the last statement in a block, a semicolon is optional.

```tolk
// optional at the top-level
Expand All @@ -194,7 +173,7 @@ fun demo() {

## Comments

Like most modern languages, Tolk supports single-line (or end-of-line) and multi-line (block) comments:
Tolk supports single-line or end-of-line and multi-line or block comments:

```tolk
// This is a single-line comment
Expand All @@ -207,6 +186,8 @@ const TWO = 1 /* + 100 */ + 1 // 2

## Conditional operators

In [conditions](/languages/tolk/syntax/conditions-loops), `if` is a statement. `else if` and `else` blocks are optional.

```tolk
fun sortNumbers(a: int, b: int) {
if (a > b) {
Expand All @@ -217,19 +198,15 @@ fun sortNumbers(a: int, b: int) {
}
```

In Tolk, `if` is a statement, with `else if` and `else` optional blocks.

A ternary operator is also available:

```tolk
val sign = a > 0 ? 1 : a < 0 ? -1 : 0;
```

See: [conditions and loops](/languages/tolk/syntax/conditions-loops).

## Union types and matching

Union types allow a variable to hold "one of possible types". They are typically handled by `match`:
[Union types](/languages/tolk/types/unions) allow a variable to hold one of possible types. They are typically handled by `match`:

```tolk
fun processValue(value: int | slice) {
Expand Down Expand Up @@ -257,25 +234,23 @@ fun processValue(value: int | slice) {
}
```

Unions types are commonly used when [handling incoming messages](/languages/tolk/features/message-handling).

See: [union types](/languages/tolk/types/unions).
Union types are commonly used when [handling incoming messages](/languages/tolk/features/message-handling).

## While loop

Tolk does not have a `for` loop; use [`while` loop](/languages/tolk/syntax/conditions-loops) for repeated execution.

```tolk
while (i > 0) {
// ...
i -= 1;
}
```

The `for` loop does not exist.

See: [conditions and loops](/languages/tolk/syntax/conditions-loops).

## Assert and throw

The `try-catch` statement is supported for [exceptions](/languages/tolk/syntax/exceptions), although it is not commonly used in contracts.

```tolk
const ERROR_NO_BALANCE = 403;

Expand All @@ -286,12 +261,10 @@ throw ERROR_NO_BALANCE;
assert (balance > 0) throw ERROR_NO_BALANCE;
```

A try-catch statement is also supported, although it is not commonly used in contracts.

See: [exceptions](/languages/tolk/syntax/exceptions).

## Iterate over a map

To iterate, [maps](/languages/tolk/types/maps) can be used:

```tolk
fun iterateOverMap(m: map<int32, Point>) {
var r = m.findFirst();
Expand All @@ -302,11 +275,9 @@ fun iterateOverMap(m: map<int32, Point>) {
}
```

See: [maps](/languages/tolk/types/maps).

## Send a message to another contract

An outgoing message body is typically represented by a structure (for example, `RequestedInfo`).
To [construct and send a message](/languages/tolk/features/message-sending), a message body is typically represented by a structure. For example, `RequestedInfo`:

```tolk
val reply = createMessage({
Expand All @@ -318,17 +289,13 @@ val reply = createMessage({
reply.send(SEND_MODE_REGULAR);
```

See: [constructing and sending messages](/languages/tolk/features/message-sending).

## Contract getters

Contract getters (or "get methods") are declared with `get fun`:
[Contract getters](/languages/tolk/features/contract-getters) or get-methods are declared with `get fun`:

```tolk
get fun currentOwner() {
val storage = lazy Storage.load();
return storage.ownerAddress;
}
```

See: [contract getters](/languages/tolk/features/contract-getters).
Loading