Skip to main content

4.3 Aggregates

danger

This Reference Manual output has not been verified, and may contain omissions or errors. Report any problems on the tracking issue

1

[ An aggregate combines component values into a composite value of an array type, record type, or record extension.]

1.a/5

Term entry: aggregate — construct used to define a value of a composite type by specifying the values of the components of the type

Syntax

2/5

aggregate ::=
record_aggregate | extension_aggregate | array_aggregate
| delta_aggregate | container_aggregate

Name Resolution Rules

3/5

The expected type for an aggregate shall be a single array type, a single type with the Aggregate aspect specified, or a single descendant of a record type or of a record extension.

3.a
discussion

See 8.6, “The Context of Overload Resolution” for the meaning of “shall be a single ... type”.

3.b/3
ramification

There are additional rules for each kind of aggregate. These aggregate rules are additive; a legal expression needs to satisfy all of the applicable rules. That means the rule given here must be satisfied even when it is syntactically possible to tell which specific kind of aggregate is being used.

3.c/5
reason

Generally, we don't want to look in aggregates to resolve them. For instance, Ada 95 allowed array types to match extension_aggregates, even though those have to be record types. Thus, we allow any record type with any visible (nondiscriminant) components to match an aggregate, even though only delta_aggregates allow private types or private extensions. Similarly, we allow any container type to match an aggregate, even though only container_aggregates allow container types.

Legality Rules

4/5

A record_aggregate or extension_aggregate shall not be of a class-wide type.

4.a
ramification

When the expected type in some context is class-wide, an aggregate has to be explicitly qualified by the specific type of value to be created, so that the expected type for the aggregate itself is specific.

4.b
discussion

We used to disallow aggregates of a type with unknown discriminants. However, that was unnecessarily restrictive in the case of an extension aggregate, and irrelevant to a record aggregate (since a type that is legal for a record aggregate could not possibly have unknown discriminants) and to an array aggregate (the only specific types that can have unknown discriminants are private types, private extensions, and types derived from them).

4.c/5
reason

We don't mention delta_aggregates, as those can get the specific type from the object represented by the base_expression (possibly at run time). We don't mention array_aggregates, as those cannot even be of a tagged type, so being class-wide is impossible.

Dynamic Semantics

5

For the evaluation of an aggregate, an anonymous object is created and values for the components or ancestor part are obtained (as described in the subsequent subclause for each kind of the aggregate) and assigned into the corresponding components or ancestor part of the anonymous object. Obtaining the values and the assignments occur in an arbitrary order. The value of the aggregate is the value of this object.

5.a
discussion

The ancestor part is the set of components inherited from the ancestor type. The syntactic category ancestor_part is the expression or subtype_mark that specifies how the ancestor part of the anonymous object should be initialized.

5.b
ramification

The assignment operations do the necessary value adjustment, as described in 7.6. Note that the value as a whole is not adjusted — just the subcomponents (and ancestor part, if any). 7.6 also describes when this anonymous object is finalized.

5.c

If the ancestor_part is a subtype_mark the Initialize procedure for the ancestor type is applied to the ancestor part after default-initializing it, unless the procedure is abstract, as described in 7.6. The Adjust procedure for the ancestor type is not called in this case, since there is no assignment to the ancestor part as a whole.

6

If an aggregate is of a tagged type, a check is made that its value belongs to the first subtype of the type. Constraint_Error is raised if this check fails.

6.a
ramification

This check ensures that no values of a tagged type are ever outside the first subtype, as required for inherited dispatching operations to work properly (see 3.4). This check will always succeed if the first subtype is unconstrained. This check is not extended to untagged types to preserve upward compatibility.

Extensions to Ada 83

6.b

We now allow extension_aggregates.

Wording Changes from Ada 83

6.c

We have adopted new wording for expressing the rule that the type of an aggregate shall be determinable from the outside, though using the fact that it is nonlimited record (extension) or array.

6.d

An aggregate now creates an anonymous object. This is necessary so that controlled types will work (see 7.6).

Incompatibilities With Ada 95

6.e/2

In Ada 95, a limited type is not considered when resolving an aggregate. Since Ada 2005 now allows limited aggregates, we can have incompatibilities. For example:

6.f/2

type Lim is limited record Comp: Integer; end record; 6.g/2 type Not_Lim is record Comp: Integer; end record; 6.h/2 procedure P(X: Lim); procedure P(X: Not_Lim); 6.i/2 P((Comp => 123)); -- Illegal in Ada 2005, legal in Ada 95

6.j/2

The call to P is ambiguous in Ada 2005, while it would not be ambiguous in Ada 95 as the aggregate could not have a limited type. Qualifying the aggregate will eliminate any ambiguity. This construction would be rather confusing to a maintenance programmer, so it should be avoided, and thus we expect it to be rare.

Extensions to Ada 95

6.k/2

Aggregates can be of a limited type.

Incompatibilities With Ada 2012

6.l/5

We now allow types with the Aggregate aspect specified ("container types"), as well as private types and extensions descended from a record type or extension, to match all forms of aggregate. These types are only allowed for new types of aggregate (container_aggregates for the Aggregate aspect, and delta_aggregates for private types), but, consistent with other forms of aggregate, we do not look at the form of the aggregate to determine resolution. This can be incompatible in usually unlikely cases, where overloading of a container or private type with a type that was previously allowed in aggregates makes an existing call ambiguous. Unfortunately, Ada.Containers.Vectors has a number of such overloadings for Insert, Append, Prepend, and "&", so the problem may appear for any element type of a Vector that allows aggregates. For instance, if My_Vector is an instance of Ada.Containers.Vectors with an element type of Not_Lim as defined above, and V is an object of My_Vector.Vector, then My_Vector.Append (V, (Comp => 123)); will be illegal in Ada 2022 and legal in Ada 2012. This can easily be fixed by qualifying the aggregate with the correct type.

4.3.1 Record Aggregates

1

[In a record_aggregate, a value is specified for each component of the record or record extension value, using either a named or a positional association.]

Syntax

2

record_aggregate ::= (record_component_association_list)

3

record_component_association_list ::=
record_component_association {, record_component_association}
| null record

4/2

record_component_association ::=
[component_choice_list =>] expression
| component_choice_list => <>

5/5

component_choice_list ::=
component_selector_name {'|' component_selector_name}
| others

6

A record_component_association is a named component association if it has a component_choice_list; otherwise, it is a positional component association. Any positional component associations shall precede any named component associations. If there is a named association with a component_choice_list of others, it shall come last.

6.a
discussion

