SUBROUTINES AND CONTROL ABSTRACTION PRINCIPLES OF PROGRAMMING - - PowerPoint PPT Presentation

subroutines and control abstraction
SMART_READER_LITE
LIVE PREVIEW

SUBROUTINES AND CONTROL ABSTRACTION PRINCIPLES OF PROGRAMMING - - PowerPoint PPT Presentation

SUBROUTINES AND CONTROL ABSTRACTION PRINCIPLES OF PROGRAMMING LANGUAGES Norbert Zeh Winter 2018 Dalhousie University 1/47 ABSTRACTIONS AS PROGRAM BUILDING BLOCKS Programming is about building abstractions. Subroutines are the main method to


slide-1
SLIDE 1

SUBROUTINES AND CONTROL ABSTRACTION

PRINCIPLES OF PROGRAMMING LANGUAGES

Norbert Zeh Winter 2018

Dalhousie University 1/47

slide-2
SLIDE 2

ABSTRACTIONS AS PROGRAM BUILDING BLOCKS

Programming is about building abstractions. Subroutines are the main method to build control abstractions. The other form of abstraction we normally think about is data abstraction (next topic).

2/47

slide-3
SLIDE 3

ROAD MAP

  • Functions, procedures, and parameters
  • Inline expansion
  • Parameter passing modes
  • Passing functions as arguments
  • Default and named parameters
  • Variadic subroutines
  • Generic subroutines
  • Exception handling
  • Continuations
  • Coroutines

3/47

slide-4
SLIDE 4

ROAD MAP

  • Functions, procedures, and parameters
  • Inline expansion
  • Parameter passing modes
  • Passing functions as arguments
  • Default and named parameters
  • Variadic subroutines
  • Generic subroutines
  • Exception handling
  • Continuations
  • Coroutines

3/47

slide-5
SLIDE 5

BASIC DEFINITIONS

Subroutine

  • Function if it returns a value
  • Procedure if it does not and thus is called for its side effects

Formal parameters of a subroutine The parameter names that appear in the subroutine declaration Actual parameters or arguments of a subroutine The values bound to the formal parameters when the subroutine is called We already discussed activation records or (stack) frames as a means to manage the space for local variables allocated to each subroutine call.

4/47

slide-6
SLIDE 6

BASIC DEFINITIONS

Subroutine

  • Function if it returns a value
  • Procedure if it does not and thus is called for its side effects

Formal parameters of a subroutine The parameter names that appear in the subroutine declaration Actual parameters or arguments of a subroutine The values bound to the formal parameters when the subroutine is called We already discussed activation records or (stack) frames as a means to manage the space for local variables allocated to each subroutine call.

4/47

slide-7
SLIDE 7

BASIC DEFINITIONS

Subroutine

  • Function if it returns a value
  • Procedure if it does not and thus is called for its side effects

Formal parameters of a subroutine The parameter names that appear in the subroutine declaration Actual parameters or arguments of a subroutine The values bound to the formal parameters when the subroutine is called We already discussed activation records or (stack) frames as a means to manage the space for local variables allocated to each subroutine call.

4/47

slide-8
SLIDE 8

BASIC DEFINITIONS

Subroutine

  • Function if it returns a value
  • Procedure if it does not and thus is called for its side effects

Formal parameters of a subroutine The parameter names that appear in the subroutine declaration Actual parameters or arguments of a subroutine The values bound to the formal parameters when the subroutine is called We already discussed activation records or (stack) frames as a means to manage the space for local variables allocated to each subroutine call.

4/47

slide-9
SLIDE 9

STATIC CHAINS AND DYNAMIC CHAINS

Source code Call C D Call D C B E Call B Call E A Program execution Enter A Call E Enter E Call B Enter B Call D Enter D Call C Enter C Execution stack A E B D C

Dynamic chain Static chain

5/47

slide-10
SLIDE 10

ROAD MAP

  • Functions, procedures, and parameters
  • Inline expansion
  • Parameter passing modes
  • Passing functions as arguments
  • Default and named parameters
  • Variadic subroutines
  • Generic subroutines
  • Exception handling
  • Continuations
  • Coroutines

6/47

slide-11
SLIDE 11

ROAD MAP

  • Functions, procedures, and parameters
  • Inline expansion
  • Parameter passing modes
  • Passing functions as arguments
  • Default and named parameters
  • Variadic subroutines
  • Generic subroutines
  • Exception handling
  • Continuations
  • Coroutines

6/47

slide-12
SLIDE 12

INLINE EXPANSION

Inline expansion During compile time, the compiler replaces a subroutine call with the code of the subroutine. Advantages:

  • Avoids overhead associated with subroutine calls; faster code.
  • Encourages building abstractions in the form of many small subroutines.
  • Related to but cleaner than macros.

Disadvantages:

  • Code bloating
  • Cannot be used for recursive subroutines.
  • Code profiling becomes more difficult.

7/47

slide-13
SLIDE 13

INLINE EXPANSION

Inline expansion During compile time, the compiler replaces a subroutine call with the code of the subroutine. Advantages:

  • Avoids overhead associated with subroutine calls; faster code.
  • Encourages building abstractions in the form of many small subroutines.
  • Related to but cleaner than macros.

Disadvantages:

  • Code bloating
  • Cannot be used for recursive subroutines.
  • Code profiling becomes more difficult.

7/47

slide-14
SLIDE 14

INLINE EXPANSION

Inline expansion During compile time, the compiler replaces a subroutine call with the code of the subroutine. Advantages:

  • Avoids overhead associated with subroutine calls; faster code.
  • Encourages building abstractions in the form of many small subroutines.
  • Related to but cleaner than macros.

Disadvantages:

  • Code bloating
  • Cannot be used for recursive subroutines.
  • Code profiling becomes more difficult.

