Раскрутка компилятора: различия между версиями
[непроверенная версия] | [отпатрулированная версия] |
→Список языков, имеющих самокомпилирующиеся компиляторы:
https://go-review.googlesource.com/#/c/5652/
Компилятор Go написан на Go |
РоманСузи (обсуждение | вклад) оформление, викификация, запрос источника |
||
Строка 1: | Строка 1: | ||
'''Раскрутка компилятора''' ({{lang-en|bootstrapping}}) |
'''Раскрутка компилятора''' ({{lang-en|bootstrapping}}) — это такой метод создания [[компилятор]]а для некоторого [[Язык программирования|языка программирования]], при котором компилятор пишется на целевом языке. Раскрутка также используется для переноса компиляторов на новые [[Аппаратная платформа компьютера|платформы]]. Основные идеи раскрутки появились в середине [[1950-е|1950-х]] годов. Применение этого метода позволяет создать компилятор, который компилирует сам себя. Метод раскрутки применялся для создания компиляторов многих языков программирования, включая компиляторы [[BASIC]], [[Алгол]], [[Си (язык программирования)|Си]], [[Паскаль (язык программирования)|Паскаль]], [[ПЛ/1]], [[Factor (язык программирования)|Factor]], [[Haskell]], [[Modula-2]], [[Оберон (язык программирования)|Oberon]], [[OCaml]], [[Common Lisp]], [[Scheme]], [[Java]], [[Python]], [[Scala (язык программирования)|Scala]], [[Nemerle]] и многих других. |
||
== Что вперёд: курица или яйцо == |
== Что вперёд: курица или яйцо == |
||
Если Вам нужен компилятор для языка X (который написан на языке X), то как написать первый компилятор? Решение [[Проблема курицы и яйца|проблемы курицы и яйца]] возможно следующими методами: |
Если Вам нужен компилятор для языка X (который написан на языке X), то как написать первый компилятор? Решение [[Проблема курицы и яйца|проблемы курицы и яйца]] возможно следующими методами: |
||
* Создать [[интерпретатор]] или компилятор для языка X на языке Y. [[Вирт, Никлаус|Никлаус Вирт]] |
* Создать [[интерпретатор]] или компилятор для языка X на языке Y. [[Вирт, Никлаус|Никлаус Вирт]] написал первый компилятор [[Паскаль (язык программирования)|Паскаля]] на [[Фортран]]е. |
||
* Этот интерпретатор или компилятор для полной версии языка X уже может быть написан на языке Y кем-то другим; такая раскрутка часто применяется для языка Scheme. |
* Этот интерпретатор или компилятор для полной версии языка X уже может быть написан на языке Y кем-то другим; такая раскрутка часто применяется для языка Scheme. |
||
* Первая версия компилятора может быть написана на подмножестве языка X, для которого уже существует некий другой компилятор; таким способом были раскручены некоторые подмножества Java, Haskell и [[Free Pascal]]. |
* Первая версия компилятора может быть написана на подмножестве языка X, для которого уже существует некий другой компилятор; таким способом были раскручены некоторые подмножества Java, Haskell и [[Free Pascal]]. |
||
* Для создания компилятора языка X можно провести [[Кросс-компилятор|кросс-компиляцию]] на другой платформе, на которой уже существует компилятор для X; таким способом обычно портируются компиляторы, написанные на Си. Такой же способ используется для Free Pascal после начальной раскрутки. |
* Для создания компилятора языка X можно провести [[Кросс-компилятор|кросс-компиляцию]] на другой платформе, на которой уже существует компилятор для X; таким способом обычно портируются компиляторы, написанные на Си. Такой же способ используется для Free Pascal после начальной раскрутки. |
||
* Написание компилятора на языке X; затем компилирование вручную из исходного кода (вероятно всего, без оптимизации) и выполнение полученного кода для получения оптимизированного компилятора. [[Кнут, Дональд Эрвин|Дональд Кнут]] использовал этот метод для своей системы [[Грамотное программирование|грамотного программирования]] [ |
* Написание компилятора на языке X; затем компилирование вручную из исходного кода (вероятно всего, без оптимизации) и выполнение полученного кода для получения оптимизированного компилятора. [[Кнут, Дональд Эрвин|Дональд Кнут]] использовал этот метод для своей системы [[Грамотное программирование|грамотного программирования]] [[:en:WEB|WEB]]{{ref-en}}. |
||
== Раскрутка компилятора с использованием компилятора существующего языка == |
== Раскрутка компилятора с использованием компилятора существующего языка == |
||
Строка 13: | Строка 14: | ||
# Затем на языке 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<sub>0</sub>, который можно скомпилировать с помощью компилятора, полученного на первом шаге. После этого у программиста имеется компилятор L<sub>0</sub>, способный обработать свой [[исходный код]]. |
||
# Далее начинается постепенное расширение L<sub>0</sub> до L: добавляется какая-либо ранее не реализованная возможность языка L, после чего предыдущей версией компилируется новая, а вновь добавленную возможность можно использовать в компиляторе для последующего расширения языка. Именно этот процесс и называют раскруткой. |
# Далее начинается постепенное расширение L<sub>0</sub> до L: добавляется какая-либо ранее не реализованная возможность языка L, после чего предыдущей версией компилируется новая, а вновь добавленную возможность можно использовать в компиляторе для последующего расширения языка. Именно этот процесс и называют раскруткой. |
||
Этапы раскрутки можно сократить: после написания компилятора |
Этапы раскрутки можно сократить: после написания компилятора «L<sub>0</sub>» c помощью «С» можно сразу писать компилятор «L» с помощью «L<sub>0</sub>». |
||
== Преимущества == |
== Преимущества == |
||
Строка 25: | Строка 26: | ||
|isbn = 1850322988 |
|isbn = 1850322988 |
||
}}</ref> |
}}</ref> |
||
* это |
* это — нетривиальная проверка языка, для которого делается компилятор; |
||
* порою разработчику достаточно знать только этот язык; |
* порою разработчику достаточно знать только этот язык; |
||
* дальнейшие улучшения компилятора можно делать на языке высокого уровня; |
* дальнейшие улучшения компилятора можно делать на языке высокого уровня; |
||
* улучшение [[Кодогенерация|сгенерированного компилятором кода]] улучшает не только код программ вообще, но и код самого компилятора; |
* улучшение [[Кодогенерация|сгенерированного компилятором кода]] улучшает не только код программ вообще, но и код самого компилятора; |
||
* это |
* это — всесторонняя проверка компилятора на непротиворечивость, поскольку он должен быть в состоянии воспроизвести свой собственный код. |
||
== Недостатки == |
== Недостатки == |
||
В случае создания новых языков программирования, использование уже существующих языков может быть вполне оправданным по следующим причинам |
В случае создания новых языков программирования, использование уже существующих языков может быть вполне оправданным по следующим причинам<ref>[http://www.compiler.su/raskrutka-kompilyatora.php Раскрутка компилятора]</ref>: |
||
* компиляторы уже существующих языков, как правило, надёжны; |
* компиляторы уже существующих языков, как правило, надёжны; |
||
* для уже существующих языков имеются [[Отладка программы|отладчики]] и другие инструменты; |
* для уже существующих языков имеются [[Отладка программы|отладчики]] и другие инструменты; |
||
Строка 39: | Строка 40: | ||
== История == |
== История == |
||
Первыми языковыми инструментами, которые откомпилировали сами себя методом раскрутки, были ассемблеры. Первый язык высокого уровня, для которого был использован метод раскрутки, был [[Neliac]] в 1958 |
Первыми языковыми инструментами, которые откомпилировали сами себя методом раскрутки, были ассемблеры. Первый язык высокого уровня, для которого был использован метод раскрутки, был [[Neliac]] в 1958 г. Первыми широко используемыми языками, которые были раскручены тем же способом, были [[:en:Burroughs B5000|Burroughs B5000]] Алгол в 1961 г. и Lisp в 1962 г. Харт и Левин написали компилятор Lisp на Lisp в [[Массачусетский технологический институт|Массачусетском технологическом институте]] в 1962 г., проверяя его на уже существующем интерпретаторе Lisp. Они перешли на него, как только разработанный ими компилятор смог откомпилировать свой собственный исходный код. |
||
Компиляторами, созданными в [[Союз Советских Социалистических Республик|СССР]] и использовавшими технику раскрутки, были [[РЕФАЛ]], [[Сигма (язык программирования)|Сигма]] и [[Эпсилон (язык программирования)|Эпсилон]]. |
Компиляторами, созданными в [[Союз Советских Социалистических Республик|СССР]] и использовавшими технику раскрутки, были [[РЕФАЛ]], [[Сигма (язык программирования)|Сигма]] и [[Эпсилон (язык программирования)|Эпсилон]]. |
||
== Список языков, имеющих самокомпилирующиеся компиляторы == |
== Список языков, имеющих самокомпилирующиеся компиляторы == |
||
{{список примеров}} |
|||
* [[BASIC]] |
* [[BASIC]] |
||
* [[Алгол]] |
* [[Алгол]] |
||
Строка 68: | Строка 71: | ||
* [[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/epsilon.htm История Эпсилон]</ref> |
||
== Примечания == |
== Примечания == |
||
{{примечания}} |
{{примечания}} |
||
Строка 110: | Строка 114: | ||
|тираж = |
|тираж = |
||
}} |
}} |
||
== Ссылки == |
|||
* http://www.compiler.su/raskrutka-kompilyatora.php |
* http://www.compiler.su/raskrutka-kompilyatora.php |
||
Версия от 19:06, 24 февраля 2015
Раскрутка компилятора (англ. bootstrapping) — это такой метод создания компилятора для некоторого языка программирования, при котором компилятор пишется на целевом языке. Раскрутка также используется для переноса компиляторов на новые платформы. Основные идеи раскрутки появились в середине 1950-х годов. Применение этого метода позволяет создать компилятор, который компилирует сам себя. Метод раскрутки применялся для создания компиляторов многих языков программирования, включая компиляторы BASIC, Алгол, Си, Паскаль, ПЛ/1, Factor, Haskell, Modula-2, Oberon, OCaml, Common Lisp, Scheme, Java, Python, Scala, Nemerle и многих других.
Что вперёд: курица или яйцо
Если Вам нужен компилятор для языка X (который написан на языке X), то как написать первый компилятор? Решение проблемы курицы и яйца возможно следующими методами:
- Создать интерпретатор или компилятор для языка X на языке Y. Никлаус Вирт написал первый компилятор Паскаля на Фортране.
- Этот интерпретатор или компилятор для полной версии языка X уже может быть написан на языке Y кем-то другим; такая раскрутка часто применяется для языка Scheme.
- Первая версия компилятора может быть написана на подмножестве языка X, для которого уже существует некий другой компилятор; таким способом были раскручены некоторые подмножества Java, Haskell и Free Pascal.
- Для создания компилятора языка X можно провести кросс-компиляцию на другой платформе, на которой уже существует компилятор для X; таким способом обычно портируются компиляторы, написанные на Си. Такой же способ используется для Free Pascal после начальной раскрутки.
- Написание компилятора на языке X; затем компилирование вручную из исходного кода (вероятно всего, без оптимизации) и выполнение полученного кода для получения оптимизированного компилятора. Дональд Кнут использовал этот метод для своей системы грамотного программирования WEB (англ.).
Раскрутка компилятора с использованием компилятора существующего языка
Создание компилятора языка L методом раскрутки подразумевает последовательность некоторых шагов.
- На первом шаге из языка L выделяется подмножество L0, которое не требует больших усилий для реализации, но является достаточным для написания компилятора самого себя. Затем, используя какой-либо существующий для этой платформы язык (например, C) программируется компилятор L0—С.
- Затем на языке L0 пишется компилятор самого языка L0, то есть L0—L0, который можно скомпилировать с помощью компилятора, полученного на первом шаге. После этого у программиста имеется компилятор L0, способный обработать свой исходный код.
- Далее начинается постепенное расширение L0 до L: добавляется какая-либо ранее не реализованная возможность языка L, после чего предыдущей версией компилируется новая, а вновь добавленную возможность можно использовать в компиляторе для последующего расширения языка. Именно этот процесс и называют раскруткой.
Этапы раскрутки можно сократить: после написания компилятора «L0» c помощью «С» можно сразу писать компилятор «L» с помощью «L0».
Преимущества
У создания компиляторов методом раскрутки есть следующие преимущества: [1]
- это — нетривиальная проверка языка, для которого делается компилятор;
- порою разработчику достаточно знать только этот язык;
- дальнейшие улучшения компилятора можно делать на языке высокого уровня;
- улучшение сгенерированного компилятором кода улучшает не только код программ вообще, но и код самого компилятора;
- это — всесторонняя проверка компилятора на непротиворечивость, поскольку он должен быть в состоянии воспроизвести свой собственный код.
Недостатки
В случае создания новых языков программирования, использование уже существующих языков может быть вполне оправданным по следующим причинам[2]:
- компиляторы уже существующих языков, как правило, надёжны;
- для уже существующих языков имеются отладчики и другие инструменты;
- невозможность использования генераторов синтаксических анализаторов;
- использование интерпретатора для самоинтерпретации нового языка отрицательно скажется на скорости: сперва исполняемый код интерпретатора подмножества нового языка транслирует исходный код интерпретатора полной версии языка, и только затем полученный код интерпретатора будет выполнять интерпретацию пользовательской программы.
История
Первыми языковыми инструментами, которые откомпилировали сами себя методом раскрутки, были ассемблеры. Первый язык высокого уровня, для которого был использован метод раскрутки, был Neliac в 1958 г. Первыми широко используемыми языками, которые были раскручены тем же способом, были Burroughs B5000 Алгол в 1961 г. и Lisp в 1962 г. Харт и Левин написали компилятор Lisp на Lisp в Массачусетском технологическом институте в 1962 г., проверяя его на уже существующем интерпретаторе Lisp. Они перешли на него, как только разработанный ими компилятор смог откомпилировать свой собственный исходный код. Компиляторами, созданными в СССР и использовавшими технику раскрутки, были РЕФАЛ, Сигма и Эпсилон.
Список языков, имеющих самокомпилирующиеся компиляторы
Список примеров в этой статье не основывается на авторитетных источниках, посвящённых непосредственно предмету статьи. |
- BASIC
- Алгол
- Си
- C++
- Common Lisp
- Eiffel
- F Sharp
- Factor
- Haskell
- Go
- Java
- Mercury
- Modula-2
- Nemerle
- Oberon
- OCaml
- Паскаль
- Perl 6
- ПЛ/1
- Python
- Rust
- Scheme
- Scala
- TypeScript
- XPL
- РЕФАЛ
- Сигма[3]
- Эпсилон[4]
Примечания
- ↑ Patrick D. Terry. Compilers and Compiler Generators: An Introduction With C++. — International Thomson Computer Press, 1997. — ISBN 1850322988.
- ↑ Раскрутка компилятора
- ↑ История Сигмы
- ↑ История Эпсилон
Литература
- Альфред Ахо, Рави Сети, Джеффри Ульман. Раскрутка // Компиляторы: принципы, технологии и инструменты = Compilers: Principles, Techniques, and Tools. — М.: Вильямс, 2003. — С. 681—684. — 768 с. — ISBN 5-8459-0189-8.
- С. З. Свердлов. Самокомпилятор. Раскрутка // Языки программирования и методы трансляции. — СПб.: Питер, 2007. — С. 427—431. — 638 с. — ISBN 5-469-00378-7.