Version 1.4 of ai12s/ai12-0294-1.txt

Unformatted version of ai12s/ai12-0294-1.txt version 1.4
Other versions for file ai12s/ai12-0294-1.txt

!standard 3.3(23/3)          18-11-27 AI12-0294-1/02
!standard 5.5(8)
!standard 5.5(9/5)
!standard 5.5(9.1/5)
!standard 5.5.3(20/5)
!class Amendment 18-11-15
!status Amendment 1-2012 18-11-15
!status work item 18-11-15
!status received 18-10-21
!priority Low
!difficulty Easy
!subject More clean-ups for Ada 2020
!summary
[Editor's note: These cleanups have already been applied to the draft Standard.]
Various minor issues are corrected:
(1) Accept statements are banned in the body of a procedural iterator loop.
(2) Wording involving the nominal subtype of an object is improved.
(3) The elaboration order of a chunk_specification and a loop_parameter_specification is that the chunk_specification is elaborated first.
(4) There is an assume-the-worst rule for aspect Yield used on subprograms declared inside a generic body.
!problem
Various minor issues, mostly caused by other Amendment AIs, are repaired.
(1) 5.5.3 (from AI12-0189-1) allows accept statements in the body of a procedural iterator loop. However, such accept statements would be illegal if the loop was written manually (as 9.5.2(14) would be violated.
(2) 3.3(23/3) contains the following sentence:
"The object's actual subtype (that is, its subtype) can be more restrictive than the nominal subtype of the view; it always is if the nominal subtype is an indefinite subtype."
The middle "is" in this sentence is hanging and it's unclear to what it refers. This should be clarified.
(3) AI12-0251-1 proposes that a loop_parameter_specification is elaborated and parameters are created before the chunk_specification, if any, is elaborated. But the number of loop parameters to create is determined, in part, by the chunk_specification. Moreover, this is specifying an order different than the order in which these constructs are written. This is weird.
(4) AI12-0279-1 adds a rule to prevent Nonblocking => True and Yield => True from being given for the same subprogram (since Yield requires blocking, it is incompatible with Nonblocking). However, Legality Rules are not enforced in instance bodies, and the rule is written to exclude most uses of Nonblocking in generic units from the check. Therefore, an assume-the-worst rule is needed in generic bodies to prevent the impossible case from happening.
!proposal
(See Summary.)
!wording
(1) Add after 5.5.3(20/5) [from AI12-0189-1]:
The sequence_of_statements of a loop_statement with a procedural_iterator as its iteration_scheme shall not contain an accept_statement.
AARM Reason: An accept_statement is not allowed in a procedure (see 9.5.2), it has to be directly in a task_body. Since the loop body here is implemented as a procedure, we can't allow accept_statements there, either, even if the loop itself is directly in a task_body.
AARM Ramification: This includes cases where the accept_statement is part of another construct, for instance, a select_statement.
(2) Modify 3.3(23/3):
The object's actual subtype (that is, its subtype) can be more restrictive than the nominal subtype of the view; it always is {more restrictive} if the nominal subtype is an indefinite subtype.
(3) Replace 5.5(9/5-9.1/5): [As modified by AI12-0119-1 and AI12-0251-1]
If the reserved word parallel is present in a loop_statement (a /parallel loop/), the iterations are partitioned into one or more /chunks/, each with its own separate logical thread of control (see clause 9). If a chunk_specification is present in a parallel loop, it is elaborated first, and the result of the elaboration determines the maximum number of chunks used for the parallel loop. If the chunk_specification is an /integer_/simple_expression, the elaboration evaluates the expression, and the value of the expression determines the maximum number of chunks. If a discrete_subtype_definition is present, the elaboration elaborates the discrete_subtype_definition, which defines the subtype of the chunk parameter, and the number of values in this subtype determines the maximum number of chunks. After elaborating the chunk_specification, a check is made that the determined maximum number of chunks is greater than zero. If this check fails, Program_Error is raised.
For the execution of a loop_statement that has an iteration_scheme including a loop_parameter_specification, after elaborating the chunk_specification, if any, the loop_parameter_specification is elaborated. This elaboration elaborates the discrete_subtype_definition, which defines the subtype of the loop parameter. If the discrete_subtype_definition defines a subtype with a null range, the execution of the loop_statement is complete. Otherwise, the sequence_of_statements is executed once for each value of the discrete subtype defined by the discrete_subtype_definition that satisfies the predicates of the subtype (or until the loop is left as a consequence of a transfer of control). Prior to each such iteration, the corresponding value of the discrete subtype is assigned to the loop parameter associated with the given iteration. If the loop is a parallel loop, each chunk has its own logical thread of control with its own copy of the loop parameter; otherwise (a /sequential loop/), a single logical thread of control performs the loop, and there is a single copy of the loop parameter. Each logical thread of control handles a distinct subrange of the values of the subtype of the loop parameter such that all values are covered with no overlaps. Within each logical thread of control, the values are assigned to the loop parameter in increasing order unless the reserved word reverse is present, in which case the values are assigned in decreasing order.
AARM To Be Honest: This wording does not describe when the loop parameter object(s) are created. That creation has no side-effects (other than possibly raising Storage_Error, but anything can do that), so we simplified the wording by leaving it out. Each object has to be created before any iteration that depends on it starts, but we do not (for instance) require that the objects are all created at once at the start of the loop, nor that the objects are created after the elaboration of the discrete_subtype_definition.
If a chunk_specification with a discrete_subtype_definition is present, then the logical thread of control associated with a given chunk has its own copy of the chunk parameter initialized with a distinct value from the discrete subtype defined by the discrete_subtype_definition. The values of the chunk parameters are assigned such that they increase with increasing values of the ranges covered by the corresponding loop parameters.
Delete AARM 5.5(9.a) (it is effectively replaced by the AARM note given above)
(4) Replace D.2.1(9/5) [as added by AI12-0279-1] with:
If a Yield aspect is specified True for a primitive subprogram S of a type T, then the aspect is inherited by the corresponding primitive subprogram of each descendant of T.
Legality Rules
If the Yield aspect is specified for a dispatching subprogram that inherits the aspect, the specified value shall be confirming.
If the Nonblocking aspect (see 9.5) of the associated callable entity is statically True, the Yield aspect shall not be specified as True. For a callable entity that is declared within a generic body, this rule is checked assuming that any nonstatic Nonblocking attributes in the expression of the Nonblocking aspect of the entity are statically True.
AARM Reason: The second sentence here is an assume-the-worst rule. The only Nonblocking attributes that are nonstatic are those that depend, directly or indirectly, on the nonblocking aspect of a generic formal parameter. We have to assume these might in fact have the value True if given an appropriate actual entity.
In addition to the places where Legality Rules normally apply (see 12.3), these rules also apply in the private part of an instance of a generic unit.
!discussion
(1) As noted in the problem, 9.5.2(14) would make an accept statement illegal in a procedure, if the loop was written explicitly. Of course, that's true for exit and goto as well, and we require those to be implemented. But those terminate the iteration, while an accept statement would not have that effect. So supporting that would complicate the implementation for no obvious benefit. Therefore, we ban then unconditionally in this case.
(2) This wording goes back to the 2.0 version of Ada 9x (that is, the first version with actual wording), so fixing it isn't a priority.
However, the original question arose from an ARG member who though that "as" was missing from this text. The resulting sentence would violate the Dewar rule (surely not all nominal subtypes are indefinite). The author then spent a substantial amount of time trying to figure out a meaning that doesn't violate the Dewar rule.
A normal reader shouldn't have to apply the Dewar rule to be able to read the RM, thus we clarify the sentence. No change in meaning is intended.
(3) It appears that it was easier to fit chunk_specifications into the existing wording if they were elaborated later. But, as noted above, that causes ramifications that are problematical. While the creation of loop parameters doesn't have any detectable effect, it still seems strange to require doing something before there is enough information to decide the details of what to do.
In reversing the elaboration, we also reversed the order of the paragraphs in the wording. This required substantial revisions to the wording, so that the definitions of "parallel loop" and "chunk" come before the usages.
(4) Since the Yield implies that a potentially blocking call will be part of the subprogram body, it is by definition incompatible with Nonblocking => True. We can't allow this problem to go undetected, as it could cause blocking to happen inside of a parallel construct or protected actions, neither of which may be prepared for blocking.
Consider the following generic:
generic type Priv is private; with procedure Munge (Obj : in out Priv); package Gen is procedure Proc1 (Obj : in out Priv) with Nonblocking => Munge'Nonblocking, Yield => True; private procedure Proc2 (Obj : in out Priv) with Nonblocking => Munge'Nonblocking, Yield => True; end Gen;
package body Gen is procedure Proc3 (Obj : in out Priv) with Nonblocking => Munge'Nonblocking, Yield => True; end Gen;
All of these are legal in the generic, as Munge'Nonblocking is not "statically true".
If Gen is instantiated with a procedure that is Nonblocking, then all three of Proc1, Proc2, and Proc3 will be nonblocking in the instance.
Proc1 will be rechecked by the normal legality rule processing, thus making the instance illegal. Proc2 will be rechecked because we added the usual boilerplate about checking in the private part. However, Proc3 will never be rechecked, and thus a dangerous subprogram could be declared and used.
The only way to prevent this problem is to reject Proc3 assuming that some instance will have Munge'Nomblocking evaluate to True. This should not present a problem in practice, since if a declaration like Proc3 is required, it can always be moved to the private part (like Proc2), where it will be legal and be rechecked as needed. A second workaround would be to give the declaration of Munge the aspect Nonblocking => False, so that the contract is visible.
!corrigendum 3.3(23/3)
Replace the paragraph:
At the place where a view of an object is defined, a nominal subtype is associated with the view. The object's actual subtype (that is, its subtype) can be more restrictive than the nominal subtype of the view; it always is if the nominal subtype is an indefinite subtype. A subtype is an indefinite subtype if it is an unconstrained array subtype, or if it has unknown discriminants or unconstrained discriminants without defaults (see 3.7); otherwise, the subtype is a definite subtype (all elementary subtypes are definite subtypes). A class-wide subtype is defined to have unknown discriminants, and is therefore an indefinite subtype. An indefinite subtype does not by itself provide enough information to create an object; an additional constraint or explicit initialization expression is necessary (see 3.3.1). A component cannot have an indefinite nominal subtype.
by:
At the place where a view of an object is defined, a nominal subtype is associated with the view. The object's actual subtype (that is, its subtype) can be more restrictive than the nominal subtype of the view; it always is more restrictive if the nominal subtype is an indefinite subtype. A subtype is an indefinite subtype if it is an unconstrained array subtype, or if it has unknown discriminants or unconstrained discriminants without defaults (see 3.7); otherwise, the subtype is a definite subtype (all elementary subtypes are definite subtypes). A class-wide subtype is defined to have unknown discriminants, and is therefore an indefinite subtype. An indefinite subtype does not by itself provide enough information to create an object; an additional constraint or explicit initialization expression is necessary (see 3.3.1). A component cannot have an indefinite nominal subtype.
!corrigendum 5.5(8)
Insert after the paragraph:
For the execution of a loop_statement with a while iteration_scheme, the condition is evaluated before each execution of the sequence_of_statements; if the value of the condition is True, the sequence_of_statements is executed; if False, the execution of the loop_statement is complete.
the new paragraph:
If the reserved word parallel is present in a loop_statement (a parallel loop), the iterations are partitioned into one or more chunks, each with its own separate logical thread of control (see clause 9). If a chunk_specification is present in a parallel loop, it is elaborated first, and the result of the elaboration determines the maximum number of chunks used for the parallel loop. If the chunk_specification is an integer_simple_expression, the elaboration evaluates the expression, and the value of the expression determines the maximum number of chunks. If a discrete_subtype_definition is present, the elaboration elaborates the discrete_subtype_definition, which defines the subtype of the chunk parameter, and the number of values in this subtype determines the maximum number of chunks. After elaborating the chunk_specification, a check is made that the determined maximum number of chunks is greater than zero. If this check fails, Program_Error is raised.
!corrigendum 5.5(9/4)
Replace the paragraph:
For the execution of a loop_statement with the iteration_scheme being for loop_parameter_specification, the loop_parameter_specification is first elaborated. This elaboration creates the loop parameter and elaborates the discrete_subtype_definition. If the discrete_subtype_definition defines a subtype with a null range, the execution of the loop_statement is complete. Otherwise, the sequence_of_statements is executed once for each value of the discrete subtype defined by the discrete_subtype_definition that satisfies the predicates of the subtype (or until the loop is left as a consequence of a transfer of control). Prior to each such iteration, the corresponding value of the discrete subtype is assigned to the loop parameter. These values are assigned in increasing order unless the reserved word reverse is present, in which case the values are assigned in decreasing order.
by:
For the execution of a loop_statement that has an iteration_scheme including a loop_parameter_specification, after elaborating the chunk_specification, if any, the loop_parameter_specification is elaborated. This elaboration elaborates the discrete_subtype_definition, which defines the subtype of the loop parameter. If the discrete_subtype_definition defines a subtype with a null range, the execution of the loop_statement is complete. Otherwise, the sequence_of_statements is executed once for each value of the discrete subtype defined by the discrete_subtype_definition that satisfies the predicates of the subtype (or until the loop is left as a consequence of a transfer of control). Prior to each such iteration, the corresponding value of the discrete subtype is assigned to the loop parameter associated with the given iteration. If the loop is a parallel loop, each chunk has its own logical thread of control with its own copy of the loop parameter; otherwise (a sequential loop), a single logical thread of control performs the loop, and there is a single copy of the loop parameter. Each logical thread of control handles a distinct subrange of the values of the subtype of the loop parameter such that all values are covered with no overlaps. Within each logical thread of control, the values are assigned to the loop parameter in increasing order unless the reserved word reverse is present, in which case the values are assigned in decreasing order.
If a chunk_specification with a discrete_subtype_definition is present, then the logical thread of control associated with a given chunk has its own copy of the chunk parameter initialized with a distinct value from the discrete subtype defined by the discrete_subtype_definition. The values of the chunk parameters are assigned such that they increase with increasing values of the ranges covered by the corresponding loop parameters.
Whether or not a chunk_specification is present in a parallel loop, the total number of iterations of the loop represents an upper bound on the number of logical threads of control devoted to the loop.
!comment The following is mainly to force a conflict.
!corrigendum 5.5.3(0)
Insert after the paragraph:
The sequence_of_statements of a loop_statement with a procedural_iterator as its iteration_scheme shall contain an exit_statement, return statement, goto_statement, or requeue_statement that leaves the loop only if the callable entity C associated with the procedural_iterator has an Allows_Exit aspect specified True.
the new paragraph:
The sequence_of_statements of a loop_statement with a procedural_iterator as its iteration_scheme shall not contain an accept_statement.
!corrigendum D.2.1(1.5/2)
Insert after the paragraph:
Dispatching serves as the parent of other language-defined library units concerned with task dispatching.
the new paragraphs:
For a noninstance subprogram (including a generic formal subprogram), a generic subprogram, or an entry, the following language-defined aspect may be specified with an aspect_specification (see 13.1.1):
Yield
The type of aspect Yield is Boolean.
If directly specified, the aspect_definition shall be a static expression. If not specified (including by inheritance), the aspect is False.
If a Yield aspect is specified True for a primitive subprogram S of a type T, then the aspect is inherited by the corresponding primitive subprogram of each descendant of T.
Legality Rules
If the Yield aspect is specified for a dispatching subprogram that inherits the aspect, the specified value shall be confirming.
If the Nonblocking aspect (see 9.5) of the associated callable entity is statically True, the Yield aspect shall not be specified as True. For a callable entity that is declared within a generic body, this rule is checked assuming that any nonstatic Nonblocking attributes in the expression of the Nonblocking aspect of the entity are statically True.
In addition to the places where Legality Rules normally apply (see 12.3), these rules also apply in the private part of an instance of a generic unit.
!ASIS
No changes needed.
!ACATS test
An ACATS B-Test is needed for (1). No test is needed for (2).
!appendix

From: Randy Brukardt
Sent: Friday, November 16, 2018  7:16 PM

AI12-0251-1 defines the chunk syntax as:

parallel [(chunk_specification)] for loop_parameter_specification

but the Dynamic Semantics are:

The chunk_specification is elaborated after the loop_parameter_specification 
is elaborated, and before any iterations are performed. 

Why is the elaboration in the opposite order of the textual appearance?

I can't think of any reason that elaboration of one should have anything to 
do with elaboration of the other, so this order seems arbitrary. In such a 
case, I'd expect the order to be textual (that's certainly the order that a 
reader would expect). Moreover, you can't actually do anything until both 
are elaborated (you have to know how many chunks there are before you can do
any iterations), so I don't see any implementation reason for this choice.

The only reason that I can see for this choice is that it caused less change 
in the wording, but that shouldn't be the reason for any choice which has a 
run-time consequence.

Is there something that I missed?

I'd either leave the order unspecified (but that would be unusual for 
elaboration) or do the elaboration in textual order. I can't think of any 
other case where elaboration is done out-of-order within a single construct.

