Руководство по Ada (Ada 2022)
4.3.4 Агрегаты Delta
Вычисление агрегата delta (для записей или массивов) даёт составное значение, которое начинается с копии другого значения того же типа, а затем присваивает некоторые (но обычно не все) компоненты копии.
Синтаксис
array_delta_aggregate ::=
(base_expression с delta array_component_association_list)
| '[' base_expression с delta array_component_association_list ']'
(base_expression с delta array_component_association_list)
| '[' base_expression с delta array_component_association_list ']'
Правила разрешения имён
Ожидаемый тип для record_delta_aggregate должен быть одиночным потомком типа записи или расширения записи.
Ожидаемый тип для array_delta_aggregate должен быть типом массива.
Правила разрешения имён и правила допустимости для каждого record_component_association агрегата record_delta_aggregate определены в 4.3.1.
Для array_delta_aggregate ожидаемый тип для каждого discrete_choice в array_component_association — это тип индекса типа delta_aggregate.
Ожидаемый тип expression в array_component_association определяется аналогично array_component_association в array_aggregate типа delta_aggregate.
Правила допустимости
Для array_delta_aggregate, array_component_association не должны использовать символ "квадратных скобок" <>, а discrete_choice не должны быть others.
Для array_delta_aggregate размерность типа delta_aggregate должна быть 1.
Для array_delta_aggregate, base_expression и каждое expression в каждой array_component_association должны быть типов без ограничений.
Динамическая семантика
Вычисление delta_aggregate начинается с вычисления base_expression delta_aggregate; затем это значение используется для создания и инициализации анонимного объекта aggregate. Границы анонимного объекта array_delta_aggregate и дискриминанты (если есть) анонимного объекта record_delta_aggregate — те же, что и у base_expression. Если record_delta_aggregate — это тип с меткой, его метка — метка конкретного типа; если это тип класса, его метка — метка base_expression.
Для record_delta_aggregate, для каждого компонента, связанного с каждой record_component_association (в произвольном порядке):
- если ассоциированный компонент принадлежит к variant, проверяется, что значения дискриминантов таковы, что анонимный объект имеет этот компонент. Исключение Constraint_Error возникает, если эта проверка не пройдёт.
- вычисляется expression record_component_association, преобразуется в номинальный подтип соответствующего компонента и присваивается компоненту анонимного объекта.
Для array_delta_aggregate, для каждого discrete_choice каждой array_component_association (в порядке, заданном в окружающем discrete_choice_list и array_component_association_list соответственно), discrete_choice вычисляется; для каждого представленного значения индекса (в возрастающем порядке, если discrete_choice представляет диапазон):
- значение индекса преобразуется в тип индекса типа массива.
- проверяется, принадлежит ли значение индекса диапазону индексов анонимного объекта aggregate; Constraint_Error генерируется, если проверка не пройдёт.
- вычисляется expression компонента, преобразуется в подтип компонента массива и присваивается компоненту анонимного объекта, идентифицируемого значением индекса.
Примеры
Примеры использования агрегатов delta в пост-условиях:
procedure Двенадцатое (D : in out Дата) -- см. 3.8 для типа Дата
с Post => D = (D'Old с delta День => 12);
с Post => D = (D'Old с delta День => 12);
procedure Ответ (V : in out Вектор;
A, B : in Целое) -- см. 3.6 для типа Вектор
с Post => V = (V'Old с delta A .. B => 42.0, V'Первое => 0.0);
A, B : in Целое) -- см. 3.6 для типа Вектор
с Post => V = (V'Old с delta A .. B => 42.0, V'Первое => 0.0);
Примеры, где выражение базы нетривиально:
Новая_Ячейка : Ячейка := (Минимальная_Ячейка (Голова) с delta Значение => 42);
-- см. 3.10.1 для Ячейка и Голова; 6.1 для Минимальная_Ячейка
-- см. 3.10.1 для Ячейка и Голова; 6.1 для Минимальная_Ячейка
A1 : Вектор := ((0 => 1.0, 1 => 2.0, 2 => 3.0)
с delta Целое(Случайное * 2.0) => 14.2);
-- см. 3.6 для объявления типа Вектор
-- см. 6.1 для объявления Случайное
с delta Целое(Случайное * 2.0) => 14.2);
-- см. 3.6 для объявления типа Вектор
-- см. 6.1 для объявления Случайное
Завтра := ((Вчера с delta День => 12)
с delta Месяц => Апрель); -- см. 3.8
с delta Месяц => Апрель); -- см. 3.8
Пример, где выражение базы — тип класса:
function Перевести (P : Точка'Класс; X, Y : Вещественный) return Точка'Класс is
(P с delta X => P.X + X,
Y => P.Y + Y); -- см. 3.9 для объявления типа Точка
(P с delta X => P.X + X,
Y => P.Y + Y); -- см. 3.9 для объявления типа Точка