Top Banner
06/20/22 1 Programming Languages and Compilers (CS 421) Elsa L Gunter 2112 SC, UIUC http://courses.engr.illinois. edu/cs421 Based in part on slides by Mattox Beckman, as updated by Vikram Adve and Gul Agha
61

Programming Languages and Compilers (CS 421)

Jan 04, 2016

Download

Documents

hilary-walls

Programming Languages and Compilers (CS 421). Elsa L Gunter 2112 SC, UIUC http://courses.engr.illinois.edu/cs421. Based in part on slides by Mattox Beckman, as updated by Vikram Adve and Gul Agha. Mapping Functions Over Lists. # let rec map f list = match list with [] -> [] - PowerPoint PPT Presentation
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Programming Languages and Compilers (CS 421)

04/20/23 1

Programming Languages and Compilers (CS 421)

Elsa L Gunter

2112 SC, UIUC

http://courses.engr.illinois.edu/cs421

Based in part on slides by Mattox Beckman, as updated by Vikram Adve and Gul Agha

Page 2: Programming Languages and Compilers (CS 421)

04/20/23 2

Mapping Functions Over Lists

# let rec map f list = match list with [] -> [] | (h::t) -> (f h) :: (map f t);;val map : ('a -> 'b) -> 'a list -> 'b list =

<fun># map plus_two fib5;;- : int list = [10; 7; 5; 4; 3; 3]# map (fun x -> x - 1) fib6;;: int list = [12; 7; 4; 2; 1; 0; 0]

Page 3: Programming Languages and Compilers (CS 421)

04/20/23 3

Mapping Recursion

One common form of structural recursion applies a function to each element in the structure

# let rec doubleList list = match list with [ ] -> [ ] | x::xs -> 2 * x :: doubleList xs;;val doubleList : int list -> int list = <fun># doubleList [2;3;4];;- : int list = [4; 6; 8]

Page 4: Programming Languages and Compilers (CS 421)

04/20/23 4

Mapping Recursion

Can use the higher-order recursive map function instead of direct recursion

# let doubleList list = List.map (fun x -> 2 * x) list;;val doubleList : int list -> int list = <fun># doubleList [2;3;4];;- : int list = [4; 6; 8]

Same function, but no explicit rec

Page 5: Programming Languages and Compilers (CS 421)

Your turn now

Write a function

make_app : ((‘a -> ‘b) * ‘a) list -> ‘b list

that takes a list of function – input pairs and gives the result of applying each function to its argument. Use map, no explicit recursion.

let make_app l =

04/20/23 5

Page 6: Programming Languages and Compilers (CS 421)

04/20/23 6

Folding Recursion

Another common form “folds” an operation over the elements of the structure

# let rec multList list = match list with [ ] -> 1 | x::xs -> x * multList xs;;val multList : int list -> int = <fun># multList [2;4;6];;- : int = 48 Computes (2 * (4 * (6 * 1)))

Page 7: Programming Languages and Compilers (CS 421)

04/20/23 7

Folding Functions over Lists

How are the following functions similar?# let rec sumList list = match list with [ ] -> 0 | x::xs -> x + sumList xs;;val sumList : int list -> int = <fun># sumList [2;3;4];;- : int = 9# let rec multList list = match list with [ ] -> 1 | x::xs -> x * multList xs;;val multList : int list -> int = <fun># multList [2;3;4];;- : int = 24

Page 8: Programming Languages and Compilers (CS 421)

04/20/23 8

Folding Functions over Lists

How are the following functions similar?# let rec sumList list = match list with [ ] -> 0 | x::xs -> x + sumList xs;;val sumList : int list -> int = <fun># sumList [2;3;4];;- : int = 9# let rec multList list = match list with [ ] -> 1 | x::xs -> x * multList xs;;val multList : int list -> int = <fun># multList [2;3;4];;- : int = 24

Base Case

Page 9: Programming Languages and Compilers (CS 421)

04/20/23 9

Folding Functions over Lists

How are the following functions similar?# let rec sumList list = match list with [ ] -> 0 | x::xs -> x + sumList xs;;val sumList : int list -> int = <fun># sumList [2;3;4];;- : int = 9# let rec multList list = match list with [ ] -> 1 | x::xs -> x * multList xs;;val multList : int list -> int = <fun># multList [2;3;4];;- : int = 24

Recursive Call

Page 10: Programming Languages and Compilers (CS 421)

04/20/23 10

Folding Functions over Lists

How are the following functions similar?# let rec sumList list = match list with [ ] -> 0 | x::xs -> x + sumList xs;;val sumList : int list -> int = <fun># sumList [2;3;4];;- : int = 9# let rec multList list = match list with [ ] -> 1 | x::xs -> x * multList xs;;val multList : int list -> int = <fun># multList [2;3;4];;- : int = 24

Head Element

Page 11: Programming Languages and Compilers (CS 421)

04/20/23 11

Folding Functions over Lists

How are the following functions similar?# let rec sumList list = match list with [ ] -> 0 | x::xs -> x + sumList xs;;val sumList : int list -> int = <fun># sumList [2;3;4];;- : int = 9# let rec multList list = match list with [ ] -> 1 | x::xs -> x * multList xs;;val multList : int list -> int = <fun># multList [2;3;4];;- : int = 24

Combining Operation

Page 12: Programming Languages and Compilers (CS 421)

04/20/23 12

Folding Functions over Lists

How are the following functions similar?# let rec sumList list = match list with [ ] -> 0 | x::xs -> x + sumList xs;;val sumList : int list -> int = <fun># sumList [2;3;4];;- : int = 9# let rec multList list = match list with [ ] -> 1 | x::xs -> x * multList xs;;val multList : int list -> int = <fun># multList [2;3;4];;- : int = 24R

Rec value

Rec value

Combining Operation

Page 13: Programming Languages and Compilers (CS 421)

04/20/23 13

Recursing over lists

# let rec fold_right f list b = match list with [] -> b | (x :: xs) -> f x (fold_right f xs b);;val fold_right : ('a -> 'b -> 'b) -> 'a list -> 'b ->

'b = <fun># fold_right (fun s -> fun () -> print_string s) ["hi"; "there"] ();;therehi- : unit = ()

The Primitive Recursion Fairy

Page 14: Programming Languages and Compilers (CS 421)

04/20/23 14

Folding Recursion

multList folds to the right Same as:# let multList list = List.fold_right (fun x -> fun rv -> x * rv) list 1;;val multList : int list -> int = <fun># multList [2;4;6];;- : int = 48

Page 15: Programming Languages and Compilers (CS 421)

04/20/23 15

Encoding Recursion with Fold

# let rec append list1 list2 = match list1 with [ ] -> list2 | x::xs -> x :: append xs list2;;val append : 'a list -> 'a list -> 'a list = <fun>

Base Case Operation Recursive Call

# let append list1 list2 = fold_right (fun x rv -> x :: rv) list1 list2;;val append : 'a list -> 'a list -> 'a list = <fun># append [1;2;3] [4;5;6];; - : int list = [1; 2; 3; 4; 5; 6]

Page 16: Programming Languages and Compilers (CS 421)

Question

let rec length l = match l with [] -> 0 | (a :: bs) -> 1 + length bsHow do you write length with fold_right, but no explicit recursion?

04/20/23 17

Page 17: Programming Languages and Compilers (CS 421)

Question

let rec length l = match l with [] -> 0 | (a :: bs) -> 1 + length bsHow do you write length with fold_right, but no explicit recursion?let length list = List.fold_right (fun x -> fun n -> n + 1) list 0

04/20/23 18

Page 18: Programming Languages and Compilers (CS 421)

04/20/23 19

Map from Fold

# let map f list = fold_right (fun x -> fun y -> f x :: y)

list [ ];;val map : ('a -> 'b) -> 'a list -> 'b list =

<fun># map ((+)1) [1;2;3];;- : int list = [2; 3; 4] Can you write fold_right (or fold_left)

with just map? How, or why not?

Page 19: Programming Languages and Compilers (CS 421)

04/20/23 20

Iterating over lists

# let rec fold_left f a list = match list with [] -> a | (x :: xs) -> fold_left f (f a x) xs;;val fold_left : ('a -> 'b -> 'a) -> 'a -> 'b list ->

'a = <fun># fold_left (fun () -> print_string) () ["hi"; "there"];;hithere- : unit = ()

Page 20: Programming Languages and Compilers (CS 421)

04/20/23 21

Encoding Tail Recursion with fold_left

# let prod list = let rec prod_aux l acc = match l with [] -> acc | (y :: rest) -> prod_aux rest (acc * y) in prod_aux list 1;;val prod : int list -> int = <fun>

Init Acc Value Recursive Call Operation

# let prod list = List.fold_left (fun acc y -> acc * y) 1 list;;val prod: int list -> int = <fun># prod [4;5;6];; - : int =120

Page 21: Programming Languages and Compilers (CS 421)

Question

let length l = let rec length_aux list n = match list with [] -> n | (a :: bs) -> length_aux bs (n + 1)in length_aux l 0How do you write length with fold_left, but no explicit recursion?

04/20/23 22

Page 22: Programming Languages and Compilers (CS 421)

Question

let length l = let rec length_aux list n = match list with [] -> n | (a :: bs) -> length_aux bs (n + 1)in length_aux l 0How do you write length with fold_left, but no explicit recursion?let length list = List.fold_left (fun n -> fun x -> n + 1) 0 list

04/20/23 23

Page 23: Programming Languages and Compilers (CS 421)

04/20/23 24

Folding

# let rec fold_left f a list = match list with [] -> a | (x :: xs) -> fold_left f (f a x) xs;;val fold_left : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a

= <fun>fold_left f a [x1; x2;…;xn] = f(…(f (f a x1) x2)…)xn

# let rec fold_right f list b = match list with [ ] -> b | (x :: xs) -> f x (fold_right f xs b);;val fold_right : ('a -> 'b -> 'b) -> 'a list -> 'b ->

'b = <fun>fold_right f [x1; x2;…;xn] b = f x1(f x2 (…(f xn b)…))

Page 24: Programming Languages and Compilers (CS 421)

04/20/23 25

Recall

# let rec poor_rev list = match list with [] -> [] | (x::xs) -> poor_rev xs @ [x];;val poor_rev : 'a list -> 'a list = <fun>

What is its running time?

Page 25: Programming Languages and Compilers (CS 421)

04/20/23 27

Tail Recursion - Example

# let rec rev_aux list revlist = match list with [ ] -> revlist | x :: xs -> rev_aux xs (x::revlist);;val rev_aux : 'a list -> 'a list -> 'a list =

<fun>

# let rev list = rev_aux list [ ];;val rev : 'a list -> 'a list = <fun>

What is its running time?

Page 26: Programming Languages and Compilers (CS 421)

04/20/23 28

Comparison

poor_rev [1,2,3] = (poor_rev [2,3]) @ [1] = ((poor_rev [3]) @ [2]) @ [1] = (((poor_rev [ ]) @ [3]) @ [2]) @ [1] = (([ ] @ [3]) @ [2]) @ [1]) = ([3] @ [2]) @ [1] = (3:: ([ ] @ [2])) @ [1] = [3,2] @ [1] = 3 :: ([2] @ [1]) = 3 :: (2:: ([ ] @ [1])) = [3, 2, 1]

Page 27: Programming Languages and Compilers (CS 421)

04/20/23 29

Comparison

rev [1,2,3] = rev_aux [1,2,3] [ ] = rev_aux [2,3] [1] = rev_aux [3] [2,1] = rev_aux [ ] [3,2,1] = [3,2,1]

Page 28: Programming Languages and Compilers (CS 421)

04/20/23 30

Folding - Tail Recursion

- # let rev list =- fold_left- (fun l -> fun x -> x :: l) //comb

op [] //accumulator cell list

Page 29: Programming Languages and Compilers (CS 421)

04/20/23 31

Folding

Can replace recursion by fold_right in any forward primitive recursive definition Primitive recursive means it only recurses

on immediate subcomponents of recursive data structure

Can replace recursion by fold_left in any tail primitive recursive definition

Page 30: Programming Languages and Compilers (CS 421)

04/20/23 32

Continuations

A programming technique for all forms of “non-local” control flow: non-local jumps exceptions general conversion of non-tail calls to

tail calls Essentially it’s a higher-order

function version of GOTO

Page 31: Programming Languages and Compilers (CS 421)

04/20/23 33

Continuations

Idea: Use functions to represent the control flow of a program

Method: Each procedure takes a function as an extra argument to which to pass its result; outer procedure “returns” no result

Function receiving the result called a continuation

Continuation acts as “accumulator” for work still to be done

Page 32: Programming Languages and Compilers (CS 421)

04/20/23 34

Continuation Passing Style

Writing procedures such that all procedure calls take a continuation to which to give (pass) the result, and return no result, is called continuation passing style (CPS)

Page 33: Programming Languages and Compilers (CS 421)

04/20/23 35

Continuation Passing Style

A compilation technique to implement non-local control flow, especially useful in interpreters.

A formalization of non-local control flow in denotational semantics

Possible intermediate state in compiling functional code

Page 34: Programming Languages and Compilers (CS 421)

Why CPS?

Makes order of evaluation explicitly clear Allocates variables (to become registers) for

each step of computation Essentially converts functional programs into

imperative ones Major step for compiling to assembly or byte

code Tail recursion easily identified Strict forward recursion converted to tail

recursion At the expense of building large closures in heap

04/20/23 36

Page 35: Programming Languages and Compilers (CS 421)

04/20/23 37

Example

Simple reporting continuation:# let report x = (print_int x; print_newline( ) );;val report : int -> unit = <fun>

Simple function using a continuation:# let addk a b k = k (a + b);;val addk : int -> int -> (int -> ’a) -> ’a = <fun># addk 22 20 report;;2- : unit = ()

Page 36: Programming Languages and Compilers (CS 421)

Simple Functions Taking Continuations

Given a primitive operation, can convert it to pass its result forward to a continuation

Examples:# let subk x y k = k(x + y);;val subk : int -> int -> (int -> 'a) -> 'a = <fun># let eqk x y k = k(x = y);;val eqk : 'a -> 'a -> (bool -> 'b) -> 'b = <fun># let timesk x y k = k(x * y);;val timesk : int -> int -> (int -> 'a) -> 'a = <fun>

04/20/23 38

Page 37: Programming Languages and Compilers (CS 421)

Nesting Continuations

# let add_three x y z = (x + y) + z;;val add_three : int -> int -> int -> int = <fun># let add_three x y z= let p = x + y in p + z;;val add_three : int -> int -> int -> int = <fun># let add_three_k x y z k = addk x y (fun p -> addk p z k );;val add_three_k : int -> int -> int -> (int -> 'a)

-> 'a = <fun>

04/20/23 40

Page 38: Programming Languages and Compilers (CS 421)

add_three: a different order

# let add_three x y z = x + (y + z);; How do we write add_three_k to use a

different order?

let add_three_k x y z k =

04/20/23 41

Page 39: Programming Languages and Compilers (CS 421)

04/20/23 43

Recursive Functions

Recall:# let rec factorial n = if n = 0 then 1 else n * factorial (n -

1);; val factorial : int -> int = <fun># factorial 5;;- : int = 120

Page 40: Programming Languages and Compilers (CS 421)

04/20/23 44

Recursive Functions

# let rec factorial n = let b = (n = 0) in (* First computation *) if b then 1 (* Returned value *) else let s = n – 1 in (* Second computation

*) let r = factorial s in (* Third

computation *) n * r in (* Returned value *) ;;val factorial : int -> int = <fun># factorial 5;;- : int = 120

Page 41: Programming Languages and Compilers (CS 421)

04/20/23 45

Recursive Functions

# let rec factorialk n k = eqk n 0 (fun b -> (* First computation *) if b then k 1 (* Passed value *) else subk n 1 (* Second computation *) (fun s -> factorialk s (* Third computation *) (fun r -> timesk n r k))) (* Passed value *)val factorialk : int -> int = <fun># factorialk 5 report;;120- : unit = ()

Page 42: Programming Languages and Compilers (CS 421)

04/20/23 46

Recursive Functions

To make recursive call, must build intermediate continuation to take recursive value: r build it to final result: n * r And pass it to final continuation: times n r k = k (n * r)

Page 43: Programming Languages and Compilers (CS 421)

Example: CPS for length

let rec length list = match list with [] -> 0 | (a :: bs) -> 1 + length bsWhat is the let-expanded version of this?

04/20/23 47

Page 44: Programming Languages and Compilers (CS 421)

Example: CPS for length

let rec length list = match list with [] -> 0 | (a :: bs) -> 1 + length bsWhat is the let-expanded version of this?let rec length list = match list with [] -> 0 | (a :: bs) -> let r1 = length bs in 1 + r1

04/20/23 48

Page 45: Programming Languages and Compilers (CS 421)

Example: CPS for length

#let rec length list = match list with [] -> 0 | (a :: bs) -> let r1 = length bs in 1 + r1What is the CSP version of this?

04/20/23 49

Page 46: Programming Languages and Compilers (CS 421)

Example: CPS for length

#let rec length list = match list with [] -> 0 | (a :: bs) -> let r1 = length bs in 1 + r1What is the CSP version of this?#let rec lengthk list k = match list with [ ] -> k 0 | x :: xs -> lengthk xs (fun r -> addk r 1 k);;val lengthk : 'a list -> (int -> 'b) -> 'b = <fun># lengthk [2;4;6;8] report;;4- : unit = ()

04/20/23 50

Page 47: Programming Languages and Compilers (CS 421)

CPS for Higher Order Functions

In CPS, every procedure / function takes a continuation to receive its result

Procedures passed as arguments take continuations

Procedures returned as results take continuations

CPS version of higher-order functions must expect input procedures to take continuations

04/20/23 52

Page 48: Programming Languages and Compilers (CS 421)

Example: all

#let rec all p l = match l with [] -> true | (x :: xs) -> let b = p x in if b then all p xs else falseval all : ('a -> bool) -> 'a list -> bool = <fun>What is the CPS version of this?

04/20/23 53

Page 49: Programming Languages and Compilers (CS 421)

Example: all

#let rec all p l = match l with [] -> true

| (x :: xs) -> let b = p x in if b then all p xs else falseval all : ('a -> bool) -> 'a list -> bool = <fun>What is the CPS version of this?#let rec allk pk l k =

04/20/23 54

Page 50: Programming Languages and Compilers (CS 421)

Example: all

#let rec all p l = match l with [] -> true

| (x :: xs) -> let b = p x in if b then all p xs else falseval all : ('a -> bool) -> 'a list -> bool = <fun>What is the CPS version of this?#let rec allk pk l k = match l with [] -> true

04/20/23 55

Page 51: Programming Languages and Compilers (CS 421)

Example: all

#let rec all p l = match l with [] -> true

| (x :: xs) -> let b = p x in if b then all p xs else falseval all : ('a -> bool) -> 'a list -> bool = <fun>What is the CPS version of this?#let rec allk pk l k = match l with [] -> k true

04/20/23 56

Page 52: Programming Languages and Compilers (CS 421)

Example: all

#let rec all p l = match l with [] -> true | (x :: xs) -> let b = p x in if b then all p xs else falseval all : ('a -> bool) -> 'a list -> bool = <fun>What is the CPS version of this?#let rec allk pk l k = match l with [] -> k true | (x :: xs) -> pk x (fun b -> if b then allk pk xs k else k false)val allk : ('a -> (bool -> 'b) -> 'b) -> 'a list -> (bool -> 'b) -> 'b = <fun>04/20/23 57

Page 53: Programming Languages and Compilers (CS 421)

Example: all

#let rec all p l = match l with [] -> true | (x :: xs) -> let b = p x in if b then all p xs else falseval all : ('a -> bool) -> 'a list -> bool = <fun>What is the CPS version of this?#let rec allk pk l k = match l with [] -> k true | (x :: xs) -> pk x (fun b -> if b then allk pk xs k else k false)val allk : ('a -> (bool -> 'b) -> 'b) -> 'a list -> (bool -> 'b) -> 'b = <fun>04/20/23 58

Page 54: Programming Languages and Compilers (CS 421)

Example: all

#let rec all p l = match l with [] -> true | (x :: xs) -> let b = p x in if b then all p xs else falseval all : ('a -> bool) -> 'a list -> bool = <fun>What is the CPS version of this?#let rec allk pk l k = match l with [] -> k true | (x :: xs) -> pk x (fun b -> if b then allk pk xs k else k false)val allk : ('a -> (bool -> 'b) -> 'b) -> 'a list -> (bool -> 'b) -> 'b = <fun>04/20/23 59

Page 55: Programming Languages and Compilers (CS 421)

Example: all

#let rec all p l = match l with [] -> true | (x :: xs) -> let b = p x in if b then all p xs else falseval all : ('a -> bool) -> 'a list -> bool = <fun>What is the CPS version of this?#let rec allk pk l k = match l with [] -> k true | (x :: xs) -> pk x (fun b -> if b then allk pk xs k else k false)val allk : ('a -> (bool -> 'b) -> 'b) -> 'a list -> (bool -> 'b) -> 'b = <fun>04/20/23 60

Page 56: Programming Languages and Compilers (CS 421)

04/20/23 62

Terminology

Tail Position: A subexpression s of expressions e, such that if evaluated, will be taken as the value of e if (x>3) then x + 2 else x - 4 let x = 5 in x + 4

Tail Call: A function call that occurs in tail position if (h x) then f x else (x + g x)

Page 57: Programming Languages and Compilers (CS 421)

04/20/23 63

Terminology

Available: A function call that can be executed by the current expression

The fastest way to be unavailable is to be guarded by an abstraction (anonymous function, lambda lifted). if (h x) then f x else (x + g x) if (h x) then (fun x -> f x) else (g (x + x))

Not available

Page 58: Programming Languages and Compilers (CS 421)

04/20/23 64

CPS Transformation

Step 1: Add continuation argument to any function definition: let f arg = e let f arg k = e Idea: Every function takes an extra

parameter saying where the result goes Step 2: A simple expression in tail position

should be passed to a continuation instead of returned: return a k a Assuming a is a constant or variable. “Simple” = “No available function calls.”

Page 59: Programming Languages and Compilers (CS 421)

04/20/23 65

CPS Transformation

Step 3: Pass the current continuation to every function call in tail position return f arg f arg k The function “isn’t going to return,” so we

need to tell it where to put the result.

Page 60: Programming Languages and Compilers (CS 421)

CPS Transformation

Step 4: Each function call not in tail position needs to be converted to take a new continuation (containing the old continuation as appropriate) return op (f arg) f arg (fun r -> k(op r)) op represents a primitive operation

return f(g arg) g arg (fun r-> f r k)

04/20/23 66

Page 61: Programming Languages and Compilers (CS 421)

04/20/23 67

Example

Before:let rec add_list lst =match lst with [ ] -> 0| 0 :: xs -> add_list

xs| x :: xs -> (+) x

(add_list xs);;

After:let rec add_listk lst k = (* rule 1 *)match lst with| [ ] -> k 0 (* rule 2 *)| 0 :: xs -> add_listk xs k (* rule 3 *)| x :: xs -> add_listk xs (fun r -> k ((+) x r));; (* rule 4 *)