Истоки
Несколько лет назад я написал компилятор Паскаля. Мотивация была простой: в юности я узнал из своих первых книжек по программированию, что компилятор — вещь чрезвычайно сложная. Это утверждение засело занозой в мозгу и в конце концов потребовало проверки на опыте.
ha.art.pl
Сперва родился простейший компилятор PL/0, а из него постепенно вырос почти полнофункциональный компилятор Паскаля для MS-DOS. Вдохновением мне служила книга Compiler Construction, написанная создателем языка Паскаль Никлаусом Виртом. И пусть взгляды Вирта уже устарели и утратили всякую связь с реалиями ИТ, а компиляторы делают совсем не так, как учил Вирт. Однако его методы по-прежнему просты, изящны, а главное — приносят радость, ведь самостоятельно разобрать текст программы рекурсивным спуском и сгенерировать машинный код намного заманчивее, чем призывать на помощь яков, бизонов и всех их преемников.
Судьба моего компилятора оказалась не самой тривиальной. Он прожил две жизни: первую — в моих руках, вторую — в руках польских ценителей компьютерных древностей.
XD Pascal
Мой свежеиспечённый компилятор получил название XD Pascal. Он поддерживал все операторы Паскаля, кроме goto
и with
. Первый показался мне трудным для реализации, поскольку разрушал идеально иерархичную структуру программы. Второй — создавал путаницу с областями видимости имён.
Поддерживались и все основные типы данных. За рамками остались только беззнаковые целые числа, множества, перечисления и вариантные записи — однако всё это явно не предметы первой необходимости. Тем не менее, я не мог отказать себе в удовольствии от чисел с плавающей точкой и их арифметики на сопроцессоре 8087 — тут сказалась профессиональная склонность к инженерным расчётам.
При реализации процедур и функций я опасался, что большой проблемой окажутся рекурсия и хранение локальных переменных в стеке. Однако настоящая трудность, специфичная для Паскаля, подстерегала совсем в другом месте — в работе с вложенными процедурами. Может возникнуть совершенно невинная надобность обратиться к локальной переменной внешней процедуры из внутренней. Однако во внутренней процедуре нет адреса стекового кадра внешней процедуры — внутренняя процедура не знает, от чего отсчитывать адрес искомой переменной. Этот адрес приходится всякий раз передавать во внутреннюю процедуру через дополнительный скрытый параметр. Подозреваю, что именно это осложнение заставило разработчиков C вовсе отказаться от вложения функций. Однако в Паскале они есть, и с этим приходится считаться.
Генератор кода создавал самые простые исполняемые файлы COM для реального режима MS-DOS. Машинный код генерировался напрямую, без помощи внешнего ассемблера или компоновщика. Для данных я использовал 32-битные регистры архитектуры 80386, а адресация осталась 16-битной, в виде пары сегмент-смещение.
Модель памяти примерно соответствовала «малой» (если кто-то ещё помнит эту терминологию 16-битной эпохи): для кода, глобальных данных и стека выделялось по одному сегменту размером 64 кб.
Использование памяти
Генерация файлов EXE и переключение сегментов на лету казались чересчур сложным делом, и тесные рамки «малой» модели заставили меня распрощаться с идеей самокомпиляции. Конечно, мне встречались самокомпилируемые компиляторы, код которых целиком умещался в одном сегменте (например, Context). Однако они редко умели делать хоть что-то полезное кроме этой самокомпиляции. Я же хотел сделать свой компилятор хоть немного пригодным для численных расчётов и вывода графики. Поэтому среди примеров программ появились фракталы, решение линейных уравнений по Гауссу, быстрое преобразование Фурье и даже оценивание фильтром Калмана ошибок инерциальной навигационной системы.
Фрагмент множества Мандельброта
Быстрое преобразование Фурье
Оценивание погрешностей инерциальной навигационной системы
То, что у меня получилось в итоге, больше всего напоминало древний как мир Turbo Pascal 3.0 (ещё без ООП) и любительский BeRo Tiny Pascal. Автор последнего совладал с самокомпиляцией под Windows, однако пожертвовал арифметикой с плавающей точкой и многими тонкостями грамматики, которые мне хотелось соблюсти. Из более современных особенностей в моём XD Pascal появились позаимствованные из Delphi однострочные комментарии (//
) и автопеременная Result
.
Впрочем, ещё с самого своего рождения мой компилятор был отмечен печатью смерти. Паскаль уже необратимо выходил из моды, а MS-DOS давно стал архаикой. В тот день, когда я перешёл с 32-битной Windows XP на 64-битную Windows 7 без виртуальной машины DOS, я мысленно похоронил свой проект.
Возрождение
Затем произошло странное. После трёх лет полного забвения некая группа польских энтузиастов ретрокомпьютинга и любителей Atari отыскала мой компилятор. Судя по всему, абстрактные проблемы самокомпилируемости и строгости реализации грамматики их волновали мало. Им просто нужен был удобный инструмент программирования их любимой машины. Из моего проекта они сделали собственный компилятор Mad Pascal для архитектуры 6502. Грамматика языка разрослась, появилась поддержка модулей с секциями интерфейса и реализации, оператора goto
, беззнаковых целых чисел, множеств и перечислений, ассемблерных вставок. Вместо машинного кода теперь генерировался ассемблерный код. Его финальная трансляция делалась ассемблером собственной разработки.
Внешне язык стал заметно ближе к фактическому стандарту Паскаля. Внутри компилятор выглядит несколько устрашающе, зарезервированные слова перемешаны с именами стандартных процедур, однако это авторов нисколько не смущает. Как бы оно ни выглядело, но дело оказалось на удивление живучим: вот уже три года Mad Pascal регулярно обновляется, на нём написано немало игр, авторы ежегодно выступают на ретроконференции Silly Venture (ссылка требует VPN). Возникает ощущение, что в Польше вообще очень сильны традиции почитания Atari.
Весной 2018 года произошло событие, весьма примечательное для польской тусовки поклонников Atari: вышла книга «Robbo. Solucja» («Роббо. Прохождение») в жанре экспериментальной литературы. Здесь надо сказать, что сама игра Robbo для Atari, изданная 30 лет назад, до сих пор волнует сердца поляков старшего поколения и наполняет их патриотическим восторгом. В общем, неудивительно, что появилась посвящённая игре книжка. Забавно лишь то, что она, по словам авторов, на 60 % состоит из инструкций по прохождению игры, сгенерированных самим компьютером Atari. Программа генерации написана на том самом Mad Pascal.
graczpospolita.pl
И кажется, некоторые восприняли книгу как достойный образец современного искусства:
Было бы неверно относиться к книге только как к предмету коллекционирования для поклонников Robbo или, в более общем смысле, для поклонников Atari. Нам приходится иметь дело с редким случаем столкновения культуры видеоигр с литературой (в данном случае электронной), когда отправной точкой является «игра», а не «литература». Для некоторых это бессмысленное искусство ради искусства. Для других подобное скрещивание несёт совершенно новые возможности и опыт. Ничто не мешает вам создать версию Robbo, которую вы можете закончить с помощью «прохождения» из книги. Книга хорошо согласуется с моим взглядом на игры как на искусство. Искусство, в котором игрок может быть как воспринимающим, так и творящим — если во время «игры» присутствует «аудитория», наблюдающая за игроком, создающим свою собственную историю «игры». Содержание книги можно адаптировать для перформанса с игроком, проходящим Robbo, используя элементы «пошаговых инструкций» из книги. Чтобы не оставаться голословным: перформанс по мотивам «Robbo. Solucja» состоялся 11 мая 2018 года в галерее современного искусства «Бункер» в Кракове, во время презентации книги в рамках выставки «Неисчерпаемость».
Перформанс в Кракове. Ради этого стоило написать компилятор.
Источник