<<

Imperative Programming with Dependent Types (Extended Abstract)

Hongwei Xi University of Cincinnati [email protected]

Abstract tirely unclear what it means to say A has type int array(a) for some mutable variable a: if we update the value of a, In this paper, we enrich imperative programming with this changes the type of A but A itself is unchanged. As a form of dependent types. We start with explaining some in DML, we introduce a clear separation between ordinary motivations for this enrichment and mentioning some ma- run-time expressions and a distinguished family of index jor obstacles that need to be overcome. We then present the expressions, linked by singleton types of form int(a): ev- design of a source level dependently typed imperative pro- ery expression of type int(a) must evaluate to a (if the gramming language , forming both static and dy- evaluation terminates). This decision is also crucial to ob- namic semantics and then establishing the type soundness taining a practical type-checking algorithm. theorem. We also present realistic examples, which have There is yet another obstacle. Suppose we have already all been verified in a prototype implementation, in support declared that a mutable variable x has type int(a) for some of the practicality of Xanadu. We claim that the language a. Usually, the type of a variable is fixed upon declaration design of Xanadu is novel and it serves as an informative in a programming language. This means that we cannot example that demonstrates a means to combine imperative even type the assignment x := x + 1 since x and x + 1 have programming with dependent types. different types int(a) and int(a+1), respectively, making dependent types largely useless in imperative programming. In order to type x := x + 1, we must allow the type of x 1 Introduction to change from int(a) into int(a + 1) after evaluating the assignment. In [16, 8], the functional programming language ML is We propose to allow the type of a variable to change extended with a restricted form of dependent types. This ex- during evaluation and study some consequences of this pro- tension yields a dependently typed functional programming posal in the design of a source level programming language. language DML, in which the programmer can use depen- Note that a similar approach is already used in Typed As- r dent types to more accurately capture program properties sembly Language (TAL) [5], where the type of a register and thus detect more program errors at compile-time. It is may change during execution so as to reflect the type of the r also demonstrated that dependent types in DML can facili- content of at different program points. tate array bound check elimination [15], redundant pattern We present some introductory examples on imperative matching clause removal [9], tag check elimination and un- programming with dependent types before going into fur- tagged representation of datatypes [10]. Evidently, an im- ther details, giving the reader some feel as to what depen- mediate question is whether we can reap some similar ben- dent types can actually do in practice. These examples en- efits by introducing dependent types into imperative pro- able us to identify certain ways of using dependent types gramming. We give a positive answer to this question in in practical programming, which we also regard as a major this paper. contribution of the paper. Intuitively speaking, dependent types are types which In Figure 1, the Xanadu program implements a binary depend on the values of language expressions. For instance, search function on an integer array. We use int[0,n] as we can refine the type int for integers into infinitely many a shorthand for [i:int | 0<=i<=n] int(i). Note singleton types int(a), where a, ranging over all integers, that the concrete syntax [i:int | 0<=i<=n] stands is the expression on which this type depends. Also, we for a dependent sum constructor, usually written as Σi : γ, can form a type int array(a) for integer arrays of size where γ is the subset sort a : int 0 a n , that a, where a ranges over all natural numbers. We cannot rely is, the sort for all index expressions{ between| ≤ 0≤and}n. In directly on standard systems of dependent types [4] for lan- short, int[0,n] is the type for all integers i satisfying guages with computational effects. For instance, it is en- 0 i n. Similarly, we use int[-1,n) for all integers ≤ ≤ {n:nat} union <’a>list of nat { int bsearch(key: int, vec[n]: int) { Nil(0); var: {n:nat} Cons(n+1) of ’a * <’a>list(n); low: int[0,n]; high: int[-1,n); } int mid, x;; (’a){m:nat, n:nat} low = 0; high = arraysize(vec) - 1; <’a>list(m+n) revApp(xs:<’a>list(m),ys:<’a>list(n)) { while (low <= high) { var: ’a x;; mid = (low + high) / 2; x = vec[mid]; invariant: if (key == x) { return mid; } [m1:nat,n1:nat | m1+n1 = m+n] else if (key < x) { high = mid-1; } (xs:<’a>list(m1), ys:<’a>list(n1)) else { low = mid+1; } while (true) { } switch (xs) { return -1; case Nil: return ys; } case Cons(x,xs): ys = Cons(x,ys); } } Figure 1. Binary search in Xanadu exit; /* can never be reached */ } j satisfying 1 j < n. The declared− ≤ type int[0,n] for variable low, which (’a){n:nat} will be called the master type of low, means that we can <’a>list(n) reverse (xs: <’a>list(n)) { only store an integer i satisfying 0 i n into variable return revApp(xs, Nil); low, where n is the size of the array≤ in vec≤ . The declared } type for variable high can be interpreted similarly. It can be proven in the type system of Xanadu that the array sub- scripting vec[mid] in the program is always safe at run- Figure 2. The list reverse function in Xanadu time, that is, the integer in mid is always within the bounds of the array in vec when the subscripting is performed. We will briefly explain the reason for this in Section 4. There- We then define the function revApp, which takes a pair fore, it is unnecessary to insert run-time array bound checks of lists (xs, ys) and returns a list that is the concatenation when we compile the program. of the reverse of xs to ys. The header of the function in- In Figure 2, we first declare a polymorphic union type dicates that revApp yields a list of length m + n when to represent lists. A union type in Xanadu is the same as a given a pair of lists of lengths m and n, respectively. The datatype in ML. In this case, the declaration indicates that syntax following the keyword invariant denotes a state we index the union type with an index of sort nat, which type, which can be regarded as a form of loop invariant. stands for the length of a list in this case. An index of The state type means that the variables xs and ys must sort nat basically means that the index represents a natural have types <’a>list(m1) and <’a>list(n1) at the number. program point immediately before the loop, where m1 and n1 are natural numbers satisfying m1+n1 = m+n. The Nil(0) indicates that Nil is assigned the type switch statement inside the loop corresponds to a case • <’a>list(0), that is, Nil is a list of length 0. statement in ML. For instance, suppose the clause: case Cons(x, xs): ys = Cons(x, ys) {n:nat} Cons(n+1) of ’a * <’a>list(n) is chosen at run-time; the head and tail of xs are then as- • means that Cons is given the following type signed to x and xs, respectively; Cons(x, ys) is as- signed to ys and the loop repeats. The function reverse {n:nat} is defined as a special case of revApp and its header indi- ’a * <’a>list(n) -> <’a>list(n+1) cates that this function returns a list of length n when given one of length n. that is, Cons yields a list of length n + 1 when given We present another example in Figure 3 to demon- a pair consisting of an element and a list of length n. strate some use of dependently typed record. We define a We write {n:nat} for the dependent function type polymorphic record <’a>sparseArray(m,n) for rep- constructor, usually written as Πn : nat, which can resenting two-dimensional sparse arrays of dimension m by also be seen as a universal quantifier. n in which each element is of type ’a. Let r be a record {m:nat,n:nat} cutes the code with no run-time array bound checking if the record <’a>sparseArray(m, n) { type-checking is successful. We plan to compile Xanadu row: int(m); /* number of rows */ programs into DTAL code, using annotations in Xanadu col: int(n); /* number of columns */ programs, which are in the form of dependent types, to gen- data[m]: list erate dependent types in DTAL code. This can be regarded /*array of lists representing rows*/ as an alternative design to that of Touchstone. Some pre- } liminary results, including a prototype compiler, have been reported in [14]. In general, the type system of Xanadu al- lows the programmer to use dependent types to capture pro- Figure 3. A dependent record type gram invariants more accurately, and this, in return, leads to more effective detection of program errors and more thor- ough elimination of array bound checks. of type <’a>sparseArray(m, n). Then r has three The most significant contribution of the paper is the de- components, namely, row, col and data. Clearly, the sign of Xanadu, a source level imperative programming types assigned to row and col indicate that r.row and language supporting a form of dependent types. This de- r.col return the dimensions of r. The type assigned to sign includes forming both static and dynamic semantics for data states that r.data is an array of size m. In this ar- Xanadu and imposing restrictions to make Xanadu practi- ray, each element, which represents a row in a sparse array, cal. We also establish the type soundness of Xanadu, which is a list of pairs and each pair consists of a natural num- constitutes the main technical contribution of the paper. We ber less than n and an element of type ’a. For instance, view the design of Xanadu as an example that illustrates an a list consisting of two pairs (6, 2.7183) and (23, 3.1416) approach to enriching imperative programming with depen- represents a row in a sparse array where the 6th and 23rd dent types. elements are 2.7183 and 3.1416, respectively, and the rest The rest of paper is organized as follows. We form a lan- are 0.0. A Xanadu program implementing the multiplica- guage Xanadu0 in Section 2, which allows the type of a vari- tion between a sparse array and a vector can be found at able to change during evaluation but supports no dependent [13], in which all array subscripting is proven safe in the types. The introduction of Xanadu0 is mainly for setting type system of Xanadu. Π,Σ up the machinery to reason about the language Xanadu0 , There is another important motivation behind the design which essentially extends Xanadu0 with a restricted form of Xanadu. In an untrusted computing environment such Π,Σ of dependent types. We present Xanadu0 in Section 3, as the Internet, a code recipient may not trust the origin of where we also form both static and dynamic semantics for received mobile code. This makes array bound check elim- Π,Σ Xanadu0 and establish its type soundness. We then dis- ination significantly more difficult since we need not only cuss in Section 4 some key issues on the design of an exter- to eliminate array bound checks but also to convince the nal language Xanadu and a type inference algorithm for it. code recipient that the elimination is done correctly. The Section 5 deals with some restrictions and extensions that notion of proof-carrying code [6] can address the difficulty make Xanadu more realistic. Lastly, we mention a proto- by attaching to mobile code a proof asserting that the code type implementation, discuss some related work and con- can never perform out-of-bounds array subscripting at run- clude. We refer the interested reader to [12] for the details time. The code recipient can then verify the attached proof omitted here. independently and execute the code with no run-time array We focus on the technical development of Xanadu in this bound checking if the proof verification is successful. abstract, which is considerably involved. A short and intu- However, there remains a challenging question with this itive introduction on Xanadu can be found in [11], where approach: how can we generate such a proof in the first various programming examples are presented with explana- place? The Touchstone compiler [7], which compiles pro- tion. Also, it could be helpful if the reader would briefly grams in a type-safe subset of C into proof-carrying code, read Section 4 before studying Section 2 and Section 3 so handles this question with loop invariant synthesis in source as to get a feel as to how type inference is performed in programs. This is a fully automatic approach, but it is highly Xanadu. heuristic and can be too limited in practice. For instance, the Touchstone compiler seems unable to handle the binary search example presented in Figure 1. As for the example 2 Xanadu0 of sparse matrix multiplication, it does not even seem clear how a heuristic approach can actually work in this case. We start with a simple programming language Xanadu0 We have designed a dependently typed assembly lan- and present its syntax in Figure 4. For instance, the follow- guage DTAL in [14]. The type system of DTAL is capable ing program in C: of capturing memory safety of code at assembly level, in- cluding both type safety and safe array subscripting. After int fact(int x) { receiving DTAL code, a code recipient uses type-checking return ((x > 0)? x * fact (x-1) : 1); to verify whether the received code is memory safe and exe- } types τ ::= bool int τ array unit top | | | | function types λ ::= (τ1, . . . , τn) τ constants c ::= b n → | | hi expressions e ::= c x X op(e1, . . . , en) x := e e1; e2 if(e, e1, e2) while(e1, e2) | | | | | | | | alloc(e1, e2) arraysize (e) e1[e2] e[e1] := e2 | | | | let X = e1 in e2 end newvar x in e end call(X; e1, . . . , en) values v ::= X c | | | functions f ::= λ(X1,...,Xn).e declarations D ::= [] D[X f : λ] value variable contexts Γ ::= |Γ,X :7→λ Γ,X : τ reference variable contexts ∆ ::= · | ∆, x : τ | programs P ::= letdef· | D in e end

