Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate...

56
Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Transcript of Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate...

Page 1: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Programming Language PrinciplesLecture 25

Prepared byManuel E. Bermúdez, Ph.D.

Associate ProfessorUniversity of Florida

Subroutines (Part 2)

Page 2: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Parameter Passing

• Formal parameters: Parameters that appear in the declaration of a subroutine

• Actual parameters: expressions actually used in procedure call.

• Some languages allow only ONE parameter passing mode:– C, Fortran, ML, Lisp.

• Other languages allow multiple parameter passing modes:– Pascal, Modula, Ada, Java

Page 3: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Main Parameter Passing Modes

1) Call by value: Pass the value of the argument. – C, C++, Pascal (also allows pass by reference),

Java (primitive types).– Can be expensive: large structures are copied.

2) Call by reference: Pass the address of the argument.– Smalltalk, Lisp, ML, Clu, C++, Java (non primitive

types, including arrays).– C, C++ have const mode: cannot change

parameter.

3) Call by name: Pass the text of the argument.– C pre-processor (#define)– More later.

Page 4: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Choosing Parameter Passing Mode• Many languages provide a choice:

– Pass by value:• Intent is to not modify the argument.

– Pass by reference:• Intent is to modify the argument.• Often used to avoid expense of copying

large structure, even if there’s no intent to modify it. Leaves door open for mistakes.

• In some languages (C, C++) modifying the argument can be explicitly forbidden (const)

Page 5: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Parameter Passing in Ada

ADA provides 3 modes: in, out, in-out.

• In: From caller to callee (call by value).• Out: From callee to caller (call by result).• In-out: Uses both. (call by value/result).

– Ada specifies that all three are to be implemented by copying the values. However, Ada specifically permits passing either values or addresses.

Page 6: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Parameter Passing Modes: Example

var y:integer;procedure

A(x:integer);begin

write(x);x := 1;write(y+x);

end;begin

y := 5;A(y);write(y);

end;

Pass by value:Output is (5,6,5)

Page 7: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Parameter Passing Modes: Example

var y:integer;procedure

A(x:integer);begin

write(x);x := 1;write(y+x);

end;begin

y := 5;A(y);write(y);

end;

Pass by reference:Output is (5,2,1)

Page 8: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Parameter Passing Modes: Example

var y:integer;procedure

A(x:integer);begin

write(x);x := 1;write(y+x);

end;begin

y := 5;A(y);write(y);

end;

Pass by result:Output is (??,6,1)

Page 9: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Parameter Passing Modes: Example

var y:integer;procedure

A(x:integer);begin

write(x);x := 1;write(y+x);

end;begin

y := 5;A(y);write(y);

end;

Pass by value/result:Output is (5,6,1)

Page 10: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Parameter Passing in Ada (cont’d)• Example:

• This Ada program is considered erroneous: it can tell the difference between pass by reference and value/result.

Page 11: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Parameter Passing in Pascal

• Use keyword var to effect pass by reference.

• With var , output is (5,2,1).

• Without var, output is (5,6,5)

var y:integer;procedure A(var x:integer);

beginwrite(x);x := 1;write(y+x);

end;begin

y := 5;A(y);write(y);

end;

Page 12: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Parameter Passing in C

• All parameters passed by value.• However, can use pointers (which are

passed by value):

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

} ... swap(&p,&q);

Page 13: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Parameter Passing in C++

• C++ has reference parameters.• Use the & prefix.

void swap (int &a, int &b) {

int t;

t = a;

a = b;

b = t;

}

swap (p,q);

• Parameters can be declared const.

Page 14: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

References in C++

• Any variable can be a reference, allowing aliasing:

int i;

int &j = i;

i = 2;

j = 3;

• Aliasing is useful for function returns:

cout << a << b << c;

is short for ((cout.operator<<(a)).operator<<(b)).operator<<(c);

Page 15: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

References in C++ (cont’d)

• Without references, << and >> would have to return a pointer to their stream:

((cout.operator<<(a))->operator<<(b))->operator<<(c);

Or worse,

