В.Ш. Кауфман - Языки программирования - концепции и принципы (1990) (1160787), страница 7
Текст из файла (страница 7)
6. while ch /= '.' loop
7. if ch = '(' or ch = ')' then
8. т_обмен.возьми (ch) ;
9. end if ;
10. т_обмен.дай (ch) ;
11. end loop ;
12. end печать_скобок ;
Итак, в программе двенадцать строчек (номера строчек не входят в
программу - они нужны, чтобы обсуждать ее свойства). Общий вид программы
напоминает текст на Алголе 60 или Паскале (некоторые знакомые ключевые
слова, характерная ступенчатая запись и т.п.). Это и не удивительно. Ведь
Ада из семейства "поздних алголоидов". Как уже сказано, этот язык - развитие
Паскаля, в свою очередь созданного (Никлаусом Виртом) на основе Алгола 60.
Вместе с тем даже в этой простой программе заметны характерные
особенности поздних языков индустриального программирования.
Во-первых, высокоразвитая модульность. Фраза с ключевым словом "with"
(в переводе с английского "с" или "совместно с") говорит о том, что данную
процедуру следует читать, понимать и исполнять во вполне определенном
контексте. Этот контекст задан модулем-ПАКЕТОМ с именем "т_обмен". В нем
содержатся определения всех ресурсов, необходимых для ввода-вывода текстов
(в частности, процедуры "дай" очередной символ со стандартного устройства
ввода и "возьми" очередной символ на стандартное устройство вывода). Внутри
программы, использующей такой пакет, обращаться к его ресурсам следует по
составным именам (сначала название пакета, а затем через точку - название
ресурса) как к полям записи в Паскале. При необходимости можно, конечно,
ввести сокращенные обозначения для часто используемых ресурсов.
Во-вторых, богатый набор типов данных. В строчке 3 находится объявление
переменной ch типа "символ". Это один из предопределенных типов Ады. Здесь и
далее предопределенные идентификаторы языка Ада переведены на русский язык.
В оригинале - тип character. Наглядность для нас важнее, чем формальное
следование правилам языка; ведь он здесь служит лишь примером общих
концепций в ЯП. Ни в Алголе 60, ни в Фортране такого символьного типа,
равноправного с остальными типами, нет. Один из источников выразительной
мощи языка Ада - возможность строить новые типы данных, не предопределенные
авторами языка. Такая возможность теперь имеется во всех новых ЯП и мы с ней
подробно познакомимся.
В-третьих, ради надежности повышена избыточность, способствующая
устранению случайных ошибок. Это и (сколь угодно) длинные названия-
идентификаторы, которые можно к тому же составлять из отдельных слов,
соединенных одиночным подчеркиванием. Это и строгая скобочная структура
текста - каждый управляющий конструкт снабжен специальным "закрывающим"
ключевым словом (цикл в строчках с 6 по 11, условный оператор в строчках 7-
9, процедура в строчках 2-12). Надежности, ясности, четкой структуре и
избыточности способствуют также и строгие правила ступенчатой записи
программ (в Аде она настоятельно рекомендуется в определении языка и
отражена в его синтаксисе).
Смысл программы достаточно очевиден. В строчке 5 вводится первый символ
обрабатываемой последовательности и помещается в переменную ch. Далее цикл,
работающий до тех пор, пока значением переменной ch не станет символ "."
("/=" - это "не равно", "." - это признак конца последовательности
обрабатываемых символов). В теле цикла - условный оператор, который посылает
на устройство вывода очередной символ, если это открывающая или закрывающая
скобка. Затем (строкой 10), вводится в переменную ch очередной символ
последовательности и цикл повторяется. Вместе с циклом завершается и
процедура печать_скобок.
2.2. Обзор языка Ада
Этот раздел близок по структуре и стилю к разделу 1.4 официального
определения языка Ада - национальному стандарту США 1983 г., в 1986 г.
ставшему без изменений международным стандартом (стандартом ИСО).
Рассказывая об этом языке и приводя примеры (из различных источников), будем
и впредь опираться на это официальное определение.
Без существенных изменений оно принято и в качестве отечественного
ГОСТа, имеется его перевод на русский язык, отечественные реализации Ады
также ориентируются на это определение.
Однако наша цель - не определить язык, а продемонстрировать концепции,
характерные (и, как правило, перспективные) для базовых языков
индустриального программирования. Поэтому будем стремиться упрощать
изложение и избегать деталей, несущественных для нашей задачи.
Само по себе их обилие в официальном сообщении, к сожалению, также
характерно. Оно свидетельствует либо о неразвитости науки и практики
языкотворчества, либо о фундаментальных свойствах такого социального
явления, как ЯП. Поразительный пример лаконичности - определение Никлаусом
Виртом языка Модула-2 [5]).
Итак, нас интересует не столько сам язык Ада, сколько возможность
использовать его в качестве источника идей для модели А. Вместе с тем,
приводя примеры программ на языке Ада, будем строго следовать стандарту,
чтобы не создавать у читателей лишних затруднений при последующем
самостоятельном освоении языка. Понятия языка Ада (Ада-понятия) будем
выделять прописными буквами.
Ада-программа состоит из одного или более программных МОДУЛЕЙ
(сегментов), которые можно компилировать раздельно (кроме задач).
Ада-модуль - это ПОДПРОГРАММА (определяет действия - части отдельных
ПРОЦЕССОВ) или ПАКЕТ (определяет часть контекста - совокупность объектов,
предназначенных для совместного использования) или ЗАДАЧА (определяет
асинхронный процесс) или РОДОВОЙ модуль (заготовка пакета или подпрограммы с
параметрами периода компиляции).
В каждом модуле обычно две части: внешность или СПЕЦИФИКАЦИЯ (содержит
сведения, видимые из других модулей) и внутренность или ТЕЛО (содержит
детали реализации, невидимые из других модулей). Разделение спецификации и
тела вместе с раздельной компиляцией дает возможность проектировать, писать
и проверять программу как набор относительно самостоятельных (слабо
зависимых) компонент.
Ада-программа пользуется ТРАНСЛЯЦИОННОЙ БИБЛИОТЕКОЙ. Поэтому в тексте
создаваемого модуля следует указывать названия используемых библиотечных
модулей.
2.2.1 Модули
Подпрограмма - основной конструкт для определения подпроцессов (ввод
данных, обновление значений переменных, вывод данных и т.п.). У подпрограммы
могут быть параметры, посредством которых ее связывают с контекстом вызова.
Различают две категории подпрограмм - процедуры и функции. Последние
отличаются тем, что вырабатывают результат, непосредственно доступный в
точке вызова функции. Поэтому вызов функции всегда входит в некоторое
выражение.
Пакет - основной конструкт для определения именованного контекста
(иногда говорят "логически связанной" совокупности объектов). Несколько
расплывчатое "логически связанной" подразумевает возможность объединить в
пакет все то, что автор пожелает видеть единым модулем, названным подходящим
именем. Это может быть сделано потому, что, во-первых, все связанные в пакет
объекты предполагается использовать совместно; во-вторых, необходимо или
удобно совместно реализовывать; в-третьих, невозможно или неудобно раздельно
определять из-за адовских ограничений на ВИДИМОСТЬ имен. Возможны и иные
причины объединения в один пакет определений отдельных имен. Часть из них
может быть при этом скрыта, ЗАЩИЩЕНА от непосредственного использования
другими модулями; доступ к таким именам строго регламентирован - только
через имена, в спецификации пакета явно предназначенные для внешнего
использования.
Задача - основной конструкт для определения асинхронного процесса,
способного выполняться параллельно с другими процессами. Процессом
называется определенным образом идентифицируемая последовательность действий
исполнителя, линейно-упорядоченная во времени. В одном модуле-задаче можно
определить один асинхронный процесс или совокупность аналогичных асинхронных
процессов (так называемый ЗАДАЧНЫЙ ТИП). Асинхронность можно обеспечивать
как отдельными процессорами для каждого процесса, так и "прерывистым"
выполнением различных процессов на одном процессоре.
2.2.2. Объявления и операторы
В теле модуля в общем случае две части - ОБЪЯВЛЕНИЯ и ОПЕРАТОРЫ.
Объявления вводят новые знаки (ИМЕНА) и связывают их с денотатами
(ОБЪЕКТАМИ). Эта связь имени с определенным объектом (знаковая ситуация)
сохраняет силу в пределах ОБЛАСТИ ДЕЙСТВИЯ имени. Таким образом, формально
объект - это то, что можно именовать. Вместе с тем авторы языка Ада
стремились к тому, чтобы ада-объектами было удобно представлять
содержательные объекты решаемой задачи. Ада-объектами могут быть, в
частности, ПОСТОЯННАЯ, ПЕРЕМЕННАЯ, ТИП, ИСКЛЮЧЕНИЕ, ПОДПРОГРАММА, ПАКЕТ,
ЗАДАЧА и РОДОВОЙ модуль.
Операторы предписывают действия, которые выполняются в порядке
следования операторов в тексте программы (если только операторы ВЫХОДА из
конструкта (exit), ВОЗВРАТА (return), ПЕРЕХОДА по метке (go to) или
возникновение исключения (исключительной ситуации) не заставят продолжить
исполнение с другого места).
Оператор ПРИСВАИВАНИЯ изменяет значение переменной.
ВЫЗОВ ПРОЦЕДУРЫ активизирует исполнение соответствующей процедуры после
связывания каждого фактического параметра (АРГУМЕНТА) с соответствующим
формальным параметром (ПАРАМЕТРОМ).
УСЛОВНЫЙ (if) и ВЫБИРАЮЩИЙ (case) операторы позволяют выбрать одну из
возможных вложенных последовательностей операторов в зависимости от значения
УПРАВЛЯЮЩЕГО ВЫРАЖЕНИЯ (условия).
Оператор ЦИКЛА - основной конструкт для описания повторяющихся
действий. Он предписывает повторять указанные в его теле действия до тех
пор, пока не будет выполнен оператор выхода, явно указанный в теле цикла,
или не станет истинным условие окончания цикла.
Блочный оператор (БЛОК) соединяет последовательность операторов с
непосредственно предшествующими ей объявлениями в единую ОБЛАСТЬ
ЛОКАЛИЗАЦИИ. Объявленные в ней объекты считаются ЛОКАЛЬНЫМИ в этой области.
Имеются операторы, обслуживающие взаимодействие асинхронных процессов.
При исполнении модуля могут возникать ошибочные ситуации, в которых
нельзя нормально продолжать работу. Например, возможно арифметическое
переполнение или попытка получить доступ к компоненте массива с
несуществующим индексом. Для обработки таких ИСКЛЮЧЕНИЙ (исключительных
ситуаций) в конце сегментов можно разместить специальные операторы РЕАКЦИИ
на исключение (exception). Имеются и явные операторы ВОЗБУЖДЕНИЯ исключений
(raise). Они включают в действие аппарат обработки возбужденного исключения.
2.2.3 Типы данных
Среди ада-объектов можно выделить ОБЪЕКТЫ ДАННЫХ (т.е. объекты, которым
разрешено играть роль данных по отношению к каким-либо операциям). Каждый
объект данных в Аде характеризуется определенным ТИПОМ. Своеобразие этого
языка в значительной степени связано именно с системой типов. Для тех, кто
работал только с Фортраном, Алголом и Бейсиком, многое в этой системе
окажется совершенно незнакомым. В частности, возможность определять новые
типы, отражающие особенности решаемой задачи. Для освоивших Паскаль адовские
типы привычнее, система адовских типов полнее и строже.
Тип, с одной стороны, - важнейшая компонента аппарата прогнозирования-
контроля. Приписывая объекту данных определенный тип, ограничивают его
возможное поведение. С другой стороны, зная тип, получают возможность это
поведение контролировать. Наконец, зная ограничения на возможное поведение,
можно рационально выделять память и другие ресурсы. С типом в Аде связывают
три основных ограничения.
Тип ограничивает, во-первых, ОБЛАСТЬ ЗНАЧЕНИЙ объекта; во-вторых,
НАБОР ОПЕРАЦИЙ, в которых объекту разрешено фигурировать; в-третьих, набор
допустимых для него ролей в этих операциях (второй операнд, результат и
т.п.).
Имеется четыре категории типов: СКАЛЯРНЫЕ (в том числе ПЕРЕЧИСЛЯЕМЫЕ и
ЧИСЛОВЫЕ), СОСТАВНЫЕ (в том числе РЕГУЛЯРНЫЕ (массивы) и КОМБИНИРОВАННЫЕ
(записи, структуры)), ССЫЛОЧНЫЕ (указатели) и ПРИВАТНЫЕ (закрытые,
защишенные - их представление для пользователя невидимо).