Tolk is a language for writing smart contracts in TON. Think of Tolk as the "next‑generation FunC". Tolk compiler is literally a fork of FunC compiler, introducing familiar syntax similar to TypeScript, but leaving all low-level optimizations untouched.
Tolk was announced at the TON Gateway in Dubai in November 2024.
This channel will contain updates and releases of Tolk, highlights of planned features, and occasional posts about compilers and language design in general.
Useful links:
- Documentation
- GitHub (Tolk is a part of ton-blockchain repo)
- IDE plugins: "TON" in JetBrains, "Tolk" in VS Code
- Read an interview about TOLK history and plans
- Watch announcement on YouTube
Tolk was announced at the TON Gateway in Dubai in November 2024.
This channel will contain updates and releases of Tolk, highlights of planned features, and occasional posts about compilers and language design in general.
Useful links:
- Documentation
- GitHub (Tolk is a part of ton-blockchain repo)
- IDE plugins: "TON" in JetBrains, "Tolk" in VS Code
- Read an interview about TOLK history and plans
- Watch announcement on YouTube
YouTube
The Evolution of FunC to Tolk
Meet Aleksandr Kirsanov, TON Core engineer, as he unveils Tolk, a groundbreaking new programming language for TON blockchain. In his engaging talk, Aleksandr delves into:
▪️ The evolution from FunC to Tolk, designed to simplify smart contract development…
▪️ The evolution from FunC to Tolk, designed to simplify smart contract development…
🔥9👍3
Two months of absence: what was going on?
Two months have passed since the announcement of Tolk. You might be wondered, what was going on and why there we no releases yet.
Throughout all November, I've been working on the vision of the future. My goal was to "visualize" what Tolk v1.0 should look like. What's the language we're all targeting to, so that it solves lots of practical problems, avoids manual cells/slices manipulation, provides sufficient mechanisms for ABI generation, but still being zero overhead. I have created a giant roadmap (40 PDF pages!) describing the vision, and how, step by step, we're going to reach it.
Throughout all December, I've been constantly working on the compiler's kernel. As you know, Tolk is a fork of FunC. FunC compiler internals are very challenging to be extended and modified. The way FunC looks like is just a mirror of its internal implementation. Heading towards the future, I had to partially "untangle" this "legacy FunC core", so that in the future, it will be able to "interbreed" with features it was not originally designed for.
Currently I am done with this preparation. Tolk v0.7 has just been released. It contains a fully rewritten semantic analysis kernel (though almost invisible to the end user, huh).
✅ Notable changes in Tolk v0.7:
1. Under the hood: refactor and revamp compiler internals. AST-level semantic analysis kernel
2. Under the hood: rewrite the type system from Hindley-Milner to static typing
3. Clear and readable error messages on type mismatch
4. Generic functions
5. The
6. Type casting via
PR on GitHub with detailed info. IDE plugins are updated accordingly.
BTW, a new version of blueprint was also released. You can now update compilers (Tolk / FunC / Tact) independently, they became peer dependencies.
P.S. I'll uncover the details about planned Tolk v1.0 quite soon.
Two months have passed since the announcement of Tolk. You might be wondered, what was going on and why there we no releases yet.
Throughout all November, I've been working on the vision of the future. My goal was to "visualize" what Tolk v1.0 should look like. What's the language we're all targeting to, so that it solves lots of practical problems, avoids manual cells/slices manipulation, provides sufficient mechanisms for ABI generation, but still being zero overhead. I have created a giant roadmap (40 PDF pages!) describing the vision, and how, step by step, we're going to reach it.
Throughout all December, I've been constantly working on the compiler's kernel. As you know, Tolk is a fork of FunC. FunC compiler internals are very challenging to be extended and modified. The way FunC looks like is just a mirror of its internal implementation. Heading towards the future, I had to partially "untangle" this "legacy FunC core", so that in the future, it will be able to "interbreed" with features it was not originally designed for.
Currently I am done with this preparation. Tolk v0.7 has just been released. It contains a fully rewritten semantic analysis kernel (though almost invisible to the end user, huh).
✅ Notable changes in Tolk v0.7:
1. Under the hood: refactor and revamp compiler internals. AST-level semantic analysis kernel
2. Under the hood: rewrite the type system from Hindley-Milner to static typing
3. Clear and readable error messages on type mismatch
4. Generic functions
fun f<T>(...) and instantiations like f<int>(...)5. The
bool type6. Type casting via
value as TPR on GitHub with detailed info. IDE plugins are updated accordingly.
BTW, a new version of blueprint was also released. You can now update compilers (Tolk / FunC / Tact) independently, they became peer dependencies.
P.S. I'll uncover the details about planned Tolk v1.0 quite soon.
🔥12🎉8❤5
The Hindley-Milner type system, and Why Tolk decided to avoid it
You know, that FunC is "functional C". But do you know, what makes it "functional"? Not its low-level nature. Not its peculiar syntax. And even not the
The Hindley-Milner type system is a common approach for functional languages, where types are inferred from usage through unification. As a result, type declarations are not necessary:
For example,
For example,
This "unification", looking pretty at first glance, arises problems, if we actually do not want types to unify. Imagine, we want to have nullable types:
Instead of an error, Hindley-Milner would perform unification and result in
A fun fact: you don't notice these problems in FunC. Because FunC's type system is very limited. But Tolk will have bool, fixed-width integers, nullability, smart casts, structures, and generics — these problems will become significant. Hindley-Milner will clash with structure methods, struggle with proper generics, and become entirely impractical for union types (despite theoretical claims that it was "designed for union types").
The goal is to have predictable, explicit, and positionally-checked static typing. While Hindley-Milner is powerful, it's actually "type inference for the poor" — simple to implement when there's no time to fundamentally design the language.
By the way, unreadable type errors also stem from Hindley-Milner:
What the programmer actually wants to see is:
That's why Tolk v0.7 contains a fully rewritten type system, encoupled with clear error messages and an IDE plugin with type inference included. It's the groundwork for future enhancements.
You know, that FunC is "functional C". But do you know, what makes it "functional"? Not its low-level nature. Not its peculiar syntax. And even not the
~ tilda. "Functional" is mostly about the Hindley-Milner type system.The Hindley-Milner type system is a common approach for functional languages, where types are inferred from usage through unification. As a result, type declarations are not necessary:
() f(a, b) {
return a + b; // a and b now int, since `+` (int, int)
}
For example,
() f(slice s) {}
var s = null;
f(s); // infer s as slice, since f accepts slice
For example,
int f(x) {
(a, b) = (0, x);
return a + b; // x becomes int, since x and b edge
}
This "unification", looking pretty at first glance, arises problems, if we actually do not want types to unify. Imagine, we want to have nullable types:
int (not nullable) and int? (nullable), so that we can assign null only to int?. What would Hindley-Milner think about this?
var x = 0; // unify(Hole, Int) = Int
...
x = null; // unify(Int, Nullable<Hole>) = Nullable<Int>
Instead of an error, Hindley-Milner would perform unification and result in
x: int?. Not as we wanted to, right? (while it can be "fixed", it would step away from HM's nature)A fun fact: you don't notice these problems in FunC. Because FunC's type system is very limited. But Tolk will have bool, fixed-width integers, nullability, smart casts, structures, and generics — these problems will become significant. Hindley-Milner will clash with structure methods, struggle with proper generics, and become entirely impractical for union types (despite theoretical claims that it was "designed for union types").
The goal is to have predictable, explicit, and positionally-checked static typing. While Hindley-Milner is powerful, it's actually "type inference for the poor" — simple to implement when there's no time to fundamentally design the language.
By the way, unreadable type errors also stem from Hindley-Milner:
error: function return type (int, int) cannot be unified with implicit end-of-block return type (int, ()): cannot unify type () with int
What the programmer actually wants to see is:
1) can not assign `(int, slice)` to variable of type `(int, int)`
2) can not call method for `builder` with object of type `int`
3) missing `return`
That's why Tolk v0.7 contains a fully rewritten type system, encoupled with clear error messages and an IDE plugin with type inference included. It's the groundwork for future enhancements.
🔥7❤2
Tolk v0.8: preparation for structures
A new version of Tolk was released several days ago. We're starting a way to eventually implement structures with auto packing to/from cells. This will take several steps (each publicly released), it's the first one.
✅ Notable changes in Tolk v0.8:
1. Syntax
2. Allow
PR on GitHub with detailed info.
Using syntax `tensorVar.{i}` and `tupleVar.{i}`, you can access tensors/tuples by indices without unpacking them.
It works for tensors:
It works for tuples (does asm INDEX/SETINDEX under the hood):
It works for nesting
Why is this essential?
In the future, we'll have structures, declared like this:
Structures will be stored like tensors on a stack:
It means, that `obj.{field}` is exactly the same as `tensorVar.{i}`:
Same goes for nested objects:
So, implementing indexed access for tensors/tuples covering all scenarios is a direct step towards structures.
A new version of Tolk was released several days ago. We're starting a way to eventually implement structures with auto packing to/from cells. This will take several steps (each publicly released), it's the first one.
✅ Notable changes in Tolk v0.8:
1. Syntax
tensorVar.0 and tupleVar.0, both for reading and writing2. Allow
cell, slice, etc. to be valid identifiersPR on GitHub with detailed info.
Using syntax `tensorVar.{i}` and `tupleVar.{i}`, you can access tensors/tuples by indices without unpacking them.
It works for tensors:
var t = (5, someSlice, someBuilder); // 3 stack slots
t.0 // 5
t.0 = 10; // t is now (10, ...)
t.0 += 1; // t is now (11, ...)
increment(mutate t.0); // t is now (12, ...)
t.0.increment(); // t is now (13, ...)
t.1 // slice
t.100500 // compilation error
It works for tuples (does asm INDEX/SETINDEX under the hood):
var t = [5, someSlice, someBuilder]; // 1 tuple on a stack with 3 items
t.0 // "0 INDEX", reads 5
t.0 = 10; // "0 SETINDEX", t is now [10, ...]
t.0 += 1; // "0 INDEX" to read 10, "0 SETINDEX" to write 11
increment(mutate t.0); // also, the same way
t.0.increment(); // also, the same way
t.1 // "1 INDEX", it's slice
t.100500 // compilation error
It works for nesting
var.{i}.{j}. It works for nested tensors, nested tuples, tuples nested into tensors. It works for mutate. It works for globals.Why is this essential?
In the future, we'll have structures, declared like this:
struct User {
id: int;
name: slice;
}
Structures will be stored like tensors on a stack:
var u: User = { id: 5, name: "" };
// u is actually 2 slots on a stack, the same as
var u: (int, slice) = (5, "");
fun getUser(): User { ... }
// on a stack, the same as
fun getUser(): (int, slice) { ... }
It means, that `obj.{field}` is exactly the same as `tensorVar.{i}`:
var u: User = ...; // u: (int, slice) = ...
u.id; // u.0
u.id = 10; // u.0 = 10
Same goes for nested objects:
struct Storage {
lastUpdated: int;
owner: User;
}
s.lastUpdated // s.0
s.owner.id // s.1.0
So, implementing indexed access for tensors/tuples covering all scenarios is a direct step towards structures.
🔥15👍8🗿3