Figure 4. The syntax for Xanadu0

is equivalent to extending a declaration D in Xanadu0 with 2.1 Static Semantics the following binding:

[X λ(X1).body :(int) int], Xanadu0 is a monomorphically typed first-order lan- 7→ → guage. The only subtyping rules in Xanadu0 are the fol- where body is lowing. newvar x in (co-eq) (co-top) x := X1; if(x > 0, x call(X; x 1), 1) = τ τ = τ top end ∗ − | ≤ | ≤

There are two kinds of variables in Xanadu0. We use x for Given two reference variable contexts ∆0 and ∆1, we have reference variables and X for value variables. Basically, a the following rule (co-context) for coercing ∆0 into ∆1, reference variable is like a variable in imperative program- where we assume dom(∆0) = dom(∆1). ming while a value variable is like one in (call-by-value) functional programming. We find that value variables are = ∆0(x) ∆1(x) for all x dom(∆0) convenient for certain theoretical purposes but they are not | ≤ ∈ ∆0 = ∆1 indispensable. 1 | We use op for some primitive operations such as arith- ∆ ;Γ e : metic and boolean operations. For a reference variable con- A typing judgment in Xanadu0 is of form 0 (∆ ; τ) e τ` text ∆, the domain dom(∆) is the set of reference vari- 1 , which means that the expression has type under ∆ ;Γ e ∆ ables declared in ∆. The domain dom(Γ) of a value vari- the context 0 and the evaluation of changes 0 into ∆ able context Γ is defined similarly. We require that no ref- 1. For instance, we will see that the following is derivable, erence (value) variables appear more than once in ∆ (Γ). call(X; e , . . . , e ) x : int; (x := true):(x : bool; unit), Also, we use 1 n to indicate a function call · ` in Xanadu0, where X is assumed to be bound to a function taking n arguments. which clearly indicates that the type of x changes from int The most significant feature of Xanadu0 is its type sys- into bool after the assignment x := true. tem, in which the type of a reference variable is allowed to We present some of the typing rules for Xanadu0 in Fig- change during evaluation. We emphasize at this point that ure 5. Given a function f = λ(X1,...,Xn).e and a func- Xanadu0 is not intended for demonstrating the advantage of tion type λ = (τ1, . . . , τn) τ, the rule (type-function) a language that allows the type of a reference variable to is for typing a function. We→ emphasize that only toplevel change during evaluation. Such advantage seems unclear functions are allowed in Xanadu0. Notice that the rule (if there is any) until the introduction of dependent types. (type-newvar) assigns every uninitialized variable the type The design of Xanadu0 is primarily for setting up some ma- top. This implies that a variable is already initialized if it Π,Σ chinery needed to reason about Xanadu0 , which is to be has a type other than top. introduced in Section 3, allowing for a less involved presen- In Xanadu0, the type of a reference variable can change tation. during evaluation. For instance, the following function can 1Another reason for having value variables is that we may also support be given the type (int, int) bool in Xanadu0. Note various functional programming features in Xanadu in future. that the type of x changes from→top into int and then into ∆0;Γ e : (∆1; τ) ` (type-assign) ∆0;Γ x := e : (∆1[x τ]; unit) ` 7→ ∆0;Γ e : (∆1; bool) ∆1;Γ e1 : (∆2; unit) ∆2 = ∆ ∆1;Γ e2 : (∆3; unit) ∆3 = ∆ ` ` | ` | (type-if) ∆0;Γ if(e, e1, e2) : (∆; unit) ` ∆0 = ∆ ∆; Γ e1 : (∆1; bool) ∆1;Γ e2 : (∆2; unit) ∆2 = ∆ | ` ` | (type-while) ∆0;Γ while(e1, e2) : (∆1; unit) ` ∆0;Γ e1 : (∆1; int) ∆1;Γ e2 : (∆2; τ) ` ` (type-alloc) ∆0;Γ alloc(e1, e2) : (∆2; τ array) ` Γ(X) = (τ1, . . . , τn) τ ∆0;Γ e1 : (∆1; τ1) ∆n 1;Γ en : (∆n; τn) → ` ··· − ` (type-call) ∆0;Γ call(X; e1, . . . , en) : (∆n; τ) ` ∆0, x : top;Γ e : (∆1, x : τ1; τ2) ` (type-newvar) ∆0;Γ newvar x in e end : (∆1; τ2) ` ;Γ,X1 : τ1,...,Xn : τn e :( ; τ) · ` · (type-function) Γ λ(X1,...,Xn).e :(τ1, . . . , τn) τ ` →

Figure 5. Some typing rules for Xanadu0

bool during evaluation. Xanadu0 is unclear, we feel that the cost of boxed represen- tation is simply too high. However, the introduction of a λ(X1,X2). restricted form of dependent types into Xanadu0 will com- newvar x in pletely alter the situation as illustrated in Section 3. x := X1 X2; if(x > 0, x := true, x := false); x end − 2.2 Dynamic Semantics

In the rule (type-assign), we use ∆1[x τ] for a finite map We form an abstract machine for assigning dynamic se- ∆ such that ∆(x) = τ and ∆(y) = ∆ 7→(y) for all other vari- 1 mantics to Xanadu0. A machine state is a pair of fi- ables y in dom(∆) = dom(∆1). The rule (type-while) nite mappings , . The domain domM( ) of is a set needs some explanation. The reference variable context ∆ of heap addresses,hV Hi which one may assumeH are representedH in the rule can essentially be regarded as a loop invariant on as natural numbers. For every h dom( ), (h) is a the types of reference variables in the loop that must hold ∈ H H tuple (hc0, . . . , hcn 1), where we use hc for either a con- at the beginning of the loop. In Xanadu0, the programmer stant or a heap address.− The domain dom( ) of is a is responsible for providing such loop invariants. One may set of reference variables and maps x to someV hc forV ev- argue that this practice is too burdensome for the program- V ery x dom(V ). A judgment of form [e] D 0[e0] mer. However, we feel that this argument is less tenable means∈ that expression e under machine stateM →evaluatesM to because (a) it already suffices to provide invariants only for M e0 under 0, where declaration D binds the function sym- those variables whose types may change in a loop and (b) it bols in e Mto some functions. Notice that heap addresses can seems most likely that there are only few such variables. In creep into expressions during evaluation. 2 We thus ex- particular, there is no need for such invariants if there are no tend the syntax for Xanadu0 to treat heap addresses as con- variables whose types change during evaluation. The pro- stants. This enables us to form expressions involving heap grammer, who is allowed to change the types of variables addresses, which are needed for forming evaluation rules. when programming in Xanadu0, can always choose not to We also introduce expressions of the following form do so and thus provide no loop invariants. newvar x = hc in e end A real serious problem with Xanadu0 is in compilation. and treat newvar x in e end as If we can assign to a reference variable a value of any type, newvar x = in e end. we need a uniform representation for values of all types, that The typing rule (type-newvar)hifor is, we need to box all values which cannot be represented newvar x = hc in e end in a word on a real machine. This is similar to supporting polymorphism in a language. Given that the advantage of 2This happens when the rule (eval-alloc) is applied. (eval-newvar-2) , [newvar x = hc1 in hc2 end] D , [hc2] hV Hi → hV Hi (eval-while) [while(e1, e2)] D [if(e1, (e2; while(e1, e2)), )] M → M hi n 0 h dom( ) ≥ 6∈ H (eval-alloc-3) V, [alloc(n, hc)] D , [h (hc, . . . , hc)] [h] h Hi → hV H 7→ i (h) = (hc0, . . . , hck 1) 0 n < k H − ≤ (eval-array-access-in) , [h[n]] D , [hcn] hV Hi → hV Hi (h) = (hc0, . . . , hck 1) n < 0 k n H − ∨ ≤ (eval-array-access-out) , [h[n]] D subscript hV Hi → (h) = (hc0, . . . , hck 1) 0 n < k H − ≤ 0 = [h (hc0, . . . , hcn 1, hc, hcn+1, . . . , hck 1)] H H 7→ − − (eval-array-assign-in) , [h[n] = hc] D , 0 [ ] hV Hi → hV H i hi (h) = (hc0, . . . , hck 1) n < 0 k n H − ∨ ≤ (eval-array-assign-out) , [h[n] = hc] D subscript hV Hi →

Figure 6. Some evaluation rules for Xanadu0 is given below, where H is a finite mapping that maps heap rule for typing a heap address. addresses in e to types. More details on this is to be pre- sented in Subsection 2.3. (type-heap-address) ∆; Γ H h : (∆; H(h)) ` ∆0, x : H(hc); Γ H e : (∆1, x : τ1; τ2) ` ∆0;Γ H newvar x = hc in e end : (∆1; τ2) We use judgments = ∆ and = H to mean ` models ∆ and modelsM | H, respectively.H | The precise M H We list some of the evaluation rules for Xanadu0 in Fig- meaning of these judgments follows from the rules in Fig- ure 6. We use h dom( ) in the rule (eval-alloc-3) to ure 7. Also, we write = H if = , and = H mean that h is a new6∈ heapH address. Note that an array is holds. M | M hV Hi H | always initialized upon allocation. Also we use subscript Assume that ∆0;Γ H , e : (∆1; τ) is derivable. Also as- to indicate that an out-of-bounds array subscripting excep- sume that models ∆` and H, that is, = ∆ and = tion has occurred during evaluation. The evaluation rules H are derivable.M In order to establish theM type | soundnessM for | for propagating exception subscript are all omitted. Xanadu0, we need to prove that if [e] D 0[e0] then M → M We use heap addresses to form expressions when assign- 0 = ∆0 and 0 = H0 are derivable for some ∆0 and 0 M | M | H ing dynamic semantics to Xanadu0. However, it is conceiv- such that ∆0;Γ e0 : (∆1; τ) is derivable. ` able that there are other approaches to assigning dynamic Unfortunately, it is impossible to establish this. For in- semantics to Xanadu0 that require no use of expressions stance, let = ( , ) such that (x1) = (x2) = h and containing heap addresses. Therefore, we do not include (h) = (0)M. NoteV thatH we use (0)Vfor a tupleV consisting of heap addresses as a part of Xanadu0. exactlyH one element 0. Clearly, = ∆ is derivable for M | ∆ = x1 : int array(1), x2 : top array(1). Also note that ∆; Γ x2[0] := true : (∆; unit) is derivable. Sup- 2.3 Type Soundness ` pose that we evaluate x2[0] := true under . This evalu- M ation leads into 0 = ( , 0), where 0(h) = (true), M M V H H When establishing the soundness for Xanadu0, we need but 0 = ∆ is no longer derivable since (x1) = h and M | V to type expressions containing heap addresses. For this pur- 0(h), which is (true), is not an integer tuple. H pose, we use H for a finite mapping from heap addresses to We introduce the following notion of regularity to ad- array types and change the form of a typing judgment into dress the problem. ∆0;Γ H e : (∆1; τ), where we assume that all heap ad- dresses` in e are in the domain dom(H) of H. This affects all the typing rules in Figure 5. Also we use the following Definition 2.1 (Regularity) Let be a derivation of = D M | (model-unit) (model-top) (model-bool) (model-int) = : unit = hc : top = b : bool = i : int H | hi H | H | H | = (x): τ (h) = (hc0, . . . , hcn 1) = hc0 : τ = hcn 1 : τ H | V (model-var) H − H | · · · H | − (model-array) , = x : τ = h : τ array(n) hV Hi | H | = x : ∆(x) for all x dom(∆) = h : H(h) for all h dom(H) M | ∈ (model-context) H | ∈ (model-heap) = ∆ = H M | H |

