!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) @drepl @xbullet that is an indexed aggregate, each @fa is evaluated in an arbitrary order, and the Assign_Indexed procedure is invoked in sequence with the anonymous object @i 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, and the result of evaluating each @fa as the third parameter;> @dby @xbullet that is an indexed aggregate, each @fa is evaluated in an arbitrary order, and the Assign_Indexed procedure is invoked {once for each @fa of the @fa with the anonymous object @i 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 of the @fa, and the result of evaluating each @fa as the third parameter;> !corrigendum 4.3.5(46/5) @drepl @xinbull with a @fa, for each @fa of the list in an arbitrary order, the @fa is evaluated as is the @fa of the @fa (in an arbitrary order), and the Add_Named procedure is invoked once for each value covered by the @fa, with the anonymous object @i as the first parameter, the value from the @fa as the second parameter, and the result of evaluating the @fa as the third parameter;> @dby @xinbull with a @fa, for each @fa of the list in an arbitrary order, the @fa is evaluated, and the Add_Named procedure is invoked once for each value covered by the @fa (in an arbitrary order), with the anonymous object @i as the first parameter, the value from the @fa as the second parameter, and the result of evaluating the @fa of the @fa as the third parameter;> !corrigendum 4.3.5(53/5) @dinsa @xhang<@xterms<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 @i as the first parameter and the result of evaluating the @fa as the second parameter.> @dinst 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 ****************************************************************