!standard 4.3.3(2) 19-02-04 AI12-0306-1/01 !standard 4.3.3(3/5) !standard 4.3.3(9/5) !standard 4.3.3(26/5) !standard 4.3.3(26.1/5) !standard 4.3.3(33/3) !standard 4.3.3(38) !standard 4.3.3(39) !standard 4.3.3(42) !reference AI12-0212-1 !class Amendment 19-02-04 !status work item 19-02-04 !status received 19-01-23 !priority Low !difficulty Easy !subject Split null array aggregates from positional array aggregates !summary Change the syntax slightly to improve the wording of array aggregates. !problem The wording for null array aggregates seems unnecessarily complicated, defining a term and having to exclude that term from the bounds bullet. Also, some of the array aggregate examples ought to show the use of square brackets. And the first Note is now nonsense. !proposal (See Summary.) !wording Starting from the wording of AI12-0212-1: Replace 4.3.3(2) with: array_aggregate ::= positional_array_aggregate | null_array_aggregate | named_array_aggregate Replace 4.3.3(3/2) with: positional_array_aggregate ::= (expression, expression {, expression}) | (expression {, expression}, others => expression) | (expression {, expression}, others => <>) | '[' expression{, expression}[, others => expression] ']' | '[' expression{, expression}, others => <> ']' null_array_aggregate ::= '[' ']' Modify 4.3.3(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}[/null aggregate/ -- [ ]]. Add after 4.3.3(20): AARM To Be Honest: This is true even in cases where there is no corresponding legal positional_array_aggregate. [Author's note: We could have fixed this wording to make an equivalence of a null string_literal with a null_array_aggregate. However, considering that for Ada prior to Ada 2020, neither null or single character positional_array_aggregates existed, and we've never considered that a problem, why go all pedantic now?] Revert 4.3.3(26) to its Ada 95 version. (This removes "that is not a null aggregate".) Modify 4.3.3(26.1/5): For a {null_array_aggregate}[null aggregate], bounds for each dimension are determined as for a positional_array_aggregate with zero expressions for each dimension;} Replace AARM 4.3.3(26.a/5) with: AARM Reason: We need a separate rule to describe what happens for a multidimensional null_array_aggregate; we wouldn't have needed this rule only for the single dimension case. Replace 4.3.3(33/3) with: In an array_aggregate {delimited by parentheses}, positional notation may only be used with two or more expressions; a single expression in parentheses is interpreted as a parenthesized expression. {An array_aggregate delimited by brackets}[A named_array_aggregate, such as (1 => X),] may be used to specify an array with a single component. [Author's note: Just noticed that this Note is now a lie.] Change a few existing examples to use square brackets: Replace 4.3.3(38) with: (1 .. 5 => (1 .. 8 => 0.0)) -- two-dimensional [1 .. N => new Cell] -- N new cells, in particular for N = 0 Replace 4.3.3(39) with: 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 Replace 4.3.3(42) with: (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)] !discussion !ASIS Not sure, as there is a minor syntax change. !ACATS test No additional tests needed. !appendix From: Randy Brukardt Sent: Wednesday, January 23, 2019 6:17 PM [Split from a thread in AI12-0212-1 - Editor.] 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.) **************************************************************** From: Tucker Taft Sent: Wednesday, January 23, 2019 9:52 PM Might it be simpler to define "null_aggregate" in one place, and use it for both array aggregates and container aggregates? In any case, I agree with your moving the definition of the bounds of a multidimensional null aggregate to a more appropriate place. **************************************************************** From: Randy Brukardt Sent: Thursday, January 24, 2019 1:40 PM > Might it be simpler to define "null_aggregate" in one place, and use > it for both array aggregates and container aggregates? I thought of that, but it doesn't work well, because there are many rules that use the syntactic term "array_aggregate", and those (like the applicable index constraint) need to apply to a null array aggregate. We could try to say something like "a null_aggregate of an array type is a array_aggregate", but that's weird (we don't usually try to amend the meaning of syntax terms), and it increases the wording needed (I didn't check the containers wording, but I'd expect some similar issue to arise). Changing all of the wording to use an English term rather than syntax would be way too much churn (there are more than twenty such paragraphs). Probably the sweet spot is null_array_aggregate (which would, of course, be an array_aggregate) rather than having to use wording to separate it from positional_array_aggregate in the bounds rules. Should I write something like this up (later)? **************************************************************** From: Tucker Taft Sent: Thursday, January 24, 2019 6:37 PM ... > I thought of that, but it doesn't work well, because there are many > rules that use the syntactic term "array_aggregate", and those (like > the applicable index constraint) need to apply to a null array aggregate. Couldn't we write: array_aggregate ::= positional_array_aggregate | named_array_aggregate positional_array_aggregate ::= (...) | [...] | null_aggregate null_aggregate ::= '[' ']' That would seem to make it clear that one legal syntax for a positional_array_aggregate is null_aggregate. ... > Probably the sweet spot is null_array_aggregate (which would, of > course, be an array_aggregate) rather than having to use wording to > separate it from positional_array_aggregate in the bounds rules. > Should I write something like this up (later)? See my suggestion above. I realize I am probably missing something. **************************************************************** From: Randy Brukardt Sent: Thursday, January 24, 2019 7:07 PM > That would seem to make it clear that one legal syntax for a > positional_array_aggregate is null_aggregate. We could but it doesn't help any of the wording. ... > > Probably the sweet spot is null_array_aggregate (which would, of > > course, be an array_aggregate) rather than having to use wording to > > separate it from positional_array_aggregate in the bounds rules. > > Should I write something like this up (later)? > > See my suggestion above. I realize I am probably missing something. Yup. So far as I can tell, the only places where positional_array_aggregate is significant is in the equivalence for string literals and in the bounds of positional_array_aggregate. But, in the latter, we don't actually *want* a null aggregate to be treated the same as a positional_array_aggregate. And in the former, we have always allowed null strings and singleton strings even though there never was such a thing for positional_array_aggregates. So we don't really need to change that now, either. Every other rule is either on all array_aggregates or specific to named_array_aggregates. So, there is no advantage to having null_array_aggregate included in positional_array_aggregate (regardless of *how* its included), and depending on your view of the string literal rule, it could be a negative. (I'd probably change the string literal rule to explicitly include the null_array_aggregate case, just so we don't have that reach anymore, but that's clearly not required.) The point of the syntax change that I considered too much for an editorial review is to get it out of positional_array_aggregate altogether. If I was going to leave it in positional_array_aggregate, I could justify that, but it doesn't help the wording much. I'd rather help the wording more, or not bother. **************************************************************** From: Tucker Taft Sent: Saturday, January 26, 2019 6:15 PM Would things be simplified if we changed the wording slightly, as follows, where we leave the null aggregate (implicitly) within the first paragraph, but have an extra rule that is only for a null aggregate that is representing an aggregate for a multidimensional array type: "For a positional_array_aggregate Redundant[(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 Redundant[(or the length of the string_literal)]; {For a null aggregate for a multidimensional array type, 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.}" **************************************************************** From: Randy Brukardt Sent: Sunday, January 27, 2019 3:45 PM That's where I started, but that leaves these two bullets overlapping in the null aggregate multidimensional case (both bullets appear to apply). We could, I guess, leave it to common sense that the more specific bullet is the one to use, but it would be better to make it clear. I then tried: For a positional_array_aggregate Redundant[(or equivalent string_literal)] without an others choice {that is not a null aggregate for a multidimensional array type}, 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 for a multidimensional array type, 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.} But the exclusion text is a real mouthful, so I simplified it to what I have. Anyway, I thought it was better to separately define null_array_aggregate because: (1) It's more like the container_aggregate presentation; (2) It eliminates the need to define the term "null aggregate"; (3) It eliminates any need to mess with the positional_array_aggregate bullet. The downside is that it leaves the old handwaving about null string literals, but I suppose that's tolerable (we've tolerated it for at least 23 years, we can keep tolerating it). If you don't agree, that's fine, it's not that big of an improvement. That's why I asked rather than just doing it. But I don't think it is possible to do better outside of that than what I already proposed for the wording. **************************************************************** From: Tucker Taft Sent: Sunday, January 27, 2019 5:23 PM OK, your approach of defining null_array_aggregate seems like the right solution. **************************************************************** From: Randy Brukardt Sent: Friday, January 25, 2019 4:51 PM Should some of the examples in 4.3.3 be redone to use [] instead of ()? It seems that there should be some examples showing that use (esp. if we want to think of it as preferred in new code). **************************************************************** From: Gary Dismukes Sent: Friday, January 25, 2019 5:21 PM Definitely. *************************************************************** From: Randy Brukardt Sent: Friday, January 25, 2019 6:22 PM I think I've got a volunteer!!! ;-) ****************************************************************