Figure 7. Modeling Rules for Xanadu0

∆. If the following rule is applied in , D index objects i, j ::= a n i + j i j (h) = (hc0, . . . , hcn 1) | | | − | H − i j i j = hc0 : τ = hcn 1 : τ ∗ | ÷ | H | · · · H | − (model-array) index propositions p ::= i < j i j i = j = h : τ array(n) i = j | i ≤ j | i > j | H | 6 | ≥ | | p1 p2 p1 p2 we say associates h with τ. is a regular derivation if ∧ | ∨ associatesD each heap addressDh with at most one type. index sorts γ ::= int a : γ p D index contexts φ ::= φ,| {a : γ |φ,} p We now argue that the above = , = ∆ cannot · | | M hV Hi | constraint Φ ::= p p Φ have a regular derivations. Note that we must have a deriva- | ⊃ | Φ1 Φ2 a : γ.Φ tion of the following form in order to derive = x1 : ∧ | ∀ int array(1). M | (h) = (1) = 1 : int Figure 8. Syntax for some integer constraint H H | (model-array) = h : int array(1) domain H | Similarly, we also must have a derivation of the following form in order to derive = x2 : top array(1) . M | (h) = (1) = 1 : top types τ ::= bool(i) int(i) unit H H | (model-array) τ array(|i) Σa :| γ.τ | = h : top array(1) | H | function types λ ::= Πφ.(τ1, . . . , τn) τ Therefore, = ∆ cannot have a regular derivation since expressions e ::= · · · | → any derivationM of| = ∆ must associate h with both int M | i e unpack e1 as a X in e2 end and top. values· · · | h | i |v ::= ih v| i · · · | h | i Lemma 2.2 Assume that = ∆0 has a regular deriva- state types σ ::= φ.∆ M | ∃ tion and = H, ∆0;Γ H e : (∆1; τ) and [e] D M | ` M → 0[e0] are derivable, Then there exist ∆0 and H0 extending M Π,Σ H such that 0 = ∆0 has a regular derivation and both Figure 9. Syntax for Xanadu M | 0 0 0 = H0 and ∆0 ;Γ H e0 : (∆1; τ) are derivable. M | 0 ` 0 Proof This follows from a structural induction on the Π,Σ 3 Xanadu0 derivation of ∆0;Γ H , e : (∆1; τ). D ` Theorem 2.3 Let P = letdef D in e end be a program In this section, we extend Xanadu0 into a dependently Π,Σ such that P is derivable; if [e] D∗ 0[e0], then either ` M → M typed programming language Xanadu0 , where the depen- e0 is , or 0[e0] D subscript, or 0[e0] D 00[e00] hi M → M → M dent types are of a restricted form as in DML [16, 8]. for some 00 and e00. In other words, the evaluation of a We fix an integer constraint domain in Figure 8 and re- well-typedM program in Xanadu either terminates normally, 0 strict the type index expressions in XanaduΠ,Σ, namely, the or raises a subscript exception, or runs forever. 0 expressions that can be used to index a type, to this domain. This is a sorted domain and subset sorts can be formed. For Proof Obviously, = has a regular derivation. This instance, we use nat for the subset sort a : int a 0 . theorem then followsM from | · Lemma 2.2. We emphasize that the sort int should not{ be confused| ≥ with} We are now ready to incorporate dependent types into im- the type int. We say that a satisfaction relation φ = Φ is perative programming. satisfiable if (φ)Φ holds in the integer constraint domain,| where (φ)Φ is defined as follows. 3.1 Static Semantics

