Справочник по Ada 2012
4.9 Статические выражения и статические типы
Некоторые выражения скалярного или строкового типа определены как статические. Аналогично, некоторые дискретные диапазоны определены как статические, а также некоторые скалярные и строковые типы — как статические типы. Статический означает определяемый на этапе компиляции, используя объявленные свойства или значения сущностей программы.
Статическое выражение — это скалярное или строковое выражение, которое является одним из следующих:
- числовой литерал numeric_literal;
- литерал строки string_literal статического строкового типа;
- имя name, обозначающее объявление именованного числа или статической константы;
- вызов функции function_call, чьё имя функции или префикс функции name или префикс prefix статически обозначает статическую функцию, и чьи фактические параметры, если таковые имеются (приведенные явно или по умолчанию), являются статическими выражениями;
- ссылка на атрибут attribute_reference, обозначающая скалярное значение, и чей префикс prefix обозначает статический скалярный тип;
- ссылка на атрибут attribute_reference, чей префикс prefix статически обозначает статически ограниченный массив или массивный тип, а атрибут attribute_designator — First, Last или Length с необязательной размерностью;
- преобразование типа type_conversion, чей маркер типа subtype_mark обозначает статический скалярный тип, а операнд — статическое выражение;
- квалифицированное выражение qualified_expression, чей маркер типа subtype_mark обозначает статический (скалярный или строковый) тип, а операнд — статическое выражение;
- проверка на принадлежность, где тестируемое выражение simple_expression является статическим выражением, а список выбора на принадлежность membership_choice_list состоит только из выборов на принадлежность membership_choice, которые являются либо статическими выражениями выбора simple_expression, статическими диапазонами range или маркерами типа subtype_mark, которые обозначают статический (скалярный или строковый) тип;
- форма управления короткого замыкания, оба отношения которой — статические выражения;
- условное выражение conditional_expression, все условия которого, выражения выбора и зависимые выражения являются статическими выражениями;
- статическое выражение в скобках.
Имена name статически обозначают сущность, если они обозначают сущность и:
- Это прямое имя direct_name, развернутое имя или литерал символа character_literal, и оно обозначает объявление, отличное от переименования renaming_declaration; или
- Это ссылка на атрибут attribute_reference, чей префикс prefix статически обозначает некоторую сущность; или
- Это обозначает переименование renaming_declaration с именем name, которое статически обозначает переименованную сущность.
Статическая функция — одна из следующих:
- предопределённый оператор, чьи типы параметра и результата — все скалярные типы, ни один из которых не является потомком формальных скалярных типов;
- предопределённый оператор конкатенации, чьё результирующий тип — строковый тип;
- литерал перечисления;
- определённый в языке атрибут, являющийся функцией, если префикс prefix обозначает статический скалярный тип, и если типы параметра и результата — скалярные.
В любом случае, формальный подпрограмма-параметр не является статической функцией.
Статическая константа — это константный вид, объявленный полным объявлением константы или объявлением переименования объекта object_renaming_declaration со статическим номинальным типом, имеющая значение, определённое статическим скалярным выражением или статическим строковым выражением, длина которого не превышает максимальную длину string_literal в реализации.
Статический диапазон — это диапазон range, границы которого являются статическими выражениями, или ссылка на атрибут диапазона range_attribute_reference, эквивалентная такому диапазону range. Статический discrete_range — это диапазон, являющийся статическим диапазоном или указанием типа subtype_indication, определяющего статический скалярный тип. Базовый диапазон скалярного типа — статический диапазон, за исключением случаев, когда тип является потомком формального скалярного типа.
Статический тип — это либо статический скалярный тип, либо статический строковый тип. Статический скалярный тип — это неограниченный скалярный тип, тип которого не является потомком формального типа, или ограниченный скалярный тип, образованный путём наложения совместимого статического ограничения на статический скалярный тип. Статический строковый тип — это неограниченный строковый тип, подтип индекса и подтип компонента которого статичны, или ограниченный строковый тип, образованный путём наложения совместимого статического ограничения на статический строковый тип. В любом случае, подтип формального объекта-параметра с режимом in out и подтип результата формальной функции-параметра не являются статическими. Кроме того, тип не является статическим, если к нему применяются спецификации Dynamic_Predicate.
Разные виды статических ограничений определяются следующим образом:
- Нулевое ограничение всегда является статическим;
- Ограничение скалярного типа является статическим, если оно не имеет ограничения диапазона range_constraint или имеет статический диапазон;
- Ограничение индекса является статическим, если каждый дискретный диапазон discrete_range является статическим, и каждый подтип индекса соответствующего массива является статическим;
- Ограничение дискриминанты является статическим, если каждое выражение expression ограничения является статическим, и подтип каждой дискриминанты является статическим.
В любом случае, ограничение первого подтипа скалярного формального типа не является ни статическим, ни нулевым.
Подтип является статически ограниченным, если он ограничен и его ограничение является статическим. Объект является статически ограниченным, если его номинальный подтип статически ограничен или если он статическая строковая константа.
Правила легальности
Выражение является статически неоцениваемым, если оно является частью:
- правого операнда формы статического короткого замыкания, значение которой определяется его левым операндом; или
- зависимого выражения if_expression, чей ассоциированный condition является статическим и равен False; или
- условия или зависимого выражения if_expression, где условие, соответствующее хотя бы одному предшествующему зависимому выражению if_expression, является статическим и равно True; или
- зависимого выражения case_expression, чей expression выбора является статическим и чьё значение не покрывается соответствующим списком дискретного выбора discrete_choice_list; или
- a choice_simple_expression (or a simple_expression of a range that occurs as a membership_choice of a membership_choice_list) of a static membership test that is preceded in the enclosing membership_choice_list by another item whose individual membership test (see 4.5.2) statically yields True.
Статическое выражение вычисляется во время компиляции, за исключением случаев, когда оно статически не вычисляется. Вычисление статического выражения во время компиляции выполняется точно, без выполнения Overflow_Checks. Для статического выражения, которое вычисляется:
- Выражение является недопустимым, если его вычисление не проходит языковой проверку, отличную от Overflow_Check. Для целей этого вычисления предполагается, что политика утверждения равна Check.
- Если выражение не является частью более крупного статического выражения и ожидается, что выражение будет иметь один определенный тип, то его значение должно быть в пределах базового диапазона его ожидаемого типа. В противном случае значение может быть произвольно большим или маленьким.
- Если выражение имеет тип universal_real, а его ожидаемый тип является типом десятичной фиксированной точки, то его значение должно быть кратным small типа десятичной точки. Это ограничение не применяется, если ожидаемый тип является потомком формального скалярного типа (или соответствующего фактического типа в экземпляре).
В дополнение к местам, где обычно применяются Правила законности (см. 12.3), вышеуказанные ограничения также применяются в частях экземпляра универсального блока.
Требования к реализации
Для действительного статического выражения, которое не является частью более крупного статического выражения и чей ожидаемый тип не является потомком формального типа, реализация должна округлять или усекать значение (в соответствии с атрибутом Machine_Rounds ожидаемого типа) до ближайшего машинного числа ожидаемого типа; если значение находится точно посередине между двумя машинными числами, то выполняемое округление определяется реализацией. Если ожидаемый тип является потомком формального типа или если статическое выражение появляется в теле экземпляра универсального блока, а соответствующее выражение не является статическим в соответствующем универсальном блоке, то специальное округление или усечение не требуется — применяются обычные правила точности (см. Приложение G).
Рекомендации по реализации
Для действительного статического выражения, которое не является частью более крупного статического выражения и чей ожидаемый тип не является потомком формального типа, округление должно быть таким же, как стандартное округление для целевой системы.
ПРИМЕЧАНИЯ
28 Выражение может быть статическим, даже если оно встречается в контексте, где статичность не требуется.
29 Статическое (или динамическое) type_conversion от действительного типа к целому типу выполняет округление. Если значение операнда находится точно посередине между двумя целыми числами, округление выполняется от нуля.
Примеры
Примеры статических выражений:
1 + 1 -- 2
abs(-10)*3 -- 30
abs(-10)*3 -- 30
Kilo : constant := 1000;
Mega : constant := Kilo*Kilo; -- 1_000_000
Long : constant := Float'Digits*2;
Mega : constant := Kilo*Kilo; -- 1_000_000
Long : constant := Float'Digits*2;
Half_Pi : constant := Pi/2; -- см. 3.3.2
Deg_To_Rad : constant := Half_Pi/90;
Rad_To_Deg : constant := 1.0/Deg_To_Rad; -- эквивалентно 1.0/((3.14159_26536/2)/90)
Deg_To_Rad : constant := Half_Pi/90;
Rad_To_Deg : constant := 1.0/Deg_To_Rad; -- эквивалентно 1.0/((3.14159_26536/2)/90)