These rules were implied by the BNF in an early version of the RM9X, but it made the grammar harder to read, and was inconsistent with how we handle discriminant constraints. Note that for array aggregates we still express some of the rules in the grammar, but array aggregates are significantly different because an array aggregate is either all positional (with a possible others at the end), or all named.

7

In the record_component_association_list for a record_aggregate, if there is only one association, it shall be a named association.

7.a/3
reason

Otherwise, the construct would be interpreted as a parenthesized expression. This is considered a syntax rule, since it is relevant to overload resolution. We choose not to express it with BNF so we can share the definition of record_component_association_list in both record_aggregate and extension_aggregate.

7.b
ramification

The record_component_association_list of an extension_aggregate does not have such a restriction.

Name Resolution Rules

8/2

The expected type for a record_aggregate shall be a single record type or record extension.

8.a
ramification

This rule is used to resolve whether an aggregate is an array_aggregate or a record_aggregate. The presence of a with is used to resolve between a record_aggregate and an extension_aggregate.

9/5

For the record_component_association_list of a record_aggregate, all components of the composite value defined by the aggregate are needed[; for the association list of an extension_aggregate, only those components not determined by the ancestor expression or subtype are needed (see 4.3.2).] Each component_selector_name in a record_component_association of a record_aggregate or extension_aggregate shall denote a needed component [(including possibly a discriminant)]. Each component_selector_name in a record_component_association of a record_delta_aggregate (see 4.3.4) shall denote a nondiscriminant component of the type of the aggregate.

9.a
ramification

For the association list of a record_aggregate, “needed components” includes every component of the composite value, but does not include those in unchosen variants (see AI83-309). If there are variants, then the value specified for the discriminant that governs them determines which variant is chosen, and hence which components are needed.

9.b

If an extension defines a new known_discriminant_part, then all of its discriminants are needed in the component association list of an extension aggregate for that type, even if the discriminants have the same names and types as discriminants of the type of the ancestor expression. This is necessary to ensure that the positions in the record_component_association_list are well defined, and that discriminants that govern variant_parts can be given by static expressions.

9.c/5
reason

We don't define “needed” for record_delta_aggregates so that there is no completeness requirement. But that means that we need to ensure that the rules using “needed” doesn't appear to apply to record_delta_aggregates, and we also need Legality Rules to prevent giving the same component twice and giving components from two different variants.

9.d/5

Term entry: needed component — component of a record type or record extension that is required to have its value specified within a given aggregate

10

The expected type for the expression of a record_component_association is the type of the associated component(s); the associated component(s) are as follows:

11
  • For a positional association, the component [(including possibly a discriminant)] in the corresponding relative position (in the declarative region of the type), counting only the needed components;
11.a
ramification

This means that for an association list of an extension_aggregate, only noninherited components are counted to determine the position.

11.b/3

For a derived type (including type extensions), the order of declaration is defined in 3.4, “Derived Types and Classes”. In particular, all discriminants come first, regardless of whether they are defined for the parent type or are newly added to the derived type.

12
  • For a named association with one or more component_selector_names, the named component(s);
  • 13
  • For a named association with the reserved word others, all needed components that are not associated with some previous association.

Legality Rules

14

If the type of a record_aggregate is a record extension, then it shall be a descendant of a record type, through one or more record extensions (and no private extensions).

15/5

A record_component_association_list shall be null record only if the list occurs in a record_aggregate or extension_aggregate, and there are no components needed for that list.

15.a
ramification

For example, "(null record)" is a record_aggregate for a null record type. Similarly, "(T'(A) with null record)" is an extension_aggregate for a type defined as a null record extension of T.

15.b/3

If no components are needed and null record is not used, the record_component_association must necessarily be others => <>, as that is the only record_component_association that does not require an associated component.

16/5

For a record_aggregate or extension_aggregate, each record_component_association other than an others choice with a <> shall have at least one associated component, and each needed component shall be associated with exactly one record_component_association. For a record_delta_aggregate, each component_selector_name of each component_choice_list shall denote a distinct nondiscriminant component of the type of the aggregate.

16.a/2
ramification

These rules apply to an association with an others choice with an expression. An others choice with a <> can match zero components or several components with different types.

16.b/2
reason

Without these rules, there would be no way to know what was the expected type for the expression of the association. Note that some of the rules do not apply to <> associations, as we do not need to resolve anything. We allow others => <> to match no components as this is similar to array aggregates. That means that (others => <>) always represents a default-initialized record or array value.

16.c/4
This paragraph was deleted.
16.d
ramification

The rule that requires at least one associated component for each record_component_association implies that there can be no extra associations for components that don't exist in the composite value, or that are already determined by the ancestor expression or subtype of an extension_aggregate.

16.e

The second part of the first sentence ensures that no needed components are left out, nor specified twice.

16.1/5

If a record_component_association with an expression has two or more associated components, all of them shall be of the same type, or all of them shall be of anonymous access types whose subtypes statically match. In addition, Legality Rules are enforced separately for each associated component.

16.f/4
discussion

AI83-00244 also requires that the expression shall be legal for each associated component. Ada 95 omitted this wording, as it was thought that all cases of difference had been eliminated. That probably was true, but Ada 2005 reintroduced cases where the types match but the legality differs. For example:

16.g/4

