!standard 4.3(2) 17-12-21 AI12-0127-1/13 !standard 4.3(3/2) !standard 4.3(4) !standard 4.3.1(9) !standard 4.3.1(15/3) !standard 4.3.1(16/4) !standard 4.3.1(17/5) !standard 4.3.1(17.1/2) !standard 4.3.3(4) !standard 4.3.3(14) !standard 4.3.3(17) !standard 4.3.4(0) !standard 7.5(2.6/2) !class Amendment 14-08-21 !status Amendment 1-2012 17-11-21 !status ARG Approved 8-0-0 17-10-14 !status work item 14-08-21 !status received 14-07-14 !priority Medium !difficulty Hard !subject Partial aggregate notation !summary A notation for updating part of a composite type is defined (where the remainder of the type is unchanged). !problem It is common to need to use an object of a composite type with just a small modification (often of a single component). This can be awkward to express in Ada. For instance, consider a record type Rec with many components, one of which is Colour, a variable R of type Rec, and the need to call procedure Foo with R but using the Black colour. There are two ways to do this in current Ada, but both are ugly. The first uses a temporary variable, a copy, and an assignment to the component: declare T : Rec := R; begin T.Colour := Black; Foo (T); end; The other way uses an aggregate listing all components of Rec, which is very cumbersome and a burden for maintenance: Foo ((X => R.X, Y => R.Y, ...., Colour => Black)); This construct is especially common in postconditions. It's common for a subprogram only to change a small part of a large composite type. procedure Foo (Fighters : in out Rec) with Post => (Fighters = (X => Fighters'Old.X, Y => Fighters'Old.Y, ... Colour => Black, Shape => Trapezoid)); This is cumbersome enough that the Postcondition author might check the changed component and not even mention that the other components are unchanged. Some better way to write these should be provided. [Editor's note: Sorry, these identifiers reminded me of the title of one of my favorite albums of all time. It should be pretty obvious (at least after a visit to Wikipedia); I would have liked to work in the two "the"s but that was over the top.] !proposal (See wording.) !wording Replace 4.3(2): aggregate ::= record_aggregate | extension_aggregate | array_aggregate with: aggregate ::= record_aggregate | extension_aggregate | array_aggregate | delta_aggregate Replace 4.3(3/2): The expected type for an aggregate shall be a single array type, record type, or record extension. with: 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 shall be a single array type, record type, or record extension. Replace 4.3(4): An aggregate shall not be of a class-wide type. with: A record aggregate or extension aggregate shall not be of a class-wide type. Modify 4.3.1(9): 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. AARM 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" don'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 variants. Replace 4.3.1(15/3) with: 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. AARM Ramification: /null record/ is not allowed at all in a record_delta_aggregate. Replace 4.3.1(16/4) with (2 paragraphs): 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. 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. Modify the start of 4.3.1(17/5): {For a record_aggregate or extension_aggregate, if}[If] a variant_part ... Add after 4.3.1(17.1/2): A record_component_association of the record_component_association_list of a record_delta_aggregate shall not: * use the compound delimiter <> (box) rather than an expression; * have an expression of a limited type; * omit the component_choice_list; or * have a component_choice_list that is an /others/ choice. For a record_delta_aggregate, no two component_selector_names shall denote components declared within different variants of the same variant part. Replace 4.3.3(4): named_array_aggregate ::= (array_component_association {, array_component_association}) with: named_array_aggregate ::= ( array_component_association_list ) array_component_association_list ::= array_component_association {, array_component_association} Add after 4.3.3(14): * For the *base_*expression of a delta_aggregate, if the nominal subtype of the delta_aggregate is a constrained array subtype, the applicable index constraint is the constraint of the subtype; In 4.3.3(17/5) replace: ... only if it is the single discrete_choice of its discrete_choice_list, and there is only one array_component_association in the array_aggregate. with: ... 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 REDUNDANT:[, not an array_aggregate]. AARM Ramification: We allow multiple dynamic choices in array delta aggregates, but only one dynamic choice per association even in that case. Add a new subclause: 4.3.4 Delta Aggregates A (record or array) delta aggregate yields a composite value resulting from starting with a copy of another value of the same type and then subsequently assigning to some (but typically not all) components of the copy. Syntax delta_aggregate ::= record_delta_aggregate | array_delta_aggregate record_delta_aggregate ::= (*base_*expression with delta record_component_association_list) array_delta_aggregate ::= (*base_*expression with delta array_component_association_list) Name Resolution Rules The expected type for a record_delta_aggregate shall be a single descendant of a record type or record extension. The expected type for an array_delta_aggregate shall be a single array type. The expected type for the *base_*expression of any delta_aggregate is the type of the enclosing delta_aggregate. @Redundant[The Name Resolution Rules and Legality Rules for each record_component_association of a record_delta_aggregate are as defined in 4.3.1.] 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. 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 For an array_delta_aggregate, the array_component_association shall not use the box symbol <>, and the discrete_choice shall not be others. For an array_delta_aggregate, the dimensionality of the type of the delta aggregate shall be 1. For an array_delta_aggregate, the *base_*expression and each expression in every array_component_association shall be of a nonlimited type. AARM 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 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 as the components necessarily are also limited except in pathological cases). Dynamic Semantics The evaluation of a delta_aggregate begins with evaluating the *base*_expression of the delta_aggregate and using that value to create and initialize the anonymous object of the aggregate. The bounds of the anonymous object of an array_delta_aggregate and the discriminants and tag (if any) of the anonymous object of a record_delta_aggregate are those of the *base_*expression. AARM 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. AARM Ramification: This requires that the underlying tag (if any) associated with the delta aggregate is that of the *base_*expression in the delta_aggregate and not that of the nominal type of the *base_*expression in the delta_aggregate. AARM 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. For a record_delta_aggregate, for each component associated with each record_component_association (in an unspecified order): * 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. * 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. 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): * the index value is converted to the index type of the array type. * 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. * the component expression is evaluated, converted to the array component subtype, and assigned to the component of the anonymous array object identified by the index value. Examples Simple use in a postcondition: procedure Twelfth (D : in out Date) -- see 3.8 for type Date with Post => D = (D'Old with delta Day => 12); 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); The base expression can be non-trivial: New_Cell : Cell := (Min_Cell (Link) with delta Value => 42); -- see 3.10.1 for Cell and Link; 6.1 for Min_Cell A1 : Vector := ((1.0, 2.0, 3.0) with delta Integer (Random * 3.0) => 14.2); -- see 3.6 for declaration of type Vector -- see 6.1 for declaration of Random Tomorrow := ((Yesterday with delta Day => 12) with delta Month => Apr); -- see 3.8 The base expression may also be class-wide: function Translate (P : Point'Class; X, Y : Float) return Point'Class is (P with delta X => P.X + X, Y => P.Y + Y); -- see 3.9 for declaration of type Point Add after 7.5(2.6/2): * the *base_*expression of a record_delta_aggregate (see 4.3.4) !discussion SPARK 2014 defines an attribute Update for this purpose. Using this attribute, the call in the question can be expressed as: Foo (R'Update (Colour => Black)); We believe it is better to use aggregate syntax for this, as we certainly want aggregate semantics relative to temporaries, build-in-place, limited types, resolution, and the like to apply. Additionally, by using aggregate notation, we can reuse some of the existing definitions for aggregate elements. Multi-dimensional array aggregates ---------------------------------- This will be a separate AI as it is much more complex than the record and single dimension array cases. Discriminants ------------- Should we allow discriminants in record updates? We decided "No". They would have to be listed first, and require any variant section to be completely updated. (Indeed, all discriminant-dependent components would have to be present.) !examples Using this facility, the initial example in the !problem can be written: Foo ((R with delta Colour => Black)); The postcondition example can be written as: procedure Foo (Fighters : in out Rec) with Post => (Fighters = (Fighters'Old with delta Colour => Black, Shape => Trapazoid)); Also see the examples in the !wording section. !corrigendum 4.3(2) @drepl @xcode<@fa@fa< ::= >@fa> @dby @xcode<@fa@fa< ::= >@fa> !corrigendum 4.3(3/2) @drepl The expected type for an @fa shall be a single array type, record type, or record extension. @dby The expected type for a @fa 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 shall be a single array type, record type, or record extension. !corrigendum 4.3(4) @drepl An @fa shall not be of a class-wide type. @dby A @fa or @fa shall not be of a class-wide type. !corrigendum 4.3.1(9) @drepl For the @fa of a @fa, all components of the composite value defined by the aggregate are @i; for the association list of an @fa, only those components not determined by the ancestor expression or subtype are needed (see 4.3.2). Each @fa in a @fa shall denote a needed component (including possibly a discriminant). @dby For the @fa of a @fa, all components of the composite value defined by the aggregate are @i; for the association list of an @fa, only those components not determined by the ancestor expression or subtype are needed (see 4.3.2). Each @i@fa in a @fa of a @fa or @fa shall denote a needed component (including possibly a discriminant). Each @i@fa in a @fa of a @fa (see 4.3.4) shall denote a nondiscriminant component of the type of the @fa. !corrigendum 4.3.1(15/3) @drepl The reserved words @b may appear only if there are no components needed in a given @fa. @dby A @fa shall be @b only if the list occurs in a @fa or @fa, and there are no components needed for that list. !corrigendum 4.3.1(16/4) @drepl Each @fa other than an @b choice with a <@> shall have at least one associated component, and each needed component shall be associated with exactly one @fa. If a @fa with an @fa 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. @dby For a @fa or @fa, each @fa other than an @b choice with a <@> shall have at least one associated component, and each needed component shall be associated with exactly one @fa. For a @fa, each @I@fa of each @fa shall denote a distinct nondiscriminant component of the type of the aggregate. If a @fa with an @fa 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. !corrigendum 4.3.1(17/5) @drepl The value of a discriminant that governs a @fa @i

shall be given by a static expression, unless @i

is nested within a @fa @i that is not selected by the discriminant value governing the @fa enclosing @i. @dby For a @fa or @fa, if a @fa @i

is nested within a @fa @i that is not selected by the discriminant value governing the @fa enclosing @i, then there is no restriction on the discriminant governing @i

