Компиляторы в языках программирования

Какие задачи в программировании выполняет компилятор? Почему попытки создания универсального языка и универсального компилятора закончились неудачей? По каким причинам многие крупные фирмы разрабатывают собственные языки программирования? На эти и другие вопросы отвечает кандидат физико-математических наук Университета Иннополис Евгений Зуев.

Говоря простыми словами, компилятор — это программа, которая преобразует текст пользовательской программы в некоторое представление, пригодное для выполнения ее на компьютере.

В этом смысле компиляторы возникли вместе с первыми языками программирования в конце 50-х годов. Компилятор с фортрана вместе с языком фортран появился в 1958 году. Таким образом, история, связанная с языками программирования и компиляторами, насчитывает уже больше шестидесяти лет. Несмотря на это, трудно сказать, что это направление в программировании, в Computer Science, является устоявшимся, застывшим. Скорее, наоборот, с течением времени, с появлением новых задач, которые решают компьютеры, появляется потребность в создании новых языков программирования и, соответственно, в разработке компиляторов для этих языков.

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

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

Вот эту задачу и решает любой компилятор с любого языка программирования. Всегда, когда появляется новый язык программирования, возникает потребность в том, чтобы программу на этом языке перевести в вид, понятный компьютеру, чтобы компьютер мог выполнить эту программу. Опять-таки всегда существует некий семантический зазор, semantic gap, между понятиями любой программы, которую пишет программист, и понятиями, которыми оперирует компьютер. Для преодоления этого семантического разрыва и предназначен компилятор. Попросту говоря, компилятор — это некая программа, переводящая программу, написанную программистом, в машинный код или в тот вид, который понимает, который может выполнить компьютер.

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

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

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

Программисту удобно создавать модели своей предметной области, оперируя такими понятиями, как классы и функции.

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

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

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

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

В последнее время наметилась явная тенденция, когда каждая сколько-нибудь крупная фирма, имеющая отношение к компьютерам и программному обеспечению, выпускает собственный язык программирования. Эта тенденция характерна для очень многих современных фирм, имеющих отношение к компьютерам и программному обеспечению. Google, Facebook, не говоря уже о Microsoft и Oracle, имеют собственные языки программирования, которые они продвигают в широкие массы программистов. Естественно, для этих языков требуются компиляторы. Как правило, фирмы создают эти компиляторы сами, вместе с языками. Но, с другой стороны, существует большая сфера самодеятельных разработчиков, небольших фирм, которые по ряду причин тоже могут быть заинтересованы в том, чтобы иметь собственные компиляторы для известных языков. Или они создают собственные языки программирования и, соответственно, компиляторы для них. То есть можно точно утверждать, что работающий в этой сфере специалист без работы не останется.

В некотором смысле структура если не всех, то многих компиляторов очень похожа. Несмотря на это, предпринимавшиеся лет, наверное, 40 назад попытки создания универсального языка и, соответственно, универсального компилятора закончились неудачей по довольно простой причине: проблем, которые решает программное обеспечение, очень много. Они по природе своей различны. Одно дело — написать, например, программу, которая управляет самолетом, и совсем другое дело — написать бухгалтерскую программу. Это разные области знания. Соответственно, для их решения нужны разные инструменты. А язык и компилятор — это инструмент для решения определенных задач. Создать универсальный язык, который был бы пригоден для различных сфер, вряд ли возможно, и, соответственно, компиляторы для различных языков будут разными.

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

Полный текст статьи читайте на Postnauka.ru