- использующие ТЕХТ_ Ю локальные процедуры
begin
- последовательность операторов процедуры G
endG;
В этом примере ПРЕОБРАЗОВАНИЕ и СЕРВИС являются субмодулями процедуры ВЕРШИНА, a G - субмодулем пакета СЕРВИС. Видимость в этом примере такая же, как и в предыдущем, с одним отличием: TEXT—10 используется только в G, поэтому соответствующий спецификатор совместности написан для G, а не для процедуры ВЕРШИНА. В остальном видимость идентификаторов в соответствующих телах программ обеих версий одинакова. Например, в соответствующем теле субмодуля G (непосредственно) видимы процедура ВЕРШИНА, тип ВЕЩЕСТВ, переменные Р и С, пакет СЕРВИС и содержащиеся в нем именованное число ПИ и подпрограммы F и G.
Порядок компиляции
Правила, определяющие порядок компилирования модулей, являются непосредственным следствием правил видимости и, в частности, того факта, что любой библиотечный модуль, упомянутый в спецификаторе контекста компилируемого модуля, видим в нем.
Компилируемый модуль должен компилироваться после всех библиотечных модулей, указанных в его спецификаторе контекста. Вторичный модуль, являющийся телом подпрограммы или пакета, должен компилироваться после соответствующего библиотечного модуля. Любой субмодуль родительского компилируемого модуля должен компилироваться после него.
Компилирование, при котором в компилируемом модуле обнаружена ошибка, считается неудавшимся и никак не влияет на программную библиотеку; то же самое относится и к перекомпиляции (никакой компилируемый модуль не может стать устаревшим вследствие такой перекомпиляции) .
Порядок компилирования компилируемых модулей программы должен отвечать частичной упорядоченности, определенной приведенными выше правилами.
Аналогичные правила применяются при перекомпиляции. На компилируемый модуль потенциально влияет изменение любого библиотечного модуля, упомянутого в его спецификаторе контекста. На вторичный модуль потенциально влияет изменение соответствующего библиотечного модуля. На субмодуль потенциально влияет изменение родительского компилируемого модуля. В результате успешной перекомпиляции компилируемого модуля все компилируемые модули, на которые потенциально влияет данный, считаются устаревшими и должны перекомпилироваться, кроме тех, которые больше не нужны. Реализация может уменьшить стоимость перекомпиляции, если установит, что данные изменения не повлияли на модули, которые находились под потенциальным влиянием данного.
Перекомпилирование субмодулей некоторого модуля на сам этот модуль никакого влияния не оказывает. Изменения в теле подпрограммы или пакета не влияют на другие компилируемые модули (кроме субмодулей этого тела), так как эти компилируемые модули имеют доступ только к спецификации подпрограммы или пакета. В реализации допустимы описанные ниже отступления от этого правила, связанные с открытыми подстановками, некоторыми оптимизациями, осуществляемыми компилятором, и некоторыми аспектами реализации настраиваемых программных модулей.
Если прагма INLINE применяется к описанию подпрограммы в спецификации пакета, то открытая подстановка возможна, только если тело пакета откомпилировано раньше модулей, вызывающих эту подпрограмму. В таком случае открытая подстановка создает зависимость вызывающего модуля от тела пакета; компилятор должен распознавать такую зависимость при определении необходимости перекомпиляции. Если вызывающий модуль компилируется раньше, чем тело пакета, то для таких вызовов прагма INLINE может игнорироваться компилятором (при этом может быть выдано предупреждение о невозможности открытой подстановки). То же относится и к раздельно компилируемой подпрограмме, к которой применена прагма INLINE.
С целью оптимизации реализация может компилировать несколько модулей данной компиляции, создавая при этом дальнейшие зависимости между этими компилируемыми модулями. Эти зависимости должны учитываться компилятором для определения необходимых перекомпиляций.
Реализация может требовать, чтобы описание настройки и соответствующее тело были частями одной и той же компиляции независимо от того, раздельно ли компилируется настраиваемый модуль, или он локален в другом компилируемом модуле. Реализация может также требовать, чтобы субмодули настраиваемого модуля были частью одной и той же компиляции.
Примеры порядка компиляции:
В примере 1 (см. 10.1.1) процедура КВАДРАТНОЕ_УРАВНЕНИЕ должна компилироваться после библиотечных пакетов TEXT—10 и ВЕЩЕСТВ-ОПЕРАЦИЙ, так как они упомянуты в спецификаторе совместности процедуры.
В примере 2 (см. 10.1.2) тело пакета ФОНД должно компилироваться после соответствующей спецификации пакета.
В примере 2 (см. 10.1.2) спецификация пакета ФОНД должна компилироваться до процедуры ПРОЦЕССОР. С другой стороны, процедура ПРОЦЕССОР может компилироваться как до, так и после тела пакета ФОНД.
В примере 3 (см. 10.2.1) процедура G должна компилироваться после пакета ТЕХТ_Ю, так как этот пакет упомянут в спецификаторе совместности процедуры G. В то же время пакет ТЕХТ_Ю может компилироваться как до, так и после процедуры ВЕРШИНА.
В примере 3 (см. 10.2.1) субмодули ПРЕОБРАЗОВАНИЕ и СЕРВИС должны компилироваться пбсле главной программы ВЕРШИНА. Субмодуль G должен компилироваться после его родительского модуля СЕРВИС.
Примечание. Для библиотечных пакетов из правил перекомпиляции следует, что тело пакета становится устаревшим после перекомпиляции соответствующей спецификации. Если новая спецификация пакета не требует задания тела (т. е. она не содержит описаний программных модулей), то перекомпиляции тела такого пакета не требуется. В любом случае устаревшее тело пакета не должно использоваться, и поэтому может быть удалено из программной библиотеки.
Программная библиотека
Правила языка требуют, чтобы компилятор одинаковым образом обрабатывал программу, состоящую из нескольких компилируемых модулей (и субмодулей) или из одного компилируемого модуля. Должен быть предусмотрен библиотечный файл, содержащий информацию о компилируемых модулях программной библиотеки, в который могут включаться символьные таблицы и другая информация, относящаяся к предыдущим компиляциям.
Обычно входными данными для компилятора являются компилируемые модули (или модуль) и библиотечный файл. Последний используется для проверок и корректируется после успешного компилирования этих модулей.
Примечание. Компилируемые модули компиляции попадают в одну программную библиотеку. Возможно существование различных программных библиотек; в языке не определены правила их именования - это обеспечивается окружением системы программирования .
Для создания программной библиотеки данной программы или данного семейства программ следует ввести команды. Эти команды могут разрешать использование модулей из других программных библиотек. Наконец, для запроса состояний модулей в программной библиотеке также следует ввести команды. Форма этих команд не задана в определении языка.
Предвыполнение библиотечных модулей
Перед выполнением главной программы все библиотечные модули, необходимые для главной программы, и тела этих модулей (если они есть) предвыполняются. Такими библиотечными модулями являются модули, упомянутые в спецификаторах совместности для главной программы, ее тела и субмодулей, а также модули, упомянутые в спецификаторах совместности для этих библиотечных модулей, их тел и субмодулей, и так далее, вплоть до получения транзитивного замыкания.
Предвыполнение таких библиотечных модулей и их тел производится в соответствии с частичной упорядоченностью, определяемой спецификаторами совместности (см. 10.3). Кроме того, библиотечный модуль, упомянутый в спецификаторе контекста для субмодуля, должен быть предвыполнен до тела библиотечного модуля-предка этого субмодуля,
Порядок предвыполнения, отвечающий такому отношению упорядоченности, не всегда обеспечивает выполнение следующего требования: тело любого библиотечного модуля предвыполняется прежде любого другого компилируемого модуля, при предвыполнении которого необходимо предвыполнение тела этого библиотечного модуля. Для указания необходимости более раннего предвыполнения тел библиотечных модулей используется прагма ELABORATE (ПРЕДВЫПОЛНЕНИЕ). Эта прагма записывается в виде:
pragma ELABORATE (простое—имя_библиотечного_модуля
{, простое_ілмя—библиотечного _модуляУ);
Такие прагмы допустимы только непосредственно после спецификатора контекста компилируемого модуля (до следующего за ним библиотечного или вторичного модуля). Аргументы этой прагмы должны быть простыми именами библиотечных модулей, упомянутых в спецификаторе контекста, и каждый такой библиотечный модуль должен иметь соответствующее тело. Эта прагма указывает, что тело библиотечного модуля должно предвыполняться до данного компилируемого модуля. Если данный компилируемый модуль — субмодуль, то тело библиотечного модуля должно предвыполняться до тела библиотечного модуля-предка (субмодуля).
Программа неправильна, если не может быть найден необходимый порядок предвыполнения (т. е. если существуют циклические зависимости). Предвыполнение компилируемых модулей программы в остальных случаях осуществляется в некотором порядке, который не определен в языке.
Оптимизация программы
Компиляторы могут осуществлять оптимизацию предвыполнения описаний и выполнения операторов. В частности, компилятор может оптимизировать программу, вычисляя определенные выражения помимо статических. Если одно из таких выражений, статических или нет, при вычислении привело бы к возбуждению исключения, то код этой части программы может быть заменен кодом возбуждения того же исключения; это справедливо для исключений, возбуждаемых при вычислении имен и простых выражений (см. также разд. 11.6).
Компилятор может определить, что некоторые операторы или подпрограммы никогда не будут выполняться, например, если их выполнение зависит от условия, имеющего значение FALSE.В таком случае соответствующие части объективного машинного кода могут быть опущены. Такое правило позволяет на уровне языка производить условную компиляцию.
Примечание. Выражение, вычисление которого может привести к возбуждению исключения, не обязательно представляет ошибку, если выражение находится в операторе или подпрограмме, которые никогда не выполняются. Компилятор может предупреждать' программиста о потенциальной ошибке.
11. ИСКЛЮЧЕНИЯ
В этой главе определяются средства обработки ошибок или других исключительных ситуаций, которые возникают при выполнении программы. Такая ситуация называется исключением. Возбуждение исключения следует понимать как прекращение нормального выполнения программы для обработки соответствующей ситуации. Ответное действие на возбуждение исключения называется обработкой исключения.
В описании исключения задается имя исключения. Исключение может быть возбуждено либо оператором возбуждения, либо каким-либо другим оператором или операцией, распространяющими исключение. При возбуждении исключения управление может быть передано обработчику исключения, написанному пользователем либо в конце оператора блока, либо в конце тел подпрограммы, пакета или задачного модуля.
Описания исключений
В описании исключения задается его имя. Это имя можно употреблять только в операторах возбуждения, обработчиках исключений и описаниях переименования.
описание_исключения : : = список_идентификаторов: exception;
Описание исключения с несколькими идентификаторами эквивалентно последовательности единичных описаний с одним идентификатором (см. разд. 3.2). Каждое единичное описание исключения задает имя отличного от других исключения. В частности, если настраиваемый модуль содержит описание исключения, то такие описания, неявно сгенерированные различными конкретизациями настройки, ссылаются на разные исключения (но все они имеют один и тот же идентификатор). Конкретное исключение, обозначенное именем, определяется во время компиляции и является одним и тем же, независимо от числа предвыполнений его описания. Следовательно, если описание исключения находится в рекурсивной подпрограмме, то имя исключения обозначает одно и то же исключение для всех вызовов рекурсивной подпрограммы.
Следующие исключения предопределены в языке. Они возбуждаются при обнаружении описанных ниже ситуаций (в скобках дан перевод имени исключения на русский язык).
CONSTRAINT_ERROR (ОШИБКА_ОГРАНИЧЕНИЯ) Это исключение возбуждается в любой из следующих ситуаций: при попытке нарушить ограничение диапазона, ограничение индекса или ограничение дискриминанта; при попытке использовать компонент записи, не существующий для текущих значений дискриминанта; при попытке использовать именуемый компонент, индексируемый компонент, отрезок или атрибут объекта, обозначенного ссылочным значением, если этот объект не существует, поскольку ссылочное значение равно null.
NUMERIC_ERROR (ЧИСЛОВАЯ_ОШИБКА) Это исключение возбуждается при выполнении предопределенной числовой операции, которая не может выработать верный результат (для вещественных типов в пределах предписанной точности). Сюда относится также случай использования реализацией предопределенных числовых операций для выполнения, вычисления или предвыполнения некоторой конструкции. Данные в разд. 4.5.7 правила определяют случаи, для которых от реализации не требуется возбуждения исключений при возникновении этой ошибочной ситуации (см. также разд. 11.6).