• - использующие ТЕХТ_ Ю локальные процедуры

begin

  • - последовательность операторов процедуры G

endG;

В этом примере ПРЕОБРАЗОВАНИЕ и СЕРВИС являются субмодулями процедуры ВЕРШИНА, a G - субмодулем пакета СЕРВИС. Видимость в этом примере такая же, как и в предыдущем, с одним отличием: TEXT—10 используется только в G, поэтому соответствующий спецификатор совмест­ности написан для G, а не для процедуры ВЕРШИНА. В остальном види­мость идентификаторов в соответствующих телах программ обеих версий одинакова. Например, в соответствующем теле субмодуля G (непосредст­венно) видимы процедура ВЕРШИНА, тип ВЕЩЕСТВ, переменные Р и С, па­кет СЕРВИС и содержащиеся в нем именованное число ПИ и подпрограммы F и G.

  1. Порядок компиляции

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

Компилируемый модуль должен компилироваться после всех библио­течных модулей, указанных в его спецификаторе контекста. Вторичный мо­дуль, являющийся телом подпрограммы или пакета, должен компилиро­ваться после соответствующего библиотечного модуля. Любой субмодуль родительского компилируемого модуля должен компилироваться после него.

Компилирование, при котором в компилируемом модуле обнаружена ошибка, считается неудавшимся и никак не влияет на программную биб­лиотеку; то же самое относится и к перекомпиляции (никакой компилиру­емый модуль не может стать устаревшим вследствие такой перекомпиля­ции) .

Порядок компилирования компилируемых модулей программы дол­жен отвечать частичной упорядоченности, определенной приведенными вы­ше правилами.

Аналогичные правила применяются при перекомпиляции. На компили­руемый модуль потенциально влияет изменение любого библиотечного мо­дуля, упомянутого в его спецификаторе контекста. На вторичный модуль потенциально влияет изменение соответствующего библиотечного модуля. На субмодуль потенциально влияет изменение родительского компилиру­емого модуля. В результате успешной перекомпиляции компилируемого модуля все компилируемые модули, на которые потенциально влияет дан­ный, считаются устаревшими и должны перекомпилироваться, кроме тех, которые больше не нужны. Реализация может уменьшить стоимость пере­компиляции, если установит, что данные изменения не повлияли на модули, которые находились под потенциальным влиянием данного.

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

  1. Если прагма INLINE применяется к описанию подпрограммы в специ­фикации пакета, то открытая подстановка возможна, только если тело па­кета откомпилировано раньше модулей, вызывающих эту подпрограмму. В таком случае открытая подстановка создает зависимость вызывающего мо­дуля от тела пакета; компилятор должен распознавать такую зависимость при определении необходимости перекомпиляции. Если вызывающий мо­дуль компилируется раньше, чем тело пакета, то для таких вызовов прагма INLINE может игнорироваться компилятором (при этом может быть выда­но предупреждение о невозможности открытой подстановки). То же отно­сится и к раздельно компилируемой подпрограмме, к которой применена прагма INLINE.

  2. С целью оптимизации реализация может компилировать несколько модулей данной компиляции, создавая при этом дальнейшие зависимости между этими компилируемыми модулями. Эти зависимости должны учи­тываться компилятором для определения необходимых перекомпиляций.

  3. Реализация может требовать, чтобы описание настройки и соответст­вующее тело были частями одной и той же компиляции независимо от того, раздельно ли компилируется настраиваемый модуль, или он локален в дру­гом компилируемом модуле. Реализация может также требовать, чтобы субмодули настраиваемого модуля были частью одной и той же компи­ляции.

Примеры порядка компиляции:

  1. В примере 1 (см. 10.1.1) процедура КВАДРАТНОЕ_УРАВНЕНИЕ должна компилироваться после библиотечных пакетов TEXT—10 и ВЕЩЕСТВ-ОПЕРАЦИЙ, так как они упомянуты в спецификаторе совмест­ности процедуры.

  2. В примере 2 (см. 10.1.2) тело пакета ФОНД должно компилировать­ся после соответствующей спецификации пакета.

  3. В примере 2 (см. 10.1.2) спецификация пакета ФОНД должна компи­лироваться до процедуры ПРОЦЕССОР. С другой стороны, процедура ПРО­ЦЕССОР может компилироваться как до, так и после тела пакета ФОНД.

  4. В примере 3 (см. 10.2.1) процедура G должна компилироваться пос­ле пакета ТЕХТ_Ю, так как этот пакет упомянут в спецификаторе совмест­ности процедуры G. В то же время пакет ТЕХТ_Ю может компилироваться как до, так и после процедуры ВЕРШИНА.

  5. В примере 3 (см. 10.2.1) субмодули ПРЕОБРАЗОВАНИЕ и СЕРВИС должны компилироваться пбсле главной программы ВЕРШИНА. Субмодуль G должен компилироваться после его родительского модуля СЕРВИС.

Примечание. Для библиотечных пакетов из правил перекомпиляции следует, что тело пакета становится устаревшим после перекомпиляции соответствующей специ­фикации. Если новая спецификация пакета не требует задания тела (т. е. она не содер­жит описаний программных модулей), то перекомпиляции тела такого пакета не тре­буется. В любом случае устаревшее тело пакета не должно использоваться, и поэтому может быть удалено из программной библиотеки.

  1. Программная библиотека

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