type Rec (D : access Integer) is record F : access Integer; end record; 16.h/5 begin declare X : aliased Integer; R : Rec := (D | F => X'Access); -- Legal for D, illegal for F

16.i/4

There are additional ways for this to happen; because of cases like the above we require that the Legality Rules are checked individually for each associated component.

17/5

For a record_aggregate or extension_aggregate, if a variant_part P is nested within a variant V that is not selected by the discriminant value governing the variant_part enclosing V, then there is no restriction on the discriminant governing P. Otherwise, the value of the discriminant that governs P shall be given by a static expression, or by a nonstatic expression having a constrained static nominal subtype. In this latter case of a nonstatic expression, there shall be exactly one discrete_choice_list of P that covers each value that belongs to the nominal subtype and satisfies the predicates of the subtype, and there shall be at least one such value.

17.a
ramification

This expression might either be given within the aggregate itself, or in a constraint on the parent subtype in a derived_type_definition for some ancestor of the type of the aggregate.

17.a.1/5

This means that in the nonstatic value case, the (static) subtype cannot have a null range.

17.1/2

A record_component_association for a discriminant without a default_expression shall have an expression rather than <>.

17.b/2
reason

A discriminant must always have a defined value, but <> means uninitialized for a discrete type unless the component has a default value.

17.2/5

A record_component_association of the record_component_association_list of a record_delta_aggregate shall not:

17.3/5
17.c/5
ramification

A record_delta_aggregate cannot use positional notation; all choices shall be named choices.

17.6/5 17.7/5

For a record_delta_aggregate, no two component_selector_names shall denote components declared within different variants of the same variant_part.

Dynamic Semantics

18

The evaluation of a record_aggregate consists of the evaluation of the record_component_association_list.

19/5

For the evaluation of a record_component_association_list, any per-object constraints (see 3.8) for components specified in the association list are elaborated and any expressions are evaluated and converted to the subtype of the associated component. Any constraint elaborations and expression evaluations (and conversions) occur in an arbitrary order, except that the expression for a discriminant is evaluated (and converted) prior to the elaboration of any per-object constraint that depends on it, which in turn occurs prior to the evaluation and conversion of the expression for the component with the per-object constraint. If the value of a discriminant that governs a selected variant_part is given by a nonstatic expression, and the evaluation of that expression yields a value that does not belong to the nominal subtype of the expression, then Constraint_Error is raised.

19.a
ramification

The conversion in the first rule might raise Constraint_Error.

19.b
discussion

This check in the first rule presumably happened as part of the dependent compatibility check in Ada 83.

19.c/5
ramification

The test on the value of the discriminant can only fail if the value is outside the base range of its type, does not satisfy the (static) predicates of the subtype (possible when the predicate is disabled), or is an invalid representation. This is a rule similar to that used for case statements. As with case statements, this is not a “check”; it cannot be Suppressed.

19.1/2

For a record_component_association with an expression, the expression defines the value for the associated component(s). For a record_component_association with <>, if the component_declaration has a default_expression, that default_expression defines the value for the associated component(s); otherwise, the associated component(s) are initialized by default as for a stand-alone object of the component subtype (see 3.3.1).

20

The expression of a record_component_association is evaluated (and converted) once for each associated component.

20.a/3
ramification

We don't need similar language for <>, as we're considering the value of <> for each individual component. Each component has its own default expression or its own default initialization (they can be different for each component; the components even could have different types), and each one has to be evaluated. So there is no need to repeat that.

21/5

NOTE By the rules given above, for a record_aggregate with positional associations, expressions specifying discriminant values appear first and in the same order as their corresponding discriminant_specifications, since the known_discriminant_part occurs first in the declaration of the type.

Examples

22

Example of a record aggregate with positional associations:

23

(4, July, 1776) -- see 3.8

24

Examples of record aggregates with named associations:

25

(Day => 4, Month => July, Year => 1776) (Month => July, Day => 4, Year => 1776) 26 (Disk, Closed, Track => 5, Cylinder => 12) -- see 3.8.1 (Unit => Disk, Status => Closed, Cylinder => 9, Track => 1)

27/2

Examples of component associations with several choices:

28

(Value => 0, Succ|Pred => new Cell'(0, null, null)) -- see 3.10.1 29 -- The allocator is evaluated twice: -- Succ and Pred designate different cells 29.1/2 (Value => 0, Succ|Pred => <>) -- see 3.10.1 29.2/2 -- Succ and Pred will be set to null

30

Examples of record aggregates for tagged types (see 3.9 and 3.9.1):

31

Expression'(null record) Literal'(Value => 0.0) Painted_Point'(0.0, Pi/2.0, Paint => Red)

Extensions to Ada 83

31.a

Null record aggregates may now be specified, via "(null record)". However, this syntax is more useful for null record extensions in extension aggregates.

Wording Changes from Ada 83

31.b

Various AIs have been incorporated (AI83-00189, AI83-00244, and AI83-00309). In particular, Ada 83 did not explicitly disallow extra values in a record aggregate. Now we do.

Extensions to Ada 95

31.c/2

<> can be used in place of an expression in a record_aggregate, default initializing the component.

Wording Changes from Ada 95

31.d/2

Limited record_aggregates are allowed (since all kinds of aggregates can now be limited, see 4.3).

Incompatibilities With Ada 2005

31.e/3
correction

Corrected wording so that the rule for discriminants governing variant_parts was not effectively circular. The change makes a few aggregates where a nonstatic discriminant governs an empty variant_part illegal. However, most Ada implementations already enforce some version of the new rule and already reject these aggregates. So it is unlikely that any incompatibility will be noticed in practice.

Extensions to Ada 2005

31.f/3
correction

Fixed the wording so that others => <> can be used in place of null record. This is needed to avoid a generic contract issue for generic bodies: we do not want to have to assume the worst to disallow others => <> if the record type might be a null record.

31.g/3
correction

We now allow multiple components with anonymous access types to be specified with a single component association. This is to be consistent with the capabilities of a named access type.

Extensions to Ada 2012

31.h/5

The value of a discriminant that governs a variant_part in an aggregate can be nonstatic if the nominal subtype of the discriminant expression is static and all possible values select a single variant.

Wording Changes from Ada 2012

31.i/4

Corrigendum: We explicitly say that the Legality Rules have to be rechecked for each component individually. This seems obvious, but as the AARM note 4.3.1 (16.c) appeared to say that this was not necessary, and since we explicitly state this sort of thing for generic instances, it seemed better to be explicit.

31.j/5

Made wording changes for delta_aggregates.

4.3.2 Extension Aggregates

1

[An extension_aggregate specifies a value for a type that is a record extension by specifying a value or subtype for an ancestor of the type, followed by associations for any components not determined by the ancestor_part.]

Language Design Principles

1.a

The model underlying this syntax is that a record extension can also be viewed as a regular record type with an ancestor "prefix". The record_component_association_list corresponds to exactly what would be needed if there were no ancestor/prefix type. The ancestor_part determines the value of the ancestor/prefix.

Syntax

2

extension_aggregate ::=
(ancestor_part with record_component_association_list)

3

ancestor_part ::= expression | subtype_mark

Name Resolution Rules

4/2

The expected type for an extension_aggregate shall be a single type that is a record extension. If the ancestor_part is an expression, it is expected to be of any tagged type.

4.a
reason

We could have made the expected type T'Class where T is the ultimate ancestor of the type of the aggregate, or we could have made it even more specific than that. However, if the overload resolution rules get too complicated, the implementation gets more difficult and it becomes harder to produce good error messages.

4.b/3
ramification

This rule is additive with the rule given in 4.3. That means the 4.3 rule must be satisfied even though it is always syntactically possible to tell that something is an extension aggregate rather than another kind of aggregate. Specifically, that means that an extension aggregate is ambiguous if the context is overloaded on array and/or untagged record types, even though those are never legal contexts for an extension aggregate. Thus, this rule acts more like a Legality Rule than a Name Resolution Rule.

Legality Rules

5/3

If the ancestor_part is a subtype_mark, it shall denote a specific tagged subtype. If the ancestor_part is an expression, it shall not be dynamically tagged. The type of the extension_aggregate shall be a descendant of the type of the ancestor_part (the ancestor type), through one or more record extensions (and no private extensions). If the ancestor_part is a subtype_mark, the view of the ancestor type from which the type is descended (see 7.3.1) shall not have unknown discriminants.

5.a/2
reason

The expression cannot be dynamically tagged to prevent implicit "truncation" of a dynamically-tagged value to the specific ancestor type. This is similar to the rules in 3.9.2.

5.1/5

If the type of the ancestor_part is limited and at least one component is needed in the record_component_association_list, then the ancestor_part shall not have an operative constituent expression (see 4.4) that is a call to a function with an unconstrained result subtype.

5.b/3
reason

This restriction simplifies implementation, because it ensures that either the caller or the callee knows the size to allocate for the aggregate. Without this restriction, information from both caller and callee would have to be combined to determine the appropriate size.

5.c/3

The (F(...) with null record) case is exempt from this rule, because such extension aggregates are created internally for inherited functions returning null-extension types — we can't very well make those illegal. Moreover, we don't need the rule for null extensions, as the result can simply use the space returned by the function call.

5.d/5

The mention of “operative constituents” means that constructs like parenthesized expressions, qualified_expressions, and conditional_expressions are ignored when enforcing this rule.

Static Semantics

6

For the record_component_association_list of an extension_aggregate, the only components needed are those of the composite value defined by the aggregate that are not inherited from the type of the ancestor_part, plus any inherited discriminants if the ancestor_part is a subtype_mark that denotes an unconstrained subtype.

Dynamic Semantics

7

For the evaluation of an extension_aggregate, the record_component_association_list is evaluated. If the ancestor_part is an expression, it is also evaluated; if the ancestor_part is a subtype_mark, the components of the value of the aggregate not given by the record_component_association_list are initialized by default as for an object of the ancestor type. Any implicit initializations or evaluations are performed in an arbitrary order, except that the expression for a discriminant is evaluated prior to any other evaluation or initialization that depends on it.

8/3

If the type of the ancestor_part has discriminants and the ancestor_part is not a subtype_mark that denotes an unconstrained subtype, then a check is made that each discriminant determined by the ancestor_part has the value specified for a corresponding discriminant, if any, either in the record_component_association_list, or in the derived_type_definition for some ancestor of the type of the extension_aggregate. Constraint_Error is raised if this check fails.

8.a
ramification

Corresponding and specified discriminants are defined in 3.7. The rules requiring static compatibility between new discriminants of a derived type and the parent discriminant(s) they constrain ensure that at most one check is required per discriminant of the ancestor expression.

8.b/3

The check needs to be made any time that the ancestor is constrained; the source of the discriminants or the constraints is irrelevant.

9/5

NOTE 1 By the rules given in 4.3.1, if all components of the value of the extension_aggregate are determined by the ancestor_part, then the record_component_association_list will be simply null record.

10

NOTE 2 If the ancestor_part is a subtype_mark, then its type can be abstract. If its type is controlled, then as the last step of evaluating the aggregate, the Initialize procedure of the ancestor type is called, unless the Initialize procedure is abstract (see 7.6).

Examples

11

Examples of extension aggregates (for types defined in 3.9.1):

12

Painted_Point'(Point with Red) (Point'(P) with Paint => Black) 13/5

(Expression with Left => new Literal'(Value => 1.2), Right => new Literal'(Value => 3.4)) Addition'(Binop with null record) -- presuming Binop is of type Binary_Operation

Extensions to Ada 83

13.a

The extension aggregate syntax is new.

Incompatibilities With Ada 95

13.b/2
correction

Amendment Eliminated implicit “truncation” of a dynamically tagged value when it is used as an ancestor expression. If an aggregate includes such an expression, it is illegal in Ada 2005. Such aggregates are thought to be rare; the problem can be fixed with a type conversion to the appropriate specific type if it occurs.

Wording Changes from Ada 95

13.c/2

Limited extension_aggregates are allowed (since all kinds of aggregates can now be limited, see 4.3).

Inconsistencies With Ada 2005

13.d/3
correction

An extension_aggregate with an ancestor_part whose discriminants are constrained and inherited might now raise Constraint_Error if the aggregate's type is constrained, while it was OK in Ada 2005. In almost all cases, this will make no difference as the constraint will be checked by the immediately following use of the aggregate, but it is possible to compare such an aggregate for equality; in this case, no exception would be raised by Ada 2005, while Ada 2012 will raise Constraint_Error. This should be very rare, and having the possibility means that the representation of the aggregate type has to be able to support unconstrained values of the type, even if the first subtype is constrained and no such objects can be created any other way.

Incompatibilities With Ada 2005

13.e/3
correction

A limited unconstrained ancestor expression that is a function call is now illegal unless the extension part is null. Such aggregates were first introduced in Ada 2005 and are very complex to implement as they must be built-in-place with an unknown size; as such, it is unlikely that they are implemented correctly in existing compilers and thus not often used in existing code.

13.f/3
correction

An ancestor_part that is a subtype with unknown discriminants is now explicitly illegal. Such a subtype should not be used to declare an object, and the ancestor_part acts like an object. The Ada 95 rules did not disallow such cases, so it is possible that code exists that uses such an ancestor, but this should be rare.

Wording Changes from Ada 2012

13.g/5

Rewrote a Legality Rule to use the new term “operative constituent” in order to reduce duplication of text about ignoring parenthesized expressions and similar constructs.

4.3.3 Array Aggregates

1

[In an array_aggregate, a value is specified for each component of an array, either positionally or by its index.] For a positional_array_aggregate, the components are given in increasing-index order, with a final others, if any, representing any remaining components. For a named_array_aggregate, the components are identified by the values covered by the discrete_choices.

Language Design Principles

1.a/1

The rules in this subclause are based on terms and rules for discrete_choice_lists defined in 3.8.1, “Variant Parts and Discrete Choices”. For example, the requirements that others come last and stand alone are found there.

Syntax

2/5

array_aggregate ::=
positional_array_aggregate | null_array_aggregate | named_array_aggregate

3/5

positional_array_aggregate ::=
(expression, expression {, expression})
| (expression {, expression}, others => expression)
| (expression {, expression}, others => <>)
| '[' expression {, expression}[, others => expression] ']'
| '[' expression {, expression}, others => <> ']'

3.1/5

null_array_aggregate ::= '[' ']'

4/5

named_array_aggregate ::=
(array_component_association_list)
| '[' array_component_association_list ']'

4.1/5

array_component_association_list ::=
array_component_association {, array_component_association}

5/5

array_component_association ::=
discrete_choice_list => expression
| discrete_choice_list => <>
| iterated_component_association

5.1/5

iterated_component_association ::=
for defining_identifier in discrete_choice_list => expression
| for iterator_specification => expression

6

An n-dimensional array_aggregate is one that is written as n levels of nested array_aggregates (or at the bottom level, equivalent string_literals). For the multidimensional case (n >= 2) the array_aggregates (or equivalent string_literals) at the n–1 lower levels are called subaggregates of the enclosing n-dimensional array_aggregate. The expressions of the bottom level subaggregates (or of the array_aggregate itself if one-dimensional) are called the array component expressions of the enclosing n-dimensional array_aggregate.

6.a
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.

6.b

To be honest: An others choice is the reserved word others as it appears in a positional_array_aggregate or as the discrete_choice of the discrete_choice_list in an array_component_association.

6.1/5

The defining_identifier of an iterated_component_association declares an index parameter, an object of the corresponding index type.

Name Resolution Rules

7/2

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.

7.a/2
ramification

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.

8

The expected type for each discrete_choice in any discrete_choice_list of a named_array_aggregate is the type of the corresponding index; the corresponding index for an array_aggregate that is not a subaggregate is the first index of its type; for an (n–m)-dimensional subaggregate within an array_aggregate of an n-dimensional type, the corresponding index is the index in position m+1.

Legality Rules

9/5

An array_aggregate of an n-dimensional array type shall be written as an n-dimensional array_aggregate, or as a null_array_aggregate.

9.a
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.

10/5

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:

11/4
  • 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;
  • 12
  • For the expression of an assignment_statement where the name denotes an array variable, the applicable index constraint is the constraint of the array variable;
12.a
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).

