Version 1.6 of ai22s/ai22-0031-1.txt
!standard 4.3.5(44/5) 22-09-06 AI22-0031-1/04
!standard 4.3.5(46/5)
!standard 4.3.5(53/5)
!class binding interpretation 22-01-26
!status Corrigendum 1-2022 22-02-03
!status WG9 Approved 22-10-18
!status ARG Approved 16-0-0 22-02-03
!status work item 22-01-26
!status received 21-11-09
!priority Low
!difficulty Easy
!qualifier Omission
!subject Issues with dynamic evaluation of container aggregates
!summary
The parameters to calls on the subprograms specified in the Aggregate aspect
are converted to the appropriate formal subtype.
The calls to Add_Indexed for an indexed positional container aggregate are
performed in an unspecified order.
The expressions of a named container aggregate that are an indexed aggregate
or have Add_Named are evaluated once for each value covered by each choice.
!issue
(1) The key type, element type, and container type of a container aggregate
are given by the required profiles of the subprograms specified in an
Aggregate aspect. However, there are no limitations on the subtypes of those
types in those subprograms. Clearly, we want any constraints and/or predicates
of the parameter types to be enforced. But there is no wording about
converting values to the appropriate subtype. Should we add such
wording? (Yes.)
(2) 4.3.5(44/5) says in part "...the Assign_Indexed procedure is invoked in
sequence with...". However, this call has an explicit index parameter.
Therefore, one would get the same result regardless of the order in which the
procedure is invoked. As such, "in sequence" is over-specification, and should
be removed (especially as the expressions can be evaluated in an arbitrary order).
(3) 4.3.5(46/5) says:
for a container_element_association with a key_choice_list, for each
key_choice of the list in an arbitrary order, the key_choice is evaluated
as is the expression of the container_element_association (in an arbitrary
order), and the Add_Named procedure is invoked once for each value covered
by the key_choice, with the anonymous object A as the first parameter, the
value from the key_choice as the second parameter, and the result of
evaluating the expression as the third parameter;
This wording implies that the expression is evaluated only once for each
key_choice, even when the key_choice is a discrete_range that covers many key
values. This is different than other aggregates (including other container
aggregates). Is this difference intended? (No.)
!recommendation
(See Summary.)
!wording
(1) Add after 4.3.5(53/5):
When the above wording says that a subprogram is invoked or called, this is
a subprogram call as defined in 6.4, with parameter associations as
specified in the wording evaluated as defined 6.4.1. Redundant:[In
particular, this means that the parameters are converted to the subtype of
the formal parameter (which can raise an exception -- see 4.6).]
(2) Modify 4.3.5(44/5):
* for a positional_container_aggregate that is an indexed aggregate, each
expression is evaluated in an arbitrary order, and the Assign_Indexed
procedure is invoked [in sequence]{once for each expression of the
aggregate} with the anonymous object 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 expression{ of the
aggregate}, and the result of evaluating each expression as the third
parameter;
(3) Replace 4.3.5(46/5) with:
* for a container_element_association with a key_choice_list, for each
key_choice of the list in an arbitrary order, the key_choice is evaluated,
and the Add_Named procedure is invoked once for each value covered
by the key_choice (in an arbitrary order), with the anonymous object A as
the first parameter, the value from the key_choice as the second parameter,
and the result of evaluating the expression of the
container_element_association as the third parameter;
!discussion
(1) The intended meaning of 4.3.5(31-53/5) when it says that a subprogram is
invoked, or that a call is made on a subprogram, that this is a normal
subprogram call as defined in 6.4-6.4.1, including all of the rules for
parameter evaluation. Rather than trying to explain that at each place, we
add a blanket rule at the end making that explicit. We write that in terms of
a regular subprogram call in case other checks or conversions need to be made
for a particular parameter (we've made aliased and access parameters illegal
-- see AI22-0021-1 -- to reduce the need for such checks, but it's safer to
assume we didn't catch them all).
We used a blanket rule as the subtypes in question don't have names. So one
would have to say something like "converted to the subtype of the second
formal parameter of Add_Unnamed" in each place. There are 17 such places in
4.3.5(31-53/5), so that would add a lot of wording which would distract from
the actual meaning.
(2) Since Add_Indexed has an explicit index parameter, the order of the calls
does not matter. Indeed, if the underlying container allowed it, they could be
made in parallel (a capability not supported in Ada 2022). The only
requirement is that the index be increasing for each expression. We add
"of the aggregate" to the wording to try to clarify that the index value isn't
related to the order in which the calls are made, just to the order of the
expressions in the aggregate.
(3) The proposed wording requires that the key_choice be evaluated before the
expression. For a key_choice that is a discrete_range, this is required, as we
don't know how many times to evaluate the expression and make the calls until
the range is evaluated. For other key_choices, we wouldn't need to insist on an
order, but doing so would make the wording even more complicated. The proposed
wording also assumes that the expression evaluations and the calls are done
together. This also would not be required, but practical concerns suggest that
implementations will always do this (one would need a lot of temporary places
to put key values and elements if they are evaluated before the calls are made).
!corrigendum 4.3.5(44/5)
Replace the paragraph:
- for a positional_container_aggregate that is an indexed
aggregate, each expression is evaluated in an arbitrary order, and the
Assign_Indexed procedure is invoked in sequence with the anonymous
object 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 expression, and the
result of evaluating each expression as the third parameter;
by:
- for a positional_container_aggregate that is an indexed
aggregate, each expression is evaluated in an arbitrary order, and the
Assign_Indexed procedure is invoked {once for each expression of the
aggregate with the anonymous object 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 expression of the
aggregate, and the result of evaluating each expression as the third
parameter;
!corrigendum 4.3.5(46/5)
Replace the paragraph:
- for a container_element_association with a key_choice_list,
for each key_choice of the list in an arbitrary order, the
key_choice is evaluated as is the expression of the
container_element_association (in an arbitrary order), and the
Add_Named procedure is invoked once for each value covered by the
key_choice, with the anonymous object A as the first parameter,
the value from the key_choice as the second parameter, and the
result of evaluating the expression as the third parameter;
by:
- for a container_element_association with a key_choice_list,
for each key_choice of the list in an arbitrary order, the
key_choice is evaluated, and the Add_Named procedure is invoked once for
each value covered by the key_choice (in an arbitrary order), with the
anonymous object A as the first parameter, the value from the
key_choice as the second parameter, and the result of evaluating the
expression of the container_element_association as the third
parameter;
!corrigendum 4.3.5(53/5)
Insert after the paragraph:
- 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.
the new paragraph:
When the above wording says that a subprogram is invoked or called, this is
a subprogram call as defined in 6.4, with parameter associations as
specified in the wording evaluated as defined 6.4.1. Redundant:[In
particular, this means that the parameters are converted to the subtype of
the formal parameter (which can raise an exception -- see 4.6).]
!ACATS test
ACATS C-Tests should check that each of these changes is followed. (The
existing 4.3.5 test objectives assume that all of these changes are made to
the language.)
!appendix
****************************************************************
Questions? Ask the ACAA Technical Agent