Low-level detailsThis page assumes prior knowledge of the Tolk type system
and TVM.
It is intended as a concise low-level reference page.
int, intN, coins
All numeric types are backed by TVM INT.
A reminder: intN uses full 257‑bit precision, so any integer value fits into it.
Overflow happens only at serialization.
bool
Type bool is backed by TVM INT with value -1 or 0 at runtime.
The unsafe cast someBool as int is valid and produces -1 or 0.
address and any_address
Addresses are backed by TVM SLICE values containing raw binary data.
A nullable address? is either TVM NULL or SLICE.
The unsafe cast someAddr as slice and back is valid.
cell
Type cell is backed by TVM CELL.
The unsafe cast someCell as Cell<T> is valid.
Cell<T>
Type Cell<T> is also backed by TVM CELL. The type parameter T is purely compile‑time metadata.
slice
Type slice is backed by TVM SLICE.
bitsN
Type bitsN is backed by TVM SLICE.
The unsafe cast someSlice as bitsN and back is valid.
RemainingBitsAndRefs
Type “remaining” is backed by TVM SLICE. It’s actually an alias for slice, handled specially at deserialization.
builder
Type builder is backed by TVM BUILDER. Note that already written bits cannot be read. The only possible way to access builder’s data is converting it to a slice.
Structures
Fields of a structure are placed sequentially on the stack. For example,Point occupies two stack slots, and Line — four:
Line value, four integers are placed onto the stack:
Enums
Every enum is backed by TVM INT. Tolk supports integer enums only (not addresses, for example).Nullable types T?
Atomics like int? / address? / cell? / etc. occupy a single stack slot: it holds either TVM NULL or a value.
Point or a tensor (bool, cell)) occupy N+1 slots: the last is used for typeid.
Point).
That typeid is stored in an extra slot. Typeid for null is 0.
Expressions such as p == null or p is Point check that typeid slot.
A tricky example. A struct below, being nullable, requires an extra stack slot:
Union types T1 | T2 | ...
Unions are represented as “tagged unions”:
- each alternative type is assigned a unique typeid (e.g., 1234 for
int) - the union occupies N+1 stack slots, where N is the maximum size of
T_i - (N+1)-th slot contains typeid of the current value
match is implemented as a comparison of the (N+1)-th slot, and passing/assigning a value is a bit of stack juggling.
An extra stack slot for typeid is called “tagged union”.
Union types in Tolk,
enum in Rust, std::variant in C++ — they all are tagged unions.T | null is called “nullable” and optimized for atomics: int? use a single slot. Non-atomics are handled generally, with typeid=0.
Tensors (T1, T2, ...)
Tensor components are placed sequentially, identical to struct fields.
For example, (coins, Point, int?) occupies 4 slots: “INT (coins), INT (p.x), INT (p.y), INT/NULL”.
tuple
Type tuple is backed by TVM TUPLE — one stack slot regardless of the number of elements in it (up to 255).
Typed tuple [T1, T2, ...]
A typed tuple is also TVM TUPLE. Its shape is known at compile-time, but at runtime it’s the same tuple.
map<K, V>
Every map is one stack slot: either TVM NULL or TVM CELL.
Non‑empty maps (cells) have a non‑trivial bit‑level layout (follow hashmaps in TL/B).
Callables (...ArgsT) -> ResultT
A callable and continuation is backed by TVM CONT.
void and never
Both represent the absence of a value and occupy zero stack slots.
For example, a void function does not place any value onto the stack.
See also: