You're almost ready to write your own Ada program in an Outside Assignment, but first we need to discuss the control constructs.
Ada encourages structured programming by providing control constructs such as
block ifs with elsifs and else while loops for loops case statements
Ada also provides a goto statement, but it's seldom if ever needed. That's because the constructs above handle the flow of control more clearly, making the program easier to read. With the constructs above, we know how control reaches each statement. When gotos are used, there can be many paths to a statement, and we're not sure how control got there.
Let's look at the above control constructs, and the goto statement, one at a time. Discussion of the declare statement and Ada "blocks" is postponed until we cover exception handlers.
The "IF" Block
if A >= B and C = A + D then -----; -----; (block of code) -----; end if;
In Ada, every if introduces a block of code that ends with end if;. There are no exceptions; every if always has an end if;. The condition is followed by then, and it can be any expression with a Boolean result. The above example is valid if A, B, C, and D are suitably declared. Each statement in the block of code, including the last, has a semicolon. Note that end if; is two reserved words, so there must be at least one space between them. All Ada control constructs, including if blocks, can be nested to any depth.
In Pascal and C, if is designed to execute only one statement conditionally. If there are several statements to be executed conditionally, they have to be enclosed with "begin ... end" in Pascal or braces in C, so they will be considered as one statement. In Ada, however, if always starts a block of code, so "begin ... end" or braces aren't necessary. The end of the block is always marked by end if; even if there's just one statement in the block.
if A >= B and C = A + D then -----; -----; -----; elsif G = H + P then -----; elsif Q > R or S <= T then -----; -----; else -----; end if;
The reserved words elsif and else are also available; note the unusual spelling of elsif. In the above example, only one of the four blocks of code will be executed. If A >= B and C = A + D is True, the first block of code will be executed and the remaining tests and blocks will be skipped. Control will continue after the end if;. If A >= B and C = A + D is False, then G = H + P will be tested. If it's True, the second block, and only that block, will be executed; otherwise, Q > R or S <= T will be tested. If that's True, the third block will be executed; otherwise the else block will be executed. If all the tests are False and there's no else block, then no blocks are executed.
The above block of code is equivalent with the following code:
if A >= B and C = A + D then -----; -----; -----; else if G = H + P then -----; else if Q > R or S <= T then -----; -----; else -----; end if; end if; end if;
Note that elsif is equivalent to else plus if ... end if;. Although the two program segments above are equivalent, the first one is much clearer. The example on first one doesn't require multiple end ifs at the bottom, and the indentation emphasizes that only one of the four blocks of code will be executed.
D, N : Integer := 1; ... if D = 0 then One; elsif N/D = 1 then Two; elsif D = 1 then Three; else Four; end if;In this segment of code, which procedure(s) will be called?
Procedure One will be called.
No, both D and N are initialized to 1, so the first test, D = 0, is False and the second test is made. The block that's executed is the first block following a test that's True.
Procedure Two will be called
You're right! The first test, D = 0, is False, so the second test is made. N/D = 1 is True, so Two is called. Since only one block of code is executed in an if block, the remaining tests are not done.
Procedure Three will be called.
No, both D and N are initialized to 1, so the second test, N/D = 1, is True. The block that's executed is the first block following a test that's True.  Once a block is executed, no further tests in that if block are made. Thus, Three isn't called even though D = 1 is True.
Procedure Four will be called.
No, both D and N are initialized to 1, so the second test, N/D = 1, is True. The block that's executed is the first block following a test that's True. The else block is executed only if all the tests are False.
Procedures Two and Three will be called.
No, although N/D = 1 and D = 1 are both True, only one block of code in an if block is executed. The block that's executed is the first block following a test that's True.
while I < 10 loop -----; -----; -----; end loop;
The while loop first evaluates the Boolean expression (I < 10 in this example).* If it's False, the block of code isn't executed at all, and execution continues after the end loop;. If it's True, the block of code is executed and then the Boolean condition is again evaluated. If the condition is still True, the block is executed again and the Boolean expression is evaluated again, and so forth. When the Boolean expression becomes False, the block of code is skipped and execution continues after the end loop;.
To create an "infinite loop," it isn't necessary to write while True loop ... end loop;. We simply write loop ... end loop;, like this:
loop -----; -----; -----; end loop;
An infinite loop might be useful in a device that continually does the same thing so long as power is applied.
Ada doesn't have a "repeat ... until" loop, with the test at the bottom. However, we can create a loop that's equivalent to a "repeat ... until" loop by using what would otherwise be an infinite loop with an exit statement, to be covered very soon.
for Ix in 1 .. 10 loop for Ix in reverse 1 .. 10 loop -----; -----; -----; -----; end loop; end loop;
Here are two sample for loops. We need not declare the index (Ix in these examples) in the declarative region of the program; an index of a for loop declares itself. In these examples, Ix comes into existence at the for statement and goes out of existence at end loop; the index isn't available outside the loop. If the name Ix happens to appear in the declarative region, it's a different Ix. Inside the loop Ix refers to the index; there the name Ix is said to hide any Ix that might be mentioned in the declarative region.
The index variable may not be modified. In these examples, Ix may not appear on the left side of an assignment statement, etc.
In the first example above, the block of statements is executed ten times, with Ix equal to 1, then 2, then 3, etc., up to 10. In the second example, Ix starts at 10 and counts down to 1. Note that the range is still written 1 .. 10, but the keyword reverse precedes the range.
The index of a for loop can have any discrete type. That means any integer or enumeration type. It can't be of type Float. For example, if we write
type Rainbow_Color is (Red, Orange, Yellow, Green, Blue, Indigo, Violet); type Traffic_Light_Color is (Red, Amber, Green);then we can write for Ix in Red .. Blue loop,, and the compiler will know that Ix must be of type Rainbow_Color. Similarly, the compiler will know that the type of Ix must be Traffic_Light_Color if we write for IX in Red .. Amber loop. But the compiler can't handle for Ix in Red .. Green loop because of the ambiguity. In this case we must specify the type. For example, we could write either of these:
for Ix in Rainbow_Color'(Red) .. Green loop for Ix in Rainbow_Color range Red .. Green loop
Because the index can have any discrete type, there's no STEP clause in Ada, as there is in Basic. One might increment an Integer index by 2, but we couldn't add 2 to Red. For uniformity, no STEP clause is available, even if the index type is Integer.
Ranges may contain expressions. If A, B, C, and D are Integer variables, we can say for I in A + B .. C + D loop or for I in reverse A + B .. C + D loop. In both cases the range is null if C + D is less than A + B. That won't cause an error; the loop is simply skipped when the range is null.
QuestionIf we have
type Rainbow_Color is (Red, Orange, Yellow, Green, Blue, Indigo, Violet); J : Integer := 5;which one of these statements is illegal?
for I in -J .. J loop
No, number 1 is legal. The expressions on both sides of .. have the same type. I will be of type Integer and will take 11 values, from -5 to 5.
for I in J .. Violet loop
You're right! Number 2 is illegal because the expressions before and after the ".." must be of the same type.
for I in Violet .. Red loop
No, number 3 is legal. The expressions on both sides of .. have the same type. The loop will be skipped because Red is less than Violet, giving a null range. But the syntax is legal. To make I start at Violet and count down to Red, we would write
for I in reverse Red .. Violet loop