35
May 1, 2003May 1, 2003 1 Imperative Programming with Dependent Types Hongwei Xi Boston University

May 1, 2003May 1, 2003 1 Imperative Programming with Dependent Types Hongwei Xi Boston University

  • View
    217

  • Download
    2

Embed Size (px)

Citation preview

May 1, 2003May 1, 2003 1

Imperative Programming with Dependent Types

Hongwei XiBoston University

May 1, 2003 2

Talk Overview

Motivation– Detecting program errors (at compile-time)– Generating proof-carrying code

Programming language Xanadu:– Design decisions– Dependent type system– Programming examples

Current Status and Future Work

May 1, 2003 3

A Wish List

We would like to have a programming language that should– be simple and general– support extensive error checking– facilitate proofs of program properties– possess correct and efficient implementation– ... ...

May 1, 2003 4

Reality

Invariably, there are many conflicts among this wish list

These conflicts must be resolved with careful attention to the needs of the user

May 1, 2003 5

Advantages of Types

Capturing errors at compile-time Enabling compiler optimizations Facilitating program verification

– Using types to encode program properties and verifying the encoded properties through type-checking

Serving as program documentation– Unlike informal comments, types can be fully

trusted after type-checking

May 1, 2003 6

Limitations of (Simple) Types

Not general enough– Many correct programs cannot be typed– For instance, type casts are widely used in C

Not specific enough– Many interesting properties cannot be

captured– For instance, types in Java cannot handle safe

array access

May 1, 2003 7

Narrowing the Gap

NuPrl Coq

Program Extraction Proof synthesis

ML withDependent Types

ML

May 1, 2003 8

Informal Program Comments

/* the function should not be applied to a negative integer

*/int factorial (x: int) { if (x < 0) exit(1); /*defensive

programming*/ if (x == 0) return 1;

else return (x * factorial (x-1));}

May 1, 2003 9

Formalizing Program Comments

{n:nat}int factorial (x: int(n)) { if (x == 0) return 1;

else return (x * factorial (x-1));}

Note: factorial (-1) is ill-typed and rejected!

May 1, 2003 10

Informal Program 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;}

May 1, 2003 11

Formalizing Program 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 */ … … …}

May 1, 2003 12

Dependent Types

Dependent types are types that are– more refined– dependent on the values of expressions

Examples– int(i): singleton type containing only integer i– <int> array(n): type for integer arrays of size

n

May 1, 2003 13

Type System Design

A practically useful type system should be– Scalable– Applicable– Comprehensible– Unobtrusive– Flexible

May 1, 2003 14

Xanadu

Xanadu is a dependently typed imperative programming language with C-like syntax

The type of a variable in Xanadu can change during execution

The programmer may need to provide dependent type annotations for type-checking purpose

May 1, 2003 15

Early Design Decisions

Practical type-checking Realistic programming features Conservative extension Pay-only-if-you-use policy

May 1, 2003 16

Examples of Dependent Types (I)

int(a): singleton types containing the only integer equal to a, where a ranges over all integers

<‘a> array(a): types for arrays of size a in which all elements are of type ‘a, where ‘a ranges over all natural numbers

May 1, 2003 17

Examples of Dependent Types (II)

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)

May 1, 2003 18

A Xanadu Program

{n:nat} unit init (int vec[n]) { var: int ind, size;; /* arraysize: {n:nat} <‘a> array(n) -> int(n) */ size = arraysize(vec); invariant: [i:nat] (ind: int(i)) for (ind=0; ind<size; ind=ind+1){ vec[ind] = ind; }}

May 1, 2003 19

A Slight Variation

{n:nat} unit init (int vec[n]) { var: nat ind, size;; /* arraysize: {n:nat} <‘a> array(n)-> int(n)

*/ size = arraysize(vec); for (ind=0; ind<size; ind=ind+1){ vec[ind] = ind; }}

May 1, 2003 20

Dependent Record Types

A polymorphic type for arrays

{n:nat} <‘a> array(n) { size: int(n); data[n]: ‘a}

May 1, 2003 21

Binary Search in Xanadu

{n:nat}int bs(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;}

May 1, 2003 22

Dependent Record Types

A polymorphic type for 2-dimensional arrays:

{m:nat,n:nat} <‘a> array2(m,n) { row: int(m); col: int(n); data[m][n]: ‘a}

May 1, 2003 23

Dependent Record Types

A polymorphic type for sparse arrays:

{m:nat,n:nat} <‘a>sparseArray(m,n) { row: int(m); col: int(n); data[m]: <int[0,n) * ‘a> list}

May 1, 2003 24

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 * <‘a> list(n)-> <‘a> list(n+1)

May 1, 2003 25

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) }

May 1, 2003 26

Typing Judgment in Xanadu

eContext for index variables

Context for variables with mutable types

Context for variables with fixed types

May 1, 2003 27

Typing Assignment

exexunit

May 1, 2003 28

Typing Loop

e1booliieunitwhileeeiunit

May 1, 2003 29

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 */

}

May 1, 2003 30

Constraint Generation in Type-checking

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

May 1, 2003 31

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 athttp://www.cs.bu.edu/~hwxi/Xanadu/Xanadu.html

May 1, 2003 32

Conclusion (I)

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

May 1, 2003 33

Conclusion (II)

We have designed a type-theoretic approach to capturing simple arithmetic reasoning

The preliminary studies indicate that this approach allows the programmer to capture many more properties in realistic programs while retaining practical type-checking

May 1, 2003 34

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 …

May 1, 2003 35

Related Work

Here is a (partial) list of some closely related work.– Dependent types in practical

programming (Xi & Pfenning)– TALC Compiler (Morrisett et al at Cornell)– Safe C compiler (Necula & Lee)– TIL compiler (the Fox project at CMU)