***************************************************************

From: Randy Brukardt
Sent: Friday, November 16, 2018  7:59 PM

...
> Why is the elaboration in the opposite order of the textual 
> appearance?

Note that arguably this order is outright wrong, since the existing wording 
says:

For the execution of a loop_statement with the iteration_scheme including a 
loop_parameter_specification, the loop_parameter_specification is first 
elaborated. This elaboration creates the loop parameter and elaborates 
the discrete_subtype_definition.

But how can you create "the loop parameter" when you don't know how many 
chunks there are? Since this creation doesn't have any actual effect, it's
probably safe to ignore that wording, but still it doesn't make a ton of 
sense.

****************************************************************

From: Tucker Taft
Sent: Friday, November 16, 2018  9:22 PM

I agree it makes more sense to elaborate in the textual order.

****************************************************************

From: Randy Brukardt
Sent: Wednesday, November 21, 2018  7:45 PM

I'm trying to word this for the cleanup AI.

The simple fix is just to reword the existing paragraphs as needed:

Modify 5.5(9/5): [As modified by AI12-0119-1 and AI12-0251-1]

  For the execution of a loop_statement with the iteration_scheme
  including a loop_parameter_specification, the
  loop_parameter_specification is [first] elaborated{ after any
  chunk_specification (see below)}. This elaboration
  creates the loop parameter and elaborates the
  discrete_subtype_definition. If the discrete_subtype_definition
  defines a subtype with a null range, the execution of the
  loop_statement is complete. Otherwise, the sequence_of_statements is
  executed once for each value of the discrete subtype defined by the
  discrete_subtype_definition that satisfies the predicates of the
  subtype (or until the loop is left as a consequence of a transfer of
  control). Prior to each such iteration, the corresponding value of the
  discrete subtype is assigned to the loop parameter. If the reserved
  word parallel is present (a /parallel/ loop), the iterations
  are partitioned into one or more /chunks/, each with its own
  separate logical thread of control (see clause 9), and its
  own copy of the loop parameter; otherwise a single logical thread of
  control performs the loop. Within each logical thread of control,
  the values are assigned to the loop parameter in increasing order
  unless the reserved word reverse is present, in which case the values
  are assigned in decreasing order.

