Почему так трудно написать компилятор для Perl 6?

Перевод статьи Why is it hard to write a compiler for Perl 6? с любезного согласия Moritz Lenz

Сегодня обманчиво простой вопрос на # Perl6: на самом ли деле труднее писать компилятор для Perl 6, чем для любого другого языка программирования?

Ответ прост: да, сложнее (и больше работы), чем для многих других языков. Более актуален вопрос: почему?

Итак, давайте взглянем. Первый заключается в том организационно: Perl 6 еще не полностью изучены и формально определены; это гораздо более стабильным, чем это было раньше, но менее устойчивы, чем, скажем, ориентированных C89.

Но даже если не принимать во внимание эту точку, и нацелены на подмножество, например компилятор Rakudo Perl 6 реализует прямо сейчас, или подождать год и нацелены на первый релиз Язык Perl 6, пункт остается в силе.

Итак, давайте посмотрим на некоторые технические аспекты.

Статический против Dynamic

Perl 6 имеет как статические, так и динамические углы. Например, лексические поиски являются статическая, в том смысле, что они могут быть решены во время компиляции. Но это не опция. Для компилятора должным образом поддерживать собственные типы, он должен разрешить их во время компиляции. Мы также ожидаем, компилятор, сообщите нам о некоторых ошибок во время компиляции, так что должно быть достаточное количество статического анализа.

С другой стороны, аннотации типов не являются обязательными почти везде, и методы поздно неизбежно. Так как компилятор должен также поддерживать функции, обычно находящиеся в динамических языках.

И хотя метод звонки поздно неизбежно, составляя роли на классы компиляции время работы, с обязательным анализом времени компиляции.

Mutable грамматика

Perl 6 грамматики может изменить во время разбора, например, вновь определенных операторов, но и за счет более инвазивных операций, таких как определение сленгов и макросы. Говоря о сленгов: Perl 6 не имеют ни одного грамматику, он переключается туда и обратно между "основной" язык, регулярные выражения, характер классы внутри регулярных выражений, цитат, и все другие диалекты вы можете думать.

Так как данные расширения грамматики сделано с, ну, Perl 6 грамматики, она заставляет парсер может взаимодействовать с Perl 6 регулярных выражений и грамматик. В этот момент вы, возможно, точно также использовать их для разбора все это, и вы получите определенный уровень минимально необходимого самодостаточным.

Программирование Meta-Object

В языке, как C ++, поведение системы объекта жестко закодированы в языке, и так компилятор может работать при таком предположении и оптимизации черт из нее.

В Perl 6, система объект определяется другими объектами и классами, в мета-объектов. Так что есть еще один слой косвенной, которые должны быть обработаны.

Смешивание компиляции и время выполнения

Заявления, подобные классов, но также BEGIN блоков и правая сторона constant деклараций работать, как только они будут проанализированы. Это означает, компилятор должен иметь возможность запускать Perl 6 код при компиляции Perl 6 код. А также наоборот, через EVAL .

Что еще более важно, он должен иметь возможность запускать Perl 6 код, прежде чем он закончил составление весь модуль компиляции. Это означает, что даже не полностью построен лексические колодки, и не инициализируется все переменные. Так что необходимы специальные "статические lexpads", в которой во время компиляции обычаи переменных может упасть вернуться. Также система объект должен быть в состоянии работать с типами, которые еще полностью не заявлены.

Таким образом, участие много trickiness.

Сериализация, Repossession

Типы объекты, определенные в ходе их мета-объектов. Это означает, что когда вы предварительной компиляции модуля (или даже просто настройку, то есть массовое встроенных модулей), компилятор должен сериализовать типы и их мета-объектов. В том числе замыканий. У вас есть какие-либо идеи, как трудно правильно сериализовать закрытия?

Но, классы изменчивы. Так что другой модуль может загрузить предварительно скомпилированный модуль, и добавить еще один метод к нему, или в противном случае возиться с ним. Теперь компилятор должен сериализовать тот факт, что если второй модуль загружен, объект из первого модуля изменен. Мы говорим, что контекст сериализации из второго модуля repossesses тип.

И есть очень много способов, в которых это может пойти не так.

Генеральный Featuritis

Одна из многих Perl 6 девизов "мучить реализатор на имени пользователя". Так оно требует не только как статическая и динамическая типизация, но и функциональные особенности, продолжения, исключения, ленивые списки, мощный грамматика двигателя, названные аргументы, VARIADIC аргументы, самоанализ кадров вызовов, затворы, лексических и динамических переменных, упакованных типов (для непосредственного взаимодействия с C библиотек, например), и фазеров (код, который будет автоматически работать на различных этапах программы).

Все эти особенности не слишком сложно реализовать изолированно, а в сочетании они настоящий убийца. И вы хотите, чтобы это было быстро, не так ли?