control structures any mechanism that departs from straight-line execution: –selection:...

22
Control Structures Any mechanism that departs from straight-line execution: Selection: if-statements Multiway-selection: case statements Unbounded iteration: while-loops Definite iteration: for-loops Iterations over collections transfer of control: gotos unbounded transfer of control: exceptions, backtracking

Upload: kaley-blore

Post on 14-Dec-2015

220 views

Category:

Documents


0 download

TRANSCRIPT

Control Structures

• Any mechanism that departs from straight-line execution:

– Selection: if-statements

– Multiway-selection: case statements

– Unbounded iteration: while-loops

– Definite iteration: for-loops

– Iterations over collections

– transfer of control: gotos

– unbounded transfer of control: exceptions, backtracking

Selection

• if Condition then Statement -- Pascal, Ada• if (Condition) Statement -- C, C++ Java• All you need for a universal machine: increment, decrement, branch on

zero. All the rest is programmer convenience!• To avoid ambiguities, use end marker: end if, “}” • To deal with alternatives, use keyword or bracketing:

if Condition then if (Condition) {

Statements Statements }

elsif Condition then else if (Condition) {

Statements Statements}

else else {

Statements Statements}

end if;

Nesting

if Condition then if (Condition)

if Condition then if (Condition) {

Statements Statements

end if; }

else else {

Statements Statements

end if; }

Statement Grouping

• Pascal introduces begin-end pair to mark sequence• C/C++/Java abbreviate keywords to { }• Ada dispenses with brackets for sequences, because keywords

for the enclosing control structure are sufficient:

• for J in 1 .. N loop … end loop;– More writing => more readable

• The use of grouping in C a reminder that it is an expression language

• The use of grouping in C++/Java is just syntactic tradition• Another possibility (ABC, Python): make indentation significant

Short-Circuit Evaluation

• If x is more than five times greater than y, compute z:• if x / y > 5 then z := … -- but what if y is 0?

• If y /= 0 and x/ y > 5then z := … -- but operators evaluate their arguments

• Solutions:– a lazy evaluation rule for logical operators (LISP, C, etc)

– a control structure with a different syntax

• C1 && C2 does not evaluate C2 if C1 is false • if C1 and then C2 then ditto• C1 || C2 does not evaluate C2 if C1 is true• if C1 or else C2 then ditto

Multiway selection

• The case statement is the most useful control structure because most programs are interpreters.

• Can be simulated with a sequence of if-statements, but logic• become obscured.

case Next_Char is

when ‘I’ => Val := 1;

when ‘V’ => Val := 5;

when ‘X’ => Val := 10;

when ‘C’ => Val := 100;

when ‘D’ => Val := 500;

when ‘M’ => Val := 1000;

when others => raise Illegal_Numeral;

end case;

The well-structured case statement

• Type of expression must be discrete: an enumerable set of values (floating-point numbers not acceptable)

• each choice is independent of the others (no flow-through)• There are no duplicate choices• All possible choices are covered• There is mechanism to specify a default outcome for choices

not given explicitly.

Implementation

• Finite set of possibilities: can build a table of addresses, and• convert expression into table index:

– compute value

– transform into index

– retrieve address of corresponding code fragment

– branch to code fragment and execute

– branch to end of case statement

• All cases have the same execution cost• All choices must be static: computable at compile-time

Complications

case (X + 1) is -- any integer value (discrete but large)

when integer’first .. 0 => Put_Line (“negative”);

when 1 => Put_Line (“unit”);

when 3 | 5 | 7 | 11 => Put_Line (“smal prime”);

when 2 | 4 | 6 | 8 | 10 => Put_Line (“small even”);

when 21 => Put_Line (“the house wins”);

when 12 .. 20 | 22 .. 99 => Put_Line (“manageable”);

when others => Put_Line (“Irrelevant”);

end case;• Implementation must be combination of tables and if-statements.

Unstructured flow (Duff’s device)

void send (int* to, int* from, int count) {int n = (count + 7 ) / 8;switch (count % 8) {

case 0 : do { *to++ = *from++;case 7 : *to++ = *from++;case 6 : *to++ = *from++;case 5 : *to++ = *from++;case 4 : *to++ = *from++;case 3 : *to++ = *from++;case 2 : *to++ = *from++;case 1 : *to++ = *from++; } while (--n >0); }}

What does this do? Why bother?

Indefinite loops