( )Φ = Φ (φ, a : int)Φ = (φ) a : int.Φ Π,Σ · ∀ A typing judgment in Xanadu0 is of the following (φ, a : γ p )Φ = (φ, a : γ)(p Φ) form, which is considerably involved and thus deserves { (φ,| p)Φ} = (φ)(p Φ) ⊃ ⊃ some detailed explanation. Π,Σ The additional syntax of Xanadu0 to that of Xanadu0 φ1; ∆1;Γ e :(φ2; ∆2; τ) is given in Figure 9. For every integer i, int(i) is a sin- ` gleton type such that the value of every expression of this There are several invariants associated with such as a typing type equals i. Similarly, bool(1) and bool(0) are singleton judgment. types for expressions with values equal to true and false, re- spectively. Also we use Σa : γ.τ for a sum type. We omit 1. All reference variables in e are declared in ∆1. the rules for forming legal types, which are standard. For instance, it is required that φ = 0 i 1 be satisfiable 2. All value variables in e are declared in Γ. in order to form bool(i), where| we≤ assume≤ that all index 3. φ1 ∆1[ref ctx] is derivable. variables in i are declared in φ. ` τ Also, we define the erasure of a type as follows. 4. φ1 Γ[val ctx] is derivable. ` unit = unit top = top 5. φ2 is an extension of φ1, i.e., φ2 = φ1, φ for some φ. boolk (i)k = bool kint(ki) = int k k k k τ array(i) = τ array Σa : γ.τ = τ 6. φ2 ∆2[ref ctx] is derivable. k k k k k k k k ` Note that int is interpreted as Σa : int.int(a) and 7. φ2 τ : is derivable. ` ∗ τ array as Σa : nat.τ array(a). Essentially, φ1; ∆1;Γ e :(φ2; ∆2; τ) means that for each The significance of type erasure is that for every well- ` Π,Σ substitution θ1 satisfying θ1 : φ1 there exists a substi- typed program P in Xanadu0 , if we replace each type · ` tution θ2 satisfying θ2 : φ2 such that e[θ1] can be given in P with its erasure then P becomes a well-type program · ` Π,Σ type τ[θ2] under ∆1[θ1]; Γ[θ1] and the evaluation of e[θ1] in Xanadu0. By this, we say that Xanadu is a conser- 0 changes ∆1[θ1] into ∆2[θ2]. vative extension of Xanadu0. A program that is typable in Π,Σ Π,Σ Some of the typing rules for Xanadu0 are presented in Xanadu0 is already typable in Xanadu0, but dependent Π,Σ Figure 10. In both rules (type-if) and (type-while), the state types in Xanadu0 can allow the programmer to capture type φ.∆ is to be either provided or synthesized. more program properties and thus lead to the construction ∃ of more robust programs (as more program errors are de- 3.2 Dynamic Semantics tected statically). We use a judgment of form φ τ : to indicate ` ∗ Π,Σ that τ is a well-formed type under index variable context The dynamic semantics of Xanadu0 is formed on φ. The rules for deriving such judgments are standard top of that of Xanadu0. We no longer need rules like and thus omitted. We use judgments φ ∆[ref ctx] and (eval-array-access-out) and (eval-array-assign-out) since ` Π,Σ φ Γ[val ctx] to mean that ∆ and Γ are well-formed refer- the type system of Xanadu0 is designed to guarantee that ` Π,Σ ence and value variable contexts, respectively. The rules for the evaluation of a well-typed program in Xanadu0 can these judgments are also standard and thus omitted. never lead to out-of-bounds array subscripting.3 We need We omit the details on how substitution is performed, some additional rules in Figure 11 for handling new lan- which is standard. Given a term such as a type or a con- guage constructs. text, we use [θ] for the result from• applying θ to . We • • introduce a judgment of form φ θ : φ0 and present the 3.3 Type Equality and Coercion following rules for deriving such judgments.`

