Справочник команд
У двоичного flang команды перечислены в его собственной справке (она вставлена в конце страницы из flang --help). Для каждой здесь сказано, когда её запускать, как вызывать, какие у неё ключи, что она печатает и с каким кодом возврата выходит. Всё это сверяется с flang --help и flang <команда> --help; каждый вывод ниже снят с нынешнего двоичного.
Шпаргалка
| Команда | Когда запускать | Типичный вызов |
|---|---|---|
check | после каждой правки: разбор, типы, завершаемость, prover, unit-тесты | flang check привет.flang |
test | чтобы прогнать только unit-тесты (пример) | flang test привет.flang |
run | чтобы вычислить одну функцию и напечатать значение | flang run привет.flang --function «Удвоить» --args '{"н":21}' |
emit | чтобы сгенерировать код на одном из десяти целевых языков | flang emit привет.flang --target js --file привет.js |
ast | чтобы увидеть разобранную программу деревом JSON | flang ast привет.flang --pretty |
tokens | чтобы увидеть, чем лексер счёл каждое слово | flang tokens привет.flang |
lint | чтобы строки не были слишком длинными, а ветвления — слишком глубокими, по пределам из .flangrc | flang lint scripts/ |
facts | чтобы проверить утверждения на данных из JSON-файла | flang facts привет.flang --facts факты.json --claims '["…"]' |
io | чтобы запустить программу, которая читает файлы, запускает процессы или ходит в сеть | flang io план.flang --pretty |
lock | чтобы записать lock-файл, в котором лежат сами зависимости | flang lock привет.flang > flang.lock |
package | чтобы собрать пакет: lock плюс имя, версия и список доказанного | flang package привет.flang > привет.flang-package |
new | чтобы начать новый пакет | flang new проба |
run-script | чтобы запустить короткую команду проекта из .flangrc | flang run-script site:build |
repl | чтобы пробовать выражения интерактивно | flang repl привет.flang |
lsp | запускает редактор: языковой сервер | flang lsp --stdio |
Ещё: flang --help, flang --version, flang <команда> --help; flang --machine [<файл>] печатает, насколько быстра эта машина (шагов вычисления в секунду); flang --mcp-mode — сервер для ИИ-помощника по стандартному вводу и выводу (flang --mcp-mode --help — как его подключить).
Три ключа годятся при любой команде и ограничивают сам двоичный на этот прогон:
| Ключ | Что задаёт |
|---|---|
--depth-limit N (--предел-глубины) | предел глубины вызовов |
--step-limit N (--предел-шагов) | предел шагов; исчерпание — FLANG_RECURSION_LIMIT с числом |
--memory-limit N (--предел-памяти) | предел памяти, байтами или с буквой K, M, G, T; 0 — без предела. У check, test и run по умолчанию три четверти памяти машины. На пределе прогон останавливается с кодом 5 и называет функцию и число шагов |
Долгие прогоны печатают в поток ошибок строку хода шагов N из M ….
Примеры ниже идут на этом файле, docs/examples/cli/double.flang:
module «Hello»
total function «Удвоить»
accepts н: number
returns number
example «Двадцать один»
given н equals 21
expected 42
н plus н
Коды возврата
Коды значат одно и то же во всех командах.
| Код | Что значит |
|---|---|
0 | сделано, замечаний нет |
1 | программа не прошла проверку; у facts и io — программа сама ответила «нет» |
2 | кривой вызов: неизвестный ключ, неверное значение, нет такого файла |
3 | сделано, но проверено не всё, и вывод называет, что именно. А ещё: run и io отказываются запускать программу, гарантии которой не доказаны |
4 | часть проверок не запускалась вовсе (check --fast) |
5 | прогон остановлен на пределе памяти |
В скрипте сборки различайте 1 и 3: 1 — работа не сделана, 3 — сделана, но поручиться за неё целиком нельзя.
Входной файл: четыре расширения
Файл программы может кончаться на .flang, .fp, .фп или .фланг; все четыре равноправны. .flang — основное; .fp избавляет от переключения раскладки; .фп и .фланг позволяют русскому имени файла остаться в одном алфавите. Команды берут файл по пути, так что годится и любое другое имя.
flang test различает один файл и набор файлов по доводу, см. test. Файл с любым из четырёх расширений берётся как один файл:
$ flang test привет.фп
привет.фп: примеров 1, прошло 1, не прошло 0
check
Проверяет программу: разбор, связывание имён, типы, завершаемость, prover и unit-тесты. Запускайте после каждой правки.
flang check <файл.flang> [--proof [--json] [--strict] [--record <файл>]]
[--fast] [--step-limit N] [--depth-limit N]
У каждого ключа есть и кириллическое написание, оно в скобках.
| Ключ | Что делает |
|---|---|
--proof | печатает отчёт о доказательствах: у каждой функции — чем доказано завершение, у каждого постусловия — доказано ли оно, проверено только на примерах или не доказано. Постусловие без доказательства и без примеров даёт код 3 |
--json | вместе с --proof: тот же отчёт в JSON |
--strict (--строго) | вместе с --proof: код 0 только когда доказана каждая гарантия. Для CI. Подробно ниже |
--record <файл> (--записать) | вместе с --proof: записать само доказательство в файл, чтобы его перепроверила независимая программа flang/proof/checker/checker.c |
--fast (--быстро) | только имена, типы, полнота pattern matching и завершаемость. Prover и unit-тесты не запускаются, вывод говорит об этом, код возврата 4. Вместе с --proof нельзя |
--step-limit N (--предел-шагов) | поднять предел шагов на этот прогон. Нужен для --proof --json на очень больших файлах. Ключа --max-steps у check нет: это кривой вызов, код 2 |
--depth-limit N (--предел-глубины) | поднять предел глубины вызовов на этот прогон. Не путать с --max-depth у emit: тот записывается в сгенерированную программу |
--memory-limit N (--предел-памяти) | предел памяти, см. выше; на пределе код 5 |
Коды: 0 — замечаний нет; 1 — программа не прошла либо с --proof гарантия нарушена; 2 — в программе есть объявления, которые двоичный не проверяет вовсе (категорные объявления, процессы, надзор), и он их называет; 3 — с --proof гарантия не доказана, в том числе проверенная только на примерах (сетка N), закон, посчитанный только на сетке, гарантия, доказанная при недоказанной посылке, и файл без ввоза, запись доказательства которого независимый сверщик не принял (НЕ СОШЛОСЬ СО СВЕРЩИКОМ); с --strict — ещё и файл без единой гарантии; 4 — с --fast. Строка сверщика идёт перед строкой приговора. Файлу с ввозом сверщик не получает записей ввезённых модулей; его несогласие там названо НЕЗАВИСИМО НЕ ПРОВЕРЕНО и код не меняет (ADR-0115).
$ flang check docs/examples/cli/double.flang
модуль «Hello»: функций 1, из них с доказанным завершением 1; типов 0
docs/examples/cli/double.flang: проверено — разбор, типы, завершаемость, ядро и примеры; замечаний нет
Первая строка считает функции и сколько из них с доказанным завершением. Вторая говорит, что прошли все проверки: разбор, типы, завершаемость, prover («ядро») и unit-тесты.
Когда проверка не прошла, вывод называет код ошибки, строку и столбец. Здесь docs/examples/cli/bad.flang объявляет returns string, а тело даёт число:
$ flang check docs/examples/cli/bad.flang
модуль «Bad»: функций 1, из них с доказанным завершением 1; типов 0
FLANG_TYPE в файле docs/examples/cli/bad.flang, строка 6, столбец 5: функция «Удвоить» объявлена как строка, а тело даёт число
docs/examples/cli/bad.flang: не проверено — замечаний 1
$ echo $?
1
Каждый код FLANG_… и как его чинить — в Справочнике отказов.
$ flang check docs/examples/cli/double.flang --fast
модуль «Hello»: функций 1, из них с доказанным завершением 1; типов 0
ПРОВЕРЕНО: связывание имён и повторы объявлений, типы, исчерпываемость разбора,
завершаемость (в том числе взаимная рекурсия по компонентам), процессы, планы.
НЕ СМОТРЕЛИ НА ЭТОМ ПРОГОНЕ: ядро доказательств — обязательств 0, теорем 0;
законы категории на сетке; прогон примеров — примеров 1.
И это не «нарушений нет»: про них не сказано ничего — ни хорошего, ни плохого.
«Не смотрели» — не то же, что «объявлено, доказательства нет»: второе
значит «смотрели и не смогли», а здесь вопроса не задавали вовсе.
Спросить всё — та же команда без «--быстро».
docs/examples/cli/double.flang: часть проверок НЕ ЗАПУСКАЛАСЬ — код возврата 4, а не 0
$ echo $?
4
--strict: свой код возврата на каждый итог
Без --strict команда check --proof выходит с 0 и когда доказано всё, и когда часть гарантий проверена только на ваших примерах. Слова в выводе разные, но скрипт сборки читает код возврата. С --strict у каждого итога свой код:
| Итог | Код | Когда |
|---|---|---|
ДОКАЗАНО | 0 | гарантия есть хотя бы одна, и доказана каждая |
ОПРОВЕРГНУТО | 1 | найден контрпример |
НЕ УДАЛОСЬ ДОКАЗАТЬ | 3 | контрпримера нет, но доказано не всё; вывод называет, что |
НЕ ПОДДЕРЖИВАЕТСЯ | 2 | программа объявляет то, что двоичный не проверяет, и вывод это называет |
У кода 3 три причины, их различают слова после него: ОПОРА НЕ СУДИЛАСЬ — гарантия проверена только на примерах; ОБЪЯВЛЕНО, НЕ ДОКАЗАНО — у гарантии нет ни доказательства, ни примеров; ПРОВЕРЕНО ВПУСТУЮ — гарантий нет вовсе. Когда причин несколько, называется самая серьёзная: контрпример важнее отсутствия доказательства, а отсутствие доказательства важнее «только примеров».
Файл без гарантий по умолчанию проходит, а под --strict — нет, потому что «доказывать нечего» — не доказательство:
$ flang check привет.flang --proof --strict | tail -2
привет.flang: НЕ УДАЛОСЬ ДОКАЗАТЬ — ПРОВЕРЕНО ВПУСТУЮ, ОБЯЗАТЕЛЬСТВ НЕТ ВОВСЕ — утверждений 0: доказано 0, условно 0, сетка 0, объявлено, не доказано 0, отвергнуто 0, нарушено 0; законов на сетке 0, на веру 0 — код возврата 3
ничего: ни одно утверждение не назвало ни правила, ни шага
Прошедшие примеры — не доказательство. Здесь постусловие ложно, а два примера случайно проходят:
модуль «Grid»
тотальная функция «Удвоить»
принимает н: неотрицательное
возвращает число
обеспечивает «не больше ста» результат не больше 100
пример «один»
дано н равно 1
ожидается 2
пример «десять»
дано н равно 10
ожидается 20
н плюс н
flang check docs/examples/cli/grid.flang выходит с 0: доказательств он не судит. flang check docs/examples/cli/grid.flang --proof выходит с 3: отчёт пишет сетка 1 — одна гарантия проверена только на примерах — и НЕ ДОКАЗАНО — ОПОРА НЕ СУДИЛАСЬ. С --strict код тоже 3. flang run такую программу считать отказывается (см. run), а с --trust при н = 100 нарушает постусловие:
$ flang run docs/examples/cli/grid.flang --function «Удвоить» --args '{"н":100}' --trust
на веру: доказанность не считалась — запуск по ключу --trust
FLANG_PROPERTY: нарушено свойство «не больше ста» функции «Удвоить»
$ echo $?
1
--strict делает строгим только компилятор. Независимая программа проверки flang/proof/checker/checker.c на записи доказательства, где не доказано ничего, отвечает НЕ ПРОВЕРЕНО — ВПУСТУЮ с кодом 3 и без ключа.
--strict без --proof — кривой вызов, код 2. Пробные программы на все итоги лежат в flang/proof/probes/strict/; прогон — bootstrap/flang io flang/proof/probes/strict/run.fscript --plan Binary.
test
Прогоняет unit-тесты (пример), объявленные внутри функций. Сначала делает те же проверки, что check: прошедший тест в программе с ошибкой типов ничего не значит.
flang test <файл.flang | каталог | маска> [--no-check] [--json] [--ledger]
[--max-steps N] [--max-depth N]
| Ключ | Что делает |
|---|---|
--no-check | не проверять, только прогнать примеры — пока программа ещё в правке |
--json | итог одной строкой JSON |
--ledger | по строке на файл через табуляцию — чтобы сравнивать прогоны через diff |
--max-steps N | предел шагов вычислителя |
--max-depth N | предел глубины |
--memory-limit N | предел памяти; на пределе код 5 |
Довод, который не кончается ни на одно из четырёх расширений или содержит * или ?, — это набор файлов:
flang test flang/stdlib/ весь каталог, вглубь
flang test 'docs/examples/**/*.flang' по маске (кавычки — от оболочки)
Коды: 0 — взяты все файлы и прошли все примеры; 1 — пример не прошёл или файл не взят; 2 — кривой вызов.
Блок прогон описывает сценарий над процессами. flang test исполняет его планировщиком flang/self/conc.flang и сверяет ожидания; блок считается одним примером, поэтому блок с ложным ожиданием валит файл кодом 1:
$ flang test flang/concurrency/examples/counter.flang
flang/concurrency/examples/counter.flang: примеров 4, прошло 4, не прошло 0
$ flang test docs/examples/cli/double.flang
docs/examples/cli/double.flang: примеров 1, прошло 1, не прошло 0
Для не прошедшего примера печатаются обе стороны: ожидалось и получено. Длинное значение обрезается на 200 знаках, и полная длина называется числом.
run
Вычисляет одну функцию и печатает значение. Считает сам двоичный: ни компилятор C, ни Node не нужны.
flang run <файл.flang> --function «Имя» [--args '{"н":10}'] [--max-steps N]
[--max-depth N] [--trust] [--unproven refuse|warn|allow]
[--cost]
| Ключ | Что делает |
|---|---|
--function «Имя» | какую функцию вычислить. Обязателен |
--args '{…}' | аргументы плоским JSON-объектом из скаляров. Списки и вложенные объекты не принимаются |
--max-steps N | предел шагов вычислителя |
--max-depth N | предел глубины вычисляемой программы (свой предел двоичного — --depth-limit) |
--memory-limit N | предел памяти; на пределе код 5 |
--cost (--цена) | после значения строкой в поток ошибок: шагов вычислителя, пик памяти процесса в байтах и секунды прогона — цена прогона: шагов 6, пик памяти 13443072 байт, секунд 0.005997 |
--trust (--на-веру) | запустить, даже если гарантии не доказаны; доказательства не проверяются вовсе, и об этом говорит отдельная строка |
--unproven СЛОВО (--недоказанное) | что делать, когда гарантии не доказаны: refuse — не запускать (по умолчанию), warn — сказать и запустить, allow — то же, что --trust. По-русски: отказ, предупреждение, разрешение |
Аргументы сначала сверяются с объявленными типами: «Факториал» от −3 отвергается с FLANG_TYPE, а не вычисляется.
run не запускает недоказанную программу. Перед вычислением он проверяет доказательства всего, что программа использует (а не только этого файла), и печатает одну строку в поток ошибок: доказано: утверждений N (N гарантий, все доказаны) либо не доказано: … — и тогда не вычисляется ничего, код 3.
$ flang run docs/examples/cli/double.flang --function «Удвоить» --args '{"н":21}'
доказано: утверждений 0
42
Чтобы разрешить недоказанные программы раз и навсегда, задайте ключ unproven в .flangrc (Настройки): unproven = warn. Ключ командной строки старше переменной среды FLANG_UNPROVEN, она старше .flangrc, а он — умолчания refuse. Строка перед значением называет, что разрешило запуск: ключ или настройку и путь к её файлу. Неизвестное значение — код 2 с объяснением.
emit
Генерирует код на целевом языке. Все десять целей встроены в двоичный. Каталог из --out заводится сам, вместе с подкаталогами, которых требует цель.
flang emit <файл.flang> --target c|cpp|go|rust|java|js|ts|elixir|python|csharp
[--out каталог | --file имя] [--cli|--no-cli] [--repl]
[--runtime каталог] [--index-base 0|1]
[--max-steps N] [--max-depth N] [--no-check]
[--no-postconditions]
| Ключ | Что делает | |
|---|---|---|
--target <цель> | c, cpp, go, rust, java, js, ts, elixir, python, csharp. Обязателен | |
--out каталог | записать все файлы в каталог | |
--file имя | один файл на стандартный вывод | |
--cli, --no-cli | генерировать ли запускалку командной строки | |
--repl | сгенерировать ещё и интерактивный вход. Только цель c | |
--protocol файл (--протокол) | только цель c: записать ещё журнал перевода — во что перешла каждая конструкция и по какому правилу; его перепроверяет flang/translation/matcher.c | |
--runtime каталог | где лежат исходники рантайма цели | |
| `--index-base 0\ | 1` | объявить базу индексов программы |
--max-steps N | предел шагов, записываемый в сгенерированный код | |
--max-depth N | предел глубины, записываемый в сгенерированный код | |
--no-check | не запускать prover. Разбор, типы и завершаемость проверяются всё равно | |
--no-postconditions | не генерировать проверки постусловий во время работы. Доказываются они по-прежнему: ключ меняет только сгенерированный код, и его шапка об этом говорит. Предусловия, проверки завершения и пределы шагов и глубины остаются. Замеры — в flang emit --help |
Генерируется только проверенная программа. Перед генерацией emit делает те же проверки, что flang check; при ошибке не пишется ни одного файла, код 1.
--no-check убирает prover и больше ничего
С --no-check разбор, имена, типы и завершаемость проверяются, и программа, не прошедшая их, всё так же не генерируется. Что меняется:
- Постусловия не доказываются, поэтому ни одно нельзя убрать из сгенерированного кода: каждое становится проверкой во время работы. Код больше и медленнее, но не слабее.
- Неверные доказательства не ловятся. Прогоните
flang check, прежде чем доверять результату. - Код, сгенерированный так, нельзя класть в сборку самого компилятора: отпечаток сборки не сойдётся. Двоичный печатает это предупреждение после каждого запуска с ключом.
Сколько времени ключ экономит, зависит от файла: на одних файлах — в разы, на других весь круг с ключом идёт дольше, потому что лишние проверки обходятся сборке C дороже, чем prover обходится emit. Числа — в flang emit --help. На двух самых больших модулях компилятора, flang/self/distributed.flang и flang/self/bounded.flang, prover выбирает весь предел шагов, и сгенерировать их можно только с этим ключом.
Коды emit:
| Код | Что значит |
|---|---|
0 | сгенерировано, проверено всё |
1 | не прошло проверку; не записано ничего |
2 | кривой вызов: нет такой цели, нет файла, неверное значение ключа |
3 | сгенерировано, но проверено не всё: двоичный не проверяет категорные объявления и процессы и называет, что пропустил |
emit не прогоняет unit-тесты и говорит об этом; прогоните их flang test.
$ flang emit привет.flang --target c --out вывод
напечатано файлов 6, байт …, в вывод
проверено перед печатью — разбор, типы, завершаемость и ядро доказательств.
ПРИМЕРЫ НЕ ПРОГНАНЫ: их считает вычислитель на самом языке, и на самых больших
программах он в предел шагов этого бинарника не укладывается — свяжи с ними
печать, и компилятор перестал бы печатать сам себя. Прогоните их отдельно:
flang test <файл>
$ ls вывод
Makefile flang_cli.c flang_runtime.c flang_runtime.h privet.c privet.h
Вывод говорит: записано 6 файлов; программа проверена перед генерацией; unit-тесты не прогнаны. Сгенерированная запускалка сверяет аргументы с объявленными типами так же, как flang run: на −3 для параметра неотрицательное она отвечает FLANG_TYPE. Имена файлов — имя модуля латиницей («Привет» → privet.c).
Неизвестная цель — код 2 и список целей:
$ flang emit docs/examples/cli/double.flang --target нету
flang emit: цели «нету» у этой сборки flang нет — целей здесь ДЕСЯТЬ — «c», «cpp», «go», «rust», «java», «js», «ts», «elixir», «python», «csharp».
Невтащенных целей больше нет: все десять живут в замыкании этой сборки, и
печатает их она сама, без Node.
$ echo $?
2
ast
Печатает разобранную программу с подключёнными импортами деревом JSON — ровно то, что получает генератор кода.
flang ast <файл.flang> [--pretty]
| Ключ | Что делает |
|---|---|
--pretty | отступ в два пробела |
Типы и завершаемость здесь не проверяются: дерево показывает, что прочитано, а не что верно. Команда отказывает только на ошибках разбора и неподключённых импортах.
$ flang ast привет.flang --pretty | head -8
{
"flang": 1,
"module": "Привет",
"types": [],
"functions": [
{
"name": "Удвоить",
"total": true,
tokens
Печатает поток токенов: что прочитал лексер, до разбора. Нужна, чтобы узнать, чем станет слово, если его написать. grep на это не ответит: слово в комментарии, внутри строкового литерала или внутри имени в ёлочках ключевым словом не становится никогда.
flang tokens <файл.flang> [--json] [--pretty]
flang tokens --keyword «фраза»
| Ключ | Что делает |
|---|---|
--json | JSON с теми же ключами, что у flang ast: kind, value, text, quoted и span со строкой и столбцом |
--pretty | JSON с отступами; включает --json сам |
--keyword «фраза» | ключевое ли это слово. Фраза из нескольких слов проверяется как одна фраза. Файл с этим ключом не называют |
Отказывает там же, где лексер, — незакрытый литерал, рваный отступ — с кодом 1; JSON при этом печатается всё равно, с пустым tokens и заполненным diagnostics.
$ flang tokens привет.flang | head -4
1:1 слово module
1:8 ёлочка Привет
1:16 /
3:1 слово total
$ flang tokens --keyword 'элемент или беда'
«элемент или беда» — не ключевое слово языка: одним ключевым токеном лексер это не отдаёт
$ flang tokens --keyword 'код символа'
«код символа» — ключевое слово, конструкция «charCode»
Каждая строка — строка:столбец, вид токена (слово, ёлочка — имя в ёлочках) и его текст.
lint
flang lint меряет исходники flang двумя мерами и сверяет их с пределами, записанными в .flangrc:
- длина строки — сколько знаков в строке;
- глубина ветвлений — сколько
еслииразборвложено друг в друга в теле функции.
Оба предела живут в файле настроек рядом с остальными ключами:
max-line-length = 120
max-conditional-depth = 2
lint = refuse
Ключа нет — предела нет: у проекта без этих строк находок не бывает вовсе.
Вызов
flang lint [<путь>…] [--max-line-length N] [--max-conditional-depth N]
[--warn | --refuse] [--tsv]
Путь — файл или каталог. Каталог обходится целиком, кроме имён, начинающихся с точки; берутся файлы с пятью расширениями исходников: .flang, .fscript, .fp, .фп, .фланг. Названный файл, который не исходник flang, пропускается, и об этом сказано. Без пути обходится рабочий каталог.
Ключ командной строки старше .flangrc проекта, а файл проекта старше .flangrc в домашнем каталоге.
$ flang lint docs/examples/guide/ladder-before.flang docs/examples/guide/walk-tree.flang
docs/examples/guide/ladder-before.flang:17: глубина ветвлений 3 > 2 в «Цена доставки» (max-conditional-depth)
docs/examples/guide/walk-tree.flang:15: длина строки 206 > 120 (max-line-length)
flang lint: файлов 2; max-line-length 120: 1; max-conditional-depth 2: 1; не разобрано 0
Находка называет файл, строку, измеренное значение, предел и ключ. Последняя строка уходит в поток ошибок и считает файлы и находки.
| Код | Что значит |
|---|---|
0 | ничего сверх пределов, или lint = warn |
1 | находки есть, и lint = refuse |
2 | плохой вызов: незнакомый ключ, несуществующий путь, негодное значение в .flangrc |
3 | сверх пределов ничего, но часть файлов не разобралась, и глубина в них не измерена |
--tsv печатает по находке на строку, поля через табуляцию, без итоговой строки:
length <путь> <строка> <длина> <предел>
depth <путь> <строка> <глубина> <предел> <функция> <первая строка> <последняя строка>
unparsed <путь>
skipped <путь>
Что считается
Длина считается в знаках, а не в байтах: «Сумма» — семь знаков. Перевод строки не считается, табуляция — один знак. Длинный строковый литерал — тоже длинная строка.
Глубина меряется по дереву разбора тела функции, а не по отступам. Каждое если и каждый разбор на пути от тела до узла прибавляет уровень, где бы он ни стоял: в условии, в ветви, в доводе вызова, в значении пусть. Глубина функции — самый глубокий такой путь, и находка указывает на строку самого глубокого ветвления.
если а
то 1
иначе если б
то 2
иначе 3
Это глубина 2: если в ветви иначе другого если стоит уровнем глубже. Лестница из пяти таких ветвей — глубина 5. Мелким код остаётся от списка правил и одного разбор, а не от лестницы.
или и и притом для линтера не ветвления, хотя дерево разбора пишет их как если. Примеры, обеспечивает, требует и теоремы не меряются: только тело.
Где грамматика даёт перенести строку
Строка переносится только там, где грамматика позволяет продолжить:
- внутри списка — после
[и после запятой; - внутри скобок — перед
иначе; - на уровне утверждения —
если … то … иначе …тремя строками.
Запись, вариант с полями и цепочка вызовов не переносятся: перевод строки внутри них заканчивает выражение. Такую строку укорачивают, назвав её часть через пусть или маленькой функцией.
facts
Проверяет утверждения на данных. Утверждение имеет вид «слева оператор справа»; слева — факт, поле факта или функция от фактов, справа — то же или литерал.
flang facts <файл.flang> --claims '["…"]' [--facts факты.json] [--steps N] [--pretty]
| Ключ | Что делает |
|---|---|
--claims '[…]' | что проверять, JSON-массивом строк. Обязателен |
--facts файл | факты JSON-объектом. Без ключа фактов нет |
--steps N | предел шагов. По умолчанию 10000 |
--pretty | JSON с отступами |
Коды: 0 — подтверждено; 1 — опровергнуто (результат всё равно уходит на стандартный вывод, а код нужен, чтобы упал CI); 2 — кривой вызов: нет файла, не разобран JSON, не подключились импорты.
В утверждении можно вызывать только функции с доказанным завершением; любая другая отвергается до вычисления.
$ cat факты.json
{"н": 21}
$ flang facts привет.flang --facts факты.json --claims '["«Удвоить» от н равно 42"]' --pretty | head -7
{
"ok": true,
"results": [
{
"claim": "«Удвоить» от н равно 42",
"holds": true,
"why": "«Удвоить» от факта «н» = 42; требование «равно 42» выполнено",
io
Запускает план: единственный способ, которым программа на flang работает с файлами, процессами, сетью или терминалом. Сама программа этого не делает: каждый шаг возвращает команду как данные («запиши этот файл»), рантайм её выполняет и вызывает программу снова с ответом. Поэтому все функции плана остаются чистыми и тотальными, а их unit-тестам не нужны ни файлы, ни сеть.
flang io <файл.flang> [--plan 'Имя'] [--max-orders N] [--seed N] [--in-dir]
[--max-steps N] [--timeout N] [--pretty] [--trust]
[--unproven refuse|warn|allow] [-- довод…]
| Ключ | Что делает |
|---|---|
--plan 'Имя' | какой план запустить, если их в файле несколько |
--max-orders N | предел команд за прогон. По умолчанию 10000 |
--max-steps N | предел шагов на один шаг плана |
--timeout N | сколько процесс, запущенный «Запустить процесс», может молчать, в миллисекундах, от его последнего байта в stdout или stderr. По умолчанию 30000. Дольше — рантайм его убивает и отвечает «Сбой» с FLANG_IO_TIMEOUT. 0 или не число — кривой вызов, код 2 |
--seed N | зерно случайности: прогон становится повторимым |
--in-dir | запретить пути за пределами каталога входного файла |
--pretty | JSON с отступами |
--trust (--на-веру) | запустить план с недоказанными гарантиями; доказательства не проверяются, и об этом говорит отдельная строка |
--unproven СЛОВО (--недоказанное) | refuse (по умолчанию), warn, allow; раз и навсегда — ключ unproven в .flangrc |
-- | всё после него уходит плану, а не flang io. План получает эти доводы командой «Прочитать доводы» — списком строк, по порядку |
Как и run, io сначала проверяет доказательства и печатает одну строку в поток ошибок; план с недоказанными гарантиями не запускается, код 3.
Имя плана пишется без ёлочек, а имя с пробелом — в кавычках оболочки. В исходнике имена пишутся в ёлочках, но --plan берёт имя ровно как набрано, вместе с ёлочками:
$ flang io scripts/shortcut-collector.fscript --plan «Целость»
доказано: утверждений 9
{"error":"не найден план ««Целость»»","diagnostics":[{"code":"FLANG_UNKNOWN_PLAN","message":"не найден план ««Целость»»","severity":"error"}]}
$ echo $?
3
$ flang io scripts/shortcut-collector.fscript --plan Целость
доказано: утверждений 9
{"plan":"Целость","result":"коротких команд 217; …
$ echo $?
0
Без кавычек оболочки имя из двух слов оболочка разбивает на два довода:
$ flang io flang/scripts/kernel-forgeries.fscript --plan «Аксиом ноль»
flang io: непонятный ключ «ноль»»
$ echo $?
2
$ flang io flang/scripts/kernel-forgeries.fscript --plan 'Аксиом ноль' --trust
на веру: доказанность не считалась — запуск по ключу --trust
{"plan":"Аксиом ноль","result":"подделки отвергнуты: 36 файлов каталога … аксиом ноль, нарушений 0", …
$ echo $?
0
Сама справка flang io --help пишет --plan «Имя»; там ёлочки только показывают, куда ставить имя.
Права отнимаются по одному: --no-read, --no-write, --no-net, --no-clock, --no-random, --no-spawn, --no-env, --no-args, --no-screen. По умолчанию можно всё: запуская программу через flang io, вы соглашаетесь с тем, что она делает.
Ключа --args у io нет: план начинается со своей функции начинает с, а не с аргументов. Данные передавайте после --.
$ flang io docs/examples/crypto/revocation.flang --args '{}'
flang io: непонятный ключ «--args»
$ echo $?
2
Коды: 0 — план дошёл до конца; 1 — программа сдалась сама («Провал»): нашла проблему и назвала её; 2 — кривой вызов; 3 — сломался инструмент, или программа ответила «Не проверено» (проверить то, о чём просили, ей было нечем), или план не доказан, а ни --trust, ни настройка unproven его не разрешили.
Пример плана, план.flang, записывает один файл:
модуль «План»
тип «Ход»
вариант «Пишем»
вариант «Ждём запись»
план «Записать привет»
состояние «Ход»
начинает с «Начало»
обрабатывает «Дальше»
тотальная функция «Начало»
возвращает «Ход»
пример «план начинается с записи»
ожидается вариант «Пишем»
вариант «Пишем»
тотальная функция «После записи»
принимает отклик: «Отклик»
возвращает «Продолжение»
пример «записано шесть байт»
дано отклик равно вариант «Записано» с сколько равным 6
ожидается вариант «Конец работы» с значение равным 6
разбор отклик
случай вариант «Записано» с сколько как сколько
то вариант «Конец работы» с значение равным сколько
случай любое
то вариант «Провал» с код равным "FLANG_IO_ORDER" и сообщение равным "ждали подтверждение записи"
тотальная функция «Дальше»
принимает ход: «Ход», отклик: «Отклик»
возвращает «Продолжение»
пример «первым делом пишется файл»
дано ход равно вариант «Пишем»
дано отклик равно вариант «Пока ничего»
ожидается вариант «Сделать» с поручение равным (вариант «Записать файл» с путь равным "привет.txt" и содержимое равным "привет") и потом равным (вариант «Ждём запись»)
разбор ход
случай вариант «Пишем»
то вариант «Сделать» с поручение равным (вариант «Записать файл» с путь равным "привет.txt" и содержимое равным "привет") и потом равным (вариант «Ждём запись»)
случай вариант «Ждём запись»
то «После записи» от отклик
Вывод — результат плана и журнал: каждая команда («поручение») с ответом рантайма («отклик»):
$ flang io план.flang --pretty
доказано: утверждений 0
{
"plan": "Записать привет",
"result": 6,
"orders": 1,
"log": [
{
"поручение": {
"variant": "Записать файл",
"fields": {
"путь": "привет.txt",
"содержимое": "привет"
}
},
"отклик": {
"variant": "Записано",
"fields": {
"сколько": 6
}
}
}
]
}
Отнимите право — и план получит отказ как ответ и сдастся с кодом 1:
$ flang io план.flang --no-write
доказано: утверждений 0
{"error":"ждали подтверждение записи","diagnostics":[{"code":"FLANG_IO_ORDER","message":"ждали подтверждение записи","severity":"error","span":{"line":7,"column":1}}]}
$ echo $?
1
Терминал. Экран — управляющий терминал (/dev/tty), и место у него одно, «экран»; любое другое имя — FLANG_IO_PLACE. «Показать» рисует кадр целиком (очистка, потом текст) в терминале, а не в stdout — в stdout идёт результат плана. На первом «Показать» рантайм переходит на запасной экран терминала и прячет курсор, а по окончании прогона возвращает оба. «Ждать событие» ждёт клавишу не дольше «срока» миллисекунд (0 или без срока — без предела): клавиша даёт «Случилось» с «откуда» равным «клавиатура», истёкший срок — «Срок вышел». Имена клавиш: ввод, пробел, таб, возврат, выход, вверх, вниз, влево, вправо; прочие приходят самим знаком. Ctrl-C по-прежнему останавливает программу. «Размер экрана» отдаёт ширину и высоту в знаках. Без терминала (вывод в трубу, CI, nohup) эти команды отвечают FLANG_IO_NO_SCREEN; с --no-screen — FLANG_IO_DENIED.
HTTPS. Команда «Запросить» поддерживает https. В исходниках рантайма её исполняет клиент TLS 1.3 на языке (flang/stdlib/tls-client.flang), напечатанный в C и собранный в двоичный; двоичный, напечатанный до этой правки, ходит через внешний curl и без него отвечает FLANG_IO_NO_TLS (ADR-0101). Клиент проверяет цепочку до корня, срок, имя узла и подпись узла; беда сертификата — FLANG_IO_TLS_CERT, прочая — FLANG_IO_TLS. Корни — --trust-roots <файл PEM> или системная связка. Отзыв сертификата (OCSP, CRL) не проверяется. «Открыть соединение» — голый TCP.
Датаграммы. «Отправить датаграмму» и «Принять датаграмму» — UDP поверх IPv4, октеты списком чисел; ответ — «Записано», «Датаграмма» или «Срок вышел».
lock
Печатает lock-файл программы: JSON, в котором лежат сами зависимости, а не ссылки на них. Для каждого подключённого модуля записан весь его исходник, и адрес ему — sha256 этого исходника. Реестра нет и скачивать нечего: всё уже в lock-файле.
flang lock <файл.flang> [--pretty]
| Ключ | Что делает |
|---|---|
--pretty | отступ в два пробела |
Если рядом с входным файлом лежит flang.lock, все команды берут импорты из него и исходников зависимостей не читают. Испорченный lock-файл отвергается с FLANG_LOCK.
$ flang lock docs/examples/cli/double.flang
{"схема":2,"вход":"./double.flang","модули":[],"печать":"dcf9b0c54a6a814573047949d66a78d7e4706c67ae8873e637823fa799609779"}
double.flang ничего не подключает, поэтому список модулей («модули») пуст.
package
Печатает пакет: то же содержимое, что у lock-файла, плюс имя, версия, источник и список доказанного.
flang package <файл.flang> [--pretty]
| Ключ | Что делает |
|---|---|
--pretty | отступ в два пробела |
Имя и версия берутся из файла flang.package рядом с входным файлом, а не из ключей. Без него команда отказывает с кодом 1:
$ flang package привет.flang
FLANG_PACKAGE: рядом с привет.flang нет объявления flang.package: пакету нужны имя и версия, и берутся они оттуда, а не из вызова
$ echo $?
1
С flang.package рядом пакет собирается:
$ cat flang.package
{"имя": "Привет", "версия": "1.0.0"}
$ flang package привет.flang | head -c 400
{"схема":2,"имя":"Привет","версия":"1.0.0","вход":"./привет.flang","модули":[{"имя":"Привет","путь":"./привет.flang","функций":1,"адрес":"2bc2186046bc075d03953d3ff11c333835b8561a724dc526bb95c91730fe0699","исходник":"module «Привет»\n\ntotal function «Удвоить»\n accepts н: number\n returns number\n examp
Пакет собирается только из проверенной программы. Как им пользоваться — Как писать пакеты.
new
Заводит каталог с готовым пакетом: модуль с одной тотальной функцией и unit-тестом, каталог fspec/ с одной доказанной спекой и программой проверки guard.flang, манифест flang.package и README.
flang new <имя> [--force]
| Ключ | Что делает |
|---|---|
--force (--силой) | переписать каталог, если он уже есть |
$ flang new проба-cli
flang new: пакет «проба-cli» создан в …/проба-cli
cd проба-cli && flang check проба-cli.flang
flang io fspec/guard.flang
$ ls проба-cli
README.md flang.package fspec проба-cli.flang
Существующий каталог без --force — код 1; имя с пробелом, косой чертой, кавычками или ёлочками либо занятое слово (имя команды, flang, fspec) — код 2, и не создаётся ни одного файла.
run-script
flang run-script [<имя> [доводы…]]
Короткая команда проекта — имя для строки оболочки. Записывается в файле настроек .flangrc как script.<имя> = <команда>, как scripts в package.json:
script.site:build = node docs/site/build.mjs
Без имени flang run-script перечисляет короткие команды проекта; с именем — запускает эту, и всё после имени уходит команде. В каталоге, где .flangrc состоит из двух показанных строк:
$ cat .flangrc
script.hello = echo hello
script.fail = exit 7
$ flang run-script hello
hello
$ echo $?
0
$ flang run-script fail
$ echo $?
7
$ flang run-script missing
flang run-script: короткой команды «missing» в «…/.flangrc» нет. Вот какие есть:
hello echo hello
fail exit 7
$ echo $?
2
Файл — ближайший .flangrc от текущего каталога вверх; файл в домашнем каталоге коротких команд не задаёт. Строка исполняется /bin/sh -c в каталоге этого файла, и код возврата — её собственный. Если имя записано дважды, берётся последняя строка. В строке из нескольких команд через && доводы достаются последней.
| Код возврата | Когда |
|---|---|
| собственный код команды | команда запустилась |
2 | такого имени нет, или нет .flangrc |
3 | файл не прочитался, или не запустился /bin/sh |
Ключи самого двоичного --depth-limit и --step-limit двоичный забирает до имени, и команде они не достаются.
repl
Интерактивная оболочка — то же, что голый flang в терминале. Объявления накапливаются за сессию, выражения вычисляются сразу, .помощь показывает команды оболочки. Файл в доводе загружается при запуске.
flang repl [<файл.flang>] [--max-steps N] [--max-depth N]
| Ключ | Что делает |
|---|---|
--max-steps N | предел шагов вычислителя |
--max-depth N | предел глубины |
Выражение вычисляется так: для сессии генерируется C (как у flang emit), собирается системным компилятором C и запускается:
$ echo '«Удвоить» от 21' | flang repl привет.flang
объявлено: тотальная функция «Удвоить» — завершение доказано
загружено из привет.flang
42
Без компилятора C оболочка работает всё равно: проверяет разбор, типы и завершаемость и вместо значения отвечает «проверено», о чём говорит при запуске:
$ echo '«Удвоить» от 21' | FLANG_CC=/nonexistent/cc flang repl привет.flang
вычислять нечем: компилятора C нет (ни $FLANG_CC, ни cc, ни gcc, ни clang в PATH).
Разбор, типы и завершаемость проверяются по-прежнему; выражение отвечает «проверено».
объявлено: тотальная функция «Удвоить» — завершение доказано
загружено из привет.flang
проверено
Компилятор C и его файлы ищутся через FLANG_CC, FLANG_INCLUDE_DIR и FLANG_LIB_DIR.
lsp
Языковой сервер flang по стандартному вводу и выводу (рамки Content-Length с телом JSON, как требует спецификация LSP). Его запускает редактор; запущенный вручную, он молча ждёт сообщений.
flang lsp [--stdio]
| Ключ | Что делает |
|---|---|
--stdio | общаться через стандартный ввод и вывод |
Умеет: диагностику (те же проверки, что flang check: разбор, имена, типы, завершаемость), дополнение, подсказку с сигнатурой при наведении и переход к объявлению. На стандартный вывод идут только сообщения протокола, всё прочее — в поток ошибок.
Проверить, что сервер работает, — послать ему одно сообщение:
$ printf 'Content-Length: 107\r\n\r\n{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"processId":null,"rootUri":null,"capabilities":{}}}' | flang lsp --stdio
Content-Length: 311
{"jsonrpc":"2.0","id":1,"result":{"capabilities":{"positionEncoding":"utf-16","textDocumentSync":{"openClose":true,"change":1,"save":{"includeText":false}},"completionProvider":{"triggerCharacters":["«","."]},"hoverProvider":true,"definitionProvider":true},"serverInfo":{"name":"flang-lsp","version":"0.1.0"}}}
Известное ограничение: в программе с использует (импорт) ошибка в подключённом модуле уходит в журнал редактора, а не подчёркивается в буфере этого модуля.
Справка двоичного целиком
Ниже — то, что печатает сам двоичный: flang --help и flang <команда> --help по каждой команде. Текст вставлен из вывода при сборке страницы и сверяется с ним на каждой проверке, поэтому расходиться с двоичным не может. Двоичный говорит по-русски.
$ flang --help
flang 0.7.29 — язык, проверяемый до запуска: типы и доказанное завершение.
flang оболочка: объявляй и считай сразу
flang check <файл> разбор, типы, завершаемость, доказательства
flang test <файл|каталог> прогон примеров: один файл или целый каталог
flang run <файл> --function «Имя» вычислить одну функцию и напечатать значение
flang emit <файл> --target «цель» напечатать программу: c|cpp|go|rust|java|js|ts|elixir|python|csharp
flang ast <файл> разобранная программа деревом в JSON
flang tokens <файл> поток токенов: чем каждое слово стало у лексера
flang lint [<путь>…] длина строк и глубина ветвлений против «.flangrc»
flang facts <файл> --claims '[…]' проверить утверждения на фактах
flang io <файл> исполнить план: файлы, каталоги, процессы, сеть
flang lock <файл> замок: сами зависимости, а не ссылки на них
flang package <файл> пакет: замок с именем, версией и ведомостью
flang new <имя> новый пакет с нуля: модуль, fspec/, манифест
flang run-script <имя> короткая команда проекта из «.flangrc»
flang repl [файл] та же оболочка, названная по имени
flang lsp [--stdio] языковой сервер для редактора (LSP)
flang --mcp-mode служба для ИИ-помощника (MCP по стандартным потокам)
flang --help эта справка
flang --version версия
flang --machine [<файл>] постоянная этой машины: витков в секунду
flang <команда> --help все ключи команды
--depth-limit N предел глубины вызовов САМОГО бинарника
на этот прогон; годится при любой команде
и поднимает заодно стек. Кириллицей:
--предел-глубины
--step-limit N предел ШАГОВ самого бинарника на этот
прогон; годится при любой команде, печать
включая. НЕ путать с «--max-steps N» у
«emit»: тот впечатывается в вывод и своему
прогону не говорит ничего. Кириллицей:
--предел-шагов
--memory-limit N предел ПАМЯТИ самого бинарника на этот
прогон, байтами или с буквой K, M, G, T;
0 — без предела. У check, test и run по
умолчанию три четверти памяти машины. На
пределе — остановка кодом 5 с именем
функции и числом шагов. Кириллицей:
--предел-памяти
Без доводов и без терминала на входе (конвейер, «--json») бинарник остаётся
прогонщиком: JSON на входе, JSON на выходе, по запросу на строку.
Здесь все 15 команд, и «flang lsp» среди них; отдельная команда «flang-lsp» —
тот же языковой сервер, который кладёт на «PATH» пакет npm.
Служба для ИИ-помощника отвечает НЕ «ок»: три вердикта — «доказано», «сетка N»
и «объявлено, не доказано» — уходят порознь. «flang --mcp-mode --help» — как её
прописать помощнику.
Чего бинарник не судит — ЗАКОНЫ КАТЕГОРИИ бинарник СЧИТАЕТ САМ — на сетке, с названным числом
значений: что объявленное равенство есть эквивалентность, что композиция
его уважает, что она ассоциативна и что квадрат естественного
преобразования коммутирует. Это счёт, а не доказательство, и отчёт говорит
об этом словами.
ЧЕГО НЕТ — УСТРОЙСТВО тех же объявлений: что категория замкнута под
композицией, что у каждого объекта есть единица, что концы у композиции
сходятся, что морфизм и преобразование объявлены как надо. Целиком нет
этих: связь модулей, бифунктор, изоморфизм, моноид, монада, множества,
объявленные свойства, требования, процесс, надзор, прогон.
Программу с такими объявлениями «flang check» НЕ пропускает молча: он
называет, чего не проверил, и отвечает кодом 2.
Подробности: man flang
flang check --help
$ flang check --help
flang check <файл.flang> [--proof [--json] [--strict] [--record <файл>]]
[--fast] [--step-limit N] [--depth-limit N]
Разбор, типы, завершаемость, ядро доказательства. Замечания с кодом и местом,
код возврата 1, если программа не прошла.
--fast только связывание, типы, исчерпываемость и
завершаемость. Ядро доказательств, законы категории и
прогон примеров НЕ ЗАПУСКАЮТСЯ, и об этом говорится
вслух: что пропущено, сколько обязательств и сколько
примеров не смотрели. Код возврата 4 — «часть проверок
не запускалась»; ноль остаётся за «спрошено всё».
Рядом с «--proof» не имеет смысла и отвергается:
ведомость — это ответ ядра. Кириллицей: --быстро
--proof ведомость: чем несётся обещание «тотальная» у каждой
функции и чем — каждое высказанное утверждение
--json вместе с --proof: ведомость машинным видом
--strict вместе с --proof: четыре исхода разъезжаются кодами.
0 — ДОКАЗАНО: утверждений хотя бы одно и у КАЖДОГО
вердикт «доказано»; 1 — ОПРОВЕРГНУТО; 3 — НЕ УДАЛОСЬ
ДОКАЗАТЬ (опора на сетку значений автора, на
недоказанную посылку или «объявлено, не доказано»);
2 — НЕ ПОДДЕРЖИВАЕТСЯ. Код 4 остаётся за «--fast».
Без ключа опора остаётся нулём и называется строкой.
Кириллицей: --строго
--record <файл> вместе с --proof: положить САМО доказательство в файл
строками, которые читает и человек, и сверщик
(flang/proof/checker.flang). Ключ пишется и кириллицей:
--записать
--step-limit N ключ САМОГО бинарника (стоит где угодно в строке) —
поднять предел шагов ПРОВЕРЯЮЩЕГО на этот прогон.
Умолчание вшито при сборке (scripts/bootstrap-reprint.sh) и
ловит зацикливание; ключ поднимает его осознанно и
только там, где сказано. Исчерпание остаётся внятным:
FLANG_RECURSION_LIMIT с числом. Кириллицей: --предел-шагов
--depth-limit N поднять предел ГЛУБИНЫ вызовов на этот прогон. Ключ
общий у всех команд бинарника и поднимает заодно стек,
которым глубина и несётся. Не путать с «--max-depth» у
«emit»: тот кладёт число в НАПЕЧАТАННУЮ программу, а
этот — в текущий прогон. Кириллицей: --предел-глубины
--memory-limit N предел памяти прогона (умолчание — три четверти памяти
машины); на пределе — код 5 с именем функции и числом
шагов. Кириллицей: --предел-памяти
ПУСТАЯ ВЕДОМОСТЬ ПОД «--strict» — НЕ УСПЕХ. Ноль под ключом требует хотя бы
одного обязательства: у программы без единого утверждения и закона прибор не
проверил ничего, и ответ ей — ПРОВЕРЕНО ВПУСТУЮ, код 3. «Доказано ноль из
нуля» — тишина, а не доказательство, и код 0 значил бы «ничего не нашли».
Умолчание тут не тронуто: без ключа такая программа по-прежнему ноль.
Категорной поверхности и процессов бинарник НЕ СУДИТ ВОВСЕ — ни доказуемых
правил (концы стрелок, замкнутость категории, полнота связи), ни законов на
сетке (моноид, монада, изоморфизм, равенство морфизмов, множества, квадрат
связи, пять объявленных свойств), ни процессов, надзора и прогонов. Слоёв,
которые это делают, в бинарнике нет. Поэтому программа с такими объявлениями
получает отказ с названным пробелом и код 2 — и у check, и у --proof:
«замечаний нет» и пустой раздел ведомости читались бы как «проверено», а это
неправда. Поиск нарушений по примерам тоже не переехал: ведомость говорит «не
искали», а не «не найдено». Печать такую программу ПЕЧАТАЕТ, но называет тот же
пробел и уходит кодом 3: файлы есть, ручаться за них целиком нельзя.
ДВА ЗАЗОРА, которые бинарник не умеет даже НАЗВАТЬ, и потому названы здесь.
Уточнённые числовые типы («сотых», «вес») стоят типом в подписи, а не
отдельной строкой: программу с ними от обычной по объявлениям не отличить, и
check на ней отвечает «замечаний нет». Мост из FTS («.fts»-модели, законы
поверх них) бинарник не принимает вовсе.
Полный список правил, которых здесь нет, — не в этой справке, а в проверке:
flang/scripts/binary-rules-guard.mjs сверяет СОСТАВ ПРАВИЛ двух реализаций в
обе стороны, и правило, дописанное одной из них, красит её само.
flang test --help
$ flang test --help
flang test <файл.flang | каталог | маска> [--no-check] [--json]
[--max-steps N] [--max-depth N]
Прогон примеров, объявленных внутри функций. Сначала проверяет программу теми
же проверками, что и check: «пример сошёлся» на программе с ошибкой типов не
значит ничего.
Довод, не кончающийся на «.flang», и всякий довод со звездой или вопросом —
это НАБОР файлов, а не один файл:
flang test flang/stdlib/ весь каталог, вглубь
flang test 'examples/**/*.flang' по маске (кавычки — от оболочки)
У набора печатается каждый не прошедший пример и каждый не взятый файл, а
прошедшие — числом. Код возврата 0 — взяты все файлы и сошлись все примеры;
1 — что-то не сошлось или файл не взят; 2 — кривой вызов.
--no-check не проверять — смотреть на поведение примеров, пока
программа ещё в правке
--json машиночитаемый итог одной строкой
--ledger ведомость: по строке на файл, для сверки диффом
--max-steps N предел шагов вычислителя
--max-depth N предел глубины
--memory-limit N предел памяти прогона (умолчание — три четверти памяти
машины); на пределе — код 5 с именем функции и числом шагов.
Кириллицей: --предел-памяти
У не сошедшегося примера называются ОБЕ стороны: ожидалось и получено.
Длинное значение обрезается на 200 знаках, и длина полного сказана числом.
Примеры, объявленные при морфизмах теорката, здесь не прогоняются: их считает
версия для Node. На таких программах счёт «примеров N» окажется меньше её.
flang run --help
$ flang run --help
flang run <файл.flang> --function «Имя» [--args '{"н":10}'] [--max-steps N]
[--max-depth N] [--trust] [--unproven refuse|warn|allow]
[--cost]
Вычисляет ОДНУ функцию и печатает значение. Считает сам flang — ни Node, ни
«cc» для этого не нужны.
Аргументы сверяются объявленным типам ДО вычисления: «Факториал» от −3
отвергается FLANG_TYPE, а не считается.
ПЕРЕД ВЫЧИСЛЕНИЕМ СЧИТАЕТСЯ ВЕРДИКТ и одной строкой уходит в поток ошибок:
«доказано: утверждений N» либо «не доказано: …». Судится ЗАМЫКАНИЕ — всё,
что связано, а не один файл. Недоказанная программа не считается вовсе:
код 3 (ADR-0045). Запустить её всё же — «--trust» на один прогон либо ключ
«unproven» в «.flangrc» — раз и навсегда.
--function «Имя» что вычислять
--args '{…}' аргументы: ПЛОСКИЙ объект скаляров, вроде '{"н":10}'.
Списка или вложенного объекта здесь не принимают —
их считает версия для Node
--max-steps N предел шагов вычислителя
--max-depth N предел глубины ВЫЧИСЛЯЕМОЙ программы. Предел самого
бинарника — другой счётчик и другой ключ:
«--depth-limit N»
--memory-limit N предел памяти прогона (умолчание — три четверти памяти
машины); на пределе — код 5 с именем функции и числом
шагов. Кириллицей: --предел-памяти
--cost после значения одной строкой в поток ошибок: шагов
вычислителя (тот же счётчик, что у «--max-steps»), пик
памяти процесса в байтах и секунды всего прогона.
Кириллицей — «--цена»
--trust считать недоказанную: вердикт не считается вовсе, и об
этом говорится своей строкой. Кириллицей — «--на-веру»
--unproven СЛОВО что делать с недоказанной, все три исхода сразу:
refuse — не запускать (умолчание), warn — сказать и
запустить, allow — запустить, вердикта не считая (то же,
что «--trust»). Кириллицей — «--недоказанное отказ |
предупреждение | разрешение»
ТО ЖЕ РАЗ И НАВСЕГДА — ключ «unproven» в «.flangrc»
(docs/guide/settings.ru.md): «unproven = warn». Старшинство: ключ команды
старше переменной среды FLANG_UNPROVEN, та старше «.flangrc», а он —
умолчания «refuse». Значения, которого нет, файл молча не проглатывает:
отказ словами и код 2. Запись до 0.7.22, «недоказанное = отказ», читается
по-прежнему, и одной строкой сказано, какой английской её заменить.
flang emit --help
$ flang emit --help
flang emit <файл.flang> --target c|cpp|go|rust|java|js|ts|elixir|python|csharp
[--out каталог | --file имя] [--cli|--no-cli] [--repl]
[--runtime каталог] [--index-base 0|1]
[--max-steps N] [--max-depth N] [--no-check]
[--no-postconditions]
Печатает программу без Node — во все десять целей. Каталог из «--out»
заводится сам, вместе с промежуточными и с подкаталогами, которых просит цель
(у Go путь файла — это имя пакета).
--out каталог записать все файлы в каталог
--protocol файл рядом с C напечатать протокол перевода (только у цели «c»,
ADR-0030): что во что перешло и по какому правилу; его
переигрывает flang/translation/matcher.c. Кириллицей —
--протокол
--file имя один файл на стандартный вывод
--cli | --no-cli печатать ли прогонщик
--repl напечатать ещё и человеческий вход (только цель «c»)
--runtime каталог где лежат исходники рантайма цели
--max-steps N предел шагов, ВПЕЧАТЫВАЕМЫЙ в напечатанную программу
(«#define FL_MAX_STEPS»). Своему прогону печати он не
говорит ничего — для него «--step-limit N»
--max-depth N предел глубины, ВПЕЧАТЫВАЕМЫЙ в напечатанную программу
(«#define FL_MAX_DEPTH»). Своему прогону печати он не
говорит ничего — для него «--depth-limit N»
--no-check не гонять ядро доказательств. Насколько быстрее —
зависит от модуля, и РАЗНИЦА ОГРОМНА: числа ниже.
Напечатанное толще. ЧТО ЭТИМ НЕЛЬЗЯ — ниже, отдельным
абзацем: в ствол напечатанное так НЕ ГОДИТСЯ
--no-postconditions не печатать сторожей постусловий В КОД. Судятся они
по-прежнему: это ключ печати, а не проверки. Напечатанное
заметно быстрее и говорит о ключе своей шапкой — числа и
условия ниже, отдельным абзацем
ПЕЧАТАЕТСЯ ТОЛЬКО ПРОВЕРЕННОЕ. Перед печатью программа судится той же дорогой,
что и «flang check»: разбор, связывание, типы, завершаемость и ядро
доказательств. Замечание — печать отменена и код 1, ни файла не записано.
ЧЕГО ЭТА СБОРКА НЕ СУДИТ, она называет. Категорную поверхность и процессы с
надзором она не судит вовсе. Такая программа ПЕЧАТАЕТСЯ — иначе эту часть языка
нечем было бы собрать без Node, — но несуждённое зовётся поимённо, а код 3.
Коды: 0 напечатано и пробелов нет, 1 не прошло проверку, 2 неверен вызов,
3 напечатано, но проверено не всё.
ПРИМЕРЫ не прогоняются, и это названо, а не умолчано: их считает вычислитель на
самом языке, и на самых больших программах дерева он в предел шагов этой сборки
не укладывается — свяжи с ними печать, и компилятор перестал бы печатать сам
себя, то есть сломалась бы раскрутка. Прогоняются они «flang test <файл>».
«--no-check» СНИМАЕТ РОВНО ЯДРО ДОКАЗАТЕЛЬСТВ, и больше ничего. Разбор,
связывание, типы и завершаемость судятся и с ним, и печать при замечании
по-прежнему отменяется кодом 1. Имя ключа шире его дела: написание занято у
«flang test» и у версии для Node, и второе заводить не стали — потому дело и
названо здесь, а не оставлено на догадку.
СКОЛЬКО ОН ЭКОНОМИТ — ЧИСЛО НЕ ОДНО, и разброс больше самой экономии;
«вдвое» неправда в обе стороны. Замер 30 августа 2026 на этом дереве, круг
«печать + сборка», по два прогона:
flang/self/builtins.flang 148,8 → 18,9 с в 7,9 раза быстрее
flang/self/cli.flang 13,1 → 7,5 с в 1,8 раза
flang/self/lexer.flang 6,5 → 6,9 с КЛЮЧ ВРЕДИТ
Цена ядра растёт с числом ДОКАЗЫВАЕМЫХ постусловий, а не с размером файла:
у lexer.flang ядро стоит 4 % печати, у builtins.flang — 95 %. А сборка с
ключом идёт ДОЛЬШЕ, потому что сторожей в напечатанном больше. Где ядро
дёшево, ключ проигрывает — не берите его по привычке, померьте.
ОТДЕЛЬНЫЙ СЛУЧАЙ — где ядру не хватает миллиарда шагов: distributed.flang и
bounded.flang без ключа не печатаются ВОВСЕ («ядро доказательства
прекращено» через 110 с), с ключом печатаются за 4,4 с.
ЧЕГО ОН НЕ ДАЁТ — а это важнее того, что даёт:
* НАПЕЧАТАННОЕ ЭТИМ КЛЮЧОМ НЕ ГОДИТСЯ В СТВОЛ. Отпечаток семени не сойдётся
(«scripts/seed-fingerprint»), а собранный из такого семени двоичный толще
и поведёт СЛЕДУЮЩУЮ печать медленнее — то есть беда переезжает дальше
самого семени. Перепечатка семени идёт БЕЗ этого ключа, всегда;
* доказательств никто не проверял. Ложное доказательство ядро ловит, а без
ядра оно проходит молча — прогоните «flang check», прежде чем верить;
* быстрее становится ПЕЧАТЬ, а не напечатанное. Постусловия уезжают в код
все до одного, включая доказанные, которые печать с ядром снимает: список
снимаемых считает то самое ядро. Напечатанное толще и на работе медленнее
(замер: сторожей на «flang/stdlib/lists.flang» 67 против 29), но не
слабее — лишний сторож стережёт то, что и так верно.
Это средство разработчика, а не замена перепечатке. Двоичный говорит всё то же
самое ВСЛУХ после каждой печати с ключом, чтобы ключ, уехавший в скопированный
рецепт, не стал привычкой за день.
«--no-postconditions» СНИМАЕТ СТОРОЖЕЙ В НАПЕЧАТАННОМ КОДЕ, А НЕ ПРОВЕРКУ.
Постусловие остаётся в исходнике, остаётся обещанием и судится этой же
командой: разбор, типы, завершаемость и ядро доказательств идут как обычно, и
замечание по-прежнему отменяет печать кодом 1. «flang check» и «flang test»
ключа не знают вовсе — они считают постусловия ВСЕГДА.
ЗАЧЕМ. Постусловие пересчитывается на КАЖДОМ возврате. Замер 2 сентября 2026,
раскладка терминального экрана (19 функций, 25 обещаний, цель go, кадр целиком,
«go test -benchtime 200x -count 5», медиана пяти, AMD EPYC 7742):
кадр 80×24 42,6 мс со сторожами → 6,00 мс без них в 7,1 раза
кадр 200×50 100,0 мс → 14,6 мс в 6,9 раза
выделений на кадре 200×50: 151 226 → 29 354
напечатанного кода на Go: 1862 строки → 1303, сторожей rt.Post 23 → 0
Кадр перерисовывается не только по такту, но и на каждое нажатие клавиши и на
каждый SIGWINCH; 15 мс не видно, 100 мс видно. На программе, которую зовут раз
в час, ключ не нужен — померьте, прежде чем брать.
СВЕРЕНО, ЧТО СНЯТИЕ НЕ МЕНЯЕТ ЗНАЧЕНИЙ: 1119 входов на трёх функциях той же
раскладки, печать с ключом против печати без него — расхождений нет. И то, что
печатает ключ, совпало БАЙТ В БАЙТ с печатью исходника, из которого строки
«обеспечивает» вырезаны руками.
ВСЕ ВОСЕМЬ ЦЕЛЕЙ ВЕДУТ СЕБЯ ОДИНАКОВО: постусловия снимаются с разобранной
программы до того места, где цели расходятся, — печатнику про ключ знать
нечего.
НАПЕЧАТАННОЕ ГОВОРИТ О КЛЮЧЕ САМО. В шапку каждого файла кладётся заметка:
ключ, число снятых сторожей и то, что обещания проверяются на воротах, а не
здесь. Молча отдать облегчённый код нельзя — тот, кто взял его в руки, обязан
узнать об этом из него. Без заметки остаются два файла, где её негде
поставить: «go.mod» (шапки нет вовсе) и «flang.csproj» (XML-комментарий не
терпит двух дефисов подряд, а имя ключа их содержит).
ЧЕГО КЛЮЧ НЕ СНИМАЕТ: предусловия, сторожа убывания у тотальных функций,
пределы шагов и глубины, разбор отказов надзора.
ПЕРЕПЕЧАТКОЙ СЕМЕНИ ЭТО НЕ ПОЛЬЗУЮТСЯ: компилятор собирают со сторожами,
довод тот же, что у «--no-check».
РАНТАЙМ ЦЕЛИ уезжает в вывод ДОСЛОВНО, поэтому читается с диска: от двух
файлов у go, rust, js и python до шести у java и csharp, у cpp четыре (три
из них рантайм «c»). Ищутся они в
«--runtime», затем в $FLANG_RUNTIME_DIR, затем рядом с установленным flang
(share/flang/<цель>); в дереве исходников это flang/src/emit/<цель>. Полный
перечень имён — man flang.
СВЕРХУ УЖЕ СКАЗАНО, ЧТО ПЕЧАТАЕТСЯ ТОЛЬКО ПРОВЕРЕННОЕ, и это правда: типы и
завершаемость печать судит и при замечании отменяется. Проверено прогоном
25 августа 2026: функция, объявленная как «число», с телом-строкой даёт
FLANG_TYPE, «печать отменена», код 1 и ни одного файла.
ЧЕМ ЭТА ПЕЧАТЬ ОТЛИЧАЕТСЯ ОТ ПЕЧАТИ ПОЛНОГО ИНСТРУМЕНТАРИЯ:
c недостижимое НЕ отбрасывается, доказанное не метится
(«markProven»); напечатанного просто больше, работает так же;
все прочие недостижимое отбрасывается, как у свидетеля.
У ВСЕХ ДЕВЯТИ ПУСТА ГРАНИЦА ВХОДА: таблицу объявленных типов строит слой
типов свидетеля, которого на flang нет ни строки. Напечатанное собирается и
работает, но аргументы прогонщика объявленным типам не сверяются, и об этом
сказано словами после печати.
Невтащенных целей больше нет: все десять живут в замыкании этой сборки, и
печатает их она сама, без Node.
flang ast --help
$ flang ast --help
flang ast <файл.flang> [--pretty]
Печатает разобранную и СВЯЗАННУЮ программу деревом в JSON — то же самое, что
видит печать в целевой язык. Связывание здесь не украшение: без него у
программы с «использует … из "…"» дерево вышло бы неполным, и первым признаком
стала бы не ошибка команды, а несобирающийся напечатанный код.
--pretty с отступами в два пробела
Проверок типов и завершаемости здесь нет НАМЕРЕННО: дерево — это то, что
прочитано, а не то, что признано годным. Отказывает команда только на том, из
чего дерева не выходит вовсе, — на разборе и на связывании.
flang tokens --help
$ flang tokens --help
flang tokens <файл.flang> [--json] [--pretty]
flang tokens --keyword «фраза»
Печатает поток токенов — то, что прочитал ЛЕКСЕР, до разбора и до связывания.
Вопрос, ради которого команда есть, один: чем станет это слово, если его
написать. Грепом он не решается — ломает программу не текст, а токен: слово в
комментарии, слово внутри строкового литерала и имя в ёлочках ключевым словом
не становятся никогда.
--json машинный вид: те же ключи, что у «flang ast» — kind, value, text,
quoted и span со строкой и столбцом
--pretty с отступами в два пробела; машинный вид включает сам
--keyword «фраза» ключевое ли это слово: имя конструкции или отказ. Фраза
из нескольких слов проверяется как фраза — «код символа» лексер
отдаёт ОДНИМ токеном, а «элемент или беда» тремя, и формой языка
вторая не является
Связывания здесь нет, в отличие от «flang ast»: токены файла от подключений не
зависят вовсе. Отказ бывает там же, где отказал сам лексер, — незакрытый
литерал, рваный отступ; тогда код 1, а машинный вид всё равно печатается, с
пустым tokens и заполненным diagnostics.
flang lint --help
$ flang lint --help
flang lint [<путь>…] [--max-line-length N] [--max-conditional-depth N]
[--warn | --refuse] [--tsv]
Меряет исходники и планы flang двумя мерами: длину строки в знаках и
глубину ветвлений в теле функции. Каталог обходится целиком, кроме имён с
точкой в начале; без путей — рабочий каталог. Файл не исходник — пропущен.
--max-line-length N предел длины строки в знаках
--max-conditional-depth N предел глубины: сколько «если» и «разбор»
вложено друг в друга в теле функции
--warn назвать нарушения и ответить нулём
--refuse назвать нарушения и ответить единицей
--tsv машинный вид: строка на находку, поля через
табуляцию, без итоговой строки
Те же пределы — ключи «.flangrc»: max-line-length, max-conditional-depth и
lint = refuse|warn. Ключ команды старше файла проекта, файл проекта старше
файла дома. Предела нет нигде — мера не применяется.
Коды: 0 — нарушений нет или сказано «warn»; 1 — нарушения есть; 2 — плохой
вызов, нет пути или негодное значение в «.flangrc»; 3 — нарушений нет, но
часть файлов не разобралась, и глубина в них не измерена.
flang facts --help
$ flang facts --help
flang facts <файл.flang> --claims '["…"]' [--facts факты.json] [--steps N] [--pretty]
Проверяет утверждения на фактах — то, ради чего язык написан. Утверждение
имеет вид «<что-то> <оператор> <что-то>»; слева бывает факт, поле факта или
вызов функции от фактов, справа — то же самое или литерал.
--facts файл факты JSON-объектом (без ключа — фактов нет)
--claims '[…]' что проверять, JSON-массивом строк
--steps N предел шагов вычисления (по умолчанию 10000)
--pretty JSON с отступами
КОД 1 ЗДЕСЬ ЗНАЧИТ «ОПРОВЕРГНУТО», а не «сломалось»: вердикт всё равно уходит
в stdout, и код нужен, чтобы на нём падал CI. Код 2 — отказ вызова: не назван
файл, не разобран JSON, не связалась программа.
Вызов зовётся ТОЛЬКО у функции, чьё завершение доказано: нетотальная даёт
отказ до всякого вычисления. Упирание в предел шагов — тоже ответ, «не
досчитали за отведённый бюджет», а не сбой инструмента.
flang io --help
$ flang io --help
flang io <файл.flang> [--plan «Имя»] [--max-orders N] [--seed N] [--in-dir] [--pretty]
[--timeout МС] [--trust] [--unproven refuse|warn|allow] [-- довод…]
Исполняет ПЛАН — единственное место языка, где программа встречается с миром.
Встречается не сама: каждый шаг возвращает ОПИСАНИЕ действия, а делает его
хозяин. Поэтому все функции плана остаются тотальными и проверяются обычными
примерами — без файлов и без сети.
--plan «Имя» какой план исполнять, если их несколько
--max-orders N предел поручений за прогон (по умолчанию 10000)
--seed N семя случайности: прогон становится повторимым.
«Случайное число» без семени берёт /dev/urandom;
«Случайные октеты» берут его всегда, а под семенем
отказывают кодом FLANG_IO_ENTROPY
--in-dir запретить пути за пределы каталога входного файла
--trust-roots Ф связка корней PEM для «https»; без ключа — системная
--max-steps N предел шагов вычисления на один виток
--timeout МС срок ТИШИНЫ процесса из «Запустить процесс», миллисекундами
(по умолчанию 30000): отсчёт от последнего байта в stdout
или stderr, а не от запуска. Молчит дольше — хозяин убивает
его и отвечает «Сбой» с кодом FLANG_IO_TIMEOUT. Свой срок
плана (поручение «Запустить процесс с пределом»)
этого срока НЕ отменяет: ждут оба, бьёт тот, что раньше
--pretty JSON с отступами
--trust исполнить недоказанный план: вердикт не считается вовсе, и
об этом говорится своей строкой. Кириллицей — «--на-веру»
--unproven СЛОВО что делать с недоказанным: refuse — не исполнять
(умолчание), warn — сказать и исполнить, allow — то же, что
«--trust». Кириллицей — «--недоказанное отказ |
предупреждение | разрешение». Раз и навсегда — ключ
«unproven» в «.flangrc» (docs/guide/settings.ru.md)
-- ГРАНИЦА: всё, что стоит после этого отдельного довода, —
доводы ПЛАНА, а не ключи команды. Их отдаёт поручение
«Прочитать доводы» списком строк, в том же порядке и без
разбора. Ключи самого «flang io» в этот список не попадают
никогда, имени программы и имени файла плана в нём нет.
Нет «--» в строке — список пуст
Полномочия сужаются по одному: --no-read, --no-write, --no-net, --no-clock,
--no-random, --no-spawn, --no-env, --no-args, --no-screen. Умолчание —
«можно всё»: запуск программы этой командой и есть согласие на её действия.
КОДЫ ВОЗВРАТА — контракт. 0 — план дошёл до конца; 1 — ПРОГРАММА СДАЛАСЬ
САМА («Провал»), то есть нашла беду и назвала её; 2 — кривой вызов; 3 —
сломался инструмент ЛИБО программа сказала «Не проверено», то есть смотреть
ей было нечем. Первое и второе различает не код отказа, а то, КТО принял
решение; второе и третье — то, ЧТО решено: «нашёл беду» против «не смог
посмотреть». Тройкой же отвечает и ОТКАЗ ЗАПУСКА недоказанного плана: перед
работой считается вердикт о замыкании и одной строкой уходит в поток ошибок
(ADR-0045); «--trust» («--на-веру») его пропускает, «--unproven warn»
предупреждает и работает, а сказать это раз и навсегда можно ключом
«unproven» в «.flangrc». Негодное значение там — код 2, а не тишина.
Среду и доводы хозяин читает сам: «Прочитать переменную среды» отдаёт РОВНО
названную переменную («Значение среды»), а незаданную — отдельным откликом
«Переменной среды нет», а не пустой строкой; пустое имя — отказ FLANG_IO_ENV.
Среды целиком не отдаётся: вместе с ней уехали бы ключи и пароли, которых
план не спрашивал. Запрет — --no-env и --no-args, отказом FLANG_IO_DENIED.
ЭКРАН ДВОИЧНОГО — УПРАВЛЯЮЩИЙ ТЕРМИНАЛ (/dev/tty), и место у него ОДНО, оно
зовётся «экран»; всякое другое имя — отказ FLANG_IO_PLACE. «Показать» кладёт
«текст» целым кадром: очистка, потом текст. Пишется кадр в терминал, а НЕ в
stdout — там вердикт плана, и смешивать их нельзя. На первом «Показать»
хозяин уходит на запасной экран терминала и прячет курсор, а при завершении
прогона — удачном ли, по отказу ли — возвращает как было.
«Ждать событие» переводит терминал в посимвольный режим и ждёт нажатия не
дольше «срока» миллисекунд; срок 0 или неназванный — без предела. Пришла
клавиша — «Случилось» с «откуда» равным «клавиатура»; вышел срок — «Срок
вышел». Имена клавиш: ввод, пробел, таб, возврат, выход, вверх, вниз, влево,
вправо; прочее приходит самим знаком. CTRL-C ПРОДОЛЖАЕТ УБИВАТЬ ПРОГРАММУ и
в ожидании тоже: выход человеку программа не отнимает.
«Размер экрана» отдаёт «Экран» с «ширина» и «высота» — знаков в строке и
строк на экране. Нулевой или нечитаемый размер — отказ, а не 80×24: кадр по
выдуманной ширине рисуется молча и неверно.
Терминала нет — вывод уведён в трубу или в файл, CI, nohup — и все три
поручения отвечают FLANG_IO_NO_SCREEN, ровно как отвечали всегда.
«https» у «Запросить» исполняет САМ ДВОИЧНЫЙ: клиент TLS 1.3 на языке
(flang/stdlib/tls-client.flang), напечатанный в C и собранный в него; curl
не нужен. Беда сертификата — FLANG_IO_TLS_CERT, прочая — FLANG_IO_TLS, код
клиента первым словом. Корни — --trust-roots <PEM>, иначе системная связка.
ОТЗЫВ СЕРТИФИКАТА НЕ ПРОВЕРЯЕТСЯ. «Открыть соединение» — голый TCP.
UDP (IPv4): «Отправить датаграмму» и «Принять датаграмму» (ADR-0101).
flang lock --help
$ flang lock --help
flang lock <файл.flang> [--pretty]
Печатает ЗАМОК программы — JSON, в котором лежат САМИ зависимости, а не ссылки
на них: у каждого импортированного модуля записан его исходник целиком, а
адресом ему служит sha256 по этому исходнику. Склада нет вовсе — скачивать
неоткуда, потому что всё уже в замке; сжатия в формате нет тоже.
flang lock программа.flang > flang.lock
Если рядом с входным файлом лежит flang.lock, все команды берут импорты ИЗ НЕГО
и исходников зависимостей не читают вовсе — их может не быть на диске. Замок
самозаверен печатью: испорченный замок — отказ FLANG_LOCK, а не тихая сборка из
чего попало. Обновляется замок целиком: в нём лежит код, а не хеш.
--pretty с отступами в два пробела
Входного модуля в грузе нет: замок отвечает на вопрос «из чего собрана эта
программа», а сама программа лежит рядом с ним.
flang package --help
$ flang package --help
flang package <файл.flang> [--pretty]
Печатает ПАКЕТ — тот же груз, что в замке, плюс имя, версия, источник и
ведомость доказанного. Имя и версию команда берёт из объявления flang.package
рядом со входным файлом, а не из ключей вызова: ключ живёт в истории оболочки,
а объявление живёт в репозитории и попадает в «git diff».
flang package strings.flang > strings.flang-package
Подключается пакет одной строкой и без новых слов в языке:
использует «Строки» из "strings.flang-package"
Исходников зависимостей при этом на диске нет, склада нет, сети не надо: код уже
в файле. Испорченный пакет — отказ FLANG_PACKAGE. Двух версий одной библиотеки в
программе по-прежнему не бывает; два пакета, привезшие один путь с разным
содержимым, — тоже FLANG_PACKAGE, а не молчаливый выбор первого.
--pretty с отступами в два пробела
Пакет собирается ТОЛЬКО ИЗ ПРОВЕРЕННОГО: пакет — это обещание, а обещать за
непроверенное нельзя.
flang new --help
$ flang new --help
flang new <имя> [--force]
Создаёт каталог <имя>/ с готовой структурой пакета одной командой: базовый
модуль с тотальной функцией и примером, каталог fspec/ с одной доказанной
спекой и стражем guard.flang, манифест flang.package и README.
flang new проба
cd проба
flang check проба.flang
flang io fspec/guard.flang
Имя пакета — без пробела, косой черты, обратной косой черты, кавычек и
гильемет, вне списка зарезервированных слов (имена команд бинарника,
«flang», «fspec») и не «.»/«..». Недопустимое имя — отказ FLANG_NEW,
код 2, и ни один файл не создаётся.
--force переписать каталог, если он уже существует. Кириллицей: --силой.
Без ключа существующий каталог — отказ
FLANG_NEW, код 1: команда не переписывает чужую работу молча.
Образец fspec/ команда берёт рядом с собой (<каталог двоичного>/../fspec)
или из FLANG_FSPEC_TEMPLATE_DIR; не нашла ни того ни другого — отказ
FLANG_NEW, код 1, и каталог не заводится вовсе.
flang run-script --help
$ flang run-script --help
flang run-script [<имя> [доводы…]]
Короткая команда проекта: имя, за которым стоит строка оболочки. Записана она
в файле настроек «.flangrc» строкой «script.<имя> = <команда>»:
script.site:build = node docs/site/build.mjs
flang run-script перечень: имя и команда каждой
flang run-script site:build исполнить
flang run-script version 0.7.23 доводы после имени уезжают команде
Файл — ближайший «.flangrc» от рабочего каталога вверх, по правилу остальных
настроек; файл дома коротких команд не даёт. Команду исполняет «/bin/sh -c» в
каталоге этого файла, и код возврата — её собственный. Одноимённых строк две —
берётся последняя. У строки из нескольких команд через «&&» доводы достаются
последней.
Имени в файле нет — код 2 и перечень; файла нет — код 2; оболочка не
запустилась — код 3.
flang repl --help
$ flang repl --help
flang repl [<файл.flang>] [--max-steps N] [--max-depth N]
Интерактивная оболочка — то же самое, что голая команда «flang» на терминале.
Объявления накапливаются в сессии, выражения вычисляются сразу, «.помощь»
показывает команды. Файл в аргументе загружается в сессию при запуске.
Выражение считается так: сессия печатается в C тем же способом, что у
«flang emit», собирается системным «cc» против lib/libcompiler_flang.a и
запускается. Нет «cc» — оболочка не выключается, а проверяет разбор, типы и
завершаемость и говорит об этом при запуске.
Где искать: FLANG_CC, FLANG_INCLUDE_DIR, FLANG_LIB_DIR.
flang lsp --help
$ flang lsp --help
flang lsp [--stdio]
Языковой сервер flang по стандартному вводу-выводу: рамки Content-Length, тело
JSON, как требует спецификация LSP. Запускается редактором, а не человеком —
вручную он будет молча ждать сообщений.
Умеет то же, что «flang-lsp» из инструментария на Node, и ТЕМ ЖЕ СЛОЕМ
(«flang/self/lsp.flang»): диагностику той же дорогой, что «flang check» —
разбор, связывание, типы, завершаемость, — дополнение, наведение с подписью и
переход к объявлению.
Расхождение со свидетелем одно, и оно названо: у программы с «использует» беда
импортированного модуля уходит в журнал редактора, а не подчёркивается в его
буфере. «Место» (self/types.flang) поля файла не имеет, поэтому файл беды
называется тогда и только тогда, когда исходник один.
Печатать в stdout что-либо, кроме сообщений протокола, нельзя: редактор читает
оттуда рамки. Всё человеческое уходит в stderr.
Переменные окружения
| Переменная | Что задаёт |
|---|---|
FLANG_RUNTIME_DIR | где emit ищет исходники рантайма цели, если не задан --runtime |
FLANG_CC | какой компилятор C зовёт repl |
FLANG_INCLUDE_DIR, FLANG_LIB_DIR | где repl ищет заголовки и библиотеку |
FLANG_UNPROVEN | что run и io делают с недоказанными программами: refuse, warn, allow |
FLANG_RECURSION_LIMIT — не переменная, а код ошибки: кончился предел шагов или глубины.
Дальше
- Справочник отказов — каждый код
FLANG_…и как его чинить. - Справочник конструкций — что писать в самом файле.
- Как писать пакеты — что делать с выводом
lockиpackage.