480 likes | 638 Views
What Is An Exception?. An event within a computation that causes termination in a non-standard way. Examples:. Division by zero Null pointer. What Is An Interrupt?. An exception that arises from the external environement, e.g. another computation. Examples:. Terminate Any exception.
E N D
What Is An Exception? An event within a computation that causes termination in a non-standard way Examples: • Division by zero • Null pointer
What Is An Interrupt? An exception that arises from the external environement, e.g. another computation Examples: • Terminate • Any exception
This Talk • Haskell is unique in providing both full support for interrupts and a semantics for this. • But the semantics is subtle, and relies on quite considerable technical machinery. • We give a simple, formally justified, semantics for interrupts in a small language.
An Exceptional Language Syntax: data Expr = Val Int | Throw | Add Expr Expr | Seq Expr Expr | Catch Expr Expr Semantics: e can evaluate to v e v
x Throw x Val n y v Seq x y v Seq x y Throw x Throw y v x Val n Catch x y Val n Catch x y v Sequencing: Catch:
Finally, An Example Problem: how can we ensure that evaluation of x is always succeeded by evaluation of y? finally x y =
Finally, An Example Problem: how can we ensure that evaluation of x is always succeeded by evaluation of y? finally x y = Seq x y
Finally, An Example Problem: how can we ensure that evaluation of x is always succeeded by evaluation of y? finally x y = If x produces an exception, y is not evaluated Seq x y
Finally, An Example Problem: how can we ensure that evaluation of x is always succeeded by evaluation of y? finally x y = Seq (Catch x y) y
Finally, An Example Problem: how can we ensure that evaluation of x is always succeeded by evaluation of y? If x produces an exception, y may be evaluated twice finally x y = Seq (Catch x y) y
Finally, An Example Problem: how can we ensure that evaluation of x is always succeeded by evaluation of y? finally x y = Seq (Catch x (Seq y Throw)) y
Finally, An Example Problem: how can we ensure that evaluation of x is always succeeded by evaluation of y? finally x y Now has the correct behaviour = Seq (Catch x (Seq y Throw)) y
x Throw Adding Interrupts To avoid the need for concurrency, we adopt the following worst-case rule for interrupts: Evaluation can be interrupted at any time by replacing the current expression by throw
Note: • Evaluation is now non-deterministic. • Finally no longer behaves as expected. Seq (Catch x (Seq y Throw)) y could be interrupted as y is about to be evaluated
Controlling Interrupts Syntax: data Expr = ••• | Block Expr | Unblock Expr Semantics: e can evaluate to v in interrupt status i e iv
x U Throw x U v x B v Unblock x i v Block x i v Key rules: The other rules are simply modified to propogate the current interrupt status to their arguments.
Finally Revisited finally x y = Seq (Catch x (Seq y Throw)) y
Finally Revisited finally x y = Block (Seq (Catch (Unblock x) (Seq y Throw)) y)
Finally Revisited finally x y = Block (Seq (Catch (Unblock x) (Seq y Throw)) y) Modulo syntax, finally in Haskell is defined in precisely the same way
Is Our Semantics Correct? • How does our high-level semantics reflect our low-level intuition about interrupts? • To address this issue, we first define a virtual machine, its semantics, and a compiler. • We explain the basic ideas informally using an example - the paper gives full details.
Example Catch (Unblock (2+3)) 4 Code
Example Catch (Unblock (2+3)) 4 Code
Example Catch (Unblock (2+3)) 4 Code MARK [ ] UNMARK
Example Catch (Unblock (2+3)) 4 Code MARK [ ] UNMARK
Example Catch (Unblock (2+3)) 4 Code MARK [PUSH 4] UNMARK
Example Catch (Unblock (2+3)) 4 Code MARK [PUSH 4] UNMARK
Example Catch (Unblock (2+3)) 4 Code MARK [PUSH 4] SET U RESET UNMARK
Example Catch (Unblock (2+3)) 4 Code MARK [PUSH 4] SET U RESET UNMARK
Example Catch (Unblock (2+3)) 4 Code MARK [PUSH 4] SET U PUSH 2 PUSH 3 ADD RESET UNMARK
Example Catch (Unblock (2+3)) 4 Code Status Stack MARK [PUSH 4] SET U PUSH 2 PUSH 3 ADD RESET UNMARK
Example Catch (Unblock (2+3)) 4 Code Status Stack B MARK [PUSH 4] SET U PUSH 2 PUSH 3 ADD RESET UNMARK
Example Catch (Unblock (2+3)) 4 Code Status Stack B SET U PUSH 2 PUSH 3 ADD RESET UNMARK HAN [PUSH 4]
Example Catch (Unblock (2+3)) 4 Code Status Stack U PUSH 2 PUSH 3 ADD RESET UNMARK INT B HAN [PUSH 4]
Example Catch (Unblock (2+3)) 4 Code Status Stack U PUSH 3 ADD RESET UNMARK VAL 2 INT B HAN [PUSH 4]
Example Catch (Unblock (2+3)) 4 Code Status Stack U ADD RESET UNMARK VAL 3 VAL 2 INT B HAN [PUSH 4]
Example Catch (Unblock (2+3)) 4 Code Status Stack U ADD RESET UNMARK VAL 3 VAL 2 INT B HAN [PUSH 4] interrupt!
Example Catch (Unblock (2+3)) 4 Code Status Stack U THROW RESET UNMARK VAL 3 VAL 2 INT B HAN [PUSH 4] interrupt!
Example Catch (Unblock (2+3)) 4 Code Status Stack U THROW RESET UNMARK VAL 2 INT B HAN [PUSH 4]
Example Catch (Unblock (2+3)) 4 Code Status Stack U THROW RESET UNMARK INT B HAN [PUSH 4]
Example Catch (Unblock (2+3)) 4 Code Status Stack B THROW RESET UNMARK HAN [PUSH 4]
Example Catch (Unblock (2+3)) 4 Code Status Stack B PUSH 4
Example Catch (Unblock (2+3)) 4 Code Status Stack B VAL 4
Example Catch (Unblock (2+3)) 4 Code Status Stack B VAL 4 Final result
Compiler Correctness We will exploit two basic notions of reachability for configurations of our virtual machine. x * Y x can reach everything in Y x Y x will reach something in Y
* Theorem comp e c i s U { | e i Val n } c i VAL n : s { | e i Throw } i s Proof: approximately 10 pages of calculation, much of which requires considerable care.
Summary • Simple semantics for interrupts, formally justified by a compiler correctness theorem. • Discovery of an error in the semantics for Haskell, concerning the delivery of interrupts. • Verification of finally, a useful high-level operator for programming with exceptions/interrupts.
Further Work • Mechanical verification • Bisimulation theorem • Generalising the language • Reasoning about programs • Calculating the compiler