13
  • 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;
  • 14
  • 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;
14.a
discussion

Here, the array_aggregate with others is being used within a larger aggregate.

14.1/5
15.a
discussion

RM83 omitted this case, presumably as an oversight. We want to minimize situations where an expression becomes illegal if parenthesized.

15.1/5
16

The applicable index constraint applies to an array_aggregate that appears in such a context, as well as to any subaggregates thereof. In the case of an explicit_actual_parameter (or default_expression) for a call on a generic formal subprogram, no applicable index constraint is defined.

16.a
reason

This avoids generic contract model problems, because only mode conformance is required when matching actual subprograms with generic formal subprograms.

17/5

The discrete_choice_list of an array_component_association (including an iterated_component_association) is allowed to have a discrete_choice that is a nonstatic choice_expression or that is a subtype_indication or range that defines a nonstatic or null range, only if it is the single discrete_choice of its discrete_choice_list, and either there is only one array_component_association in the enclosing array_component_association_list or the enclosing aggregate is an array_delta_aggregate[, not an array_aggregate].

17.a
discussion

We now allow a nonstatic others choice even if there are other array component expressions as well.

17.b/5
ramification

We allow multiple dynamic choices in array_delta_aggregates, but only one dynamic choice per association even in that case.

17.1/5

Either all or none of the array_component_associations of an array_component_association_list shall be iterated_component_associations with an iterator_specification.

