Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
КонспЛекци1.10.052.doc
Скачиваний:
12
Добавлен:
06.12.2018
Размер:
8.63 Mб
Скачать
      1. Компиляторы

Компиля́тор —

Программа или техническое средство, выполняющее компиляцию.[1][2]

Машинная программа, используемая для компиляции.[3][2]

Программа, переводящая текст программы на языке высокого уровня в эквивалентную программу на машинном языке.[4]

Программа, предназначенная для трансляции высокоуровневого языка в абсолютный код или, иногда, в язык ассемблера. Входной информацией для компилятора (исходный код) является описание алгоритма или программа на проблемно-ориентированном языке, а на выходе компилятора — эквивалентное описание алгоритма на машинно-ориентированном языке (объектный код).[5]

выполняющая (после трансляции) компоновку программы.

Компиляция —

трансляция программы на язык, близкий к машинному,[3][2] и последующая ее компоновка.

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

трансляция программы, составленной на исходном языке, и последующая ее компоновка в программу на некоем машинонезависимом низкоуровневом интерпретируемом коде (как например в случае языка Java).

Компилировать — производить трансляцию машинной программы с проблемно-ориентированного языка на машинно-ориентированный язык [3] и последующую компоновку программы в готовый к использованию программный модуль.Содержание

1 Виды компиляторов[2]

2 Виды компиляции[2]

3 Основы

4 Структура компилятора

5 Трансляция и компоновка

6 Интересные факты

7 См. также

8 Примечания

9 Литература

Виды компиляторов[2]

Векторизующий. Компилирует исходный код в машинный код для компьютеров, оснащённых векторным процессором.

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

Диалоговый. См.: диалоговый транслятор.

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

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

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

Отладочный. Устраняет отдельные виды синтаксических ошибок.

Резидентный. Постоянно находится в оперативной памяти и доступен для повторного использования многими задачами.

Самокомпилируемый. Написан на том же языке, с которого осуществляется компиляция.

Универсальный. Основан на формальном описании синтаксиса и семантики входного языка. Важными составными частями такого компилятора являются: ядро, синтаксический и семантический загрузчики.

Виды компиляции[2]

Пакетная. Компиляция нескольких исходных модулей в одном пункте задания.

Построчная. То же, что и интерпретация.

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

Основы

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

Некоторые компиляторы (например, Java) переводят программу не в машинный код, а в программу на некотором специально созданном низкоуровневом интрепретируемом языке. Такой язык — байт-код (в случае с Java Java-байт-код) — также можно считать языком машинных команд, поскольку в качестве его интерпретатором используется виртуальная машина. Байт-код не является машинным кодом какого-либо компьютера, т. е. машинным кодом в прямом смысле слова, и может переноситься на различные компьютерные архитектуры без перекомпиляции. Байт-код интерпретируется (исполняется) виртуальной машиной.

Например, для языка Java это JVM (язык виртуальной машины Java), или так называемый байт-код Java (вслед за ним все промежуточные низкоуровневые интрепретируемые языки стали называть байт-кодами). Для языков программирования на платформе .NET Framework (C#, Managed C++, Visual Basic .NET и другие) — это MSIL (Microsoft Intermediate Language).

Программа на байт-коде подлежит интерпретации виртуальной машиной, либо ещё одной компиляции уже в машинный код непосредственно перед исполнением. Последнее называется «Just-In-Time компиляция» (JIT), по названию подобного компилятора для Java. MSIL-код компилируется в код целевой машины также JIT-компилятором, а библиотеки .NET Framework компилируются заранее.

Для каждой целевой машины (IBM, Apple, Sun и т. д.) и каждой операционной системы или семейства операционных систем, работающих на целевой машине, требуется написание своего компилятора. Существуют также так называемые кросс-компиляторы, позволяющие на одной машине и в среде одной ОС генерировать код, предназначенный для выполнения на другой целевой машине и/или в среде другой ОС. Кроме того, компиляторы могут быть оптимизированы под разные типы процессоров из одного семейства (путём поддержки специфичных для этих процессоров машинных команд). Например, код, скомпилированный под процессоры семейства Pentium, может использовать специфичные для этих процессоров наборы инструкций — MMX, SSE, SSE2.

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

Существуют программы, которые решают обратную задачу — перевод программы с низкоуровневого языка на высокоуровневый. Этот процесс называют декомпиляцией, а такие программы — декомпиляторами. (Яркий пример таких программ - дизассемблеры) Но поскольку компиляция — это процесс с потерями, точно восстановить исходный код, скажем, на C++, в общем случае невозможно. Более эффективно декомпилируются программы в байт-кодах — например, существует довольно надёжный декомпилятор для Flash. Разновидность декомпилирования является дизассемблирование машинного кода в код на языке ассемблера, который всегда выполняется успешно. Связано это с тем, что между кодами машинных команд и командами ассемблера имеется практически взаимно-однозначное соответствие.

Структура компилятора

Любой компилятор состоит из транслятора и компоновщика. Часто в качестве компоновщика компилятор использует внешний компоновщик, реализованный в виде самостоятельной программы, а сам выполняет лишь трансляцию исходный текст (по этой причине многие ошибочно считают компилятор разновидность транслятора). Компилятор может быть реализован и как своеобразная программа-менеджер, для трансляции программы вызвающая сооствествующий транслятор (трансляторы - если разные части программы написаны на разных языках программирования) и затем - для компоновки программы, - вызывающая компоновщик. Ярким примером такого компилятора является имеющаяся во всех UNIX-системах (и Linux-системах в том числе) утилита make (имеются реализации утилиты make и в других системах, в частности в Windows-системах).

Процесс компиляции состоит из следующих фаз:

Лексический анализ. На этой фазе последовательность символов исходного файла преобразуется в последовательность лексем.

Синтаксический (грамматический) анализ. Последовательность лексем преобразуется в древо разбора.

Семантический анализ. Древо разбора обрабатывается с целью установления его семантики (смысла) — например, привязка идентификаторов к их опеределниям, типам данным, проверка совместимости типов данных, определение результирующих типов данных выражений и т. д. Результат обычно называется «промежуточным представлением/кодом», и может быть дополненным древом разбора, новым древом, абстрактным набором команд или чем-то ещё, удобным для дальнейшей обработки.

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

Генерация кода. Из промежуточного представления порождается код на целевом языке (в том числе выполняется компоновка программы).

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

Трансляция и компоновка

Важной исторической особенностью компилятора, отражённой в его названии (англ. compile — собирать вместе, составлять), являлось то, что он мог производить как трансляцию так и компоновку (то есть состоял из двух части — транслятора и компоновщика). Это связано с тем, что раздельные трансляция и компоновка как отдельная фазы компиляции выделились значительно позже появления компиляторов. В связи с этим, вместо термина «компилятор» иногда используют термин «транслятор» как его синоним, что, правда, терминологически неправильно: либо в старой литературе, либо когда хотят подчеркнуть его способность переводить программу в машинный код (и наоборот, используют термин «компилятор» для подчёркивания способности собирать из многих файлов один).

Интересные факты

На заре развития компьютеров первые компиляторы (трансляторы) называли «программирующими программами»[6] (так как в тот момент программой считался только машинный код, а «программирующая программа» была способна из человеческого текста сделать машинный код, то есть запрограммировать ЭВМ).

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

какую программу компилятор должен построить ,

что и как создаваемая нами таким образом программа должна делать (в том числе какие данные и как обрабатывать).

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