Dependent Types for Termination 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.

Download Report

Transcript Dependent Types for Termination 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.

Dependent Types for
Termination Verification
Hongwei Xi
University of Cincinnati
1
Overview
Motivation


Program error detection at compile-time
Compilation certification
Termination Verification for Dependent ML


Theoretical development
Practical applications
Conclusion
2
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.
3
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 typechecking
Serving as program documentation

Unlike informal comments, types are formally
verified and can thus be fully trusted
4
Compiler Correctness
How can we prove the correctness of
a (realistic) compiler?
Source program
e


compilation
Target code
|.|
|e|
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)
5
Compilation Certification
Source program
e: P(e) holds
compilation
|.|
Target code
|e|: P(|e|) holds
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
6
Narrowing the Gap
Coq
NuPrl
Program Extraction
Proof Synthesis
Dependent ML
ML
7
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
8
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} <n> =>
Nat(n) -> ‘a -> (Nat -> ‘a -> ‘a) -> ‘a
(* Nat is for [n:nat] Nat(n) *)
9
Ackermann Function in DML
fun ack (m, n) =
if m = 0 then n+1
else if n = 0 then ack (m-1, 1)
else ack (m-1, ack (m, n-1))
withtype
{m:nat,n:nat} <m,n> => int(m) * int(n) -> nat
(* Note: nat = [a:int | a >=0] int(a) *)
10
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
11
ML0: start point
base types
d ::= int | bool | (user defined datatypes)
types t ::= d | t1  t2 | t1 * t2
patterns p ::= x | c(p) | <> | <p1, p2>
match clauses ms ::= (p  e) | (p  e | ms)
expressions
e ::= 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
12
Integer Constraint Domain
We use a for index variables
index expressions
i, j ::= a | c | i + j | i – j | i * j | i / j | …
index propositions
P, 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
13
Dependent Types
dependent types
t ::= ... | 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)
14
DML0: ML0 + dependent types
expressions
e ::= ... | 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
15
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
16
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.mt for a decorated type
We use the judgemnt f; G |- e:t <<f m0 to
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.mt
17
Some Metric Typing Rules
The rule (<<-app) is:
f; G |- e1: t1  t2 <<f m0 f; G |- e2: t1 <<f m0
-------------------------------------------------
f; G |- e1(e2): t1  t2 <<f m0
The rule (<<- lab) is:
f |- i: g f |- m[a->i] < m0 G(f) = Pa:g.mt
-------------------------------------------------
f; G |- f[i]: t[a->i] <<f m0
18
DML0,m
The following typing rule is for forming
functions:
f,a:g; G,f: Pa:g.mt |- e: t <<f m
----------------------------------(type-fun)
f; G |- fun f[a:g] is e: Pa:g.t
19
Reducibility
Definition Suppose that e is a closed expression of
type t and e * v holds for some value v.
 t is a base type. Then e is reducible
 t = t1  t2. Then e is reducible if e(v1) is
reducible for every reducible value v1 of 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.
20
m-reducibility
Definition Let e be a well-typed closed
function fun f[a:g]:mt is v and m0 be
a closed metric. e is m0-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
21
Quicksort in DML
fun qs [] = []
| qs (x :: xs) = par (x, xs, [], [])
withtype {n:nat} <n,0> => 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} <p+q+r,p+1> =>
int * int list(p) * int list(q) * int list(r) ->
int list(p+q+r+1)
22
Contributions
Novel type system design to
facilitate termination verification
Unobtrusive programming
Theoretical foundation
Prototype implementation and
evaluation
23
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.
24
End of the Talk
Thank You!
Questions?
25