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

Словарь между двумя спеками разбирался целиком и не значил ничего

Функтор FTS — единственная из семи конструкций поверхности, которая утверждает соответствие понятий двух разных файлов требований:

функтор «Заказ в счёт» из «Продажи» в «Биллинг»
  использует «Продажи» из «./prodazhi.fts»
  использует «Биллинг» из «./billing.fts»

  объект Покупка отображается в «Счёт»
    поле сумма отображается в поле «сумма без НДС»

Такой конструкции нет ни в одном другом формате требований, и она ровно та, без которой не собирается замысел: спека закрывает легаси-систему, бизнес просит фичу, новая спека обязана не противоречить старой — а сравнивать две спеки можно только зная, что чему соответствует. В одной «Покупка», в другой «Счёт».

Разбор строил из этих строк всё нужное. parse на образце flang/test/fixtures/fts-naslediye/скидки-в-подписки.fts даёт legacy[0].value с imports (две пары «категория → путь»), objects (пара «Заказ → Подписка» и два поля внутри) и morphisms. Не терялось ничего.

Читать этот узел было некому, и это снималось грепом, а не чтением:

Улика прогоном. flang check на образце отвечал {"valid":true,"module":"Скидка в подписку","functions":[],"types":[],"diagnostics":[]} и кодом 0 — при том, что оба пути использует в этом файле ведут в каталог specs/, которого в дереве нет, а объекты «Заказ» и «Подписка» не объявлены нигде. Словарь, который можно написать на несуществующие слова, — не словарь, а пометка для читателя.

Что сделано. checkFunctorDictionary в flang/src/compat.mjs: обе категории обязаны быть привезены строкой использует, оба пути — читаться и разбираться, файл — объявлять ту самую категорию, каждый названный объект и каждое названное поле — существовать с обеих сторон, а типы полей — сходиться. Четыре своих кода: FLANG_FUNCTOR_SPEC_MISSING, FLANG_FUNCTOR_SPEC_NAME, FLANG_FUNCTOR_DICTIONARY, FLANG_FUNCTOR_FIELD_TYPE.

Изъятием. Три испорченных словаря лежат в flang/test/fixtures/fts-slovar/ и отличаются от целого одной строкой:

  1. поле скидка отображается в поле надбавка — два FLANG_FUNCTOR_DICTIONARY, по одному на сторону, и в каждом список имён, которые в спеке есть;
  2. поле сумма отображается в поле лояльныйFLANG_FUNCTOR_FIELD_TYPE: «Покупка.сумма» — number, «Счёт.лояльный» — flag;
  3. объект Заказ отображается в «Подписка» — два FLANG_FUNCTOR_DICTIONARY, и checked.objects остаётся нулём: объект не сошёлся, значит про его поля не известно ничего.

Целый словарь из того же прогона — valid: true и {functors:1, objects:1, fields:2, unmapped:0}.

Чем ограничено, и это важнее списка сделанного.

Правило, которое из этого вынимается. Конструкция, которая разбирается в полный узел и не имеет ни одного читателя этого узла, выглядит работающей ровно до первого замера. Грепом по имени поля — imports, fields — это видно за минуту, и такой греп стоит делать раньше, чем читать код проверки.