0% found this document useful (0 votes)
27 views33 pages

A3 Control Flow

The document discusses various concepts related to control flow in programming languages including sequencing, selection, iteration, and expressions. Sequencing refers to the implicit top-to-bottom ordering of statements. Selection allows choosing among two or more statements based on a condition. Iteration allows repeating a program fragment. Expressions produce values.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
27 views33 pages

A3 Control Flow

The document discusses various concepts related to control flow in programming languages including sequencing, selection, iteration, and expressions. Sequencing refers to the implicit top-to-bottom ordering of statements. Selection allows choosing among two or more statements based on a condition. Iteration allows repeating a program fragment. Expressions produce values.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 33

Control Flow

Ordering of what should be done in program execution


• Sequencing: implicit ordering from top to bottom
• Selection: choice is made among two or more statements
• Iteration: program fragment executed repeatedly
• Procedural abstraction: collection of control constructs encapsulated in a single
unit
• Recursion: self-referential subroutines

2110316 PROG LANG PRIN: CONTROL FLOW 1


Expression
Expression produces a value, i.e. literal constant, named variable, constant, or
operator (or function) applied to operands (or arguments)

A language may specify the location of function name.


• Prefix: before arguments, e.g. (*(+ 1 3) 2) in Lisp
• Infix: among arguments, e.g. 1+3 in most imperative languages
• Postfix: after arguments, e.g. post-increment/decrement (++ and--) in C and its
descendants

Most imperative languages use infix notation for binary operators, and prefix notation
for many operators and other functions.

2110316 PROG LANG PRIN: CONTROL FLOW 2


Precedence and Associativity
When operators are written in infix notation without parentheses, ambiguity arises as to what is an
operand of what, e.g.
a+b*c**d**e/f should be evaluated as
((((a+b)*c)**d)**e)/f or
a+(((b*c)**d)**(e/f)) or
a+((b*(c**(d**e)))/f) ?

Precedence says that certain operators, in the absence of parentheses, group more tightly than other
operators, e.g.
a-b*c is a-(b*c)

Associativity says sequences of operators of equal precedence, in the absence of parentheses, group
to the left or to the right, e.g.
a-b+c is (a-b)+c
2110316 PROG LANG PRIN: CONTROL FLOW 3
Precedence

Operators at the top group


most tightly.

In most languages ,
multiplication and division
group more tightly than
addition and subtraction.

2110316 PROG LANG PRIN: CONTROL FLOW 4


Associativity
Basic arithmetic operators almost always associate left-to-right.
9-3-2 is 4, not 8 because (9-3)-2

Exponentiation usually associates right-to-left.


4**3**2 is 4**(3**2)

Assignment associates right-to-left.


a = b = a+c is (a+c) assigned to b, then the same value assigned to a

2110316 PROG LANG PRIN: CONTROL FLOW 5


Exercise: Precedence and Associativity
Given the precedence table and associativity rules in the previous slides,
• Apply parentheses to the expression to show how operands are grouped to
operators and
• Give the result of the expression
• Where a = 1, b = 2, c = 3, d = 2, e = 2, f = 3

Fortrana + b * c ** d ** e / f result is

Pascal a < b and c < d result is

C a < b && c < d result is

2110316 PROG LANG PRIN: CONTROL FLOW 6


Evaluation Order within Expression (1)
Precedence and associativity do not specify the order in which the operands of a given
operator are evaluated, e.g.
Precedence and associativity say a - f(b) - c * d is (a - f(b)) - (c * d)
Which one is evaluated first, (a - f(b)) or (c * d) ?

Similarly, in f(a, g(b), h(c)) , what is the order in which the arguments will be evaluated?

But evaluation order is important.


• Impact on expression result via side effect
 What if f(b) modifies c and/or d?
 What if g(b) modifies a and/or c?
• Impact on code improvement
 In a*b + f(c), for example, it might be desirable to call f first, because the product a*b stored in a register
would need to be saved (on stack) during the call to f (i.e. run time cost) as f might want to use all
registers.

2110316 PROG LANG PRIN: CONTROL FLOW 7


Evaluation Order within Expression (2)
As for code improvement, most languages then leave the order of evaluation
undefined, i.e. compiler can choose whatever order that results in faster code.

Be careful when writing expression in which side effect of evaluating one operand or
argument can affect the value of another, e.g. use parentheses to impose ordering.

But Java and C# require left-to-right evaluation (i.e. cleaner semantics over run time
cost).

2110316 PROG LANG PRIN: CONTROL FLOW 8


Exercise: Precedence, Associativity, Evaluation Order
Given the precedence table and associativity rules in the previous slides, and
evaluation order within expression is left to right, what is the result of this C program?

int give2() { printf("two\n"); return 2; }


int give3() { printf("three\n"); return 3; }
int give4() { printf("four\n"); return 4; }

