CSCI 3136 Principles of Programming Languages Control Flow - 2 - - PowerPoint PPT Presentation

csci 3136 principles of programming languages
SMART_READER_LITE
LIVE PREVIEW

CSCI 3136 Principles of Programming Languages Control Flow - 2 - - PowerPoint PPT Presentation

CSCI 3136 Principles of Programming Languages Control Flow - 2 Summer 2013 Faculty of Computer Science Dalhousie University 1 / 40 Short-Circuit Evaluation of Boolean Expressions (and a b) : If a is false, b has no effect on the value of


slide-1
SLIDE 1

CSCI 3136 Principles of Programming Languages

Control Flow - 2

Summer 2013 Faculty of Computer Science Dalhousie University

1 / 40

slide-2
SLIDE 2

Short-Circuit Evaluation of Boolean Expressions

  • (and a b): If a is false, b has no effect on the value of the whole

expression.

  • (or a b): If a is true, b has no effect on the value of the whole

expression.

2 / 40

slide-3
SLIDE 3

Short-Circuit Evaluation of Boolean Expressions

  • (and a b): If a is false, b has no effect on the value of the whole

expression.

  • (or a b): If a is true, b has no effect on the value of the whole

expression. Short-circuit evaluation

  • If the value of the expression does not depend on b, the evaluation
  • f b is skipped.

This is a useful optimization. If the evaluation of b has side-effects, however, the meaning of the code may be changed.

3 / 40

slide-4
SLIDE 4

Short-Circuit Evaluation of Boolean Expressions

  • (and a b): If a is false, b has no effect on the value of the whole

expression.

  • (or a b): If a is true, b has no effect on the value of the whole

expression. Short-circuit evaluation

  • If the value of the expression does not depend on b, the evaluation
  • f b is skipped.

This is a useful optimization. If the evaluation of b has side-effects, however, the meaning of the code may be changed. Some languages provide both regular and short-circuit versions of Boolean operators. Ada

  • and vs and then
  • or vs or else

4 / 40

slide-5
SLIDE 5

Short-Circuit Evaluation: Examples

  • C: (C short-circuits && and || operators)

while( p != NULL && p->e != val ) p = p->next;

5 / 40

slide-6
SLIDE 6

Short-Circuit Evaluation: Examples

  • C: (C short-circuits && and || operators)

while( p != NULL && p->e != val ) p = p->next;

  • Pascal:(Pascal does not short-circuit and and or operators )

p := my list; while (p <> nil) and (p^ .key <> val) do p := p^ .next;

6 / 40

slide-7
SLIDE 7

Short-Circuit Evaluation: Examples

  • C: (C short-circuits && and || operators)

while( p != NULL && p->e != val ) p = p->next;

  • Pascal:(Pascal does not short-circuit and and or operators )

p := my list; while (p <> nil) and (p^ .key <> val) do p := p^ .next;

  • Perl:
  • pen( F, "file" ) or die;

7 / 40

slide-8
SLIDE 8

Short-Circuit Evaluation: Examples

  • C: (C short-circuits && and || operators)

while( p != NULL && p->e != val ) p = p->next;

  • Pascal:(Pascal does not short-circuit and and or operators )

p := my list; while (p <> nil) and (p^ .key <> val) do p := p^ .next;

  • Perl:
  • pen( F, "file" ) or die;
  • Replacing if in Perl or shell scripts:

if( x > max ) then max = x; becomes ( x > max ) and max = x;

8 / 40

slide-9
SLIDE 9

Sequencing

In imperative programming languages, sequencing comes naturally, without a need for special syntax to support it. Mixed imperative/functional languages (LISP, Scheme, ...) often provide special constructs for sequencing. Issue: What’s the value of a sequence of expressions/statements?

  • The value of the last subexpression (most common)

C: a = 4, b = 5 LISP: (progn (setq a 4) (setq b 5))

  • The value of the first subexpression

LISP: (prog1 (setq a 4) (setq b 5))

  • The value of the second subexpression (supported in LISP)

LISP: (prog2 (setq a 4) (setq b 5) (setq c 6))

9 / 40

slide-10
SLIDE 10

Sequencing

In imperative programming languages, sequencing comes naturally, without a need for special syntax to support it. Mixed imperative/functional languages (LISP, Scheme, ...) often provide special constructs for sequencing. Issue: What’s the value of a sequence of expressions/statements?

  • The value of the last subexpression (most common)

