Transcript

COMPILING EXCEPTIONSCORRECTLY

Graham Hutton and Joel WrightUniversity of Nottingham

2

What Is An Exception?

Division by zero;

Stack overflow;

Null pointer.

Examples:

An event within a computation that causes termination in a non-standard

way.

3

This Talk

Most modern languages support programming with exceptions, e.g. using throw and catch;

The compilation of such exception primitives is traditionally viewed as an advanced topic;

We give a simple explanation and verification, using elementary functional techniques.

4

Step 1 - Arithmetic Expressions

data Expr = Val Int | Add Expr Expr

eval :: Expr Inteval (Val n) = neval (Add x y) = eval x + eval y

Syntax:

Semantics:

5

type Stack = [Int]

data Op = PUSH Int | ADD

type Code = [Op]

comp :: Expr Code

comp (Val n) = [PUSH n]

comp (Add x y) = comp x ++ comp y ++ [ADD]

Virtual machine:

Compiler:

6

Compiler Correctness

Expr Int

Code Stack

eval

exec []

comp []

exec s (comp e) = eval e : s

Theorem:

7

Proof: by induction, using a distribution lemma:

However, we can avoid this lemma and shorten the proof by 60% by generalising the theorem:

exec s (comp e ++ ops)= exec (eval e : s) ops

exec s (xs ++ ys)= exec (exec s xs) ys

8

eval :: Expr Maybe Inteval (Val n) = Just neval (Throw) = Nothingeval (Add x y) = eval x eval yeval (Catch x h) = eval x eval h

Step 2 - Adding Exceptions

data Expr = ••• | Throw | Catch Expr Expr

Syntax:

Semantics:

9

Add (Val 1) (Val 2)

Add Throw (Val 2)

Catch (Val 1) (Val 2)

Catch Throw (Val 2)

Just 3

Nothing

Just 1

Just 2

eval

eval

eval

eval

Examples:

10

data Op = ••• | THROW | MARK Code | UNMARK

type Stack = [Item]

data Item = VAL Int | HAN Code

comp (Throw) = [THROW]

comp (Catch x h) =

[MARK (comp h)] ++ comp x ++ [UNMARK]

Virtual machine:

Compiler:

11

How Is THROW Executed?

Informally, we must:

Unwind the stack seeking a handler;

Execute the first handler found, if any;

Skip to the next part of the computation.

12

skip :: Code Codeskip [] = []skip (UNMARK : ops) = opsskip (MARK h : ops) = skip (skip ops)skip (op : ops) = skip ops

unwind :: Stack Code Stackunwind [] ops = []unwind (VAL n : s) ops = unwind s opsunwind (HAN h : s) ops = exec s (h ++ skip ops)

Implementation:

13

1 + (catch (2 + throw) 3)

Example

Stack

Code

14

1 + (catch (2 + throw) 3)

Example

PUSH 1MARK [PUSH 3]PUSH 2THROWADDUNMARKADD

Stack

Code

15

1 + (catch (2 + throw) 3)

Example

MARK [PUSH 3]PUSH 2THROWADDUNMARKADD

Stack

Code

VAL 1

16

1 + (catch (2 + throw) 3)

Example

PUSH 2THROWADDUNMARKADD

Stack

Code

HAN [PUSH 3]VAL 1

17

1 + (catch (2 + throw) 3)

Example

THROWADDUNMARKADD

Stack

Code

VAL 2HAN [PUSH 3]VAL 1

18

1 + (catch (2 + throw) 3)

Example

THROWADDUNMARKADD

Stack

Code

HAN [PUSH 3]VAL 1

19

1 + (catch (2 + throw) 3)

Example

PUSH 3THROW ADD UNMARK ADD

Stack

Code

VAL 1

20

1 + (catch (2 + throw) 3)

Example

THROW ADD UNMARK ADD

Stack

Code

VAL 3VAL 1

21

1 + (catch (2 + throw) 3)

Example

ADD UNMARK ADD

Stack

Code

VAL 3VAL 1

22

1 + (catch (2 + throw) 3)

Example

UNMARK ADD

Stack

Code

VAL 3VAL 1

23

1 + (catch (2 + throw) 3)

Example

ADD

Stack

Code

VAL 3VAL 1

24

1 + (catch (2 + throw) 3)

Example

Stack

Code

VAL 4

25

Compiler Correctness

Expr Maybe Int

Code Stack

eval

exec []

comp conv

conv Nothing = []conv (Just n) = [VAL n]

where

26

As previously, we generalise to an arbitrary initial stack and arbitrary additional code.

Theorem:

exec s (comp e ++ ops)= exec s (trans (eval e) : ops)

trans :: Maybe Int Optrans Nothing = THROWtrans (Just n) = PUSH n

where

27

Proof: by induction, using a skipping lemma:

skip (comp e ++ ops) = skip ops

Notes:

The proof is 3.5 pages of simple calculation;

The quickcheck tool was very useful as an aid to simplifying the definitions and results.

28

Step 3 - Adding Jumps

MARK a code for x UNMARK JUMP ba: code for hb: remaining code

Catch x h

is now compiled to

Basic idea:

See the paper for further

details.

29

Summary

Explanation and verification of the compilation of exceptions using stack unwinding.

Stepwise development to aid understanding:

1 - Arithmetic expressions;

2 - Adding exceptions;

3 - Adding jumps.

30

Further Work

Mechanical verification;

Modular compilers;

Calculating the compiler;

Generalising the language;

Compiler optimisations.