Control Structures
Hierarchical Statement Structure Standard in imperative languages since Algol60. Exceptions: Early FORTRAN, COBOL, early BASIC, APL. (Fortran kludged definite loops.)
Control structures within function Sequence: { S 1, S 2 … S k } Conditional: if statement, case statement. Loop: while loop, for loop. Jump: goto, exception raising
Expression evaluation Ambiguity of grouping: is 1+2*3 interpreted as (1+2)*3=9 or 1+(2*3)=7? Solutions: Operator precedence. * binds more tightly than +, so 1+2*3 = 7. Order precedence. Always compute left to right so 1+2*3=(1+2)*3 = 9 Best to use a lot of parentheses.
Short circuit evaluation If Y <> 0 and X/Y > 5, compute Z. if (Y <> 0 and X/Y > 5) Z = … --- but operators evaluate their arguments Solutions: Lazy evaluation of Booleans: if (Y <> 0 && X/Y > 5) Z = … Explicit conditionals if (Y <> 0) then if (X/Y > 5) Z= …
Prefix and postfix notation Prefix: Operator precedes its arguments Postfix: Operator follows its arguments e.g. (1+3*N)/[(1+N)*(1+2*N)] Prefix: / + 1 * 3 N *+ 1 N + 1 * 2 N Postfix: 1 3 N * + 1 N N * + * / If each operator has a fixed number of arguments, then prefix and postfix are unambiguous with no need for brackets, precedence, or associativity conventions.
Control structure between functions Function call and return Coroutine yield Parallel synchronization Exception raising
Assembly language In assembly language, (essentially) the only control structures are: Progression: Move to the next statement (increment the program counter). Unconditional jump: JMP A Jump to address A Conditional jump: JMZ R,A If (R==0) then jump to A Possible forms of conditions and addresses vary.
Sequence Pascal: begin … end C, C++, Java: { … } Ada: Brackets for sequence are unnecessary. Keywords for control structures suffice. for J in 1.. N loop … end loop ABC, Python: Indicate structure by indentation.
Semicolons Pascal: Semicolons are separators C etc.: Semicolons are terminators begin X := 1; { X = 1; Y := 2 Y = 2; end }
Conditionals if Condition then Statement -- Pascal, Ada if (Condition) Statement -- C, C++, Java To avoid ambiguities, use end marker: end if, “}” To deal with alternatives, use keyword or bracketing: if Conditions if (Conditions) then Statements { Statements } elseif Conditions else if (Conditions) then Statements then { Statements} else Statements else { Statements } end if
if-else ambiguity if Conditions if (Conditions) then then { if Conditions if (Conditions) then Statements { Statements } else Statements else { Statements } end if } end if
Compiling conditionals if (Cond) then Statement1 else Statement2 Assembly: …. Compute Cond in register R JMZ R,L … Code for Statement1 JMP END L: … Code for Statement2 END: … Next statement
Multi-way selection “The case statement is the most useful control structure because most programs are interpreters.” (Ed Schonberg) Can achieve same with conditionals, but case statements are clearer. case (NextChar) { I: N=1; V: N=5; X: N=10 L: N=50 }
The well-structured case statement Discrete type. No flow-through (hideous C misdesign). Every value is in exactly one option. Default option for values not covered. Labels are computable at compile time.
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
Loops while loop: test at beginning while (Condition) Statement repeat loop: test at end repeat Statement until Condition do Statement while (Condition) breaking out: test in middle loop Statement if (condition) then exitloop; Statement end loop
Multiple exits If you want to exit from imbedded loops, you need to specify which one you’re exiting. Ada solution: Label loops Outer: while C1 loop … Inner: while C2 loop … Innermost: while C3 loop … exit Outer when MajorFailure; exit Inner when SmallAnnoyance; end loop Innermost; end loop Inner; end loop Outer;
Definite loops for J in loop … end loop for (int I=0; I < N; I++) … Design issues: Evaluation of bounds (only at start, since Algol60) Scope of loop variables Empty bodies Increments other than 1 Backward iteration Non-numeric domains
Definite loops Since the C for loop for (start; test; increment) body; allows arbitrary test conditions and arbitrary increment actions, this is not really a definite loop at all, just an distinctively formatted while loop. However, the compiler is sensitive to the particular construction for (int I=0; I < N; I++) and optimizes the code for this.
C: break and continue break: exit innermost loop (exitloop) continue: go to next iteration of innermost loop.
Loop counter Local to loop? If not, what is the value on exit? Settable in body of loop? Multiple loop counters?
Non-numeric domains Ada: for M in months loop … end loop Other data types: iterator = Collection.iterator(); element thing = iterator.first; while (iterator.moreElements()) { Body; thing = interator.next(); }
Implementation of loops loop Statement1; if (condition) exit loop; Statement2; end loop L1: … Code for Statement1 … Compute not(condition) and put in R; JMZ R,L2 … Code for Statement2 JMP L1 L2: Next statement
Gotos If you don’t have hierarchical statement structure, you need goto’s. “Go To Statements Considered Harmful” --- Dijkstra, 1968 Many more recent languages (e.g. Java) don’t have them. Certainly must prohibit jumping into the middle of a embedded structure; e.g. { … go to L for (int I=0; I<N; I++) { … L: …} }