C: a = 4, b = 5 = ⇒ 5 LISP: (progn (setq a 4) (setq b 5))

  • The value of the first subexpression

LISP: (prog1 (setq a 4) (setq b 5))

  • The value of the second subexpression (supported in LISP)

LISP: (prog2 (setq a 4) (setq b 5) (setq c 6))

10 / 40

slide-11
SLIDE 11

Sequencing

In imperative programming languages, sequencing comes naturally, without a need for special syntax to support it. Mixed imperative/functional languages (LISP, Scheme, ...) often provide special constructs for sequencing. Issue: What’s the value of a sequence of expressions/statements?

  • The value of the last subexpression (most common)

C: a = 4, b = 5 = ⇒ 5 LISP: (progn (setq a 4) (setq b 5)) = ⇒ 5

  • The value of the first subexpression

LISP: (prog1 (setq a 4) (setq b 5))

  • The value of the second subexpression (supported in LISP)

LISP: (prog2 (setq a 4) (setq b 5) (setq c 6))

11 / 40

slide-12
SLIDE 12

Sequencing

In imperative programming languages, sequencing comes naturally, without a need for special syntax to support it. Mixed imperative/functional languages (LISP, Scheme, ...) often provide special constructs for sequencing. Issue: What’s the value of a sequence of expressions/statements?

  • The value of the last subexpression (most common)

C: a = 4, b = 5 = ⇒ 5 LISP: (progn (setq a 4) (setq b 5)) = ⇒ 5

  • The value of the first subexpression

LISP: (prog1 (setq a 4) (setq b 5)) = ⇒ 4

  • The value of the second subexpression (supported in LISP)

LISP: (prog2 (setq a 4) (setq b 5) (setq c 6))

12 / 40

slide-13
SLIDE 13

Sequencing

In imperative programming languages, sequencing comes naturally, without a need for special syntax to support it. Mixed imperative/functional languages (LISP, Scheme, ...) often provide special constructs for sequencing. Issue: What’s the value of a sequence of expressions/statements?

  • The value of the last subexpression (most common)

C: a = 4, b = 5 = ⇒ 5 LISP: (progn (setq a 4) (setq b 5)) = ⇒ 5

  • The value of the first subexpression

LISP: (prog1 (setq a 4) (setq b 5)) = ⇒ 4

  • The value of the second subexpression (supported in LISP)

LISP: (prog2 (setq a 4) (setq b 5) (setq c 6)) = ⇒ 5

13 / 40

slide-14
SLIDE 14

Goto and Alternatives

Use of goto is bad programming practice if the same effect can be achieved using different constructs. Sometimes, however, it is unavoidable:

  • Break out of a loop
  • Break out of a subroutine
  • Break out of a deeply nested context

Many languages provide alternatives:

  • One-and-a-half loop
  • return statement
  • Structured exception handling

14 / 40

slide-15
SLIDE 15

Selection (Alternation)

  • Standard if-then-else statement

if ... then ... else ...

  • Multi-way if-then-else statement

if ... then ... elsif ... then ... elsif ... then ... ... else ...

  • Switch statement

switch ... of case ...: ... case ...: ... ...

15 / 40

slide-16
SLIDE 16

Switch Statements

Switch statements are a special case of if/then/elsif/else. Principal motivation: Generate more efficient code. Compiler can use different methods to generate efficient code:

  • Sequential testing
  • Binary search
  • Hash table
  • Jump table

16 / 40

slide-17
SLIDE 17

Implementation of Switch Statements (1)

i := ... (* expression *) IF i = 1 THEN clause A ELSIF i IN 2, 7 THEN clause B ELSIF i IN 3..5 THEN clause C ELSIF i = 10 THEN clause D ELSE clause E END —————————— CASE i OF 1: clause A | 2, 7: clause B | 3..5: clause C | 10: clause D ELSE clause E END r1:= ...

  • - expression

if r1 = 1 goto L1 clause A goto L6 L1: if r1 = 2 goto L2 if r1 = 7 goto L3 L2: clause B goto L6 L3: if r1 < 3 goto L4 if r1 > 5 goto L4 clause C goto L6 L4: if r1 = 10 goto L5 clause D goto L6 L5: clause E L6: ...

17 / 40

slide-18
SLIDE 18

Implementation of Switch Statements (1)

