6.S050
Created: 2023-05-11 Thu 11:06
while
, for
, if
, function callsgoto
?break
to IMP
: Original (big-step) semanticsEvaluation relations:
break
to IMP
break
to IMP
Evaluation relations:
break
to IMP
break
to IMP
: What about the other rules?Everything else needs to change…
Now try adding continue
…
setjmp=/=longjmp
)goto
Control transfers to something other than the next statement
Explicit representation of the "rest" of a computation
Represent continuation explicitly as parameter \(k\)
let rec fact n =
if n = 0 then 1 else n * (fact (n - 1))
let rec fact_cps n k =
if n = 0
then k 1
else fact_cps (n - 1) (fun x -> k (n * x))
type tree = Leaf of int | Node of tree * tree
let rec sum = function
| Leaf x -> x
| Node (t, t') -> sum t + sum t'
let rec height = function
| Leaf _ -> 0
| Node (t, t') -> 1 + (max (height t) + (height t'))
let rec sum_times_height t = sum t * height t
Can we do this in one pass over the tree?
type tree = Leaf of int | Node of tree * tree
let sum_times_height t =
let rec inner t = match t with
| Leaf x -> (0, x)
| Node (t, t') ->
let (s, h) = inner t in
let (s', h') = inner t' in
(s + s', 1 + (max h h'))
in
let (s, h) = inner t in
s * h
What if the tree is very tall? Should we worry about overflowing the stack?
type tree = Leaf of int | Node of tree * tree
let sum_times_height t =
let rec inner t k = match t with
| Leaf x -> k 0 x
| Node (t, t') ->
inner t (fun s h ->
inner t' (fun s' h' ->
k (s + s') (1 + (max h h'))))
in
inner t (fun s h -> s * h)
Translate this function to CPS
let rec fib n = match n with
| 0 -> 0
| 1 -> 1
| n -> fib (n - 1) + fib (n - 2)
Solution:
let rec fib n = match n with
| 0 -> 0
| 1 -> 1
| n -> fib (n - 1) + fib (n - 2)
let rec fib_cps n k = match n with
| 0 -> k 0
| 1 -> k 1
| n -> fib (n - 1) (fun x ->
fib (n - 2) (fun x' ->
k (x + x')))
(Similar to early returns in imperative languages.)
type tree = Leaf of int | Node of tree * tree
let rec tree_product t = match t with
| Leaf x -> x
| Node (t, t') -> (tree_product t) * (tree_product t')
What if a leaf is zero? Can we avoid doing the rest of the work?
First translate to CPS
type tree = Leaf of int | Node of tree * tree
let rec tree_product t k = match t with
| Leaf x -> k x
| Node (t, t') ->
tree_product t (fun x ->
tree_product t' (fun x' -> k (x * x')))
Separate the "early return" continuation from "keep processing" continuation
type tree = Leaf of int | Node of tree * tree
let tree_product t k_early_return =
let rec prod t k =
match t with
| Leaf 0 -> k_early_return 0
| Leaf x -> k x
| Node (t, t') ->
tree_product t (fun x ->
tree_product t' (fun x' -> k (x * x')))
in
prod t k_early_return
Note that this will "return" from multiple nested calls
CPS conversion can be done automatically: