CVS difference for ai12s/ai12-0212-1.txt

Differences between 1.20 and version 1.21
Log of other versions for file ai12s/ai12-0212-1.txt

--- ai12s/ai12-0212-1.txt	2019/01/13 06:35:02	1.20
+++ ai12s/ai12-0212-1.txt	2019/01/25 08:38:51	1.21
@@ -1,10 +1,28 @@
 !standard 4.3.5(0)                                  19-01-11  AI12-0212-1/09
 !standard 1.1.4(12)
 !standard 1.1.4(13)
+!standard 2.1(15)
 !standard 2.2(9/5)
+!standard 3.7.1(3)
 !standard 3.8.1(4)
+!standard 4.3(2/5)
+!standard 4.3(3/5)
+!standard 4.3.1(5)
 !standard 4.3.3(3/2)
-!standard 4.3.3(4)
+!standard 4.3.3(4/5)
+!standard 4.3.3(5.1/5)
+!standard 4.3.3(9)
+!standard 4.3.3(17/5)
+!standard 4.3.3(21)
+!standard 4.3.3(23.2/5)
+!standard 4.3.3(26)
+!standard 4.3.3(27)
+!standard 4.3.3(31)
+!standard 4.3.4(4/5)
+!standard 4.4(3.1/3)
+!standard 11.2(3)
+!standard 13.1.1(5/3)
+!standard 13.1.1(7/3)
 !class Amendment 16-12-27
 !status Amendment 1-2012 18-11-19
 !status ARG Approved 5-0-2  18-10-21
@@ -16,7 +34,7 @@
 !summary
 
 Add aggregate syntax to construct container instances, using a syntax
-based on array aggregates, but using square brackets ("[...]").  Allow
+based on array aggregates, but using square brackets ("[...]"). Allow
 container iterators in array aggregates, and permit the use of square
 brackets, which eases the specification of a null array and a
 single-element array, without resorting to somewhat awkward named notation.
@@ -66,15 +84,15 @@
 One challenge with existing array aggregates is that an empty array
 aggregate (a "null array" in Ada parlance) requires the use of a null
 range. When the container is not indexed by contiguous discrete key values,
-this poses a bit of a problem.  Single-element array aggregates are also
-awkward in Ada, in that positional notation cannot be used.  Therefore,
+this poses a bit of a problem. Single-element array aggregates are also
+awkward in Ada, in that positional notation cannot be used. Therefore,
 we propose to adopt the use of square brackets ("[...]") for container
 aggregates.
 
 We also propose (though it is not essential to the container aggregate
 proposal and could be carved out) to permit the use of square brackets
 for array aggregates, which would allow the use of "[]" as an empty
-array aggregate, with semantics like that of empty string literals.  We
+array aggregate, with semantics like that of empty string literals. We
 do not propose to permit the use of square brackets for record or
 extension aggregates, as we believe arrays and containers are similar,
 in that they represent a data structure made of elements all of the same
@@ -83,7 +101,7 @@
 record aggregate. Furthermore, by disallowing record-ish aggregates from
 using square brackets, we can allow container aggregates for visible
 record or record extensions, rather than restricting them to private
-types.  Finally, we already somewhat equated arrays and containers in
+types. Finally, we already somewhat equated arrays and containers in
 the "for X of Container_Or_Array ..." iterator syntax, while there is
 (of course!) no corresponding iteration defined over a record type.
 
@@ -292,10 +310,10 @@
 
   The expected type for a delta_aggregate shall be a single array type,
   or a single descendant of a record type or of a record extension. The
-  expected type for [any other aggregate] {an array aggregate, a
+  expected type for [any other aggregate] {an array_aggregate, a
   record_aggregate, or an extension_aggregate} shall be a single array
-  type, record type, or record extension. {The expected type for a container
-  aggregate shall be a single array type or a single type with
+  type, record type, or record extension. {The expected type for a 
+  container_aggregate shall be a single array type or a single type with
   the Aggregate aspect specified.}
 
 ---- wording for adding container iterators to array aggregates
@@ -371,27 +389,40 @@
   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
+  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).}
 
-Add after 4.3.3(26):
-   * For a named_array_aggregate containing only
-     iterated_component_associations with an iterator_specification, the
-     lower bound is determined as for a positional_array_aggregate without
-     an OTHERS choice, and the upper bound is determined from the lower
-     bound and the total number of values produced by the iteration(s);
+Modify 4.3.3(26):
 
-Modify 4.3.3(30):
+  For a positional_array_aggregate Redundant[(or equivalent string_literal)] 
+  without an /others/ choice{ that is not a null aggregate}, 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 Redundant[(or the length of the string_literal)];
+
+  {For a null aggregate, bounds for each dimension are determined as for a
+  positional_array_aggregate with zero expressions for each dimension;}
+
+    {AARM Reason: We need a separate rule to describe what happens for a 
+    multidimensional null aggregate; the single dimension case directly follows 
+    from the positional_array_aggregate definition.}
+
+  {For a named_array_aggregate containing only
+  iterated_component_associations with an iterator_specification, the
+  lower bound is determined as for a positional_array_aggregate without
+  an /others/ choice, and the upper bound is determined from the lower
+  bound and the total number of values produced by the iteration(s);
+
+Modify 4.3.3(27):
+
+  For {any other}[a] named_array_aggregate without an others choice, the 
+  bounds are determined by the smallest and largest index values covered 
+  by any discrete_choice_list. 
 
-  For a multidimensional array_aggregate, a check is made that all
-  subaggregates that correspond to the same index have the same bounds.
- {For a null aggregate used to define the value of a multidimensional
-  array type, bounds for each dimension are determined as for a
-  positional_array_aggregate with zero expressions.}
-
 Add after 4.3.3(31):
 
   Implementation Permissions
@@ -410,7 +441,7 @@
 
   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 ']'
 
 ----  end of wording for array [delta] aggregate enhancement ----
 
@@ -438,11 +469,11 @@
        Assign_Indexed => /procedure_/name])
 
     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, 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. If the
     associated type T is a private type, the full type shall not be an
