220 likes | 323 Views
Dependent Types in Practical Programming. Hongwei Xi Oregon Graduate Institute. Motivation: Narrowing the Huge Gap. Coq. NuPrl. Program Extraction. Proof synthesis. ML with Dependent Types. ML. Some Key Issues in Language Design. Program error detection Program verification
E N D
Dependent Types in Practical Programming Hongwei Xi Oregon Graduate Institute
Motivation: Narrowing the Huge Gap Coq NuPrl Program Extraction Proof synthesis ML with Dependent Types ML
Some Key Issues in Language Design • Program error detection • Program verification • Large scale programming • Program documentation • Efficient implementation
Some key features in SML • Rich programming constructs • Imperative features • Advanced type system • Sophisticated module system
zip:dynamic safety datatype ‘a list = nil | :: ‘a * ‘a list exception UnequalLengths fun(‘a, ‘b) zip(nil, nil) = nil | zip(x :: xs, y :: ys) = (x, y) :: zip(xs, ys) | zip(x :: xs, nil) = raise UnequalLengths | zip(nil, y :: ys) = raise UnequalLengths
An Example of Dependent Types • We refine the datatype‘a list: typeref ‘a list of nat with nil <| ‘a list(0) | :: <|{n:nat} ‘a*‘a list(n)->’a list(n+1) • Some explanation • nil is a list of length 0 • :: yields a list of length n+1 when given an element of type‘aand a list of length n
zip: static safety fun(‘a, ‘b) zip(nil, nil) = nil | zip(x :: xs, y :: ys) = (x, y) :: zip(xs,ys) (* | zip(x :: xs, nil) = raise UnequalLengths | zip(nil, y :: ys) = raise UnequalLengths *) where zip <| {n:nat} ‘a list(n) * ‘b list(n) -> ‘a * ‘b list(n)
zip: An Elaborated Version fun(‘a, ‘b) zip[0](nil, nil) = nil | zip[n+1](x :: xs, y :: ys) =(x, y) :: zip[n](xs,ys) where zip <| {n:nat} ‘a list(n) * ‘b list(n) -> ‘a * ‘b list(n)
Array bounds Checking Array bounds checking refers to determining whether the value of an expression is within the bounds of an array when it is used to index the array. • Pascal, Ada, Modula-3, SML, Java are among the programming languages which require that all bounds violations be captured. • C and C++ are not. However, array bounds checking can be expensive. • FoxNet (SML): up to 30% loss of throughput • SPIN kernel (Modula-3): significant performance loss
Array Bounds Check Elimination • Some previous approaches: • Synthesizing loop invariants (Suzuki & Ishihata): too expensive in practice to be applicable • Flow analysis (Gupta; Kolte & Wolfe): totally automatic but sensitive to program structures and not thorough • A recent approach: • Safe C compiler (Necula and Lee): relatively simple language constructs A serious drawback: no or little feedback
Some Built-in Dependent Types • int(i)stands for the singleton type which contains only integeri. • bool(b)stands for the singleton type which contains only booleanb. • ‘a array(n)stands for the type of arrays of sizenwhose elements are of type‘a.
Dependent Types of Some Built-in Functions assert sub <| {size:nat}{index:nat | index < size} ‘a array(size) * int(index) -> ‘a • This implies thatsubcan only be applied to an array of sizesizeand an integer of value indexsuch that0 <= index < sizeholds. • Other array operations such as update can be typed similarly.
Dot Product: A version in DML fun{n:nat} dotprod v1 v2 = let fun loop(i, n, result) = if i = n then result else loop(i+1, n, result+sub(v1,i)*sub(v2,i)) where loop <| {i:nat | i<=n} int(i) * int(n) -> int in loop (0, length v1, 0) end where dotprod <| int array(n) -> int array(n) -> int
Dot Product: A Version in de Caml let dotprod v1 v2 = begin let result = ref 0 in for i = 0 to vect_length v1 - 1 do result := result + v1..(i) * v2..(i) done; !result end withtype {n:nat} int vect(n) -> int vect(n) -> int ;; (* for example: dotprod [|1;2;3|] [|1;2;3|] = 1*1 + 2*2 + 3*3 = 14 *)
Dependently Typed Assembly Language • We aim for passing dependent types from source level to assembly level. • This is inspired and/or supported by • TIL compiler (Fox project at CMU) • RML compiler (Tolmach and Oliva) • Proof-carrying code (Necula and Lee) • Typed Assembly Language (Morrisett et al)
Some Advantages of DTAL • Providing invaluable support for compiler writers (Tolmach and Oliva; Morrisett et al) • Producing memory safety proofs for proof-carrying code • An alternative to proof-carrying code • Aggressive compiler optimization
bcopy: A Version in de Caml let bcopy (src, dst) = let length = vect_length src in for n = 0 to length - 1 do dst..(n) <- src..(n) done withtype {i:nat}{j:nat | i <= j} ‘a vect(i) * ‘a vect(j) -> unit ;;
bcopy: A Version in DTAL bcopy: {i:nat}{j:nat | i<=j} [r1: int(i), r2: int array(i), r3: int array(j)] mov r4, 0 // set the count to be 0 jmp loop // start the loop loop: {i:nat}{j:nat | i<=j}{k:nat} [r1: int(i), r2: int array(i), r3: int array(j), r4: int(k)] sub r5, r4, r1 beq r5, finish // r4 = r1 and done load r5, r2(r4) // r5 <- r2(r4) store r3(r4), r5 // r3(r4) <- r5 add r4, r4, 1 // r4 <- r4 + 1 jmp loop // loop again finish:[] halt
Proof Generation forProof-Carrying Code Code Unpacking Poof-Carrying Code Verifying Proof Executing Memory Safety Termination
A Similar Scenario Code-carrying proof? NuPrl proof Proof verification Program extraction
Significant Features of DML • Exhibiting convincing signs of a practical programming language • Theoretical fundation • Prototype implementation and evaluation • Enhancing both code safety and code efficiency • Generating DTAL (ongoing research)
Current Status and Future Direction • We have finished the following. • Theoretical development of DML • A prototype implementation of DML • A prototype implementation of DTAL • We are working on the following. • Writing a DML front-end for Caml-light (de Caml) • Designing a dependently typed assembly language • We intend to do the following. • Dependent types for (a subset of) Java!