Стандартная библиотека FunC
Эта страница переведен а сообществом на русский язык, но нуждается в улучшениях. Если вы хотите принять участие в переводе свяжитесь с @alexgton.
В этом разделе обсуждается библиотека stdlib.fc со стандартными функциями, используемыми в FunC.
В настоящее время библиотека является просто оберткой для наиболее распространенного ассемблера команд TVM, которые не являются встроенными. Описание каждой команды TVM, используемой в библиотеке, можно найти в разделе документация TVM. Некоторые описания были взяты для этого документа.
Некоторые функции в файле закомментированы. Это означает, что они уже стали встроенными в целях оптимизации. Однако сигнатура типа и семантика остаются прежними.
Обратите внимание, что некоторые менее распространенные команды не представлены в stdlib. Они также будут добавлены в будущем.
Примитивы для манипулирования кортежами
Имена и типы в основном говорят сами за себя. См. полиморфизм с forall для получения дополнительной информации о полиморфных функциях.
Обратите внимание, что в настоящее время значения атомарного типа tuple не могут быть преобразованы в составные типы кортежей (например, [int, cell]) и наоборот.
Списки в стиле Lisp
Списки могут быть представлены как вложенные кортежи из 2 элементов. Пустой список традиционно представляется как значение TVM null (его можно получить, вызвав null()). Например, кортеж (1, (2, (3, null))) представляет список [1, 2, 3]. Элементы списка могут быть разных типов.
cons
forall X -> tuple cons(X head, tuple tail) asm "CONS";
Добавляет элемент в начало списка в стиле lisp.
uncons
forall X -> (X, tuple) uncons(tuple list) asm "UNCONS";
Извлекает начало и конец списка в стиле lisp.
list_next
forall X -> (tuple, X) list_next(tuple list) asm( -> 1 0) "UNCONS";
Извлекает начало и конец списка в стиле lisp. Может использоваться как (не)модифицирующий метод.
() foo(tuple xs) {
(_, int x) = xs.list_next(); ;; get the first element, `_` means do not use tail list
int y = xs~list_next(); ;; pop the first element
int z = xs~list_next(); ;; pop the second element
}
car
forall X -> X car(tuple list) asm "CAR";
Возвращает начало списка в стиле lisp.
cdr
tuple cdr(tuple list) asm "CDR";
Возвращает конец списка в стиле lisp.
Другие примитивы кортежа
empty_tuple
tuple empty_tuple() asm "NIL";
Создает кортеж из 0 элементов.
tpush
forall X -> tuple tpush(tuple t, X value) asm "TPUSH";
forall X -> (tuple, ()) ~tpush(tuple t, X value) asm "TPUSH";
Добавляет значение x к Tuple t = (x1, ..., xn), но только если полученный Tuple t' = (x1, ..., xn, x) не длиннее 255 символов. В противном случае выдается исключение проверки типа.
single
forall X -> [X] single(X x) asm "SINGLE";
Создает одиночку, т. е. кортеж длиной один.
unsingle
forall X -> X unsingle([X] t) asm "UNSINGLE";
Распаковывает одиночку.
pair
forall X, Y -> [X, Y] pair(X x, Y y) asm "PAIR";
Создает пару.
unpair
forall X, Y -> (X, Y) unpair([X, Y] t) asm "UNPAIR";
Распаковывает пару.
triple
forall X, Y, Z -> [X, Y, Z] triple(X x, Y y, Z z) asm "TRIPLE";
Создает тройку.
untriple
forall X, Y, Z -> (X, Y, Z) untriple([X, Y, Z] t) asm "UNTRIPLE";
Распаковывает тройку.
tuple4
forall X, Y, Z, W -> [X, Y, Z, W] tuple4(X x, Y y, Z z, W w) asm "4 TUPLE";
Создает кортеж из 4 элементов.
untuple4
forall X, Y, Z, W -> (X, Y, Z, W) untuple4([X, Y, Z, W] t) asm "4 UNTUPLE";
Распаковывает кортеж из 4 элементов.
first
forall X -> X first(tuple t) asm "FIRST";
Возвращает первый элемент кортежа.
second
forall X -> X second(tuple t) asm "SECOND";
Возвращает второй элемент кортежа.
third
forall X -> X third(tuple t) asm "THIRD";
Возвращает третий элемент кортежа.
fourth
forall X -> X fourth(tuple t) asm "3 INDEX";
Возвращает четвертый элемент кортежа.
pair_first
forall X, Y -> X pair_first([X, Y] p) asm "FIRST";
Возвращает первый элемент пары.
pair_second
forall X, Y -> Y pair_second([X, Y] p) asm "SECOND";
Возвращает второй элемент пары.
triple_first
forall X, Y, Z -> X triple_first([X, Y, Z] p) asm "FIRST";
Возвращает первый элемент тройки.
triple_second
forall X, Y, Z -> Y triple_second([X, Y, Z] p) asm "SECOND";
Возвращает второй элемент тройки.
triple_third
forall X, Y, Z -> Z triple_third([X, Y, Z] p) asm "THIRD";
Возвращает третий элемент тройки.
Примитивы, специфичные для домена
Извлечение информации из c7
Некоторые полезные сведения о вызове смарт-контракта можно найти в специальном регистре c7. Эти примитивы служат для удобного извлечения данных.
now
int now() asm "NOW";
Возвращает текущее время Unix как целое число
my_address
slice my_address() asm "MYADDR";
Возвращает внутренний адрес текущего смарт-контракта как срез с MsgAddressInt. При необходимости его можно проанализировать далее с помощью примитивов, таких как parse_std_addr.
get_balance
[int, cell] get_balance() asm "BALANCE";
Возвращает оставшийся баланс смарт-контракта в виде tuple, состоящего из int (оставшийся баланс в nanotoncoin) и cell (словарь с 32-битными ключами, представляющими баланс "дополнительных валют"). Поскольку это произойдет в фазе вычислений, баланс контракта будет включать входящее сообщение value, вычитать storage_fee и import_fee.
Необработанные примитивы, такие как send_raw_message, не обновляют это поле.
cur_lt
int cur_lt() asm "LTIME";
Возвращает логическое время текущей транзакции.
block_lt
int block_lt() asm "BLOCKLT";
Возвращает начальное логическое время текущего блока.
config_param
cell config_param(int x) asm "CONFIGOPTPARAM";
Возвращает значен ие глобального параметра конфигурации с целочисленным индексом i как cell или null значение.
Хэши
cell_hash
int cell_hash(cell c) asm "HASHCU";
Вычисляет хэш представления cell c и возвращает его как 256-битное беззнаковое целое число x. Полезно для подписи и проверки подписей произвольных сущностей, представленных деревом ячеек.
slice_hash
int slice_hash(slice s) asm "HASHSU";
Вычисляет хэш slice s и возвращает его как 256-битное целое число без знака x. Результат такой же, как если бы была создана обычная ячейка, содержащая только данные и ссылки из s, и ее хэш был вычислен cell_hash.
string_hash
int string_hash(slice s) asm "SHA256U";
Вычисляет sha256 бит данных slice s. Если длина бит s не делится на восемь, выдается исключение потери значимости ячейки. Значение хэша возвращается как 256-битное целое число без знака x.
Проверка подписи
check_signature
int check_signature(int hash, slice signature, int public_key) asm "CHKSIGNU";
Проверяет signature Ed25519 для hash (256-битное беззнаковое целое число, обычно вычисляемое как хэш некоторых данных) с помощью public_key (также представленного 256-битным беззнаковым целым числом). Подпись должна содержать не менее 512 бит данных; используются только первые 512 бит. Если подпись действительна, результат равен -1; в противном случае это 0. Обратите внимание, что CHKSIGNU создает 256-битный срез с хешем и вызывает CHKSIGNS. То есть, если hash вычисляется как хеш некоторых данных, эти данные хешируются дважды, второе хеширование происходит внутри CHKSIGNS.
check_data_signature
int check_data_signature(slice data, slice signature, int public_key) asm "CHKSIGNS";
Проверяет, является ли signature допустимой подписью Ed25519 части данных slice data, используя public_key, аналогично check_signature. Если длина бит data не делится на восемь, выдается исключение переполнения ячейки. Проверка подписей Ed25519 является стандартной, с использованием sha256 для сокращения data до 256-битного числа, которое фактически подписано.
Вычисление размера boc
Приведенные ниже примитивы могут быть полезны для расчета платы за хранение предоставленных пользователем данных.
compute_data_size?
(int, int, int, int) compute_data_size?(cell c, int max_cells) asm "CDATASIZEQ NULLSWAPIFNOT2 NULLSWAPIFNOT";
Возвращает (x, y, z, -1) или (null, null, null, 0). Рекурсивно вычисляет количество отдельных ячеек x, битов данных y и ссылок на ячейки z в DAG с корнем cell c, фактически возвращая общее хранилище, используемое этим DAG, с учетом идентификации равных ячеек. Значения x, y и z вычисляются путем обхода в глубину этого DAG с хэш-таблицей хэшей посещенных ячеек, используемых для предотвращения посещений уже посещенных ячеек. Общее количество посещенных ячеек x не может превышать неотрицательного max_cells; в противном случае в ычисление прерывается до посещения (max_cells + 1)-й ячейки и возвращается нулевой флаг, указывающий на ошибку. Если c равно null, возвращается x = y = z = 0.
slice_compute_data_size?
(int, int, int, int) slice_compute_data_size?(slice s, int max_cells) asm "SDATASIZEQ NULLSWAPIFNOT2 NULLSWAPIFNOT";
Аналогично compute_data_size?, но принимает slice s вместо cell. Возвращаемое значение x не учитывает ячейку, содержащую сам срез s; однако биты данных и ссылки на ячейки s учитываются в y и z.
compute_data_size
(int, int, int) compute_data_size(cell c, int max_cells) impure asm "CDATASIZE";
Не тихая версия compute_data_size?, которая выдает исключение переполнения ячейки (8) при сбое.
slice_compute_data_size
(int, int, int) slice_compute_data_size(slice s, int max_cells) impure asm "SDATASIZE";
Не тихая версия slice_compute_data_size?, которая выдает исключение переполнения ячейки (8) при сбое.
Сохранение и загрузка постоянного хранилища
get_data
cell get_data() asm "c4 PUSH";
Возвращает ячейку постоянного хранилища контракта. Позже ее можно проанализировать или изменить с помощью примитивов среза и конструктора.
set_data
() set_data(cell c) impure asm "c4 POP";
Устанавливает ячейку c как постоянные данные контракта. Вы можете обновить постоянное хранилище контракта с помощью этого примитива.
Примитивы продолжения
get_c3
cont get_c3() impure asm "c3 PUSH";
Обычно c3 имеет продолжение, инициализированное всем кодо м контракта. Оно используется для вызовов функций. Примитив возвращает текущее значение c3.
set_c3
() set_c3(cont c) impure asm "c3 POP";
Обновляет текущее значение c3. Обычно используется для обновления кода смарт-контракта во время выполнения. Обратите внимание, что после выполнения этого примитива текущий код (и стек рекурсивных вызовов функций) не изменится, но любой другой вызов функции будет использовать функцию из нового кода.
bless
cont bless(slice s) impure asm "BLESS";
Преобразует slice s в простое обычное продолжение c с c.code = s, пустым стеком и списком сохранения.
Примитивы, связанные с газом
accept_message
() accept_message() impure asm "ACCEPT";
Устанавливает текущий лимит газа gl на максимально допустимое значение gm и сбрасывает газовый кредит gc на ноль, уменьшая значение gr на gc в процессе. Другими словами, текущий смарт-контракт соглашается купить немного газа, чтобы завершить текущую транзакцию. Это действие требуется для обработки внешних сообщений, которые не несут никакой ценности (следовательно, нет газа).
Для получения более подробной информации проверьте accept_message effects
set_gas_limit
() set_gas_limit(int limit) impure asm "SETGASLIMIT";
Устанавливает текущий лимит газа gl на минимальное значение limit и gm и сбрасывает газовый кредит gc на ноль. В этот момент, если количество потребленного газа (включая текущую инструкцию) превышает результирующее значение gl, перед установкой новых лимитов газа выдается (необработанное) исключение отсутствия газа. Обратите внимание, что set_gas_limit с аргументом limit ≥ 2^63 − 1 эквивалентно accept_message.
Для получения более подробной информации см. accept_message effects
commit
() commit() impure asm "COMMIT";
Фиксирует текущее состояние регистров c4 ("постоянные данные") и c5 ("действия"), так что текущее выполнение считается "успешным" с сохраненными значениями, даже если позже выдается исключение.
buy_gas
() buy_gas(int gram) impure asm "BUYGAS";
Код операции BUYGAS в настоящее время не реализован
Вычисляет количество газа, которое можно купить за gram nanotoncoin, и устанавливает gl соответственно так же, как set_gas_limit.
Примитивы действий
raw_reserve
() raw_reserve(int amount, int mode) impure asm "RAWRESERVE";
Создает выходное действие, которое зарезервирует ровно amount nanotoncoin (если mode = 0), максимум amount nanotoncoin (если mode = 2) или все, кроме amount nanotoncoin (если mode = 1 или mode = 3) из оставшегося баланса на аккаунте. Это примерно эквивалентно созданию исходящего сообщения, переносящего amount nanotoncoin (или b − amount nanotoncoin, где b — оставшийся баланс) самому себе, так что последующие выходные действия не смогут потратить больше денег, чем остаток. Бит +2 в mode означает, что внешнее действие не терпит неудачу, если указанная сумма не может быть зарезервирована; вместо этого весь оставшийся баланс резервируется. Бит +8 в mode означает amount <- -amount перед выполнением любых дальнейших действий. Бит +4 в mode означает, что amount увеличивается на исходный баланс текущего аккаунта (до фазы вычислений), включая все дополнительные валюты перед выполнением любых других проверок и действий. В настоящее время amount должно быть неотрицательным целым числом, а mode должно быть в диапазоне 0..15.
raw_reserve_extra
() raw_reserve_extra(int amount, cell extra_amount, int mode) impure asm "RAWRESERVEX";
Похоже на raw_reserve, но также принимает словарь extra_amount (представленный cell или null) с дополнительными валютами. Таким образом, можно зарезервировать валюты, отличные от Toncoin.
send_raw_message
() send_raw_message(cell msg, int mode) impure asm "SENDRAWMSG";
Отправляет необработанное сообщение, содержащееся в msg, которое должно содержать правильно сериализованный объект Message X, с единственным исключением, что исходный адрес может иметь фиктивное значение addr_none (которое будет автоматически заменено текущим адресом смарт-контракта), а поля ihr_fee, fwd_fee, created_lt и created_at могут иметь произвольные значения (которые будут перезаписаны правильными значениями во время фазы действия текущей транзакции). Целочисленный параметр mode содержит флаги.
В настоящее время существует 3 режима и 4 флага для сообщений. Вы можете объединить один режим с несколькими (возможно, ни одним) флагами, чтобы получить требуемый mode. Комбинация просто означает получение суммы их значений. Таблица с описаниями режимов и флагов приведена ниже.
| Режим | Описание |
|---|---|
0 | Обычное сообщение |
64 | Перенести всю оставшуюся стоимость входящего сообщения в дополнение к стоимости, изначально указанной в новом сообщении |
128 | Перенести весь оставшийся баланс текущего смарт-контракта вместо стоимости, изначально указанной в сообщении |
| Флаг | Описание |
|---|---|
+1 | Оплатить комиссию за перевод отдельно от стоимости сообщения |
+2 | Игнорировать некоторые ошибки, возникающие при обработке этого сообщения на этапе действия (см. примечание ниже) |
+16 | В случае сбоя действия — возврат транзакции. Никакого эффекта, если используется +2. |
+32 | Текущий аккаунт должен быть уничтожен, если его результирующий баланс равен нулю (часто используется с режимом 128) |
- Недостаточно Toncoin:
- Недостаточно стоимости для перевода с сообщением (вся стоимость входящего сообщения была израсходована).
- Недостаточно средств для обработки сообщения.
- Недостаточно стоимости, прикрепленной к сообщению, для оплаты комиссий за пересылку.
- Недостаточно дополнительной валюты для отправки с сообщением.
- Недостаточно средств для оплаты исходящего внешнего сообщения.
- Сообщение слишком большое (проверьте размер сообщения для получения дополнительной информации).
- Сообщение имеет слишком большую глубину Меркла.
Однако он не игнорирует ошибки в следующих сценариях:
- Сообщение имеет недопустимый формат.
- Режим сообщения включает как 64, так и 128 модификаций.
- Исходящее сообщение имеет недопустимые библиотеки в StateInit.
- Внешнее сообщение не является обычным или включает флаг +16 или +32 или оба
- Флаг +16 - не использовать во внешних сообщениях (например, на кошельках), так как нет отправителя, который мог бы получить отклоненное сообщение.
- Флаг +2 - важно во внешних сообщениях (например, на кошельках).
Вы можете увидеть подробный пример здесь.
set_code
() set_code(cell new_code) impure asm "SETCODE";
Создает выходное действие, которое изменит этот код смарт-контракта на тот, который задан ячейкой new_code. Обратите внимание, что это изменение вступит в силу только после успешного завершения текущего выполнения смарт-контракта. (Ср. set_c3)
Примитивы генератора случайных чисел
Генератор псевдослучайных чисел использует случайное начальное число, беззнаковое 256-битное целое число и (иногда) дру гие данные, хранящиеся в c7. Начальное значение случайного начального числа перед выполнением смарт-контракта в блокчейне TON представляет собой хэш адреса смарт-контракта и глобального случайного начального числа блока. Если внутри блока есть несколько запусков одного и того же смарт-контракта, то все эти запуски будут иметь одинаковое случайное начальное число. Это можно исправить, например, запустив randomize_lt перед первым использованием генератора псевдослучайных чисел.
Keep in mind that random numbers generated by the functions below can be predicted if you do not use additional tricks.
random
int random() impure asm "RANDU256";
Генерирует новое псевдослучайное целое число без знака длиной 256 бит x. Алгоритм следующий: если r — это старое значение случайного начального числа, рассматриваемого как 32-байтовый массив (путем построения представления с обратным порядком байтов без знака длиной 256 бит), то вычисляется его sha512(r); первые 32 байта этого хэша сохраняются как новое значение r' случайного начального числа, а оставшиеся 32 байта возвращаются как следующее случайное значение x.
rand
int rand(int range) impure asm "RAND";
Генерирует новое псевдослучайное целое число z в диапазоне 0..range−1 (или range..−1, если range < 0). Точнее, генерируется случайное значение x без знака, как в random; затем z := x * range / 2^256 вычисляется.
get_seed
int get_seed() impure asm "RANDSEED";
Возвращает текущее случайное начальное число как беззнаковое 256-битное целое число.
set_seed
int set_seed(int seed) impure asm "SETRAND";
Устанавливает случайное начальное число как беззнаковое 256-битное seed.
randomize
() randomize(int x) impure asm "ADDRAND";
Смешивает беззнаковое 256-битное целое число x со случайным начальным числом r, устанавливая для случайного начального значения значение sha256 для объединения двух 32-байтовых строк: первая с представлением старого начального значения числа r, а вторая с представлением значения в порядке возрастания x.
randomize_lt
() randomize_lt() impure asm "LTIME" "ADDRAND";
Эквивалентно randomize(cur_lt());.
Примитивы манипуляции адресами
Примитивы манипуляции адресами, перечисленные ниже, сериализуют и десериализуют значения в соответствии со следующей схемой TL-B.
addr_none$00 = MsgAddressExt;
addr_extern$01 len:(## 8) external_address:(bits len)
= MsgAddressExt;
anycast_info$_ depth:(#<= 30) { depth >= 1 }
rewrite_pfx:(bits depth) = Anycast;
addr_std$10 anycast:(Maybe Anycast)
workchain_id:int8 address:bits256 = MsgAddressInt;
addr_var$11 anycast:(Maybe Anycast) addr_len:(## 9)
workchain_id:int32 address:(bits addr_len) = MsgAddressInt;
_ _:MsgAddressInt = MsgAddress;
_ _:MsgAddressExt = MsgAddress;
int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool
src:MsgAddress dest:MsgAddressInt
value:CurrencyCollection ihr_fee:Grams fwd_fee:Grams
created_lt:uint64 created_at:uint32 = CommonMsgInfoRelaxed;
ext_out_msg_info$11 src:MsgAddress dest:MsgAddressExt
created_lt:uint64 created_at:uint32 = CommonMsgInfoRelaxed;
Десериализованный MsgAddress представлен кортежем t следующим образом:
addr_noneпредставлен какt = (0), т. е. кортеж, содержащий ровно одно целое число, равное нулюaddr_externпредставлен какt = (1, s), где срезsсодержит полеexternal_address. Другими словами,t- это пара (кортеж, состоящий из двух записей), содержащая целое число, равное единице, и срезsaddr_stdпредставлен какt = (2, u, x, s), гдеu- это либоnull(еслиanycastотсутствует), либо срезs', содержащийrewrite_pfx(еслиanycastприсутствует). Далее, целое числоxявляетсяworkchain_id, а срезsсодержит адресaddr_varпредставлено какt = (3, u, x, s), гдеu,xиsимеют то же значение, что и дляaddr_std
load_msg_addr
(slice, slice) load_msg_addr(slice s) asm( -> 1 0) "LDMSGADDR";
Загружает из slice s единственный префикс, который является допустимым MsgAddress, и возвращает как этот префикс s', так и остаток s'' от s в виде срезов.
parse_addr
tuple parse_addr(slice s) asm "PARSEMSGADDR";
Раскладывает slice s, содержащий допустимый MsgAddress, на tuple t с отдельными полями этого MsgAddress. Если s не является допустимым MsgAddress, выдается исключение десериализации ячейки.
parse_std_addr
(int, int) parse_std_addr(slice s) asm "REWRITESTDADDR";
Анализирует срез s, содержащий допустимый MsgAddressInt (обычно msg_addr_std), применяет перезапись из anycast (если присутствует) к префиксу адреса той же длины и возвращает как воркчейн, так и 256-битный адрес в виде целых чисел. Если адрес не 256-битный или если s не является допустимой сериализацией MsgAddressInt, выдает исключение deserialization ячейки.
parse_var_addr
(int, slice) parse_var_addr(slice s) asm "REWRITEVARADDR";
Вариант parse_std_addr, который возвращает (переписанный) адрес как срез s, даже е сли его длина не точно 256 бит (представлено msg_addr_var).
Примитивы отладки
Примитивы отладки можно использовать для проверки состояния различных переменных во время выполнения тестов или консольных скриптов.
~dump
forall X -> () ~dump(X value) impure asm "s0 DUMP";
Выводит значение. Несколько значений можно вывести как кортеж, например ~dump([v1, v2, v3]).
~strdump
() ~strdump(slice str) impure asm "STRDUMP";
Выводит строку. Длина бит параметра среза должна делиться на 8.
dump_stack
() dump_stack() impure asm "DUMPSTK";
Выводит стек (максимум 255 верхних значений) и показывает общую глубину стека.
Примитивы среза
Говорят, что примитив загружает некоторые данные, если он возвращает данные и остаток среза (поэтому его также можно использовать как модифицирующий метод).
Говорят, что примитив загружает некоторые данные, если он возвращает только данные (его можно использовать как немодифицирующий метод).
Если не указано иное, примитивы загрузки и предзагрузки считывают данные из префикса фрагмента.
begin_parse
slice begin_parse(cell c) asm "CTOS";
Преобразует cell в slice. Обратите внимание, что c должна быть либо обычной ячейкой, либо экзотической ячейкой (см. TVM.pdf, 3.1.2), которая автоматически загружается для получения обычной ячейки c', преобразованной впоследствии в slice.
end_parse
() end_parse(slice s) impure asm "ENDS";
Проверяет, является ли s пустым. Если нет, выдает исключение.
load_ref
(slice, cell) load_ref(slice s) asm( -> 1 0) "LDREF";
Загружает первую ссылку из среза.
preload_ref
cell preload_ref(slice s) asm "PLDREF";
Предварительно загружает первую ссылку из среза.
load_int
;; (slice, int) ~load_int(slice s, int len) asm(s len -> 1 0) "LDIX";
Загружает знаковое len-битное целое число из среза.
load_uint
;; (slice, int) ~load_uint(slice s, int len) asm( -> 1 0) "LDUX";
Загружает беззнаковое len-битное целое число из среза.
preload_int
;; int preload_int(slice s, int len) asm "PLDIX";
Предварительно загружает знаковое len-битное целое число из среза.
preload_uint
;; int preload_uint(slice s, int len) asm "PLDUX";
Предварительно загружает беззнаковое len-битное целое число из среза.
load_bits
;; (slice, slice) load_bits(slice s, int len) asm(s len -> 1 0) "LDSLICEX";
Загружает первые 0 ≤ len ≤ 1023 бит из среза s в отдельный срез s''.
preload_bits
;; slice preload_bits(slice s, int len) asm "PLDSLICEX";
Предварительно загружает первые 0 ≤ len ≤ 1023 бит из slice s в отдельный slice s''.
load_coins
(slice, int) load_coins(slice s) asm( -> 1 0) "LDGRAMS";
Загружает сериализованное количество Toncoin (любое беззнаковое целое число до 2^120 - 1).
skip_bits
slice skip_bits(slice s, int len) asm "SDSKIPFIRST";
(slice, ()) ~skip_bits(slice s, int len) asm "SDSKIPFIRST";
Возвращает все, кроме первых 0 ≤ len ≤ 1023 бит s.
first_bits
slice first_bits(slice s, int len) asm "SDCUTFIRST";
Возвращает первые 0 ≤ len ≤ 1023 бит s.
skip_last_bits
slice skip_last_bits(slice s, int len) asm "SDSKIPLAST";
(slice, ()) ~skip_last_bits(slice s, int len) asm "SDSKIPLAST";
Возвращает все, кроме последних 0 ≤ len ≤ 1023 бит s.
slice_last
slice slice_last(slice s, int len) asm "SDCUTLAST";
Возвращает последние 0 ≤ len ≤ 1023 бит s.
load_dict
(slice, cell) load_dict(slice s) asm( -> 1 0) "LDDICT";
Загружает словарь D из среза s. Может применяться к словарям или к значениям произвольных типов Maybe ^Y (возвращает null, если используется конструктор nothing).
preload_dict
cell preload_dict(slice s) asm "PLDDICT";
Предварительно загружает словарь D из среза s.
skip_dict
slice skip_dict(slice s) asm "SKIPDICT";
Загружает словарь как load_dict, но возвращает только остаток среза.
Примитивы размера среза
slice_refs
int slice_refs(slice s) asm "SREFS";
Возвращает количество ссылок в срезе s.
slice_bits
int slice_bits(slice s) asm "SBITS";
Возвращает количество бит данных в срезе s.
slice_bits_refs
(int, int) slice_bits_refs(slice s) asm "SBITREFS";
Возвращает как количество бит данных, так и количество ссылок в s.
slice_empty?
int slice_empty?(slice s) asm "SEMPTY";
Проверяет, является ли срез s пустым (т. е. не содержит бит данных и ссылок на ячейки).
slice_data_empty?
int slice_data_empty?(slice s) asm "SDEMPTY";
Проверяет, нет ли в срезе s битов данных.
slice_refs_empty?
int slice_refs_empty?(slice s) asm "SREMPTY";
Проверяет, нет ли в срезе s ссылок.
slice_depth
int slice_depth(slice s) asm "SDEPTH";
Возвращает глубину среза s. Если в s нет ссылок, то возвращается 0; в противном случае возвращаемое значение равно единице плюс максимальная глубина ячеек, на которые ссылается s.
Примитивы конструктора
Говорят, что примитив сохраняет значение x в конструкторе b, если он возвращает измененную версию конструктора b' со значением x, сохраненным в конце. Его можно использовать как немодифицирующий метод.
Все перечисленные ниже примитивы сначала проверяют, достаточно ли места в builder, а затем диапазон сериализуемого значения.
begin_cell
builder begin_cell() asm "NEWC";
Создает новый пустой builder.
end_cell
cell end_cell(builder b) asm "ENDC";
Преобразует builder в обычную cell.
store_ref
builder store_ref(builder b, cell c) asm(c b) "STREF";
Сохраняет ссылку на ячейку c в builder b.
store_uint
builder store_uint(builder b, int x, int len) asm(x b len) "STUX";
Сохраняет беззнаковое len-битное целое x в b для 0 ≤ len ≤ 256.
store_int
builder store_int(builder b, int x, int len) asm(x b len) "STIX";
Сохраняет знаковое len-битное целое x в b для 0 ≤ len ≤ 257.
store_slice
builder store_slice(builder b, slice s) asm "STSLICER";
Сохраняет срез s в builder b.
store_grams
builder store_grams(builder b, int x) asm "STGRAMS";
store_coins
builder store_coins(builder b, int x) asm "STGRAMS";
Сохраняет (сериализует) целое x в диапазоне 0..2^120 − 1 в builder b. Сериализация x состоит из 4-битного беззнакового целого числа с обратным порядком байтов l, которое является наименьшим целым числом l ≥ 0, таким образом, что x < 2^8l, за которым следует 8l-битное беззнаковое представление x с обратным порядком байтов. Если x не принадлежит поддерживаемому диапазону, выдается исключение проверки диапазона.
Это наиболее распространенный способ хранения Toncoin.
store_dict
builder store_dict(builder b, cell c) asm(c b) "STDICT";
Сохраняет словарь D, представленный ячейкой c или null, в builder b. Другими словами, сохраняет 1-бит и ссылку на c, если c не является null, и 0-бит в противном случае.
store_maybe_ref
builder store_maybe_ref(builder b, cell c) asm(c b) "STOPTREF";
Эквивалентно store_dict.
Примитивы размера конструктора
builder_refs
int builder_refs(builder b) asm "BREFS";
Возвращает количество ссылок на ячейки, уже сохраненных в Builder b.
builder_bits
int builder_bits(builder b) asm "BBITS";
Возвращает количество битов данных, уже сохраненных в Builder b.
builder_depth
int builder_depth(builder b) asm "BDEPTH";
Возвращает глубину builder b. Если в b не сохранено ссылок на ячейки, то возвращает 0; в противном случае возвращаемое значение равно единице плюс максимальная глубина ячеек, на которые ссылается b.