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

type safety and exception handling
SMART_READER_LITE
LIVE PREVIEW

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


slide-1
SLIDE 1

Concepts of Program Design

Type safety and exception handling

Gabriele Keller Ron Vanderfeesten

slide-2
SLIDE 2

Overview

semantic features tools to talk about languages

static & dynamic scoping static & dynamic typing explicit & implicit typing

language concepts

functional procedural/imperative higher & first-order syntax big step and small step operational semantics abstract machines λ-calculus and de Bruijn indices inference rules, induction (algebraic) data types partial application/function closures value & type environments control stacks parametric polymorphism/ generics explicit & implicit typing

type safety

error/exception handling

slide-3
SLIDE 3

Types in programming languages

statically vs dynamically typed strongly vs weakly typed type safe vs non type safe

slide-4
SLIDE 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
slide-5
SLIDE 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’

  • Together is means that a program will either evaluate to a value of the

promised type, or run forever

e1 : τ ↦ e2 : τ ↦ e3 : τ ↦ …

slide-6
SLIDE 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?
slide-7
SLIDE 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 (); }

slide-8
SLIDE 8

Type safe languages

  • Which of these languages are type safe?
  • C
  • C++
  • C#
  • Haskell
  • Python
  • Rust
slide-9
SLIDE 9

Run-time Errors and Safety

  • How can we deal with partial functions, for example division by zero?

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

Γ ⊢ t1 : Int Γ ⊢ t2 : Int Γ ⊢ Div t1 t2 : Int

slide-10
SLIDE 10

Run-time Errors and Safety

  • Application of a partial function can yield Error
  • An Error interrupts any computation

Div v (Num 0) ↦ Error Plus Error e ↦ Error Plus e Error ↦ Error If Error e1 e2 ↦ Error

and so on.....

slide-11
SLIDE 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?
slide-12
SLIDE 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

slide-13
SLIDE 13

Exceptions

  • Exceptions in MinHs:

(1) raising (or throwing) an exception: raise e

  • e : information about handling of exception

(2) catching an exception: try e1 handle x => e2

  • catch expression raised in e1
  • exception handler is e2
  • access to information about handling exception via x
slide-14
SLIDE 14

Exceptions

  • Abstract Syntax
  • raise e Raise e
  • try e1 handle x => e2 Try e1 (x.e2)
  • Informal evaluation rules: on try e1 handle x => e2
  • evaluate e1, and
  • if (Raise v) is encountered during e1, bind x to v and then evaluate e2
slide-15
SLIDE 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
slide-16
SLIDE 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
slide-17
SLIDE 17

Exceptions - Static Semantics

  • Typing rules

Γ ⊢ Raise e: Γ ⊢ e1: τ Γ∪ {x : τexc} ⊢ e2 :τ Γ ⊢ Try e1, (x.e2):

∀ τ. τ

Γ ⊢ e : τexc τ

slide-18
SLIDE 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:
  • n s ⪻ (Raise v)
  • propagate exception upwards in the control stack s
  • use first handler encountered
slide-19
SLIDE 19

Exceptions - Dynamic Semantics

  • Entering a try block
  • Returning to a try block
  • Evaluating a raise expression
  • Raising an exception
  • Catching an exception
  • Propagating an exception

f ▷ s ⪻ Raise v s ≻ Try e1(x.e2) (Raise ☐) ▷s ≻ v s ≻ Raise e (Try ☐ (x.e2) ▷ s ≻ v1 ↦C (Try ☐ (x.e2) ▷ s)≻ e1

↦C (Raise ☐) ▷ s ≻ e

↦C s ≺ v1 ↦C s ≻ e2 [x:=v] Try ☐ x.e2 ▷ s ⪻ Raise v ↦C s ⪻ Raise v ↦C s ⪻ Raise v

slide-20
SLIDE 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
slide-21
SLIDE 21

Exceptions - Dynamic Semantics

  • Entering a try block
  • Returning to a try block
  • Evaluating a raise expression
  • Raising an exception
  • Catching an exception

(h, k) ≻ Try e1 (x.e2) ↦C (h, k) ≺ v1 (h, k) ≻(Raise e) ↦C

(h, k) ⪻ (Raise v)

(h, k’) ≻ e2 [x:=v] (handle k’ (x.e2))▷ h, k) ⪻ (Raise v) ↦C (Handle k (x.e2) ▷ h,(Try ☐ )▷ k) ≻ e1 (Handle k (x.e2) ▷ h,(Try ☐) ▷ k) ≺ v1 ↦C

( h, (Raise ☐) ▷ k) ≻ e ( h, (Raise ☐) ▷ k) ≻ v ↦C