POPL Tutorial/Exceptions

From The Twelf Project
Jump to: navigation, search
This is Literate Twelf
Code: here
Status: %% OK %%
Output: here.

Type safety for MinML: call-by-value, with recursive functions, in extrinsic form, with exceptions

Syntax

Types:

tp : type.				%name tp T.
nat : tp.
arr : tp -> tp -> tp.

Raw expressions, which admit ill-typed terms

exp : type.				%name exp E.
z : exp.
s : exp -> exp.
ifz : exp -> exp -> (exp -> exp) -> exp.
fun : tp -> tp -> (exp -> exp -> exp) -> exp.
app : exp -> exp -> exp.
raise : tp -> exp.
handle : exp -> exp -> exp.

Static semantics

A judgement picking out the well-typed terms:

of : exp -> tp -> type.			%name of Dof.
%mode of +E -T.

of/z
   : of z nat.
of/s
   : of (s E) nat <- of E nat.
of/ifz
   : of (ifz E E1 ([x] E2 x)) T
      <- of E nat
      <- of E1 T
      <- ({x:exp} of x nat -> of (E2 x) T).
of/fun
   : of (fun T1 T2 ([f] [x] E f x)) (arr T1 T2)
      <- ({f:exp} of f (arr T1 T2) -> {x:exp} of x T1 -> of (E f x) T2).
of/app
   : of (app E1 E2) T
      <- of E1 (arr T2 T)
      <- of E2 T2.
of/raise
   : of (raise T) T.
of/handle
   : of (handle E1 E2) T
      <- of E1 T
      <- of E2 T.

Dynamic semantics

value : exp -> type.			%name value Dval.
%mode value +E.

value/z : value z.
value/s : value (s E) <- value E.
value/fun : value (fun _ _ _).

raises : exp -> type.
%mode raises +E.

raises/raise   
   : raises (raise T).
raises/app/fun
   : raises (app E1 E2)
      <- raises E1.
raises/app/arg
   : raises (app E1 E2)
      <- value E1 
      <- raises E2.
raises/s
   : raises (s E)
      <- raises E.
raises/ifz
   : raises (ifz E1 E2 E3)
      <- raises E1. 

step : exp -> exp -> type.		%name step Dstep.
%mode step +E1 -E2.

