flang компилятор доказывает, что программа не зациклится 0.6.2 GitHub English

Справочник отказов

Компилятор отказывает кодом. Код всегда стоит первым словом строки:

FLANG_TYPE в файле type.flang, строка 6, столбец 3: функция «Удвоить» объявлена как число, а тело даёт строка

Найдите свой код на этой странице: одна строка «что это значит», одна «что делать». Коды сгруппированы по слою, на котором отказ рождается: пока не пройден разбор, до типов дело не дойдёт, а пока не сошлись типы — до доказательств.

Коды возврата: 0 — проверено, 1 — есть замечания, 2 — кривой вызов.

Три ловушки, которые стоят дня

Прочитайте их до того, как начнёте искать свой код. Каждая даёт отказ не там, где ошибка.

Постусловие, зовущее функцию своего же модуля, ломает тех, кто ввозит модуль списком

Файл зелёный у себя. Ввозящий падает.

// ядро.flang
модуль «Ядро»

тотальная функция «Двойка»
  принимает н: число
  возвращает число
  н умножить на 2

тотальная функция «Учтено»
  принимает н: число
  возвращает число
  обеспечивает «не меньше двойки» результат не меньше («Двойка» от н)
  («Двойка» от н) плюс 1
// ввоз.flang
модуль «Ввоз»
использует «Ядро» только «Учтено»

тотальная функция «Проба»
  принимает н: число
  возвращает число
  «Учтено» от н
flang check ядро.flang
модуль «Ядро»: функций 2, из них с доказанным завершением 2; типов 0
ядро.flang: проверено — разбор, типы, завершаемость, ядро и примеры; замечаний нет
flang check ввоз.flang
модуль «Ввоз»: функций 2, из них с доказанным завершением 0; типов 0; файлов вместе с импортами 2
без доказанного завершения: «Учтено» «Проба»
FLANG_UNKNOWN_NAME, строка 12, столбец 4: неизвестная функция «Двойка»
FLANG_UNKNOWN_NAME, строка 11, столбец 50: неизвестная функция «Двойка»
FLANG_NOT_TOTAL, строка 12, столбец 4: тотальная функция «Учтено» вызывает неизвестную функцию «Двойка»: завершение доказать нельзя
ввоз.flang: не проверено — замечаний 3

Ввоз только «Учтено» приводит одно имя. Тело и постусловие «Учтено» зовут «Двойку», которой в ввозящем нет. Столбец 50 указывает внутрь постусловия — строка та же, что и в исходном модуле, а файл не назван: проверено два файла.

Что делать — одно из трёх:

приёмкак
привести спутникаиспользует «Ядро» только «Учтено», «Двойка»
ввезти модуль целикомиспользует «Ядро»
убрать вызов из постусловиясказать то же арифметикой: результат не меньше (н умножить на 2)

Зелёный вывод не значит, что утверждения доказаны

flang check без ключей проверяет разбор, типы, завершаемость и примеры. Постусловие, которое он не сумел ни доказать, ни опровергнуть, он пропускает молча. Постусловие «меньше двойки» из примера выше ложно — файл зелёный.

Спрашивайте прямо:

flang check ядро.flang --proof
  постусловие «меньше двойки» функции «Учтено» — объявлено, не доказано: ни теоремы, ни примеров. Его считает рантайм после каждого возврата — на тех входах, которые придут

Читайте слова буквально: «доказано» — обо всех входах; «сетка N» — посчитано на N значениях, доказательством не является; «объявлено, не доказано» — утверждение высказано, за ним ничего нет.

И второе: пока в проверке стоит FLANG_UNKNOWN_NAME, функция теряет обещание тотальная и её утверждения не доказывает никто. Сначала имена, потом всё остальное.

FLANG_BOUND_ON_NAN: «не число» живёт в типе число и стоит вне порядка

Самый частый ложный испуг. Утверждение выглядит очевидно верным, а ядро отвечает контрпримером.

модуль «Проба»

тотальная функция «Прибавить один»
  принимает н: число
  возвращает число
  обеспечивает «результат больше довода» результат больше н
  н плюс 1
