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