int main() {
printf("%d\n", give4() + give2() * give3() - give4() / give2());
return 0;
}
2110316 PROG LANG PRIN: CONTROL FLOW 9
Assignment
In imperative language, assignment provides the means to make the changes to the
values of variable in memory.
Assignment takes two arguments.
• A value
• A reference to a variable into which the value should be placed.
Assignment has a side effect, i.e. it changes the value of a variable, thereby affecting
the result of any later computation in which the variable appears.
//C --Haskell has no assignment and no side effect
int max(int x, int y) { a, b :: Int
if (x > y) {return x;} else {return y;} a = 1
} b = 2
int main() max a b
{ int a, b; --2
a = 1; b = 2; max a b
printf("max is %d\n", max(a, b)); //max is 2 --2
a = 3;
printf("max is %d\n", max(a, b)); //max is 3
return 0;
}
10
Semantics of Assignment (1)
In value model of variables, a variable is a named container for a value (e.g. Pascal,
C, Java’s built-in type, PHP).
A variable has two interpretations when used with assignment.
• l-value refers to expression that denotes location.
• r-value refers to expression that denotes value.
//C
b = 2; // l-value of b is used
c = b; // r-value of b is used, l-value of c is used
a = b+c; // r-values of b and c are used, l-value of a is used

2110316 PROG LANG PRIN: CONTROL FLOW 11


Semantics of Assignment (2)
In reference model of variables, a variable is a named reference to a value (e.g. Clu,
Lisp, Haskell, Smalltalk, Java’s user-defined type (class), Python, Ruby).
• Every variable is an l-value.
• When a variable appears where an r-value is expected, it must be dereferenced to
obtain the value to which it refers (automatic in most languages).
%Clu
b := 2; % l-value of b is used
c := b; % l-value of b is dereferenced, l-value of c is used
a := b+c; % l-values of b and c are dereferenced, l-value of a is used
% 2 and 4 are immutable values at some locations to which any variables can refer

2110316 PROG LANG PRIN: CONTROL FLOW 12


Short-Circuit Evaluation
Consider these logical expressions,
(a < b) and (b < c)
(a > b) or (b > c)
When the overall value of these expressions can be determined from the first half of
the computation, compiler will generate code that skips the second half.
This saves time.

13
https://www.quora.com/How-can-I-implement-short-circuit-evaluation-and-operators-for-a-JVM-based-language-compiler-
2110316 PROG LANG PRIN: CONTROL FLOW
Short-Circuit Changes Semantics of Boolean Expressions
An example of a search for an element in a list.
my_list
key next key next

p
C short-circuits its logical operators.
//C
p = my_list;
while (p && p->key != val)
p = p->next;

Pascal does not short-circuit. Both <> will be evaluated before and, so run-time
semantic error if p is nil (unsuccessful search).
(* Pascal *)
p := my_list;
while (p <> nil) and (p^.key <> val) do (*ouch!*)
p := p^.next;

2110316 PROG LANG PRIN: CONTROL FLOW 14


Exercise: Short-Circuit
How can we use short-circuit evaluation to make the following code safer?

const int MAX = 10;


int A[MAX];

if (A[i] > foo) …

if (n/d < threshold) …

2110316 PROG LANG PRIN: CONTROL FLOW 15


Sequencing
It is the principal means of controlling the order in which side effects occur.
When one statement follows another, the first statement executes before the second.
Sequence of statements can be enclosed as a compound statement (block), e.g.
begin…end or {…}.

2110316 PROG LANG PRIN: CONTROL FLOW 16


Selection
Most languages employ variant of if ... then … else ...

if condition then statement


else if condition then statement
else if condition then statement

else statement

2110316 PROG LANG PRIN: CONTROL FLOW 17


Short-Circuited Condition in Selection
In languages with short-circuit, compilers generate target code which evaluates the
conditions for branching control to various locations without having to store any
boolean values.
if ((A > B) and (C > D)) or (E ≠ F) then r1 := A
then_clause r2 := B
else if r1 <= r2 goto L4
else_clause r1 := C
r2 := D
if r1 > r2 goto L1
L4: r1 := E
r2 := F
if r1 = r2 goto L2
L1: then_clause
goto L3
L2: else_clause
L3:

2110316 PROG LANG PRIN: CONTROL FLOW 18


Nested If
Compilers generate target code which tests each expression sequentially.
--Ada

i := … -- calculate tested expression
if i = 1 then
clause_A
elsif i = 2 or i = 7 then ≠
clause_B
elsif i in 3..5 then
clause_C
elsif i = 10 then
clause_D
else
clause_E
end if; ≠

2110316 PROG LANG PRIN: CONTROL FLOW 19


Case/Switch Statements
Less verbose syntactically than nested if but the principal motivation is to facilitate
the generation of efficient target code. -- General form
--Ada with case labels and arms goto L6 --jump to code to compute address
L1: clause_A
case … --calculate tested expression goto L7
is L2: clause_B
when 1 => clause_A goto L7
when 2 | 7 => clause_B L3: clause_C
when 3..5 => clause_C goto L7
when 10 => clause_D ...
when others => clause_E L4: clause_D
end case; goto L7
L5: clause_E
goto L7