*(*(cout.operator<<(a)).operator<<(b)).operator<<(c);

• This would spoil the cascading syntax of operator form:

*(*cout <<a) << b) << c;

Page 16: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Closures as Parameters

• Closure: Reference to a subroutine, including the referencing environment.

• This allows higher order functions.• In Pascal:

procedure apply_to_A (function f(n:integer): integer;var A:array [lo..hi:integer] of integer); var i : integer; begin for i := lo to hi do A[i] := f(A[i]); end;

Page 17: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Closures as Parameters (cont’d)

• Recall: referencing environments are required by closures, only if subroutines can be nested.

• C, C++, Java get by with subroutine pointers because there are no nested subroutines.

• In C,

void apply_to_A (int(*f)(int), int A[],int A_size) { int i;

for (i=0; I < A_size; i++) A[i]=f(A[i]); }

Page 18: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Closures as Parameters (cont’d)

• Scheme:

(define apply-to-L (lambda (f l) (if (null? l) '()

(cons (f (car l)) (apply-to-L f (cdr l))))))

• ML: fun apply_to_L (f, l) =

case l of nil => nil

| h :: t => f (h) :: apply_to_L(f, t);

Page 19: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Closures as Parameters (cont’d)

• RPAL (just for fun):

let apply_to_L f l = helper f l (Order l)

where rec helper f l n =

n eq 0 -> nil

| (helper f l (n-1) aug f(l n))

Page 20: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Call by name

• A call-by-name parameter is evaluated in the caller’s referencing environment when (and only when) it is needed.

• Call by name equivalent to the "subst" function used in lambda calculus, in normal order.

• Call by name allows strange expressions such as infinite lists in Haskell:

take 10 [0..]

(take first 10 elements from infinite list)

Page 21: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Summation routine in Algol 60

Now, y := sum(3*x*x-5*x+2, x, 1, 10);will sum the values of 3x2 -5x+2, for 1 ≤ x ≤ 10.

Page 22: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Call-by-name in Algol 60

• Such uses of call-by-name (summation) are rare.

• To implement call by name, Algol 60 implementations pass a hidden subroutine that evaluates the actual parameter in the caller's referencing environment. The hidden routine is called a thunk.

• Calling thunks proved to be prohibitively expensive.

• Call-by-name dropped in Algol 68.

Page 23: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Call by Name (cont’d)

Pass by name literally substitutes n for a, and m for b.

Result: t := n;n := m;m := t;

swap is achieved.

procedure swap(a,b:integer); var t:integer:

begin

t := a:

a := b:

b := t;

end;

...

var n,m:integer;

n := 3;

m := 4;

swap(n,m);

Page 24: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Call by Name (cont’d)

However, attempting to swap i and A[i] results in

t := i;i := A[i];A[i] := t;

17 assigned to i, but 3 assigned to A[17] (out of range)

swap not achieved.

procedure swap(a,b:integer); var t:integer:

begin

t := a:

a := b:

b := t;

end;

...

var i:integer;

var A: array[1..10]

of integer;

i := 3;

A[3] := 17;

swap(i,A[i]);

Page 25: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Default Parameters

• Parameter initialized with a default value. • If argument is not given, the default value is

used. (C++, Ada, Common Lisp,Fortran 90)

• In C++, default parameters must be the last ones:

void print (int value, int base=10) {...};

print(31); print(31,10); print(31,16); print(31,2); //output: 31 31 1f 11111

Page 26: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Default Parameters in Ada

type field is integer range 0..integer'last;

type number_base is integer range 2..16;

default_width : field := integer'width

default_base : number_base := 10;

procedure put (item : in integer;

width: in field := default_width;

base : in number_base := default_base)is ...

put(37) prints 37 in decimal in 11 columns. put(37,4) prints 37 in decimal in 4 columns. put(37,4,8) prints 45 (37 in octal) in 4 columns.

Page 27: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Default Parameters in Ada (cont’d)• We assumed that parameters are positional. • Some languages allow parameters to be named.• In Ada, (previous example):

put (item => 38, base => 8);

same as

