Исполняемые спецификации на flang Две поверхности: русская и английская запись одного правила
0%

Две поверхности: русская и английская запись одного правила

Две поверхности: русская и английская запись одного правила

Эта глава закрывает вопрос, который обычно возникает первым: если модель пишут и русскоязычный аналитик, и разработчик, которому привычнее английский, значит ли это два языка и два компилятора? Нет: один компилятор и одни проверки, две записи ключевых слов.

Минимальный пример

Правило по-русски:

модуль «Продажи»

тотальная функция «Скидка»
  принимает сумма: неотрицательное, постоянный: признак
  возвращает число
  обеспечивает «за мелкую покупку скидки нет» если сумма меньше 10000 то результат равен 0 иначе да
  пример «мелкая покупка»
    дано сумма равно 5000
    дано постоянный равно да
    ожидается 0
  пример «большая покупка постоянного клиента»
    дано сумма равно 20000
    дано постоянный равно да
    ожидается 3000
  если сумма не меньше 10000
    то (если постоянный то (сумма умножить на 15) делить на 100 иначе (сумма умножить на 10) делить на 100)
    иначе 0

То же правило по-английски:

module «Sales»

total function «Discount»
  accepts amount: nat, regular: flag
  returns number
  ensures «no discount on a small purchase» if amount is less than 10000 then result equals 0 else yes
  example «small purchase»
    given amount equals 5000
    given regular equals yes
    expected 0
  example «large purchase by a regular customer»
    given amount equals 20000
    given regular equals yes
    expected 3000
  if amount is at least 10000
    then (if regular then (amount times 15) divided by 100 else (amount times 10) divided by 100)
    else 0

Оба файла дают одинаковый ответ: функция с доказанным завершением, два примера сошлись, обещание доказано, flang run считает 3000.

$ flang run sales.en.flang --function Discount --args '{"amount": 20000, "regular": true}'
доказано: утверждений 1
3000

Что делает компилятор

У каждого ключевого слова flang есть русское и английское написание. принимает и accepts, не меньше и is at least, тотальная функция и total function — это одно слово языка. Лексер превращает оба написания в один токен, и дальше разбор, типы и доказательства не знают, какой записью пользовался автор.

Это видно прямо в потоке токенов. Строка 4 русского файла и строка 4 английского:

$ flang tokens sales.flang | sed -n '8,16p'
4:3	>
4:3	слово accepts
4:13	имя сумма
4:18	знак :
4:20	имя неотрицательное
4:35	знак ,
4:37	имя постоянный
4:47	знак :
4:49	слово tFlag

$ flang tokens sales.en.flang | sed -n '8,16p'
4:3	>
4:3	слово accepts
4:11	имя amount
4:17	знак :
4:19	имя nat
4:22	знак ,
4:24	имя regular
4:31	знак :
4:33	слово tFlag

Слово принимает стало токеном accepts, признак и flag — токеном tFlag. Имена параметров остались такими, какими их написал автор.

Узнать, чем станет фраза, можно и без файла:

$ flang tokens --keyword 'не меньше'
«не меньше» — ключевое слово, конструкция «cmpGte»

$ flang tokens --keyword 'is at least'
«is at least» — ключевое слово, конструкция «cmpGte»

Перевода через словарь или модель здесь нет. Это одна таблица ключевых слов, и номера строк в ошибках одинаково указывают на ваш файл в любой записи.

Английская запись модели курса

В песочнице лежат две версии модели скидки: order-discount.flang и order-discount.en.flang. Функции, условия, проценты и примеры в них совпадают один в один. Отчёты о доказательствах тоже совпадают: в каждой модели одно обещание доказано, три держатся только на примерах, все десять примеров сходятся.

Различаются имена: «Продажи» и «Sales», «Покупка» и «Purchase», «сумма» и «amount». Это не автоперевод — их называет автор. Переводятся только ключевые слова. Значит, русская и английская модель вольны описывать разные словари предметной области, но при одинаковой структуре правил ведут себя одинаково.

Две вещи не переводятся никогда:

  • сообщения компилятора — они по-русски на любой записи;
  • имена типов чисел — у неотрицательное английское имя nat, а не nonnegative (см. ошибки ниже).

Смешивать записи в одном файле компилятор не запрещает: module в первой строке и принимает в пятой проходят проверку. Но читать такой файл тяжело. Держите одну запись на файл.