(sub-emp) A judgment of form φ; ∆ = φ0.∆0 basically means that φ [] : | ∃ ` · ∆ coerces into ∆0[θ], that is, ∆0 under the substitution θ, for φ θ : φ0 φ i : γ some θ satisfying φ θ : φ0. We present rules for deriving ` ` (sub-var) such judgments in this` section. In the presence of dependent φ θ[a i]: φ0, a : γ ` 7→ types, it is no longer trivial to determine whether two types φ θ : φ0 φ = p[θ] ` | (sub-prop) are equivalent. For instance, we have to prove the constraint φ θ : φ0, p 1 + 1 = 2 in order to claim int(1 + 1) is equivalent to ` 3Instead, the programmer is required to insert dynamic array bound Roughly speaking, φ θ : φ0 means that θ has “type” φ0 checks in case an array index cannot be proven within the bounds of the under φ. ` indexed array. φ1; ∆1;Γ e :(φ2; ∆2; τ1) φ2 = τ1 = τ2 ` | (type-eq) φ1; ∆1;Γ e :(φ2; ∆2; τ2) ` ∆(x) = τ ∆(x) = Σa : γ.τ (type-var) (type-open) φ; ∆; Γ x :(φ; ∆; τ) φ; ∆; Γ x :(φ, a : γ; ∆; τ) ` ` φ1; ∆1;Γ e :(φ2; ∆2; τ) ` (type-assign) φ1; ∆1;Γ x := e :(φ2; ∆2[x τ]; unit) ` 7→ Γ(X) = Πφ.(τ1, . . . , τn) τ φ1 θ : φ → ` φ1; ∆1;Γ e1 :(φ2; ∆2; τ1[θ]) ` ... φn; ∆n;Γ en :(φn+1; ∆n+1; τn[θ]) ` (type-call) φ1; ∆1;Γ call(X; e1, . . . , en):(φn+1; ∆n+1; τ[θ]) ` φ1; ∆1;Γ e :(φ2; ∆2; bool(i)) ` φ2, i = 1; ∆2;Γ e1 :(φ3; ∆3; τ) φ3; ∆3 = φ.∆ ` | ∃ φ2, i = 0; ∆2;Γ e2 :(φ4; ∆4; τ) φ4; ∆4 = φ.∆ ` | ∃ (type-if) φ1; ∆1;Γ if(e, e1, e2):(φ2, φ; ∆; τ) ` φ1; ∆1 = φ.∆ φ1; φ; ∆; Γ e1 :(φ2; ∆2; bool(i)) | ∃ ` φ2, i = 1; ∆2;Γ e2 :(φ3; ∆3; unit) φ3; ∆3 = φ.∆ ` | ∃ (type-while) φ1; ∆1;Γ while(e1, e2):(φ2, i = 0; ∆2; unit) ` φ1; ∆1;Γ e1 :(φ2; ∆2; τ1) φ2; ∆2;Γ,X : τ1 e2 :(φ3; ∆3; τ2) ` ` (type-let) φ1; ∆; Γ let X = e1 in e2 end :(φ3; ∆3; τ2) ` φ1 i : γ φ1; ∆1;Γ e :(φ2; ∆2; τ) ` ` (type-pack) φ1; ∆1;Γ i e :(φ2; ∆2;Σa : γ.τ) ` h | i φ1; ∆1;Γ e1 :(φ2; ∆2;Σa : γ.τ1) ` φ2, a : γ; ∆2;Γ,X : τ1 e2 :(φ3; ∆3; τ2) ` (type-unpack) φ1; ∆; Γ unpack e1 as a X in e2 end :(φ3; ∆3; τ2) ` h | i

