T
TOLK lang
@tolk_lang
20.03.2025 09:12
🫧 Tolk v0.10: preparing for serialization — intN, bytesN, coins

This update lays the foundation of future auto-packing to/from cells by solving one critical question:
How should fields be serialized?

✅ Notable changes in Tolk v0.10:

1. Fixed-size integer types: int32, uint64, etc.
2. Type coins and function ton("0.05")
3. Types bytesN and bitsN (backed by slices at TVM)
4. Replace "..."c postfixes with stringCrc32("...") functions
5. Trailing comma support

PR on GitHub with detailed info.

❓ Fixed-size integers? In TVM? What?

Imagine Tolk already has structures, and we define an incoming message:

struct CounterIncrement {
counter_id: int;
inc_by: int;
}


A client sends this message following the TL/B schema:

counterIncrement
counter_id:int32
inc_by:int64
= CounterIncrement;


But how do we tell the compiler that counter_id is int32 and inc_by is int64? This information is missing in the struct definition.

✖ Rejected approaches: why they fail

Several syntax ideas were considered:


// type casting?
counter_id: int as int32;
inc_by: int as int64;

// inline annotations?
counter_id: int @int32;
inc_by: int @int64;

// annotations above fields?
@serialize(int32)
counter_id: int;
@serialize(int64)
inc_by: int;


Each of these quickly breaks down when handling more complex cases.

For example, how would we handle TL-B Maybe int32? Would we write:

// this?
inc_by: (int as int32)?;
// or this?
inc_by: int? as int32?;
// or this?
inc_by: Maybe<int> as Maybe<int32>;


And what about TL/B Both (Maybe int32) int64?

// this?
my_data: Both<Maybe<int as int32>, int as int64>;
// or this?
my_data: Both<Maybe<int>, int> as Both<Maybe<int32>, int64>;
// or how??


With every new case, the syntax becomes more complex, ambiguous, and error-prone.

✔ The solution: `int32` as a first-class type


struct CounterIncrement {
counter_id: int32;
inc_by: int64;
}


No annotations. No confusing as syntax. No ambiguity.

This scales perfectly:

struct MyMsg {
inc_by: int32?;
my_data: (int32?, int64);
}


These are distinct types. A variable can be int32 and similar:

var op: int32 = ...;
var query_id: uint64 = ...;


This makes serialization predictable, structured, and error-free.

✔ What about overflow?

A reasonable question: what happens if a value exceeds the limit?

var v: uint8 = 255;
v += 1; // ???


Answer: no runtime overflow or clamping! It's just int at TVM.

* arithmetic works normally – v becomes 256
* no extra gas cost – no runtime bounds checks
* overflow will only happen at serialization


struct Resp {
outValue: uint8;
}

resp.outValue = v; // 256
resp.toCell(); // a runtime "overflow" error


✔ Why is this the best approach?

Think of smart contracts as a black box:
- inputs are encoded (int32, uint64, etc.)
- inside the contract, arithmetic uses full 257-bit precision
- outputs are serialized again — overflow happens only at this stage

This is similar to how mulDivFloor(x,y,z) uses 513-bit precision internally. Your contract keeps precision internally and only enforces constraints at the border with an outside world.

🌳 Tolk will follow a type-based philosophy

This post covered the foundation of automatic serialization. The right way is to have a rich type system. Having nested types, having generics, having aliases — will allow to describe every practical TL/B case, but at a language level.

In v0.10, we introduce intN (fixed integers), bytesN (definite slices), coins (variadic integers), and some more additions. Read the details in the PR.

How will Either L R and even more complex TL/B structures be expressed?
Stay tuned for the next update...
6
🔥 4
👍 3
🤔 1
8 4.1K

Обсуждение 0

Обсуждение не доступно в веб-версии. Чтобы написать комментарий, перейдите в приложение Telegram.

Обсудить в Telegram
T

TOLK lang

844
Channel devoted to TOLK — "next-generation FunC" — a language for writing smart contracts in TON
Открыть в Telegram