7/47

slide-15
SLIDE 15

ROAD MAP

  • Functions, procedures, and parameters
  • Inline expansion
  • Parameter passing modes
  • Passing functions as arguments
  • Default and named parameters
  • Variadic subroutines
  • Generic subroutines
  • Exception handling
  • Continuations
  • Coroutines

8/47

slide-16
SLIDE 16

ROAD MAP

  • Functions, procedures, and parameters
  • Inline expansion
  • Parameter passing modes
  • Passing functions as arguments
  • Default and named parameters
  • Variadic subroutines
  • Generic subroutines
  • Exception handling
  • Continuations
  • Coroutines

8/47

slide-17
SLIDE 17

PARAMETER PASSING

Notation: f(a, b, c) C, C++, Java, … (f a b c) Lisp, Scheme a f: b fcont: c Smalltalk, Objective C f a b c Haskell, shell scripts Meaning: Execute the named subroutine with its formal arguments bound to the provided actual arguments. How exactly? Parameter passing modes

  • By value
  • By reference, by sharing
  • By value/return

9/47

slide-18
SLIDE 18

PARAMETER PASSING

Notation: f(a, b, c) C, C++, Java, … (f a b c) Lisp, Scheme a f: b fcont: c Smalltalk, Objective C f a b c Haskell, shell scripts Meaning: Execute the named subroutine with its formal arguments bound to the provided actual arguments. How exactly? Parameter passing modes

  • By value
  • By reference, by sharing
  • By value/return

9/47

slide-19
SLIDE 19

PARAMETER PASSING

Notation: f(a, b, c) C, C++, Java, … (f a b c) Lisp, Scheme a f: b fcont: c Smalltalk, Objective C f a b c Haskell, shell scripts Meaning: Execute the named subroutine with its formal arguments bound to the provided actual arguments. How exactly? Parameter passing modes

  • By value
  • By reference, by sharing
  • By value/return

9/47

slide-20
SLIDE 20

PARAMETER PASSING

Notation: f(a, b, c) C, C++, Java, … (f a b c) Lisp, Scheme a f: b fcont: c Smalltalk, Objective C f a b c Haskell, shell scripts Meaning: Execute the named subroutine with its formal arguments bound to the provided actual arguments. How exactly? Parameter passing modes

  • By value
  • By reference, by sharing
  • By value/return

9/47

slide-21
SLIDE 21

PARAMETER PASSING MODES

Call by value

  • A copy of the argument’s value is passed.
  • Changes to the formal parameter do not affect the actual parameter.

Call by reference

  • The address of the argument is passed.
  • Formal parameter is an alias of the actual parameter.
  • Changes to the formal parameter affect the actual parameter.
  • The actual parameter must be an l-value.

10/47

slide-22
SLIDE 22

EXAMPLES OF PARAMETER PASSING MODES (1)

FORTRAN:

  • All parameters are passed by reference.
  • Temporary variables are used to pass non-l-value expressions.

Pascal:

  • Call by value is the default.
  • Keyword var before formal parameter switches to call by reference:

Example: procedure sub(a : integer; var b : integer) C:

  • Call by value
  • Arrays are passed by value, as poisters
  • To simulate call by reference, pass a pointer

11/47

slide-23
SLIDE 23

EXAMPLES OF PARAMETER PASSING MODES (1)

FORTRAN:

  • All parameters are passed by reference.
  • Temporary variables are used to pass non-l-value expressions.

Pascal:

  • Call by value is the default.
  • Keyword var before formal parameter switches to call by reference:

Example: procedure sub(a : integer; var b : integer) C:

  • Call by value
  • Arrays are passed by value, as poisters
  • To simulate call by reference, pass a pointer

11/47

slide-24
SLIDE 24

EXAMPLES OF PARAMETER PASSING MODES (1)

FORTRAN:

  • All parameters are passed by reference.
  • Temporary variables are used to pass non-l-value expressions.

Pascal:

  • Call by value is the default.
  • Keyword var before formal parameter switches to call by reference:

Example: procedure sub(a : integer; var b : integer) C:

  • Call by value
  • Arrays are passed by value, as poisters
  • To simulate call by reference, pass a pointer

11/47

slide-25
SLIDE 25

EXAMPLES OF PARAMETER PASSING MODES (2)

Smalltalk, Lisp, Clu, ML:

  • Reference model of variables

⇒ Call by sharing: Object can be altered, just as with call by reference but the identity of the object cannot change. Ada:

  • in parameters: Call by value
  • in out parameters: Call by reference or call by value/return
  • out parameters: “Call by result”

C++:

  • Same as C but with the addition of reference parameters:

void swap(int &a, int &b) { int t = a; a = b; b = t; }

  • References can be declared const: efficiency of call by reference and safety
  • f call by value

12/47

slide-26
SLIDE 26

EXAMPLES OF PARAMETER PASSING MODES (2)

Smalltalk, Lisp, Clu, ML:

  • Reference model of variables

⇒ Call by sharing: Object can be altered, just as with call by reference but the identity of the object cannot change. Ada:

  • in parameters: Call by value
  • in out parameters: Call by reference or call by value/return
  • out parameters: “Call by result”

C++:

  • Same as C but with the addition of reference parameters:

void swap(int &a, int &b) { int t = a; a = b; b = t; }

  • References can be declared const: efficiency of call by reference and safety
  • f call by value

12/47

slide-27
SLIDE 27

EXAMPLES OF PARAMETER PASSING MODES (2)

Smalltalk, Lisp, Clu, ML:

  • Reference model of variables

⇒ Call by sharing: Object can be altered, just as with call by reference but the identity of the object cannot change. Ada:

  • in parameters: Call by value
  • in out parameters: Call by reference or call by value/return
  • out parameters: “Call by result”