18/3

In a named_array_aggregate where all discrete_choices are static, no two discrete_choices are allowed to cover the same value (see 3.8.1); if there is no others choice, the discrete_choices taken together shall exactly cover a contiguous sequence of values of the corresponding index type.

18.a
ramification

This implies that each component must be specified exactly once. See AI83-309.

18.b/3
reason

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.

19

A bottom level subaggregate of a multidimensional array_aggregate of a given array type is allowed to be a string_literal only if the component type of the array type is a character type; each character of such a string_literal shall correspond to a defining_character_literal of the component type.

Static Semantics

20

A subaggregate that is a string_literal is equivalent to one that is a positional_array_aggregate of the same length, with each expression being the character_literal for the corresponding character of the string_literal.

20.a/5

To be honest: This is true even in cases where there is no corresponding legal positional_array_aggregate.

20.1/5

The subtype (and nominal subtype) of an index parameter is the corresponding index subtype.

Dynamic Semantics

20.2/5

For an array_aggregate that contains only array_component_associations that are iterated_component_associations with iterator_specifications, evaluation proceeds in two steps:

20.3/5

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 produced by the iteration; 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);
20.4/5

2.
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. A check is made that the second iteration results in an array length no greater than the maximum determined by the first iteration; Constraint_Error is raised if this check fails.
20.b/5

To be honest: 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.

21/5

The evaluation of any other array_aggregate of a given array type proceeds in two steps:

22

1.
Any discrete_choices of this aggregate and of its subaggregates are evaluated in an arbitrary order, and converted to the corresponding index type;
23

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.
23.a
ramification

Subaggregates are not separately evaluated. The conversion of the value of the component expressions to the component subtype might raise Constraint_Error.

23.b/3

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).

23.1/4

Each expression in an array_component_association defines the value for the associated component(s). For an array_component_association with <>, the associated component(s) are initialized to the Default_Component_Value of the array type if this aspect has been specified for the array type; otherwise, they are initialized by default as for a stand-alone object of the component subtype (see 3.3.1).

23.2/5

During an evaluation of the expression of an iterated_component_association with a discrete_choice_list, the value of the corresponding index parameter is that of the corresponding index of the corresponding array component. During an evaluation of the expression of an iterated_component_association with an iterator_specification, the value of the loop parameter of the iterator_specification is the value produced by the iteration (as described in 5.5.2).

23.c/5
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.

24

The bounds of the index range of an array_aggregate [(including a subaggregate)] are determined as follows:

25
  • For an array_aggregate with an others choice, the bounds are those of the corresponding index range from the applicable index constraint;
  • 26
  • 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)];
  • 26.1/5
  • For a null_array_aggregate, bounds for each dimension are determined as for a positional_array_aggregate without an others choice that has no expressions for each dimension;
26.a/5
reason

We need a separate rule to describe what happens for a multidimensional null_array_aggregate; we could've combined the single-dimension case with the positional_array_aggregate rule.

26.2/5
27.a
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.

28

For an array_aggregate, a check is made that the index range defined by its bounds is compatible with the corresponding index subtype.

28.a
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.

28.b
ramification