Modify 5.5(9.1/5): [As modified by AI12-0251-1]

  If a chunk_specification is present in a parallel loop, it determines
  the maximum number of logical threads of control devoted to the
  parallel loop. The chunk_specification is elaborated {before}[after] the
  loop_parameter_specification is elaborated[, and before any
  iterations are performed]. If the
  chunk_specification is an /integer_/simple_expression, this
  elaboration evaluates the expression, and the value of the expression
  determines the maximum number of logical threads of control devoted to
  the parallel loop. If a discrete_subtype_definition is present, this
  elaboration elaborates the discrete_subtype_definition, and creates
  one or more logical threads of control, each having its own copy of
  the chunk parameter initialized with a distinct value from the
  discrete subtype defined by the discrete_subtype_definition. Each
  logical thread of control handles a distinct subrange of the values of
  the subtype of the loop parameter such that all values are covered
  with no overlaps. If there is a chunk parameter, its assigned value
  increases with increasing values of the loop parameter. When the
  chunk_specification is elaborated, a check is made that the determined
  maximum number of logical threads of control is greater than zero. If
  this check fails, Program_Error is raised.

============

But this order is weird, because the second item elaborated comes first.
Just reversing the paragraphs doesn't work, because the first paragraph has 
the definitions of "parallel loop" and "chunk" that are used in the second 
paragraph. So we'd have to rewrite this extensively to make that work, 
possibly something like: [The change information doesn't reflect the change 
in the order of the paragraphs.]

  {If the reserved word parallel is present in a loop_statement (a
  /parallel/ loop), the iterations are partitioned into one or more
  /chunks/, each with its own separate logical thread of control (see
  clause 9).} If a chunk_specification is present in a parallel loop, it
  determines the maximum number of logical threads of control devoted to the
  parallel loop. The chunk_specification is {first} elaborated [after the
  loop_parameter_specification is elaborated, and before any
  iterations are performed]. If the
  chunk_specification is an /integer_/simple_expression, this
  elaboration evaluates the expression, and the value of the expression
  determines the maximum number of logical threads of control devoted to
  the parallel loop. If a discrete_subtype_definition is present, this
  elaboration elaborates the discrete_subtype_definition, and creates
  one or more logical threads of control, each having its own copy of
  the chunk parameter initialized with a distinct value from the
  discrete subtype defined by the discrete_subtype_definition. Each
  logical thread of control handles a distinct subrange of the values of
  the subtype of the loop parameter such that all values are covered
  with no overlaps. If there is a chunk parameter, its assigned value
  increases with increasing values of the loop parameter. When the
  chunk_specification is elaborated, a check is made that the determined
  maximum number of logical threads of control is greater than zero. If
  this check fails, Program_Error is raised.

  For the execution of a loop_statement with the iteration_scheme
  including a loop_parameter_specification, the
  loop_parameter_specification is [first] elaborated{ after any
  chunk_specification}. This elaboration
  creates the loop parameter and elaborates the
  discrete_subtype_definition. If the discrete_subtype_definition
  defines a subtype with a null range, the execution of the
  loop_statement is complete. Otherwise, the sequence_of_statements is
  executed once for each value of the discrete subtype defined by the
  discrete_subtype_definition that satisfies the predicates of the
  subtype (or until the loop is left as a consequence of a transfer of
  control). Prior to each such iteration, the corresponding value of the
  discrete subtype is assigned to the loop parameter. {For a parallel
  loop, each chunk has}[If the reserved
  word parallel is present (a /parallel/ loop), the iterations
  are partitioned into one or more /chunks/, each with] its own
  separate logical thread of control [(see clause 9)], and its
  own copy of the loop parameter; {for other loops,}[otherwise] a single
  logical thread of
  control performs the loop. Within each logical thread of control,
  the values are assigned to the loop parameter in increasing order
  unless the reserved word reverse is present, in which case the values
  are assigned in decreasing order.

