Раскрутка компилятора: различия между версиями
[непроверенная версия] | [непроверенная версия] |
Ассемблер некорректно называть языком или компилятором. |
м Добавлено уточнение про python как самокомпилирующийся язык |
||
(не показано 9 промежуточных версий 6 участников) | |||
Строка 1: | Строка 1: | ||
{{много внутренних ссылок}} |
|||
'''Раскрутка компилятора''' ({{lang-en|bootstrapping}} — от {{lang-en2|boot}} и {{lang-en2|strap}}) — метод создания [[транслятор]]а |
'''Раскрутка компилятора''' ({{lang-en|bootstrapping}} — от {{lang-en2|boot}} и {{lang-en2|strap}}) — метод создания [[транслятор]]а для некоторого [[Язык программирования|языка программирования]], при котором транслятор пишется на том же языке программирования, для трансляции которого создаётся; создание транслятором [[Исполняемый файл|исполняемых файлов]] из [[Исходный код|исходного кода]] самого транслятора. Используется для переноса трансляторов на новые [[Архитектура компьютера|архитектуры]]. Появился в середине [[1950-е годы|1950-х годов]]. Позволяет создать транслятор, который генерирует сам себя. Применялся для создания трансляторов многих языков программирования, включая языки «[[Бейсик]]», «[[Алгол]]», «[[Си (язык программирования)|C]]», «[[Паскаль (язык программирования)|Паскаль]]», «[[ПЛ/1]]», [[Factor (язык программирования)|Factor]], [[Haskell]], «[[Модула-2]]», «[[Оберон (язык программирования)|Оберон]]», [[OCaml]], [[Common Lisp]], [[Scheme]], [[Java]], *[[Python]] (Есть разные реализации этого проекта: CPython - на "[[Си (язык программирования)|C]]" (основная реализация), Jython - на "[[Java]]", и PyPy - самокомпилирующийся), [[Scala (язык программирования)|Scala]], [[Nemerle]], [[Kotlin]] и другие. |
||
== Проблема курицы и яйца == |
== Проблема курицы и яйца == |
||
{{См. также|Проблема курицы и яйца}} |
{{См. также|Проблема курицы и яйца}} |
||
Пусть создан новый |
Пусть создан новый язык программирования L. Пусть на языке L составлен исходный код транслятора для языка L. Как получить транслятор, способный из этого кода создать исполняемый файл? |
||
Методы решения [[Проблема курицы и яйца|проблемы]] перечислены ниже |
Методы решения [[Проблема курицы и яйца|проблемы]] перечислены ниже: |
||
* Автор языка L может вручную выполнить трансляцию исходного кода с языка L на [[машинный код|машинный язык]] или на язык [[Ассемблер|ассемблера]]. Затем можно выполнить полученный код для создания [[ |
* Автор языка L может вручную выполнить трансляцию исходного кода с языка L на [[машинный код|машинный язык]] или на язык [[Ассемблер|ассемблера]]. Затем можно выполнить полученный код для создания исполняемого файла [[Компилятор|компилятора]]. Так поступили [[Вирт, Никлаус|Никлаус Вирт]] с учениками при создании первого компилятора для языка «[[Паскаль (язык программирования)|Паскаль]]», а также [[Кнут, Дональд Эрвин|Дональд Кнут]] при создании своей системы [[Грамотное программирование|грамотного программирования]] [[WEB (система программирования)|WEB]]. |
||
* Автор языка L может составить исходный код |
* Автор языка L может составить исходный код транслятора на языке, для которого уже существует транслятор. Попытку такого рода (впрочем, неудачную) предпринимал Никлаус Вирт при создании первого [[компилятор|компилятора]] для языка «Паскаль» на языке «[[Фортран]]». |
||
* То же, но автор языка L сам не составляет исходный код, а поручает эту операцию другому лицу. Такой способ часто применяется при создании трансляторов для языка [[Scheme]]. |
* То же, но автор языка L сам не составляет исходный код, а поручает эту операцию другому лицу. Такой способ часто применяется при создании трансляторов для языка [[Scheme]]. |
||
Строка 15: | Строка 16: | ||
* Первая версия компилятора может быть написана на подмножестве языка L, для которого уже существует некий другой компилятор. Таким способом были получены компиляторы для подмножества языков [[Java]], [[Haskell]] и [[Free Pascal]]. |
* Первая версия компилятора может быть написана на подмножестве языка L, для которого уже существует некий другой компилятор. Таким способом были получены компиляторы для подмножества языков [[Java]], [[Haskell]] и [[Free Pascal]]. |
||
* Создать транслятор для новой |
* Создать транслятор для новой платформы можно путём [[Кросс-компилятор|кросс-компиляции]] — создания исполняемого файла транслятора для новой платформы на платформе, для которой транслятор уже существует. Таким способом обычно [[Портирование программного обеспечения|портируются]] компиляторы, написанные на языках [[Си (язык программирования)|C]] и [[Free Pascal]]. |
||
== Раскрутка компилятора с использованием компилятора существующего языка == |
== Раскрутка компилятора с использованием компилятора существующего языка == |
||
Создание транслятора языка L методом раскрутки подразумевает выполнение некоторых шагов. |
Создание транслятора языка L методом раскрутки подразумевает выполнение некоторых шагов. |
||
# На первом шаге из языка L выделяется подмножество L<sub>0</sub>, которое не требует больших усилий для реализации, но является достаточным для написания транслятора самого себя. Затем, используя какой-либо существующий для этой |
# На первом шаге из языка L выделяется подмножество L<sub>0</sub>, которое не требует больших усилий для реализации, но является достаточным для написания транслятора самого себя. Затем, используя какой-либо существующий для этой платформы [[Язык программирования|язык]] (например, [[Си (язык программирования)|C]]), составляется исходный код транслятора для L<sub>0</sub>. |
||
# Затем на языке L<sub>0</sub> составляется транслятор для самого языка L<sub>0</sub>. Исполняемый файл транслятора создаётся с помощью транслятора, полученного на первом шаге. После этого у программиста имеется транслятор L<sub>0</sub>, способный обработать свой [[исходный код]]. |
# Затем на языке L<sub>0</sub> составляется транслятор для самого языка L<sub>0</sub>. Исполняемый файл транслятора создаётся с помощью транслятора, полученного на первом шаге. После этого у программиста имеется транслятор L<sub>0</sub>, способный обработать свой [[исходный код]]. |
||
# Далее начинается постепенное расширение L<sub>0</sub> до L: добавляется какая-либо ранее не реализованная возможность языка L, после чего предыдущей версией транслятора создаётся новая, а вновь добавленную возможность можно использовать в трансляторе для последующего расширения языка. |
# Далее начинается постепенное расширение L<sub>0</sub> до L: добавляется какая-либо ранее не реализованная возможность языка L, после чего предыдущей версией транслятора создаётся новая, а вновь добавленную возможность можно использовать в трансляторе для последующего расширения языка. |
||
Строка 29: | Строка 30: | ||
== Преимущества == |
== Преимущества == |
||
Достоинства метода раскрутки<ref>{{книга |
Достоинства метода раскрутки<ref>{{книга |
||
|автор |
|автор = Patrick D. Terry |
||
|заглавие |
|заглавие = Compilers and Compiler Generators: An Introduction With C++ |
||
|ссылка |
|ссылка = http://scifac.ru.ac.za/compilers/ |
||
|издательство |
|издательство = International Thomson Computer Press |
||
|год |
|год = 1997 |
||
|isbn |
|isbn = 1850322988 |
||
|archive-date = 2011-07-29 |
|||
|archive-url = https://web.archive.org/web/20110729041846/http://www.scifac.ru.ac.za/compilers/ |
|||
}}</ref>: |
}}</ref>: |
||
* проверка возможностей языка L; |
* проверка возможностей языка L; |
||
Строка 43: | Строка 46: | ||
== Недостатки == |
== Недостатки == |
||
При создании новых языков программирования использование уже существующих языков может быть вполне оправданным по следующим причинам<ref> |
При создании новых языков программирования использование уже существующих языков может быть вполне оправданным по следующим причинам<ref>{{Cite web |url=http://www.compiler.su/raskrutka-kompilyatora.php |title=Раскрутка компилятора |access-date=2013-03-20 |archive-date=2020-08-09 |archive-url=https://web.archive.org/web/20200809231316/http://compiler.su/raskrutka-kompilyatora.php |deadlink=no }}</ref>: |
||
* компиляторы уже существующих языков, как правило, надёжны (отлажены, изучены, стабильны); |
* компиляторы уже существующих языков, как правило, надёжны (отлажены, изучены, стабильны); |
||
* для уже существующих языков имеются [[Отладка программы|отладчики]], [[Статический анализ кода|статические анализаторы]] и другие инструменты; |
* для уже существующих языков имеются [[Отладка программы|отладчики]], [[Статический анализ кода|статические анализаторы]] и другие инструменты; |
||
Строка 85: | Строка 88: | ||
* [[Perl 6]] |
* [[Perl 6]] |
||
* «[[ПЛ/1]]» |
* «[[ПЛ/1]]» |
||
* [[Python]] |
|||
* [[Rust (язык программирования)|Rust]] |
* [[Rust (язык программирования)|Rust]] |
||
* [[Scheme]] |
* [[Scheme]] |
||
Строка 109: | Строка 111: | ||
* [[XPL (язык программирования)|XPL]] |
* [[XPL (язык программирования)|XPL]] |
||
* [[РЕФАЛ]] |
* [[РЕФАЛ]] |
||
* «[[Сигма (язык программирования)|Сигма]]»<ref>[http://www.computer-museum.ru/books/n_mozaika/sigma_2.htm История языка Сигма].</ref> |
* «[[Сигма (язык программирования)|Сигма]]»<ref>[http://www.computer-museum.ru/books/n_mozaika/sigma_2.htm История языка Сигма] {{Wayback|url=http://www.computer-museum.ru/books/n_mozaika/sigma_2.htm |date=20130720031809 }}.</ref> |
||
* «[[Эпсилон (язык программирования)|Эпсилон]]»<ref>[http://www.computer-museum.ru/books/n_mozaika/epsilon.htm История языка Эпсилон].</ref> |
* «[[Эпсилон (язык программирования)|Эпсилон]]»<ref>[http://www.computer-museum.ru/books/n_mozaika/epsilon.htm История языка Эпсилон] {{Wayback|url=http://www.computer-museum.ru/books/n_mozaika/epsilon.htm |date=20130720030840 }}.</ref> |
||
== Примечания == |
== Примечания == |
Текущая версия от 17:59, 17 апреля 2024
В этой статье может быть слишком много ссылок на другие статьи, и, возможно, их количество нужно сократить. |
Раскрутка компилятора (англ. bootstrapping — от boot и strap) — метод создания транслятора для некоторого языка программирования, при котором транслятор пишется на том же языке программирования, для трансляции которого создаётся; создание транслятором исполняемых файлов из исходного кода самого транслятора. Используется для переноса трансляторов на новые архитектуры. Появился в середине 1950-х годов. Позволяет создать транслятор, который генерирует сам себя. Применялся для создания трансляторов многих языков программирования, включая языки «Бейсик», «Алгол», «C», «Паскаль», «ПЛ/1», Factor, Haskell, «Модула-2», «Оберон», OCaml, Common Lisp, Scheme, Java, *Python (Есть разные реализации этого проекта: CPython - на "C" (основная реализация), Jython - на "Java", и PyPy - самокомпилирующийся), Scala, Nemerle, Kotlin и другие.
Проблема курицы и яйца
[править | править код]Пусть создан новый язык программирования L. Пусть на языке L составлен исходный код транслятора для языка L. Как получить транслятор, способный из этого кода создать исполняемый файл?
Методы решения проблемы перечислены ниже:
- Автор языка L может вручную выполнить трансляцию исходного кода с языка L на машинный язык или на язык ассемблера. Затем можно выполнить полученный код для создания исполняемого файла компилятора. Так поступили Никлаус Вирт с учениками при создании первого компилятора для языка «Паскаль», а также Дональд Кнут при создании своей системы грамотного программирования WEB.
- Автор языка L может составить исходный код транслятора на языке, для которого уже существует транслятор. Попытку такого рода (впрочем, неудачную) предпринимал Никлаус Вирт при создании первого компилятора для языка «Паскаль» на языке «Фортран».
- То же, но автор языка L сам не составляет исходный код, а поручает эту операцию другому лицу. Такой способ часто применяется при создании трансляторов для языка Scheme.
- Первая версия компилятора может быть написана на подмножестве языка L, для которого уже существует некий другой компилятор. Таким способом были получены компиляторы для подмножества языков Java, Haskell и Free Pascal.
- Создать транслятор для новой платформы можно путём кросс-компиляции — создания исполняемого файла транслятора для новой платформы на платформе, для которой транслятор уже существует. Таким способом обычно портируются компиляторы, написанные на языках C и Free Pascal.
Раскрутка компилятора с использованием компилятора существующего языка
[править | править код]Создание транслятора языка L методом раскрутки подразумевает выполнение некоторых шагов.
- На первом шаге из языка L выделяется подмножество L0, которое не требует больших усилий для реализации, но является достаточным для написания транслятора самого себя. Затем, используя какой-либо существующий для этой платформы язык (например, C), составляется исходный код транслятора для L0.
- Затем на языке L0 составляется транслятор для самого языка L0. Исполняемый файл транслятора создаётся с помощью транслятора, полученного на первом шаге. После этого у программиста имеется транслятор L0, способный обработать свой исходный код.
- Далее начинается постепенное расширение L0 до L: добавляется какая-либо ранее не реализованная возможность языка L, после чего предыдущей версией транслятора создаётся новая, а вновь добавленную возможность можно использовать в трансляторе для последующего расширения языка.
Именно этот процесс и называют раскруткой.
Число шагов можно уменьшить, если после составления транслятора L0 на языке С сразу начинать составлять транслятор L на подмножестве L0.
Преимущества
[править | править код]Достоинства метода раскрутки[1]:
- проверка возможностей языка L;
- отсутствие необходимости изучения других языков (порою разработчику достаточно знать только язык L);
- возможность дальнейшего улучшения транслятора на языке высокого уровня L;
- постоянное улучшение качества кода (улучшение кода транслятора приводит к улучшению качества кода всех программ, создаваемых транслятором, включая сам транслятор);
- всесторонняя проверка транслятора на непротиворечивость (транслятор должен быть способен воспроизвести свой собственный код).
Недостатки
[править | править код]При создании новых языков программирования использование уже существующих языков может быть вполне оправданным по следующим причинам[2]:
- компиляторы уже существующих языков, как правило, надёжны (отлажены, изучены, стабильны);
- для уже существующих языков имеются отладчики, статические анализаторы и другие инструменты;
- невозможность использования генераторов синтаксических анализаторов;
- использование интерпретатора для самоинтерпретации нового языка может отрицательно сказаться на скорости: старый интерпретатор интерпретирует код нового интерпретатора, который интерпретирует код сценария пользователя (двойная интерпретация)[3].
История
[править | править код]Ассемблер можно считать первым транслятором, который относительно просто реализуется непосредственно в машинных кодах.
Neliac[англ.] — диалект языка «Алгол 58» и одноимённый компилятор, разработанные в 1958 году; первый язык высокого уровня, для которого был использован метод раскрутки.
Первыми широко используемыми языками, которые были раскручены тем же способом, стали:
- Burroughs B5000[англ.] («Алгол 60») в 1961 году;
- «Лисп» в 1962 году.
В 1962 году Тим Харт (англ. Tim Hart) и Марк Левин (Mark Levin) в Массачусетском технологическом институте написали первый компилятор «Лиспа» на языке Lisp[4] и проверили его на уже существующем интерпретаторе языка Lisp. Они перешли на него, как только разработанный ими компилятор смог откомпилировать свой собственный исходный код.
В СССР метод раскрутки использовался для создания компиляторов РЕФАЛ, «Сигма» и «Эпсилон».
Список языков, имеющих самокомпилирующиеся компиляторы
[править | править код]Список примеров в этой статье не основывается на авторитетных источниках, посвящённых непосредственно предмету статьи. |
- «Бейсик»
- «Алгол»
- C
- C++
- C#
- CoffeeScript
- Common Lisp
- Eiffel
- F#
- Factor
- Haskell
- Go
- Java
- Mercury
- «Модула-2»
- Nemerle
- Oberon
- OCaml
- «Паскаль»
- Perl 6
- «ПЛ/1»
- Rust
- Scheme
- Scala
- Standard ML
- Urn
Первый компилятор для языка ML, как для самостоятельного языка (после его выделения из LCF как встроенного и интерпретируемого) был написан Лукой Карделли[англ.] целиком на языке «Паскаль» (включая среду выполнения (англ. runtime)). Вскоре компилятор был переписан на диалекте «VAX ML» и получил название «Edinburgh ML». Этот компилятор служил платформой для исследования языка, постепенно приблизив ML к виду SML’90. Далее на нём был написан SML/NJ[англ.], в то время как среда исполнения была переписана на языке Си. Затем был раскручен SML/NJ, и далее на его основе раскручивались все остальные реализации языка. В настоящее время существует более десятка компиляторов и несколько интерпретаторов, в том числе с нестандартными расширениями, все из которых написаны на SML и обычно способны компилировать друг друга. Единственным исключением является неактуальный для SML инкрементальный компилятор Poplog, написанный на Lisp-подобном языке POP-11, не поддерживающий современные стандарты языка SML и его библиотеки. [5]
Примечания
[править | править код]- ↑ Patrick D. Terry. Compilers and Compiler Generators: An Introduction With C++. — International Thomson Computer Press, 1997. — ISBN 1850322988. Архивировано 29 июля 2011 года.
- ↑ Раскрутка компилятора . Дата обращения: 20 марта 2013. Архивировано 9 августа 2020 года.
- ↑ В некоторых случаях при двойной интерпретации производительность исполняемого файла может увеличиться. См. PyPy.
- ↑ Tim Hart and Mike Levin. AI Memo 39-The new compiler . Дата обращения: 13 октября 2006. (недоступная ссылка)
- ↑ MacQueen D. Luca Cardelli and the Early Evolution of ML.
- ↑ История языка Сигма Архивная копия от 20 июля 2013 на Wayback Machine.
- ↑ История языка Эпсилон Архивная копия от 20 июля 2013 на Wayback Machine.
Литература
[править | править код]- Альфред Ахо, Рави Сети, Джеффри Ульман. Раскрутка // Компиляторы: принципы, технологии и инструменты = Compilers: Principles, Techniques, and Tools. — М.: Вильямс, 2003. — С. 681—684. — 768 с. — ISBN 5-8459-0189-8.
- Свердлов С. З. Самокомпилятор. Раскрутка // Языки программирования и методы трансляции. — СПб.: Питер, 2007. — С. 427—431. — 638 с. — ISBN 5-469-00378-7.
- Вирт Н. Построение компиляторов, Москва, ДМК Пресс, 2010, ISBN 978-5-94074-585-3, ISBN 0-201-40353-6