The definition of compatibility handles the special case of a null range, which is always compatible with a subtype. See AI83-00313.

29/3

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.

29.a
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.

30

For a multidimensional array_aggregate, a check is made that all subaggregates that correspond to the same index have the same bounds.

30.a
ramification

No array bounds “sliding” is performed on subaggregates.

30.b
reason

If sliding were performed, it would not be obvious which subaggregate would determine the bounds of the corresponding index.

31

The exception Constraint_Error is raised if any of the above checks fail.

Implementation Permissions

32/5

When evaluating iterated_component_associations for an array_aggregate that contains only iterated_component_associations with iterator_specifications, the first step of evaluating an iterated_component_association can be omitted if the implementation can determine the maximum number of values by some other means.

32.a/5
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.

33/5

NOTE 1 In an array_aggregate delimited by parentheses, positional notation can only be used with two or more expressions; a single expression in parentheses is interpreted as a parenthesized expression. An array_aggregate delimited by square brackets can be used to specify an array with a single component.

34/5

NOTE 2 An index parameter is a constant object (see 3.3).

Examples

35

Examples of array aggregates with positional associations:

36

(7, 9, 5, 1, 3, 2, 4, 8, 6, 0) Table'(5, 8, 4, 1, others => 0) -- see 3.6

37

Examples of array aggregates with named associations:

38/5

(1 .. 5 => (1 .. 8 => 0.0)) -- two-dimensional [1 .. N => new Cell] -- N new cells, in particular for N = 0 39/5

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

40

Examples of two-dimensional array aggregates:

41

-- Three aggregates for the same value of subtype Matrix(1..2,1..3) (see 3.6): 42/5

((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)]

43

Examples of aggregates as initial values:

44

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 45 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" 46/5

G : constant Matrix := (for I in 1 .. 4 => (for J in 1 .. 4 => (if I=J then 1.0 else 0.0))); -- Identity matrix 47/5

Empty_Matrix : constant Matrix := []; -- A matrix without elements

48/2

Example of an array aggregate with defaulted others choice and with an applicable index constraint provided by an enclosing record aggregate:

49/5

Buffer'(Size => 50, Pos => 1, Value => ('x', others => <>)) -- see 3.7

Incompatibilities With Ada 83

49.a.1/1

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:

49.a.2/1

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;

49.a.3/1

This change eliminates generic contract model problems.

Extensions to Ada 83

49.a

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.

49.b

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.

49.c

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

49.d

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).

49.e

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

49.f/2

<> can be used in place of an expression in an array_aggregate, default-initializing the component.

Wording Changes from Ada 95

49.g/2

Limited array_aggregates are allowed (since all kinds of aggregates can now be limited, see 4.3).

49.h/2

Fixed aggregates to use the subtype of the return object of a function, rather than the result subtype, because they can be different for an extended_return_statement, and we want to use the subtype that's explicitly in the code at the point of the expression.

Inconsistencies With Ada 2005

49.i/3
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

49.j/3

Added a definition of the applicable index constraint for conditional_expressions (which are new).

Inconsistencies With Ada 2012

49.k/4

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

49.l/5

The iterated_component_association is new (more than 25 years after it was originally proposed). It has been extended to allow container iterators as well as the basic index iterators.

49.m/5

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

49.o/4

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.

49.p/5

Made syntax and wording changes for delta_aggregates.

49.q/5

Added a definition of the applicable index constraint for declare_expressions (which are new). This allows others in array aggregates inside of declare_expressions.

4.3.4 Delta Aggregates

1/5

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

2/5

delta_aggregate ::= record_delta_aggregate | array_delta_aggregate

3/5

record_delta_aggregate ::=
(base_expression with delta record_component_association_list)

4/5

array_delta_aggregate ::=
(base_expression with delta array_component_association_list)
| '[' base_expression with delta array_component_association_list ']'

Name Resolution Rules

5/5

The expected type for a record_delta_aggregate shall be a single descendant of a record type or record extension.

6/5

The expected type for an array_delta_aggregate shall be a single array type.

7/5

The expected type for the base_expression of any delta_aggregate is the type of the enclosing delta_aggregate.

8/5

[The Name Resolution Rules and Legality Rules for each record_component_association of a record_delta_aggregate are as defined in 4.3.1.]

9/5

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.

10/5

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

11/5

For an array_delta_aggregate, the array_component_association shall not use the box symbol <>, and the discrete_choice shall not be others.

12/5

For an array_delta_aggregate, the dimensionality of the type of the delta_aggregate shall be 1.

13/5

For an array_delta_aggregate, the base_expression and each expression in every array_component_association shall be of a nonlimited type.

13.a/5
ramification

The base_expression of a record_delta_aggregate may be of a limited type (for example a record with limited components), as it is not restricted. A rule in 4.3.1 ensures that we do not assign to a limited component. We do not allow any part of an array_delta_aggregate to be of a limited type, even the base_expression, as this is a useless construct (you would not be able to update anything because the components necessarily are also limited except in pathological cases).

Dynamic Semantics

14/5

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.

14.a/5
ramification

This is the same anonymous object as described in 7.6, “Assignment and Finalization”; in particular, it might be required to be built in place.

14.b/5

For a specific tagged type, any extension components that the actual object underlying the base_expression might have are not used to initialize the anonymous object, which is critical if the aggregate is required to be built-in-place.

14.c/5

To be honest: The anonymous object associated with the evaluation of a delta_aggregate begins its life as a variable, not a constant (3.3 notwithstanding). This must be the case because the object is initialized and then subsequently modified. After evaluation of the delta_aggregate is complete, the object is a constant object. This is similar to the way that an extended return statement can provide a variable view of an object that will eventually be a constant object after the function returns its result.

15/5

For a record_delta_aggregate, for each component associated with each record_component_association (in an unspecified order):

16/5
  • 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.
  • 17/5
  • 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.
18/5

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):

19/5
  • the index value is converted to the index type of the array type.
  • 20/5
  • 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.
  • 21/5
  • 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.
21.a/5
reason

Unlike other aggregates, an array_delta_aggregate is evaluated in the order that it is written. This is necessary to get deterministic behavior, as (unlike other aggregates, including record_delta_aggregates) there is no requirement that the specified components be distinct. As such, the order requirement ensures that every array_delta_aggregate has a well-defined result, even if the same component is specified multiple times.

Examples

22/5

Examples of use of delta aggregates in a postcondition:

23/5

