5.5 Loop Statements
Syntax
Name Resolution Rules
Static Semantics
Dynamic Semantics
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.
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.
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.
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.
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.
for J in reverse 1 .. 0
for J in 0 .. 1
Examples
Example of a loop
statement without an iteration scheme:
loop
Get(Current_Character);
exit when Current_Character = '*';
end loop;
Example of a loop
statement with a while iteration scheme:
while Bid(N).Price < Cut_Off.Price loop
Record_Bid(Bid(N).Price);
N := N + 1;
end loop;
Example of a loop
statement with a for iteration scheme:
for J in Buffer'Range loop -- works even with a null range
if Buffer(J) /= Space then
Put(Buffer(J));
end if;
end loop;
Example of a loop
statement with a name:
Summation:
while Next /= Head
loop --
see 3.10.1
Sum := Sum + Next.Value;
Next := Next.Succ;
end loop Summation;
Example of a simple
parallel loop:
--
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;
Example of a parallel
loop with a chunk specification:
declare
subtype Chunk_Number is Natural range 1 .. 8;
Partial_Sum,
Partial_Max : array (Chunk_Number) of Natural := (others => 0);
Partial_Min : array (Chunk_Number) of Natural :=
(others => Natural'Last);
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;
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;
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe