Ada Reference Manual (Ada 2022)
4.3.4 Delta Aggregates
Evaluating a (record or array) delta aggregate yields a composite value that starts with a copy of another value of the same type and then assigns to some (but typically not all) components of the copy.
Syntax
array_delta_aggregate ::=
(base_expression with delta array_component_association_list)
| '[' base_expression with delta array_component_association_list ']'
(base_expression with delta array_component_association_list)
| '[' base_expression with delta array_component_association_list ']'
Name Resolution Rules
The expected type for a record_delta_aggregate shall be a single descendant of a record type or record extension.
The expected type for an array_delta_aggregate shall be a single array type.
The expected type for the base_expression of any delta_aggregate is the type of the enclosing delta_aggregate.
The Name Resolution Rules and Legality Rules for each record_component_association of a record_delta_aggregate are as defined in 4.3.1.
For an array_delta_aggregate, the expected type for each discrete_choice in an array_component_association is the index type of the type of the delta_aggregate.
The expected type of the expression in an array_component_association is defined as for an array_component_association occurring within an array_aggregate of the type of the delta_aggregate.
Legality Rules
For an array_delta_aggregate, the array_component_association shall not use the box symbol <>, and the discrete_choice shall not be others.
For an array_delta_aggregate, the dimensionality of the type of the delta_aggregate shall be 1.
For an array_delta_aggregate, the base_expression and each expression in every array_component_association shall be of a nonlimited type.
Dynamic Semantics
The evaluation of a delta_aggregate begins with the evaluation of the base_expression of the delta_aggregate; then that value is used to create and initialize the anonymous object of the aggregate. The bounds of the anonymous object of an array_delta_aggregate and the discriminants (if any) of the anonymous object of a record_delta_aggregate are those of the base_expression. If a record_delta_aggregate is of a specific tagged type, its tag is that of the specific type; if it is of a class-wide type, its tag is that of the base_expression.
For a record_delta_aggregate, for each component associated with each record_component_association (in an unspecified order):
- if the associated component belongs to a variant, a check is made that the values of the discriminants are such that the anonymous object has this component. The exception Constraint_Error is raised if this check fails.
- the expression of the record_component_association is evaluated, converted to the nominal subtype of the associated component, and assigned to the component of the anonymous object.
For an array_delta_aggregate, for each discrete_choice of each array_component_association (in the order given in the enclosing discrete_choice_list and array_component_association_list, respectively) the discrete_choice is evaluated; for each represented index value (in ascending order, if the discrete_choice represents a range):
- the index value is converted to the index type of the array type.
- a check is made that the index value belongs to the index range of the anonymous object of the aggregate; Constraint_Error is raised if this check fails.
- the component expression is evaluated, converted to the array component subtype, and assigned to the component of the anonymous object identified by the index value.
Examples
Examples of use of delta aggregates in a postcondition:
procedure Twelfth (D : in out Date) -- see 3.8 for type Date
with Post => D = (D'Old with delta Day => 12);
with Post => D = (D'Old with delta Day => 12);
procedure The_Answer (V : in out Vector;
A, B : in Integer) -- see 3.6 for type Vector
with Post => V = (V'Old with delta A .. B => 42.0, V'First => 0.0);
A, B : in Integer) -- see 3.6 for type Vector
with Post => V = (V'Old with delta A .. B => 42.0, V'First => 0.0);
Examples where the base expression is nontrivial:
New_Cell : Cell := (Min_Cell (Head) with delta Value => 42);
-- see 3.10.1 for Cell and Head; 6.1 for Min_Cell
-- see 3.10.1 for Cell and Head; 6.1 for Min_Cell
A1 : Vector := ((0 => 1.0, 1 => 2.0, 2 => 3.0)
with delta Integer(Random * 2.0) => 14.2);
-- see 3.6 for declaration of type Vector
-- see 6.1 for declaration of Random
with delta Integer(Random * 2.0) => 14.2);
-- see 3.6 for declaration of type Vector
-- see 6.1 for declaration of Random
Tomorrow := ((Yesterday with delta Day => 12)
with delta Month => April); -- see 3.8
with delta Month => April); -- see 3.8
Example where the base expression is class-wide:
function Translate (P : Point'Class; X, Y : Real) return Point'Class is
(P with delta X => P.X + X,
Y => P.Y + Y); -- see 3.9 for declaration of type Point
(P with delta X => P.X + X,
Y => P.Y + Y); -- see 3.9 for declaration of type Point