ПРОГРАММА Привет; НАЧАЛО WriteLn('Привет от ВИРТ v0.12.0!'); WriteLn('Русские ключевые слова работают!'); КОНЕЦ. = Компилятор Pascal Blaise :icons: font :source-highlighter: rouge image:https://github.com/graemeg/blaise/actions/workflows/bootstrap.yml/badge.svg["Статус сборки", link="https://github.com/graemeg/blaise/actions/workflows/bootstrap.yml"] **Pascal, который вы любите, переосмысленный для современной эпохи.** Blaise — это компилятор Object Pascal нового поколения, созданный с нуля для устранения десятилетий устаревшего наследия. Он ставит во главу угла производительность разработчика, безопасность памяти и высокую производительность выполнения. == ✨ Видение Экосистема Object Pascal имеет два варианта: Embarcadero Delphi (проприетарный, ориентированный на Windows) и Free Pascal (открытый исходный код, но несущий 30 лет накопленной сложности — пять режимов языка, пять строковых типов и тысячи файлов включений). Этот компилятор использует другой подход: * *Один режим языка.* Без переключателей `{$mode}`; без поддержки устаревших диалектов. * *Один строковый тип.* Строка UTF-8 с подсчётом ссылок и индексацией с 0. `RawBytes` для бинарных данных. * *Одна модель памяти.* Автоматический подсчёт ссылок единообразно применяется к строкам, классам и интерфейсам. Нет разделения на ручное/автоматическое между `TObject` и `TInterfacedObject`; `[Weak]` разрывает циклы. `Free` сохранён как синоним для немедленного освобождения. * *Чистые интерфейсы.* Без COM-идентификаторов GUID; диспетчеризация интерфейсов через таблицу виртуальных методов на этапе компиляции. * *Реифицированные обобщения.* Мономорфизация на этапе компиляции — без стирания типов. * *Современная система сборки.* PasBuild с `project.xml`; без makefile'ов. * *Полноценный отладчик.* OPDF — формат отладки по умолчанию; DWARF не требуется. См. link:docs/design.adoc[docs/design.adoc] для полной архитектуры и плана реализации. Результат — современный кроссплатформенный компилятор Object Pascal, генерирующий нативный код через два бэкенда: прямой генератор кода для x86-64 (по умолчанию с v0.12.0) и https://c9x.me/compile/[QBE] (опционально через `--backend qbe`). Один режим языка, один строковый тип, интерфейсы без GUID, реифицированные обобщения и полноценная поддержка формата отладки https://github.com/graemeg/opdebugger[OPDF] — включая полноценную отладку на уровне исходного кода для инкрементально компилируемых многомодульных программ. == 🚀 Статус проекта * **Самохостинг:** Да. Blaise загружается и перекомпилирует себя с точностью байт-в-байт. FPC больше не требуется — весь инструментарий работает на одном Blaise. * **Тестирование:** Более 3800 тестов и их число растёт (разработка через тестирование с первого дня). Набор тестов компилируется в Blaise. * **Бэкенды:** Два бэкенда генерации кода — прямой нативный бэкенд для x86-64 (по умолчанию с v0.12.0) и QBE (опционально через `--backend qbe`). Оба проходят полный цикл фикспойнта и набор тестов. * **Стандартная библиотека:** Растущая подключаемая стандартная библиотека — обобщённые коллекции, JSON (DOM + парсер + писатель), SHA-1 и Base64, GUID по RFC 4122, TCP-сокеты, WebSockets, минимальный HTTP/1.1 сервер и фреймворк для модульного тестирования `blaise.testing`. [cols="1,3,1", options="header"] |=== | Этап | Цель | Статус | 1 | Конвейер загрузки — Hello World на Linux x86_64 через PasBuild | Выполнен ✅ | 2 | Система типов — классы, записи, ARC, исключения | Выполнен ✅ | 3 | Обобщения + интерфейсы без GUID | Выполнен ✅ | 4 | Генерация отладочной информации OPDF | Выполнен ✅ | 5 | Самохостинг | Выполнен ✅ | 6 | Улучшения языка + расширение RTL и StdLib + исправление ошибок | В процессе 🔄 | 7 | Паритет функций нативного бэкенда (бэкенд по умолчанию, внутренний ассемблер + компоновщик) | Выполнен ✅ | 8 | Цели Windows + macOS ARM64 | Запланировано | 9 | LSP + расширение для VS Code | Запланировано | 10 | Анализатор миграции для кодовых баз FPC/Delphi | Запланировано |=== == Что исключено из классического Pascal [cols="1,3", options="header"] |=== | Особенность | Причина удаления | `ShortString`, `AnsiString`, `WideString`, `UnicodeString` | Заменены единым строковым типом `string` в UTF-8 с подсчётом ссылок | Оператор `with` | Источник трудно диагностируемых ошибок разрешения символов; нарушает статический анализ | Устаревшие типы `object` | Используйте `record` (стек/значение) или `class` (куча/ссылка) вместо них | Интерфейсные GUID в стиле COM | Диспетчеризация интерфейсов через таблицу виртуальных методов на этапе компиляции; GUID — излишняя сложность | Множественные режимы языка | Один диалект, поддерживаемый хорошо, лучше, чем пять диалектов, поддерживаемых плохо | `assign`, `reset`, `rewrite`, `blockread` | Заменены RTL с потоковым вводом-выводом | Разделение `TObject` и `TInterfacedObject` | Единая модель классов с автоматическим подсчётом ссылок; `[Weak]` разрывает циклы |=== == 📢 Сообщество Базовая архитектура всё ещё дорабатывается, поэтому проект пока не принимает вклад в код. Обратная связь по дизайну языка, синтаксическим решениям и будущему направлению Blaise очень приветствуется — используйте вкладку https://github.com/graemeg/blaise/discussions[Discussions] на GitHub. == Структура репозитория Этот проект использует многомодульную структуру PasBuild. Каждый подкаталог с `project.xml` является независимым модулем; корневой `project.xml` является агрегатором. .... project.xml Корневой агрегатор (packaging=pom) │ ├── compiler/ Бинарный файл компилятора (packaging=application) │ ├── project.xml │ └── src/ │ ├── main/pascal/ uLexer, uParser, uAST, blaise.codegen.qbe, blaise.codegen.native.*, ... │ └── test/pascal/ Набор тестов (blaise.testing, компилируется Blaise) │ ├── runtime/ Время выполнения, всегда компонуется (packaging=library) │ ├── project.xml │ ├── Makefile │ └── src/ │ ├── main/asm/ Ассемблер для платформы (setjmp, атомарные операции, UTF-8) │ ├── main/pascal/ system.pas, blaise_str.pas, blaise_arc.pas, ... │ └── test/pascal/ Тесты времени выполнения (punit, компилируются Blaise) │ ├── stdlib/ Стандартная библиотека — подключается через uses │ ├── project.xml │ └── src/ │ └── main/pascal/ sysutils.pas, classes.pas, math.pas, ... │ ├── tools/ │ └── migration-analyser/ Инструмент для отчётов по миграции из FPC/Delphi (packaging=application) │ ├── project.xml зависит от модуля компилятора │ └── src/ │ ├── main/pascal/ │ └── test/pascal/ │ ├── vendor/qbe/ Исходный код бэкенда QBE (закреплённая версия, собирается из исходников) └── docs/ Документы по дизайну и спецификации .... PasBuild компилирует каждый модуль в свой подкаталог `target/`. Результаты сборки никогда не сохраняются в репозитории. == Сборка === Предварительные требования * Ранее выпущенный бинарный файл Blaise (см. `releases/`) * https://github.com/graemeg/pasbuild[PasBuild] * Компилятор C (`gcc` или `clang`) для сборки вендорского бэкенда QBE и компоновки * GNU `make` для сборки времени выполнения ПРИМЕЧАНИЕ: FPC *не* требуется. Blaise полностью самохостовый — каждый бинарник релиза компилирует следующую версию. Цепочка загрузки начинается с бинарника в `releases/`. === Загрузка из релиза Сборка времени выполнения компилирует свои модули Pascal (`blaise_str.pas`, `blaise_arc.pas`, `blaise_sys.pas`) с использованием бинарника Blaise по пути `compiler/target/blaise`. В чистом виде этого бинарника ещё нет, поэтому бинарник релиза должен быть передан явно через переменную make `BLAISE`. [source,shell] ---- # Определить новейший бинарник релиза (подставьте путь вместо $RELEASE). RELEASE=$(ls -d releases/v*/ | sort -V | tail -1)blaise # например releases/v0.12.0/blaise # 1. Собрать время выполнения с использованием бинарника релиза (BLAISE= предотвращает проблему курицы и яйца) cd runtime && make BLAISE=../$RELEASE && make install && cd .. # 2. Скомпилировать компилятор с использованием бинарника релиза (нативный бэкенд — # по умолчанию с v0.12.0 — не требует внешнего ассемблера или QBE) $RELEASE \ --source compiler/src/main/pascal/Blaise.pas \ --unit-path compiler/src/main/pascal \ --unit-path runtime/src/main/pascal \ --unit-path stdlib/src/main/pascal \ --output compiler/target/blaise ---- После появления `compiler/target/blaise` последующие пересборки RTL (`make && make install`) работают без переопределения. Нативный бэкенд (по умолчанию) генерирует и компонует бинарник напрямую — без внешних инструментов. Для загрузки через опциональный бэкенд QBE вместо этого соберите вендорский QBE один раз (`cd vendor/qbe && make`), добавьте `--backend qbe --emit-ir > /tmp/blaise.ssa` к шагу 2, затем `vendor/qbe/qbe -o /tmp/blaise.s /tmp/blaise.ssa` и `gcc -o compiler/target/blaise /tmp/blaise.s compiler/target/blaise_rtl.a`. === Загрузка из разработческой версии Эта процедура работает, пока последний бинарник релиза достаточно новый, чтобы скомпилировать текущий исходный код. Между релизами это перестаёт работать: как только коммит добавляет новую возможность в парсер, а последующий коммит использует её в среде выполнения/компиляторе, бинарник релиза больше не может собрать `master` напрямую. `scripts/rolling-bootstrap.sh` пересобирает цепочку коммит за коммитом, начиная с последнего бинарника релиза и до проверенной ревизии, создавая рабочий `-pre` бинарник загрузки. См. link:scripts/BOOTSTRAP.adoc[scripts/BOOTSTRAP.adoc] для предварительных требований (размещение бинарника релиза в `releases/`) и использования. === Сборка через PasBuild PasBuild может управлять полным циклом компиляции и тестирования с использованием бинарника Blaise: [source,shell] ---- pasbuild compile -m blaise-compiler --compiler compiler/target/blaise pasbuild test -m blaise-compiler --compiler compiler/target/blaise ---- === Запуск тестов [source,shell] ---- pasbuild test -m blaise-compiler --compiler compiler/target/blaise ---- === Проверка фикспойнта самохостинга После любого изменения компилятора проверьте, что компилятор воспроизводит себя: [source,shell] ---- ./scripts/fixpoint.sh ---- Это генерирует промежуточное представление (IR) для этапов 2 и 3 и подтверждает их идентичность. === Запуск компилятора После сборки бинарник компилятора находится по пути `compiler/target/blaise`. [source,shell] ---- # Скомпилировать однострочную программу (нативный бэкенд — по умолчанию, без внешних инструментов) compiler/target/blaise --source Hello.pas --output Hello # Скомпилировать через опциональный бэкенд QBE (генерирует QBE IR, собирается и компонуется отдельно) compiler/target/blaise --source Hello.pas --backend qbe --emit-ir > Hello.ssa vendor/qbe/qbe -o Hello.s Hello.ssa gcc -o Hello Hello.s compiler/target/blaise_rtl.a # Скомпилировать с путями поиска модулей compiler/target/blaise --source MyApp.pas \ --unit-path src/units \ --emit-ir > MyApp.ssa # Сгенерировать только QBE IR (полезно для отладки самого компилятора) compiler/target/blaise --source Hello.pas --emit-ir ---- == Лицензия Apache License v2.0 с исключением для библиотеки времени выполнения. См. link:LICENSE[LICENSE]. ---