250 likes | 260 Views
This article discusses the theoretical development and practical applications of termination verification for dependent ML using dependent types. It also explores program error detection at compile-time and compilation certification.
E N D
Dependent Types forTermination Verification Hongwei Xi University of Cincinnati
Overview • Motivation • Program error detection at compile-time • Compilation certification • Termination Verification for Dependent ML • Theoretical development • Practical applications • Conclusion
Program Error Detection Unfortunately one often pays a price for [languages which impose no disciplines of types] in the time taken to find rather inscrutable bugs — anyone who mistakenly applies CDR to an atom in LISP and finds himself absurdly adding a property list to an integer, will know the symptoms. -- Robin Milner A Theory of Type Polymorphism in Programming Therefore, a stronger type discipline allows for capturing more program errors at compile-time.
Some Advantages of Types • Detecting program errors at compile-time • Enabling compiler optimizations • Facilitating program verification • Using types to encode program properties • Verifying the encoded properties through type-checking • Serving as program documentation • Unlike informal comments, types are formally verified and can thus be fully trusted
compilation |.| Compiler Correctness • How can we prove the correctness of a (realistic) compiler? • Verifying that the semantics of e is the same as the semantics of |e| for every program e • But this simply seems too challenging (and is unlikely to be feasible) Source program e Target code |e|
compilation |.| Compilation Certification • Assume that P(e)holds, i.e., e has the property P • Then P(|e|) should hold, too • A compiler can be designed to produce a certificate to assert that |e| does have the property P Source program e: P(e) holds Target code |e|: P(|e|) holds
Program Extraction Proof Synthesis Dependent ML Narrowing the Gap NuPrl Coq ML
Termination Verification • Termination • is a liveness property • can not be verified at run-time • is often proven with a well-founded metric that decreases whenever a recursive function call is made
Primitive Recursion datatype Nat with nat =Z(0) | {n:nat} S(n+1) of Nat(n) (* Z: Nat(0) S: {n:nat} Nat(n) -> Nat(n+1) *) fun (‘a)R Z u v = u | R (S n) u v = v n (R n u v) withtype{n:nat} Nat(n) -> ‘a -> (Nat -> ‘a -> ‘a) -> ‘a (* Nat is for [n:nat] Nat(n) *) <n> =>
Ackermann Function in DML fun ack (m, n) =if m = 0 then n+1else if n = 0 then ack (m-1, 1) else ack (m-1, ack (m, n-1)) withtype{m:nat,n:nat} int(m) * int(n) -> nat (* Note: nat = [a:int | a >=0] int(a) *) <m,n> =>
What’s really new here? • We present a formalism that • allows the programmer to supply crucial information for facilitating program termination verification • can smoothly integrate into a realistic programming language
ML0: start point base typesd ::= int | bool | (user defined datatypes) types t ::= d | t1t2| t1 *t2 patterns p ::= x | c(p) | <> | <p1, p2> match clauses ms ::= (p e) | (p e | ms) expressionse ::= x | f | c | if (e, e1, e2) | <> | <e1, e2> | lam x:t. e | fix f:t. e | e1(e2) | let x=e1 in e2 end | case e of ms values v ::= x | c | <v1, v2> | lam x:t. e context G ::= . | G, x: t
Integer Constraint Domain We use a for index variables index expressionsi, j ::= a | c | i + j | i – j | i * j | i / j | … index propositionsP, Q ::= i < j | i <= j | i > j | i >= j | i = j | i <> j | P Q | P Q index sorts g::= int | {a : g | P } index variable contexts f ::= . | f, a: g | f, P index constraints F ::= P | P F| a: g.F
Dependent Types dependent typest ::= ... | d(i) | Pa: g.t | Sa: g.t For instance,int(0), bool array(16); nat = [a:int | a >= 0] int(a); {a:int | a >= 0} int list(a) -> int list(a)
DML0: ML0 + dependent types expressionse ::= ... |la: g.v | e[i] |<i | e> | open e1 as <a |x> in e2 end values v ::= ... | la: g.v | <i | v> typing judgment f; G |- e: t
A Typing Rule f;G |-e: bool(i) f,i=1; G |-e1: t f,i=0; G |-e2: t ------------------------(type-if)f; G |-if (e, e1, e2): t
Metric Typing Judgments Definition (Metric) Let m = <i1,...,in> be a tuple of index expressions. We write f|- m: metric if we have f |- ij:nat for 1 j n. We use Pa:g.mtfor a decorated type We use the judgemnt f; G |- e:t <<f m0to mean that for each occurrence of f[i] in e, m[a->i] <m0 holds, where f is declared in G to have type Pa:g.mt
Some Metric Typing Rules • The rule (<<-app) is:f; G |- e1: t1 t2<<f m0f; G |- e2: t1<<f m0-------------------------------------------------f; G |- e1(e2): t1 t2<<f m0 • The rule (<<-lab) is:f |- i: g f |- m[a->i] <m0G(f) = Pa:g.mt-------------------------------------------------f; G |- f[i]:t[a->i] <<f m0
DML0,m The following typing rule is for forming functions: f,a:g; G,f: Pa:g.mt |- e: t<<f m----------------------------------(type-fun)f; G |- fun f[a:g] is e: Pa:g.t
Reducibility Definition Suppose that e is a closed expression of typetand e * v holds for some value v. • tis a base type. Then e is reducible • t=t1t2. Then e is reducible if e(v1) is reducible for every reducible value v1of type t1. • t = t1 *t2. Then e is reducible if v=<v1, v2> and v1, v2 are reducible. • t =Pa: g.t1. Then e is reducible if e[i] is reducible for every i:g. • t =Sa: g.t1. Then e is reducible if v=<i | v1> and v1 is reducible.
m-reducibility Definition Let e be a well-typed closed function fun f[a:g]:mt is v and m0 be a closed metric. e ism0-reducible if e[i] is reducible for each i:g satisfying m[a->i] <m0. Theorem Every closed expression e is reducible if it is well-typed in DML0,m
Quicksort in DML fun qs [] = []| qs (x :: xs) = par (x, xs, [], []) withtype {n:nat} int list(n) -> int list(n) and par (x, [], l, g) = qs (l) @ (x :: qs (g))| par (x, y :: ys, l, g) = if y <= x then par (x, ys, y :: l, g) else par (x, ys, l, y :: g) withtype{p:nat,q:nat,r:nat}int * int list(p) * int list(q) * int list(r) ->int list(p+q+r+1) <n,0> => <p+q+r,p+1> =>
Contributions • Novel type system design to facilitate termination verification • Unobtrusive programming • Theoretical foundation • Prototype implementation and evaluation
Some Closely Related Work • Termination and Reduction Checking in Logic Framework, Pientka and Pfenning • Termination Analysis for Mercury, Speirs, Somogyi and SØndergarrd • Proving correctness of reactive systems using sized types, Hughes, Pareto and Sabry. • Cost recurrences for DML programs, Bernd Grobauer.
End of the Talk • Thank You! Questions?