. Otherwise, the value of the discriminant that governs @i

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 @fa of @i

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. !corrigendum 4.3.1(17.1/2) @dinsa A @fa for a discriminant without a @fa shall have an @fa rather than <@>. @dinss A @fa of the @fa of a @fa shall not: @xbullet (box) rather than an @fa;> @xbullet of a limited type;> @xbullet; or> @xbullet that is an @b choice.> For a @fa, no two @i@fas shall denote components declared within different @fas of the same @fa. !corrigendum 4.3.3(4) @drepl @xcode<@fa@fa< ::=> @fa<(array_component_association {, array_component_association})>> @dby @xcode<@fa@fa< ::= ( array_component_association_list )>> @xcode<@fa@fa< ::=> @fa> !corrigendum 4.3.3(14) @dinsa @xbullet in an @fa, if the component's nominal subtype is a constrained array subtype, the applicable index constraint is the constraint of the subtype;> @dinst @xbullet@fa of a @fa, if the nominal subtype of the @fa is a constrained array subtype, the applicable index constraint is the constraint of the subtype;> !corrigendum 4.3.3(17/3) @drepl The @fa of an @fa is allowed to have a @fa that is a nonstatic @fa or that is a @fa or @fa that defines a nonstatic or null range, only if it is the single @fa of its @fa, and there is only one @fa in the @fa. @dby The @fa of an @fa (including an @fa) is allowed to have a @fa that is a nonstatic @fa or that is a @fa or @fa that defines a nonstatic or null range, only if it is the single @fa of its @fa, and either there is only one @fa in the enclosing @fa or the enclosing @fa is an @fa, not an @fa. !corrigendum 4.3.4(0) @dinsc A (record or array) delta aggregate yields a composite value resulting from starting with a copy of another value of the same type and then subsequently assigning to some (but typically not all) components of the copy. @s8<@i> @xcode<@fa@fa< ::= >@fa | @fa> @xcode<@fa@fa< ::=> @fa<(@iexpression >@ft<@b>@fa< record_component_association_list)>> @xcode<@fa@fa< ::=> @fa<(@iexpression >@ft<@b>@fa< array_component_association_list)>> @s8<@i> The expected type for a @fa shall be a single descendant of a record type or record extension. The expected type for an @fa shall be a single array type. The expected type for the @i@fa of any @fa is the type of the enclosing @fa. The Name Resolution Rules and Legality Rules for each @fa of a @fa are as defined in 4.3.1. For an @fa, the expected type for each @fa in an @fa is the index type of the type of the @fa. The expected type of the @fa in an @fa is defined as for an @fa occurring within an @fa of the type of the @fa. @s8<@i> For an @fa, the @fa shall not use the box symbol <@>, and the @fa shall not be @b. For an @fa, the dimensionality of the type of the @fa shall be 1. For an @fa, the @i@fa and each @fa in every @fa shall be of a nonlimited type. @s8<@i> The evaluation of a @fa begins with evaluating the @i@fa of the @fa and using that value to create and initialize the anonymous object of the @fa. The bounds of the anonymous object of an @fa and the discriminants and tag (if any) of the anonymous object of a @fa are those of the @i@fa. For a @fa, for each component associated with each @fa (in an unspecified order): @xbullet, 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.> @xbullet of the @fa is evaluated, converted to the nominal subtype of the associated component, and assigned to the component of the anonymous object.> For an @fa, for each @fa of each @fa (in the order given in the enclosing @fa and @fa, respectively) the @fa is evaluated; for each represented index value (in ascending order, if the @fa represents a range): @xbullet @xbullet; Constraint_Error is raised if this check fails.> @xbullet is evaluated, converted to the array component subtype, and assigned to the component of the anonymous object identified by the index value.> @s8<@i> Simple use in a postcondition: @xcode<@b Twelfth (D : @b Date) --@ft<@i< see 3.8 for type Date>> @b Post =@> D = (D'Old @b Day =@> 12);> @xcode<@b The_Answer (V : @b Vector; A, B : @b Integer) --@ft<@i< see 3.6 for type Vector>> @b Post =@> V = (V'Old @b A .. B =@> 42.0, V'First =@> 0.0);> The base expression can be non-trivial: @xcode Value =@> 42); --@ft<@i< see 3.10.1 for Cell and Link; 6.1 for Min_Cell>>> @xcode Integer (Random * 3.0) =@> 14.2); --@ft<@i< see 3.6 for declaration of type Vector>> --@ft<@i< see 6.1 for declaration of Random>>> @xcode Day =@> 12) @b Month =@> Apr); --@ft<@i< see 3.8>>> The base expression may also be class-wide: @xcode<@b Translate (P : Point'Class; X, Y : Float) @b Point'Class @b (P @b X =@> P.X + X, Y =@> P.Y + Y); --@ft<@i< see 3.9 for declaration of type Point>>> !corrigendum 7.5(2.6/2) @dinsa @xbullet of a @fa or the @fa of an array_component_association (see 4.3.3)> @dinst @xbullet@fa of a @fa (see 4.3.4)> !ASIS No ASIS impact. !ACATS test ACATS B-Tests and C-Tests are needed to test the implementation of this feature. !appendix topic Adding partial aggregate functionality to Ada !reference Ada 2012 RM{clause unsure} !from Simon Clubley 2014-07-13 !keywords partial aggregate device register bitfields atomic updating [The original motivation for this proposal was the simultaneous updating of multiple bitfields in a device register. However, discussions in comp.lang.ada have revealed a wide range of potential uses for this notation which would allow these other existing uses to be expressed more cleanly. The examples demonstrating the wider potential of this proposal were provided by Niklas Holsti.] Background ---------- Ada can model the bitfields in a device register as a record type containing those bitfields and can map an instance of that record type to the address of that device register. However, sometimes there is a requirement to be able to update a subset of those bitfields as an atomic operation while preserving the contents of the other bitfields in the record. In Ada, the only way to do this (apart from C style bitmasks on an integer variable) is to read the device register into a temporary instance of the record type, modify the temporary variable and write the temporary variable back to the device register. This, to put it mildly, is ugly. Normal (non-atomic) records also have similar issues. For normal records, consider a record type Rec with many components, one of which is Colour, a variable R of type Rec, and the need to call procedure Foo twice, once using R with its own Colour, and once with R but using the Black colour. There are two ways to do this in current Ada, but both are ugly. The first uses a temporary variable, a copy, and an assignment to the component: declare T : Rec := R; begin Foo (R); T.Colour := Black; Foo (T); end; The other way uses an aggregate listing all components of Rec, which is very cumbersome and a burden for maintenance: Foo (R); Foo ((X => R.X, Y => R.Y, ...., Colour => Black)); Proposal -------- An elegant solution for these problems would be a new partial aggregate syntax in which the list of record components to be modified would be listed along with their new values. One suggested syntax would be: A := (A changing C => D, E => F); or A := (A updating C => D, E => F); where A is a record and C and E are record components. [When this syntax discussion took place in comp.lang.ada, one suggestion for the keyword was "overriding" but I didn't like that because that keyword made it seem as if A was the one doing the overriding, not the later C and E references.] For an Atomic record, the compiler would generate a sequence which performs an atomic read of the whole record into a compiler generated temporary, modifies this temporary with the new component values, then performs an atomic write of this temporary back to the whole record. As the sequence would be performed on the record as a whole, C.6(15) would be guaranteed to apply. This means there would be a single read of the device register and a single write to the device register. For the normal record example above, one could simply write instead Foo (R); Foo ((R changing Colour => Black)); which is much more elegant than the above methods currently provided by Ada. In addition, Niklas also provided the following array aggregate example: type Month_Days is array (Month) of Positive; Normal_Year_Days : constant Month_Days := (Jan => 31, Feb => 28, Mar => 31, ..., Dec => 31); Leap_Year_Days : constant Month_Days := (Normal_Year_Days changing Feb => 29); It was also suggested partial aggregates could be of use in contracts within Ada 2012 and also had some uses within SPARK. However, this is one area I currently have no experience with, so I reproduce the following example as-is: |I have not yet used Ada 2012 contracts in my programming, but I believe |that partial aggregates would be quite useful in post-conditions, to |express that some "out" value is the same as some "in" value except for |changes to certain components: | | with Post => X = (X'old changing Colour => Black) Regarding the use of a new keyword, I do think we need a new keyword because we are talking about adding a subset update capability to Ada and that new usage should stand out in any code. **************************************************************** From: Tucker Taft Sent: Tuesday, July 15, 2014 11:49 AM Interestingly, SPARK 2014 has a capability almost exactly matching this, using an attribute "'Update"; for example: T : Rec := R'Update (Colour => Black); or Foo (R'Update (Colour => Black)); I believe this attribute is also available in recent releases of GNAT, though clearly at this stage it is non portable. **************************************************************** From: Randy Brukardt Sent: Tuesday, July 15, 2014 5:46 PM Steve Baird had told me about this attribute in Paris. One thing almost everyone I've talked to about it agrees is that this is a hack as an attribute -- this is a kind of aggregate and ought to look like it. Attributes are supposed to be kinds of function calls, but it's not possible to write this Update attribute as a function call. Moreover, we would want all of the aggregate rules to apply to the contents, and there aren't function calls like: R'Update (Primary_Color => True); -- Primary_Color is a subtype with a static predicate or R'Update (1..5 => True); Most likely, we'd want the aggregate rules to apply to the result, as well (build-in-place, etc. -- but here at least a function call is consistent with aggregates). SPARK had to make this an attribute because they couldn't add new syntax. That's no reason for Ada itself to limit itself in such a way. (As one Tucker Taft has said in the past, new features shouldn't look "bolted-on", and I can't imagine a worse "bolt-on" than using an attribute with aggregate semantics instead of a proper aggregate.) Ergo, this phony attribute should stay a SPARK-only thing; Ada needs a proper aggregate syntax for this. **************************************************************** From: Simon Clubley Sent: Wednesday, July 16, 2014 4:25 PM > Interestingly, SPARK 2014 has a capability almost exactly matching > this, using an attribute "'Update"; for example: > > T : Rec := R'Update (Colour => Black); > > or > > Foo (R'Update (Colour => Black)); > > I believe this attribute is also available in recent releases of > GNAT, though clearly at this stage it is non portable. Thanks. Yes, it is in GNAT. I did notice http://gcc.gnu.org/onlinedocs/gnat_rm/Attribute-Update.html is silent about if C.6(15) is guaranteed to apply when R (in your example) is Atomic. > Steve Baird had told me about this attribute in Paris. One thing > almost everyone I've talked to about it agrees is that this is a hack > as an attribute -- this is a kind of aggregate and ought to look like it. I agree with this; I think a "real" partial aggregate syntax is required. Are there any thoughts on how the proposed syntax could be improved ? > Ergo, this phony attribute should stay a SPARK-only thing; Ada needs a > proper aggregate syntax for this. Is there support here for adding partial aggregates to the next version of Ada? When combined with an Atomic record, such syntax would allow the simultaneous updating of multiple bitfields within a record mapped to a device register. It would also be useful in a more general way as shown by the examples provided in comp.lang.ada and reproduced in my submission. **************************************************************** From: Steve Baird Sent: Tuesday, July 22, 2014 12:41 PM > I think a "real" partial aggregate syntax is required. > Are there any thoughts on how the proposed syntax could be improved ? Randy and I have discussed the possibility of using extension aggregate syntax except using "with delta" in place of "with". Given type T is record F1, F2, F3, F4 : Integer; end record; X : T; and then taking this approach X'Update (F3 => 123, F4 => 456); could be expressed as (X with delta F3 => 123, F4 => 456); At this point this is nothing more than an idea that came up in conversation. **************************************************************** From: Randy Brukardt Sent: Tuesday, July 22, 2014 1:08 PM But of course one that will be included in the AI associated with this thread. So the idea will at least be on the radar. **************************************************************** From: Mark Lorenzen Sent: Wednesday, July 23, 2014 4:12 AM > I agree with this; I think a "real" partial aggregate syntax is > required. > > Are there any thoughts on how the proposed syntax could be improved ? It could maybe be done as for an extension aggregate, unless that would confuse users: Foo (R with Colour => Black); or S := (R with Colour => Black); **************************************************************** From: Simon Clubley Sent: Wednesday, July 23, 2014 3:05 PM > Randy and I have discussed the possibility of using extension > aggregate syntax except using "with delta" in place of "with". > > Given > type T is record F1, F2, F3, F4 : Integer; end record; > X : T; > and then taking this approach > X'Update (F3 => 123, F4 => 456); > could be expressed as > (X with delta F3 => 123, F4 => 456); I don't like the idea of seeing just the exact same "with" extension aggregate notation re-used for partial aggregates as I think that would be too confusing. However, while I think new syntax such as "changing" would be best, if the desire is to re-use existing keywords, then I think your "with delta" suggestion is by far the best of the suggestions I have seen so far and would not be confused with an extension aggregate. **************************************************************** From: Christoph Grein Sent: Thursday, July 24, 2014 5:13 AM The problem with these two reserved words F (X with delta F3 => 123, F4 => 456); is that one might easily forget the delta and, with some overloading of F, might arrive at a different legal interpretation. **************************************************************** From: Tucker Taft Sent: Sunday, July 27, 2014 3:23 PM Somewhat unlikely because Ada requires that there be a unique interpretation provided by context before looking inside an aggregate. **************************************************************** From: Steve Baird Sent: Saturday, June 27, 2015 9:17 AM The Update attribute provides a way of overwriting specified components of a copy of a given composite value. For a prefix ``X`` that denotes an object of a nonlimited record type or record extension ``T``, the attribute :: X'Update ( record_component_association_list ) is defined and yields a value of type ``T`` and is a *record update expression*. For a prefix ``X`` that denotes an object of a nonlimited one dimensional array type ``T``, the attribute :: X'Update ( array_component_association {, array_component_association} ) is defined and yields a value of type ``T`` and is an *array update expression*. For a prefix ``X`` that denotes an object of a nonlimited multidimensional array type ``T``, the attribute :: X'Update ( multidimensional_array_component_association {, multidimensional_array_component_association} ) is defined and yields a value of type ``T`` and is a *multi-dimensional array update*. Where ``multidimensional_array_component_association`` has the following syntax: .. centered:: **Syntax** :: multidimensional_array_component_association ::= index_expression_list_list => expression index_expression_list_list ::= index_expression_list { | index_expression_list } index_expression_list ::= ( expression {, expression} ) .. centered:: **Legality Rules** 1. The box symbol, <>, may not appear in any ``expression`` appearing in an *update expression*. .. centered:: **Dynamic Semantics** 2. In all cases (i.e., whether ``T`` is a record type, a record extension type, or an array type - see below), evaluation of ``X'Update`` begins with the creation of an anonymous object of type ``T`` which is initialized to the value of ``X`` in the same way as for an occurrence of ``X'Old`` (except that the object is constrained by its initial value but not constant). 3. Next, components of this object are updated as described in the following subsections. The attribute reference then denotes a constant view of this updated object. The master and accessibility level of this object are defined as for the anonymous object of an aggregate. 4. The assignments to components of the result object described in the following subsections are assignment operations and include performance of any checks associated with evaluation of the target component name or with implicit conversion of the source value to the component subtype. Record Update Expressions ^^^^^^^^^^^^^^^^^^^^^^^^^ For a record update expression of type ``T`` the following are required. .. centered:: **Legality Rules** 5. The ``record_component_association_list`` shall have one or more ``record_component_associations``, each of which shall have a non-**others** ``component_choice_list`` and an expression. 6. Each ``selector_name`` of each ``record_component_name`` shall denote a distinct non discriminant component of ``T``. 7. Each ``record_component_association``'s associated components shall all be of the same type. The expected type and applicable index constraint of the expression is defined as for a ``record_component_association`` occurring within a record aggregate. 8. Each selector of all ``component_choice_lists`` of a record update expression shall denote a distinct component. .. centered:: **Dynamic Semantics** 9. For each component for which an expression is provided, the expression value is assigned to the corresponding component of the result object. The order in which the components are updated is unspecified. [Components in a record update expression must be distinct. The following is illegal :: Some_Record'Update (Field_1 => ... , Field_2 => ... , Field_1 => ... ); -- illegal; components not distinct because the order of component updates is unspecified.] Array Update Expressions ^^^^^^^^^^^^^^^^^^^^^^^^^ For an array update expression of type ``T`` the following are required. .. centered:: **Legality Rules** 10. Each ``array_component_association`` of the attribute reference shall have one or more ``array_component_associations``, each of which shall have an expression. 11. The expected type and applicable index constraint of the expression is defined as for an ``array_component_association`` occurring within an array aggregate of type ``T``. The expected type for each ``discrete_choice`` is the index type of ``T``. 12. The reserved word **others** shall not occur as a ``discrete_choice`` of an ``array_component_association`` of the ``attribute_reference``. .. centered:: **Dynamic Semantics** 13. The discrete choices and array component expressions are evaluated. Each array component expression is evaluated once for each associated component, as for an array aggregate. For each such associated component of the result object, the expression value is assigned to the component. 14. Evaluations and updates are performed in the order in which the ``array_component_associations`` are given; within a single ``array_component_association``, in the order of the ``discrete_choice_list``; and within the range of a single ``discrete_choice``, in ascending order. [Note: the ``Update`` attribute for an array object allows multiple assignments to the same component, as in either :: Some_Array'Update (1 .. 10 => True, 5 => False) or :: Some_Array'Update (Param_1'Range => True, Param_2'Range => False) -- ok even if the two ranges overlap] Multi-dimensional Array Update Expressions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ For a multi-dimensional array update expression of type ``T`` the following are required. .. centered:: **Legality Rules** 15. The expected type and applicable index constraint of the expression of a ``multidimensional_array_component_association`` are defined as for the expression of an ``array_component_association`` occurring within an array aggregate of type ``T``. 16. The length of each ``index_expression_list`` shall equal the dimensionality of ``T``. The expected type for each expression in an ``index_expression_list`` is the corresponding index type of ``T``. .. centered:: **Dynamic Semantics** 17. For each ``multidimensional_array_component`` association (in the order in which they are given) and for each ``index_expression_list`` (in the order in which they are given), the index values of the ``index_expression_list`` and the expression are evaluated (in unspecified order) and the expression value is assigned to the component of the result object indexed by the given index values. Each array component expression is evaluated once for each associated ``index_expression_list``. **************************************************************** From: Florian Schanda Sent: Monday, June 6, 2016 8:38 AM This AI is part of my (overdue) Pisa homework. I have worked on this with the help of Steve. It should be concrete enough so that we have something to discuss. [This is version /02 of the AI - Ed.] **************************************************************** From: Bob Duff Sent: Monday, June 6, 2016 12:14 PM > A (record, array, multidimensional) delta aggregate yields a composite > value resulting from copying another value of the same type and then > subsequently assigning to some (but typically not all) components of > the copy. I like this feature. I don't much like the keyword "delta"; seems contrived. But I suppose I won't complain too loudly about that. "update" is probably way too incompatible. Unless we (again) try to go the "unreserved keyword" route. E.g.: (X update with ...) > index_tuple ::= ( expression {, expression} ) There seems to be a syntactic ambiguity here. Is this: X := (X with delta (1) => Y); an array delta aggregate or a multidimensional delta aggregate? Seems like you want: index_tuple ::= ( expression, expression {, expression} ) > ** Name Resolution Rules ** > > The type of a delta aggregate is the same as the type of the > expression in delta_aggregate. I think you want the type to come from context, like other aggregates. Then that type becomes the expected type for the expression. > For an array delta aggregate, the dimensionality of the type of the > delta aggregate shall be 1; for a multidimensional delta aggregate the > dimensionality of the type of the delta aggregate shall more than 1. Here's a place where the above-mentioned ambiguity comes into play. > Ranges in multidimensional updates > ---------------------------------- > > This is a proposal to allow more helpful (but slightly more complex) > multidimensional delta aggregates. It is presented as a modification > to the above !wording section. I'd leave this functionality out. **************************************************************** From: Randy Brukardt Sent: Monday, June 6, 2016 11:42 PM > This AI is part of my (overdue) Pisa homework. I have worked > on this with the help of Steve. It should be concrete enough > so that we have something to discuss. I suppose we should know better than to pair the new guy with Steve; Steve makes me work more than anyone else to construct a complete AI out of pieces. Anyway, I reformatted the submission to make it fit the standard AI format; the discussion is light and the name of the new feature switches back and forth between "partial aggregate" (the name in the first draft) and "delta aggregate" (the name in the second draft). Issues that can be fixed, but probably don't matter if there are major problems with this (not that I see any). **************************************************************** From: Steve Baird Sent: Tuesday, June 7, 2016 2:32 AM >> For an array delta aggregate, the dimensionality of the type of the >> delta >> >aggregate shall be 1; for a multidimensional delta aggregate the >> >dimensionality of the type of the delta aggregate shall more than 1. > Here's a place where the above-mentioned ambiguity comes into play. > I'd say that's the place where the ambiguity is resolved. But I agree that your proposed syntax change is an improvement and with that change there is no ambiguity to even discuss. > I think you want the type to come from context, like other aggregates. > Then that type becomes the expected type for the expression. Interesting question. Given that we didn't modify 4.3(3/2), I agree with you. But we could modify that rule. Do we want to allow type T is new String; procedure P (X : String) is ... ; procedure P (X : T) is ... ; Y : String := ... ; begin P (X => (Y with delta ...)); ? Probably not, so 4.3(3/2) is left unmodified and I agree with your proposed change. **************************************************************** From: Randy Brukardt Sent: Tuesday, June 7, 2016 5:02 PM I've applied these two changes into the working draft of the AI (so we don't have to waste meeting time discussing them). I changed the Name Resolution Rule in A.3.4 as follows (copying A.3.2 as closely as possible): The expected type for a delta_aggregate shall be a single array type, record type, or record extension. The expected type for the *base_*expression is the type of the enclosing delta_aggregate. Note that I gave the first expression in the aggregate a prefix so it can't be confused with any of the others: delta_aggregate ::= (*base_*expression with delta delta_aggregate_association) We may want to come up with a better prefix for this. The next paragraph doesn't make any sense as written: The expected type for expression in a delta_aggregate depends on which form of delta_aggregate_association is used: a record type for record_component_association_list, and an array type for array_component_association_list or multidimensional_array_component_association_list. The *base_*expression's type doesn't depend on that at all, and there is no other expression (directly) in the syntax of a delta_aggregate. The way expressions in component_associations are interpreted depends on those component associations, but that is already defined in 4.3.1 and 4.3.3 (to the extent that you reuse those, hopefully a lot). Indeed, I'd only mention the types for the new kind of association, the multidimensional_array_component_association. The others are defined where they're declared, repeating wording here is only going to introduce conflicts. (I didn't make that change in the draft, it needs discussion.) **************************************************************** From: Tucker Taft Sent: Tuesday, June 7, 2016 5:16 PM I agree with your points here Randy. I had the same concerns with some of the wording. **************************************************************** From: Randy Brukardt Sent: Tuesday, June 7, 2016 5:40 PM ... > The next paragraph doesn't make any sense as written: > > The expected type for expression in a delta_aggregate depends on which > form of delta_aggregate_association is used: a record type for > record_component_association_list, and an array type for > array_component_association_list or > multidimensional_array_component_association_list. It strikes me that there needs to be a Legality Rule that prevents a record from having array components and vice versa. But we surely wouldn't want to get that tangled into resolution. Resolution is hard enough as it is, and we don't want to make it too smart. The Legality Rule could be: If the delta_aggregate contains a record_component_association_list, the type of the *base_*expression shall be a record type. Similarly, if the delta_aggregate contains an array_component_association_list or multidimensional_array_component_list, the type of the *base_*expression shall be an array type. Perhaps this could be combined with some of the other Legality Rules. **************************************************************** From: Bob Duff Sent: Tuesday, June 7, 2016 6:03 PM > >> For an array delta aggregate, the dimensionality of the type of the > >> delta > >> >aggregate shall be 1; for a multidimensional delta aggregate the > >> >dimensionality of the type of the delta aggregate shall more than 1. > > Here's a place where the above-mentioned ambiguity comes into play. > > > > I'd say that's the place where the ambiguity is resolved. No, that's not marked as a Name Resolution rule. Just Legality. So it can't be used to resolve syntactic ambiguities. > But I agree that your proposed syntax change is an improvement and > with that change there is no ambiguity to even discuss. OK. > > I think you want the type to come from context, like other aggregates. > > Then that type becomes the expected type for the expression. > > Interesting question. Given that we didn't modify 4.3(3/2), I agree > with you. But we could modify that rule. > > Do we want to allow > > type T is new String; > procedure P (X : String) is ... ; > procedure P (X : T) is ... ; > Y : String := ... ; > begin > P (X => (Y with delta ...)); No. Resolution rules should be weak. > ? Probably not, so 4.3(3/2) is left unmodified and I agree with your > proposed change. **************************************************************** From: Steve Baird Sent: Wednesday, June 8, 2016 5:58 AM > It strikes me that there needs to be a Legality Rule that prevents a > record from having array components and vice versa We already have name resolution rules like 4.3.1 - The expected type for a record_aggregate shall be a single record type or record extension. 4.3.2 - The expected type for an extension_aggregate shall be a single type that is a record extension. 4.3.3 - The expected type for an array_aggregate (that is not a subaggregate) shall be a single array type Would it be more consistent to have name resolution rules (as opposed to legality rules) which specify that the expected type of a delta_aggregate is a single record type or record extension if the delta_aggregate_association is a record_component_association_list and a single array type otherwise ? **************************************************************** From: Tucker Taft Sent: Wednesday, June 8, 2016 6:05 AM I think you might have it backwards. The expected type for an aggregate comes first, then you indicate what is allowed inside. There is a fundamental rule with aggregates that you don't look "inside" until you know what is the type of the aggregate. **************************************************************** From: Bob Duff Sent: Wednesday, June 8, 2016 6:05 AM > Would it be more consistent to have name resolution rules (as opposed > to legality rules) which specify that the expected type of a > delta_aggregate is a single record type or record extension if the > delta_aggregate_association is a record_component_association_list and > a single array type otherwise ? Maybe have separate syntax rules for delta_record_aggregate and delta_array_aggregate. **************************************************************** From: Florian Schnada Sent: Thursday, September 29, 2016 9:16 AM This is my attempt at implementing everything that was discussed and recorded in the minutes (btw, thanks Randy for these, they are excellent!). I have also attached a patch for the text file version. This may be more convenient for you to apply. YMMV. [Following was version /04 of the AI.] **************************************************************** From: Edmond Schonberg Sent: Thursday, September 29, 2016 4:29 PM Excellent write-up! One question about array delta aggregates: the text suggests that each delta is a modification of a single component, but discrete_choices include ranges and subtype indications, which imply slice assignments. Are such choices excluded, or should the text mention indexed components and slices as legal targets of a delta assignment? **************************************************************** From: Randy Brukardt Sent: Thursday, September 29, 2016 4:51 PM I haven't read Florian's write up yet, but discrete range choices and the like of aggregates are modeled as a loop in the language semantics -- the component value is evaluated and assigned for each value of the range (in an unspecified order). I would have expected Florian's write-up to keep the semantics of each kind of choice the same, so that there is as little new complication as possible. (I'm sure he doesn't want to redescribe the various kinds of array choices and their semantics.) Ergo, there are no "slice assignments"; it's just a bunch of individual components being updated. That's important for wording purposes (whether one wants to think of it as a slice assignment is your own option, of course, but the language certainly would not consider it so). Specifically: (A delta 1..3 => Foo) and (A delta 1 => Foo, 2 => Foo, 3 => Foo) have exactly the same canonical semantics, and there is no slice anywhere to be seen. **************************************************************** From: Tucker Taft Sent: Thursday, September 29, 2016 4:57 PM > I haven't read Florian's write up yet, but discrete range choices and > the like of aggregates are modeled as a loop in the language semantics > -- the component value is evaluated and assigned for each value of the > range (in an unspecified order). > > I would have expected Florian's write-up to keep the semantics of each > kind of choice the same, so that there is as little new complication as possible. > (I'm sure he doesn't want to redescribe the various kinds of array > choices and their semantics.) > > Ergo, there are no "slice assignments"; it's just a bunch of > individual components being updated. That's important for wording > purposes (whether one wants to think of it as a slice assignment is > your own option, of course, but the language certainly would not consider it so). I agree with the above. > Specifically: > (A delta 1..3 => Foo) > and (A delta 1 => Foo, 2 => Foo, 3 => Foo) > > have exactly the same canonical semantics, and there is no slice > anywhere to be seen. Agreed. But I also haven't gone through the proposed wording in detail yet! **************************************************************** From: Edmond Schonberg Sent: Thursday, September 29, 2016 5:02 AM > Specifically: > (A delta 1..3 => Foo) > and (A delta 1 => Foo, 2 => Foo, 3 => Foo) > > have exactly the same canonical semantics, and there is no slice > anywhere to be seen. > Makes sense, and indeed the code will have to consist of individual assignments. **************************************************************** From: Tucker Taft Sent: Thursday, September 29, 2016 5:13 PM Generally, looks good! But... I worry that we are referencing the semantics of 'Old and build-in-place in the dynamic semantics section. I could see mentioning them in an AARM note. But expecting the reader, as an aid to understanding the dynamic semantics of delta aggregates, to have to look forward to the definition of 'Old, followed by a perusal of the build-in-place rules, seems downright perverse! ;-) You have these references in brackets, so I presume that means this is redundant information and hence not necessary to appear in normative RM text here. If so, I heartily suggest that the bracketed wording move to an AARM note. **************************************************************** From: Randy Brukardt Sent: Sunday, October 2, 2016 11:48 PM > ... But expecting the > reader, as an aid to understanding the dynamic semantics of delta > aggregates, to have to look forward to the definition of 'Old, > followed by a perusal of the build-in-place rules, seems downright > perverse! ;-) I recognize the Hand of Baird in this text! ;-) Steve was originally a co-author on this AI. **************************************************************** From: Randy Brukardt Sent: Sunday, October 2, 2016 11:24 PM > This is my attempt at implementing everything that was discussed and > recorded in the minutes (btw, thanks Randy for these, they are > excellent!). I have also attached a patch for the text file version. > This may be more convenient for you to apply. YMMV. One thing that was suggested in e-mail [by Bob, I think] (not the minutes) was to completely separate the syntax and rules for record_delta_aggregate and array_delta_aggregate, since they're mostly disjoint anyway. That should decrease the verbiage. I was expecting this change to be made (because it was obvious to me), but since it was left out of the minutes, I'm not surprised it wasn't. This could start something like: 4.3.4 Delta Aggregates A (record or array) delta aggregate yields a composite value resulting from copying another value of the same type and then subsequently assigning to some (but typically not all) components of the copy. Syntax record_delta_aggregate ::= (*base_*expression with delta record_component_association_list) array_delta_aggregate ::= (*base_*expression with delta array_component_association_list) Name Resolution Rules The expected type for a record_delta_aggregate shall be a single record type or record extension. The expected type for an array_delta_aggregate shall be a single array type. The expected type for the *base_*expression of either of these agrgegates is the type of the enclosing record_delta_aggregate or array_delta_aggregate For a record_delta_aggregate, the expected type and applicable index constraint of the expression in each record_component_association is defined as for a record_component_association occurring within a record aggregate. For an array_delta_aggregate, the expected type for each discrete_choice in an array_component_association is the index type of type of the array_delta_aggregate. The expected type and applicable index constraint of the expression in array_component_association is defined as for an array_component_association occurring within an array aggregate of the type of the array_delta_aggregate. .... You could even put them into separate clauses to get rid of all of the "for a record delta aggregate ..."s. **************************************************************** From: Randy Brukardt Sent: Sunday, October 2, 2016 11:35 PM Other comments on the draft: For a delta aggregate the expression in a record_component_association or a array_component_association shall not be of a limited type. Which expression is being discussed here? I'd guess that it is supposed to be the *base*_expression, and if that's the intent, this rule should say that. (Use the prefix if you go through the trouble to define it!) [P.S. I took the extra comma out of your version.] --- I second Tucker's comment about 'Old. I can't imagine what that has to do with aggregate semantics; it would make more sense if 'Old had been described in terms of delta aggregate semantics. I think that whatever semantics needs to be described normatively, needs to be described here, and the rest can go into an AARM note. We especially don't want a forward reference here. --- In the examples, you need cross-references to where the objects/types are declared elsewhere in the RM. For instance, the first example should have something like "(See x.x.x for the declaration of D.)" as part of the comment. I'm not going to try to figure out where an object named "D" is declared in the RM! (Searching doesn't work for obvious reasons.) **************************************************************** From: Randy Brukardt Sent: Sunday, October 2, 2016 11:35 PM Two other comments: > For a delta aggregate the expression in a record_component_association > or a array_component_association shall not be of a limited type. > > Which expression is being discussed here? I'd guess that it is > supposed to be the *base*_expression, and if that's the intent, this > rule should say that. (Use the prefix if you go through the trouble to > define it!) [P.S. I took the extra comma out of your version.] The rule added after 7.5(2.10/2) has the same issue. The reason this is important is by leaving out the prefix, the reader wonders if that was on purpose. --- You didn't update the rest of the AI, particularly the !discussion. I deleted all of the multidimensional text, but otherwise left it unchanged. PLEASE do not get in the habit of just updating the wording and leaving the rest of it to the poor editor. The wording is often the easy part! And I am not good at guessing what your intent is (which is what goes in the discussion). I'll fix up headers and file e-mail, but that's it. There's one other ARG member who is in that habit whom I won't name but will identify as "Heave Beard", and it's important to point out that it isn't acceptable. I don't have much hope of fixing Heave Beard but I don't plan to let anyone else get away with it consistently. **************************************************************** From: Florian Schanda Sent: Tuesday, October 4, 2016 5:13 AM > PLEASE do not get in the habit of just updating the wording and > leaving the rest of it to the poor editor. The wording is often the > easy part! And I am not good at guessing what your intent is (which is > what goes in the discussion). I'll fix up headers and file e-mail, but > that's it. Oh, right. I think I suffered from a mis-understanding then. I was imagining I was told off before for changing the rest; so if its OK to change the bit before the wording then I shall do that! I do want to be a good citizen :) **************************************************************** From: Randy Brukardt Sent: Wednesday, October 5, 2016 9:24 PM > Oh, right. I think I suffered from a mis-understanding then. > I was imagining I was told off before for changing the rest; so if its > OK to change the bit before the wording then I shall do that! Well, the !question (or !problem) should generally be left alone unless you have explicit instructions to change them. It's the !summary, !proposal, and !discussion (which FOLLOWS the wording) that should be updated if they conflict in some way with the proposed wording. > I do want to be a good citizen :) Thanks. I realize your example for AIs was that Heave Beard guy, which is like using Wally from Dibert's office as a model for hard work. :-) ("Heave Beard" is good about one thing -- doing his homework early. I think he thinks that gives me more time to finish it for him. ;-) **************************************************************** From: Florian Schanda Sent: Tuesday, October 4, 2016 9:14 AM > But... I worry that we are referencing the semantics of 'Old and > build-in-place in the dynamic semantics section. I could see > mentioning them in an AARM note. But expecting the reader, as an aid > to understanding the dynamic semantics of delta aggregates, to have to > look forward to the definition of 'Old, followed by a perusal of the > build-in-place rules, seems downright perverse! ;-) You have these > references in brackets, so I presume that means this is redundant > information and hence not necessary to appear in normative RM text > here. If so, I heartily suggest that the bracketed wording move to an AARM > note. Yes, this is in square brackets (in the style of the SPARK RM). But really for the Ada RM this should be an AARM clarification/note/something. **************************************************************** From: Florian Schanda Sent: Tuesday, October 4, 2016 9:20 AM > For a delta aggregate the expression in a record_component_association > or a array_component_association shall not be of a limited type. > > Which expression is being discussed here? I'd guess that it is > supposed to be the *base*_expression, and if that's the intent, this > rule should say that. (Use the prefix if you go through the trouble to > define it!) [P.S. I took the extra comma out of your version.] No, it really does mean the expression in each record_component_association_list or array_component_association_list. The base_expression can be of a limited type. What we wanted to stop was having an assignment to a component that is of limited type. **************************************************************** From: Florian Schanda Sent: Tuesday, October 4, 2016 9:21 AM > In the examples, you need cross-references to where the objects/types > are declared elsewhere in the RM. For instance, the first example > should have something like "(See x.x.x for the declaration of D.)" as > part of the comment. I'm not going to try to figure out where an > object named "D" is declared in the RM! (Searching doesn't work for > obvious reasons.) Ok, I've done this. I'll send an updated version tomorrow that will include these references. **************************************************************** From: Florian Schanda Sent: Wednesday, October 5, 2016 6:10 AM Homework (attempt 2) for AI12-0127-1 (delta aggregates) [This is version /05 of the AI - Editor.] And again, with comments from the mailing list applied. **************************************************************** From: Steve Baird Sent: Wednesday, October 5, 2016 12:12 PM A few minor points. > A (record, array) delta aggregate yields a composite value resulting > from copying another value of the same type This is informal introductory text, so I'd suggest replacing "copying" with "starting with" because the type of the aggregate can be limited. We don't want to suggest that we are copying limited values. > > The expected type for a record_delta_aggregate shall be a record type, > or record extension. > > The expected type for an array_delta_aggregate shall be a single array > type. Why is the word "single" missing in the record case? Note that the analogous rule in 4.3.1 says "shall be a single record type or record extension". > For an array_delta_aggregates, the expected type for each > discrete_choice in an array_component_association is the index type of > type of the delta aggregate. Only a language lawyer would care about this one, but ... A name resolution rule shouldn't depend on a legality rule. So strictly speaking this should really say something like "the first index type" even though a) later on a legality rule will impose a requirement that that the array type's dimensionality is 1; and b) the text is clearer to the casual reader as it stands and would probably require a clarifying note after this "correction". **************************************************************** From: Randy Brukardt Sent: Wednesday, October 5, 2016 7:41 PM > > A (record, array) delta aggregate yields a composite value resulting > > from copying another value of the same type > > This is informal introductory text, so I'd suggest replacing "copying" > with "starting with" because the type of the aggregate can be limited. > We don't want to suggest that we are copying limited values. Right. I've made an updated version of the AI with the first two of Steve's changes and a number of typo and formatting changes. So we can waste less time at the meeting enumerating typos. ;-) On this topic, it might make sense to have a note somewhere that the *base*_expression would have to be a new limited value (following the rules of 7.5); you can't use this construct to modify an existing limited object (as an aggregate is a new object, so using an existing object would make a copy of that object). [I *did not* add such a note, but we should consider it.] Also on this topic, 7.5 has an AARM Note: AARM Ramification: Note this does not permit the *base_*expression of an array_delta_aggregate to be of limited type as this is a useless construct (you would not be able to update anything). It took me a while to figure this out. I believe the point is that it isn't possible to have declared a limited array with non-limited components. [I suspect that this idea is incorrect in bizarre corner cases, but it probably isn't worth having support for this that only useful in pathological cases.] However, if we're not going to allow limited *base*_expressions for an array_delta_aggregate, then we need a Legality Rule to that effect in 4.3.4. (And the AARM note needs to reflect that as well.) That fact would just be buried in 7.5, a long way from 4.3.4. [I made these changes in my update.] > > The expected type for a record_delta_aggregate shall be a record > > type, or record extension. > > > > The expected type for an array_delta_aggregate shall be a single > > array type. > > Why is the word "single" missing in the record case? > Note that the analogous rule in 4.3.1 says "shall be a single record > type or record extension". Looks like a mistake to me; there's also an extra comma. I made those changes in my update. > > For an array_delta_aggregates, the expected type for each > > discrete_choice in an array_component_association is the index type > > of type of the delta aggregate. > > Only a language lawyer would care about this one, but ... > > A name resolution rule shouldn't depend on a legality rule. > So strictly speaking this should really say something like "the first > index type" even though > a) later on a legality rule will impose a requirement that that > the array type's dimensionality is 1; and > b) the text is clearer to the casual reader as it stands and > would probably require a clarifying note after this > "correction". I think this is too pedantic. Who cares what index type gets used for an illegal aggregate? We can discuss in PA. --- I also changed most of the "array delta aggregate"s to the syntax form (with underscores). The form without underscores informally usually is taken to mean the same thing as the syntax form, but not always in the RM, and I'd rather avoid new terms if possible. And "aggregate" is almost always in the syntax form in the RM. --- The first rule in the Dynamic Semantics The evaluation of a delta_aggregate begins with evaluating the expression of the delta aggregate and using that value to create and initialize the aggregate's anonymous object. is missing the *base*_ prefix for the expression. (We have it, why not use it??) I fixed this, too. --- Simple use in a postcondition: Post => D = (D'Old with delta Day => 12) -- see 3.8 for type Date Post => V = (V'Old with delta A .. B => 42.0, V'First => 0.0); -- see 3.6 for type Vector We need the declarations of D, V, A, and B here. I suggest: procedure Twelfth (D : in out Date) -- see 3.8 for type Date with Post => D = (D'Old with delta Day => 12); 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); --- N := (Min_Cell (L) with delta Value => 42); -- see 6.1 for declaration of Min_Cell Same here with L and N. I suggest using Link and Cell from 3.10.1, so New_Cell : Cell := Min_Cell (Link) with delta Value => 42); -- see 3.10.1 for Cell and Link; 6.1 for Min_Cell Next example needs a declaration of A1, which I suggest making there by adding ": Vector". Finally: R := ((D with delta Day => 12) with delta Day => 42); -- see 3.8 for type Date Needs declarations for R and D. I suggest using the objects already declared in 3.8. Moreover, I think it would be best if this aggregate made sense (what the heck is the 42th of a month??) and thus used a different component: Tomorrow := ((Yesterday with delta Day => 12) with delta Month => Apr); -- see 3.8 --- Thanks again for the update; I should have messed it up enough. ;-) [I'll post the update once I've gotten caught up processing homework.] **************************************************************** From: Stephen Leake Sent: Saturday, August 5, 2017 12:15 PM !topic typos in ai12-0127 !reference Ada 202x RM4.3.4 !from Stephen Leake 2017-08-05 !keywords delta aggregates !discussion I just read ai12-0127 (at http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ai12s/ai12-0127-1.txt?rev=1.10) (with an eye towards enhancing Emacs Ada mode to support the new syntax), and I noticed a few typos: 4.3.4 For an array_delta_aggregates, the expected type for each discrete_choice in an array_component_association is the index type of type of the delta aggregate. "array_delta_aggregates" should not be plural Examples: New_Cell : Cell := Min_Cell (Link) with delta Value => 42); missing left paren before Min_Cell A1 : Vector := ((1, 2, 3) with delta Integer (Random * 3.0) => 14.2); components in base expression must be real; (1.0, 2.0, 3.0) **************************************************************** From: Christoph Grein Sent: Wednesday, August 9, 2017 9:30 AM The record Rec of this example seems to have among others the two components Color and Shape. Thus the Post condition seems to return False: procedure Foo (Fighters : in out Rec) with Post => (Fighters.Colour = Black and Fighters = (Fighters'Old with delta Shape => Trapazoid)); Shouldn't this be procedure Foo (Fighters : in out Rec) with Post => (Fighters = (Fighters'Old with delta Shape => Trapazoid, Colour => Black)); (This example is not part of the examples of the wording section, so the error is not overly fatal, because it won't go into the RM.) **************************************************************** From: Simon Wright Sent: Wednesday, August 9, 2017 10:26 AM > The record Rec of this example seems to have among others the two > components Color and Shape. Thus the Post condition seems to return False: > > procedure Foo (Fighters : in out Rec) > with Post => (Fighters.Colour = Black and > Fighters = (Fighters'Old with delta Shape => > Trapazoid)); Spello: TrapEzoid **************************************************************** From: Gary Dismukes Sent: Wednesday, August 9, 2017 11:56 AM > Shouldn't this be > > procedure Foo (Fighters : in out Rec) > with Post => (Fighters = (Fighters'Old with delta > Shape => Trapazoid, > Colour => Black)); > > (This example is not part of the examples of the wording section, so > the error is not overly fatal, because it won't go into the RM.) Sounds right to me. Maybe the spelling should also be fixed: "Trapazoid" should be "Trapezoid". :-) **************************************************************** From: Randy Brukardt Sent: Wednesday, August 9, 2017 10:39 PM > I just read ai12-0127 (at > http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ai12s/ai12-0127-1.t > xt?rev=1.10) > (with an eye towards enhancing Emacs Ada mode to support the new > syntax), and I noticed a few typos: ... Thanks, I think. Since this is an open AI, it hasn't yet undergone a comprehensive editorial review, and it is not unusual for it to contain a bunch of typos. In this particular case, the AI is awaiting an update and a number of problems (including typos) are supposed to be fixed by the author. At least part of the text is likely to change substantially. In any case, the editor (that would be me) is not in a position to make changes to this AI or most other AIs (other than the ones assigned to me) as there is a race condition between me and the actual author. Experience shows that attempts to fix things often disappear in the next draft anyway (when the author starts from some other version of the AI). I'll file this mail into the AI, where it might very well be forgotten (or even disappear as a victim of a race condition). As such, it's not very valuable to make editorial comments on open AIs outside of ARG meetings (or even in ARG meetings, as a significant number of AIs are redrafted without fixing them). They're best left until the AI becomes ARG-approved and is in its editorial review period. Either that or contact the AI author (you can find who that is in the most recent version of the ARG meeting minutes - if it's not assigned to anyone, it's in near-death limbo and not worth worrying about). **************************************************************** From: Steve Baird Sent: Thursday, October 5, 2017 7:12 PM I was tasked with making a nit-picking pass over this AI. All I found was the following, presented in the usual grocery-list normal form. ==== "starting with another value" => "starting with a copy of another value" --- "is the index type of type of the delta aggregate" => "is the index type of THE type of the delta aggregate" --- In 4.3.3(17/5) replace ... only if it is the single discrete_choice of its discrete_choice_list, and there is only one array_component_association in the array_aggregate. with .. 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 REDUNDANT:[, not an array_aggregate]. We want to allow (X with delta Lo1 .. Hi1 => This, Lo2 .. Hi2 => That) where every expression in sight is non-static, but we don't want to allow (X with delta Lo1 .. Hi1 | Lo2 .. Hi2 => This) in that case. --- In the legality rules, we've got "the record_component_association shall not use the box symbol <>" The use of the word "the" incorrectly presupposes that there is exactly one record_component_association. Ditto for "and the component_choice_list shall not use others". **************************************************************** From: Randy Brukardt Sent: Thursday, October 5, 2017 7:47 PM > I was tasked with making a nit-picking pass over this AI. You're tasked with producing a full update based on the discussion from last October (it wasn't updated for Vienna so it wasn't discussed). It was assigned to you as "this sort of detail seems like a job for Steve Baird" (quoting from the Pittsburgh minutes). (The "sort of detail" is checking that the wording is consistent with all of the existing aggregate wording; I was personally concerned with record component completeness rules, but others are called out in the minutes -- enough issues had been brought up that a complete check seemed to be needed.) This is an important AI that it would be good to progress. > All I found was the following, presented in the usual grocery-list > normal form. I could deal with the first three, but the fourth is just a complaint without a fix. As the (now) primary author, you need to propose a fix for everything. **************************************************************** From: Gary Dismukes Sent: Thursday, October 5, 2017 7:54 PM I happened to notice that the last update to this AI (sent by Florian) happened exactly a year ago, although the current date on the AI is shown as Oct. 6, 2016. **************************************************************** From: Gary Dismukes Sent: Thursday, October 5, 2017 7:58 PM Sorry for the noise! My frivolous message was only intended to be sent to Mr. Baird. (And sorry also for this additional noise...) **************************************************************** From: Randy Brukardt Sent: Thursday, October 5, 2017 8:16 PM .. > I happened to notice that the last update to this AI (sent by > Florian) happened exactly a year ago, although the current date on the > AI is shown as Oct. 6, 2016. I did notice that the AI was almost exactly a year old when replying to Steve, but I didn't see any need to work that in to my reply. The Ghost AI will be dated today, for instance, since I'm processing it tonight. I usually date AIs the date that I post them, which is not necessarily the date that they got sent to me. (Sometimes I adjust the date to ensure that every version has a different date, and sometimes I just do something else for no reason.) So now more noise has been generated. ;-) Moral: Take care when replying the mail from the ARG list, as the list is set up to encourage public replies to the list and not the private replies to the author. **************************************************************** From: Steve Baird Sent: Friday, October 13, 2017 9:35 PM Replace The expected type for a record_delta_aggregate shall be a single record type or record extension. with The expected type for a record_delta_aggregate shall be a single descendant of a record type. ===== After For a record_delta_aggregate, each component_selector_name of each component_choice_list shall denote a distinct non discriminant component of the type of the delta aggregate. Add No two such component_selectors shall denote components declared within different variants of the same variant part. ===== [Editor's note: These are applied to version /08 of the AI.] **************************************************************** From: Tucker Taft Sent: Saturday, October 14, 2017 7:15 AM > Replace > The expected type for a record_delta_aggregate shall be a single > record type or record extension. > > with > > The expected type for a record_delta_aggregate shall be a single > descendant of a record type. Why can't it be a single descendant of a record type or a tagged private type? > ===== > > After > > For a record_delta_aggregate, each component_selector_name of each > component_choice_list shall denote a distinct non discriminant > component of the type of the delta aggregate. > > Add > > No two such component_selectors shall denote components declared > within different variants of the same variant part. Sounds good. **************************************************************** From: Steve Baird Sent: Saturday, October 14, 2017 10:47 AM The intent here is to avoid changing the language rules in any way for non-delta aggregates. The problem is that 4.3(3) does not do what what we want for delta aggregates and it applies to all forms of aggregates. So we get rid of that and distribute the effect of that rule over each of the forms of aggregates, hopefully preserving the existing semantics. The straightforward way to do this would result in name resolution rules which look ridiculous/confusing when appearing side by side, as in The expected type for a record aggregate shall be a single array type, record type, or record extension. The expected type for a record_aggregate shall be a single record type or record extension. In cases like this, we replace the more specific rule with a legality rule. This is intended to only be a change in presentation, having no effect on the language definition for aggregates other than delta aggregates. [This is version /09 of the AI.] --------------------- Delete 4.3(3) The expected type for an aggregate shall be a single array type, record type, or record extension. [This deletes the name resolution rule that is common to all forms of aggregates] ==== Replace 4.3.1(3) The expected type for a record_aggregate shall be a single record type or record extension. with The expected type for a record aggregate shall be a single array type, record type, or record extension. And then add a new legality rule (at the start of the legality rules section, ahead of 4.3.1(14)) The type of a record_aggregate shall be a record type or record extension. ==== Replace 4.3.2(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. with The expected type for an extension_aggregate shall be a single array type, record type, or record extension. If the ancestor_part is an expression, it is expected to be of any tagged type. And then add a new legality rule (at the start of the legality rules section, ahead of 4.3.2(5/3)) The type of an extension_aggregate shall be a record extension. ==== Replace 4.3.3(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. with The expected type for an array_aggregate (that is not a subaggregate) shall be a single array type, record type, or record_extension. The component type of this array type is the expected type for each array component expression of the array_aggregate. And then add a new legality rule (at the start of the legality rules section, ahead of 4.3.3(9)) The type of an array_aggregate that is not a subaggregate shall be an array type. ==== In the proposed wording for delta aggregates, replace the name resolution rules The expected type for a record_delta_aggregate shall be a single record type or record extension. The expected type for an array_delta_aggregate shall be a single array type. with The expected type for an extension_aggregate shall be a single array type or a single descendant of a record type or of a record extension. And then add new legality rules (at the start of the legality rules section) The type of a record_delta_aggregate shall be a descendant of a record type or of a record_extension. The type of an array_delta_aggregate shall be an array type. **************************************************************** From: Randy Brukardt Sent: Friday, December 1, 2017 12:38 AM My understanding is that we don't want positional delta aggregates. However, I don't see any rule in AI12-0127-1 that requires a component_selector_name or a component_choice_list for a record aggregate. (The syntax requires this for an array_delta_aggregate, so no rule is needed for the array case.) The AI should have spelled this out in the discussion (that is, that all components have to be named), but it doesn't. Nor is there any idea how to figure what component is "first" if the names are omitted. The fact that arrays require named components suggest that records were intended to do so as well, but since the topic isn't discussed, it's hard to be certain. Anyway, there are number of rules about the contents of selector_names and choice_lists, but these are of the same form as the similar rules for record aggregates. So one has to read these with an implied "if present" (since record aggregates surely do allow positional aggregates). So I think we need to say something like: For a record_delta_aggregate, each record_component_association shall include a component_choice_list. We probably can combine this with one of the existing rules; the first Legality Rule seems best: For a record_delta_aggregate, a record_component_association_list shall not be null record. A record_component_association of the record_component_association_list of a record_delta_aggregate shall not use the box symbol <>, it shall include a component_choice_list, and that component_choice_list shall not include an others choice. [I reworded the last part a bit to better fit with the rest.] Thoughts? Brickbats? **************************************************************** From: Randy Brukardt Sent: Friday, December 1, 2017 1:30 PM Since there isn't anything in the AI or the minutes about only allowing named notation, I fear that this AI will have to go back for another vote unless we can have a clear consensus here in e-mail. So far, that seems to just mean me, which isn't enough. :-) So please comment ASAP. **************************************************************** From: Jeff Cousins Sent: Friday, December 1, 2017 1:55 PM You sound correct to me, I was going to re-read the AI tomorrow. The positional form should be discouraged anyway. **************************************************************** From: Ed Schonberg Sent: Friday, December 1, 2017 2:05 PM Positional notation, or an “others” association make no sense for a delta, your new formulation is fine. The current implementation of the AI in GNAT only accepts named associations, it never occurred to me to handle anything else. **************************************************************** From: Bob Duff Sent: Friday, December 1, 2017 2:09 PM > Since there isn't anything in the AI or the minutes about only > allowing named notation, I fear that this AI will have to go back for > another vote unless we can have a clear consensus here in e-mail. So > far, that seems to just mean me, which isn't enough. :-) So please comment > ASAP. I agree with you. But why don't you call for a letter ballot? **************************************************************** From: Tucker Taft Sent: Friday, December 1, 2017 2:24 PM Happy to limit delta aggregates to fully named notation. **************************************************************** From: Randy Brukardt Sent: Friday, December 1, 2017 3:06 PM > I agree with you. But why don't you call for a letter ballot? I mostly was interested in what to put into the draft RM, since I was about 80% finished with that when I ran into this issue last night. Too late to undo that work, so I need a preliminary answer in the next couple of working days. For a formal answer, the January phone call is soon enough (a Letter Ballot would take most of that time). And of course the real reason -- I didn't think of using a Letter Ballot. :-) **************************************************************** From: Randy Brukardt Sent: Friday, December 1, 2017 7:08 PM ...on top of the several pages of typos and editorials (to be sent when I'm finished with this AI). The minutes have the following (other than the note in brackets): ... just replace 4.3(3): [Which, BTW, is really 4.3(3/2) - RLB] 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 shall be a single array type, record type, or record extension. For 4.3.4, use the following for the resolution rules: The expected type for a record_delta_aggregate shall be a single record type or record extension. The expected type for an array_delta_aggregate shall be a single array type. But this latter record rule doesn't allow private types with visible record type/extension ancestors, which was the entire point of the change. Most likely, the rule should match the 4.3(3/2) wording... The expected type for a record_delta_aggregate shall be a single descendant of a record type or record extension. We're reaching the point of too many changes. I think I agree with Bob that we ought to have a Letter Ballot, so we don't have to waste our limited time on this during our call. (There are at least two other AIs that can be handled on the same ballot.) **************************************************************** From: Randy Brukardt Sent: Friday, December 1, 2017 9:23 PM (Actually, this has turned into a complete rabbit hole. Probably most of you should jump to the bottom and just read the conclusions...but not Steve, he was the one that was supposed to work this out and obviously botched it. :-) The third last paragraph of the Name Resolution Rules in 4.3.4 says: For a record_delta_aggregate, the expected type and applicable index constraint of the expression in each record_component_association is defined as for a record_component_association occurring within a record_aggregate. The last paragraph of the Name Resolution Rules in 4.3.4 says: The expected type and applicable index constraint of the expression in array_component_association is defined as for an array_component_association occurring within an array_aggregate of the type of the delta_aggregate. Why does the second of these say "of the type of the delta_aggregate" and the first doesn't? It would seem that if either of them needs to mention the type, they both would. This quickly turns into a trip into the rabbit hole. (1) There exist types which a record_aggregate would not be legal (for instance, a private type descended from a record type), so we don't want to insist on the type. (2) There is no reason that I can see to mention the applicable index type in this rule; 4.3.3(14) is the applicable array aggregate rule and I can see no reason why it wouldn't apply. (It just talks about component expressions and aggregates, both of which clearly apply to delta aggregates.) So long as the subtype is well-defined (and it has to be if any of these rules work for record aggregates), we're good. (3) The actual rule that this is trying to reference (4.3.1(10) and 4.3.1(12)) doesn't actually mention any types. Moreover, it doesn't mention any kinds of enclosing aggregate. Ergo, it already applies (there is nothing that would prevent it from applying), and thus the record_aggregate rule in 4.3.4 is redundant and confusing. There's a similar rule in the Legality Rules. I suspect it would be better to simply put a redundant statement somewhere and drop both of those rules from 4.3.4. Something like: @Redundant[The interpretation of each record_component_association of a record_delta_aggregate is defined in 4.3.1.] Perhaps it would be better to spell out that we mean just Name Resolution and Legality Rules: @Redundant[The Name Resolution Rules and Legality Rules for each record_component_association of a record_delta_aggregate are as defined in 4.3.1.] And we then have to fix up any rules in 4.3.1 that don't make sense. Unfortunately, that seems to be a bunch of them. (4) The new rule in 4.3.1 (4.3.1(9.1/5)) says: Each selector_name in a record_component_association of a record_delta_aggregate shall denote a nondiscriminant component of the record type. *the record type*!!!??? What if the delta aggregate has a private extension type, or a record extension type?? There might not be any record type anywhere. (Note that we separately mention "record extension" in the record resolution rules.) It also doesn't say what entity the type is from. Probably this should just say "type of the aggregate" and quit: Each 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. [BTW, this probably shouldn't be a separate paragraph, either. The interpretation of a selector_name should be all in one paragraph. Also, as this is a forward reference, we probably ought to mention where record_delta_aggregate can be found (as I did above). For the HTML version, one can just click on it to go there, but a paper or PDF version isn't so easy to figure out. Finally, I don't know why the *component_* part is omitted in this paragraph; it seems to be in most of the other rules. Best to add it in.] (5) Turning to the Legality Rules, 4.3.1(14) isn't about component associations. 4.3.1(17.1/2) seems OK, and <> isn't allowed anyway (another separate Legality Rule). 4.3.1(16/4) seems to have a problem however: 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. 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. The problem here is ", and each needed component shall be associated with exactly one record_component_association". We didn't define "needed" for delta aggregates, so this part of the rule is impossible to interpret. Probably we need to bifurcate this like we did with 4.3.1(9/5) (which would move one of the rules found in 4.3.4 here - avoid duplication!). The last two sentences do need to apply here. This gives something like as a replacement for 4.3.1(16/4): 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. For other aggregates, 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. 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. [Note: I split this into two paragraphs, so it's clearer that the second part applies to all aggregates. Otherwise it appears to only apply to the non-delta aggregates. Also note that this puts the less common case first, which has sometimes given people heartburn. It could be turned around at the cost of more words.] (6) It also makes more sense to bifurcate 4.3.1(15/3) as: For a record_delta_aggregate, the record_component_association_list shall not be /null record/; otherwise; the reserved words /null record/ may appear only if there are no components needed in a given record_component_association_list. Again, this avoids any issues of what "needed" means for a delta aggregate. Rewording the last part to be more consistent (and avoid the nasty word "may"): For a record_delta_aggregate, the record_component_association_list shall not be /null record/; otherwise, a record_component_association list shall be /null record/ only if there are no components needed for that list. [Note: This puts the less common case first; if that gives people serious heartburn we could say "For a record_aggregate or extension_aggregate" instead (but that's quite a bit longer).] (7) Having done that, it seems to me to make the most sense to move the renaming record_component_association rules to 4.3.1 as well: A record_component_association of the record_component_association_list of a record_delta_aggregate shall not use the box symbol <>, it shall include a component_choice_list, and that component_choice_list shall not include an others choice. For a record_delta_aggregate, no two component_selector_names shall denote components declared within different variants of the same variant part. "box symbol <>" is bizarre. The only normative wording using this uses "compound delimiter <>" (2.2, 3.6), with a parenthetical remark about the name box in 3.6. So I'd replace "box symbol <>" by "compound delimiter <> (box)" here. =================================== Conclusion: Move all of the record_component_association_list Resolution and Legality rules to 4.3.1, leaving only a cross-reference statement. Redo the rules in 4.3.1 so it is crystal-clear when they apply to a delta aggregate (and when they don't). Specifically: In 4.3.4 (the new delta aggregate clause), delete all of the rules about record_component_associations. Replace those by a single line: @Redundant[The Name Resolution Rules and Legality Rules for each record_component_association of a record_delta_aggregate are as defined in 4.3.1.] Replace the modified 4.3.1(9/5) and the newly inserted paragraph with: 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. Replace 4.3.1(15/3) with: For a record_delta_aggregate, the record_component_association_list shall not be /null record/; otherwise, a record_component_association list shall be /null record/ only if there are no components needed for that list. Replace 4.3.1(16/4) with (2 paragraphs): 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. For other aggregates, 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. [Note: One could put the usual case first by replacing "other aggregates" with "a record_aggregate or extension_aggregate", then swapping the lines. Better? I don't see an easy way to do that for 4.3.1(15/3), though.] 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. Add after 4.3.1(17.1/2): A record_component_association of the record_component_association_list of a record_delta_aggregate shall not use the compound delimiter <> (box), it shall include a component_choice_list, and that component_choice_list shall not include an /others/ choice. For a record_delta_aggragate, no two component_selector_names shall denote components declared within different variants of the same variant part. ----------------- Whew! Thoughts??? (Note: I haven't looked at the array rules yet; I worry that they have similar issues. The record ones took all night and I still need to do backups...so next week.) **************************************************************** From: Jeff Cousins Sent: Saturday, December 2, 2017 5:19 AM I would prefer to put the more usual case first in the 4.3.1(16/4) replacement. Couldn't 4.3.1(15/3) be something like: A record_component_association_list may only be a null record if no components are needed for that list, and the list is not for a record_delta_aggregate. or is that too simplistic? **************************************************************** From: Randy Brukardt Sent: Monday, December 4, 2017 6:29 PM > I would prefer to put the more usual case first in the 4.3.1(16/4) replacement. Seems OK assuming some change to the latter. >Couldn't 4.3.1(15/3) be something like: > > A record_component_association_list may only be a null record if no >components are needed for that list, and the list is not for a >record_delta_aggregate. > > or is that too simplistic? Just a bit. I wondered something similar (but decided to avoid more mail-box filling), but the problem is "needed" isn't defined for record_delta_aggregates. So the first part is meaningless for a record_delta_aggregate, and one wants to be able to evaluate rules left-to-right. Also, "a null record" is awkward, since we're talking about the keywords "null record" as opposed to an empty record. Also, "may only" is nasty from an ISO perspective; it would be better to use "shall" as this is a Legality Rule (I didn't mention that previously, but I was trying to make the wording more typical Standard-ease). OTOH, we could simplify my version in a different way: 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. AARM Ramification: /null record/ is not allowed at all in a record_delta_aggregate. We don't have to mention record_delta_aggregates at all if we are only listing the positive rules. **************************************************************** From: Randy Brukardt Sent: Monday, December 4, 2017 9:30 PM > Whew! Thoughts??? (Note: I haven't looked at the array rules yet; I > worry that they have similar issues. The record ones took all night > and I still need to do backups...so next week.) I've looked at the array rules now, and they are much better. All of the existing rules in 4.3.3 include some form of "for an array_aggregate", so we have a clean slate. (The record rules didn't do that because they are already shared between record and extension aggregates; sharing them with the third kind of aggregate seems best to handle that.) Two points: There is no need to mention "applicable index constraint" in the delta aggregate rules. We don't need an applicable index constraint for an array delta aggregate, as they cannot be either positional nor have an others choice. (The term does not appear elsewhere.) 4.3.3(14) applies to the component expression of any aggregate, so it is fine; 4.3.3(10) says that 4.3.3(14) applies to array_aggregates (only), but that is talking about the aggregate that is the component expression (the one that might have and others iff it is an array aggregate), and not the enclosing aggregate (which might be a delta aggregate). (If it was talking about the enclosing aggregate, record aggregates wouldn't provide an applicable index constraint, which is obvious nonsense.) Thus, there is no need to mention "applicable index constraint" in 4.3.4. (Not sure how Steve convinced us otherwise, but he was wrong.) --- I think it would be good to explicitly define the bounds of the anonymous object of an array_delta_aggregate. Aggregates only have types (not subtypes), and in particular do not use the subtype of the aggregate to determine the bounds of a named array aggregate. I would expect that the same is true here (especially as there is no check that the bounds match any subtype; that happens later when the aggregate is converted to some subtype for use -- note again that there are no rules in 4.3.1 or 4.3.3 requiring a check on the actual bounds/discriminants of the subtype of the aggregate). Specifically, we should explicitly state that the "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." Then (like all other aggregates), the subtype conversion that occurs when the aggregate is used (or qualified) will ensure that the subtype (bounds/discriminants) are appropriate. We have to be certain that all of the below raise Constraint_Error. type Arr is array (Natural range <>) of Integer; subtype Arr_0_3 is Arr(0..3); subtype Arr_0_4 is Arr(0..4); subtype Arr_1_5 is Arr(1..5); procedure Do_It (P : in Arr_1_5); function Fun return Arr; Arr_Obj_1 : Arr_0_4 := ...; Arr_Obj_2 : Arr_0_3 := ...; Do_It ((Arr_Obj_1 with delta 2 => 3)); -- (1) Do_It ((Arr_Obj_2 with delta 2 => 3)); -- (2) Do_It ((Fun with delta 2 => 3)); -- (3) The aggregate at (1) has bounds of 0..4, which are different than the bounds of the subtype of 1..5. We don't want sliding here (array aggregates don't slide). The aggregate at (2) shows that sliding isn't enough anyway, here the number of components is wrong. The aggregate at (3) shows that the bounds aren't necessarily known at compile-time. ------------------ Given the lack of comment on the previous iterations (other than from Jeff), I'm just going to make all of these changes and plan on a letter ballot on this AI. So get any comments in sooner rather than later. **************************************************************** From: Tucker Taft Sent: Monday, December 4, 2017 9:40 PM Thanks for digging into this. It sounds like you have come up with significant improvements, with a little help from Jeff. I'll admit I haven't followed all of the discussion, but I will look forward to a new version. **************************************************************** From: Steve Baird Sent: Monday, December 4, 2017 10:27 PM > There is no need to mention "applicable index constraint" in the delta > aggregate rules. We don't need an applicable index constraint for an > array delta aggregate, as they cannot be either positional nor have an > others choice. (The term does not appear elsewhere.) What about in defining the applicable index constraint of the base expression, as in X : String (1 .. 4) := ((others => 'X') with delta 1 => 'Y'); -- "YXXX" ? I thought we had a rule that the applicable index constraint of the base expression is that (if any) of the delta aggregate. Ditto for expected type. **************************************************************** From: Randy Brukardt Sent: Monday, December 4, 2017 10:41 PM That seems like a rule that should have existed, but the only rule in the most recent AI draft applied to the expressions of a component_list. (There is, of course, a rule for the expected type of a base_expression; it doesn't mention "applicable index constraint"). In any case, such a rule belongs in 4.3.3 in the list of bullets (we don't want delta_aggregates to look "bolted on" in the Standard). Probably after 4.3.3(14) following the form of the other bullets: * For the *base_*expression of a delta_aggregate, if the nominal subtype of the delta_aggregate is a constrained array subtype, the applicable index constraint is the constraint of the subtype; I'll add that, too. **************************************************************** From: Randy Brukardt Sent: Tuesday, December 5, 2017 6:42 PM Here are some comments on AI12-0127-1, noted as I put this into the draft RM. Treat these as my editorial review (noted here for the record, not requiring discussion): --- I put the entire syntax on one line as it will fit (at least in the printed RM, the official ISO version) and it is much less disruption that way (else I'd have to delete most of it and replace it in the new format). --- The next paragraph number is 4.3(3/2), not 4.3(3). --- The wording of 4.3(4) should use record_aggregate and extension_aggregate with underscores and in the syntax font, like the rule it replaces and many others. --- The last sentence of 4.3.1(9) says that the Selector_Name in a record_component_association has to denote a "needed" component. The next (newly added) paragraph gives a different rule for record_delta_aggregates (that doesn't use "needed"). That doesn't make sense as written, as the "needed" rule certainly seems to apply to any record_component_association, but we didn't define "needed" for delta aggregates. Since that was intentional (we don't want the "needed" rules to apply to a delta_aggregate), we need to modify the last sentence of 4.3.1(9) (along with adding the new paragraph) to make it clear that it does not apply to delta_aggregates. I did that by adding "of a record_aggregate or extension_aggregate" after record_component_association in the last sentence of 4.3.1(9). --- The syntax change of 4.3.3 is in paragraph 4, not 3 as the AI says. --- 4.3.3(17/5) seems to be a bit of a run-on sentence, but I don't have a better idea. (This is the first paragraph that I didn't have an important comment on, and I didn't want to break the perfect streak... ;-) --- In the 4.3.4 wording: * various "record aggregate", "array aggregate", and "delta aggregate" references should have an underscore and be in the syntax font. (There's a lot, so I won't list these individually.) * There are lots of real problems here, these are discussed in individual messages sent previously. * in the first paragraph of the dynamic semantics, we have "aggregate's anonymous object". John will require the possesive to be eliminated, so we have to say "anonymous object of the aggregate". --- The items in 7.5(2.1/5-2.10/3) are in the order that they appear in the RM. As such, the new item belongs after 7.5(2.6/2) -- which references 4.3.3 -- and not at the end. That does unfortunately change the paragraph numbers for the latter bullets, but it seems better to keep the order (and all of the aggregates together). **************************************************************** From: Randy Brukardt Sent: Thursday, December 7, 2017 7:41 PM One last wording question about AI12-0127-1 (I'm done with this one now, so I ought to be moving on...) The Dynamic Semantics includes the sentence: In the case of an array component, the associated index expression is also evaluated and used in determining the target component just as in any array indexing operation. "just as in any array indexing operation" doesn't seem at all like Standards-speak. I've thought about this too much without any definitive replacement. The literal replacement: "in the same manner as an array indexing operation (see 4.1.1)" is better Standards-speak, but it still seems rather hand-wavy. The fact that there is an index check hidden here seems bad. I note that 4.1.1(7) is 4 short sentences, and the first already is included in the rule given above. The part about "determining the target component" really is just 4.1.1(5)'s "denotes the component of the array with the specified index value(s)". So an alternative is to just say what we mean: In the case of an array component, the associated index expression is also evaluated, then converted to the index type of the array type. A check is made that each index value belongs to the index range of the anonymous object of the aggregate; Constraint_Error is raised if this check fails. The component expression is evaluated and assigned to the component of the anonymous array object identified by the index value. AARM Discussion: This is the same semantics as a normal assignment to an individual indexed array component. Looking at the entire paragraph, all of it is vague and strangely written: Next, for each component for which an expression is provided, the expression is evaluated and assigned to that component of the anonymous object. In the case of an array component, the associated index expression is also evaluated and used in determining the target component just as in any array indexing operation. As with any aggregate, evaluation of a delta_aggregate then denotes the associated anonymous object. The last sentence is particularly bad: none of the existing aggregate rules ever discuss the anonymous object -- that isn't introduced until 7.6(17.1/3). Heat-vision aside: If we're going to talk about the anonymous object in 4.3.4, shouldn't we mention that it might have to be built in place? 7.6 says "aggregate", which clearly applies to delta aggregates, and it seems it has to in the limited case. I wonder if we would be better off separating the record and array cases and explain where the expression comes from, how the component is identified, and so on. Sigh -- another full rewrite. Thoughts? Suggestions? Tell me to forget about the dang AI and do something else?? :-) **************************************************************** From: Tucker Taft Sent: Thursday, December 7, 2017 7:55 PM ...> So an alternative is to just say what we mean: > > In the case of an array component, the associated index expression is > also evaluated, then converted to the index type of the array type. A > check is made that each index value belongs to the index range of the > anonymous object of the aggregate; Constraint_Error is raised if this > check fails. The component expression is evaluated and assigned to the > component of the anonymous array object identified by the index value. Much better. ... > I wonder if we would be better off separating the record and array > cases and explain where the expression comes from, how the component > is identified, and so on. Sigh -- another full rewrite. > > Thoughts? Suggestions? Tell me to forget about the dang AI and do > something else?? :-) This is worth the energy, I think. But you might just want to re-assign it to someone else, rather than beating yourself up about it. **************************************************************** From: Randy Brukardt Sent: Thursday, December 7, 2017 8:50 PM ... > > In the case of an array component, the associated index expression > > is also evaluated, then converted to the index type of the array > > type. A check is made that each index value belongs to the index > > range of the anonymous object of the aggregate; Constraint_Error is > > raised if this check fails. The component expression is evaluated > > and assigned to the component of the anonymous array object identified > > by the index value. > > Much better. Too bad it isn't right. What is the "associated index expression" if the choice is a range? Doesn't make a whole lot of sense, unfortunately. ... > > I wonder if we would be better off separating the record and array > > cases and explain where the expression comes from, how the component > > is identified, and so on. Sigh -- another full rewrite. > > > > Thoughts? Suggestions? Tell me to forget about the dang AI and do > > something else?? :-) > > This is worth the energy, I think. But you might just want to > re-assign it to someone else, rather than beating yourself up about > it. Well, assigning it to someone else is how we got this version. :-) I'd trust you to do it, but you have too much to do as it is. I'm mostly worried about running out of time/money for 2017; I wanted to get the draft RM posted soon so I can concentrate on homework (mine and others) in January. At least I was the primary author on the other two AIs yet to do, so they must be perfect already. ;-) [Editor's note: This discussion was then taken private.] **************************************************************** From: Randy Brukardt Sent: Tuesday, December 12, 2017 11:11 PM Following is the current wording for AI12-0127-1, after the various revisions and corrections noted in previous mail. If you have any comments about this wording (especially non-editorial), please bring them up ASAP. We're going to have a Letter Ballot on this updated AI in a week or so, and it would be preferable if we don't have to do several of them because people objected to something after the vote starts. P.S. I haven't posted this version on the website yet, the version here is more current than the one on the website. [Editor's note: Following was the wording from version /11 of this AI.] **************************************************************** From: Jeff Cousins Sent: Wednesday, December 13, 2017 5:52 AM A couple of editorial comments: For a record_delta_aggragate, no two component_selector_names shall denote components declared within different variants of the same variant part. aggragate -> aggregate The expected type of the expression in array_component_association is defined as for an array_component_association occurring within an array aggregate of the type of the delta aggregate. in -> in an ****************************************************************