FLANG_BOUND_ON_NAN в файле nan.flang, строка 6, столбец 3: постусловие «результат больше довода» функции «Прибавить один» ЛОЖНО, и контрпример назван: «н» объявлен типом «число», а «не число» живёт в этом типе и стоит ВНЕ ПОРЯДКА — оно не больше и не меньше ничего, включая самоё себя.

Причина: тип число содержит «не число», всякая арифметическая операция его переносит, а сравнение с ним ложно в обе стороны. Утверждение о порядке над сырой арифметикой поэтому неверно.

починкачто писатькто платит
сузить тип входапринимает н: неотрицательное или целоеникто, «не число» не втащить
поставить предусловиетребует «вход есть число» (н минус н) равен 0вызывающий
оговорить границу в самом утвержденииобеспечивает «…» не ((н минус н) равен 0) или (результат больше н)никто

Разбор

кодчто значитчто делать
FLANG_LEXслово не собралось: не закрыта кавычка, чужой знакзакройте кавычку, уберите знак
FLANG_PARSEслова разобраны, конструкция — нетсмотрите строку и столбец: чаще всего нет ветки иначе или у функции два тела
модуль «Проба»

тотальная функция «Удвоить»
  принимает н: число
  возвращает число
  если н больше 0 то н умножить на 2
FLANG_PARSE в файле parse.flang, строка 7, столбец 1: у 'если' нет ветки 'иначе'
FLANG_LEX в файле lex.flang, строка 5, столбец 3: не закрыта кавычка

Имена и ввоз

кодчто значитчто делать
FLANG_UNKNOWN_NAMEимя не связано: нет такой функции или переменнойобъявите её, ввезите модуль или проверьте написание
FLANG_AMBIGUOUS_NAMEимя приводят два ввоза сразуоставьте один ввоз или сузьте его списком только
FLANG_BAD_NAMEимя не годится по правилам записипереименуйте: имя функции — в кавычках-ёлочках, параметр — словом
FLANG_NAME_TAKENимя занято другим объявлениемдайте другое имя
FLANG_DUPLICATE_NAMEодно и то же имя объявлено дважды в одном местеуберите второе объявление
FLANG_IMPORT_NOT_FOUNDмодуль не найденпроверьте имя модуля и то, что файл лежит рядом или выше по каталогам
FLANG_IMPORT_CYCLEмодули ввозят друг друга по кругувынесите общее в третий модуль
FLANG_IMPORT_AMBIGUOUSодно имя приходит из двух модулейсузьте ввоз списком только
FLANG_IMPORT_NAMEв списке только названо имя, которого в модуле нетсверьте список с объявлениями модуля
модуль «Проба»

тотальная функция «Удвоить»
  принимает н: число
  возвращает число
  «Утроить» от н
FLANG_UNKNOWN_NAME в файле unknown.flang, строка 6, столбец 3: неизвестная функция «Утроить»
FLANG_NOT_TOTAL в файле unknown.flang, строка 6, столбец 3: тотальная функция «Удвоить» вызывает неизвестную функцию «Утроить»: завершение доказать нельзя

Незнакомое имя всегда тянет за собой второй отказ про завершаемость. Чините первый — второй уходит сам.

Если имя написано как действие, компилятор скажет об этом прямо:

FLANG_UNKNOWN_NAME в файле pr4.flang, строка 10, столбец 14: имя «м» не связано: имя вводят 'принимает', 'пусть' или образец 'случай'; а действия языка ('плюс', 'минус', 'умножить на', 'делить на', 'остаток от') пишутся МЕЖДУ значениями — «3.14 умножить на р», а не «умножить 3.14 на р»

Типы

