blaise/README.adoc

264 lines
17 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

ПРОГРАММА Привет;
НАЧАЛО
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].
---