Control Statements: Structured Control Statements: Case Statements: - Implementation using if-then-else - Understand semantics in terms of the semantics of simple constructs - actual implmentation in a compiler Loops - while, repeat, for while: let s1 = while C do S then it can also be written as s1 = if C then {S; s1} repeast let s2 = repeat S until C then it can alos be written as s2 = S; if (!C) then S2 (Note that repeat S until C means execute S; evaluate C and if C is false, repeat this process - until C is true) loop S end (S should contain an exit statement to break out of the loop - otherwise loop will never terminate). Unstructured Control Statement - goto (the only control mechanism in old FORTRAN) - programs with goto's are difficult to understand. Consider 40: if (x > y) then goto 10 if (x < y) then goto 20 goto 30 10: x = x - y goto 40 20: y = y -x goto 40 30: gcd = x an equivalent program with structured control statements is much more readable: while (x != y) do { if (x > y) then x = x - y else y = y - x } goto should be used in rare circumstances; e.g., error handling, when an unrecoverable error condition happens in a deeply nested loop statement Java doesn't have goto; breaking out of deeply nested loops supported via "labelled break" statemnt. e.g., l1 : for ( ... ) { whlie ( ... ) { ... break l1 } } here, break l1 staements causes the control to break out of the for loop Restrictions in use of goto: - jumps outside of a procedure - jumps from outer blocks to inner blocks or unrelated blocks goto l1; if ( ... ) then { int x ; x = 5 ; l1: y = x * x ; } in this case, (if goto is allowed to inner blocks) the value of x is not known when jump is made to l1, since x is allocated only when the block containing it (if statement evaluates to true) is entered, but in this case jump is to middle of the block, so x is not even defined! Similarly, gotos into unrelated blocks is not allowed: if ( ... ) { ... goto l2 ; } else { ... l2 : ... } Procedure Calls: Communication between the calling and the called procedures via parameters. Parameters are passed using different mechanisms. Parameter passing is the mechanism of substitution of formal parameters by actual parameters. Execution of the body of the procedures is the replacement of procedure invocation with procedure body Parameter passing mechanisms: Call-by-value : evaluate the actual parameters, assign them to corresponding formal parameters, execute the body of the procedure int p(int x) { x = x + 1 ; return x ; } with call-by-value, an expression y = p(5+3) is executed as follows: evaluate 5+3 = 8, call p with 8, assign 8 to x, increment x, return x which is assigned to y. Call-by-reference: evaluate actual parameters, which must have l-values assign these l-values to l-values of corresponding formal parameters, execute the body. int z = 8 ; y = p(z) ; after the call, y and z will both have value 9. Call-by-reference is explicit in C, whereas implicit in C++; for the above program, in C, one has to write it as int p (int *x) { *x = *x + 1 ; return *x ; } ... int z ; y = p (&z) ; Call-by-value-result: works like call by value bu in addition, formal parameters are assigned to actual parameters at the end of procedure with call-by-value-result (which C doesn't support - hence the following is pseudo-code), void p (int x, int y) { x = x + 1 ; y = y + 1 ; } ... int a = 3 ; p (a, a) ; after the call, a will have the value 4, whereas with cally-by-reference, a will have the value 5. the following is the equivalent of call-by-value-result call above: x = a ; y = a ; x = a ; x = x + 1 ; y = y + 1 ; a = x ; a = y ; thus, at the end, a = 4.