flang язык, в котором спецификация исполняется

К README · Указатель документации

Две реализации и неподвижная точка

Реализации две, и обе поддерживаются намеренно. Эталонная написана на TypeScript и JavaScript и служит определением поведения языка. Самоприменяющаяся написана на самом flang.

Ядро FTS, написанное на flang

[flang/core/](../../flang/core) — это ядро FTS (лексер, парсер, вычислитель, печать JSON), переписанное на flang: 300 функций, каждая помечена тотальная и доказана. fts check тоже не имеет права зависнуть.

Критерий правильности здесь не «свои тесты проходят». Он дифференциальный и записан в [flang/core/SPEC.md](../../flang/core/SPEC.md): прогнать всю цепочку — текст → лексер на flang → парсер на flang → печать JSON на flang — и потребовать, чтобы выданная строка побайтово совпала с JSON.stringify(compile(текст)) ядра на TypeScript. Прогон идёт по каждой модели .fts репозитория — на чистом клоне их 50, на обеих поверхностях (47 отступных и 3 скобочных) — с нулём расхождений. Если на машине есть внешний каталог моделей, его модели попадают в тот же прогон, и число у вас окажется больше; обещание касается корпуса, а не числа. Диагностики сверяются отдельно — на 34 намеренно сломанных отступных моделях и 13 скобочных, причём и код, и текст сообщения.

Компилятор, написанный на flang, и неподвижная точка

[flang/self/](../../flang/self) — это компилятор flang, написанный на flang. Пять слоёв, и у каждого свой эталон на JavaScript, с которым он сверяется точно — не «в целом так же», а до последней составляющей результата:

СлойФункцийЭталонЧто обязано совпасть
self/lexer.flang88src/lexer.mjsпоток токенов: вид, значение, закавыченность, строка и столбец
self/parser.flang372src/parser.mjsAST — побайтово после сериализации
self/types.flang276src/types.mjsдиагностики (код, текст, строка и столбец) и таблица сигнатур
self/totality.flang124src/totality.mjsвердикт: список доказанных функций в том же порядке, диагностики, признак ok
self/emit-c.flang328src/emit/c.mjsнапечатанный C — побайтово, и он собирается без предупреждений

Готовность определяется не тем, что «собралось», а классической неподвижной точкой:

1. компилятор на JS печатает self/*.flang   → C → сборка → flang₁
2. flang₁ печатает те же self/*.flang       → C → сборка → flang₂
3. C, напечатанный flang₁, и C, напечатанный flang₂, совпадают побайтово

Неподвижная точка сошлась. Эталон, flang₁ и flang₂ печатают компилятор одинаково — все семь напечатанных файлов C, — то есть компилятор понимает язык так же, как эталон, и никакой набор тестов этого не заменяет. Проверка — flang/test/self-bootstrap.test.mjs, и она печатает результат:

✔ шаги 2 и 3: flang₁ печатает сам себя, flang₂ печатает то же самое
ℹ неподвижная точка сошлась: 7 файлов совпали побайтово у эталона, flang₁ и flang₂

Именно отсюда берётся релиз: C в релизном архиве напечатан из этих исходников. Эталонную реализацию при этом не удаляют и не удалят — относительно неё и проверяется схождение, а её удаление сделало бы проверку невозможной.