Обычно входными данными для компилятора являются компилируе­мые модули (или модуль) и библиотечный файл. Последний используется для проверок и корректируется после успешного компилирования этих модулей.

Примечание. Компилируемые модули компиляции попадают в одну программную библиотеку. Возможно существование различных программных библиотек; в языке не определены правила их именования - это обеспечивается окружением системы про­граммирования .

Для создания программной библиотеки данной программы или данного семейст­ва программ следует ввести команды. Эти команды могут разрешать использование модулей из других программных библиотек. Наконец, для запроса состояний модулей в программной библиотеке также следует ввести команды. Форма этих команд не за­дана в определении языка.

  1. Предвыполнение библиотечных модулей

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

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

Порядок предвыполнения, отвечающий такому отношению упорядо­ченности, не всегда обеспечивает выполнение следующего требования: тело любого библиотечного модуля предвыполняется прежде любого другого компилируемого модуля, при предвыполнении которого необходимо пред­выполнение тела этого библиотечного модуля. Для указания необходимос­ти более раннего предвыполнения тел библиотечных модулей используется прагма ELABORATE (ПРЕДВЫПОЛНЕНИЕ). Эта прагма записывается в виде:

pragma ELABORATE (простое—имя_библиотечного_модуля

{, простое_ілмя—библиотечного _модуляУ);

Такие прагмы допустимы только непосредственно после специфика­тора контекста компилируемого модуля (до следующего за ним библиотеч­ного или вторичного модуля). Аргументы этой прагмы должны быть прос­тыми именами библиотечных модулей, упомянутых в спецификаторе кон­текста, и каждый такой библиотечный модуль должен иметь соответствую­щее тело. Эта прагма указывает, что тело библиотечного модуля должно предвыполняться до данного компилируемого модуля. Если данный ком­пилируемый модуль — субмодуль, то тело библиотечного модуля должно предвыполняться до тела библиотечного модуля-предка (субмодуля).

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

  1. Оптимизация программы

Компиляторы могут осуществлять оптимизацию предвыполнения опи­саний и выполнения операторов. В частности, компилятор может оптимизи­ровать программу, вычисляя определенные выражения помимо статичес­ких. Если одно из таких выражений, статических или нет, при вычислении привело бы к возбуждению исключения, то код этой части программы мо­жет быть заменен кодом возбуждения того же исключения; это справедли­во для исключений, возбуждаемых при вычислении имен и простых выра­жений (см. также разд. 11.6).

Компилятор может определить, что некоторые операторы или подпро­граммы никогда не будут выполняться, например, если их выполнение за­висит от условия, имеющего значение FALSE.В таком случае соответствую­щие части объективного машинного кода могут быть опущены. Такое пра­вило позволяет на уровне языка производить условную компиляцию.

Примечание. Выражение, вычисление которого может привести к возбуждению исключения, не обязательно представляет ошибку, если выражение находится в опера­торе или подпрограмме, которые никогда не выполняются. Компилятор может преду­преждать' программиста о потенциальной ошибке.

11. ИСКЛЮЧЕНИЯ

В этой главе определяются средства обработки ошибок или других ис­ключительных ситуаций, которые возникают при выполнении программы. Такая ситуация называется исключением. Возбуждение исключения следует понимать как прекращение нормального выполнения программы для обра­ботки соответствующей ситуации. Ответное действие на возбуждение ис­ключения называется обработкой исключения.

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

  1. Описания исключений

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

описание_исключения : : = список_идентификаторов: exception;

Описание исключения с несколькими идентификаторами эквивалентно последовательности единичных описаний с одним идентификатором (см. разд. 3.2). Каждое единичное описание исключения задает имя отличного от других исключения. В частности, если настраиваемый модуль содержит опи­сание исключения, то такие описания, неявно сгенерированные различными конкретизациями настройки, ссылаются на разные исключения (но все они имеют один и тот же идентификатор). Конкретное исключение, обозначен­ное именем, определяется во время компиляции и является одним и тем же, независимо от числа предвыполнений его описания. Следовательно, если описание исключения находится в рекурсивной подпрограмме, то имя ис­ключения обозначает одно и то же исключение для всех вызовов рекурсив­ной подпрограммы.

Следующие исключения предопределены в языке. Они возбуждаются при обнаружении описанных ниже ситуаций (в скобках дан перевод имени исключения на русский язык).

CONSTRAINT_ERROR (ОШИБКА_ОГРАНИЧЕНИЯ) Это исключение возбуждается в любой из следующих ситуаций: при попытке нарушить огра­ничение диапазона, ограничение индекса или ограничение дискриминанта; при попытке использовать компонент записи, не существующий для теку­щих значений дискриминанта; при попытке использовать именуемый ком­понент, индексируемый компонент, отрезок или атрибут объекта, обозна­ченного ссылочным значением, если этот объект не существует, поскольку ссылочное значение равно null.

NUMERIC_ERROR (ЧИСЛОВАЯ_ОШИБКА) Это исключение возбужда­ется при выполнении предопределенной числовой операции, которая не мо­жет выработать верный результат (для вещественных типов в пределах предписанной точности). Сюда относится также случай использования реа­лизацией предопределенных числовых операций для выполнения, вычисле­ния или предвыполнения некоторой конструкции. Данные в разд. 4.5.7 пра­вила определяют случаи, для которых от реализации не требуется возбужде­ния исключений при возникновении этой ошибочной ситуации (см. также разд. 11.6).