-    array type.  If type T is limited, the name specified for Empty
+    array type. If type T is limited, the name specified for Empty
     shall denote a function rather than a constant object.
 
 Name Resolution Rules
@@ -452,9 +483,9 @@
     or that has one IN parameter of type Integer with a default expression.
       AARM 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
+      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
+      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.
@@ -476,7 +507,7 @@
     OUT parameter of type T, the second an IN parameter of a nonlimited
     type (the /key type/ of the container), and the third,
     an IN parameter of a nonlimited type that is called the /element
-    type/ of T.  In the case of Assign_Indexed, the key type shall be the
+    type/ of T. In the case of Assign_Indexed, the key type shall be the
     same type as that of the parameters of New_Indexed.
 
     If both Add_Unnamed and Assign_Indexed are specified, the final
@@ -505,7 +536,7 @@
    | key_choice_list => <>
    | iterated_element_association
 
-   key_choice_list ::= key_choice {| key_choice}
+   key_choice_list ::= key_choice {'|' key_choice}
 
    key_choice ::= /key_/expression | discrete_range
 
@@ -516,7 +547,7 @@
 Name Resolution Rules
 
 The expected type for a container_aggregate shall be a type for which
-the Aggregate aspect has been specified.  The expected type for each
+the Aggregate aspect has been specified. The expected type for each
 expression of a container_aggregate is the element type of the expected
 type.
 
@@ -531,11 +562,11 @@
 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
+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. [Redundant: (A null_container_aggregate can be of any type
-with an Aggregate aspect.)]
+procedure. [Redundant: A null_container_aggregate can be of any type
+with an Aggregate aspect.]
 
 A non-null container aggregate is called an /indexed aggregate/ if the
 expected type T of the aggregate specifies an Assign_Indexed procedure
@@ -550,7 +581,7 @@
 an indexed aggregate.
   AARM 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
+  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. Note that to be consistent with array aggregates, we do
   not support specifying <> in an iterated_element_association.
@@ -562,7 +593,7 @@
 be the same as the key type of the aggregate.
   AARM 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/value pair, rather than the loop parameter. But if there is no
   /key_/expression, the loop parameter itself is used as the key.
 
 For a named_container_aggregate that is an indexed aggregate, all
@@ -766,23 +797,17 @@
       Include (S, Item * 2);
    end loop;
 
-   --  A set aggregate with a filter (separate AI)
-   S := [for Item in 1 .. 100 when Is_Prime (Item) => Item];
-
-   --  is equivalent to
-   S := Empty_Set;
-   for Item in 1 .. 5 loop
-      if Is_Prime then
-         Include (S, Item);
-      end if;
-   end loop;
-
    --  A set aggregate consisting of two iterated_element_associations
    S := [for Item in 1 .. 5 => Item,
          for Item in 1 .. 5 => -Item];
 
    --  Is equivalent (assuming set semantics) to
-   S := [for Item in -5 .. 5 when Item /= 0 => Item];
+   S := Empty_Set;
+   for Item in -5 .. 5 loop
+      if Item /= 0 then
+         Include (S, Item * 2);
+      end if;
+   end loop;
 
    --  Example aggregates using Map_Type
    M : Map_Type;
@@ -970,12 +995,12 @@
 
 We originally used "Add_Positional" instead of "Add_Unnamed" in the
 Aggregate aspect, but that created confusion because the Add_Unnamed
-operation is used for both named and positional aggregates.  Add_Unnamed
+operation is used for both named and positional aggregates. Add_Unnamed
 is used for named aggregates when they use a container iterator without
 a specified key-expression.
 
 Before we had Assign_Indexed, we allowed both Add_Unnamed and Add_Named
-for a single type.  But in fact, it really doesn't make much sense
+for a single type. But in fact, it really doesn't make much sense
 to allow both, since what would be the "default" value of the key
 if you were to apply Add_Unnamed to something like a "map" container.
 On the other hand, both Add_Unnamed and Assign_Indexed
@@ -1030,16 +1055,17 @@
 !corrigendum 1.1.4(13)
 
 @drepl
-@xcode<@fa<constraint> ::= @fa<scalar_constraint> | @fa<composite_constraint>
-@fa<discrete_choice_list> ::= @fa<discrete_choice> {| @fa<discrete_choice>}>
+@xindent<@fa<constraint>@ ::=@ @fa<scalar_constraint>@ |@ @fa<composite_constraint>@hr
+@fa<discrete_choice_list>@ ::=@ @fa<discrete_choice>@ {|@ @fa<discrete_choice>}>
 @dby
-@xcode<@fa<constraint> ::= @fa<scalar_constraint> | @fa<composite_constraint>>
+@xindent<@fa<constraint>@ ::=@ @fa<scalar_constraint>@ |@ @fa<composite_constraint>>
 
 @xbullet<For symbols used in this notation (square brackets, curly brackets, and
 the vertical line), the symbols when surrounded by ' represent themselves:>
-@xcode<@fa<discrete_choice_list> ::= @fa<discrete_choice> {'|' @fa<discrete_choice>}
-@fa<named_container_aggregate> ::= '[' @fa<container_element_association_list> ']'>
 
+@xindent<@fa<discrete_choice_list>@ ::=@ @fa<discrete_choice>@ {'|'@ @fa<discrete_choice>}@hr
+@fa<named_container_aggregate>@ ::=@ '['@ @fa<container_element_association_list>@ ']'>
+
 !comment Add [ and ] to the table of characters in 2.1(15). Not doing that here.
 
 !corrigendum 2.2(9)
@@ -1052,44 +1078,678 @@
 !corrigendum 3.8.1(4)
 
 @drepl
-@xcode<@fa<discrete_choice_list>@fa< ::= >@fa<discrete_choice> {| @fa<discrete_choice>}>
+@xindent<@fa<discrete_choice_list>@fa<@ ::=@ >@fa<discrete_choice>@ {|@ @fa<discrete_choice>}>
 @dby
-@xcode<@fa<discrete_choice_list>@fa< ::= >@fa<discrete_choice> {'|' @fa<discrete_choice>}>
+@xindent<@fa<discrete_choice_list>@fa<@ ::=@ >@fa<discrete_choice>@ {'|'@ @fa<discrete_choice>}>
 
