Почему самодостаточные компиляторы считаются обрядом для новых языков?


30

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

Мне любопытно, почему это так. Компилятор кажется очень важной частью программного обеспечения для написания, и я думаю, что не все языки хорошо подходят для их создания. Разве не имеет смысла тратить усилия на то, чтобы добиться лучших результатов?


17
«Компилятор кажется очень важной частью программного обеспечения для написания, и я полагаю, что не все языки хорошо подходят для их создания». Я бы посчитал это очень веской причиной для написания компилятора на новом языке, а именно доказать, что язык соответствует задаче.
Джорджио

13
Если это не язык специального назначения, язык, на котором не очень удобно писать компилятор, вероятно, тоже не подходит для того, что я хочу делать.
CodesInChaos

3
AFAIK, это не всегда верно для Фортрана. Несколько компиляторов Фортрана (например, gfortranиз GCC ...) не кодируются на Фортране.
Василий Старынкевич

Ответы:


29

Разве не имеет смысла тратить усилия на то, чтобы добиться лучших результатов?

Как что?

Приятной особенностью компиляторов является то, что они не имеют много зависимостей. Это делает их хорошими кандидатами на новый язык, который, вероятно, еще не имеет очень большой или разнообразной стандартной библиотеки.

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

И хотя компиляторы кажутся огромной работой, они довольно малы по большому счету. Если разработчики языка не могут даже сделать что-то, что они делали раньше на новом языке, как они собираются делать новые вещи? Как они будут обрабатывать такие большие вещи, как стандартные библиотеки или IDE?


В качестве дополнительного примечания, я хотел бы отметить, что, несмотря на то, что это хорошо, есть множество причин, по которым компилятор может быть написан на другом языке. Например, большинство javascript-движков не написаны на javascript. Для этого есть много причин: интеграция с другим программным обеспечением, привязка к существующим библиотекам / зависимостям, превосходные инструменты, производительность, унаследованный код ... Иногда самокомпиляция языка хороша, но все же имеет смысл поддерживать основной компилятор в другой. Тем не менее, сам по себе язык имеет смысл. Просто вы обычно не можете позволить себе перестроить всю экосистему.
Дагналии

2
@arnaud И тот факт, что компилятору Javascript потребуется среда Javascript, которая не может быть написана на Javascript, потому что Javascript требует среды Javascript, <повторите парадоксально> , потому что среда Javascript не предоставляется операционной системой (и если было, это не будет написано в Javascript).
Qix

3
@Qix en.wikipedia.org/wiki/Bootstrapping_%28compilers%29 Но в основном нет причин использовать его. Он широко известен как плохой язык, браузеры не используют его для компиляции, потому что они контролируют ситуацию :), в то время как у остальных из нас нет выбора в Интернете.
Ден

3
Я не уверен в претензии «не имейте много зависимостей». Это может быть правдой для внешнего интерфейса компилятора . Но как только у вас есть AST, запуск собственного оптимизатора и генератора кода не выглядит многообещающим маршрутом. Помимо того факта, что современные методы оптимизации требуют сложных формальных логических движков, для которых может потребоваться использовать стороннюю библиотеку, нет причин заново изобретать колесо для каждого нового языка вместо того, чтобы опираться на прочную отраслевую основу, такую ​​как GCC или LLVM.
5gon12eder

30

Цель иметь компилятор на языке, который компилируется, часто является частью практики « есть свою собачью еду ». Он демонстрирует миру, что вы считаете язык, компилятор и экосистему поддерживающих модулей и инструментов «достаточно хорошими для серьезной работы» или «готовыми к производству».

Он также имеет действенный эффект, заставляя тех, кто ближе к языку, компилятору и дизайну среды выполнения, непосредственно сталкиваться с последствиями всех решений, которые они приняли, и выбранных ими приоритетов развития - бородавок и всего остального. Это часто приводит к созданию основной группы, которая не только понимает языковую среду в теории, но и имеет большой практический опыт использования языка / инструментов в суровых суровых условиях реального слова.


1
для полноты: съесть свою собачью еду ; см. кормление собак (прил.) или кормление собак (глагол)
Qix

17

Люди создают новые языки общего назначения по одной основной причине: они ненавидят по крайней мере одну вещь о любом другом языке. Вот почему так много языков не отрываются от земли. У вас есть отличная идея для языка, который улучшит вашу жизнь в программировании, но вы должны сделать первую реализацию на языке, который раздражает вас хотя бы одним способом. Самостоятельный хостинг означает, что вам больше не нужно работать на этом старом надоедливом языке. Вот почему создатели языка работают над этим шагом и рассматривают его как важную веху.

