Imperative Programming with Dependent Types Hongwei Xi University of Cincinnati 6 November 2015 Talk Overview Motivation Program error detection Compilation certification Proof-carrying code Programming language Xanadu Design decisions Dependent type system Programming.

Download Report

Transcript Imperative Programming with Dependent Types Hongwei Xi University of Cincinnati 6 November 2015 Talk Overview Motivation Program error detection Compilation certification Proof-carrying code Programming language Xanadu Design decisions Dependent type system Programming.

Imperative Programming
with Dependent Types
Hongwei Xi
University of Cincinnati
28 April 2020
1
Talk Overview
Motivation
Program error detection
Compilation certification
Proof-carrying code
Programming language Xanadu
Design decisions
Dependent type system
Programming examples
Conclusion
28 April 2020
2
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 trusted
28 April 2020
3
Limitations of (Simple) Types
Not general enough
Many correct programs cannot be typed
For instance, downcasts are widely used
in Java
Not specific enough
Many interesting program properties
cannot be captured
For instance, types in Java cannot handle
safe array access
28 April 2020
4
Narrowing the Gap
Coq
NuPrl
Program Extraction
Proof synthesis
Dependent ML
ML
28 April 2020
5
A Challenging Problem
How can we prove the correctness of
a (realistic) compiler?
Source program
P
compilation
Target code
|.|
|P|
Verifying that the semantics of P is the same as
the semantics of |P| for every program P
But this simply seems too challenging (and is
unlikely to be feasible)
28 April 2020
6
Compilation Certification
Source program
P: P(P) holds
compilation
|.|
Target code
|P|: |P|(|P|) holds
Assume that P(P) holds, i.e., P has the
property P
Then there is likely some property |P|
related to P such that |P|(|P|) holds
A compiler can be designed to produce a
certificate that asserts |P| does have the
property |P|
28 April 2020
7
Proof-Carrying Code
Unpacking
Code
Poof-Carrying
Code
Proof
Verifying
Executing
Memory Safety
Termination
28 April 2020
8
Proof Construction
Source program
P
Proof of P(P)
compilation
|.|
proof
translation
Target code
|P|
Proof of |P|(|P|)
Building type derivations at source level
with a practical type inference algorithm
Translating such type derivations into
proofs at target level
28 April 2020
9
Talk Overview
Motivation
Program error detection
Compilation certification
Proof-carrying code
Programming language Xanadu
Design decisions
Dependent type system
Programming examples
Conclusion
28 April 2020
10
Xanadu: an Exotic Place
In Xanadu did Kubla Khan
A stately pleasure-dome decree
……
-- Samuel Taylor Coleridge
28 April 2020
11
Xanadu: an “Exotic” Language
Xanadu is an imperative programming
language with C/Java-like syntax that
supports a restricted form of dependent
types
The type of a variable in Xanadu may
change during execution
The programmer may need to provide
dependent type annotations for typechecking purpose
28 April 2020
12
A Type for Arrays
size
data
A polymorphic type for arrays
record <‘a> array {
size: int;
data[]: ‘a
}
But this does not enforce that the integer
stored in size is the size of the array to
which data points
28 April 2020
13
A Dependent Type for Arrays
A polymorphic type for arrays
{n:nat}
record <‘a> array(n) {
size: int(n);
data[n]: ‘a
}
28 April 2020
14
Informal Comments
/* the function should not be applied to
a negative integer
*/
int factorial (x: int) {
/* defensive programming */
if (x < 0) exit(1);
if (x == 0) return 1;
else return (x * factorial (x-1));
}
Note: factorial(-1) is well-typed!
28 April 2020
15
Formalizing Comments
{n:nat}
int factorial (x: int(n)) {
if (x == 0) return 1;
else return (x * factorial (x-1));
}
Note: factorial (-1) is now ill-typed and rejected!
28 April 2020
16
Informal Comments
/* arrays a and b are of equal size */
float dotprod (float a[], float b[]) {
int i; float sum = 0.0;
if (a.size != b.size) exit(1);
for (i = 0; i < a.size; i = i + 1) {
sum = sum + a[i] * b[i];
}
return sum;
}
28 April 2020
17
Formalizing Comments
{n:nat}
float dotprod (a: <float> array(n),
b: <float> array(n)) {
/* dotprod is assigned the following type:
{n:nat}. (<float> array(n),<float> array(n)) -> float
*/
/* function body */
… … …
}
28 April 2020
18
Some Design Decisions
Practical type-checking
Realistic programming features
Conservative extension
Pay-only-if-you-use policy
28 April 2020
19
Examples of Dependent Types
int(i): singleton type containing the
only integer equal to i, where a ranges
over all integers
<‘a> array(n): type for arrays of size n
in which all elements are of type ‘a,
where n ranges over all natural
numbers
28 April 2020
20
Examples of Dependent Types
int(i,j) is defined as
[a:int | i < a < j] int(a),
that is, the sum of all types int(a)
for i < a < j
int[i,j), int(i,j], int[i,j] are defined
similarly
nat is defined as
[a:int | a >=0] int(a)
28 April 2020
21
Array Initialization in Xanadu
{n:nat}
unit init (vec: <int> array(n)) {
var: int ind;;
invariant: [i:int | i>=0] (ind: int(i))
for (ind=0; ind<vec.size; ind=ind+1){
vec.data[ind] = 0;
}
}
28 April 2020
22
A Slight Variation
{n:nat}
unit init (vec: <int> array(n)) {
var: int ind;;
invariant: [i:int | i<=n] (ind: int(i))
for (ind=vec.size; ind>=0; ind=ind-1){
vec.data[ind] = 0;
}
}
28 April 2020
23
Another Slight Variation
{n:nat}
unit init (vec: <int> array(n)) {
var: nat ind;;
for (ind=0; ind<vec.size; ind=ind+1){
vec.data[ind] = 0;
}
}
28 April 2020
24
Binary Search in Xanadu
{n:nat}
int bsearch (key: int, vec: <int> array(n)) {
var: int l, h, m, x;;
l = 0; h = vec.size - 1;
invariant:
[i:int,j:int | 0<=i<=j+1<=n] (l:int(i),h:int(j))
while (l <= h) {
m = (l + h) / 2; x = vec.data[m];
if (x < key) { l = m - 1; }
else if (x > key) { h = m + 1; }
else { return m; }
}
return –1;
}
28 April 2020
25
A Slight Variation
{n:nat}
int bsearch (key: int, vec: <int> array(n)) {
var: l: int[0, n], h: int[-1, n);
int m, x;;
l = 0; h = vec.size - 1;
while (l <= h) {
m = (l + h) / 2; x = vec.data[m];
if (x < key) { l = m - 1; }
else if (x > key) { h = m + 1; }
else { return m; }
}
return –1;
}
28 April 2020
26
2-dimensional Arrays
A polymorphic type for 2-dimensional
arrays:
{m:nat,n:nat}
record <‘a>array2(m,n) {
row: int(m);
col: int(n);
data[m][n]: ‘a
}
28 April 2020
27
Sparse Arrays
A polymorphic type for sparse arrays:
{m:nat,n:nat}
record <‘a> sparseArray(m,n) {
row: int(m);
col: int(n);
data[m]: <int[0,n) * ‘a> list
}
28 April 2020
28
Dependent Union Types
A polymorphic type for lists:
union <‘a> list with nat = {
Nil(0);
{n:nat} Cons(n+1) of ‘a * <‘a> list(n)
}
Nil: <‘a> list(0)
Cons:{n:nat}.‘a *
28 April 2020
<‘a> list(n) -> <‘a> list(n+1)
29
Dependent Union Types
A polymorphic type for binary trees:
union <‘a> tree with (nat,nat) = {
E(0,0);
{sl:nat,sr:nat,hl:nat,hr:nat}
B(sl+sr+1,1+max(hl,hr)) of
<‘a> tree(sl,hl) * ‘a * <‘a> tree(sr,hr)
}
The two indices represent size and
height, respectively
28 April 2020
30
Type Judgment in Xanadu
f1;D1;G |- e: (f2;D2;t)
f: Context for index variables
D: Context for variables with mutable types
G: Context for variables with fixed types
28 April 2020
31
Typing an Assignment
f1;D1;G |- e: (f2;D2;t)
--------------------------f1;D1;G |- x = e: (f2;D2[x->t];unit)
28 April 2020
32
Typing a Loop
f1;D1 |- $f.D
f1,f;D;G|- e1:(f2;D2;bool(i))
f2,i=1;D2;G |- e2:(f3;D3;unit)
f3;D3 |- $f.D
---------------------------f1;D1;G |-while(e1,e2):(f2,i=0;D2;unit)
Note: $f.D is a loop invariant
28 April 2020
33
Reverse Append in Xanadu
(‘a) {m: nat, n: nat} <‘a> list(m+n)
revApp (xs: <‘a> list(m), ys: <‘a> list(n)) {
var: ‘a x;;
invariant:
[m1: nat, n1: nat | m1+n1=m+n]
(xs: <‘a> list(m1), ys: <‘a> list(n1))
while (true) {
switch (xs) {
case Nil: return ys;
case Cons(x, xs): ys = Cons(x, ys);
}
}
exit; /* can never be reached */
}
28 April 2020
34
A Generated Constraint
The following integer constraint is
generated when the revApp example
is type-checked:
m:nat,n:nat,m1:nat,n1:nat,
m1+n1=m+n,a:nat,m1=a+1
|= a+(n1+1)=m+n
28 April 2020
35
Talk Overview
Motivation
Program error detection
Compilation certification
Proof-carrying code
Programming language Xanadu
Design decisions
Dependent type system
Programming examples
Conclusion
28 April 2020
36
Current Status of Xanadu
A prototype implementation of Xanadu in
Objective Caml that
performs two-phase type-checking, and
generates assembly level code
An interpreter for interpreting assembly
level code
A variety of examples (FFT, Heapsort,
Quicksort, Gaussian elimination, etc.) at
http://www.ececs.uc.edu/~hwxi/Xanadu/Xanadu.html
28 April 2020
37
Conclusion
It is still largely an elusive goal in
practice to verify the correctness of
a program
It is therefore important to identify
those program properties that can be
effectively verified for realistic
programs
28 April 2020
38
Conclusion
We have designed a type-theoretic
approach to capturing some simple
arithmetic reasoning in programming
The preliminary studies indicate that
this approach allows the programmer
to capture many more properties in
realistic programs while retaining
practical type-checking
28 April 2020
39
Future Work
Adding more programming features into
Xanadu
in particular, OO features
Type-preserving compilation: constructing
a compiler for Xanadu that can translate
dependent types from source level into
bytecode level
Incorporating dependent types into (a
subset of) Java and …
28 April 2020
40
Related Work
Here is some related work
Dependent types in practical programming (Xi & Pfenning)
Cayenne (Augustsson)
TALC Compiler (Morrisett et al at Cornell)
Safe C compiler: Touchstone (Necula & Lee)
TIL compiler (the Fox project at CMU)
FLINT compiler (Shao et al at Yale)
Secure Internet Programming (Appel, Felten et al at
Princeton)
28 April 2020
41
End of the Talk
Thank You!
28 April 2020
Questions?
42