C++:

  • Same as C but with the addition of reference parameters:

void swap(int &a, int &b) { int t = a; a = b; b = t; }

  • References can be declared const: efficiency of call by reference and safety
  • f call by value

12/47

slide-28
SLIDE 28

EXAMPLES OF PARAMETER PASSING MODES (3)

Java, Python:

  • Call by value for primitive types
  • Call by sharing for compound types (objects)

C#:

  • Call by value/sharing is the default
  • ref and out keywords to force call by reference
  • Distinction between call by value and call by sharing made at data type level:
  • struct types are values.
  • class types are references.

13/47

slide-29
SLIDE 29

EXAMPLES OF PARAMETER PASSING MODES (3)

Java, Python:

  • Call by value for primitive types
  • Call by sharing for compound types (objects)

C#:

  • Call by value/sharing is the default
  • ref and out keywords to force call by reference
  • Distinction between call by value and call by sharing made at data type level:
  • struct types are values.
  • class types are references.

13/47

slide-30
SLIDE 30

READ-ONLY PARAMETERS

A common practice in Pascal:

  • Large values are passed by reference for efficiency reasons
  • High potential for bugs

Read-only parameters address this problem:

  • Efficiency of call by reference
  • Safety of call by value

Modula 3: readonly parameters ANSI C, C++: const parameters When using call by value, declaring a parameter readonly or const is pointless.

14/47

slide-31
SLIDE 31

READ-ONLY PARAMETERS

A common practice in Pascal:

  • Large values are passed by reference for efficiency reasons
  • High potential for bugs

Read-only parameters address this problem:

  • Efficiency of call by reference
  • Safety of call by value

Modula 3: readonly parameters ANSI C, C++: const parameters When using call by value, declaring a parameter readonly or const is pointless.

14/47

slide-32
SLIDE 32

READ-ONLY PARAMETERS

A common practice in Pascal:

  • Large values are passed by reference for efficiency reasons
  • High potential for bugs

Read-only parameters address this problem:

  • Efficiency of call by reference
  • Safety of call by value

Modula 3: readonly parameters ANSI C, C++: const parameters When using call by value, declaring a parameter readonly or const is pointless.

14/47

slide-33
SLIDE 33

READ-ONLY PARAMETERS

A common practice in Pascal:

  • Large values are passed by reference for efficiency reasons
  • High potential for bugs

Read-only parameters address this problem:

  • Efficiency of call by reference
  • Safety of call by value

Modula 3: readonly parameters ANSI C, C++: const parameters When using call by value, declaring a parameter readonly or const is pointless.

14/47

slide-34
SLIDE 34

SOME USES OF CONST IN C++

Constant definition:

const int buffersize = 512;

Read-only function parameter:

void f(const int &i) { ... }

Immutable reference returned by a function (e.g., container interfaces):

const string &f() { ... }

Object method that cannot change the object (the only type of method that can be invoked on a const object):

int A::f(int i, string s) const { ... }

15/47

slide-35
SLIDE 35

SOME USES OF CONST IN C++

Constant definition:

const int buffersize = 512;

Read-only function parameter:

void f(const int &i) { ... }

Immutable reference returned by a function (e.g., container interfaces):

const string &f() { ... }

Object method that cannot change the object (the only type of method that can be invoked on a const object):

int A::f(int i, string s) const { ... }

15/47

slide-36
SLIDE 36

SOME USES OF CONST IN C++

Constant definition:

const int buffersize = 512;

Read-only function parameter:

void f(const int &i) { ... }

Immutable reference returned by a function (e.g., container interfaces):

const string &f() { ... }

Object method that cannot change the object (the only type of method that can be invoked on a const object):

int A::f(int i, string s) const { ... }

15/47

slide-37
SLIDE 37

SOME USES OF CONST IN C++

Constant definition:

const int buffersize = 512;

Read-only function parameter:

void f(const int &i) { ... }

Immutable reference returned by a function (e.g., container interfaces):

const string &f() { ... }

Object method that cannot change the object (the only type of method that can be invoked on a const object):

int A::f(int i, string s) const { ... }

15/47

slide-38
SLIDE 38

ROAD MAP

  • Functions, procedures, and parameters
  • Inline expansion
  • Parameter passing modes
  • Passing functions as arguments
  • Default and named parameters
  • Variadic subroutines
  • Generic subroutines
  • Exception handling
  • Continuations
  • Coroutines

16/47

slide-39
SLIDE 39

ROAD MAP

  • Functions, procedures, and parameters
  • Inline expansion
  • Parameter passing modes
  • Passing functions as arguments
  • Default and named parameters
  • Variadic subroutines
  • Generic subroutines
  • Exception handling
  • Continuations
  • Coroutines

16/47

slide-40
SLIDE 40

SUBROUTINE CLOSURES AS PARAMETERS

Function as parameters and function return values require the passing of closures. Languages that support this:

  • Pascal
  • Ada 95 (not Ada 83)
  • All functional programming languages

Restricted passing of functions in C/C++ and FORTRAN:

  • Functions are not allowed to nest (or not significantly in FORTRAN)
  • No need for closures
  • Pointers to subroutines suffice

17/47

slide-41
SLIDE 41

SUBROUTINE CLOSURES AS PARAMETERS

Function as parameters and function return values require the passing of closures. Languages that support this:

  • Pascal
  • Ada 95 (not Ada 83)
  • All functional programming languages

Restricted passing of functions in C/C++ and FORTRAN:

  • Functions are not allowed to nest (or not significantly in FORTRAN)
  • No need for closures
  • Pointers to subroutines suffice

17/47

slide-42
SLIDE 42

SUBROUTINE CLOSURES AS PARAMETERS

Function as parameters and function return values require the passing of closures. Languages that support this:

  • Pascal
  • Ada 95 (not Ada 83)
  • All functional programming languages

