Р.У. Себеста - Основные копцепции языков программирования (2001) (1160794), страница 12
Текст из файла (страница 12)
выражения. операторы присваивания и управляющие операторы в языках С и )ача практически идентичны. (С другой стороны, массивы, подпрограммы и семантика этих языков различаются значительно.) Логический язык программирования — пример языка. основанного на продукционных правилах. В императивном языке программирования алгоритмы описываются очень подробно с обязательным указанием порядка выполнения команд или операторов.
В языке, основанном на пролукционных правилах. не сушествует определенного порядка применения правил. и система реализации языка должна сама выбрать нужный порядок выполнения команд, который привелет к желаемому результату. Такой подход к разработке программного обеспечения радикально отличается от полходов„используемых в остальных трех группах языков программирования и, безусловно, требует абсолютно иных языков. Самый популярный язык логического программирования Рго1оя и собственно логическое программирование описываются в главе 15. С языками программировании иногда путают такие языки разметки.
как НТМ(.. Олмако эти языки не описывают вычислений — они всего лишь задают обший вил локумента. Тем не менее, к языкам разметки применимы многие методы разработки и критерии оценки, описываемые в данной главе. Помимо всего прочего, вполне очевидна важность читабельности и легкости создания кодов разметки. 1.6. Компромиссы при разработке языка Описанные в разделе 13 критерии оценки языков программирования создают основу для разработки языка. К сожалению. эта основа внутренне противоречива.
В своей проницательной статье, посвяшенной вопросал~ разработки языков программирования, Хоар отметил: 'Сушествует так много важных. но противоречивых критериев, что их согласование между собой и уловлетворение является основной задачей проектирования" (Ноаге, 1973). Глава1. Вводные замечания Примером пары конфликтующих между собой критериев могут служять належность и стоимость выполнения программы. Например. в языке Ада выполняется проверка всех ссылок на элементы массива. для того чтобы гарантировать, что инлекс или инлексы нахолятся в допустимых пределах.
Это значительно повышает стоимость выполнения программ. написанных на языке Ада. содержащих большое количество ссылок на элеиенты массивов, В языке С проверка прелелов изменения индексов не предусмотрена, так что программы на языке С выполняются быстрее, чем семантически эквивалентные программы на языке Ада.
хотя надежность выше у последних. Разработчики языка Ада пожертвовали эффективностью выполнения в пользу надежности. В качестве другого примера конфликтующих между собой критериев, прямо приволяших к поиску компромиссов при разработке, рассмотрим язык АР)..
Этот язык содержит мощный набор операторов для действий с массивами. Из-за большого количества этих операторов лля их представления в язык АР(, пришлось включить значительное число новых символов. Кроме того, многие операторы языка АР(. могут использоваться в отдельных длинных и сложных выражениях. Такая высокая степень выразительности языка позволяет легко писать программы, содержащие большое количество операций с массивами.
Действительно. огромное количество вычислений может быть описано в очень компактной программе. Недостатком является плохая читабельность программ. написанных на языке АР(.. Компактное и лаконичное выражение с математической точки зрения, конечно. красиво. но для всех. кроме автора, создает сложности при чтении. Известный автор Даниель Мак-Кракен (Оап(е! МсСгасйеп) однажды отметил. что чтение и анализ программы из четырех строк, написанной на языке АР(..
заняли у него четыре часа (МсСгасйеп, 19Т0). Таким образом, разработчики языка АР(. пожертвовали читабельностью в пользу легкости созлания программ. Противоречия между гибкостью и безопасностью обычны лля языков программирования. Записи в языке Разса1 разрешают ячейке памяти в разное время содержать переменные разных типов. Например. ячейка может содержать либо указатель. либо целое число.
Таким образом, с помещенным в такую ячейку указателем можно выполнять действия, определенные лля целых величин. Это создает лазейлу в проверке типов. позволяющую программе выполнять арифметические действия с указателями. что иногда бывает улобным. Однако следует заметить, что бесконтрольно использовать ячейки памяти опасно. Существует множество примеров конфликтов между критериями разработки (и оценки) языка; некоторые из них очевидны, другие — едва различимы. Отсюда следует, что решить задачу выбора конструкций и свойств языка невозможно без компромиссов.
1.7. Методы реализации Как указано в разделе 1.4.1, двумя основными компонентами компьютера являются его оперативная память и процессор. Оперативная память используется лля хранения программ и данных. Процессор — это совокупность электронных схем, обеспечивающих реализацию набора элементарных операций, или машинных команд. т.е. арифметических и логических операций. В большинстве компьютеров некоторые из этих команл. иногда называемых макрокомандами. реализуются с помощью набора низкоуровневых команл, называемых микрокомандами.
Поскольку микрокоманды всегда скрыты от программиста, то их обсужление, как правило, не включается в обсуждение программного обеспечения. По этой причине микрокоманлы мы далее обсуждать не будем. 1.7. Методы реализации Набор макрокоманд компьютера называется его машинным языком. При отсутствии остатьиого программного обеспечения большая часть аппаратного обеспечения компьютера "понимает" только его машинный язык. Теоретически можно спроектировать и создать компьютер, использующий некий язык высокого уровня в качестве машинного, ио это было бы очень сложно и лорого. Более того, он был бы крайне негибким, поскольку такой компьютер сложно (хотя и можно) использовать совместно с другими языками высокого уровня.
Более практичное решение — аппаратно реализовать язык очень низкого уровня, что обеспечит выполнение наиболее распространенных элементарных операций и потребует системного программного обеспечения для взаимодействия с программами, написанными на языках высокого уровня. Система реализации языка не может рассматриваться как елннственное программное обеспечение компьютера. Кроме нее нужен также большой набор программ, поддерживающих языковые конструкции более высокого уровня, чем конструкции машинного языка. Такой набор программ называется операционной системой. Языковые конструкции, поддерживаемые операционной системой, осуществляют управление системными ресурсами, операциями ввода-вывода, системой управления файлами. релакторами текста и/или программ, а также обеспечивают выполнение большого количества других необходимых функций.
Поскольку системам реализации языка требуется большое количество возможностей операционной системы, они взаимодействуют с ней. а не с процессором (на машинном языке). Уровни операционной системы и систем реализации языков программирования находятся выше уровня машинного языка. Эти системы можно представить в виде виртуальных компьютеров, обеспечивающих взаимодействие с пользователем, находящимся на более высоком уровне.
Например, операционная система и компилятор языка С создают виртуальный компьютер языка С. С другим компилятором машина может стать другим виртуальным компьютером. Большинство вычислительных систем создает несколько различных виртуальных компьютеров. Пользовательские программы образуют следующий уровень, находящийся над уровнем виртуальных компьютеров. Многоуровневое представление компьютера показано на рис.
1.2. Системы реализации первых языков программирования высокого уровня были созданы в конце!950-х годов и считались одними из сложнейших систем программного обеспечения того времени. В 1960-х годах были провелеиы интенсивные научноисследовательские работы, направленные на анализ и формализацию процесса конструирования этих реализаций языков высокого уровня. Наибольшие успехи были достигнуты в области синтаксического анализа, главным образом из-за того, что эта часть процесса реализации является приложением части теории автоматов и теории формальных языков, которые в то время были хорошо изучены. Глава1. Вводныв замвчпиия Виртуальный Виртуал КОМПЬЮ ройтй Виртуа тмпью изыка С кьмпьютар паыт Ава Рис. 1.2. Мноеоз ровневый интерфейс пирит»атьных наттпьютеров, создавае.мый стандартной вычислительной системой 1.7.1.
Компиляция Языки программирования могут реализовываться одним из трех метолов. Например, программа может переводиться на машинный язык и выполняться непосрелственно компьютером. Такая реализация называется компиляцией. Преимушество этого метода— очень быстрое выполнение программы после завершения процесса трансляции. Большинство промышленных реализаций таких языков, как С, СОВО1 и Ада, выполняются с помошью компилятора.
Язык, который компилятор переводит в машинный, называется исходным языком. Процесс компиляции протекает в несколько этапов, важнейшие из которых показаны на рис. 1.3. 47 1.7. Мвтоды реализации (необязательно) Результаты Рис. !.3. Лроттесс яозтьаялык Лексический анализатор объединяет символы исходной программы в лексические единицы.
Лексические единицы программы — это идентификаторы. служебные слова, операторы и знаки пунктуации. Поскольку комментарии исходной программы компилятором не используются, то лексический аназнзатор их игнорирует. Синтаксический анализатор получает от лексического анализатора лексические единицы и использует нх для создания иерархических структур, называемых деревьями синтаксического аначиза. Эти деревья представляют собой синтаксическую структуру про- 48 Глава1. Вводные замечания граммы. Однако в большинстве случаев никакой структуры дерева синтаксического анализа не создается, а просто генерир>ется и используется информация.
необходимая для его создания. К лексическим единицам и деревьям синтаксического аназиза мы еше вернемся в главе 3. Генератор промежуточных команд создает программы на особом языке. промежуточном между языком исхолной программы и машинным языком. 10тметим, что термины "язык" и "кол' — часто взаимозаменяемы.) Промежуточные языки зачастую очень похожи на языки ассемблера и иногда действительно ими являются. В остатьных сл> чаях промеж>- точный кол имеет более высокий уровень. чем язык ассемблера.
Неотъемлемой частью генератора промеж>точного кола является семантический аназизатор. выполняюший поиск тех ошибок, выявление которых в процессе синтаксического разбора затруднительно шюо невозможно, например. ошибок. связанных с несовместилюстью типов. Простейшие примеры синтаксического анализа и генерации промеж>точного кода рассмотрены в главе 3.