-----------

Is this enough better to use instead of the previous version? Or is this not 
worth the redo? There's a bit of duplication about the logical threads of 
control, but I thought we needed the reason for the chunks to appear up 
front. Any suggestions or improvements???
 
****************************************************************

From: Tucker Taft
Sent: Wednesday, November 21, 2018  8:53 PM

Let me give it a try.  I think your second version is an improvement, but it 
still seems a bit weird to start talking about creating multiple loop 
parameters before we even elaborate the definition of the loop parameter.
I'll send a reply at some point over the long weekend.

****************************************************************

From: Randy Brukardt
Sent: Wednesday, November 21, 2018  9:12 PM

Sounds good. I probably won't look at it until Monday anyway (leaving for the 
holiday soon).

Keep in mind that there is a small third paragraph that I didn't show (or
change) in the version I sent. You might want to stick it into the blender 
as well as the parts I showed.

***************************************************************

From: Tucker Taft
Sent: Wednesday, November 21, 2018  9:39 PM

Below is an attempt.  I am not going to use "{}" or "[]" because I think 
it just adds to the confusion.


If the reserved word parallel is present in a loop_statement (a 
/parallel/ loop), the iterations are partitioned into one or more
/chunks/, each with its own separate logical thread of control (see 
clause 9). If a chunk_specification is present in a parallel loop, it is
elaborated first, and the result of the elaboration determines the
maximum number of chunks used for the parallel loop.  If the
chunk_specification is an /integer_/simple_expression, the elaboration
evaluates the expression, and the value of the expression determines the
maximum number of chunks. If a discrete_subtype_definition is present,
the elaboration elaborates the discrete_subtype_definition, which
defines the subtype of the chunk parameter, and the number of values in
this subtype determines the maximum number of chunks. After elaborating
the chunk_specification, a check is made that the determined maximum
number of chunks is greater than zero. If this check fails,
Program_Error is raised.