• All loops can be expressed as while-loops• Condition is evaluated at each iteration• If condition is initially false, loop is never executed

while Condition loop .. end loop;

• equivalent to

if Condition then

while Condition loop … end loop;

end if;

• (provided Condition has no side-effects…)

What if we want to execute at least once?

• Pascal introduces until-loop.• C/C++ use different syntax with while:

while (Condition) { … }

do { … } while (Condition)

• While form is most common• Can always simulate with a boolean variable:

first := True;

while (Condition or else first) loop

first := False;

end loop;

Breaking out

• More common is the need for an indefinite loop that terminates in the middle of an iteration.

• C/C++/Java: break• Ada : exit statement

loop -- infinite loop

compute_first_part;

exit when got_it;

compute_some_more;

end loop;

Multiple exits

• Within nested loops, useful to specify exit from several of them• Ada solution: give names to loops• Otherwise: use a counter (Modula) or use a goto.

• Outer: while C1 loop ...• Inner: while C2 loop...• Innermost: while C3 loop...• exit Outer when Major_Failure;• exit Inner when Small_Annoyance;• ...• end loop Innermost;• end loop Inner;• end loop Outer;

Definite loops

• Counting loops are iterators over discrete domains:• for J in 1..10 loop …• for (int I = 0; I < N; I++ ) ..• Design issues:

– Evaluation of bounds (only once, ever since Algol60)

– Scope of loop variable

– Empty loops

– Increments other than one

– Backwards iteration

– non-numeric domains

Evaluation of bounds

for J in 1 .. N loop

N := N + 1;

end loop; -- terminates?

• In Ada, bounds are evaluated once before iteration starts. The above always terminates (and is abominable style).

• The C/C++/Java loop has hybrid semantics: for (int J = 0; J < last; J++) { … last++; -- does not terminate! }

The loop variable

• Best if local to loop and treated as constant• Avoids issue of value at termination, and value on abrupt exit

• counter : integer := 17; -- outer declaration• ...• for counter in 1 ..10 loop• do_something; -- 1 <= counter <= 10• end loop;• …• -- counter is still 17

Different increments

• The universal Algol60 form:• for J from Exp1 to Exp2 by Exp3 do…• Too rich for most cases. Exp3 is most often +1, -1.• What is meaning if Exp1 > Exp2 and Exp3 < 0 ?• In C/ C++

for (int J = Exp1; J <= Exp2; J = J + Exp3) …

• In Ada:

for J in 1 .. N loop -- increment is +1

for J in reverse 1 .. N loop -- increment is -1

• Everything else can be programmed with while-loop

Non-numeric domains

• Ada form generalizes to discrete types:

• for M in months loop …

• Basic pattern on other data-types:• define primitive operations: first, next, more_elements:

Iterator = Collection.Iterate(); // build an iterator over a collection of elements

element thing = iterator.first; // define loop variable

while (iterator.more_elements ()) {

...

thing = iterator.next (); // value is each successive element

}

How do we know it’s right?

• Pre-Conditions and Post-conditions:• {P} S {Q} means:• if Proposition P holds before executing S,• and the execution of S terminates,• then proposition Q holds afterwards.• Need to formulate pre- and post-conditions for all statement

forms, and syntax-directed rules of inference.

{P and C} S {P}

(P and C} while C do S end loop; {P and not C}

i.e. on exit from a while-loop we know the condition is false.

Efficient exponentiation

function Exp (Base : Integer; Expon : Integer) return integer is

N : Integer := Expon; -- to pick up successive bits of exponent

Res : Integer := 1; -- running result

Pow : Integer := Base; -- successive powers: Base ** (2 ** I)

begin

while N > 0 loop

if N mod 2 = 1 then

Res := Res * Pow;

end if;

Pow := Pow * Pow;

N := N / 2;

end loop;

return Res;

end Exp;

Adding invariants

function Exp (Base : Integer; Expon : Integer) return integer is

… declarations

… {i = 0} to count iterations

begin

while N > 0 loop

{i := i + 1}

if N mod 2 = 1 then { N mod 2 is ith bit of Expon from left}

Res := Res * Pow; { Res := Base ** (Expon mod 2 ** i}

end if;

Pow := Pow * Pow; { Pow := Base ** (2 ** i)}

N := N / 2; { N := Expon / ( 2 ** i) }

end loop;

return Res; {i = log Expon; N = 0; Res = Base ** Expon}

end Exp;