-!comment Replace "{|" with "{'|'" in 3.7.1(3), 4.3.1(5), 4.4(3.1/3), and 11.2(3).
+!comment Replace "{|" with "{'|'" in 3.7.1(3), 4.3.1(5), and 11.2(3).
 !comment Not making these changes here.
+
+!corrigendum 4.3(2/5)
+
+@drepl
+@xindent<@fa<aggregate>@fa<@ ::=@ >@fa<record_aggregate>@ |@ @fa<extension_aggregate>@ |@ @fa<array_aggregate>>
+@dby
+@xindent<@fa<aggregate>@fa<@ ::=@ >
+@ @ @ @ @fa<record_aggregate>@ |@ @fa<extension_aggregate>@ |@ @fa<array_aggregate>@hr 
+@ @ |@ @fa<delta_aggregate>@ |@ @fa<container_aggregate>>
 
-!comment *** TBD: Changes in 4.3.
 
+!corrigendum 4.3(3/5)
+
+@drepl
+The expected type for a @fa<delta_aggregate> shall be a single array type, or
+a single descendant of a record type or of a record extension.
+The expected type for any other @fa<aggregate> shall be a single array type,
+record type, or record extension.
+@dby
+The expected type for a @fa<delta_aggregate> shall be a single array type, or
+a single descendant of a record type or of a record extension.
+The expected type for an @fa<array_aggregate>, a @fa<record_aggregate>, or an 
+@fa<extension_aggregate> shall be a single array type, record type, or 
+record extension. The expected type for a @fa<container_aggregate> shall be a 
+single array type or a single type with the Aggregate aspect specified.
+
+
 !corrigendum 4.3.3(3/2)
 
 @drepl