Π,Σ Figure 10. Some typing rules for Xanadu0

int(2). In other words, type equality is modulo constraint such that P is derivable; if [e] ∗ 0[e0], then ei- ` M →D M satisfaction. ther e0 is or 0[e0] D 00[e00] for some 00 and e00. hi M → M M We write φ = τ1 = τ2 to mean that types τ1 and τ2 are In other words, the evaluation of a well-type program in | equivalent under the index variable context φ. Similarly, we Xanadu0 either terminates normally or runs forever. write φ = τ1 τ2 to mean that type τ1 coerces into type | ≤ The theorem can be proven by following the same approach τ2 under φ. The rules for type equality and coercion are presented in Figure 12. as is used in the proof for Theorem 2.3, though it is much more involved this time. Please find more details in [12]. Notice that the need for deriving judgments of forms φ ` θ : φ0, φ = τ1 = τ2 and φ; ∆ = φ0.∆0 involves constraint satisfaction.| | ∃ 4 Type Inference

3.4 Type Soundness We have so far presented an implicitly typed language Π,Σ Π,Σ Xanadu0 . The typing rules in Xanadu0 are not syntax- Π,Σ directed, making it difficult to implement a practical type We now state the type soundness theorem for Xanadu0 Π,Σ as follows. inference algorithm for programs written in Xanadu0 . Therefore, it becomes necessary to provide an external lan- Theorem 3.1 Let P = letdef D in e end be a program guage in which the programmer can supply type annotations [e] D 0[e0] M → M (eval-pack) [ i e ] D 0[ i e0 ] M h | i → M h | i [e1] D 0[e0 ] M → M 1 (eval-unpack-1) [unpack e1 as a X in e2 end] D 0[unpack e0 as a X in e2 end] M h | i → M 1 h | i (eval-unpack-2) [unpack i hc as a X in e2 end] D [e2 a i X hc ] M h | i h | i → M { 7→ }{ 7→ }

Π,Σ Figure 11. Additional evaluation rules for Xanadu0