кодчто значитчто делать
FLANG_TYPEобъявленный тип разошёлся с тем, что даёт тело или доводприведите одно к другому
FLANG_TYPE_ARGSтипу даны аргументы, а он их не принимаетуберите аргументы: типы в языке не параметрические
FLANG_TYPE_PARAMпараметр типа не связанназовите тип целиком
FLANG_APPLYвызов не сходится: не то число доводов или зовут не функциюсверьте вызов с подписью
FLANG_BUILTIN_ARGSвстроенному действию дали не столько доводовсверьте с описанием операции
FLANG_MATCH_NOT_EXHAUSTIVEразбор покрывает не все случаидопишите недостающий случай
FLANG_MATCH_UNREACHABLEслучай перекрыт предыдущим и никогда не сработаетуберите его или переставьте выше
FLANG_EXAMPLEпример не сошёлся с ожидаемымпочините тело или ожидание
FLANG_TYPE в файле type.flang, строка 6, столбец 3: функция «Удвоить» объявлена как число, а тело даёт строка
FLANG_TYPE в файле dup.flang, строка 8, столбец 1: функция «Удвоить» объявлена дважды
FLANG_MATCH_NOT_EXHAUSTIVE в файле match.flang, строка 6, столбец 3: разбор списка не покрывает «пусто»
FLANG_EXAMPLE: пример «Двойка» функции «Удвоить»: значение не совпало с ожидаемым: ожидалось 5, получено 4

Завершаемость и пределы

кодчто значитчто делать
FLANG_NOT_TOTALфункция объявлена тотальная, а завершение не доказанопередавайте в рекурсию ЧАСТЬ довода, а не пересчитанное число
FLANG_MEASUREобъявленная мера не убываетпоправьте убывает или сам вызов
FLANG_RECURSION_LIMITпри вычислении кончились шаги или глубинаподнимите --max-steps / --max-depth либо почините рекурсию
FLANG_STEP_LIMITпредел шагов кончился внутри примератот же ключ --max-steps
FLANG_BUDGET_EXHAUSTEDкончился запас, отпущенный прогонуувеличьте запас или сузьте задачу
FLANG_MEMORYпамяти не хватилоуменьшите данные прогона
FLANG_STOPPEDпрогон остановлен снаружиперезапустите
модуль «Проба»

тотальная функция «Считать»
  принимает н: число
  возвращает число
  если н равно 0 то 0 иначе («Считать» отплюс 1))
FLANG_NOT_TOTAL в файле total.flang, строка 6, столбец 30: тотальная функция «Считать»: рекурсивный вызов «Считать» не убывает — аргумент 1 («н» add 1) увеличивает параметр «н». Передавайте часть аргумента: хвост списка из образца «голова и хвост», поле варианта из образца, поле записи или элемент коллекции
flang run rec.flang --function "Вниз" --args '{"н":100}' --max-steps 5
FLANG_RECURSION_LIMIT: функция «Вниз» исчерпала лимит шагов (5) на глубине вызовов 1

Утверждения и доказательство

Требования, обещания и теоремы.

кодчто значитчто делать
FLANG_PROPERTYпостусловие нарушено при вычисленииутверждение или тело неверны — смотрите вход, на котором сорвалось
FLANG_PRECONDITIONпредусловие записано неверносверьте форму требует «имя» <утверждение>
FLANG_PRECONDITION_CALLвызывающий не снял предусловие вызываемойдокажите условие в месте вызова или сузьте тип довода
FLANG_BOUND_ON_NANутверждение о порядке ложно из-за «не числа»см. третью ловушку выше
FLANG_PROOFядро не приняло доказательствониже — уточнённые коды FLANG_PROOF_*
FLANG_PROOF_NO_GOALтеорема ничего не закрывает: постусловия с таким именем нетназовите теорему точно так же, как постусловие
FLANG_PROOF_AMBIGUOUSтеорема закрывала бы сразу два постусловиядайте постусловиям разные имена
FLANG_PROOF_CLAIM_MISMATCHутверждаем не совпало с постусловием слово в словоскопируйте текст постусловия дословно
FLANG_PROOF_DUPLICATEодно постусловие доказывают две теоремыоставьте одну
FLANG_PROOF_STEPшаг не обоснован или шагов нет вовседобавьте по свойству «…», по примеру «…» или по предположению
FLANG_PROOF_UNFINISHEDдоказательство не закрытодопишите следовательно доказано
FLANG_PROOF_UNKNOWN_VARв утверждении стоит несвязанное имявведите его строкой дано
FLANG_PROOF_VAR_TYPEтип переменной теоремы разошёлся с типом параметраприведите дано к подписи функции
FLANG_PROOF_INDUCTION_TYPEпо этому типу индукции нетиндукция идёт по объявленной сумме или по отрезку неотрицательное
FLANG_PROOF_INDUCTION_CASESразобраны не все случаи принципадопишите недостающий случай
FLANG_PROOF_INDUCTION_BRANCHветвь случая не сведена к целиобоснуйте ветвь
FLANG_PROOF_INDUCTION_STEPшаг не сведён к предположениюдобавьте по предположению и приведите стороны знак в знак
FLANG_PROOF_INDUCTION_DESCENTспуск не строгий: шаг не на единицусведите шаг ровно к одному вниз
FLANG_INITIAL_FAILUREпринцип по объявленному типу не породилсяпроверьте, что тип объявлен суммой вариантов
FLANG_UNCOVERED_FAILUREпуть отказа не покрыт разборомдобавьте случай на отказ
модуль «Проба»