Две записи полей

Поле объекта пишется двумя способами, и оба равноправны:

модуль «Счета»

объект «Строка счёта»
  номер является строкой
  «сумма»: неотрицательное
  комментарий иногда является строкой

тотальная функция «Номер строки»
  принимает строка: «Строка счёта»
  возвращает строка
  пример «комментарий можно не задавать»
    дано строка равно запись «Строка счёта» с номер равным "СЧ-1" и «сумма» равным 900
    ожидается "СЧ-1"
  строка.номер

«сумма»: неотрицательное и номер является строкой дают одно и то же поле. Слово иногда является делает поле необязательным: в примере запись собрана без комментария, и проверка проходит. flang ast отмечает такое поле "optional": true.

Имена и кавычки

Имя из одного слова можно писать без ёлочек: номер, amount, Счёт. Имя с пробелом пишется в ёлочках: «постоянный клиент», «Строка счёта». Ёлочки — граница имени: внутри них лексер видит одно имя, а не набор слов. В объявлении объекта и в типе параметра компилятор примет и прямые кавычки, но в выражении "…" — это строка. Держите для имён ёлочки, и путаницы не будет.

CamelCase не нужен. Если модель читают аналитики и разработчики вперемешку, «готов к отгрузке» понятнее, чем ReadyForShipment.

Имена сравниваются побайтно, без нормализации Юникода. Буква «й» одной кодовой точкой и «и» с отдельным комбинирующим знаком на экране выглядят одинаково, но для компилятора это два разных имени. Функция объявлена с первым написанием, а вызвана со вторым — и вот начало ответа:

$ flang check names.flang
FLANG_UNKNOWN_NAME в файле names.flang, строка 11, столбец 3: имя «Мой» не связано

Если имена приходят из разных редакторов или копируются из документов, приводите файлы к NFC до проверки: uconv -x any-nfc или unicodedata.normalize('NFC', …) в Python.

Значения

Признак пишется да/нет или yes/no; годятся и true/false. Числа пишутся цифрами, строки — в прямых кавычках. Пустого значения нет: где ответа может не быть, заводится тип с вариантами.

Практика в песочнице

Нажмите «Проверить» и запишите итоговую строку отчёта. Затем откройте английскую модель ниже и сравните: совпадают ли числа доказанных обещаний и примеров?

Переименуйте object «Purchase» в object «Order», но не трогайте функции, которые на него ссылаются. Проверьте и найдите FLANG_UNKNOWN_NAME — компилятор не переименовывает ссылки за автора, а называет каждую строку, где старое имя осталось.

Перепишите поля объекта «Строка счёта» через является: например, номер является строкой. Убедитесь, что проверка и примеры дают тот же ответ.

Типичные ошибки

Опечатка в первом слове. Файл обязан начинаться с модуль или module:

$ flang check typo.flang
FLANG_PARSE в файле typo.flang, строка 1, столбец 1: не разобрана конструкция: неожиданное 'модль'
typo.flang: не проверено — замечаний 1

Английское имя типа наугад. У неотрицательное английское имя nat:

$ flang check nonneg.flang
модуль «Sales»: функций 1, из них с доказанным завершением 1; типов 0
FLANG_UNKNOWN_NAME в файле nonneg.flang, строка 3, столбец 1: неизвестный тип «nonnegative»
nonneg.flang: не проверено — замечаний 1

Опечатка в имени поля. Обращение к полю проверяется по объявлению объекта: FLANG_TYPE … запись «Счёт» не имеет поля «номер счёта». Правка — то же имя, что в объявлении, буква в букву.

Чек-лист

  • Я объясняю, что русская и английская запись — один компилятор и одни проверки, а не перевод.
  • Я знаю, что переводятся только ключевые слова, а имена объектов, полей и функций выбирает автор.
  • Я пишу многословные имена в ёлочках и знаю, что "…" в выражении — строка.
  • Я знаю, что имена сравниваются побайтно, и привожу файлы к NFC.

Кейсы каталога по этой теме

Дальше: объекты и типы

Нашли неточность? Выделите фрагмент текста — рядом появится жучок.

Нужен разбор именно вашей ситуации?

Статья описывает общий случай. Если у вас частный — можно разобрать его отдельно, платно. А если не хватает целого материала, предложите тему: её оплачивают вскладчину, и она выходит открытой для всех.

Доска запросов
Дальше