For a loop statement that has an iteration scheme including a
loop_parameter_specification, after elaborating the chunk_specification,
if any, the loop_parameter_specification is elaborated. This elaboration
elaborates the discrete_subtype_definition, which defines the subtype of
the loop parameter. If the discrete_subtype_definition defines a subtype
with a null range, the execution of the loop_statement is complete.
Otherwise, the sequence_of_statements is executed once for each value of
the discrete subtype defined by the discrete_subtype_definition that
satisfies the predicates of the subtype (or until the loop is left as a
consequence of a transfer of control). Prior to each such iteration, the
corresponding value of the discrete subtype is assigned to the loop
parameter associated with the given iteration. If the loop is a parallel
loop, each chunk has its own logical thread of control with its own copy
of the loop parameter; otherwise (a /sequential/ loop), a single logical
thread of control performs the loop, and there is a single copy of the
loop parameter. Each logical thread of control handles a distinct
subrange of the values of the subtype of the loop parameter such that
all values are covered with no overlaps.  Within each logical thread of
control, the values are assigned to the loop parameter in increasing
order unless the reserved word reverse is present, in which case the
values are assigned in decreasing order.

If a chunk_specification with a discrete_subtype_definition is present,
then the logical thread of control associated with a given chunk has its
own copy of the chunk parameter initialized with a distinct value from
the discrete subtype defined by the discrete_subtype_definition.  The
values of the chunk parameters are assigned such that they increase with
increasing values of the ranges covered by the corresponding loop
parameters.

