Upload
kelsi-vesey
View
218
Download
0
Embed Size (px)
Citation preview
Dependent Types in Practical Programming
Hongwei Xi
Oregon Graduate Institute
Motivation: Narrowing the Huge Gap
NuPrl Coq
Program Extraction Proof synthesis
ML withDependent 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 ‘a and 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 whetherthe 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 integer i.
• bool(b)stands for the singleton type which contains only boolean b.
• ‘a array(n) stands for the type of arrays of size n whose 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 that sub can only be applied to an array of size size and an integer of value index such that 0 <= index < size holds.
• 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 DTALbcopy: {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
Proof
Poof-CarryingCode
Unpacking
Verifying
Executing
Memory SafetyTermination
A Similar Scenario
NuPrl proof Proof verificationProgram extraction
Code-carrying proof?
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!