put (base => 8, item => 38)

Page 28: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Variable number of arguments

• In C, C++:

#include <stdarg.h> /* macros and types defns */

int printf (char *format, ...) {

va_list args;

va_start (args, format);

char cp = va_arg(args,char);

double dp = va-arg(args,double);

}

Here we assume two arguments, of type char and double, are expected. If not, chaos will ensue ...

part of code

Page 29: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Function Return Values

• Many languages restrict return types from functions.

• Algol 60, Fortran: must be a scalar value.• Pascal, Modula-2: must be scalar or pointer.• Modula-3, Ada 95: allow a function to return

a subroutine (as a closure).• C: function can return a pointer to a

function.• Lisp, ML, Algol 68, RPAL: returning closures

is common.

Page 30: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Generics

• Often we need a single operation on a variety of different object types.

– Queue a number.– Push something on a stack.– Existing subroutines for stacks of integers, but

now we need stacks of *trees* :-)

• Polymorphic subroutines (Lisp, RPAL) provide a solution, but . . .

– No compile time checking.– Compiler slower and more complicated.– Forces structural view of type equivalence.

Page 31: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Generics (cont’d)

Other solution:

• Generic Modules -- Collection of similar subroutines or modules that operate on different types.

• Useful to create containers:– data abstraction that holds a collection of objects,

but whose operations are generally oblivious to the type of these objects. (Queue, heap, sorting)

• Generics (a.k.a. templates) appear in Modula-3, Clu, Ada, C++, Java.

• Generic modules are a purely static mechanism. They provide a mechanism to create needed source at compile time.

Page 32: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Generic queue package in Ada:

Queue contains up to max_items objects of type item.

Operations are enqueue and dequeue.

Implemented as circular list.

Generics must be instantiated.

Page 33: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Generic queues in C++:

Generic classes must be instantiated.

Generic functions need not be instantiated.

Page 34: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Generic Sorting in C++

Generic functions in C++ need not be instantiated. Example:

template<class T> void sort(T A[], int A_size) { ... }

. . .

int ints[10]; double reals[50]; char *string[30];

. . . sort(ints, 10); sort(reals, 50); sort(string, 30);

Page 35: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Generics in Ada (cont’d)

Ada doesn’t allow subroutines as parameters.Can use generics instead:

Page 36: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Generics in Ada (cont’d)

• Now, we can instantiate:

subtype index is integer range 1 .. 100;scores: array(index) of integer;

function foo (n: in integer) return integer is begin ... end;

procedure apply_to_ints is new apply_to_array (integer, int_array, foo);

apply_to_ints(scores);

Page 37: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Generics (cont’d)

Important: Generics are strictly a compile-time issue.

Designers of Ada: “restricted form of context-sensititve macro facility”.

B. Stroustrup (designer of C++): “clever kind of macro that obeys scope, naming, and type rules of C++”.

Page 38: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Generics (cont’d)

Problem with generics:

• A certain type may permit an operation, but the operation may not behave as expected.

• Example: sorting algorithm. The < behaves well for ints and doubles. For characters and strings it will compare ASCII values or pointers !

Page 39: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Exceptions

• An exception is an unexpected or unusual condition that arises during program execution. May be system-detected or raised explicitly.

• Often I/O related, failure due to some I/O related issue (end of file, wrong input, etc.)

• Often necessary to repair stack (back up execution), and proceed.

Page 40: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Exceptions (cont’d)

Before exceptions, to cope with errors:

1. Invent a value, used by caller, to detect failure.

2. Return an explicit status value, examined after every call.

3. Pass a closure (when available) for an error-handling routine.

None of these are satisfactory (clutter, or hard to program).

Page 41: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Exceptions (cont’d)

• Clu, Ada, Modula-3, C++, Java, ML all provide exception handling:

• Programmer provides handlers that are lexically bound to blocks of code.

• In general:– If exception is not handled locally, control

propagates back up the dynamic chain until either the program stops or a handler is found.

Page 42: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Exceptions (cont’d)

• Exception handlers are (typically) attached to a list of statements.