For the implementation of binary search in Figure 1, the φ = x = y master type of low is int[0,n], which indicates that | (eq-int) φ = int(x) = int(y) low can only store an integer whose value is between 0 | and n. Similarly, the master type of high is int[-1,n), φ = τ1 = τ2 φ = x = y meaning that only an integer whose value j satisfying 1 | | (eq-array) − ≤ φ = τ1 array(x) = τ2 array(y) j < n can be stored in high. The master types of variables | mid and x are int, that is, these variables can only store φ, a : γ = τ1 = τ2 | (eq-exi-ivar) integers. For a variable appearing as an argument in a func- φ = Σa : γ.τ1 = Σa : γ.τ2 | tion declaration, the master type of the variable is assumed φ = τ1 = τ2 to be the type erasure of the type of the argument (unless | (co-eq) φ = τ1 τ2 the programmer declare the master type of the variable ex- | ≤ plicitly). For instance, the master types of key and vec are (co-top) φ = τ top int and int array, respectively. | ≤ φ = ∆(x) ∆0(x) | ≤ 4.2 No Value Variables for all x dom(∆) = dom(∆0) ∈ (co-context) φ; ∆ = ∆0 | Value variables are not available to the programmer in φ θ : φ0 φ; ∆ = ∆0[θ] our current implementation. The need for value variables ` | (co-state-type) occurs in the elaboration phase where a program is trans- φ; ∆ = φ0.∆0 | ∃ formed from external representation into internal represen- tation and then type-checked. We present a simple example to illustrate this point. Figure 12. Some type equality and coercion Suppose that the assignment x2 = fact(x1) + 1 Π,Σ rules for Xanadu0 occurs in a program, where function fact has already been given the type τ = (int) int. This assignment is for- → mally represented as x2 := +(call(F act; x1), 1), where F act is declare to have type τ. Unfortunately, this assign- to facilitate type inference. We outline some key decisions ment does not type check since the type of + is Π i : we have made in the design of an external language Xanadu. nat, j : nat .(int(i), int(j)) int(i + j) and it is{ im- We omit most details on the design of a type infer- possible to coerce} int into int(→i) for any index i. In order ence algorithm for Xanadu, which largely follows the bi- to overcome the problem, we elaborate x2 = fact(x1) directional approach explained in [16]. However, we ex- + 1 into x2 := unpack call(F act; x1) as a X in + plain a key step in type inference that involves synthesizing (X, 1) end, which can be readily typed. h | i state type invariant for both loops and conditionals. 4.3 State Type Invariant Synthesis 4.1 Master Types for Variables It is readily seen that we need a state type φ.∆ in Π,Σ ∃ In theory, a reference variable in Xanadu0 is allowed order to type either a conditional if(e, e1, e2) or a loop to store a value of any type. However, we impose some while(e1, e2). Clearly, such a state type, which is essen- restriction on this feature in practice. We assign every ref- tially an invariant about the types of some reference vari- erence variable x a type τ and allow a value to be stored in ables at a program point, must be supplied by the program- x only if the value can be coerced to have type τ. We call τ mer or automatically synthesized. This is to be a crucial is- the master type of x and write µ(x) for it. sue in the design of a type inference algorithm for Xanadu. A state type invariant for a loop is of form φ.∆. It would obviously be too obtrusive if the programmer∃ had expressions e ::= to write a loop invariant for each loop. Therefore, it is im- c x op(e1, . . . , en) x := e e1; e2 | | | | | portant in practice to effectively synthesize loop invariants λφ.(∆, if(e, e1, e2)) λφ.(∆, while(e1, e2)) | | for common cases. We are less enthusiastic about sophis- alloc(e1, e2) arraysize (e) | | ticated approaches to loop invariant synthesis since such e1[e2] e[e1] := e2 | | approaches are usually highly heuristic and often make it newvar x : τ in e end call(X; e1, . . . , en) exceedingly difficult for the programmer to figure out the | cause of type errors in case they occur. We use the example in Figure 1 to illustrate the simple Figure 13. The syntax for external language approach we have adopted for loop invariant synthesis in our current implementation of Xanadu. Let (φ, ∆0) be the invariant hint provided by the pro- It should be clear how the presented examples in con- grammer at the beginning of a loop. If there is no hint pro- crete syntax such as the one in Figure 1 can be mapped vided, we assume (φ, ∆0) = ( , ), that is, both φ and ∆0 into the corresponding expressions in the formal syntax for are empty. Also, let τ(x) be the· type· of the reference vari- Xanadu. able x immediately before loop entrance. 4.5 An Example We first list all the variables x1, . . . , xn in the loop • whose values may potentially be modified during the execution of the loop at run-time. For the loop in Fig- We briefly explain how the array subscripting ure 1, the variables x, mid, low, high belong vec[mid] in Figure 1 is proven safe in the type to such a list, but the variables key, vec do not. system of Xanadu. The presented type invariant synthesis approach yields Let ∆1 be a reference variable context whose domain the state type φ.∆ for the loop in Figure 1, where φ is • consists of all declared reference variables and empty and ∆ declares∃ that the variables low, high and mid and x have types int[0,n], int[-1,n), top and ∆0(x) if x dom(∆0); top. We apply the rule (type-open) to low and high.  ∈ ∆1(x) = µ(x) if x = xi ∆0 and τ(x) = top; Then low has type int(i) for index variable i of sort a :  6∈ 6 τ(x) otherwise. int 0 a n , where index variable n is declared of{ sort  nat.| Similarly,≤ ≤ high} has type int(j) for index variable j For the loop in Figure 1, ∆1 maps x, mid, low, of sort a : int 1 a < n . After the assignment high to the following types, respectively: top, top, mid ={ (low +|high) − ≤ / 2, }mid has type int((i + int[0,n], and int[-1,n). In addition, ∆1 maps j)/2). We now need to prove 0 (i + j)/2 < n under the key and vec to int and int array(n), respec- assumption that n is a natural number,≤ 0 i n, 1 tively. j < n and i j. This can be readily verified.≤ ≤ Note− that≤ i j is in the≤ assumption because the loop condition must We use φ.∆1 for the loop invariant. For the loop in ≤ • ∃ hold when the assignment is x = vec[mid] executed. Figure 1, it can be verified that φ.∆1 is indeed a loop invariant and this invariant suffices∃ to guarantee that the array subscripting vec[mid] in the loop is safe, 5 Extensions that is, mid is within the bounds of vec. The state type invariant synthesis for a conditional is done We now describe some programming features that can similarly. be incorporated into Xanadu to make it a more realistic lan- guage. Note that all these features are already supported in a prototype implementation of Xanadu. 4.4 The External Language Xanadu 5.1 Tuples and Polymorphism The syntax for Xanadu is given in Figure 13. The expression λφ.(∆, while(e , e )) conveys that (φ, ∆) is 1 2 Π,Σ the hint mentioned in Section 4.3 that facilitates state Tuples, which are not present in Xanadu0 for the sake type invariant synthesis for the loop while(e1, e2). Note of a less involved presentation, can be readily added into that λφ is used to indicate that this expression is poly- Xanadu. morphic on φ, that is, what is executed at run-time is The interaction between the dependent type system of Π,Σ while(e1[θ], e2[θ]) for some substitution θ with “type” Xanadu0 and polymorphism is minor. As demonstrated φ. The expression λφ.(∆, if(e, e1, e2)) is interpreted simi- in Figure 2, polymorphism is already included in Xanadu. larly. In newvar x : τ in e end, τ is the master type of As a matter of fact, even polymorphic recursion is available the newly declared variable x. in Xanadu. The type of every declared function in Xanadu is provided by the programmer and therefore it adds virtually form that is then interpreted. The implementation is written no cost to support polymorphic recursion. in Objective Caml and its current version is available on- line at [13], where one can also find many running program 5.2 Higher-order Functions examples in Xanadu, including implementations of binary search, fast Fourier transform, heapsort, Gaussian elimina- Currently, we allow a function to accept functions as its tion, red-black trees, random-access lists, various list func- arguments but forbid a function call to return a function. tions, etc. The type-checker consist of two phases in which 4 The type system of Xanadu could be readily extended to the first one checks whether the erasure of a Xanadu pro- support curried functions but such an extension would make gram is well-typed and the second one performs dependent it greatly more complicated to compile Xanadu programs. type-checking. The first phase is straight forward and the It should be further studied whether it is worth the effort to second phase involves solving linear constraints on integers. fully support higher-order functions in Xanadu. The method used in the implementation for solving linear constraints is based on Fourier-Motzkin elimination [1] and 5.3 Exceptions some information on this is already mentioned in [15].

The exception mechanism similar to the one in Java can 7 Related Work be readily incorporated into Xanadu. We currently support exceptions like break and continue in a loop to allow for al- tering the control-flow. Also we allow the use of return(e) Generally speaking, there are two directions for extend- to immediately return the evaluation result of e to the caller ing a Hindely-Milner style of type system. One direction is of a function and the use of exit to abnormally stop the eval- to extend it so as to accept more programs as type-correct uation of a program. and the other is to extend it so as to assign more accurate types to programs. Our work follows the second direction. 5.4 Union Types and Record Types A pioneering study in this direction is the work on refine- ment types [3], which aims at expressing and checking more properties of programs that are already well-typed in ML, A mechanism for declaring dependent union types, rather than admitting more programs as type-correct, which which directly corresponds to dependent datatypes in DML is the goal of most other research on extending type sys- [16, 8] is added into Xanadu and pattern matching is pro- tems. The mechanism of refinement types incorporates the vided for decomposing the values of a union type. A con- notion of intersection types and can thus ascribe multiple crete example of this feature is given in Figure 2. types to terms in a uniform way. An example of dependent record type is given in Fig- ure 3, where the type <’a>sparseArray(m,n) is de- DML is a functional programming language that en- clared for sparse arrays of dimension m by n in which all riches ML with a restricted form of dependent types [16], elements are of type ’a. allowing the programmer to capture more program invari- ants through types and thus detect more program errors at compile-time. In particular, the programmer can refine 5.5 Global Variables datatypes with type index expressions in DML, capturing more invariants in various data structures. For instance, It is also allowed to declare global variables in Xanadu. one can form a datatype in DML that is precisely for all The inclusion of global variables leads to some difficulty. red/black trees and do practical programming with such a In the following example, a global variable count is de- type. The type system of DML is also studied for array clared and initialized with 0. It is required that every global bound check elimination [15]. variable be initialized upon declaration. The master type of Most closely related to DML is the system of indexed count [i:nat] int(i) is , meaning that only a natural types developed independently by Zenger in his Ph.D. The- count number can be stored in . sis [18] (an earlier version of which is described in [17]). global count: [i:nat] int(i) = 0 He works in the context of lazy functional programming. In general, his approach seems to require more changes to a Some implications from adding global variables are ex- given Haskell program to make it amenable to checking in- plained in [12] and approaches to addressing these impli- dexed types than is the case for DML and ML. This is par- cations are also given there. ticularly apparent in the case of existential dependent types, which are tied to data constructors. This has the advantage 6 Implementation of a simpler algorithm for elaboration and type-checking than ours, but the program (and not just the type) has to be more explicit. We have prototyped a type-checker for Xanadu that han- dles all the features mentioned in this paper and a rudi- 4By erasure we basically mean ignoring all syntax related to type index mentary compiler for compiling a Xanadu program into a expressions. Typed Assembly Language (TAL) is introduced in [5], [2] D. Detlefs. An overview of the extended static checking sys- in which a significant feature is that the type of a register tem. In Workshop on Formal Methods in Software Practice, is allowed to change during execution. This sheds some 1996. light on the design of Xanadu. However, a language like [3] T. Freeman and F. Pfenning. Refinement types for ML. In Xanadu0, which essentially adopts the notion of TAL at the ACM SIGPLAN Conference on Programming Language De- source level seems of limited interest. sign and Implementation, pages 268–277, Toronto, Ontario, A dependently typed assembly language (DTAL) is de- 1991. signed on top of TAL with a dependent type system to over- [4] P. Martin-Lof.¨ Intuitionistic Type Theory. Bibliopolis, come some limitations inherent in TAL [14]. The type sys- Naples, Italy, 1984. tem of DTAL is capable of capturing memory safety, which [5] G. Morrisett, D. Walker, K. Crary, and N. Glew. From Sys- includes both type safety and safe array subscripting. The tem F to Typed Assembly Language. ACM Transactions on notion of dependent types in DTAL is adopted from DML. Programming Languages and Systems, 21(3):527–568, May The design of Xanadu is partly prompted by the need for 1999. generating DTAL code. Also, the techniques employed in [6] G. Necula. Proof-carrying code. In Conference Record of Π,Σ 24th Annual ACM Symposium on Principles of Program- establishing the type soundness for Xanadu0 are largely ming Languages, pages 106–119, Paris, France, 1997. ACM adopted from [14]. press. The work on extended static checking (ESC) [2] also [7] G. Necula and P. Lee. The design and implementation of a emphasizes the use of formal annotations in capturing the certifying compiler. In ACM SIGPLAN ’98 Conference on program invariants. These invariants can then be verified Programming Language Design and Implementation, pages through (light-weight) theorem proving. ESC is developed 333–344. ACM press, June 1998. on top of the imperative programming language Modular- [8] H. Xi. Dependent Types in Practical Programming. PhD 3, taking an approach based on first-order logic assertions. thesis, Carnegie Mellon University, 1998. pp. viii+189. It provides a specification language for the programmer to Available as specify properties including a list of variables that a pro- http://www.cs.cmu.edu/˜hwxi/DML/thesis.ps. cedure may modify, a precondition which must be satisfied [9] H. Xi. Dead code elimination through dependent types. In before a function call, a postcondition that must hold when The First International Workshop on Practical Aspects of a function terminates, and so forth. Further study is needed Declarative Languages, San Antonio, January 1999. to determine whether ESC can readily handle higher-order [10] H. Xi. Some Practical Aspects of Dependent Datatypes, functions. November 1999. Available as http://www.cs.bu.edu/˜hwxi/academic/papers/PADD.ps. 8 Conclusion [11] H. Xi. Facilitating Program Verification with Dependent Types, March 2000. Available as http://www.cs.bu.edu/˜hwxi/academic/papers/FPVDT.ps. We have presented in the design of Xanadu a novel ap- [12] H. Xi. Imperative Programming with Dependent Types. In proach to enriching imperative programming with a form Proceedings of 15th IEEE Symposium on Logic in Computer of dependent types. This includes forming both static and Science, pages 375–387, Santo Barbara, June 2000. dynamic semantics for Xanadu and then establishing its [13] H. Xi. Xanadu: Imperative Programming with Dependent type soundness. We have also prototyped a type-checker Types, 2001. Available at for Xanadu and a rudimentary compiler for compiling a http://www.cs.bu.edu/˜hwxi/Xanadu/. Xanadu program into a form that is then interpreted, demon- [14] H. Xi and R. Harper. A Dependently Typed Assembly strating a proof of concept. Language. Technical Report CSE-99-008, Oregon Graduate In future work, we plan to continue the development of Institute, July 1999. Also available as Xanadu, extending the language with features such as inner http://www.cs.bu.edu/˜hwxi/academic/papers/DTAL.ps. functions and modules. Also we intend to study the use [15] H. Xi and F. Pfenning. Eliminating array bound checking of dependent types in compilation, compiling Xanadu into through dependent types. In Proceedings of ACM SIGPLAN DTAL. Conference on Programming Language Design and Imple- mentation, pages 249–257, Montreal,´ Canada, June 1998. 9 Acknowledgment [16] H. Xi and F. Pfenning. Dependent types in practical pro- gramming. In Proceedings of ACM SIGPLAN Symposium on Principles of Programming Languages, pages 214–227, I thank Jerry Paul for reading a draft and providing me San Antonio, Texas, January 1999. with his comments. [17] C. Zenger. Indexed types. Theoretical Computer Science, 187:147–165, 1997. References [18] C. Zenger. Indizierte Typen. PhD thesis, Fakultat¨ fur¨ Infor- matik, Universitat¨ Karlsruhe, 1998. [1] G. Dantzig and B. Eaves. Fourier-Motzkin elimination and its dual. Journal of Combinatorial Theory (A), 14:288–297, 1973.