Справочник по Ada 95
4.3.3 Агрегаты массивов
В агрегате массива array_aggregate значение указывается для каждого компонента массива, либо позиционно, либо по его индексу. Для позиционного агрегата массива positional_array_aggregate компоненты задаются в порядке возрастания индексов, а заключительное ключевое слово others, если оно есть, представляет все оставшиеся компоненты. Для именованного агрегата массива named_array_aggregate компоненты идентифицируются значениями, охватываемыми discrete_choices.
Синтаксис
array_aggregate ::=
positional_array_aggregate | named_array_aggregate
positional_array_aggregate | named_array_aggregate
positional_array_aggregate ::=
(expression, expression {, expression})
| (expression {, expression}, others => expression)
(expression, expression {, expression})
| (expression {, expression}, others => expression)
named_array_aggregate ::=
(array_component_association {, array_component_association})
(array_component_association {, array_component_association})
array_component_association ::=
discrete_choice_list => expression
discrete_choice_list => expression
N-мерный array_aggregate — это агрегат, записанный как вложенные array_aggregate (или на нижнем уровне эквивалентные string_literals) по n уровням. В многомерном случае (n ≥ 2) array_aggregate (или эквивалентные string_literals) на n−1 нижних уровнях называются под-агрегатами охватывающего n-мерного array_aggregate. expressionы нижнего уровня под-агрегатов (или самого array_aggregate, если он одномерный) называются выражениями компонентов массива охватывающего n-мерного 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, expression оператора return_statement, выражения инициализации в object_declaration или default_expression (для параметра или компонента), когда номинальный подтип соответствующего формального параметра, формального параметра обобщённого параметра, результата функции, объекта или компонента является ограниченным подтипом массива, соответствующее ограничение индекса — это ограничение подтипа;
- Для expression оператора assignment_statement, где name обозначает переменную массива, соответствующее ограничение индекса — это ограничение переменной массива;
- Для операнда qualified_expression, подтип которого subtype_mark обозначает ограниченный подтип массива, соответствующее ограничение индекса — это ограничение подтипа;
- Для выражения компонента expression в aggregate, если номинальный подтип компонента — ограниченный подтип массива, соответствующее ограничение индекса — это ограничение подтипа;
- Для скобочного выражения expression, соответствующее ограничение индекса — это, если таковое существует, ограничение, определённое для expression.
Соответствующее ограничение индекса применяется к array_aggregate, который появляется в таком контексте, а также к любым под-агрегатам. В случае explicit_actual_parameter (или default_expression) для вызова формального обобщённого подпрограммы соответствующее ограничение индекса не определено.
discrete_choice_list array_component_association может иметь discrete_choice, который является нестатическим expression или является discrete_range, определяющим нестатический или пустой диапазон, только если это единственный discrete_choice в discrete_choice_list, и в array_aggregate присутствует только одна array_component_association.
В именованном агрегате массива named_array_aggregate с более чем одним discrete_choice два discrete_choice не могут охватывать одно и то же значение (см. 3.8.1); если выбора others нет, discrete_choices вместе должны точно охватывать непрерывную последовательность значений соответствующего типа индекса.
Под-агрегат нижнего уровня многомерного array_aggregate данного типа массива может быть string_literal только если тип компонентов массива — это тип символов; каждый символ такого string_literal должен соответствовать defining_character_literal типа компонентов.
Статическая семантика
Под-агрегат, являющийся string_literal, эквивалентен positional_array_aggregate той же длины, где каждое expression — это character_literal соответствующего символа string_literal.
Динамическая семантика
Вычисление array_aggregate заданного типа массива происходит в два этапа:
- 1.
- Любые discrete_choice этого агрегата и его под-агрегатов вычисляются в произвольном порядке и преобразуются к соответствующему типу индекса;
- 2.
- Выражения компонентов массива агрегата вычисляются в произвольном порядке, и их значения преобразуются к подтипу компонентов массива; выражение компонента массива вычисляется один раз для каждого соответствующего компонента.
Границы диапазона индекса array_aggregate (включая под-агрегат) определяются следующим образом:
- Для array_aggregate с выбором others границы — это границы соответствующего диапазона индекса из применимого ограничения индекса;
- Для позиционного агрегата массива positional_array_aggregate (или эквивалентного string_literal) без выбора others нижняя граница — это нижняя граница соответствующего диапазона индекса в применимом ограничении индекса, если оно определено, или нижняя граница соответствующего подтипа индекса, если нет; в любом случае верхняя граница определяется по нижней границе и количеству expression (или длине string_literal);
- Для именованного агрегата массива named_array_aggregate без выбора others границы определяются наименьшим и наибольшим значениями индексов, охватываемыми любым discrete_choice_list.
Для array_aggregate проверяется, что диапазон индексов, определённый его границами, совместим с соответствующим подтипом индекса.
Для массива с выбором others выполняется проверка, что ни один выражение не указан для значения индекса вне границ, определяемых соответствующим ограничением индекса.
Для многомерного массива выполняется проверка, что все подмассивы, соответствующие одному и тому же индексу, имеют одинаковые границы.
Если любая из вышеуказанных проверок завершится неудачей, генерируется исключение Constraint_Error.
ПРИМЕЧАНИЯ
10 В массиве позиционная нотация может использоваться только с двумя или более выражениями; одно выражение в скобках интерпретируется как выражение_в_скобках. Именованный_массив, такой как (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"