procedure Twelfth (D : in out Date) -- see 3.8 for type Date with Post => D = (D'Old with delta Day => 12); 24/5 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);

25/5

Examples where the base expression is nontrivial:

26/5

New_Cell : Cell := (Min_Cell (Head) with delta Value => 42); -- see 3.10.1 for Cell and Head; 6.1 for Min_Cell 27/5 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 28/5 Tomorrow := ((Yesterday with delta Day => 12) with delta Month => April); -- see 3.8

29/5

Example where the base expression is class-wide:

30/5

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

Extensions to Ada 2012

30.a/5

Delta aggregates are new.

4.3.5 Container Aggregates

1/5

In a container_aggregate, values are specified for elements of a container; for a positional_container_aggregate, the elements are given sequentially; for a named_container_aggregate, the elements are specified by a sequence of key/value pairs, or using an iterator. The Aggregate aspect of the type of the aggregate determines how the elements are combined to form the container.

1.a/5

Term entry: container aggregate — construct used to define a value of a type that represents a collection of elements, by explicitly specifying the elements in the collection

2/5

For a type other than an array type, the following type-related operational aspect may be specified:

3/5

Aggregate
This aspect is an aggregate of the form:
3.a/5

Aspect Description for Aggregate: Mechanism to define user-defined aggregates.

4/5

(Empty => name[,
Add_Named => procedure_name][,
Add_Unnamed => procedure_name][,
New_Indexed => function_name,
Assign_Indexed => procedure_name])

4.a/5
ramification

As this aspect is described with syntax, it has to be given exactly as specified here. That means it cannot be given as a positional aggregate, nor can the order of the elements be changed. For instance, New_Indexed always has to occur before Assign_Indexed, and Empty always has to be first.

5/5
The type for which this aspect is specified is known as the container type of the Aggregate aspect. A procedure_name shall be specified for at least one of Add_Named, Add_Unnamed, or Assign_Indexed. If Add_Named is specified, neither Add_Unnamed nor Assign_Indexed shall be specified. Either both or neither of New_Indexed and Assign_Indexed shall be specified.

Name Resolution Rules

6/5

The name specified for Empty for an Aggregate aspect shall denote a constant of the container type, or denote exactly one function with a result type of the container type that has no parameters, or that has one in parameter of a signed integer type.

6.a/5
reason

In the function case, the parameter, if present may be used to specify an initial size for the container, in anticipation of adding elements to it. For a positional aggregate, or a named aggregate that doesn't use an iterator, it will be initialized with the number of elements. For a named aggregate that uses an iterator, the implementation is permitted to estimate the number of elements that the iterator will produce, but it is not required to do so.

7/5

The procedure_name specified for Add_Unnamed for an Aggregate aspect shall denote exactly one procedure that has two parameters, the first an in out parameter of the container type, and the second an in parameter of some nonlimited type, called the element type of the container type.

8/5

The function_name specified for New_Indexed for an Aggregate aspect shall denote exactly one function with a result type of the container type, and two parameters of the same discrete type, with that type being the key type of the container type.

8.a/5
reason

The New_Indexed function is used instead of Empty as the first step of creating an aggregate that is initialized using the Assign_Indexed procedure.

9/5

The procedure_name specified for Add_Named or Assign_Indexed for an Aggregate aspect shall denote exactly one procedure that has three parameters, the first an in out parameter of the container type, the second an in parameter of a nonlimited type (the key type of the container type), and the third, an in parameter of a nonlimited type that is called the element type of the container type.

Legality Rules

10/5

If the container type of an Aggregate aspect is a private type, the full type of the container type shall not be an array type. If the container type is limited, the name specified for Empty shall denote a function rather than a constant object.

11/5

For an Aggregate aspect, the key type of Assign_Indexed shall be the same type as that of the parameters of New_Indexed. Additionally, if both Add_Unnamed and Assign_Indexed are specified, the final parameters shall be of the same type — the element type of the container type.

Static Semantics

12/5

The Aggregate aspect is nonoverridable (see 13.1.1).

Syntax

13/5

container_aggregate ::=
null_container_aggregate
| positional_container_aggregate
| named_container_aggregate

14/5

null_container_aggregate ::= '[' ']'

15/5

positional_container_aggregate ::= '[' expression{, expression} ']'

16/5

named_container_aggregate ::= '[' container_element_association_list ']'

16.a/5
reason

Unlike other aggregates, container aggregates have to be surrounded with brackets rather than parentheses. Using brackets allows writing zero- and one-element positional aggregates. (Were we to use parentheses, a one-element positional aggregate would look the same as and would always be interpreted as a parenthesized expression.) Unlike the case for arrays, where it is always possible to give bounds to work around this gap, such an aggregate could not be written at all for a sequence type (such as a list) where there is no index or key to use.

17/5

container_element_association_list ::=
container_element_association {, container_element_association}

18/5

container_element_association ::=
key_choice_list => expression
| key_choice_list => <>
| iterated_element_association

19/5

key_choice_list ::= key_choice {'|' key_choice}

20/5

key_choice ::= key_expression | discrete_range

21/5

iterated_element_association ::=
for loop_parameter_specification[ use key_expression] => expression
| for iterator_specification[ use key_expression] => expression

Name Resolution Rules

22/5

The expected type for a container_aggregate shall be a single type for which the Aggregate aspect has been specified. The expected type for each expression of a container_aggregate is the element type of the expected type.

23/5

The expected type for a key_expression, or a discrete_range of a key_choice, is the key type of the expected type of the aggregate.

Legality Rules

24/5

The expected type for a positional_container_aggregate shall have an Aggregate aspect that includes a specification for an Add_Unnamed procedure or an Assign_Indexed procedure. The expected type for a named_container_aggregate that contains one or more iterated_element_associations with a key_expression shall have an Aggregate aspect that includes a specification for the Add_Named procedure. The expected type for a named_container_aggregate that contains one or more key_choice_lists shall have an Aggregate aspect that includes a specification for the Add_Named or Assign_Indexed procedure. [A null_container_aggregate can be of any type with an Aggregate aspect.]

25/5

A non-null container aggregate is called an indexed aggregate if the expected type T of the aggregate specifies an Assign_Indexed procedure in its Aggregate aspect, and either there is no Add_Unnamed procedure specified for the type, or the aggregate is a named_container_aggregate with a container_element_association that contains a key_choice_list or a loop_parameter_specification. The key type of an indexed aggregate is also called the index type of the aggregate.

26/5

A container_element_association with a <> rather than an expression, or with a key_choice that is a discrete_range, is permitted only in an indexed aggregate.

26.a/5
reason

Only an element of an indexed aggregate can be left uninitialized, because the compiler can simply omit producing an Assign_Indexed operation for the given index. For other kinds of aggregates, there are no operations that add an element without giving it a value. We could have defined such (optional) operations, but they would have added significant complication to an already complex feature without adding much additional expressive power. Note that, to be consistent with array aggregates, we do not support specifying <> in an iterated_element_association.

27/5

For an iterated_element_association without a key_expression, if the aggregate is an indexed aggregate or the expected type of the aggregate specifies an Add_Named procedure in its Aggregate aspect, then the type of the loop parameter of the iterated_element_association shall be the same as the key type of the aggregate.

27.a/5
ramification

If there is a key_expression in an iterated_element_association, it determines the key of each added key/value pair, rather than the loop parameter. But if there is no key_expression, the loop parameter itself is used as the key.

28/5

For a named_container_aggregate that is an indexed aggregate, all container_element_associations shall contain either a key_choice_list, or a loop_parameter_specification without a key_expression or iterator_filter. Furthermore, for such an aggregate, either:

29/5
30.a/5
reason

The above is trying to mimic the rules for named_array_aggregates, without others.

Dynamic Semantics

31/5

The evaluation of a container_aggregate starts by creating an anonymous object A of the expected type T, initialized as follows:

32/5
40.a/5
implementation note

This value ought to be an estimate for the number of elements in the aggregate, if one is available. If not, it is suggested to use the default value for the parameter if one exists, and zero otherwise.

40.b/5
implementation defined

The value of the parameter to Empty for some container_aggregates.

41/5

The evaluation then proceeds as follows:

42/5 52/5

1.
the iterated_element_association is elaborated;
53/5

2.
an iteration is performed, and for each value conditionally produced by the iteration (see 5.5 and 5.5.2) the Add_Unnamed procedure is invoked, with the anonymous object A as the first parameter and the result of evaluating the expression as the second parameter.
53.a/5
ramification

In this case, the value of the loop parameter is not directly relevant, though presumably it appears within the expression of the iterated_element_association.

Examples

54/5

Examples of specifying the Aggregate aspect for a Set_Type, a Map_Type, and a Vector_Type:

55/5

-- Set_Type is a set-like container type. type Set_Type is private with Aggregate => (Empty => Empty_Set, Add_Unnamed => Include); function Empty_Set return Set_Type; 56/5 subtype Small_Int is Integer range -1000..1000; 57/5 procedure Include (S : in out Set_Type; N : in Small_Int); 58/5 -- Map_Type is a map-like container type. type Map_Type is private with Aggregate => (Empty => Empty_Map, Add_Named => Add_To_Map); 59/5 procedure Add_To_Map (M : in out Map_Type; Key : in Integer; Value : in String); 60/5 Empty_Map : constant Map_Type; 61/5 -- Vector_Type is an extensible array-like container type. type Vector_Type is private with Aggregate => (Empty => Empty_Vector, Add_Unnamed => Append_One, New_Indexed => New_Vector, Assign_Indexed => Assign_Element); 62/5 function Empty_Vector (Capacity : Integer := 0) return Vector_Type; 63/5 procedure Append_One (V : in out Vector_Type; New_Item : in String); 64/5 procedure Assign_Element (V : in out Vector_Type; Index : in Positive; Item : in String); 65/5 function New_Vector (First, Last : Positive) return Vector_Type with Pre => First = Positive'First; -- Vectors are always indexed starting at the -- lower bound of their index subtype. 66/5 -- Private part not shown.

67/5

Examples of container aggregates for Set_Type, Map_Type, and Vector_Type:

68/5

-- Example aggregates using Set_Type. S : Set_Type; 69/5 -- Assign the empty set to S: S := []; 70/5 -- Is equivalent to: S := Empty_Set; 71/5 -- A positional set aggregate: S := [1, 2]; 72/5 -- Is equivalent to: S := Empty_Set; Include (S, 1); Include (S, 2); 73/5 -- A set aggregate with an iterated_element_association: S := [for Item in 1 .. 5 => Item * 2]; 74/5 -- Is equivalent to: S := Empty_Set; for Item in 1 .. 5 loop Include (S, Item * 2); end loop; 75/5 -- A set aggregate consisting of two iterated_element_associations: S := [for Item in 1 .. 5 => Item, for Item in 1 .. 5 => -Item]; 76/5

-- Is equivalent (assuming set semantics) to: S := Empty_Set; for Item in 1 .. 5 loop Include (S, Item); end loop; for Item in -5 .. -1 loop Include (S, Item); end loop; 77/5 -- Example aggregates using Map_Type. M : Map_Type; 78/5 -- A simple named map aggregate: M := [12 => "house", 14 => "beige"]; 79/5 -- Is equivalent to: M := Empty_Map; Add_To_Map (M, 12, "house"); Add_To_Map (M, 14, "beige"); 80/5 -- Define a table of pairs: type Pair is record Key : Integer; Value : access constant String; end record; 81/5 Table : constant array(Positive range <>) of Pair := [(Key => 33, Value => new String'("a nice string")), (Key => 44, Value => new String'("an even better string"))]; 82/5 -- A map aggregate using an iterated_element_association -- and a key_expression, built from from a table of key/value pairs: M := [for P of Table use P.Key => P.Value.all]; 83/5 -- Is equivalent to: M := Empty_Map; for P of Table loop Add_To_Map (M, P.Key, P.Value.all); end loop; 84/5 -- Create an image table for an array of integers: Keys : constant array(Positive range <>) of Integer := [2, 3, 5, 7, 11]; 85/5 -- A map aggregate where the values produced by the -- iterated_element_association are of the same type as the key -- (hence a separate key_expression is unnecessary): M := [for Key of Keys => Integer'Image (Key)]; 86/5 -- Is equivalent to: M := Empty_Map; for Key of Keys loop Add_To_Map (M, Key, Integer'Image (Key)); end loop; 87/5 -- Example aggregates using Vector_Type. V : Vector_Type; 88/5 -- A positional vector aggregate: V := ["abc", "def"]; 89/5 -- Is equivalent to: V := Empty_Vector (2); Append_One (V, "abc"); Append_One (V, "def"); 90/5 -- An indexed vector aggregate: V := [1 => "this", 2 => "is", 3 => "a", 4 => "test"]; 91/5 -- Is equivalent to: V := New_Vector (1, 4); Assign_Element (V, 1, "this"); Assign_Element (V, 2, "is"); Assign_Element (V, 3, "a"); Assign_Element (V, 4, "test");

Extensions to Ada 2012

91.a/5

Container aggregates are new.