i := ... (* expression *) IF i = 1 THEN clause A ELSIF i IN 2, 7 THEN clause B ELSIF i IN 3..5 THEN clause C ELSIF i = 10 THEN clause D ELSE clause E END —————————— CASE i OF 1: clause A | 2, 7: clause B | 3..5: clause C | 10: clause D ELSE clause E END r1:= ...

  • - expression

if r1 = 1 goto L1 clause A goto L6 L1: if r1 = 2 goto L2 if r1 = 7 goto L3 L2: clause B goto L6 L3: if r1 < 3 goto L4 if r1 > 5 goto L4 clause C goto L6 L4: if r1 = 10 goto L5 clause D goto L6 L5: clause E L6: ...

18 / 40

slide-19
SLIDE 19

Implementation of Switch Statements (2)

i := ... (* expression *) IF i = 1 THEN clause A ELSIF i IN 2, 7 THEN clause B ELSIF i IN 3..5 THEN clause C ELSIF i = 10 THEN clause D ELSE clause E END —————————— CASE i OF 1: clause A | 2, 7: clause B | 3..5: clause C | 10: clause D ELSE clause E END Jump table T: &L1 &L2 &L3 &L3 &L3 &L5 &L2 &L5 &L5 &L4 L6: r1:= ...--expression if r1 < 1 goto L5 if r1 > 10 goto L5 r1 := r1 -1 r2 := T[r1] goto *r2 L1: clause A goto L7 L2: clause B goto L7 L3: clause C goto L7 L4: clause D goto L7 L5: clause E goto L7 L7: ...

19 / 40

slide-20
SLIDE 20

Implementation of Switch Statements (2)

i := ... (* expression *) IF i = 1 THEN clause A ELSIF i IN 2, 7 THEN clause B ELSIF i IN 3..5 THEN clause C ELSIF i = 10 THEN clause D ELSE clause E END —————————— CASE i OF 1: clause A | 2, 7: clause B | 3..5: clause C | 10: clause D ELSE clause E END Jump table T: &L1 &L2 &L3 &L3 &L3 &L5 &L2 &L5 &L5 &L4 L6: r1:= ...--expression if r1 < 1 goto L5 if r1 > 10 goto L5 r1 := r1 -1 r2 := T[r1] goto *r2 L1: clause A goto L7 L2: clause B goto L7 L3: clause C goto L7 L4: clause D goto L7 L5: clause E goto L7 L7: ...

20 / 40

slide-21
SLIDE 21

Implementation of Switch Statements (3)

Jump table + Fast: one table lookup to find the right branch − Potentially large table: one entry per possible value Linear search − Potentially slow + No storage overhead Hash table + Fast: one hash table access to find the right branch − More complicated − Elements in a range need to be stored individually ⇒ again, possibly large table Binary search ± Fast (but slower than table lookup) + No storage overhead No single implementation is best in all circumstances. Compilers often use different strategies based on the specific code.

21 / 40

slide-22
SLIDE 22

Iteration

Enumeration-controlled loops

  • Example: for-loop
  • One iteration per element in a finite set.
  • The number of iterations is known in advance.

Logically controlled loops

  • Example: while and repeat loops
  • Executed until a Boolean condition changes.
  • The number of iterations is not known in advance.

22 / 40

slide-23
SLIDE 23

Iteration

Enumeration-controlled loops

  • Example: for-loop
  • One iteration per element in a finite set.
  • The number of iterations is known in advance.

Logically controlled loops

  • Example: while and repeat loops
  • Executed until a Boolean condition changes.
  • The number of iterations is not known in advance.

Some languages do not have loop constructs (e.g., Scheme). They use tail recursion instead.

23 / 40

slide-24
SLIDE 24

Logically Controlled Loops

  • Pre-loop test

while ... do ...

  • Post-loop test

repeat ... until ... do ... while ...

  • Mid-loop test or ”one-and-a-half loop”

loop ... when ... exit ... when ... exit ... end

24 / 40

slide-25
SLIDE 25

Logically Controlled Loops

  • Pre-loop test

while ... do ...

  • Post-loop test

repeat ... until ... do ... while ... Loop is executed at least once.

  • Mid-loop test or ”one-and-a-half loop”

loop ... when ... exit ... when ... exit ... end

25 / 40

slide-26
SLIDE 26

Implementation of Iterations (1)