***************************************************************

From: Randy Brukardt
Sent: Monday, November 26, 2018  10:22 PM

Thanks for the wording.

Three minor quibbles.

First, you have "(a /parallel/ loop)". But the term we're defining here is 
"parallel loop", not just parallel. So the italics should include "loop" --
that is "(a /parallel loop/)". The same applies to "sequential loop".

Second, you dropped part of the introduction, specifically "For [the execution
of] a loop_statement..." The "the execution of" part seems needed to be 
consistent with the wording in the rest of the clause. (See while loops and 
unconditional loops).

I presume you dropped it because it is weirdish to talk about elaboration of
a chunk_specification before describing any part of the execution of a loop.
However, I've convinced myself that it is OK, as the elaboration of a 
chunk_specification applies to a number of kinds of loops (it's supposed to 
apply to the "of" form loops, I think; Brad needs to include that in his 
AI12-0266-1 if it isn't there yet). While the following paragraph applies 
only to the execution of one kind of loop.

(Side note: splitting that paragraph into a paragraph that is general, and 
a paragraph that talks about loop parameters, should help out Brad, because
he only wants the first part anyway.)

Third, a number of terms that were previously syntax terms lost their 
underscores. I put them back, seeing no reason to make unnecessary changes.

I won't mention that a number of sentences end with an pair of blanks, and 
others with a single blank. :-)

***************************************************************

From: Randy Brukardt
Sent: Monday, November 26, 2018  10:36 PM

One last thought on this rewording. Nowhere in this wording do we say when the
loop parameter (or parameters) are created. That isn't very important (as 
there is no side-effects from such creation, as noted by an AARM Note), but it
still seems strange. I wondered if we need a To Be Honest AARM note to say
that we don't describe exactly when each loop parameter is created, since it
doesn't have any visible effect, but it does have to be done before the 
associated iteration starts. Or something like that. Thoughts?

***************************************************************

From: Tucker Taft
Sent: Tuesday, November 27, 2018  9:29 AM

> One last thought on this rewording. Nowhere in this wording do we say 
> when the loop parameter (or parameters) are created. That isn't very 
> important (as there is no side-effects from such creation, as noted by 
> an AARM Note), but it still seems strange. I wondered if we need a To 
> Be Honest AARM note to say that we don't describe exactly when each 
> loop parameter is created, since it doesn't have any visible effect, 
> but it does have to be done before the associated iteration starts. Or 
> something like that. Thoughts?

TBH sounds like the right solution.

***************************************************************

From: Tucker Taft
Sent: Tuesday, November 27, 2018  9:27 AM

> Thanks for the wording.
> 
> Three minor quibbles.
> 
> First, you have "(a /parallel/ loop)". But the term we're defining 
> here is "parallel loop", not just parallel. So the italics should 
> include "loop" -- that is "(a /parallel loop/)". The same applies to
> "sequential loop".

Fine.

> 
> Second, you dropped part of the introduction, specifically "For [the 
> execution of] a loop_statement..." The "the execution of" part seems 
> needed to be consistent with the wording in the rest of the clause. 
> (See while loops and unconditional loops).

Yes I dropped it because it didn't seem to make sense any more.
 
> I presume you dropped it because it is weirdish to talk about 
> elaboration of a chunk_specification before describing any part of the 
> execution of a loop.
> However, I've convinced myself that it is OK, as the elaboration of a 
> chunk_specification applies to a number of kinds of loops (it's 
> supposed to apply to the "of" form loops, I think; Brad needs to 
> include that in his
> AI12-0266-1 if it isn't there yet). While the following paragraph 
> applies only to the execution of one kind of loop.
> 
> (Side note: splitting that paragraph into a paragraph that is general, 
> and a paragraph that talks about loop parameters, should help out 
> Brad, because he only wants the first part anyway.)

OK.  I am not sure what you are saying here -- perhaps if I saw your rewording 
it would be obvious.

> Third, a number of terms that were previously syntax terms lost their 
> underscores. I put them back, seeing no reason to make unnecessary changes.

Make sense.
 
> I won't mention that a number of sentences end with an pair of blanks, 
> and others with a single blank. :-)

Yes, let's not mention that... ;-)

***************************************************************

From: Randy Brukardt
Sent: Tuesday, November 27, 2018  8:22 PM

...
> > Second, you dropped part of the introduction, specifically "For [the 
> > execution of] a loop_statement..." The "the execution of" part seems 
> > needed to be consistent with the wording in the rest of the clause.
> > (See while loops and unconditional loops).
> 
> Yes I dropped it because it didn't seem to make sense any more.

In a vacuum, surely. In the context of the entire Dynamic Semantics section
for this subclause, it seems wrong without it (there then would be no 
explanation of the execution of standard for loops, but there is for while 
loops and plain loops).