тотальная функция «Удвоить»
  принимает н: число
  возвращает число
  обеспечивает «удвоенное неотрицательно» если н не меньше 0 то (результат не меньше 0) иначе да
  н умножить на 2

теорема «удвоенное неотрицательно»
  дано н: число
  утверждаем если н не меньше 0 то (результат не меньше 0) иначе да
  следовательно доказано
FLANG_PROOF_STEP: теорема «удвоенное неотрицательно»: ни одного шага
FLANG_PROOF_NO_GOAL в файле pr1.flang, строка 9, столбец 1: теорема «удвоенное неотрицательно» ничего не закрывает: постусловия «удвоенное неотрицательно» нет ни у одной функции модуля. Теорема доказывает названное утверждение, а не утверждение вообще — назовите её так же, как постусловие, которое она закрывает
FLANG_PROOF_AMBIGUOUS в файле pa.flang, строка 15, столбец 1: теорема «неотрицательно» закрывала бы сразу 2 постусловия («Удвоить», «Утроить»), и выбрать нельзя. Дайте постусловиям разные имена
FLANG_PROOF_CLAIM_MISMATCH в файле pm.flang, строка 11, столбец 3: теорема «неотрицательно» утверждает не то, что обещает функция «Удвоить»: утверждение теоремы и постусловие обязаны совпадать слово в слово. Ядро не решает, что два разных утверждения означают одно и то же

Постусловие, пропущенное проверкой, считает рантайм:

flang run prop.flang --function "Половина" --args '{"н":0}'
FLANG_PROPERTY: нарушено свойство «результат меньше довода» функции «Половина»

Законы объявленных структур

Эти законы компилятор СЧИТАЕТ на конечной сетке значений автора, а не доказывает. Отказ означает найденное нарушение — контрпример есть всегда.

кодкакой закон нарушен
FLANG_EQUALITY_NOT_REFLEXIVEобъявленное равенство не рефлексивно
FLANG_EQUALITY_NOT_SYMMETRICне симметрично
FLANG_EQUALITY_NOT_TRANSITIVEне транзитивно
FLANG_EQUALITY_NOT_CONGRUENTкомпозиция равенство не уважает
FLANG_ORDER_NOT_REFLEXIVEпорядок не рефлексивен
FLANG_ORDER_NOT_ANTISYMMETRICне антисимметричен
FLANG_ORDER_NOT_TRANSITIVEне транзитивен
FLANG_CATEGORY_NOT_CLOSEDкатегория не замкнута под композицией
FLANG_CATEGORY_NO_IDENTITYу объекта нет единицы
FLANG_CATEGORY_NOT_ASSOCкомпозиция не ассоциативна
FLANG_COMPOSE_MISMATCHу композиции не сходятся концы
FLANG_MORPHISM_SHAPEморфизм объявлен не так
FLANG_FUNCTOR_NOT_TOTALфунктор определён не на всех объектах
FLANG_FUNCTOR_SQUAREквадрат функтора не коммутирует
FLANG_TRANSFORM_SHAPEпреобразование объявлено не так
FLANG_TRANSFORM_COMPONENTу преобразования не хватает составляющей
FLANG_TRANSFORM_NOT_TOTALпреобразование определено не на всех объектах
FLANG_TRANSFORM_NOT_NATURALквадрат естественного преобразования не коммутирует
FLANG_ISO_NOT_INVERSEстрелки круга не обратны друг другу
FLANG_EMBED_SHAPEвложение объявлено не так
FLANG_EMBED_NOT_INJECTIVEвложение склеивает разные значения
FLANG_MONOIDобъявление моноида неполно
FLANG_MONOID_ASSOCдействие моноида не ассоциативно
FLANG_MONOID_IDENTITYединица моноида не единица
FLANG_GROUP_INVERSEобратный элемент не обратен
FLANG_MONADобъявление монады неполно
FLANG_MONAD_ASSOCсвязывание не ассоциативно
FLANG_MONAD_LEFT_UNITлевая единица не выполняется
FLANG_MONAD_RIGHT_UNITправая единица не выполняется
FLANG_NOT_COMMUTATIVEобъявленная коммутативность нарушена
FLANG_NOT_DISTRIBUTIVEдистрибутивность нарушена
FLANG_NOT_IDEMPOTENTидемпотентность нарушена
FLANG_NOT_MONOTONEмонотонность нарушена
FLANG_MEET_NAME_TAKENимя множества уже занято
FLANG_MEET_NO_UNIVERSEу объявленных множеств нет общего носителя
FLANG_MEET_SAME_SIDEпересечение объявлено множества с самим собой
FLANG_MEET_TWICEодна и та же пара объявлена дважды