-@xcode<@fa<positional_array_aggregate>@fa< ::= >
-@fa<    (expression, expression {, expression})
-  | (expression {, expression}, >@ft<@b<others>>@fa< =@> expression)
-  | (expression {, expression}, >@ft<@b<others>>@fa< =@> <@>)>>
+@xindent<@fa<positional_array_aggregate>@fa<@ ::=@ >@hr
+@ @ @ @ (@fa<expression>,@ @fa<expression>@ {,@ @fa<expression>})@hr
+@ @ |@ (@fa<expression>@ {,@ @fa<expression>},@ @b<others>@ =@>@ @fa<expression>)@hr
+@ @ |@ (@fa<expression>@ {,@ @fa<expression>},@ @b<others>@ =@>@ <@>>
 @dby
-@xcode<@fa<positional_array_aggregate>@fa< ::= >
-@fa<    (expression, expression {, expression})
-  | (expression {, expression}, >@ft<@b<others>>@fa< =@> expression)
-  | (expression {, expression}, >@ft<@b<others>>@fa< =@> <@>)
-  | '['expression, expression {, expression}']'
-  | '['expression {, expression}, >@ft<@b<others>>@fa< =@> expression']'
-  | '['expression {, expression}, >@ft<@b<others>>@fa< =@> <@>']'>>
+@xindent<@fa<positional_array_aggregate>@fa<@ ::=@ >@hr
+@ @ @ @ (@fa<expression>,@ @fa<expression>@ {,@ @fa<expression>})@hr
+@ @ |@ (@fa<expression>@ {,@ @fa<expression>},@ @b<others>@ =@>@ @fa<expression>)@hr
+@ @ |@ (@fa<expression>@ {,@ @fa<expression>},@ @b<others>@ =@>@ <@>)@hr
+@ @ |@ '['@ @fa<expression>@ {,@ @fa<expression>}[,@ @b<others>@ =@>@ @fa<expression>]@ ']'@hr
+@ @ |@ '['@ @fa<expression>@ {,@ @fa<expression>},@ @b<others>@ =@>@ <@>@ ']'@hr
+@ @ |@ '['@ ']'>
 
 !corrigendum 4.3.3(4)
 
 @drepl
-@xcode<@fa<named_array_aggregate>@fa< ::= >
-    (@fa<array_component_association> {, @fa<array_component_association>})>
+@xindent<@fa<named_array_aggregate>@fa<@ ::=@ >@hr
+@ @ @ @ (@fa<array_component_association>@ {,@ @fa<array_component_association>})>
 @dby
-@xcode<@fa<named_array_aggregate>@fa< ::= >
-     (@fa<array_component_association_list>)
-   | '['@fa<array_component_association_list>']'>
+@xindent<@fa<named_array_aggregate>@fa<@ ::=@ >@hr
+@ @ @ @ (@fa<array_component_association_list>)@hr
+@ @ |@ '['@ @fa<array_component_association_list>@ ']'>
+
+@xindent<@fa<array_component_association_list>@fa<@ ::=@ >@hr
+@ @ @ @ @fa<array_component_association>@ {,@ @fa<array_component_association>}>
+
+!corrigendum 4.3.3(5/5)
+
+@dinsa
+@xindent<@fa<array_component_association>@fa<@ ::=@ >@hr
+@ @ @ @ @fa<discrete_choice_list>@ =@>@ @fa<expression>@hr
+@ @ |@ @fa<discrete_choice_list> =@> <@>@hr
+@ @ |@ @fa<iterated_component_association>>
+@dinst
+@xindent<@fa<iterated_component_association>@fa<@ ::=@ >@hr
+@ @ @ @ @b<for> @fa<defining_identifier>@ @b<in>@ @fa<discrete_choice_list>@ =@>@ @fa<expression>@hr
+@ @ |@ @b<for> @fa<iterator_specification>@ =@>@ @fa<expression>>
+
+!corrigendum 4.3.3(9)
+
+@drepl
+An @fa<array_aggregate> of an n-dimensional array type shall be written as
+an n-dimensional @fa<array_aggregate>.
+@dby
+An @fa<array_aggregate> of an n-dimensional array type shall be written as
+an n-dimensional @fa<array_aggregate>, or as a @i<null aggregate> @emdash [ ].
+
+!corrigendum 4.3.3(17/5)
+
+@dinsa
+The @fa<discrete_choice_list> of an @fa<array_component_association> (including
+an @fa<iterated_component_association>) is allowed to
+have a @fa<discrete_choice> that is a nonstatic @fa<choice_expression> or that is a
+@fa<subtype_indication> or @fa<range> that defines a nonstatic or null range, only
+if it is the single @fa<discrete_choice> of its @fa<discrete_choice_list>, and
+either there is only one @fa<array_component_association> in the
+enclosing @fa<array_component_association_list> or the enclosing @fa<aggregate> is
+an @fa<array_delta_aggregate>, not an @fa<array_aggregate>.
+@dinst
+Either all or none of the @fa<array_component_association>s of an
+@fa<array_component_association_list> shall be @fa<iterated_component_association>s
+with an @fa<iterator_specification>.
+
+!corrigendum 4.3.3(21)
+
+@drepl
+The evaluation of an @fa<array_aggregate> of a given array type proceeds in two 
+steps: 
+@dby
+For an @fa<array_aggregate> that contains only 
+@fa<array_component_association>s that are 
+@fa<iterated_component_association>s with @fa<iterator_specification>s,
+evaluation proceeds in two steps:
+
+@xhang<@xterms<1.>Each @fa<iterator_specification> is elaborated (in an 
+arbitrary order) and an iteration is performed solely to determine a count of
+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 bounds of the array (defined below);>
+
+@xhang<@xterms<2.>A second iteration is performed for each of the 
+@fa<iterator_specification>s, in the order given in the @fa<aggregate>, and 
+for each value produced, the associated @fa<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 the same array length;
+Constraint_Error is raised if this check fails.>
+
+The evaluation of any other @fa<array_aggregate> of a given
+array type proceeds in two steps:
+
+!corrigendum 4.3.3(23.1/4)
+
+@dinsa
+Each @fa<expression> in an
+@fa<array_component_association> defines the value for the associated
+component(s). For an @fa<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).
+@dinst
+During an evaluation of the @fa<expression> of an
+@fa<iterated_component_association> with a @fa<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 
+@fa<expression> of an @fa<iterated_component_association> with an 
+@fa<iterator_specification>, the value of the loop parameter
+of the @fa<iterator_specification> is the value produced by the iteration
+(as described in 5.5.2).
+
+!corrigendum 4.3.3(26)
+
+@drepl
+@xbullet<For a @fa<positional_array_aggregate> (or equivalent 
+@fa<string_literal>) without an @b<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 
+@fa<expression>s (or the length of the @fa<string_literal>);>
+@dby
+@xbullet<For a @fa<positional_array_aggregate> (or equivalent 
+@fa<string_literal>) without an @b<others> choice that is not a null 
+aggregate, 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 @fa<expression>s (or the length of the 
+@fa<string_literal>);>
+
+@xbullet<For a null aggregate, bounds for each dimension are determined as 
+for a @fa<positional_array_aggregate> without an @b<others> choice with 
+zero expressions for each dimension;>
+
+@xbullet<For a @fa<named_array_aggregate> containing only
+@fa<iterated_component_association>s with an @fa<iterator_specification>, the
+lower bound is determined as for a @fa<positional_array_aggregate> without
+an @b<others> choice, and the upper bound is determined from the lower
+bound and the total number of values produced by the iteration(s);>
+
+!corrigendum 4.3.3(27)
+
+@drepl
+For a @fa<named_array_aggregate> without an @b<others> choice, the bounds are 
+determined by the smallest and largest index values covered by any 
+@fa<discrete_choice_list>. 
+@dby
+For any other @fa<named_array_aggregate> without an @b<others> choice, the 
+bounds are determined by the smallest and largest index values covered by any 
+@fa<discrete_choice_list>. 
+
+!corrigendum 4.3.3(31)
+
+@dinsa
+The exception Constraint_Error is raised if any of the above checks fail. 
+@dinst
+@s8<@i<Implementation Permissions>>
+
+When evaluating @fa<iterated_component_association>s for an 
+@fa<array_aggregate> that contains only @fa<iterated_component_association>s 
+with @fa<iterator_specification>s, the first step of evaluating a 
+@fa<iterated_component_association> can be omitted if the implementation can
+determine the number of values by some other means.
+
+
+!corrigendum 4.3.4(0)
+@dinsc
+A fake to force a conflict; the actual text is in the conflict file.
+
+!corrigendum 4.3.5(0)
+
+@dinsc
+In a @fa<container_aggregate>, values are specified for elements of a
+container; for a @fa<positional_container_aggregate>, the elements are given
+sequentially; for a @fa<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 @fa<aggregate> determines how the
+elements are combined to form the container.
+
+Given a type @i<T> other than an array type, the following type-related
+operational aspect may be specified:
+
+@xhang<@xterm<Aggregate>This aspect is an @fa<aggregate> of the form:>
+
+@xindent<@ @ @ (Empty =@> @fa<name>[,@hr
+@ @ @ @ Add_Named =@> @i<procedure_>@fa<name>][,@hr
+@ @ @ @ Add_Unnamed =@> @i<procedure_>@fa<name>][,@hr
+@ @ @ @ New_Indexed =@> @i<function_>@fa<name>,@hr
+@ @ @ @ Assign_Indexed =@> @i<procedure_>@fa<name>])>
+
+@xindent<A @i<procedure_>@fa<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. If the
+associated type @i<T> is a private type, the full type shall not be an
+array type. If type @i<T> is limited, the name specified for Empty
+shall denote a function rather than a constant object.>
+
+@s8<@i<Name Resolution Rules>>
+
+The @fa<name> specified for Empty shall denote a constant of type @i<T>,
+or denote a function with a result type of @i<T> that has no parameters,
+or that has one @b<in> parameter of type Integer with a default expression.
+
+The @i<procedure_>@fa<name> specified for Add_Unnamed, if any, shall
+denote a procedure that has two parameters, the first an @b<in out>
+parameter of type @i<T>, and the second an @b<in> parameter of some
+nonlimited type, called the @i<element type> of @i<T>.
+
+The @i<function_>@fa<name> specified for New_Indexed, if any, shall denote
+a function with a result type of @i<T>, and two parameters of the same
+discrete type, with that type being the @i<key type> of the container.
+
+The @i<procedure_>@fa<name> specified for Add_Named or Assign_Indexed, if any,
+shall denote a procedure that has three parameters, the first an @b<in out>
+parameter of type @i<T>, the second an @b<in> parameter of a nonlimited type 
+(the @i<key type> of the container), and the third, an @b<in> parameter of a 
+nonlimited type that is called the @i<element type> of @i<T>. In the case of 
+Assign_Indexed, the key type shall be the same type as that of the parameters 
+of New_Indexed.
+
+If both Add_Unnamed and Assign_Indexed are specified, the final
+parameters shall be of the same type @emdash the element type of @i<T>.
+
+@s8<@i<Static Semantics>>
+
+The Aggregate aspect is nonoverridable.
+
+@s8<@i<Syntax>>
+
+@xindent<@fa<container_aggregate>@fa<@ ::=@ >@hr
+@ @ @ @ @fa<null_container_aggregate>@hr
+@ @ |@ @fa<positional_container_aggregate>@hr
+@ @ |@ @fa<named_container_aggregate>>
+
+@xindent<@fa<null_container_aggregate>@fa<@ ::=@ >'['@ ']'>
+
+@xindent<@fa<positional_container_aggregate>@fa<@ ::=@ >'['@ @fa<expression>{,@ @fa<expression>}@ ']'>
 
