type safety and exception handling
play

Type safety and exception handling Gabriele Keller Ron - PowerPoint PPT Presentation

Concepts of Program Design Type safety and exception handling Gabriele Keller Ron Vanderfeesten Overview higher & first-order syntax inference rules, induction tools to talk about languages abstract machines big step and small step


  1. Concepts of Program Design Type safety and exception handling Gabriele Keller Ron Vanderfeesten

  2. Overview higher & first-order syntax inference rules, induction tools to talk about languages abstract machines big step and small step operational semantics λ -calculus and de Bruijn indices value & type environments parametric polymorphism/ generics type safety control stacks error/exception handling semantic features partial application/function closures functional (algebraic) data types static & dynamic static & dynamic typing scoping language concepts explicit & implicit explicit & implicit procedural/imperative typing typing

  3. Types in programming languages statically vs dynamically typed type safe vs non type safe strongly vs weakly typed

  4. Static and Dynamic Semantics • MinHs (as discussed in the lecture) is a type-safe (or strongly typed) language • What exactly do we mean by this? - these terms are used by different authors to mean different things - in general, it refers to guarantees about the run-time behaviour derived from static properties of the program - Robin Milner: “ Well typed programs never go wrong ” ‣ do not exhibit undefined behaviour - we define type safety to be the following two properties: ‣ preservation ‣ progress - we look at both preservation and progress in turn

  5. Preservation and Progress • Preservation: - Idea: evaluation does not change the type of an expression - Formally: If ⊢ e : τ and e ↦ e’ , then ⊢ e’ : τ • Progress: - Idea: a well-defined program can not get stuck - Formally: If e is well typed, then either e is a final state, or there exists e’ , with e ↦ e’ e 1 : τ ↦ e 2 : τ ↦ e 3 : τ ↦ … • Together is means that a program will either evaluate to a value of the promised type, or run forever

  6. Type Safety • For any language to be type safe, the progress and preservation properties need to hold! • Strictly speaking, the term type safety only makes sense in the context of a formal static and dynamic semantics • This is one reason why formal methods in programming languages are essential • The more expressive a type system is, the more information and assertions the type checker can derive at compile type - type systems usually should be decidable - but there are exceptions • MinHs is type safe - we can show that progress and preservation hold! - but what if the language contains partial operations, like division?

  7. Run-time Errors and Safety • Stuck states: in a type safe language language, stuck states correspond to ill- defined programs, e.g., - use (+) on values of function type, for example - treat an integer value as a pointer - use an integer as function let x = 1 in x 5 • Unsafe languages/operations do not get stuck - something happens, but its not predictable and/or portable: void boom () { void (f*)(void) = 0xdeadbeef; f (); }

  8. Type safe languages • Which of these languages are type safe? - C - C++ - C# - Haskell - Python - Rust

  9. Run-time Errors and Safety • How can we deal with partial functions, for example division by zero? Γ ⊢ t 1 : Int Γ ⊢ t 2 : Int Γ ⊢ Div t 1 t 2 : Int Problem: the expression 5/0 is well-typed, but does not evaluate to a value. • There are two alternatives: (1) Change static semantics: can we enhance the type system to check for division by zero? ‣ in general, such a type system would not be decidable ‣ there exist systems that approximate this (2) Change dynamic semantics: can we modify the semantics such that the devision by zero does not lead to a stuck state ‣ this approach is widely used for type safe languages

  10. Run-time Errors and Safety • Application of a partial function can yield Error Div v (Num 0) ↦ Error • An Error interrupts any computation Plus Error e ↦ Error Plus e Error ↦ Error If Error e 1 e 2 ↦ Error and so on.....

  11. Run-time errors and Safety • Typing the Error value : - a run-time error can have any type Γ ⊢ Error : ∀ τ. τ • What type of situations lead to checked run-time errors in Haskell?

  12. Exceptions • Error handling so far: - The Error expression to handle run-time errors deterministically aborts the whole program - For many applications, this is not the appropriate behaviour - Exceptions permit a more fine grained response to run-time errors • Error: - result of a programming error (e.g., preconditions of a function not met), can be fixed by fixing the program • Exception: - result of expected, but irregular occurrence, can possibly be handled in the program

  13. Exceptions • Exceptions in MinHs: (1) raising (or throwing) an exception: raise e ‣ e : information about handling of exception (2) catching an exception: try e 1 handle x => e 2 ‣ catch expression raised in e 1 ‣ exception handler is e 2 ‣ access to information about handling exception via x

  14. Exceptions • Abstract Syntax ‣ raise e Raise e ‣ try e 1 handle x => e 2 Try e 1 ( x .e 2 ) • Informal evaluation rules: on try e 1 handle x => e 2 ‣ evaluate e 1 , and ‣ if (Raise v ) is encountered during e 1 , bind x to v and then evaluate e 2

  15. Exceptions • Example: try if (y <= 0) then raise -1 else x/y handle err => .... • try expressions can be nested ‣ innermost try expression catches ‣ handler may re-raise an exception

  16. Exceptions • Observations: - type of exception values (second argument of raise) • in many programming languages, this is a fixed type τ exc • may simply be a string or integer (exception code) • e.g., subclass Throwable in Java

  17. Exceptions - Static Semantics • Typing rules Γ ⊢ e : τ exc Γ ⊢ Raise e: ∀ τ. τ Γ ∪ { x : τ exc } ⊢ e 2 : τ Γ ⊢ e 1 : τ τ Γ ⊢ Try e 1, ( x .e 2 ):

  18. Exceptions - Dynamic Semantics • We introduce a new machines state s ⪻ (Raise v ) the machine raises an exception with the exception value v • First approach: on s ⪻ (Raise v ) ‣ propagate exception upwards in the control stack s ‣ use first handler encountered

  19. Exceptions - Dynamic Semantics • Entering a try block s ≻ Try e 1 ( x . e 2 ) ↦ C (Try ☐ ( x . e 2 ) ▷ s ) ≻ e 1 • Returning to a try block ↦ C s ≺ v 1 (Try ☐ ( x . e 2 ) ▷ s ≻ v 1 • Evaluating a raise expression s ≻ Raise e ↦ C (Raise ☐ ) ▷ s ≻ e • Raising an exception (Raise ☐ ) ▷ s ≻ v ↦ C s ⪻ Raise v • Catching an exception ↦ C s ≻ e 2 [ x:=v] Try ☐ x . e 2 ▷ s ⪻ Raise v • Propagating an exception f ▷ s ⪻ Raise v ↦ C s ⪻ Raise v

  20. Exceptions - Dynamic Semantics • What is the problem here? - efficiency: the frames are popped one by one when an exception is raised • Second approach - how can we jump directly to the appropriate handler? - we use an extra handler stack h - a handler frame contains ‣ a copy of the control stack ‣ the handler expression

  21. Exceptions - Dynamic Semantics • Entering a try block ( h, k ) ≻ Try e 1 ( x . e 2 ) ↦ C (Handle k ( x . e 2 ) ▷ h ,(Try ☐ ) ▷ k ) ≻ e 1 • Returning to a try block (Handle k ( x . e 2 ) ▷ h,(Try ☐ ) ▷ k ) ≺ v 1 ↦ C ( h, k ) ≺ v 1 • Evaluating a raise expression ( h, k ) ≻ ( Raise e ) ↦ C ( h , ( Raise ☐ ) ▷ k) ≻ e • Raising an exception ( h , (Raise ☐ ) ▷ k) ≻ v ↦ C ( h, k ) ⪻ (Raise v ) • Catching an exception (handle k’ (x . e 2 )) ▷ h , k ) ⪻ (Raise v ) ↦ C ( h, k’ ) ≻ e 2 [ x:=v]

Recommend


More recommend