Справочник Ada 2012
4.3.3 Массивные агрегаты
В array_aggregate значение указывается для каждого компонента массива, либо позиционно, либо по его индексу. Для positional_array_aggregate компоненты задаются в порядке возрастания индексов, а заключительное others, если оно есть, представляет все оставшиеся компоненты. Для named_array_aggregate компоненты идентифицируются значениями, охватываемыми discrete_choice.
Синтаксис
positional_array_aggregate ::=
(expression, expression {, expression})
| (expression {, expression}, others => expression)
| (expression {, expression}, others => <>)
(expression, expression {, expression})
| (expression {, expression}, others => expression)
| (expression {, expression}, others => <>)
Многомерный array_aggregate — это array_aggregate, записанный в виде n уровней вложенных array_aggregate (или, на нижнем уровне, эквивалентных string_literal). В многомерном случае (n >= 2) array_aggregate (или эквивалентные string_literal) на n-1 более низких уровнях называются подмассивными агрегатами окружающего многомерного array_aggregate. Выражения expression нижних уровней подмассивных агрегатов (или самого array_aggregate, если он одномерный) называются выражениями компонентов массива окружающего многомерного array_aggregate.
Правила разрешения имен
Ожидаемый тип для array_aggregate (который не является подмассивным агрегатом) должен быть типом одного массива. Тип компонента этого типа массива — ожидаемый тип для каждого выражения компонента массива array_aggregate.
Ожидаемый тип для каждого discrete_choice в любом discrete_choice_list named_array_aggregate — тип соответствующего индекса; соответствующий индекс для array_aggregate, который не является подмассивным агрегатом, — это первый индекс его типа; для (n–m)-мерного подмассивного агрегата внутри array_aggregate n-мерного типа соответствующий индекс — это индекс в позиции m+1.
Правила легитимности
array_aggregate n-мерного типа массива должен быть написан как n-мерный array_aggregate.
Выбор others разрешён для array_aggregate только в том случае, если для array_aggregate применим применимый ограничитель индексов. Применимый ограничитель индексов — это ограничение, предоставляемое некоторыми контекстами, где разрешён array_aggregate, который может быть использован для определения границ значения массива, заданного агрегатом. Каждый из следующих контекстов (и никакой другой) определяет применимый ограничитель индексов:
- Для explicit_actual_parameter, explicit_generic_actual_parameter, выражения оператора возврата, выражения возврата функции-выражения, выражения инициализации в object_declaration или default_expression (для параметра или компонента), когда номинальный подтип соответствующего формального параметра, формального параметра обобщения, объекта возврата функции, объекта возврата функции-выражения, объекта или компонента — ограниченный подтип массива, применимый ограничитель индексов — это ограничение подтипа;
- Для выражения expression оператора присваивания assignment_statement, где имя name обозначает переменную массива, применимый ограничитель индексов — это ограничение переменной массива;
- Для операнда qualified_expression, чья метка подтипа subtype_mark обозначает ограниченный подтип массива, применимый ограничитель индексов — это ограничение подтипа;
- Для выражения компонента expression в aggregate, если номинальный подтип компонента — это ограниченный подтип массива, применимый ограничитель индексов — это ограничение подтипа;
- Для выражения в скобках expression, применимый ограничитель индексов — это ограничение, если таковое есть, определённое для выражения expression;
- Для conditional_expression, применимый ограничитель индексов для каждого зависимого expression — это ограничение, если таковое есть, определённое для conditional_expression.
Применимый ограничитель индексов применяется к array_aggregate, который появляется в таком контексте, а также к любым подмассивным агрегатам. В случае явного фактического параметра explicit_actual_parameter (или default_expression) для вызова формального подпрограммы обобщения применимый ограничитель индексов не определён.
Список discrete_choice_list array_component_association разрешается содержать discrete_choice, который является нестатическим choice_expression или который является subtype_indication или range, которые определяют нестатический или нулевой диапазон, только если это единственный discrete_choice его discrete_choice_list, и в array_aggregate есть только одно array_component_association.
В named_array_aggregate, где все discrete_choice статические, не разрешается, чтобы два discrete_choice охватывали одно и то же значение (см. 3.8.1); если выбора others нет, discrete_choice вместе должны точно охватывать непрерывную последовательность значений соответствующего типа индексов.
END_OF_DOCUMENT_MARKER Нижний уровень подмножества многомерного массива_агрегат заданного типа массива разрешается быть строковой_литерал только в том случае, если тип компонента типа массива является типом символа; каждый символ такого строковой_литерал должен соответствовать определяющему_символьному_литерал типа компонента.
Статическая семантика
Подмножество, которое является строковой_литерал, эквивалентно такому, которое является позиционным_массива_агрегат той же длины, при этом каждое выражение является символьный_литерал для соответствующего символа строковой_литерал.
Динамическая семантика
Вычисление массива_агрегат заданного типа массива происходит в два этапа:
1.
Любые дискретные_выбор этого агрегата и его подмножеств вычисляются в произвольном порядке и преобразуются в соответствующий тип индекса;
2.
Выражения компонентов массива агрегата вычисляются в произвольном порядке, и их значения преобразуются в тип подтипа компонентов массива; выражение компонента массива вычисляется один раз для каждого связанного компонента.
Каждое выражение в массива_компонент_ассоциация определяет значение для связанных компонентов. Для массива_компонент_ассоциация с <>, связанные компоненты инициализируются значением по умолчанию компонента типа массива, если этот аспект был указан для типа массива; в противном случае они инициализируются по умолчанию, как и для самостоятельного объекта подтипа компонента (см. 3.3.1).
Границы диапазона индексов массива_агрегат (включая подмножество) определяются следующим образом:
- Для массива_агрегат с выбором others границы совпадают с границами соответствующего диапазона индексов из применимого ограничения индекса;
- Для позиционным_массива_агрегат (или эквивалентным строковой_литерал) без выбора others нижняя граница совпадает с нижней границей соответствующего диапазона индексов в применимом ограничении индекса, если определено, или с нижней границей соответствующего подтипа индекса, если нет; в любом случае верхняя граница определяется по нижней границе и количеству выражений (или длине строковой_литерал);
- Для именованным_массива_агрегат без выбора others границы определяются наименьшим и наибольшим значениями индексов, охватываемыми любым дискретным_списком_выборов.
Для массива_агрегат проверяется, совместим ли определенный диапазон индексов с соответствующим подтипом индекса.
Для массива_агрегат с выбором others проверяется, что ни одно выражение или <> не указано для значения индекса, выходящего за пределы границ, определенных применимым ограничением индекса.
Для многомерного массива_агрегат проверяется, что все подмножества, соответствующие одному индексу, имеют одинаковые границы.
Исключение Constraint_Error генерируется, если какой-либо из вышеперечисленных проверок завершается неудачей.
ПРИМЕЧАНИЯ
11 В массива_агрегат позиционная запись может быть использована только с двумя или более выражений; единственное выражение в скобках интерпретируется как выражение в скобках. именованным_массива_агрегат, такой как (1 => X), может быть использован для задания массива с одним компонентом.
Примеры
Примеры массивов агрегатов с позиционными ассоциациями:
(7, 9, 5, 1, 3, 2, 4, 8, 6, 0)
Table'(5, 8, 4, 1, others => 0) -- см. 3.6
Table'(5, 8, 4, 1, others => 0) -- см. 3.6
Примеры массивов агрегатов с именованными ассоциациями:
(1 .. 5 => (1 .. 8 => 0.0)) -- двумерный
(1 .. N => new Cell) -- N новых ячеек, в частности для N = 0
(1 .. N => new Cell) -- N новых ячеек, в частности для N = 0
Table'(2 | 4 | 10 => 1, others => 0)
Schedule'(Mon .. Fri => True, others => False) -- см. 3.6
Schedule'(Wed | Sun => False, others => True)
Vector'(1 => 2.5) -- однокомпонентный вектор
Schedule'(Mon .. Fri => True, others => False) -- см. 3.6
Schedule'(Wed | Sun => False, others => True)
Vector'(1 => 2.5) -- однокомпонентный вектор
Примеры двумерных массивов агрегатов:
-- Три агрегата для одного и того же значения подтипа Matrix(1..2,1..3) (см. 3.6):
((1.1, 1.2, 1.3), (2.1, 2.2, 2.3))
(1 => (1.1, 1.2, 1.3), 2 => (2.1, 2.2, 2.3))
(1 => (1 => 1.1, 2 => 1.2, 3 => 1.3), 2 => (1 => 2.1, 2 => 2.2, 3 => 2.3))
(1 => (1.1, 1.2, 1.3), 2 => (2.1, 2.2, 2.3))
(1 => (1 => 1.1, 2 => 1.2, 3 => 1.3), 2 => (1 => 2.1, 2 => 2.2, 3 => 2.3))
Примеры агрегатов в качестве начальных значений:
A : Table := (7, 9, 5, 1, 3, 2, 4, 8, 6, 0); -- A(1)=7, A(10)=0
B : Table := (2 | 4 | 10 => 1, others => 0); -- B(1)=0, B(10)=1
C : constant Matrix := (1 .. 5 => (1 .. 8 => 0.0)); -- C'Last(1)=5, C'Last(2)=8
B : Table := (2 | 4 | 10 => 1, others => 0); -- B(1)=0, B(10)=1
C : constant Matrix := (1 .. 5 => (1 .. 8 => 0.0)); -- C'Last(1)=5, C'Last(2)=8
D : Bit_Vector(M .. N) := (M .. N => True); -- см. 3.6
E : Bit_Vector(M .. N) := (others => True);
F : String(1 .. 1) := (1 => 'F'); -- однокомпонентный агрегат: тоже что и "F"
E : Bit_Vector(M .. N) := (others => True);
F : String(1 .. 1) := (1 => 'F'); -- однокомпонентный агрегат: тоже что и "F"
Пример массива агрегата с дефолтным выбором others и с применимым ограничением индекса, предоставленным вложенным агрегатом записи:
Buffer'(Size => 50, Pos => 1, Value => String'('x', others => <>)) -- см. 3.7