250 likes | 421 Views
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 }
E N D
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; { 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) thenthen { 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: …} }