step/s
   : step (s E) (s E') <- step E E'.
step/ifz/arg
   : step (ifz E E1 ([x] E2 x)) (ifz E' E1 ([x] E2 x))
      <- step E E'.
step/ifz/z
   : step (ifz z E1 ([x] E2 x)) E1.
step/ifz/s
   : step (ifz (s E) E1 ([x] E2 x)) (E2 E)
      <- value E.
step/app/fun
   : step (app E1 E2) (app E1' E2)
      <- step E1 E1'.
step/app/arg
   : step (app E1 E2) (app E1 E2')
      <- value E1 <- step E2 E2'.
step/app/beta-v
   : step
      (app (fun T1 T2 ([f] [x] E f x)) E2)
      (E (fun T1 T2 ([f] [x] E f x)) E2)
      <- value E2.
step/handle/body
   : step
      (handle E1 E2)
      (handle E1' E2)
      <- step E1 E1'.
step/handle/raise
   : step
      (handle E1 E2)
      E2
      <- raises E1. 
step/handle/body-v
   : step
      (handle E1 E2)
      E1
      <- value E1.

Preservation

With this encoding, we have to prove preservation explicitly, as the type of step doesn't guarantee it.

pres : step E E' -> of E T -> of E' T -> type. %name pres Dpres.
%mode pres +Dstep +Dof -Dof.

- : pres
     (step/s Dstep)
     (of/s Dof)
     (of/s Dof')
     <- pres Dstep Dof Dof'.

- : pres
     (step/ifz/arg Dstep)
     (of/ifz ([x] [dx] Dof2 x dx) Dof1 Dof)
     (of/ifz ([x] [dx] Dof2 x dx) Dof1 Dof')
     <- pres Dstep Dof Dof'.

- : pres
     step/ifz/z
     (of/ifz _ Dof1 _)
     Dof1.

- : pres
     (step/ifz/s (_ : value E))
     (of/ifz ([x] [dx] Dof2 x dx) _ (of/s Dof))
     (Dof2 E Dof).

- : pres
     (step/app/fun Dstep1)
     (of/app Dof2 Dof1)
     (of/app Dof2 Dof1')
     <- pres Dstep1 Dof1 Dof1'.

- : pres
     (step/app/arg Dstep2 _)
     (of/app Dof2 Dof1)
     (of/app Dof2' Dof1)
     <- pres Dstep2 Dof2 Dof2'.

- : pres
     (step/app/beta-v _)
     (of/app
	Dof2
	(of/fun [f] [df] [x] [dx] (Dof1 f df x dx)))
     (Dof1
	_
	(of/fun [f] [df] [x] [dx] (Dof1 f df x dx))
	_
	Dof2).

- : pres 
     (step/handle/body Dstep)
     (of/handle Dof2 Dof1)
     (of/handle Dof2 Dof1')
     <- pres Dstep Dof1 Dof1'.

- : pres
     (step/handle/raise Draise)
     (of/handle Dof2 Dof1)
     Dof2.

- : pres
     (step/handle/body-v Dval)
     (of/handle Dof2 Dof1)
     Dof1.

%worlds () (pres Dstep Dof Dof').
%total Dstep (pres Dstep _ _).

Progress

val-or-raises-or-step : exp -> type.		%name val-or-raises-or-step Dvrs.
vrs/val : val-or-raises-or-step E <- value E.
vrs/step : val-or-raises-or-step E <- step E _.
vrs/raises : val-or-raises-or-step E <- raises E.

Factoring lemmas

prog/s
   : val-or-raises-or-step E -> val-or-raises-or-step (s E) -> type.
%mode prog/s +Dvrs1 -Dvrs2.

- : prog/s
     (vrs/step Dstep)
     (vrs/step (step/s Dstep)).

- : prog/s
     (vrs/val Dval)
     (vrs/val (value/s Dval)).

- : prog/s
     (vrs/raises Draises)
     (vrs/raises (raises/s Draises)).

%worlds () (prog/s _ _).
%total {} (prog/s _ _).

prog/ifz
   :  of E nat
      -> val-or-raises-or-step E
      -> {E1} {E2} (val-or-raises-or-step (ifz E E1 ([x] E2 x)))
      -> type.
%mode prog/ifz +Dof +Dvrs +E1 +E2 -Dstep.

- : prog/ifz _ (vrs/step Dstep) _ _ (vrs/step (step/ifz/arg Dstep)).
- : prog/ifz _ (vrs/val value/z) _ _ (vrs/step step/ifz/z).
- : prog/ifz _ (vrs/val (value/s Dval)) _ _ (vrs/step (step/ifz/s Dval)).
- : prog/ifz _ (vrs/raises Draises) _ _ (vrs/raises (raises/ifz Draises)).
%worlds () (prog/ifz _ _ _ _ _).
%total {} (prog/ifz _ _ _ _ _).

prog/app
   : of E1 (arr T2 T)
      -> val-or-raises-or-step E1
      -> val-or-raises-or-step E2
      -> val-or-raises-or-step (app E1 E2)
      -> type.
%mode prog/app +Dof +Dvrs1 +Dvrs2 -Dstep.

- : prog/app
     _
     (vrs/step Dstep1)
     _
     (vrs/step (step/app/fun Dstep1)).

- : prog/app
     _
     (vrs/val Dval1)
     (vrs/step Dstep2)
     (vrs/step (step/app/arg Dstep2 Dval1)).

- : prog/app
     _
     (vrs/val Dval1)
     (vrs/val Dval2)
     (vrs/step (step/app/beta-v Dval2)).

- : prog/app
     _
     (vrs/raises Draise1)
     _
     (vrs/raises (raises/app/fun Draise1)).

- : prog/app
     _
     (vrs/val Dval1)
     (vrs/raises Draise2)
     (vrs/raises (raises/app/arg Draise2 Dval1)).

%worlds () (prog/app _ _ _ _).
%total {} (prog/app _ _ _ _).

prog/handle
   : val-or-raises-or-step E1
      -> {E2} val-or-raises-or-step (handle E1 E2)
      -> type.
%mode prog/handle +Dvrs1 +E2 -Dvrs2.

- : prog/handle (vrs/val Dval) _
     (vrs/step (step/handle/body-v Dval)).

- : prog/handle (vrs/raises Draise) _
     (vrs/step (step/handle/raise Draise)).

- : prog/handle (vrs/step Dstep) _
     (vrs/step (step/handle/body Dstep)).

%worlds () (prog/handle _ _ _).
%total {} (prog/handle _ _ _).

Main theorem

prog : of E T -> val-or-raises-or-step E -> type. %name prog Dprog.
%mode prog +Dof -Dvrs.

- : prog of/z (vrs/val value/z).

- : prog (of/s Dof) Dvrs'
     <- prog Dof Dvrs
     <- prog/s Dvrs Dvrs'.

- : prog (of/ifz ([x] [dx] Dof2 x dx) Dof1 Dof) Dvrs'
     <- prog Dof Dvrs
     <- prog/ifz Dof Dvrs _ _ Dvrs'.

- : prog (of/fun _) (vrs/val value/fun).

- : prog (of/app Dof2 Dof1) Dvrs3
     <- prog Dof1 Dvrs1
     <- prog Dof2 Dvrs2
     <- prog/app Dof1 Dvrs1 Dvrs2 Dvrs3.

- : prog (of/handle Dof2 Dof1) Dvrs2
     <- prog Dof1 Dvrs1
     <- prog/handle Dvrs1 _ Dvrs2.

- : prog of/raise (vrs/raises raises/raise).

%worlds () (prog _ _).
%total Dof (prog Dof _).

And thus we have proved type safety for minml with exceptions!