> > I presume you dropped it because it is weirdish to talk about 
> > elaboration of a chunk_specification before describing any part of 
> > the execution of a loop.
> > However, I've convinced myself that it is OK, as the elaboration of 
> > a chunk_specification applies to a number of kinds of loops (it's 
> > supposed to apply to the "of" form loops, I think; Brad needs to 
> > include that in his
> > AI12-0266-1 if it isn't there yet). While the following paragraph 
> > applies only to the execution of one kind of loop.
> > 
> > (Side note: splitting that paragraph into a paragraph that is 
> > general, and a paragraph that talks about loop parameters, should 
> > help out Brad, because he only wants the first part anyway.)
> 
> OK.  I am not sure what you are saying here -- perhaps if I saw your 
> rewording it would be obvious.

The above is confusing. I was just pointing out that most of the wording 
for chunk_specifications should apply to all kinds of parallel loops (the
elaboration, meaning in terms of chunks, and the check for nonzero all 
apply to all parallel for loops), while the rules about the loop parameter
only apply to discrete "in" for loops. "of" loops don't even have loop 
parameters per-se, and "in" cursor loops have their own set of rules for
managing the loop parameters. In particular, none of those other loop types
have ordering for their parameters, so talking about "non-overlap" and 
"increasing order" is nonsense for them. (Maybe the array loop can talk about
that in terms of the index, but the others get their chunks from the 
user-defined interface that we've been polishing over the last several 
meetings.)

I'm certain that ultimately we intend to have parallel versions of all four 
kinds of "for" loops, even though this AI (and AI12-0119-1 before it) only 
contemplates parallel discrete "in" for loops. Brad supposedly is defining 
those other kinds of loops in AI12-0266-1; the less he has to modify this 
(AI12-0251-1/AI12-0294-1) wording in order to do that sensibly, the better 
off we'll be. (It would be madness to not have chunk_specifications on those
other kinds of loops, so I'm not even considering that.)

***************************************************************

From: Tucker Taft
Sent: Tuesday, November 27, 2018  8:55 PM

> ...
>>> Second, you dropped part of the introduction, specifically "For [the 
>>> execution of] a loop_statement..." The "the execution of" part seems 
>>> needed to be consistent with the wording in the rest of the clause.
>>> (See while loops and unconditional loops).
>> 
>> Yes I dropped it because it didn't seem to make sense any more.
> 
> In a vacuum, surely. In the context of the entire Dynamic Semantics 
> section for this subclause, it seems wrong without it (there then 
> would be no explanation of the execution of standard for loops, but 
> there is for while loops and plain loops).

It may be that we can just sneak in the "For the execution of a ... at the 
beginning of the second paragraph.

>>> I presume you dropped it because it is weirdish to talk about 
>>> elaboration of a chunk_specification before describing any part of 
>>> the execution of a loop.
>>> However, I've convinced myself that it is OK, as the elaboration of 
>>> a chunk_specification applies to a number of kinds of loops (it's 
>>> supposed to apply to the "of" form loops, I think; Brad needs to 
>>> include that in his
>>> AI12-0266-1 if it isn't there yet). While the following paragraph 
>>> applies only to the execution of one kind of loop.
>>> 
>>> (Side note: splitting that paragraph into a paragraph that is 
>>> general, and a paragraph that talks about loop parameters, should 
>>> help out Brad, because he only wants the first part anyway.)
>> 
>> OK.  I am not sure what you are saying here -- perhaps if I saw your 
>> rewording it would be obvious.
> 
> The above is confusing.

Perhaps you were saying that it is good that I *already* split it up into 
multiple paragraphs.  At first I presumed you wanted it to be split further,
but maybe you are simply acknowledging that the split I proposed is useful 
for other reasons as well.

> I was just pointing out that most of the wording for 
> chunk_specifications should apply to all kinds of parallel loops (the 
> elaboration, meaning in terms of chunks, and the check for nonzero all 
> apply to all parallel for loops), while the rules about the loop 
> parameter only apply to discrete "in" for loops. "of" loops don't even 
> have loop parameters per-se, and "in" cursor loops have their own set 
> of rules for managing the loop parameters. In particular, none of 
> those other loop types have ordering for their parameters, so talking 
> about "non-overlap" and "increasing order"
> is nonsense for them. (Maybe the array loop can talk about that in 
> terms of the index, but the others get their chunks from the 
> user-defined interface that we've been polishing over the last several 
> meetings.)
> 
> I'm certain that ultimately we intend to have parallel versions of all 
> four kinds of "for" loops, even though this AI (and AI12-0119-1 before 
> it) only contemplates parallel discrete "in" for loops. Brad 
> supposedly is defining those other kinds of loops in AI12-0266-1; the 
> less he has to modify this
> (AI12-0251-1/AI12-0294-1) wording in order to do that sensibly, the 
> better off we'll be. (It would be madness to not have 
> chunk_specifications on those other kinds of loops, so I'm not even 
> considering that.)

Agreed.

***************************************************************

From: Randy Brukardt
Sent: Tuesday, November 27, 2018  9:07 PM

...
> It may be that we can just sneak in the "For the execution of a ... at 
> the beginning of the second paragraph.

That's what I did. Not sure if the rest makes complete sense with that 
added, but that's why we review what I do at meetings. :-)

***************************************************************

From: Randy Brukardt
Sent: Tuesday, November 27, 2018  1:07 AM