Многие языковые функции хорошо выглядят на бумаге, но когда вы начинаете использовать их в реальном проекте, вы начинаете видеть их ограничения. Например, сначала многие языки не имеют приличной поддержки юникода. Завершение большого проекта помогает гарантировать, что с подобными ситуациями сталкивались и с ними справлялись, а компилятор с собственным хостингом - такой же хороший проект, как и любой другой. Вот почему люди, отличные от создателей языка, считают это важной вехой.

Это не значит, что это единственная веха, на которую стоит обратить внимание. Есть функции, которые не выполняются компилятором, такие как интеграция базы данных, графические интерфейсы, работа в сети и т. Д.


Я чувствую, что (родной) язык - это язык, когда он может компилироваться и ядро linux может быть перенесено на него (так как оно охватывает большинство / все задачи, необходимые для работы большинства современных ОС).
Qix

Тем не менее, для написания компилятора не требуется приличная поддержка Unicode.
Паŭло Эберманн

11

Стив Йегге написал отличный пост в блоге, который несколько косвенно касается этого.

Важный момент # 1: компиляторы охватывают практически все аспекты информатики. Это курс высшего уровня, потому что вам нужно знать все, что вы изучаете в учебной программе по информатике, чтобы начать. Структуры данных, поиск и сортировка, асимптотическая производительность, раскраска графа? Это все там.

Есть причина, по которой Кнут работал над своим монументальным (и бесконечным) «Искусством компьютерного программирования» в течение нескольких десятилетий, хотя он начинал как (просто) учебник по компиляции. Точно так же, как Карл Саган сказал: «Если вы хотите сделать яблочный пирог с нуля, вы должны сначала изобрести вселенную», если вы хотите написать компилятор, вы должны сначала разобраться почти со всеми аспектами информатики.

Это означает, что если компилятор размещается самостоятельно, то он вполне может делать то, что мне нужно, независимо от того, что я делаю. И наоборот, если вы не написали компилятор на своем языке, есть большая вероятность, что он упустит что-то, что действительно важно для кого-то, потому что разработчикам языка никогда не приходилось писать программу, которая заставляла бы их думать обо всех этих проблемах.

Важный момент № 2: с высоты 30 000 футов удивительное количество проблем выглядит как компиляторы.

Компиляторы берут поток символов, выясняют их структуру в соответствии с некоторыми предварительно определенными правилами для конкретного домена и преобразуют их в другой поток символов. Звучит довольно широко, не так ли? Ну, да.

Независимо от того, работаете ли вы в команде Visual C ++ или нет, вам очень часто придется делать что-то, что выглядит как часть компилятора. Я делаю это буквально каждый день.

В отличие от большинства других профессий, программисты не просто используют инструменты, но создают свои собственные инструменты. Программист, который не может (из-за нехватки навыков или из-за отсутствия полезных инструментов для создания других инструментов) писать инструменты, навсегда останется инвалидом, ограниченным инструментами, которые кто-то другой предоставляет.

Если язык «не подходит для создания» программ, которые могут принимать поток символов, применять к ним правила и преобразовывать его в другой поток символов, это звучит как довольно ограниченный язык, а не тот, который был бы полезен мне.

(К счастью, я не думаю, что есть много языков программирования, которые плохо подходят для преобразования символов. C, вероятно, является одним из худших таких языков, используемых в настоящее время, однако компиляторы C, как правило, размещаются самостоятельно, поэтому никогда никого не останавливали.)

Третья причина, на которой я закончу, на личном опыте, не упомянутой Йегге (потому что он не писал о том, «почему сам хозяин»): это избавляет от ошибок. Когда вы пишете компилятор, что означает , что каждый раз , когда вы построить его (не только каждый раз , когда вы запустите его), вы зависите от него , чтобы работать, и работать правильно с приличного размером кодового (сам компилятором).

В этом месяце я использую относительно новый и известный компилятор, не являющийся хостом (вы, вероятно, можете догадаться, какой именно), и я не смогу пройти 2 дня, не запустив эту проблему. Интересно, сколько дизайнеры действительно должны были использовать это.


8

Если вы хотите, чтобы компилятор для языка X был автономным, вы сначала должны реализовать его на каком-то другом языке, скажем Y, так, чтобы он принимал ввод для языка X и выплевывал ассемблерный код, или некоторый промежуточный код, или даже код объекта для машины, на которой работает компилятор. Вы хотите, чтобы язык Y был максимально похож на язык X, поскольку в какой-то момент вы будете переводить код, написанный на Y, в X.

