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: { S1, S2 … Sk } 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 + 1 2 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; Y := 2 end { X = 1; Y = 2; } 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 then Statements elseif Conditions then Statements else Statements if (Conditions) { Statements } else if (Conditions) then { Statements} else { Statements } 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 1 .. 10 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: …} }