WHILE cond do statements END ——————————— L1: r1 = evaluate cond if not r1 goto L2 statements goto L1 L2: ...

26 / 40

slide-27
SLIDE 27

Implementation of Iterations (1)

WHILE cond do statements END ——————————— L1: r1 = evaluate cond if not r1 goto L2 statements goto L1 L2: ... for( init; cond; step ) { statements } ———————————

27 / 40

slide-28
SLIDE 28

Implementation of Iterations (1)

WHILE cond do statements END ——————————— L1: r1 = evaluate cond if not r1 goto L2 statements goto L1 L2: ... for( init; cond; step ) { statements } ——————————— init L1: r1 = evaluate cond if not r1 goto L2 statements step goto L1 L2: ...

28 / 40

slide-29
SLIDE 29

Implementation of Iterations (2)

Potentially much more efficient:

FOR i = start TO end BY step DO statements END

If modifying the loop variable inside the loop is allowed:

——————————— r1 := start r2 := end r3 := step L1: if r1 > r2 goto L2 statements r1 := r1 + r3 goto L1 L2: ...

If modifying the loop variable inside the loop is not allowed:

——————————— r1 := [(end - start)/step]+1 L1: if not r1 goto L2 statements decrement r1 goto L1 L2: ...

29 / 40

slide-30
SLIDE 30

Break and Continue

”Break” statement (”last” in Perl)

  • Exits the nearest enclosing for, do, while or switch statement.

”Continue” statement (”next” in Perl)

  • Skips the rest of the current iteration.

The loop may have a finally part, which is always executed no matter whether the iteration is executed normally or terminated using a continue or break statement.

30 / 40

slide-31
SLIDE 31

Recursion

  • Recursion replaces iteration in functional programming paradigm.

31 / 40

slide-32
SLIDE 32

Recursion

  • Recursion replaces iteration in functional programming paradigm.
  • For example:

while( condition ) { S1; S2; ... }

32 / 40

slide-33
SLIDE 33

Recursion

  • Recursion replaces iteration in functional programming paradigm.
  • For example:

while( condition ) { S1; S2; ... }

  • We can use:

procedure P() { if( condition ) { S1; S2; ...; P(); } } Iteration is a strictly imperative feature: it relies on updating the iterator variable.

33 / 40

slide-34
SLIDE 34

Implementation of Recursion

  • A naive implementation of recursion is often less efficient than a

naive implementation of iteration.

34 / 40

slide-35
SLIDE 35

Implementation of Recursion

  • A naive implementation of recursion is often less efficient than a

naive implementation of iteration.

  • An optimizing compiler often converts recursion into iteration when

possible:

− Tail recursion: There is no work to be done after the recursive call. − More general recursion: Work to be done after the recursive call may be passed to the recursive call as a continuation.

35 / 40

slide-36
SLIDE 36

Tail-recursion

  • There is no work to be done after the recursive call.
  • Tail-recursive calls are often optimized into an iterative form,

especially in functional languages.

  • An optimized tail-recursive call does not allocate additional stack

space and does not have function call overhead.

36 / 40

slide-37
SLIDE 37

Tail-recursion (Example in C)

  • Consider this recursive definition of the factorial function in C:

factorial(n) { if (n == 0) return 1; return n * factorial(n - 1); }

37 / 40

slide-38
SLIDE 38

Tail-recursion (Example in C)

  • Consider this recursive definition of the factorial function in C:

factorial(n) { if (n == 0) return 1; return n * factorial(n - 1); }

  • tail-recursive version:

factorial1(n, accumulator) { if (n == 0) return accumulator; return factorial1(n - 1, n * accumulator); } factorial(n) { return factorial1(n, 1); }

38 / 40

slide-39
SLIDE 39

Tail-recursion (Example in Scheme)

  • Consider this Scheme function to sum the elements of a list:

(define (sum lis) (if (null? lis) (+ (car lis) (sum (cdr lis)))))

39 / 40

slide-40
SLIDE 40

Tail-recursion (Example in Scheme)

  • Consider this Scheme function to sum the elements of a list:

(define (sum lis) (if (null? lis) (+ (car lis) (sum (cdr lis)))))

  • tail-recursive version:

(define (sum lis) (letrec ((helper (lambda (s lis) (if (null? lis) s (helper (+ s (car lis)) (cdr lis)))))) (helper 0 lis)))

40 / 40