Поручения и ввод-вывод

Отказы команды flang io. План возвращает ОПИСАНИЕ действия, а делает его хозяин; коды семейства FLANG_IO_* говорят, что хозяин делать отказался.

кодчто значитчто делать
FLANG_PLANплан объявлен неверносверьте форму плана
FLANG_UNKNOWN_PLANплана с таким именем в файле нетназовите существующий: --plan 'Имя'
FLANG_PLAN_UNSUPPORTEDпоручение этого вида прогонщик не исполняетзамените поручение или прогоните версией, где оно есть
FLANG_IO_NO_HOSTхозяина нет: поручение отдавать некомузапускайте через flang io, а не вычислением функции
FLANG_IO_NOT_TEXTтекстовое чтение встретило не текстчитайте октетами
FLANG_IO_UNSUPPORTEDполномочие снято ключом или действие не поддержановерните полномочие: без --no-read, --no-write, --no-net и прочих
FLANG_LOCKзамок испорчен или не сходится печатьюпересоберите замок
FLANG_PACKAGEпакет испорчен: перечень не сходится с содержимымпересоберите пакет

Полномочия сужаются по одному, умолчание — «можно всё»:

flang io план.flang --plan 'Разбор' --no-net --in-dir

Процессы

кодчто значитчто делать
FLANG_PROCESSпроцесс объявлен неверносверьте объявление процесса
FLANG_PROCESS_ACCEPTSпроцессу пришло сообщение, которого он не принимаетдопишите вид сообщения в принимает
FLANG_PROCESS_LIMITупёрлись в предел числа процессовподнимите предел или порождайте меньше
FLANG_MAILBOX_FULLящик переполнен: читатель не успеваетчитайте чаще или ограничьте отправителя
FLANG_LINK_DOWNсвязь с узлом или процессом разорванаобработайте разрыв в надзоре
FLANG_CONC_UNSUPPORTEDэта возможность процессов не поддержанасм. страницу о процессах
FLANG_HOTSWAP_REFUSEDгорячая замена кода отклоненаподгоняйте новый код под прежние объявления

Командная строка и внутреннее

кодчто значитчто делать
FLANG_CLIвызов кривой: непонятный ключ или нет доводаflang <команда> --help
FLANG_INTERNALсломался сам компиляторсообщите об этом: это отказ инструмента, не программы
FLANG_SELF_EVAL_UNSUPPORTEDформа вне того, что умеет вычислять этот путьвычисляйте обычной командой flang run
FLANG_SELF_REPL_UNSUPPORTEDоболочка эту форму не принимает — например, используетположите код в файл и проверьте flang check
FLANG_FACTCHECK_НЕТ_ОТВЕТАпроверке фактов не дали ответа вычислителя на вызовдайте ответ в наборе фактов
flang check --неткого
flang check: непонятный ключ «--неткого»

Код возврата — 2.

Дальше: Ядро отказало: чья это ошибка — как читать отказ доказательства и когда виноват не автор.