Annotated Ada Reference Manual (Ada 202y Draft 1)Legal Information
Contents   Index   References   Search   Previous   Next 

5.5 Loop Statements

1/5
{AI12-0119-1} [A loop_statement includes a sequence_of_statements that is to be executed repeatedly, zero or more times with the iterations running sequentially or concurrently with one another.] 

Syntax

2
loop_statement ::= 
   [loop_statement_identifier:]
      [iteration_schemeloop
         sequence_of_statements
       end loop [loop_identifier];
3/5
{AI05-0139-2} {AI12-0119-1} {AI12-0189-1} {AI12-0251-1} {AI12-0266-1} {AI12-0326-2} {AI12-0355-2} iteration_scheme ::= while condition
   | for loop_parameter_specification
   | for iterator_specification
   | [parallel [aspect_specification]]
     for procedural_iterator
   | parallel [(chunk_specification)] [aspect_specification]
     for loop_parameter_specification
   | parallel [(chunk_specification)] [aspect_specification]
     for iterator_specification
3.1/5
{AI12-0251-1} chunk_specification ::= 
     integer_simple_expression
   | defining_identifier in discrete_subtype_definition
4/5
{AI12-0250-1} loop_parameter_specification ::= 
   defining_identifier in [reversediscrete_subtype_definition
     [iterator_filter]
4.1/5
{AI12-0250-1} iterator_filter ::= when condition
5
If a loop_statement has a loop_statement_identifier, then the identifier shall be repeated after the end loop; otherwise, there shall not be an identifier after the end loop.
5.1/5
{AI12-0119-1} An iteration_scheme that begins with the reserved word parallel shall not have the reserved word reverse in its loop_parameter_specification.

Name Resolution Rules

5.2/5
 {AI12-0251-1} In a chunk_specification that is an integer_simple_expression, the integer_simple_expression is expected to be of any integer type. 

Static Semantics

6/5
{AI12-0061-1} A loop_parameter_specification declares a loop parameter, which is an object whose subtype (and nominal subtype) is that defined by the discrete_subtype_definition.
6.1/5
 {AI12-0251-1} In a chunk_specification that has a discrete_subtype_definition, the chunk_specification declares a chunk parameter object whose subtype (and nominal subtype) is that defined by the discrete_subtype_definition.

Dynamic Semantics

6.2/5
 {AI12-0250-1} {AI12-0327-1} The filter of an iterator construct (a loop_parameter_specification, iterator_specification, or procedural_iterator) is defined to be satisfied when there is no iterator_filter for the iterator construct, or when the condition of the iterator_filter evaluates to True for a given iteration of the iterator construct.
6.a/5
Term entry: iterator filter — construct that is used to restrict the elements produced by an iteration to those for which a boolean condition evaluates to True
6.3/5
 {AI12-0250-1} {AI12-0327-1} If a sequence_of_statements of a loop_statement with an iterator construct is said to be conditionally executed, then the statements are executed only when the filter of the iterator construct is satisfied.
6.4/5
 {AI12-0250-1} {AI12-0327-1} The loop iterators loop_parameter_specification and iterator_specification can also be used in contexts other than loop_statements (for example, see 4.3.5 and 4.5.8). In such a context, the iterator conditionally produces values in the order specified for the associated construct below or in 5.5.2. The values produced are the values given to the loop parameter when the filter of the iterator construct is satisfied for that value. [No value is produced when the condition of an iterator_filter evaluates to False.]
7/5
{AI12-0119-1} For the execution of a loop_statement, the sequence_of_statements is executed zero or more times, until the loop_statement is complete. The loop_statement is complete when a transfer of control occurs that transfers control out of the loop, or, in the case of an iteration_scheme, as specified below.
8
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.
8.1/5
 {AI12-0251-1} {AI12-0294-1} If the reserved word parallel is present in the iteration_scheme of 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.
9/5
{AI05-0139-2} {AI05-0262-1} {AI12-0071-1} {AI12-0119-1} {AI12-0250-1} {AI12-0251-1} {AI12-0294-1} {AI12-0355-2} {AI12-0416-1} For the execution of a loop_statement that has an iteration_scheme including a loop_parameter_specification, after elaborating the chunk_specification and aspect_specification, if any, the loop_parameter_specification is elaborated. This 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 conditionally 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. In the absence of a transfer of control, the associated parallel construct of a loop_parameter_specification is complete when all of its logical threads of control are complete.
9.a.1/5
To be honest: {AI12-0294-1} 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.
9.a/5
This paragraph was deleted.{AI12-0294-1}
9.b/3
Ramification: {AI05-0262-1} The predicate (if any) necessarily has to be a static predicate as a dynamic predicate is explicitly disallowed — see 3.2.4.
9.c/3
Reason: {AI05-0262-1} If there is a predicate, the loop still visits the values in the order of the underlying base type; the order of the values in the predicate is irrelevant. This is the case so that the following loops have the same sequence of calls and parameters on procedure Call for any subtype S: 
9.d
for I in S loop
   Call (I);
end loop;
9.e
for I in S'Base loop
   if I in S then
      Call (I);
   end if;
end loop;
9.f/5
Discussion: {AI12-0416-1} The rules for completing a parallel construct when there is a transfer of control are given in 5.1
10/5
{AI12-0251-1} {AI12-0294-1} 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.
11/5
{AI12-0251-1} 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.
12/5
{AI05-0262-1} {AI12-0250-1} {AI12-0266-1} [For details about the execution of a loop_statement with the iteration_scheme including an iterator_specification, see 5.5.2. For details relating to a procedural_iterator, see 5.5.3.]
13/5
NOTE 1   {AI12-0250-1} A loop parameter declared by a loop_parameter_specification is a constant; it cannot be updated within the sequence_of_statements of the loop (see 3.3).
14/5
NOTE 2   {AI12-0442-1} No separate object_declaration is expected for a loop parameter, since the loop parameter is automatically declared by the loop_parameter_specification. The scope of a loop parameter extends from the loop_parameter_specification to the end of the loop_statement, and the visibility rules are such that a loop parameter is only visible within the sequence_of_statements of the loop. 
14.a
Implementation Note: An implementation could give a warning if a variable is hidden by a loop_parameter_specification.
15/5
NOTE 3   The discrete_subtype_definition of a for loop is elaborated just once. Use of the reserved word reverse does not alter the discrete subtype defined, so that the following iteration_schemes are not equivalent; the first has a null range. 
16
for J in reverse 1 .. 0
for J in 0 .. 1
16.a
Ramification: If a loop_parameter_specification has a static discrete range, the subtype of the loop parameter is static.

Examples

17
Example of a loop statement without an iteration scheme: 
18
loop
   Get(Current_Character);
   exit when Current_Character = '*';
end loop;
19
Example of a loop statement with a while iteration scheme: 
20
while Bid(N).Price < Cut_Off.Price loop
   Record_Bid(Bid(N).Price);
   N := N + 1;
end loop;
21
Example of a loop statement with a for iteration scheme: 
22
for J in Buffer'Range loop     --  works even with a null range
   if Buffer(J) /= Space then
      Put(Buffer(J));
   end if;
end loop;
23
Example of a loop statement with a name: 
24
Summation:
   while Next /= Head loop       -- see 3.10.1
      Sum  := Sum + Next.Value;
      Next := Next.Succ;
   end loop Summation;
25/5
{AI12-0119-1} {AI12-0312-1} Example of a simple parallel loop: 
26/5
-- see 3.6
parallel
for I in Grid'Range(1) loop
   Grid(I, 1) := (for all J in Grid'Range(2) => Grid(I,J) = True);
end loop;
27/5
{AI12-0312-1} Example of a parallel loop with a chunk specification: 
28/5
declare
   subtype Chunk_Number is Natural range 1 .. 8;
29/5
   Partial_Sum,
   Partial_Max : array (Chunk_Number) of Natural := (others => 0);
   Partial_Min : array (Chunk_Number) of Natural :=
                       (others => Natural'Last);
30/5
begin
   parallel (Chunk in Chunk_Number)
   for I in Grid'Range(1) loop
      declare
         True_Count : constant Natural :=
           [for J in Grid'Range(2) =>
              (if Grid (I, J) then 1 else 0)]'Reduce("+",0);
      begin
         Partial_Sum (Chunk) := @ + True_Count;
         Partial_Min (Chunk) := Natural'Min(@, True_Count);
         Partial_Max (Chunk) := Natural'Max(@, True_Count);
      end;
   end loop;
31/5
{AI12-0386-1}    Put_Line
     ("Total=" & Partial_Sum'Reduce("+", 0)'Image &
      ", Min=" & Partial_Min'Reduce(Natural'Min, Natural'Last)'Image &
      ", Max=" & Partial_Max'Reduce(Natural'Max, 0)'Image);
end;
32/5
{AI12-0312-1} For an example of an iterator_filter, see 4.5.8. 

Wording Changes from Ada 83

32.a
The constant-ness of loop parameters is specified in 3.3, “Objects and Named Numbers”. 

Wording Changes from Ada 2005

32.b/3
{AI05-0139-2} {AI05-0262-1} {AI05-0299-1} Generalized iterator_specifications are allowed in for loops; these are documented as an extension in the appropriate subclause. 

Extensions to Ada 2012

32.c/5
{AI12-0119-1} {AI12-0251-1} {AI12-0266-1} {AI12-0294-1} Parallel loops are new.
32.d/5
{AI12-0250-1} An iterator_filter is now allowed on loop_parameter_specifications. This is mainly for consistency with aggregate and reduction iterators, where it eliminates the need for temporary objects. 

Wording Changes from Ada 2012

32.e/4
{AI12-0071-1} Corrigendum: Updated wording of loop execution to use the new term "satisfies the predicates" (see 3.2.4).
32.f/5
{AI12-0061-1} Added text so that the nominal subtype of a loop parameter is clearly defined. 

Contents   Index   References   Search   Previous   Next 
Ada-Europe Ada 2005 and 2012 Editions sponsored in part by Ada-Europe