Repository navigation
flang 0.7.31 — Ядро доказывает записи по полям и остаток в кольце; слова u8…u64 и битовые операции; контрпример постусловия на краях типов
Ядро доказывает записи по полям и остаток в кольце; слова u8…u64 и битовые операции; контрпример постусловия на краях типов
Что появилось
- Ядро доказывает равенство записей по полям. Утверждения
(запись «Пара» с а равным п.а и б равным п.б) равно пиесли (п.а равно д.а) и притом (п.б равно д.б) то п равно д иначе датеперь доказаны, и независимый сверщик это подтверждает:проиграно 2 из 2 доказанных, код 0. Раньше оба оставались «не доказано», иcheck --proofотвечал кодом 3. - Перестановка слагаемых доказывается и под
остаток от. Дляточное целоеутверждение((а плюс б) остаток от м) равно ((б плюс а) остаток от м)доказано так же, кака плюс б равно б плюс а. Раньше под остатком ядро его не брало. - Условие на весь список переходит на хвост. Функция с
требует «все положительны» для всех э из элементы: э больше 0может звать себя отхвоств ветвислучай голова и хвост. Раньше на таком вызове была ошибкаFLANG_PRECONDITION_CALL. - Целые фиксированной ширины:
u8,u16,u32,u64и знаковыеi8…i64. Значение пишетсяu32 5, в примере —дано х равно u32 1. Переполнение — ошибкаFLANG_OVERFLOW, а арифметику по модулю 2^w пишут явно:а плюс б с переполнением(наu32 4294967295иu32 2даётu32 1). Литерал вне типа отвергает проверка:а плюс 300приа: u8—литерал 300 не помещается в u8: от 0 до 255. - Битовые операции и сдвиги.
побитовое и,побитовое или,исключающее или,побитовое не,сдвиг влево на,сдвиг вправо на,поворот влево на,поворот вправо на. Например, Σ0 из SHA-256 —(х поворот вправо на 2) исключающее или (х поворот вправо на 13) исключающее или (х поворот вправо на 22)— наu32 1даётu32 1074267136. У знаковых сдвиг вправо арифметический:i32 -9сдвиг вправо на 1 —i32 -5. - Полное произведение двух слов.
а умножить на б с двойной разрядностьюдаёт запись с полямистаршаяимладшая; на ней строится длинная арифметика без 128-битного типа. Наа = u64 4294967296иб = u64 4294967296полестаршая—u64 1. - Завершение взаимной рекурсии по убыванию размера. Круг вызовов проходит проверку, если на каждом его обороте какой-то аргумент строго уменьшается, даже если между функциями он меняет место. Пример: «Прочитать» идёт по списку и зовёт «Прочитать в» от хвоста, а «Прочитать в» разбирает номер и зовёт «Прочитать» от его предшественника. Раньше —
FLANG_NOT_TOTAL: в цикле «Прочитать» → «Прочитать в» нет аргумента, который убывает, теперь —проверено. - Ядро раскрывает вызов на построенном варианте.
«Чередовать» от (вариант «След» с прежний равным н)ядро подставляет в нужную ветвьразбор, и постусловиерезультат равно «Сменить» от («Чередовать» от н)доказано, в том числе для рекурсивной функции. Раньше оно держалось только на примерах. - В
flang replесть.текст. Вставьте текст и закончите строкой.конец— оболочка сама поймёт, программа это, формула (с ∀/∃ или в LaTeX), рассуждение или категория, и проверит. На\forall a \in \mathbb{Z}, a + 1 = aответ —утверждение «формула» опровергнуто на входе a = 0(код 1). - Блок
историяпроверяет и независимый сверщик.check --proofна файле систория «потолок скидки»теперь отвечаетпроиграно 1 из 1 доказанныхи кодом 0. Раньше — код 3: сверщик истории не читал. - На сайте — кнопка «Попробовать в браузере» в шапке каждой страницы, она ведёт в песочницу. Формулы в песочнице набираются KaTeX, который лежит на самом сайте, поэтому они видны и там, где внешние CDN закрыты. Песочница подсвечивает рассуждения и формулы по их виду.
Что изменилось
- Свёртка сохраняет узкий тип накопителя.
свёртка новые начиная с л как акк и н → аккприл: список неотрицательное— этосписок неотрицательное. Раньше здесь была ошибкаFLANG_TYPE: «тело даёт список числа». - Число сужается до
неотрицательноепроверкой. В ветвитопослеесли (значение не меньше 0) и притом ((значение остаток от 1) равно 0) и притом (значение не больше 9007199254740991)значение уженеотрицательное, и функцию можно объявить свозвращает неотрицательное. - Рекурсия по разности под условием. В ветви
если бит не меньше уровеньзначениебит минус уровень— неотрицательное, и вызов«Спуск» от (бит минус уровень) и уровеньприуровень не меньше 1проходит проверку завершения. Раньше —FLANG_TYPEиFLANG_NOT_TOTAL. - Исправлены ложные постусловия библиотеки. Новая проверка на краях типов нашла в
base64,sha256иsqliteутверждения, ложные на отрицательном или дробном входе: остаток от деления сохраняет знак делимого. Каждое теперь называет входы, на которых верно (конечное неотрицательное число, целый байт, размер страницы от 512 до 65536). Сами функции считают как раньше. - Верхняя граница
u64сравнивается точно. Постусловиерезультат не больше 18446744073709550592(это 2^64−1024) ук числу хприх: u64больше не доказывается: наибольшее значениеu64больше. Раньше ядро сравнивало границу в двойной точности и называло такой шаг доказанным, хотя сверщики его отвергали.
Что сломалось
- Постусловие, ложное на краю типа, теперь ошибка.
checkпробует края типов параметров и границы изтребует. Функция «Скидка» собеспечивает «не больше пятисот» результат не больше 500и теломесли сумма больше 100000 то 501 иначе 0раньше проходила с пометкой «проверено только на примерах» (код 3), а теперь —постусловие «не больше пятисот» функции «Скидка» нарушено на входе сумма = 2147483647и код 1. Как починить: вход из сообщения — контрпример; сузьте вход строкойтребуетили исправьте постусловие. - Известное ограничение: постусловие с «для всех … таких что» может быть отвергнуто зря. Новая проверка на краях типов не учитывает ограничение «таких что» и пробует вход вне его. Например, верное
для всех н таких что н не меньше 0 обеспечивает «сдвиг неотрицателен» результат не меньше 0у функции с теломнполучаетпостусловие «сдвиг неотрицателен» функции «Сдвиг» нарушено на входе н = -1и код 1. Как обойти сейчас: запишите ограничение внутри постусловия —обеспечивает «сдвиг неотрицателен» если н не меньше 0 то результат не меньше 0 иначе да; так оно доказано, и сверщик это подтверждает. Исправим в следующем выпуске.
Описание языка
Разделы DESCRIPTION.md с v0.7.30 не менялись.
The kernel proves records by fields and remainders in the ring; u8…u64 words and bit operations; postcondition counterexamples at the type edges
What appeared
- The kernel proves records equal by their fields. The claims
(запись «Пара» с а равным п.а и б равным п.б) равно п(a record built from the fields of p is p) andесли (п.а равно д.а) и притом (п.б равно д.б) то п равно д иначе да(equal fields make equal records) are now proved, and the independent checker confirms it:проиграно 2 из 2 доказанных(2 of 2 replayed), exit code 0. Before, both stayed unproved andcheck --proofexited with 3. - Swapping the summands is proved under
остаток от(remainder) too. Forточное целое(exact integer) the claim((а плюс б) остаток от м) равно ((б плюс а) остаток от м)is proved just likeа плюс б равно б плюс а. Before, the kernel did not take it under a remainder. - A condition on the whole list carries over to the tail. A function with
требует «все положительны» для всех э из элементы: э больше 0(requires every element to be positive) may call itself onхвост(the tail) in theслучай голова и хвостbranch. Before, that call was the errorFLANG_PRECONDITION_CALL. - Fixed-width integers:
u8,u16,u32,u64and signedi8…i64. A value is writtenu32 5, in an exampleдано х равно u32 1. Overflow is the errorFLANG_OVERFLOW; arithmetic modulo 2^w is written out:а плюс б с переполнением(with wrap-around; onu32 4294967295andu32 2it givesu32 1). A literal outside the type is refused by the check:а плюс 300withа: u8givesлитерал 300 не помещается в u8: от 0 до 255. - Bit operations and shifts.
побитовое и(and),побитовое или(or),исключающее или(xor),побитовое не(not),сдвиг влево на,сдвиг вправо на(shift left, right),поворот влево на,поворот вправо на(rotate left, right). For example, SHA-256 Σ0 —(х поворот вправо на 2) исключающее или (х поворот вправо на 13) исключающее или (х поворот вправо на 22)— givesu32 1074267136onu32 1. A right shift of a signed word is arithmetic:i32 -9shifted right by 1 isi32 -5. - The full product of two words.
а умножить на б с двойной разрядностью(double width) gives a record with the fieldsстаршая(high) andмладшая(low), enough for long arithmetic without a 128-bit type. Forа = u64 4294967296andб = u64 4294967296the fieldстаршаяisu64 1. - Mutual recursion terminates by decreasing size. A cycle of calls passes the check when on every round some argument strictly shrinks, even if it moves to another position between the functions. Example: «Прочитать» walks a list and calls «Прочитать в» on the tail, and «Прочитать в» takes a number apart and calls «Прочитать» on its predecessor. Before:
FLANG_NOT_TOTAL: в цикле «Прочитать» → «Прочитать в» нет аргумента, который убывает(no decreasing argument in the cycle); now:проверено(checked). - The kernel unfolds a call on a built variant.
«Чередовать» от (вариант «След» с прежний равным н)is unfolded into the matching branch ofразбор, so the postconditionрезультат равно «Сменить» от («Чередовать» от н)is proved, recursive functions included. Before, it rested on the examples only. .текстinflang repl. Paste a text and end it with a line.конец— the shell tells whether it is a program, a formula (with ∀/∃ or in LaTeX), a reasoning or a category, and checks it. For\forall a \in \mathbb{Z}, a + 1 = athe answer isутверждение «формула» опровергнуто на входе a = 0(refuted at a = 0, exit code 1).- The independent checker reads
история(user story) blocks.check --proofon a file withистория «потолок скидки»now answersпроиграно 1 из 1 доказанныхand exit code 0. Before: exit code 3, the checker did not read stories. - A “Try in the browser” button in the header of every site page leads to the playground. Formulas in the playground are typeset by KaTeX served from the site itself, so they show where outside CDNs are blocked. The playground colours reasonings and formulas by their kind.
What changed
- A fold keeps the narrow type of its accumulator.
свёртка новые начиная с л как акк и н → аккwithл: список неотрицательноеis aсписок неотрицательное(list of non-negative). Before, it was the errorFLANG_TYPE: the body gives a list of numbers. - A number narrows to
неотрицательное(non-negative) by a check. In theтоbranch afterесли (значение не меньше 0) и притом ((значение остаток от 1) равно 0) и притом (значение не больше 9007199254740991)the value is already non-negative, and the function may be declaredвозвращает неотрицательное. - Recursion on a difference under a condition. In the branch
если бит не меньше уровень(bit is at least level) the valueбит минус уровеньis non-negative, and the call«Спуск» от (бит минус уровень) и уровеньwithуровень не меньше 1passes the termination check. Before:FLANG_TYPEandFLANG_NOT_TOTAL. - False library postconditions are fixed. The new check at the type edges found claims in
base64,sha256andsqlitethat were false on a negative or fractional input: the remainder keeps the sign of the dividend. Each claim now names the inputs it holds for (a finite non-negative number, a whole byte, a page size from 512 to 65536). The functions compute what they did before. - The upper bound of
u64is compared exactly. The postconditionрезультат не больше 18446744073709550592(2^64−1024) ofк числу хwithх: u64is no longer proved: the largestu64is bigger. Before, the kernel compared the bound in double precision and called that step proved, though the checkers refused it.
What broke
- A postcondition false at a type edge is now an error.
checktries the edges of the parameter types and the bounds fromтребует(requires). The function «Скидка» withобеспечивает «не больше пятисот» результат не больше 500(ensures the result is at most 500) and the bodyесли сумма больше 100000 то 501 иначе 0used to pass as “checked on examples only” (exit code 3); now it isпостусловие «не больше пятисот» функции «Скидка» нарушено на входе сумма = 2147483647(violated at сумма = 2147483647) and exit code 1. How to fix: the input in the message is a counterexample; narrow the input with aтребуетline or fix the postcondition. - Known limitation: a postcondition with “for all … such that” may be refused by mistake. The new check at the type edges ignores the “such that” restriction and tries an input outside it. For example, the correct
для всех н таких что н не меньше 0 обеспечивает «сдвиг неотрицателен» результат не меньше 0(for all n such that n ≥ 0, the result is ≥ 0) of a function whose body isнgetsпостусловие «сдвиг неотрицателен» функции «Сдвиг» нарушено на входе н = -1(violated at n = -1) and exit code 1. Workaround for now: put the restriction inside the postcondition —обеспечивает «сдвиг неотрицателен» если н не меньше 0 то результат не меньше 0 иначе да(if n ≥ 0 then the result is ≥ 0, else true); this form is proved, and the checker confirms it. The fix comes in the next release.
Страница выпусков: по-русски · in English.
Архив flang-0.7.31-c.tar.gz — исходники C99 и Makefile: make && sudo make install, Node не нужен. Или brew install digitable-lol/tap/flang.