During the Lexington meeting, we had some discussion about the compatibility 
of Nonblocking => True and Yield => True.

The rough draft of the minutes says on this:

  We then discuss whether Nonblocking True is incompatible with Yield True.
  Randy says that the Legality Rule 9.5(57/5) will fail in that case (the
  implicit Yield is illegal in a Nonblocking  => True routine). We then get
  hung up on whether that is going to cause a problem in an expanded generic
  body. Legality Rules aren't rechecked in bodies. We decide to add an
  explicit rule to ensure that no subprogram has Nonblocking => True and
  Yield => True.

The added rule was added to the end of the Static Semantics section defined 
the aspect, and reads:

   If the Nonblocking aspect (see 9.5) of
   the associated callable entity is statically True, the Yield aspect
   shall not be specified as True.

However, this doesn't handle the case where the Nonblocking aspect is based on 
a property of one or more actuals for generic formal parameters. For instance, 
if we have something like:

    generic
       type Priv is private;
       with procedure Munge (Obj : in out Priv);
    package Gen is
       procedure Proc1 (Obj : in out Priv)
           with Nonblocking => Munge'Nonblocking, Yield => True;
    private
       procedure Proc2 (Obj : in out Priv)
           with Nonblocking => Munge'Nonblocking, Yield => True;
    end Gen;

    package body Gen is
        procedure Proc3 (Obj : in out Priv)
           with Nonblocking => Munge'Nonblocking, Yield => True;
    end Gen;

All of Proc1, Proc2, and Proc3 would be declared this way if they intend to 
call Munge in their implementation. These generic units are legal with the 
rule as currently written, since Munge'Nonblocking is not static inside the
generic unit. It only becomes static in the instance (I'll ignore the case of
the instance being given inside of another generic with the actual being a 
formal of that generic so no one's head explodes; it doesn't cause any 
additional problems). Consider an instance with the actual for Munge being 
Nonblocking.

Ada says that by default a Legality Rule is only enforced in the visible part 
of the specification of the instance, so the instance would be illegal because
of Proc1. However, if Proc1 is commented out, the instance would be legal, 
even though Proc2 and Proc3 clearly violate the rule.

For Proc2, we need the usual generic boilerplate. I'd suggest that we move the 
existing rule to an actual Legality Rules section before adding the 
boilerplate; otherwise, it would be very strange to try to apply it to 
something not explicitly marked as a Legality Rule.

For Proc3, we need an assume-the-worst rule, as Legality Rules are never 
enforced in generic bodies. The easiest such rule that I can think of is to 
assume, for the purposes of the original rule, that any nonstatic Nonblocking
attribute has the value True in a generic body. With such a rule, we can avoid
the usual boilerplate for dealing with generic child units, since any generic
child unit is also generic, and thus the body is a generic body. (By saying
"nonstatic", we're including anything not known in the generic body; since 
only Nonblocking attributes that depend on an entity declared in a generic 
could be nonstatic, that seems good enough. If the rule went too far in some
obscure case, it would be erring on the side of correctness.

So I'd recommend that the wording of this aspect get changed to [I'm showing 
all of it except the Dynamic Semantics]:

Add after D.2.1(1.5/2)

For a noninstance subprogram (including a generic formal subprogram), a 
generic subprogram, or an entry, the following language-defined aspect may be 
specified with an aspect_specification (see 13.1.1):

Yield
   The type of aspect Yield is Boolean.

   If directly specified, the aspect_definition shall be a static expression.
   If not specified (including by inheritance), the aspect is False.

   If a Yield aspect is specified True for a primitive subprogram S of a
   type T, then the aspect is inherited by the corresponding primitive
   subprogram of each descendant of T.

Legality Rules

If the Yield aspect is specified for a dispatching subprogram that inherits 
the aspect, the specified value shall be confirming.

If the Nonblocking aspect (see 9.5) of the associated callable entity is 
statically True, the Yield aspect shall not be specified as True. For a 
callable entity that is declared within a generic body, this rule is checked
assuming that any nonstatic Nonblocking attributes in the expression of the 
Nonblocking aspect of the entity are statically True.

  AARM Reason: The second sentence here is an assume-the-worst rule. The
  only Nonblocking attributes that are nonstatic are those that depend,
  directly or indirectly, on the nonblocking aspect of a generic formal
  parameter. We have to assume these might in fact have the value True if
  given an appropriate actual entity.

In addition to the places where Legality Rules normally apply (see 12.3), 
these rules also apply in the private part of an instance of a generic unit.

---

I moved the other Legality Rule also to this new Legality Rules section; it 
would be weird if it was left in Static Semantics.

Note that the boilerplate also applies to this first rule. It could depend 
on an inherited subprogram that came only from an actual type passed to a 
formal parameter; thus a recheck could be necessary. The case would be quite
obscure -- common for rechecks -- but still needs checking.

Thoughts on this redo? It's a pretty big change, and rather obscure, so I 
think it would best go into the clean-up AI.

***************************************************************

From: Tullio Vardanega
Sent: Tuesday, November 27, 2018  4:33 AM

Yup: with brain nearly exploding, I would go with your rewrite, Randy.

***************************************************************

From: Tucker Taft
Sent: Tuesday, November 27, 2018  9:19 AM

Agreed, on both counts. ;-)

***************************************************************


Questions? Ask the ACAA Technical Agent