L6: r1 := ... --computed target of branch


goto *r1
L7:
2110316 PROG LANG PRIN: CONTROL FLOW 20
Case/Switch Implementation Example
Code at label T is an array of addresses (called jump table). Each entry is for each value from
the lowest to the highest value of the case labels.
L6 checks boundary and fetches corresponding entry from the table and branches to it. So
finding the correct arm is in constant time.
Address at label L1

< min
> max
r1 := T[r1]
goto *r1
content of r1 21
Exercise: Case/Switch Implementation
What is the problem with jump table implementation in the previous slide?

What do you think a compiler should do about it?

2110316 PROG LANG PRIN: CONTROL FLOW 22


Switch Statement with Fall-Through
Found in C and retained in C++, Java.
• Each possible value for tested expression must have its own label.
• A label with empty arm falls through into the code of subsequent label.
• To get out of a switch, a break statement must be used at the end of an arm, rather
than falling through into the next. switch (… /*tested expression */) {
case 1: clause_A;
break;
case 2:
case 7: clause_B;
break;
case 3:
case 4:
case 5: clause_C;
break;
case 10: clause_D;
break;
default: clause_E;
break; }
2110316 PROG LANG PRIN: CONTROL FLOW 23
Iteration
In most languages, iteration takes the form of loops.
An enumeration controlled loop executes over values in a given finite set.
A logically controlled loop executes until some boolean condition changes value.
An iterator iterates over elements of any well-defined set (collection).

2110316 PROG LANG PRIN: CONTROL FLOW 24


Enumeration-Controlled Loop
Test for empty bounds first, i.e. test terminating condition before the first iteration.
(* Modula-2: enumeration-controlled *)
FOR i := first TO last BY step DO

END
/* C: combination of enumeration- and logically-controlled */
for (i = first; i <= last; i += step) {

}

2110316 PROG LANG PRIN: CONTROL FLOW 25


Logically Controlled Loop
Pre-test loop: Loop body may not be executed
while condition do statement

Post-test loop: Loop body is executed at least once.


//C
do {
line = read_line(stdin);
} while line[0] != ‘$’;

Mid-test loop: A special statement is nested inside a test for terminating condition.
//C
for (;;) {
line = read_line(stdin);
if (all_blanks(line)) break;
consume_line(line);
}

2110316 PROG LANG PRIN: CONTROL FLOW 26


Iterator (1)
True iterator (e.g. Clu, Python, Ruby, C#)
• Any container abstraction provides an iterator that enumerates its items.
#Python
#Iterator goes unseen as it is implicitly used
for i in [1, 2, 3]:
print(i)
...
1
2
3

#range(first, last, step) is a built-in iterator.


#It yields integers in the range in increments of step, but not including last.
#It is a function but, when called each time, continues where it last left off, giving next integer.

my_list = [‘one’, ‘two’, ‘three’, ‘four’, ‘five’]


my_list_len = len(my_list)
for i in range(0, my_list_len, 2):
print(my_list[i])
...
one
three
five
27
Iterator (2)
Iterator as an ordinary object (e.g. C++, Java, Ada, Python).
• Provides methods for initialization, generation of the next index value, and testing
for completion. //Java
ArrayList al = new ArrayList();
//add elements to the array list
al.add("C");
al.add("A");
al.add("E");

//use iterator to display contents of al


System.out.print(“Contents of al: ”);
Iterator itr = al.iterator();

while(itr.hasNext()) {
Object element = itr.next();
System.out.print(element + “ ”);
}

Contents of al: C A E
2110316 PROG LANG PRIN: CONTROL FLOW 28
Recursion
Functions calling themselves.
Functions calling other functions that call them back in turn.
Any iterative algorithm can be rewritten as a recursive algorithm and vice versa.
Which to use in which circumstance is mainly a matter of taste.

2110316 PROG LANG PRIN: CONTROL FLOW 29


Recursion and Iteration
a if a=b
gcd(a, b) gcd(a-b, b) if a>b
positive integers, a, b gcd(a, b-a) if b>a

//C //C
//Iteration, assume a, b > 0 //Recursion, assume a, b > 0
int gcd(int a, int b) { int gcd(int a, int b) {
while (a != b) { if (a == b) return a; //base case
if (a > b) a = a-b; else if (a > b) return gcd (a-b, b);
else b = b-a; else return gcd(a, b-a);
} }
return a;
}

2110316 PROG LANG PRIN: CONTROL FLOW 30


Tail recursion Return 0
No tail
n =0
Return
1+m1(0)
n =1
Return
1+m1(1)
n =2
2110316 PROG LANG PRIN: CONTROL FLOW 31
Return 2
n = 0, x =2
Return m1(0,2)
n =1, x = 1
No intermediate value Return m1(1,1)
n =2, x = 0
2110316 PROG LANG PRIN: CONTROL FLOW 32
Loop version

2110316 PROG LANG PRIN: CONTROL FLOW 33

You might also like