Restricted passing of functions in C/C++ and FORTRAN:

  • Functions are not allowed to nest (or not significantly in FORTRAN)
  • No need for closures
  • Pointers to subroutines suffice

17/47

slide-43
SLIDE 43

ROAD MAP

  • Functions, procedures, and parameters
  • Inline expansion
  • Parameter passing modes
  • Passing functions as arguments
  • Default and named parameters
  • Variadic subroutines
  • Generic subroutines
  • Exception handling
  • Continuations
  • Coroutines

18/47

slide-44
SLIDE 44

ROAD MAP

  • Functions, procedures, and parameters
  • Inline expansion
  • Parameter passing modes
  • Passing functions as arguments
  • Default and named parameters
  • Variadic subroutines
  • Generic subroutines
  • Exception handling
  • Continuations
  • Coroutines

18/47

slide-45
SLIDE 45

DEFAULT (OPTIONAL) PARAMETERS

Default (optional) parameters need not be specified by the caller. If not specified, they take default values. Ada:

procedure put(item : in integer; width : int field := 10);

C++:

void put(int item, int width = 10) { ... }

Implementation is trivial. How?

19/47

slide-46
SLIDE 46

DEFAULT (OPTIONAL) PARAMETERS

Default (optional) parameters need not be specified by the caller. If not specified, they take default values. Ada:

procedure put(item : in integer; width : int field := 10);

C++:

void put(int item, int width = 10) { ... }

Implementation is trivial. How?

19/47

slide-47
SLIDE 47

NAMED (KEYWORD) PARAMETERS

Named (keyword) parameters need not appear in a fixed order.

  • Good for documenting the purpose of parameters in a call.
  • Necessary to utilize the full power of default parameters.

Ada:

format_page(columns => 2, width => 4, font => Helvetica);

Implementation is once again trivial. How?

20/47

slide-48
SLIDE 48

NAMED (KEYWORD) PARAMETERS

Named (keyword) parameters need not appear in a fixed order.

  • Good for documenting the purpose of parameters in a call.
  • Necessary to utilize the full power of default parameters.

Ada:

format_page(columns => 2, width => 4, font => Helvetica);

Implementation is once again trivial. How?

20/47

slide-49
SLIDE 49

ROAD MAP

  • Functions, procedures, and parameters
  • Inline expansion
  • Parameter passing modes
  • Passing functions as arguments
  • Default and named parameters
  • Variadic subroutines
  • Generic subroutines
  • Exception handling
  • Continuations
  • Coroutines

21/47

slide-50
SLIDE 50

ROAD MAP

  • Functions, procedures, and parameters
  • Inline expansion
  • Parameter passing modes
  • Passing functions as arguments
  • Default and named parameters
  • Variadic subroutines
  • Generic subroutines
  • Exception handling
  • Continuations
  • Coroutines

21/47

slide-51
SLIDE 51

VARIADIC SUBROUTINES (VARIABLE NUMBER OF ARGUMENTS)

C/C++/Python allow variable numbers of arguments:

#include <stdarg.h> int printf1(char *format, ...) { va_list args; va_start(args, format); char c = va_arg(args, char); ... va_end(args); }

Java and C# provide similar facilities, in a typesafe but more restrictive manner.

22/47

slide-52
SLIDE 52

VARIADIC SUBROUTINES (VARIABLE NUMBER OF ARGUMENTS)

C/C++/Python allow variable numbers of arguments:

#include <stdarg.h> int printf1(char *format, ...) { va_list args; va_start(args, format); char c = va_arg(args, char); ... va_end(args); }

Java and C# provide similar facilities, in a typesafe but more restrictive manner.

22/47

slide-53
SLIDE 53

ROAD MAP

  • Functions, procedures, and parameters
  • Inline expansion
  • Parameter passing modes
  • Passing functions as arguments
  • Default and named parameters
  • Variadic subroutines
  • Generic subroutines
  • Exception handling
  • Continuations
  • Coroutines

23/47

slide-54
SLIDE 54

ROAD MAP

  • Functions, procedures, and parameters
  • Inline expansion
  • Parameter passing modes
  • Passing functions as arguments
  • Default and named parameters
  • Variadic subroutines
  • Generic subroutines
  • Exception handling
  • Continuations
  • Coroutines

23/47

slide-55
SLIDE 55

GENERIC SUBROUTINES AND MODULES

Standard subroutines allow the same code to be applied to many different values. Generic subroutines can be applied to many different types. There is a trade-off involved in balancing the generality of the framework with type safety.

24/47

slide-56
SLIDE 56

GENERIC SUBROUTINES AND MODULES

Standard subroutines allow the same code to be applied to many different values. Generic subroutines can be applied to many different types. There is a trade-off involved in balancing the generality of the framework with type safety.

24/47

slide-57
SLIDE 57

GENERIC SUBROUTINES: RUNTIME TYPE CHECKS

Examples: Lisp, Scheme, Python, Ruby

(defun merge (a b) (cond ((null? a) b) ((null? b) a) ((< (car a) (car b)) (cons (car a) (merge (cdr a) b))) (t (cons (car b) (merge a (cdr b))))))

25/47

slide-58
SLIDE 58

GENERIC SUBROUTINES: COMPILE-TIME TYPE CHECKS UPON INSTANTIATION

Example: C++ templates

class A { int f(); }; class B { // No method f }; template <class T> class C { T data; int g() { return data.f(); } }; C<A> a; // OK C<B> b; // Error

26/47

slide-59
SLIDE 59

GENERIC SUBROUTINES: COMPILE-TIME TYPE CHECKS UPON DECLARATION

Examples:

  • Java interfaces
  • Haskell type classes

public static <T extends Comparable<T>> void sort(T A[]) { ... if (A[i].compareTo(A[j]) >= 0) { ... } ... } Integer[] myArray = new Integer[50]; sort(myArray);

27/47

slide-60
SLIDE 60

ROAD MAP

  • Functions, procedures, and parameters
  • Inline expansion
  • Parameter passing modes
  • Passing functions as arguments
  • Default and named parameters
  • Variadic subroutines
  • Generic subroutines
  • Exception handling
  • Continuations
  • Coroutines

28/47

slide-61
SLIDE 61

ROAD MAP

  • Functions, procedures, and parameters
  • Inline expansion
  • Parameter passing modes
  • Passing functions as arguments
  • Default and named parameters
  • Variadic subroutines
  • Generic subroutines
  • Exception handling
  • Continuations
  • Coroutines

28/47

slide-62
SLIDE 62

EXCEPTION HANDLING

Exception Unexpected or abnormal condition arising during program execution Exceptions may be generated automatically in response to runtime errors or raised explicitly in the program. Typical semantics of exception handling

  • Exception handler lexically bound to a block of code.
  • An exception raised in the block replaces the remaining code in the block

with the code of the corresponding exception handler.

  • If there is no matching handler, the subroutine exits anda handler is looked

for in the calling subroutine. Some (older) languages deviate from this.

29/47

slide-63
SLIDE 63

EXCEPTION HANDLING

Exception Unexpected or abnormal condition arising during program execution Exceptions may be generated automatically in response to runtime errors or raised explicitly in the program. Typical semantics of exception handling

  • Exception handler lexically bound to a block of code.
  • An exception raised in the block replaces the remaining code in the block

with the code of the corresponding exception handler.

  • If there is no matching handler, the subroutine exits anda handler is looked

for in the calling subroutine. Some (older) languages deviate from this.

29/47

slide-64
SLIDE 64

EXCEPTION HANDLING

Exception Unexpected or abnormal condition arising during program execution Exceptions may be generated automatically in response to runtime errors or raised explicitly in the program. Typical semantics of exception handling

  • Exception handler lexically bound to a block of code.
  • An exception raised in the block replaces the remaining code in the block

with the code of the corresponding exception handler.

  • If there is no matching handler, the subroutine exits anda handler is looked

for in the calling subroutine. Some (older) languages deviate from this.

29/47

slide-65
SLIDE 65

EXCEPTION HANDLING

Exception Unexpected or abnormal condition arising during program execution Exceptions may be generated automatically in response to runtime errors or raised explicitly in the program. Typical semantics of exception handling

  • Exception handler lexically bound to a block of code.
  • An exception raised in the block replaces the remaining code in the block

with the code of the corresponding exception handler.

  • If there is no matching handler, the subroutine exits anda handler is looked

for in the calling subroutine. Some (older) languages deviate from this.

29/47

slide-66
SLIDE 66

USE OF EXCEPTION HANDLERS

  • Perform operations necessary to recover from the exception.
  • Terminate the program gracefully, with a meaningful error message.
  • Clean up resources allocated in the protected block before re-raising the

exception.

30/47

slide-67
SLIDE 67

EXCEPTION SUPPORT IN PROGRAMMING LANGUAGES (1)

Representing exceptions:

  • Built-in exception type
  • Object derived from an exception class
  • Any kind of data can be raised as an exception

Raising exceptions:

  • Automatically by the run-time system as a result of an abnormal condition

(e.g., division by zero)

  • throw/raise statement to raise exceptions manually

31/47

slide-68
SLIDE 68

EXCEPTION SUPPORT IN PROGRAMMING LANGUAGES (1)

Representing exceptions:

  • Built-in exception type
  • Object derived from an exception class
  • Any kind of data can be raised as an exception

Raising exceptions:

  • Automatically by the run-time system as a result of an abnormal condition

(e.g., division by zero)

  • throw/raise statement to raise exceptions manually

31/47

slide-69
SLIDE 69

EXCEPTION SUPPORT IN PROGRAMMING LANGUAGES (2)

Where can exceptions be handled?

  • Most languages allow exceptions to be handled locally and propagate

unhandled exceptions up the dynamic chain.

  • Clu does not allow exceptions to be handled locally.

(How can you simulate local exception handlers?)

  • PL/I’s exception handling mechanism is similar to dynamic scoping.

Some languages require exceptions thrown but not handled inside a subroutine to be declared as part of the subroutine definition.

32/47

slide-70
SLIDE 70

EXCEPTION SUPPORT IN PROGRAMMING LANGUAGES (2)

Where can exceptions be handled?

  • Most languages allow exceptions to be handled locally and propagate

unhandled exceptions up the dynamic chain.

  • Clu does not allow exceptions to be handled locally.

(How can you simulate local exception handlers?)

  • PL/I’s exception handling mechanism is similar to dynamic scoping.

Some languages require exceptions thrown but not handled inside a subroutine to be declared as part of the subroutine definition.

32/47

slide-71
SLIDE 71

HANDLING EXCEPTIONS WITHOUT LANGUAGE SUPPORT

  • “Invent” a value that can be used instead of a real value normally returned

by a subroutine.

  • Return an explicit “status” value to the caller.

The caller needs to check this status.

  • Rely on the caller to pass a closure to be called in case of an exception.

33/47

slide-72
SLIDE 72

EXCEPTION PROPAGATION

  • Exception handlers in the current scope are examined in order.

The first one that “matches” the exception is invoked.

  • If no matching handler is found, the subroutine exits, and the process is

repeated in the caller.

  • The stack must be unwound (restored to the previous state) and any

necessary clean-up needs to be performed (e.g., deallocation of heap

  • bjects, closing of file descriptors). Some languages provide support for this

using constructs such as Java’s finally clause.

34/47

slide-73
SLIDE 73

EXCEPTION PROPAGATION