• Example (Java):

try{ int x = 5/n; } //end try block catch(ArithmeticException e){ System.out.println ("in catch, terminating method"); return; } //end catch block

Page 43: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Exceptions (cont’d)

Exception handling used for 3 purposes:

1. Handler perform some magic recovery (e.g. out of memory, free up garbage memory.

2. If magic fails, at least inform the user nicely (blue screen of death)

3. Handler can clean up the mess (rollback unfinished file writing, deallocate memory, restore previous state, etc.)

Page 44: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Exceptions (cont’d)

• In Ada, exception is a built in-type:

declare empty_queue: exception;

• In Java/C++ an exception is (what else?) an object:

class empty_queue { };

• In Module-3, an exception is another PL "object":

EXCEPTION empty_queue;

Page 45: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Exceptions (cont’d)

• Explicitly raising exceptions:

throw statement (C++, Java, Lisp) . raise statement (Ada, Modula-3, ML).

Page 46: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Exceptions (cont’d)

• Clu, Modula-3, C++, Java:In each subroutine header, include a list ofexceptions that may propagate out of theroutine.

• Modula-3: List is mandatory: run-time error if exception not listed, and exception not caught locally.

• C++: List is optional: if present, same as Modula-3; if not, all exceptions can propagate.

• Java: "checked" exceptions, must be declared; "unchecked" exceptions do not.

Page 47: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Exception Syntax in C++

try { ... // protected code } catch (end_of_file){ // library exception for eof ... // handle eof error } catch (io_error e) { // any other I/O error ... // handle io_error } catch ( ... ){ // handle any other exception // ... is an actual C++ token. }

Page 48: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Exceptions in ML and Lisp

• In ML and common Lisp the exception handler is attached to an expression:

val foo=(f(a)*b) handle Overflow => max_int;

• Overflow is a predefined exception. When exception is raised, max_int will replace the value of the expression.

Page 49: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Phrase-level Error Recovery in Recursive Descent Parsing

At beginning of procedure A, check Next_Token:If not acceptable, delete tokens until it is.

Page 50: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Exception Implementation

• To find a handler the system must "unwind" the run-time stack, reclaiming stack frames.

• Obvious implementation is a linked-list stack of handlers:

– When control enters a protected block, the handler for that block is added to the list.

– Upon exception, the run-time system pops the innermost handler off the list:• If the exception matches, call the handler.• If not, pop the list again.

Page 51: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Exception Implementation

The linked-list stack of handlers incurs run-time overhead.

Other solution:

• Keep a table that maps exceptions to blocks of code.

• When exception occurs, do binary search for block of code, using PC as key.

• If exception is reraised, search again, using return address as key.

Page 52: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Coroutines

• A coroutine is a closure into which we can transfer.

• Coroutines are execution contexts:– Exist concurrently.– Execute one at a time.– Transfer control to each other explicitly.

• Transfer from one coroutine to another:– Old program counter is saved.– Update coroutine we are leaving.– Different from a goto: after a goto, the PC is

forgotten.

• A transfer to a coroutine will take up where the previous one left off.

Page 53: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Example of Coroutines

• Interleave execution of a screen-saving routine, with a file-system-check routine.

Page 54: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Stack Allocation for Coroutines

• Coroutines are concurrent: can’t share a stack.• Solution:

– Each coroutine has fixed amount of stack space (Modula-2):• Out of space: run-time error.• Excess space is wasted.

– Stack frames allocated on the heap (Lisp, Scheme):• Increases overhead of subroutine call.• Can allocate “chunks” of memory, big

enough for the frame.

Page 55: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Cactus Stacks

• If coroutines can be created at any nesting level, (Simula), then we need a cactus stack.

Side-branch: coroutine creation (A, B, C, D).

Static links: arrows.

Dynamic links: vertical stacking.

Page 56: Programming Language Principles Lecture 25 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Subroutines (Part 2)

Programming Language PrinciplesLecture 25

Prepared byManuel E. Bermúdez, Ph.D.

Associate ProfessorUniversity of Florida

Subroutines (Part 2)