-@xcode<@fa<array_component_association_list>@fa< ::= >
-    @fa<array_component_association> {, @fa<array_component_association>}>
+@xindent<@fa<named_container_aggregate>@fa<@ ::=@ >'['@ @fa<container_element_association_list>@ ']'>
 
+@xindent<@fa<container_element_association_list>@fa<@ ::=@ >@hr
+@ @ @ @ @fa<container_element_association>@ {,@ @fa<container_element_association>}>
+
+@xindent<@fa<container_element_association>@fa<@ ::=@ >@hr
+@ @ @ @ @fa<key_choice_list> =@> @fa<expression>@hr
+@ @ |@ @fa<key_choice_list> =@> <@>@hr
+@ @ |@ @fa<iterated_element_association>>
+
+@xindent<@fa<key_choice_list>@fa<@ ::=@ >@fa<key_choice>@ {'|'@ @fa<key_choice>}>
+
+@xindent<@fa<key_choice>@fa<@ ::=@ >@i<key_>@fa<expression>@ |@ @fa<discrete_range>>
+
+@xindent<@fa<iterated_element_association>@fa<@ ::=@ >@hr
+@ @ @ @ @b<for>@ @fa<loop_parameter_specification>[@ @b<use>@ @i<key_>@fa<expression>]@ =@>@ @fa<expression>@hr
+@ @ |@ @b<for>@ @fa<iterator_specification>[@ @b<use>@ @i<key_>@fa<expression>]@ =@>@ @fa<expression>>
+
+@s8<@i<Name Resolution Rules>>
+
+The expected type for a @fa<container_aggregate> shall be a type for which
+the Aggregate aspect has been specified. The expected type for each
+@fa<expression> of a @fa<container_aggregate> is the element type of the expected
+type.
+
+The expected type for a @i<key_>@fa<expression>, or a @fa<discrete_range> of a
+@fa<key_choice>, is the key type of the expected type of the @fa<aggregate>.
+
+@s8<@i<Legality Rules>>
+
+The expected type for a @fa<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
+@fa<named_container_aggregate> that contains one or more
+@fa<iterated_element_association>s with a @i<key_>@fa<expression> shall have an
+Aggregate aspect that includes a specification for the Add_Named
+procedure. The expected type for a @fa<named_container_aggregate> that
+contains one or more @fa<key_choice_list>s shall have an Aggregate aspect
+that includes a specification for the Add_Named or Assign_Indexed
+procedure. A @fa<null_container_aggregate> can be of any type
+with an Aggregate aspect.
+
+A non-null container aggregate is called an @i<indexed aggregate> if the
+expected type @i<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 @fa<named_container_aggregate>
+with a @fa<container_element_association> that contains a @fa<key_choice_list>
+or a @fa<loop_parameter_specification>. The key type of an indexed aggregate
+is also called the @i<index type> of the aggregate.
+
+A @fa<container_element_association> with a <@> rather than an @fa<expression>,
+or with a @fa<key_choice> that is a @fa<discrete_range>, is permitted only in
+an indexed aggregate.
+
+For an @fa<iterated_element_association> without a @i<key_>@fa<expression>, if the
+@fa<aggregate> is an indexed aggregate or the expected type of the
+@fa<aggregate> specifies an Add_Named procedure in its Aggregate aspect, then
+the type of the loop parameter of the @fa<iterated_element_association> shall
+be the same as the key type of the @fa<aggregate>.
+
+For a @fa<named_container_aggregate> that is an indexed aggregate, all
+@fa<container_element_association>s shall contain either a @fa<key_choice_list>,
+or a @fa<loop_parameter_specification> without a @i<key_>@fa<expression>.
+Furthermore, for such an aggregate, either:
+
+@xbullet<all @fa<key_choice>s shall be static expressions or static ranges, 
+and every @fa<loop_parameter_specification> shall have a
+@fa<discrete_subtype_definition> that defines a non-null static range,
+and the set of values of the index type covered by the
+@fa<key_choice>s and the @fa<discrete_subtype_definition>s shall form a
+contiguous range of values with no duplications; or>
+
+@xbullet<there shall be exactly one @fa<container_element_association>, and if
+it has a @fa<key_choice_list>, the list shall have exactly one @fa<key_choice>.>
+
+@s8<@i<Dynamic Semantics>>
+
+The evaluation of a @fa<container_aggregate> starts by creating an anonymous
+object @i<A> of the expected type @i<T> initialized as follows:
+
+@xbullet<if the @fa<aggregate> is an indexed aggregate, from the result of a 
+call on the New_Indexed function; the actual parameters in this call
+represent the lower and upper bound of the @fa<aggregate>, and are
+determined as follows:>
+
+@xinbull<if the @fa<aggregate> is a @fa<positional_container_aggregate>, the 
+lower bound is the low bound of the subtype of the key parameter of the
+Add_Indexed procedure, and the upper bound has a position number
+that is the sum of the position number of the lower bound and
+one less than the number of @fa<expression>s in the @fa<aggregate>;>
+
+@xinbull<if the @fa<aggregate> is a @fa<named_container_aggregate>, the lower 
+bound is the lowest value covered by a @fa<key_choice_list> or is the low
+bound of a range defined by a @fa<discrete_subtype_definition> of a
+@fa<loop_parameter_specification>; the upper bound is the highest
+value covered by a @fa<key_choice_list> or is the high bound of a
+range defined by a @fa<discrete_subtype_definition> of a
+@fa<loop_parameter_specification>.>
+
+@xbullet<if the @fa<aggregate> is not an indexed aggregate, by assignment 
+from the Empty constant, or from a call on the Empty function specified in
+the Aggregate aspect. In the case of an Empty function with a formal
+parameter, the actual parameter has the following value:>
+
+@xinbull<for a @fa<null_container_aggregate>, the value zero;>
+
+@xinbull<for a @fa<positional_container_aggregate>, the number of 
+@fa<expression>s;>
+
+@xinbull<for a @fa<named_container_aggregate> without an 
+@fa<iterated_element_association>, the number of @i<key_>@fa<expression>s;>
+
+@xinbull<for a @fa<named_container_aggregate> where every 
+@fa<iterated_element_association> contains a @fa<loop_parameter_specification>,
+the total number of elements specified by all of the 
+@fa<container_element_association>s;>
+
+@xinbull<otherwise, to an implementation-defined value.>
+
+The evaluation then proceeds as follows:
+
+@xbullet<for a @fa<null_container_aggregate>, the anonymous object @i<A>
+is the result;>
+
+@xbullet<for a @fa<positional_container_aggregate> of a type with a specified
+Add_Unnamed procedure, each @fa<expression> is evaluated in an arbitrary
+order, and the Add_Unnamed procedure is invoked in sequence with the
+anonymous object @i<A> as the first parameter and the result of
+evaluating each @fa<expression> as the second parameter, in the order of
+the @fa<expression>s;>
+
+@xbullet<for a @fa<positional_container_aggregate> that is an indexed 
+aggregate, each @fa<expression> is evaluated in an arbitrary order, and the
+Assign_Indexed procedure is invoked in sequence with the anonymous
+object @i<A> as the first parameter, the key value as the second
+parameter, computed by starting with the low bound of the subtype of
+the key formal parameter of the Assign_Indexed procedure and taking
+the successor of this value for each successive @fa<expression>, and the
+result of evaluating each @fa<expression> as the third parameter;>
+
+@xbullet<for a @fa<named_container_aggregate> for a type with an Add_Named 
+procedure in its Aggregate aspect, the @fa<container_element_association>s
+are evaluated in an arbitrary order:>
+
+@xinbull<for a @fa<container_element_association> with a @fa<key_choice_list>,
+for each @fa<key_choice> of the list in an arbitrary order, the
+@fa<key_choice> is evaluated as is the @fa<expression> of the
+@fa<container_element_association> (in an arbitrary order), and the
+Add_Named procedure is invoked once for each value covered by the
+@fa<key_choice>, with the anonymous object @i<A> as the first parameter,
+the value from the @fa<key_choice> as the second parameter, and the
+result of evaluating the @fa<expression> as the third parameter;>
+
+@xinbull<for a @fa<container_element_association> with an 
+@fa<iterated_element_association>, the @fa<iterated_element_association> is 
+elaborated, then an iteration is performed as described in 5.5 or 5.5.2, 
+and for each value of the loop parameter of the iteration the Add_Named 
+procedure is invoked with the anonymous object @i<A> as the first parameter, 
+the result of evaluating the @fa<expression> as the third parameter, and:>
+
+@xI2bull<if there is a @i<key_>@fa<expression>, the result of evaluating
+the @i<key_>@fa<expression> as the second parameter;>
+
+@XI2Bull<otherwise, with the loop parameter as the second parameter;>
+
+@xbullet<for a @fa<named_container_aggregate> that is an indexed aggregate, 
+the evaluation proceeds as above for the case of Add_Named, but with
+the Assign_Indexed procedure being invoked in its stead; in the
+case of a @fa<container_element_association> with a <@> rather than an
+@fa<expression>, the corresponding call on Assign_Indexed is not
+performed, leaving the component as it was upon return from the New_Indexed 
+function;>
+
+@xbullet<for any other @fa<named_container_aggregate>, the
+@fa<container_element_association>s (which are necessarily
+@fa<iterated_element_association>s) are evaluated in the order given:>
+
+@xinbull<the @fa<iterated_element_association> is elaborated, then an 
+iteration is performed as described in 5.5 or 5.5.2, and for each value 
+of the loop parameter of the iteration, the Add_Unnamed procedure is invoked, 
+with the anonymous object @i<A> as the first parameter and the result of
+evaluating the @fa<expression> as the second parameter.>
+
+@s8<@i<Examples>>
+
+Declarations of Set_Type, Map_Type, and Vector_Type:
+
+@xcode<   --  @ft<@i<Set_Type is a set-like container type.>>
+   @b<type> Set_Type @b<is private>
+      @b<with> Aggregate =@> (Empty       =@> Empty_Set,
+                         Add_Unnamed =@> Include);
+   @b<function> Empty_Set @b<return> Set_Type;>
+
+@xcode<   @b<subtype> Small_Natural @b<is> Natural @b<range> 0..1000;>
+
+@xcode<   @b<procedure> Include (S : @b<in out> Set_Type; N : @b<in> Small_Natural);>
+
+@xcode<   --  @ft<@i<Map_Type is a map-like container type.>>
+   @b<type> Map_Type @b<is private>
+     @b<with> Aggregate =@>  (Empty     =@> Empty_Map,
+                         Add_Named =@> Add_To_Map);>
+
+@xcode<   @b<procedure> Add_To_Map (M : @b<in out> Map_Type; Key : @b<in> Integer; Value : @b<in> String);>
+
+@xcode<   Empty_Map : @b<constant> Map_Type;>
+
+@xcode<   --  @ft<@i<Vector_Type is an extensible array-like container type.>>
+   @b<type> Vector_Type @b<is private>
+      @b<with> Aggregate =@> (Empty          =@> Empty_Vector,
+                         Add_Unnamed    =@> Append_One,
+                         New_Indexed    =@> New_Vector,
+                         Assign_Indexed =@> Assign_Element);>
+
+@xcode<   @b<function> Empty_Vector (Capacity : Count_Type := 0) @b<return> Vector_Type;>
+
+@xcode<   @b<procedure> Append_One (V : @b<in out> Vector_Type; New_Item : @b<in> String);>
+
+@xcode<   @b<procedure> Assign_Element (V : @b<in out> Vector_Type; 
+                             Index : @b<in> Positive;
+                             Item  : @b<in> String);>
+
+@xcode<   @b<function> New_Vector (First, Last : Positive) @b<return> Vector_Type
+      @b<with> Pre =@> First = Positive'First;
+      --  @ft<@i<Vectors of are always indexed starting at the>>
+      --  @ft<@i<low bound of their index subtype.>>>
+
+@xcode<@b<private>>
+
+@xcode<   @b<type> Set_Type @b<is new> Bit_Vector (Small_Natural); -- @ft<@i<See 3.6.>>>
+
+@xcode<   @b<function> Empty_Set @b<return> Set_Type @b<is> (@b<others> =@> False);>
+
+@xcode<   @b<package> Int_String_Maps @b<is>
+      @b<new> Ada.Containers.Indefinite_Ordered_Maps  -- @ft<@i<See A.18.14.>>
+         (Key_Type =@> Integer, Element_Type =@> String);>
+
+@xcode<   @b<type> Map_Type @b<is new> Int_String_Maps.Map @b<with null record>;>
+
+@xcode<   @b<procedure> Add_To_Map (M : @b<in out> Map_Type; Key : @b<in> Integer; Value : @b<in> String)
+      @b<renames> Insert;>
+
+@xcode<   Empty_Map : @b<constant> Map_Type :=
+      (Int_String_Maps.Empty_Map @b<with null record>);>
+
+@xcode<   @b<package> String_Vectors @b<is>
+      @b<new> Ada.Containers.Indefinite_Vectors -- @ft<@i<See A.18.11.>>
+         (Index_Type =@> Positive, Element_Type =@> String);>
+
+@xcode<   @b<type> Vector_Type @b<is new> String_Vectors.Vector;>
+
+Examples of container aggregates for Set_Type, Map_Type, and Vector_Type:
+
+@xcode<--  @ft<@i<Example aggregates using Set_Type.>>
+S : Set_Type;>
+
+@xcode<--  @ft<@i<Assign S to be the empty set:>>
+S := [];>
+
+@xcode<--  @ft<@i<Is equivalent to:>>
+S := Empty_Set;>
+
+@xcode<--  @ft<@i<A positional set aggregate:>>
+S := [1, 2];>
+
+@xcode<--  @ft<@i<Is equivalent to:>>
+S := Empty_Set;
+Include (S, 1);
+Include (S, 2);>
+
+@xcode<--  @ft<@i<A set aggregate with an >>@fa<iterated_element_association>@ft<@i<:>>
+S := [@b<for> Item @b<in> 1 .. 5 =@> Item * 2];>
+
+@xcode<--  @ft<@i<Is equivalent to:>>
+S := Empty_Set;
+@b<for> Item @b<in> 1 .. 5 @b<loop>
+   Include (S, Item * 2);
+@b<end loop>;>
+
+@xcode<--  @ft<@i<A set aggregate consisting of two >>@fa<iterated_element_association>@ft<@i<s:>>
+S := [@b<for> Item @b<in> 1 .. 5 =@> Item,
+      @b<for> Item @b<in> 1 .. 5 =@> -Item];>
+
+@xcode<--  @ft<@i<Is equivalent (assuming set semantics) to:>>
+S := Empty_Set;
+@b<for> Item @b<in> -5 .. 5 @b<loop>
+   @b<if> Item /= 0 @b<then>
+      Include (S, Item * 2);
+   @b<end if>;
+@b<end loop>;>
+
+@xcode<--  @ft<@i<Example aggregates using Map_Type.>>
+M : Map_Type;>
+
+@xcode<--  @ft<@i<Create an empty map:>>
+M := [];>
+
+@xcode<--  @ft<@i<Is equivalent to:>>
+M := Empty_Map;>
+
+@xcode<--  @ft<@i<A simple named map aggregate:>>
+M := [12 =@> "house", 14 =@> "beige"];>
+
+@xcode<--  @ft<@i<Is equivalent to:>>
+M := Empty_Map;
+Add_To_Map (M, 12, "house");
+Add_To_Map (M, 14, "beige");>
+
+@xcode<--  @ft<@i<Define a table of pairs:>>
+@b<type> Pair @b<is record>
+   Key : Integer;
+   Value : @b<access constant> String;
+@b<end record>;>
+
+@xcode<Table : @b<constant array>(Positive @b<range> <@>) @b<of> Pair :=
+   [(Key =@> 33, Value =@> @b<new> String'("a nice string")),
+    (Key =@> 44, Value =@> @b<new> String'("an even better string"))];>
+
+@xcode<--  @ft<@i<A map aggregate using an >>@fa<iterated_element_association>
+--  @ft<@i<and a key_>>@fa<expression>@ft<@i<, built from from a table of key/value pairs:>>
+M := [@b<for> P @b<of> Table @b<use> P.Key =@> P.Value];>
+
+@xcode<--  @ft<@i<Is equivalent to:>>
+M := Empty_Map;
+@b<for> P @b<of> Table @b<loop>
+   Add_To_Map (M, P.Key, P.Value);
+@b<end loop>;>
+
+@xcode<--  @ft<@i<Create an image table for an array of integers:>>
+Keys : @b<constant array>(Positive @b<range> <@>) @b<of> Integer := [2, 3, 5, 7, 11];>
+
+@xcode<--  @ft<@i<A map aggregate where the values produced by the>>
+--  @fa<iterated_element_association>@ft<@i< are of the same type as the key>>
+--  @ft<@i<(eliminating the need for a separate key_>>@fa<expression>@ft<@i<):>>
+M := [@b<for> Key @b<of> Keys =@> Integer'Image (Key)];>
+
+@xcode<--  @ft<@i<Is equivalent to:>>
+M := Empty_Map;
+@b<for> Key @b<of> Keys @b<loop>
+   Add_To_Map (M, Key, Integer'Image (Key));
+@b<end loop>;>
+
+@xcode<--  @ft<@i<The above could have been written using an explicit key_>>@fa<expression>@ft<@i<:>>
+M := [@b<for> Key @b<of> Keys @b<use> Key =@> Integer'Image (Key)];>
+
+@xcode<--  @ft<@i<Example aggregates using Vector_Type.>>
+V : Vector_Type;>
+
+@xcode<--  @ft<@i<Create an empty vector aggregate:>>
+V := [];>
+
+@xcode<--  @ft<@i<Is equivalent to:>>
+V := Empty_Vector (0);>
+
+@xcode<--  @ft<@i<A positional vector aggregate:>>
+V := ["abc", "def"];>
+
+@xcode<--  @ft<@i<Is equivalent to:>>
+V := Empty_Vector (2);
+Append_One (V, "abc");
+Append_One (V, "def");>
+
+@xcode<--  @ft<@i<An indexed vector aggregate:>>
+V := [1 =@> "this", 2 =@> "is", 3 =@> "a", 4 =@> "test"];>
+
+@xcode<--  @ft<@i<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");>
+
+@xcode<--  @ft<@i<A vector of images of dynamic length:>>
+V := [@b<for> I @b<in> 1 .. N =@> Integer'Image (I)];>
+
+@xcode<--  @ft<@i<Is equivalent to:>>
+V := New_Vector (1, N);
+@b<for> I @b<in> 1 .. N @b<loop>
+   Assign_Element (V, I, Integer'Image (I));
+@b<end loop>;>
+
+@xcode<--  @ft<@i<A vector made from the elements of a map:>>
+V := [@b<for> Elem @b<of> M =@> Elem];>
+
+@xcode<--  @ft<@i<Is equivalent to:>>
+V := Empty_Vector (<estimate of size of M@>);
+@b<for> Elem @b<of> M @b<loop>
+   Add_Positional (V, Elem);
+@b<end loop>;>
+
+!corrigendum 4.4(3.1/3)
+
+@drepl
+@xindent<@fa<membership_choice_list>@fa<@ ::=@ >@fa<membership_choice>@ {|@ @fa<membership_choice>}>
+@dby
+@xindent<@fa<membership_choice_list>@fa<@ ::=@ >@fa<membership_choice>@ {'|'@ @fa<membership_choice>}>
+
+
 !corrigendum 13.1.1(5/3)
 
 @drepl
@@ -3947,6 +4607,87 @@
 Sent: Tuesday, November 21, 2018  9:06 AM
 
 All makes sense to me...
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Wednesday, January 23, 2019  6:17 PM
+
+The wording of AI12-0212-1 has:
+
+Modify 4.3.3(30):
+
+  For a multidimensional array_aggregate, a check is made that all
+  subaggregates that correspond to the same index have the same bounds.
+ {For a null aggregate used to define the value of a multidimensional
+  array type, bounds for each dimension are determined as for a
+  positional_array_aggregate with zero expressions.}
+
+But this placement doesn't make much sense: paragraphs 28-31 are about checks,
+not determining bounds. Paragraphs 24-27 are about determining bounds.
+
+Since a null aggregate is a special case of a positional_array_aggregate, it 
+makes more sense to add this new sentence after 4.3.3(26) (the paragraph 
+about positional_array_aggregates).
+
+I note that the wording is a bit screwy, in that a null aggregate *is* a 
+positional_array_aggregate. So I added "for each dimension" to the end to make 
+it a bit clearer. It also seems that we need to exclude the null aggregates 
+from the preceding paragraph, and handle all kinds of null aggregates 
+separately. That gives:
+
+For a positional_array_aggregate Redundant[(or equivalent string_literal)] 
+without an others choice{ that is not a null aggregate}, 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 Redundant[(or the length of the string_literal)];
+
+{For a null aggregate, bounds for each dimension are determined as for a 
+positional_array_aggregate with zero expressions for each dimension;
+
+   AARM Reason: We need a separate rule to describe what happens for a 
+   multidimensional null aggregate; the single dimension case directly follows 
+   from the positional_array_aggregate definition.}
+
+I made these changes, since they don't make any semantic difference.
+(Consider it my Editorial Review comments.)
+
+Aside: 4.3.3(27) seems to cover the cases already covered in the other new 
+bullet in this text. So I changed it slightly:
+
+  For {any other}[a] named_array_aggregate without an others choice, the 
+  bounds are determined by the smallest and largest index values covered by
+  any discrete_choice_list. 
+
+P.S. If we had made null aggregate a separate syntactic entity, we could
+avoid some of the mess. That is, if we defined
+
+    null_array_aggregate := '[' ']'
+
+then we wouldn't need the textual definition of "null aggregate", we
+wouldn't need the exception in 4.3.3(26), the 4.3.3(26.1) bullet would look
+more similar to the others (and we could drop the AARM note), and so far as
+I can tell, the only other paragraph that could need a bit of change would
+be 4.3.3(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.
+
+And here we could just use a TBH note, since it has been this way since
+time-immemorial even though there never were any positional_array_aggregates
+of length 0 or 1 until Ada 2020. Or we could clean up this old oddity by
+mentioning a null_array_aggregate:
+
+A subaggregate that is a string_literal is equivalent to one that is a
+positional_array_aggregate of the same length (or a null_array_aggregate if
+the length is zero), with each expression being the character_literal for
+the corresponding character of the string_literal.
+
+I didn't do this because changing the syntax seemed like a bit too much
+change to do as "editorial". (Note this is how null container aggregates are
+handled.)
 
 ****************************************************************
 

Questions? Ask the ACAA Technical Agent