Но вы не хотите писать компилятор на языке Y больше, чем необходимо, поэтому для начала вы реализуете только подмножество языка - исключая избыточные конструкции. В случае языка типа «С», в то время как , но не для или делать во время . если, но без дела или трет. Нет структур или союзов или перечислений. И т. Д. То, что у вас осталось, - это достаточно языка для написания синтаксического анализатора и генератора элементарного кода для языка X. Затем проверьте вывод. Опять таки.

После того, как у вас это получится, вы можете переписать исходный код компилятора, который был написан на языке Y, на язык X и скомпилировать исходный код языка X, используя компилятор, написанный на языке Y. В результате будет получен новый компилятор, написанный на новом языке X, который компилирует язык X, т. е. теперь он является хостингом. Однако это не является полным, так как вы реализовали только подмножество языка на языке Y.

Итак, теперь вы добавляете недостающие функции, проверяя каждую (или группу функций), чтобы они генерировали правильный код. то есть, как только функция реализована в компиляторе, вы можете писать тестовые программы, используя новые функции, компилировать и тестировать их, но вам пока не следует использовать их в исходном коде компилятора. После проверки новых возможностей вы можете использовать эти новые функции в самом исходном коде компилятора - возможно, заменив часть исходного кода, написанного в подмножестве языка - перекомпилировать исходный код компилятора, используя версию с новыми функциями.

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

Примерно 60 лет назад, когда компьютеры впервые появились на сцене (а позже, когда появились микропроцессоры), не было других языков Y, подходящих для реализации исходного компилятора. Таким образом, первые компиляторы должны были быть написаны в ассемблерном коде, а затем, когда было запущено достаточное количество компилятора, ассемблерный код будет заменен версией, написанной на новом языке. Также нет ассемблера? Весь процессор опустился на другой уровень, причем ассемблер изначально записывался в машинном коде .


2

Можно ли создать язык программирования, который не очень хорошо разработан для написания компилятора, но хорошо разработан для какой-то другой цели?

Глядя на такой язык, как SQL, я полагаю, что ответ - да. Но языки такого рода не имеют общего назначения.


1
Претензия принята: написать компилятор C на SQL.
Qix

2

Кто так говорит? ... в любом случае, это просто мнение. Кто-то может согласиться, кто-то нет, здесь нет правильного или неправильного. В некоторых языках компиляторы написаны сами по себе, в других нет. Без разницы.

Тем не менее, я думаю, что это хорошее упражнение / доказательство концепции, если язык способен «самокомпилироваться» ... это просто ... хорошо ... и это доказывает, что язык подходит для выполнения каких-то сложных вещей.

Я также хотел бы отметить, что, несмотря на то, что это хорошо, есть множество причин, по которым компилятор может быть написан на другом языке. Например, большинство javascript-движков не написаны на javascript. Для этого есть много причин: интеграция с другим программным обеспечением, привязка к существующим библиотекам / зависимостям, превосходные инструменты, производительность, унаследованный код ... Иногда самокомпиляция языка хороша, но все же имеет смысл поддерживать основной компилятор в другой. Тем не менее, сам по себе язык имеет смысл. Просто вы обычно не можете позволить себе перестроить всю экосистему.


2

Clang написан на C ++. Было бы не сложно переписать компилятор Clang Objective-C в Objective-C, но тогда это было бы совершенно бесполезно. Любое изменение в компиляторе C ++ должно быть переделано в Objective-C и наоборот. Так почему же?

Теперь есть компилятор Clang Swift. Конечно, этот компилятор может быть переписан в Swift. Но какова будет цель? Чтобы продемонстрировать, что язык достаточно мощный, чтобы написать в нем компилятор? Никого не волнует, можете ли вы писать компиляторы на Swift. Людям все равно, можете ли вы писать пользовательские интерфейсы в Swift, а вы, очевидно, можете.

Если у вас есть хорошо протестированный компилятор, который можно легко адаптировать для компиляции разных языков, бессмысленно переписывать его на разные языки, если только переписывание на одном другом языке не облегчит работу с компилятором. И если было бы целесообразно, например, написать Clang на Swift, то компиляторы Clang C, C ++ и Objective-C все были бы написаны на Swift.

Есть более важные вещи, чем доказать, что вы можете написать компилятор на каком-то языке программирования.


1

Это показывает, что язык способен обрабатывать сложную обработку строк и переводить на другой язык / интерпретировать сам.

В процессе создания компилятора (первый большой проект) возникнет проблема, которая выйдет на первый план.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.