4.3.3 Array Aggregates
Language Design Principles
Syntax
{
AI95-00287-01}
{
AI12-0212-1}
{
AI12-0306-1}
positional_array_aggregate ::=
(
expression,
expression {,
expression})
| (
expression {,
expression},
others =>
expression)
| (
expression {,
expression},
others => <>)
| '['
expression {,
expression}[,
others =>
expression] ']'
| '['
expression {,
expression},
others => <> ']'
Ramification: Subaggregates do not have
a type. They correspond to part of an array. For example, with a matrix,
a subaggregate would correspond to a single row of the matrix. The definition
of "n-dimensional"
array_aggregate
applies to subaggregates as well as
aggregates
that have a type.
Name Resolution Rules
{
AI95-00287-01}
The expected type for an
array_aggregate
(that is not a subaggregate) shall be a single array type.
The
component type of this array type is the expected type for each array
component expression of the
array_aggregate.
Ramification: {
AI95-00287-01}
We already require a single array or record type or record extension
for an
aggregate.
The above rule requiring a single array type (and similar ones for record
and extension aggregates) resolves which kind of aggregate you have.
Legality Rules
Ramification: In an m-dimensional
array_aggregate
[(including a subaggregate)], where m >= 2, each of the
expressions
has to be an (m–1)-dimensional subaggregate.
{
AI12-0418-1}
An
others choice is allowed for an
array_aggregate
only if an
applicable index constraint applies to the
array_aggregate.
[An applicable index constraint is a constraint provided
by certain contexts that can be used to determine the bounds of the array
value specified by an
array_aggregate.]
Each of the following contexts (and none other) defines an applicable
index constraint:
{
AI95-00318-02}
{
AI12-0157-1}
For an
explicit_actual_parameter,
an
explicit_generic_actual_parameter,
the
expression
of a return statement, the return expression of an expression function,
the initialization expression in an
object_declaration,
or a
default_expression
[(for a parameter or a component)], when the nominal subtype of the corresponding
formal parameter, generic formal parameter, function return object, expression
function return object, object, or component is a constrained array subtype,
the applicable index constraint is the constraint of the subtype;
Reason: This case is broken out because
the constraint comes from the actual subtype of the variable (which is
always constrained) rather than its nominal subtype (which might be unconstrained).
For the operand of a
qualified_expression
whose
subtype_mark
denotes a constrained array subtype, the applicable index constraint
is the constraint of the subtype;
For a component
expression
in an
aggregate,
if the component's nominal subtype is a constrained array subtype, the
applicable index constraint is the constraint of the subtype;
Discussion: Here, the
array_aggregate
with
others is being used within a larger aggregate.
Discussion: RM83 omitted this case, presumably
as an oversight. We want to minimize situations where an
expression
becomes illegal if parenthesized.
Reason: This avoids generic contract
model problems, because only mode conformance is required when matching
actual subprograms with generic formal subprograms.
Discussion: We now allow a nonstatic
others choice even if there are other array component expressions
as well.
Ramification: This implies that each
component must be specified exactly once. See AI83-309.
Reason: {
AI05-0262-1}
This has to apply even if there is only one static
discrete_choice;
a single choice has to represent a contiguous range (a
subtype_mark
with a static predicate might represent a discontiguous set of values).
If the (single) choice is a dynamic subtype, we don't need to make this
check as no predicates are allowed (see
3.2.4)
and thus the range has to be contiguous.
Static Semantics
{
AI12-0061-1}
The subtype (and nominal subtype) of an index parameter is the corresponding
index subtype.
Dynamic Semantics
1.
{
AI12-0212-1}
{
AI12-0250-1}
{
AI22-0006-1}
Each
iterator_specification
is elaborated (in an arbitrary order)
and an iteration
is performed solely to determine a
maximum count
for the number of values
conditionally produced
by the iteration
(see 5.5
and 5.5.2); all of these counts are
combined to determine the overall length of the array, and ultimately
the limits on the bounds of the array (defined
below);
2.
{
AI12-0212-1}
{
AI12-0250-1}
{
AI12-0327-1}
{
AI22-0006-1}
A second iteration is performed for each of the
iterator_specifications,
in the order given in the
aggregate,
and for each value conditionally produced by the iteration
(see 5.5 and 5.5.2),
the associated
expression
is evaluated, its value is converted to the component subtype of the
array type, and used to define the value of the next component of the
array starting at the low bound and proceeding sequentially toward the
high bound.
As part of this second iteration, a A
check is made that
it the
second iteration results in
the same number
of elements as an array length no greater
than the maximum determined by the first iteration; Constraint_Error
is raised if this check
fails.
This check is performed before any attempt to access any nonexistent
element of the array object.
To be honest: {
AI12-0212-1}
{
AI12-0250-1}
{
AI22-0006-1}
Constraint_Error should be raised no later than
when the iterations exceed the maximum array length; memory that doesn't
belong to the aggregate temporary should not be overwritten.
Reason: {
AI22-0006-1}
The last sentence ensures that Constraint_Error
is raised no later than when the iterations exceed the maximum array
length; memory that doesn't belong to the aggregate temporary should
not be overwritten.
1.
Any
discrete_choices
of this aggregate and of its subaggregates are evaluated in an arbitrary
order, and converted to the corresponding index type;
2.
The array component expressions of the aggregate are evaluated in an
arbitrary order and their values are converted to the component subtype
of the array type; an array component expression is evaluated once for
each associated component.
Ramification: Subaggregates are not separately
evaluated. The conversion of the value of the component expressions to
the component subtype might raise Constraint_Error.
{
AI05-0005-1}
We don't need to say that <> is evaluated once for each component,
as <> means that each component is
initialized by default.
That means that the actions defined for default initialization are applied
to each component individually. Initializing one component by default
and copying that to the others would be an incorrect implementation in
general (although it might be OK if the default initialization is known
to be constant).
Ramification: Taken together with the
preceding rule that “The array component expressions of the aggregate
are evaluated in an arbitrary order”, this implies that an index
parameter of an
iterated_component_association
can take on its values in an arbitrary order. This is different from
other constructs, such as a
loop_statement.
In contrast, a loop parameter of an
iterated_component_association
takes its values in the order defined by the iteration, the same as a
loop_statement.
The
bounds of the index range of an
array_aggregate
[(including a subaggregate)] are determined as follows:
For an
array_aggregate
with an
others choice, the bounds are those of the corresponding
index range from the applicable index constraint;
For a
positional_array_aggregate
[(or equivalent
string_literal)]
without an
others choice, the lower bound is that of the corresponding
index range in the applicable index constraint, if defined, or that of
the corresponding index subtype, if not; in either case, the upper bound
is determined from the lower bound and the number of
expressions
[(or the length of the
string_literal)];
Reason: We don't need to say that each
index value has to be covered exactly once, since that is a ramification
of the general rule on
aggregates
that each component's value has to be specified exactly once.
For an
array_aggregate,
a check is made that the index range defined by its bounds is compatible
with the corresponding index subtype.
Discussion: In RM83, this was phrased
more explicitly, but once we define "compatibility" between
a range and a subtype, it seems to make sense to take advantage of that
definition.
Ramification: The definition of compatibility
handles the special case of a null range, which is always compatible
with a subtype. See AI83-00313.
{
AI05-0037-1}
For an
array_aggregate
with an
others choice, a check is made that no
expression
or <> is specified for an index value outside the bounds determined
by the applicable index constraint.
Discussion: RM83 omitted this case, apparently
through an oversight. AI83-00309 defines this as a dynamic check, even
though other Ada 83 rules ensured that this check could be performed
statically. We now allow an others choice to be dynamic, even
if it is not the only choice, so this check now needs to be dynamic,
in some cases. Also, within a generic unit, this would be a nonstatic
check in some cases.
For a multidimensional
array_aggregate,
a check is made that all subaggregates that correspond to the same index
have the same bounds.
Ramification: No array bounds “sliding”
is performed on subaggregates.
Reason: If sliding were performed, it
would not be obvious which subaggregate would determine the bounds of
the corresponding index.
The exception Constraint_Error
is raised if any of the above checks fail.
Implementation Permissions
Discussion: For instance, if the type
of the aggregate is constrained, the implementation can (but does not
have to) calculate the expected length from the constraint.
NOTE 2 {
AI12-0061-1}
An index parameter is a constant object (see
3.3).
Examples
Examples of array
aggregates with positional associations:
(7, 9, 5, 1, 3, 2, 4, 8, 6, 0)
Table'(5, 8, 4, 1,
others => 0) --
see 3.6
Examples of array
aggregates with named associations:
{
AI12-0306-1}
(1 .. 5 => (1 .. 8 => 0.0)) --
two-dimensional
[1 .. N =>
new Cell] --
N new cells, in particular for N = 0
{
AI12-0306-1}
Table'(2 | 4 | 10 => 1,
others => 0)
Schedule'(Mon .. Fri => True,
others => False) --
see 3.6
Schedule'[Wed | Sun => False,
others => True]
Vector'(1 => 2.5) --
single-component vector
Examples of two-dimensional
array aggregates:
--
Three aggregates for the same value of subtype Matrix(1..2,1..3) (see 3.6):
{
AI12-0306-1}
((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)]
Examples of aggregates
as initial values:
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
D : Bit_Vector(M .. N) := (M .. N => True); --
see 3.6
E : Bit_Vector(M .. N) := (
others => True);
F : String(1 .. 1) := (1 => 'F'); --
a one component aggregate: same as "F"
{
AI12-0061-1}
G :
constant Matrix :=
(
for I
in 1 .. 4 =>
(
for J
in 1 .. 4 =>
(
if I=J
then 1.0
else 0.0))); --
Identity matrix
{
AI12-0312-1}
Empty_Matrix :
constant Matrix := []; --
A matrix without elements
{
AI95-00433-01}
Example of an array aggregate with defaulted others choice and with
an applicable index constraint provided by an enclosing record aggregate:
{
AI12-0178-1}
Buffer'(Size => 50, Pos => 1, Value => ('x',
others => <>)) --
see 3.7
Incompatibilities With Ada 83
In
Ada 95, no applicable index constraint is defined for a parameter in
a call to a generic formal subprogram; thus, some aggregates that are
legal in Ada 83 are illegal in Ada 95. For example:
subtype S3 is String (1 .. 3);
...
generic
with function F (The_S3 : in S3) return Integer;
package Gp is
I : constant Integer := F ((1 => '!', others => '?'));
-- The aggregate is legal in Ada 83, illegal in Ada 95.
end Gp;
This change eliminates generic contract model
problems.
Extensions to Ada 83
We now allow "named
with others" aggregates in all contexts where there is an applicable
index constraint, effectively eliminating what was RM83-4.3.2(6). Sliding
never occurs on an aggregate with others, because its bounds come from
the applicable index constraint, and therefore already match the bounds
of the target.
The legality of an others choice is no
longer affected by the staticness of the applicable index constraint.
This substantially simplifies several rules, while being slightly more
flexible for the user. It obviates the rulings of AI83-00244 and AI83-00310,
while taking advantage of the dynamic nature of the "extra values"
check required by AI83-00309.
Named array aggregates are permitted even if
the index type is descended from a formal scalar type. See
4.9
and AI83-00190.
Wording Changes from Ada 83
We now separate named and positional array aggregate
syntax, since, unlike other aggregates, named and positional associations
cannot be mixed in array aggregates (except that an others choice
is allowed in a positional array aggregate).
We have also reorganized the presentation to
handle multidimensional and one-dimensional aggregates more uniformly,
and to incorporate the rulings of AI83-00019, AI83-00309, etc.
Extensions to Ada 95
Wording Changes from Ada 95
Inconsistencies With Ada 2005
{
AI05-0037-1}
Correction: Fixed so the check for components
outside of the array applies to both
expressions
and <>s. As <> was a new feature in Ada 2005, there should
be little existing code that depends on a <> component that is
specified outside of the array (and that is nonsense anyway, that a compiler
is likely to detect even without an explicit language rule disallowing
it).
Wording Changes from Ada 2005
Inconsistencies With Ada 2012
{
AI05-0084-1}
Corrigendum: Fixed so that the Default_Component_Value
(if any) is used to initialize components specified with <>. This
is what users would expect, and all Ada 2012 implementation known at
the time of this writing initialize with the Default_Component_Value,
so it is unlikely that anyone will be affected by this inconsistency.
Extensions to Ada 2012
{
AI12-0212-1}
An
array_aggregate
can be surrounded by brackets rather than parentheses. This allows consistent
writing of zero- and one-component positional array aggregates, and is
consistent with the syntax for writing container aggregates.
Wording Changes from Ada 2012
{
AI05-0157-1}
Corrigendum: Added expression functions to the contexts that provide
an applicable index constraint, because expression functions are handled
separately in static semantics and legality rules.
Inconsistencies With Ada 2022
{
AI22-0006-1}
Corrigendum: When an
array_aggregate
is evaluated in two steps, the number of elements produced must match
for both steps, otherwise Constraint_Error is raised. In original Ada
2022, the first count only has to be larger than the second count, and
filters are not considered. So for unusual programs where iteration operates
differently or filters change answers when re-evaluated, the aggregate
may have worked as expected in original Ada 2022, while in Ada 202y Constraint_Error
will be raised. As this is a new Ada 2022 feature, and iterators and
filters usually always get the same result each time they are executed
on unchanged data, we don't expect this to occur in practice.
Wording Changes from Ada 2022
{
AI22-0008-1}
Corrigendum: Eliminated the dependence on
the nominal subtype from the wording defining the applicable index constraint
for the body_expression
of a delta_aggregate.
The nominal subtype of a delta_aggregate
wasn't defined at all in original Ada 2022, and for Ada 202y it is defined
in terms of the subtype of the body_expression
(which would make the definition circular without this rewording).
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe