# COMPILING EXCEPTIONS CORRECTLY Graham Hutton and Joel Wright University of Nottingham

• View
215

2

Embed Size (px)

### Text of COMPILING EXCEPTIONS CORRECTLY Graham Hutton and Joel Wright University of Nottingham

• 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.

• This TalkMost 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.

• Step 1 - Arithmetic Expressionsdata Expr = Val Int | Add Expr Expreval :: Expr Inteval (Val n) = neval (Add x y) = eval x + eval ySyntax:Semantics:

• type Stack = [Int]

data Op = PUSH Int | ADD

type Code = [Op]comp :: Expr Codecomp (Val n) = [PUSH n]comp (Add x y) = comp x ++ comp y ++ [ADD]Virtual machine:Compiler:

• Compiler Correctnessexec s (comp e) = eval e : sTheorem:

• 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

• Step 2 - Adding Exceptionseval :: Expr Maybe Inteval (Val n) = Just neval (Throw) = Nothingeval (Add x y) = eval x eval yeval (Catch x h) = eval x eval hdata Expr = | Throw | Catch Expr ExprSyntax:Semantics:

• Add (Val 1) (Val 2)Add Throw (Val 2)Catch (Val 1) (Val 2)Catch Throw (Val 2)Just 3NothingJust 1Just 2evalevalevalevalExamples:

• data Op = | THROW | MARK Code | UNMARK

type Stack = [Item]

data Item = VAL Int | HAN Codecomp (Throw) = [THROW]comp (Catch x h) = [MARK (comp h)] ++ comp x ++ [UNMARK]Virtual machine:Compiler:

• How Is THROW Executed?Informally, we must:Unwind the stack seeking a handler;

Execute the first handler found, if any;

• skip :: Code Codeskip [] = []skip (UNMARK : ops) = opsskip (MARK h : ops) = skip (skip ops)skip (op : ops) = skip opsunwind :: Stack Code Stackunwind [] ops = []unwind (VAL n : s) ops = unwind s opsunwind (HAN h : s) ops = exec s (h ++ skip ops)Implementation:

• Example1 + (catch (2 + throw) 3)StackCode

• Example1 + (catch (2 + throw) 3)PUSH 1MARK [PUSH 3]PUSH 2THROWADDUNMARKADDStackCode

• Example1 + (catch (2 + throw) 3)MARK [PUSH 3]PUSH 2THROWADDUNMARKADDStackCodeVAL 1

• Example1 + (catch (2 + throw) 3)PUSH 2THROWADDUNMARKADDStackCodeHAN [PUSH 3]VAL 1

• Example1 + (catch (2 + throw) 3)THROWADDUNMARKADDStackCodeVAL 2HAN [PUSH 3]VAL 1

• Example1 + (catch (2 + throw) 3)PUSH 3THROW ADD UNMARK ADD StackCodeVAL 1

• Example1 + (catch (2 + throw) 3)THROW ADD UNMARK ADD StackCodeVAL 3VAL 1

• Example1 + (catch (2 + throw) 3)ADD UNMARK ADD StackCodeVAL 3VAL 1

• Example1 + (catch (2 + throw) 3)UNMARK ADD StackCodeVAL 3VAL 1

• Example1 + (catch (2 + throw) 3)ADD StackCodeVAL 3VAL 1

• Example1 + (catch (2 + throw) 3)StackCodeVAL 4

• Compiler CorrectnessExprMaybe IntCodeStackevalexec []compconvconv Nothing = []conv (Just n) = [VAL n]where

• 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 nwhere

• Proof: by induction, using a skipping lemma:skip (comp e ++ ops) = skip opsNotes:The proof is 3.5 pages of simple calculation;

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

• Step 3 - Adding Jumps MARK a code for x UNMARK JUMP ba: code for hb: remaining codeCatch x his now compiled toBasic idea:See the paper for further details.

• SummaryExplanation and verification of the compilation of exceptions using stack unwinding.

Stepwise development to aid understanding:1 - Arithmetic expressions; 