  • Exception handlers in the current scope are examined in order.

The first one that “matches” the exception is invoked.

  • If no matching handler is found, the subroutine exits, and the process is

repeated in the caller.

  • The stack must be unwound (restored to the previous state) and any

necessary clean-up needs to be performed (e.g., deallocation of heap

  • bjects, closing of file descriptors). Some languages provide support for this

using constructs such as Java’s finally clause.

34/47

slide-74
SLIDE 74

EXCEPTION PROPAGATION

  • Exception handlers in the current scope are examined in order.

The first one that “matches” the exception is invoked.

  • If no matching handler is found, the subroutine exits, and the process is

repeated in the caller.

  • The stack must be unwound (restored to the previous state) and any

necessary clean-up needs to be performed (e.g., deallocation of heap

  • bjects, closing of file descriptors). Some languages provide support for this

using constructs such as Java’s finally clause.

34/47

slide-75
SLIDE 75

EXCEPTION PROPAGATION

  • Exception handlers in the current scope are examined in order.

The first one that “matches” the exception is invoked.

  • If no matching handler is found, the subroutine exits, and the process is

repeated in the caller.

  • The stack must be unwound (restored to the previous state) and any

necessary clean-up needs to be performed (e.g., deallocation of heap

  • bjects, closing of file descriptors). Some languages provide support for this

using constructs such as Java’s finally clause.

34/47

slide-76
SLIDE 76

IMPLEMENTING EXCEPTION HANDLING (1)

A simple implementation:

  • Every subroutine pushes a special exception handler onto the stack that is

executed when control escapes the subroutine and performs all necessary clean-up operations.

  • Every subroutine/protected code block pushes its exception handler onto a

handler stack.

  • Exception handlers with multiple alternatives are implemented using

if-then-else or switch statements in the handler. This implementation is costly because it requires the manipulation of the handler stack for each subroutine call/return.

35/47

slide-77
SLIDE 77

IMPLEMENTING EXCEPTION HANDLING (1)

A simple implementation:

  • Every subroutine pushes a special exception handler onto the stack that is

executed when control escapes the subroutine and performs all necessary clean-up operations.

  • Every subroutine/protected code block pushes its exception handler onto a

handler stack.

  • Exception handlers with multiple alternatives are implemented using

if-then-else or switch statements in the handler. This implementation is costly because it requires the manipulation of the handler stack for each subroutine call/return.

35/47

slide-78
SLIDE 78

IMPLEMENTING EXCEPTION HANDLING (1)

A simple implementation:

  • Every subroutine pushes a special exception handler onto the stack that is

executed when control escapes the subroutine and performs all necessary clean-up operations.

  • Every subroutine/protected code block pushes its exception handler onto a

handler stack.

  • Exception handlers with multiple alternatives are implemented using

if-then-else or switch statements in the handler. This implementation is costly because it requires the manipulation of the handler stack for each subroutine call/return.

35/47

slide-79
SLIDE 79

IMPLEMENTING EXCEPTION HANDLING (1)

A simple implementation:

  • Every subroutine pushes a special exception handler onto the stack that is

executed when control escapes the subroutine and performs all necessary clean-up operations.

  • Every subroutine/protected code block pushes its exception handler onto a

handler stack.

  • Exception handlers with multiple alternatives are implemented using

if-then-else or switch statements in the handler. This implementation is costly because it requires the manipulation of the handler stack for each subroutine call/return.

35/47

slide-80
SLIDE 80

IMPLEMENTING EXCEPTION HANDLING (1)

A simple implementation:

  • Every subroutine pushes a special exception handler onto the stack that is

executed when control escapes the subroutine and performs all necessary clean-up operations.

  • Every subroutine/protected code block pushes its exception handler onto a

handler stack.

  • Exception handlers with multiple alternatives are implemented using

if-then-else or switch statements in the handler. This implementation is costly because it requires the manipulation of the handler stack for each subroutine call/return.

35/47

slide-81
SLIDE 81

IMPLEMENTING EXCEPTION HANDLING (2)

A faster implementation:

  • Store a global table mapping the memory addresses of code blocks to

exception handlers (can be generated by compiler).

  • When encountering an exception, perform binary search on the table using

the program counter to locate the corresponding handler. Comparison to simple mechanism:

  • Handling an exception is more costly (binary search), but exceptions should

be rare.

  • In the absence of exceptions, the cost of this mechanism is zero!
  • Cannot be used if the program consists of separately compiled units and the

linker is not aware of this exception handling mechanism.

36/47

slide-82
SLIDE 82

IMPLEMENTING EXCEPTION HANDLING (2)

A faster implementation:

  • Store a global table mapping the memory addresses of code blocks to

exception handlers (can be generated by compiler).

  • When encountering an exception, perform binary search on the table using

the program counter to locate the corresponding handler. Comparison to simple mechanism:

  • Handling an exception is more costly (binary search), but exceptions should

be rare.

  • In the absence of exceptions, the cost of this mechanism is zero!
  • Cannot be used if the program consists of separately compiled units and the

linker is not aware of this exception handling mechanism.

36/47

slide-83
SLIDE 83

IMPLEMENTING EXCEPTION HANDLING (2)

A faster implementation:

  • Store a global table mapping the memory addresses of code blocks to

exception handlers (can be generated by compiler).

  • When encountering an exception, perform binary search on the table using

the program counter to locate the corresponding handler. Comparison to simple mechanism:

  • Handling an exception is more costly (binary search), but exceptions should

be rare.

  • In the absence of exceptions, the cost of this mechanism is zero!
  • Cannot be used if the program consists of separately compiled units and the

linker is not aware of this exception handling mechanism.

36/47

slide-84
SLIDE 84

IMPLEMENTING EXCEPTION HANDLING (2)

A faster implementation:

  • Store a global table mapping the memory addresses of code blocks to

exception handlers (can be generated by compiler).

  • When encountering an exception, perform binary search on the table using

the program counter to locate the corresponding handler. Comparison to simple mechanism:

  • Handling an exception is more costly (binary search), but exceptions should

be rare.

  • In the absence of exceptions, the cost of this mechanism is zero!
  • Cannot be used if the program consists of separately compiled units and the

linker is not aware of this exception handling mechanism.

36/47

slide-85
SLIDE 85

IMPLEMENTING EXCEPTION HANDLING (2)

A faster implementation:

  • Store a global table mapping the memory addresses of code blocks to

exception handlers (can be generated by compiler).

  • When encountering an exception, perform binary search on the table using

the program counter to locate the corresponding handler. Comparison to simple mechanism:

  • Handling an exception is more costly (binary search), but exceptions should

be rare.

  • In the absence of exceptions, the cost of this mechanism is zero!
  • Cannot be used if the program consists of separately compiled units and the

linker is not aware of this exception handling mechanism.

36/47

slide-86
SLIDE 86

IMPLEMENTING EXCEPTION HANDLING (2)

A faster implementation:

  • Store a global table mapping the memory addresses of code blocks to

exception handlers (can be generated by compiler).

  • When encountering an exception, perform binary search on the table using

the program counter to locate the corresponding handler. Comparison to simple mechanism:

  • Handling an exception is more costly (binary search), but exceptions should

be rare.

  • In the absence of exceptions, the cost of this mechanism is zero!
  • Cannot be used if the program consists of separately compiled units and the

linker is not aware of this exception handling mechanism.

36/47

slide-87
SLIDE 87

IMPLEMENTING EXCEPTION HANDLING (2)

A faster implementation:

  • Store a global table mapping the memory addresses of code blocks to

exception handlers (can be generated by compiler).

  • When encountering an exception, perform binary search on the table using

the program counter to locate the corresponding handler. Comparison to simple mechanism:

  • Handling an exception is more costly (binary search), but exceptions should

be rare.

  • In the absence of exceptions, the cost of this mechanism is zero!
  • Cannot be used if the program consists of separately compiled units and the

linker is not aware of this exception handling mechanism.

36/47

slide-88
SLIDE 88

EXCEPTIONS IN JAVA AND C++

Java:

  • throw throws an exception.
  • try encloses a protected block.
  • catch defines an exception handler.
  • finally defines block of clean-up code to

execute no matter what.

  • Only Throwable objects can be thrown.
  • Must declare uncaught checked exceptions.

C++:

  • throw, try, and catch as in Java
  • No finally block
  • Any object can be thrown.
  • Exception declarations on functions not required

try { ... throw ... ... } catch (SomeException e1) { ... } catch (SomeException e2) { ... } finally { ... }

37/47

slide-89
SLIDE 89

EXCEPTIONS IN JAVA AND C++

Java:

  • throw throws an exception.
  • try encloses a protected block.
  • catch defines an exception handler.
  • finally defines block of clean-up code to

execute no matter what.

  • Only Throwable objects can be thrown.
  • Must declare uncaught checked exceptions.

C++:

  • throw, try, and catch as in Java
  • No finally block
  • Any object can be thrown.
  • Exception declarations on functions not required

try { ... throw ... ... } catch (SomeException e1) { ... } catch (SomeException e2) { ... } finally { ... }

37/47

slide-90
SLIDE 90

ROAD MAP

  • Functions, procedures, and parameters
  • Inline expansion
  • Parameter passing modes
  • Passing functions as arguments
  • Default and named parameters
  • Variadic subroutines
  • Generic subroutines
  • Exception handling
  • Continuations
  • Coroutines

38/47

slide-91
SLIDE 91

ROAD MAP

  • Functions, procedures, and parameters
  • Inline expansion
  • Parameter passing modes
  • Passing functions as arguments
  • Default and named parameters
  • Variadic subroutines
  • Generic subroutines
  • Exception handling
  • Continuations
  • Coroutines

38/47

slide-92
SLIDE 92

CONTINUATIONS IN SCHEME

Scheme does not support exceptions. However, it has a much more general construct that subsumes subroutines, coroutines, exception handling, …: continuations. A continuation is the “future” of the current computation, represented as

  • Current stack content and referencing environment
  • Current register content
  • Current program counter

Continuations are first-class objects in Scheme: they can be passed as function arguments, returned as function results, and stored in data structures.

39/47

slide-93
SLIDE 93

CONTINUATIONS IN SCHEME

Scheme does not support exceptions. However, it has a much more general construct that subsumes subroutines, coroutines, exception handling, …: continuations. A continuation is the “future” of the current computation, represented as

  • Current stack content and referencing environment
  • Current register content
  • Current program counter

Continuations are first-class objects in Scheme: they can be passed as function arguments, returned as function results, and stored in data structures.

39/47

slide-94
SLIDE 94

CONTINUATIONS IN SCHEME

Scheme does not support exceptions. However, it has a much more general construct that subsumes subroutines, coroutines, exception handling, …: continuations. A continuation is the “future” of the current computation, represented as

  • Current stack content and referencing environment
  • Current register content
  • Current program counter

Continuations are first-class objects in Scheme: they can be passed as function arguments, returned as function results, and stored in data structures.

39/47

slide-95
SLIDE 95

CALL-WITH-CURRENT-CONTINUATION IN SCHEME

(call-with-current-continuation f) calls function f and passes the current

continuation to f as an argument. Simplest possible use: Escape procedure

  • If f never uses the continuation it was passed as an argument, then

everything works as if f had been invoked as (f).

  • If f invokes the continuation, then the program state is restored as if f had

never been called. Example: Look for the first negative number in a list

(call/cc (lambda (exit) (for-each (lambda (x) (if (negative? x) (exit x))) '(54 0 37 -3 245 19)) #t))

40/47

slide-96
SLIDE 96

CALL-WITH-CURRENT-CONTINUATION IN SCHEME

(call-with-current-continuation f) calls function f and passes the current

continuation to f as an argument. Simplest possible use: Escape procedure

  • If f never uses the continuation it was passed as an argument, then

everything works as if f had been invoked as (f).

  • If f invokes the continuation, then the program state is restored as if f had

never been called. Example: Look for the first negative number in a list

(call/cc (lambda (exit) (for-each (lambda (x) (if (negative? x) (exit x))) '(54 0 37 -3 245 19)) #t))

40/47

slide-97
SLIDE 97

CALL-WITH-CURRENT-CONTINUATION IN SCHEME

(call-with-current-continuation f) calls function f and passes the current

continuation to f as an argument. Simplest possible use: Escape procedure

  • If f never uses the continuation it was passed as an argument, then

everything works as if f had been invoked as (f).

  • If f invokes the continuation, then the program state is restored as if f had

never been called. Example: Look for the first negative number in a list

(call/cc (lambda (exit) (for-each (lambda (x) (if (negative? x) (exit x))) '(54 0 37 -3 245 19)) #t))

40/47

slide-98
SLIDE 98

CALL/CC FOR EXCEPTION HANDLING

(define (list-length obj) (call/cc (lambda (return) (letrec ((r (lambda (obj) (cond ((null? obj) 0) ((pair? obj) (+1 (r (cdr obj)))) (else (return #f)))))) (r obj))))) (list-length '(1 2 3 4)) ; --> 4 (list-length '(a b . c)) ; --> #f

41/47

slide-99
SLIDE 99

SETJMP/LONGJMP MECHANISM IN C

In C, setjmp/longjmp provide a limited form of continuations:

if (!setjmp(buffer)) { /* protected code */ } else { /* handler */ }

  • The first invocation of setjmp returns 0 and stores the current context

(registers, stack pointer, …) in the provided jump buffer.

  • If no longjmp is performed on the buffer, the then-branch terminates as

usual.

  • If longjmp is invoked, the setjmp returns for a second time, with a non-zero

return value, and the handler in the else-branch is executed.

42/47

slide-100
SLIDE 100

ROAD MAP

  • Functions, procedures, and parameters
  • Inline expansion
  • Parameter passing modes
  • Passing functions as arguments
  • Default and named parameters
  • Variadic subroutines
  • Generic subroutines
  • Exception handling
  • Continuations
  • Coroutines

43/47

slide-101
SLIDE 101

ROAD MAP

  • Functions, procedures, and parameters
  • Inline expansion
  • Parameter passing modes
  • Passing functions as arguments
  • Default and named parameters
  • Variadic subroutines
  • Generic subroutines
  • Exception handling
  • Continuations
  • Coroutines

43/47

slide-102
SLIDE 102

COROUTINES

Coroutines are separate threads of execution that voluntarily transfer control to each other. (Contrast this with threads.) Coroutine A Coroutine B Transfer B Transfer B Transfer A Transfer A Useful to implement generators, e.g., in Python

44/47

slide-103
SLIDE 103

COROUTINES

Coroutines are separate threads of execution that voluntarily transfer control to each other. (Contrast this with threads.) Coroutine A Coroutine B Transfer B Transfer B Transfer A Transfer A Useful to implement generators, e.g., in Python

44/47

slide-104
SLIDE 104

MANAGING STACK SPACE FOR COROUTINES

Coroutines are “active” at the same time. Thus, they cannot use the same stack. Some notion of stack is required to allow recursion within coroutines and support lexical scoping. Solution: Cactus stack A P Q R M C S B D Coroutine A Subroutine P Main program M Coroutine B Coroutine D Subroutine S Subroutine Q Coroutine C Subroutine R

45/47

slide-105
SLIDE 105

MANAGING STACK SPACE FOR COROUTINES

Coroutines are “active” at the same time. Thus, they cannot use the same stack. Some notion of stack is required to allow recursion within coroutines and support lexical scoping. Solution: Cactus stack A P Q R M C S B D Coroutine A Subroutine P Main program M Coroutine B Coroutine D Subroutine S Subroutine Q Coroutine C Subroutine R

45/47

slide-106
SLIDE 106

COROUTINES USING CONTINUATIONS

(define (adder args) (let* ((val (car args)) (other (cdr args)) (res (call/cc (lambda (c) (other (cons val c)))))) (if (< (char res) 100) > (adder (begin (display "Adder: ") (cons 1 (display (car res)) multiplier)) (newline) Adder: 1 (adder (cons (+ 1 (car res)) (cdr res))))))) Multiplier: 2 Adder: 4 (define (multiplier args) Multiplier: 5 (let* ((val (car args)) Adder: 10 (other (cdr args)) Multiplier 11 (res (call/cc (lambda (c) (other (cons val c)))))) Adder: 22 (if (< (car res) 100) Multiplier: 23 (begin (display "Multiplier: ") Adder: 46 (display (car res)) Multiplier: 47 (newline) Adder: 94 (multiplier (cons (* 2 (car res)) (cdr res))))))) Multiplier: 95 46/47

slide-107
SLIDE 107

SUMMARY

  • Subroutines are the main tool for building control abstractions.
  • Parameter passing modes determine how subroutines interact with the
  • utside world through their parameters.
  • Exception handling is a mechanism to recover from abnormal situations in a

program’s execution.

  • Exceptions should not be used for normal control flow! (Shame on you,

Python!)

  • Coroutines are elegant tools for implementing cooperative multi-threading.
  • Continuations subsume subroutines, coroutines, exception handling, …

47/47