g; f; g have multiset status and fs1;:::;smg rpos ft1;:::;tng; or. (d) f g; s >rpos tj for all j = 1;:::;n ..... ming Language, Proc. of ESPRIT'90, Brussels (ed. Commission of ...
Veri cation Tools in the Development of Provably Correct Compilers M. R. K. Krishna Rao P. K. Pandya R. K. Shyamasundar Computer Science Group Tata Institute of Fundamental Research Homi Bhabha Road, Colaba BOMBAY 400 005, INDIA
e-mail: fkrishna,
g
pandya, shyam @tifrvax.bitnet
Abstract. The paper presents a practical veri cation tool that helps
in the development of provably correct compilers. The tool is based on the approach of proving termination of PROLOG-like programs using term-rewriting techniques and a technique of testing whether a given PROLOG program can be soundly executed on PROLOG interpreters without the Occur-check test. The tool has been built on top of the theorem prover, RRL (Rewrite Rule Laboratory). The tool is eective for compilers developed using Hoare's re nement algebra approach. The utility of the tool is illustrated through a case study on correctness of a prototype compiler of the ProCoS level 0 language PL0 .
1 Introduction The problem of developing provably correct compilers has been of interest to researchers for many years. It is especially important to use such compilers in safety critical applications, where errors in execution of the program can be disastrous or expensive. Hoare [12] has recently proposed an approach for developing provably correct compilers based on re nement algebra and Bowen et al [5] have applied such an approach for the development of prototype compilers in PROLOG. In this paper, we present a practical veri cation tool for the analysis of logic programs and illustrate its utility in the development of provably correct compilers. A brief look into the re nement algebra approach will re ect the need and importance of such tools in the design of correct compilers. In Hoare's approach [12], a compiling speci cation is designed to describe how each construct of the source language is translated into a sequence of object code instructions. A proof that the compiling speci cation is correct must show that the behavior (or meaning) of the object code is at least as good as that of the source program. For
this purpose, the meaning of the object code can be de ned by an interpreter written in the source language itself so that a source program and its object code can be compared. Compiling speci cation consists of a set of theorems which specify the valid object code for each of the constructs of the source language. Hoare [12] shows that such theorems can be proved correct using the algebraic laws governing the source language and the interpreter for the machine programs. Each theorem is in the form of a Horn clause and describes the compilation of a composite program in terms of the compilation of its components. These Horn clauses can be translated into a logic program (say, PROLOG) to get a prototype compiler as demonstrated in [5]. Proving correctness of this prototype compiler amounts to showing that the object code generated by the compiler from a given source program satis es the compiling speci cation and that compiler generates object code for every valid source program. Such a correctness proof must show: 1. The compiler is a re nement [12] of the compiling speci cation; this can be done easily. (Compiler is sound declaraively). 2. The compiler always terminates for any valid source program. 3. The compiler is sound with respect to the compiling speci cation in spite of the various non-declarative features of PROLOG such as cut (!) and also the idiosyncracies of the PROLOG interpreters such as omission of occur-check test in the uni cation algorithm. (Compiler is sound procedurally). In this paper, we are concerned with the development of tools for checking 2 and 3 above. To be more speci c, we describe an implementation of a veri cation system that helps in proving termination of PROLOG programs in a semi-automatic (almost automatic) fashion and proving that a PROLOG program can be soundly executed on an interpreter without occur-check test in an automatic fashion. The tool is based on the results of Krishna Rao, Kapur and Shyamasundar [17] and Krishna Rao [16]. The approach proposed in [17] is based on reducing the termination problem of logic programs to the termination problem of term rewriting systems. Such a reduction or transformation makes it possible to use the various termination tools available in the rewriting literature for proving termination of logic programs. We implement the transformation procedure proposed in [17] as a front end to the rewrite rule laboratory RRL [15], where tools for proving termination of term rewriting systems are available. Using this tool, we have successfully proved the correctness of a prototype compiler for ProCoS level 0 language PL0 . It may be noted that termination of this compiler cannot be proved using the methods of [25, 21, 22]. It is hoped that the tool will be of help in the development of provably correct compilers in logic programming languages (sequential or parallel). Even though the main thrust of the paper is applicability of the above tool in the development of provably correct compilers, the tool has many other ap-
plications. For example, in the context of developing compilers through partial evaluation as proposed in Jones [14], termination is an important issue and the above tool can be used for proving termination. Rest of the paper is organized as follows. Next section provides an overview of the re nement algebra approach. Section 3 brie y describes various results on termination of logic programs and explains in detail the termination method based on which, the tool is built. Section 4 explain the problem of occur-check and section 5 describes termination techniques of rewriting. Section 6 describes the implementation of the tool, and explains various modules in the tool and their functionality. Section 7 gives a detailed case study on correctness proof for ProCoS PL0 compiler and section 8 concludes the paper with a discussion.
2 An overview of Re nement Algebra Approach Hoare [12] has proposed the use of re nement algebra in proving correctness of compiling speci cations. In this method, the compiling speci cation takes the form of a set of Horn Clauses, which together describe a correct-compilation predicate C . Formula (atom) C (p; m; ) states that the machine program m is a semantically acceptable translation of the source program p. Here, is the symbol table mapping a free variable of p to a location in machine memory. Each clause in the speci cation describes one way of compiling a composite program in terms of compilation of its components. For example,
C (p; q; m1 : m2 ; ) ( C (p; m1; ) ^ C (q; m2 ; ) C (skip; hi; ) (Here, we use (m1 : m2 ) to represent a machine program which executes m1 rst and on its completion starts executing m2 . hi denotes an empty program which terminates immediately). Each clause is proved correct w.r.t. the de nition of C using re nement algebra. Re nement algebra for the source programming language PL consists of a set of algebraic laws which allow us to establish relationships of the form p v q. Intuitively, p v q states that the program q is at least as good as the program p in all circumstances (for example, it terminates more often and it is more deterministic) e.g. x := 1; x : = 2; P v x : = 2; P. The behavior of the machine programs is formalized by giving an interpreter I for the machine language. The interpreter I is itself a program of PL. The compiling speci cation C (p; m; ) is de ned to be correct if p v I(m); i.e. the interpretation of machine code m has same or better eect as source program p with appropriate translation from the data space of target code to that of the source program (based on ). Each clause in the compiling speci cation is proved correct w.r.t. the above de nition. Such a proof can be given entirely through the re nement algebra of PL. The proof of each clause is independent of the other clauses. The advantage
of this modularity is that the proof of correctness of a large compiling speci cation becomes manageable, and that a compiling speci cation can be easily extended with new clauses. We refer the reader to [12, 13, 5] for more details of the re nement algebra approach. Bowen et al have developed a prototype compiler using this approach for the ProCoS PL0 language [5, 11]. Here, the set of Horn clauses constituting the compiling speci cation is directly translated into a PROLOG program. Such a program can be used to compile a source program p by executing a query C (p; M; 0 ), where p is a source program and 0 is the initial symbol table1 mapping global variables of p to their locations. This query will return the object code of p as binding for variable M.
3 Termination of Logic Programs Recently, termination analysis of logic programs has attracted attention of many and a good number of results are reported in the literature (see [1, 24] for a brief survey). In general, termination of a recursive program can be proved by showing that some arguments of the recursive procedure decrease (under a wellfounded ordering) after every invocation (or call) of it. That is, to show that the arguments of outer call are greater than the arguments of the inner call. Presence of local variables (variable occurring in the body but not occurring in the head of a clause) poses a few problems to this general approach (see [21, 17] for a discussion on local variables). Many approaches are proposed to tackle the presence of local variables. The results proposed so far on termination of logic programs can be broadly classi ed into two categories. 1. Many characterizations of termination of logic programs are proposed in [26, 4, 1, 24] and others. They give necessary and sucient conditions for termination. Since logic programming has the full power of Turing machine, these conditions in general are undecidable. 2. Some eorts towards developing mechanizable techniques for proving termination of logic programs are reported in [25, 21, 17, 22, 10] and others. For the same reasons as stated above, these techniques will cater to proper sub-classes of Horn clause programs. The methods proposed in [25, 21, 22] use linear predicate inequalities and their usefulness is demonstrated through a good number of examples. However, these methods have requirements like, existence of admissible solution graphs [21] and uniqueness property [25] of clauses. For example, multiplication program (Example 1 in the following subsection) and the ProCoS PL0 compiler do not satisfy 1 0 is usually
empty. However in some languages there are some prede ned variables; e.g. input and output les in pascal, which must be allocated some predetermined set of locations.
these conditions. Krishna Rao, Kapur and Shyamasundar [17] take a dierent approach and propose to transform given logic program into a term rewriting system and prove termination of rewriting system using many available techniques and tools (such as RRL and REVE [15, 18]) reported in the rewriting literature. This approach does not have restrictions like the ones mentioned above and looks promising (see [17] for a comparison of the two approaches). In the rest of the section, we introduce the notion of well-modedness and describe the main steps of the method described in [17] for proving termination.
3.1 Well-moded logic programs A mode m of an n-ary predicate p is a function from f1; ; ng to the set fin; outg. The set of input positions of p is fi j m(i) = ing (output positions are de ned similarly). Let c : A B1 ; ; Bk be a clause and let Y be a variable in the head A, then A is a producer of Y if Y occurs in an input position of A, otherwise A is a consumer of Y . Let X be a variable in Bi such that A is not a producer of X, then Bi is a consumer of X if X occurs in an input position of Bi , otherwise Bi is a producer of X. The producer-consumer relation of the above clause c is a relation on the atoms in its body and is de ned as f (Bi ; Bj ) j Bi a producer and Bj is a consumer of some variable X in c g. A clause c is well-moded if (a) its producer-consumer relation is acyclic and (b) every variable in c has a producer. A program P is well-moded if every clause in it is well-moded. A well-moded query is a well-moded clause without head. A selection rule [19] (or computation rule) gives the next literal to be resolved among the literals (subgoals) in the current goal. This notion of selection rule can be extended for a clause, as a rule which gives an evaluation order among the literals in the body of the clause [17, 16]. It can be captured by a partial order (if li < lj in the partial order, it means that li would be selected before lj is selected). A selection rule S is implied by the moding information of a wellmoded program if for each clause in the program, the evaluation order given by S is an extension of the producer-consumer relation of that clause.
Example 1: Consider the following multiplication program moding: add (in, in, out)
and
mult (in, in, out)
add(0, Y, Y). add(s(X), Y, s(Z)) :- add(X, Y, Z). mult(0, Y, 0). mult(s(X), Y, Z) :- mult(X, Y, Z1), add(Z1, Y, Z).
The producer-consumer relation of all clauses (except the last) is empty. For the last clause, it is f hmult(X;Y; Z 1); add(Z 1; Y; Z ))i; g. It is easy to see that for every clause, (i) the producer-consumer relation is acyclic and (ii) all the variables in it are having
at least one producer. So this program is well-moded. It is easy to see that PROLOG's left-to-right evaluation order on the atoms in body of each clause is a linear extension of its producer-consumer relation. Hence, PROLOG's left-to-right selection rule is implied by the moding information. 2
3.2 Method of Proving Termination The transformational method proposed in [17] contains the following steps: 1. Transforming given logic program into a term rewriting system (TRS). 2. Proving termination of the resulting term rewriting system. The transformation is based on the idea of eliminating local variables by introducing Skolem functions. For each n-ary predicate p having a moding with k output positions, we introduce k new function symbols p1 ; : : :; pk, each of arity n ? k (i.e., number of input positions). These k-function symbols correspond to the k output positions of the predicate p. If the predicate p has no output positions, we introduce a n-ary function symbol p0. We construct a set of rewrite rules to compute these new functions. In the following, we informally explain the transformation using some examples before giving its formal description.
Example 2: >From the multiplication program along with the moding information given above, we obtain the following rewrite rules:
1. Since the output of predicate add for inputs 0 and Y is Y , we get add1 (0; Y) ! Y. 2. The output of mult for inputs 0 and Y is 0. We get mult1(0; Y) ! 0. 3. From the second clause, the output of add for inputs s(X ) and Y is s(Z ), where Z is the output of add for the inputs X and Y . We get add1 (s(X); Y) ! s(add1 (X; Y)). 4. From the last clause, the output of mult for inputs s(X ) and Y is Z , where Z is the output of add for the inputs Z 1 and Y , where Z 1 is the output of mult for inputs X and Y . So we get mult1 (s(X ); Y ) ! add1 (Z 1; Y ), where Z 1 = mult1 (X; Y ). The resulting rule is mult1(s(X); Y) ! add1 (mult1(X; Y); Y). 2
When a nonvariable term appears in an output position of a body literal, we may need to introduce an inverse function as illustrated in the following example [17].
Example 3: Consider the following clause: moding: a (in, out); a(X, Y) :-
b (in, out)
and
c (in, out)
b(X, f(Z)), c(Z, Y)
The output of predicate a for input X is Y , where Y is the output of predicate c for input Z . Now, one would have to answer the question: What is the value of the input argument of predicate c (i.e., Z ) ?. One can answer this question by saying that Z is
equal to f ?1 (f (Z )), where f (Z ) is output of b for input X . Therefore, we get a1 (X) ! c1 (f ?1 (b1(X))). And to reduce f ?1 (f (Z )) to Z , a rewrite rule f ?1 (f (X)) ! X is added. 2
In the above two examples, all the variables occurring in output positions in the body are also occurring either in output positions of the head or in input positions of some other literal in the body (ie., they have at least one consumer). When there are some variables occurring only in output positions of a literal in the body, we need to add additional rewrite rules as illustrated in [17] for capturing so called unnecessary computations [17] in the logic program. The set Unsry in the following algorithm captures these unnecessary computations (see [17] for more details).
3.3 Formal description of the transformation In this subsection, we give the formal description of the transformation procedure. Given a well-moded logic program and moding information, the transformation always terminates producing a term rewriting system whose termination implies the termination of the given logic program. However, nontermination of the derived term rewriting system does not imply nontermination of the logic program. To be precise, we have proved the following theorem in [17]. Theorem 1: A well-moded logic program terminates for all well-moded queries
under any selection rule implied by the moding information of the predicates, if the derived term rewriting system terminates. The main algorithm is given below. Some of the issues related to inversefunctions and built-ins will be discussed while describing the implementation
aspects. Though input and output positions of a predicate can mix together in all possible ways, for notational convenience, we write all input positions rst, followed by all output positions (this is only for notational convenience in describing the algorithm and this is not assumed in the implementation). We write p(ti1 ; : : :; tij ; to1 ; : : :; tok ) to denote an atom p( ) containing the terms ti1 ; : : :; tij in input positions and to1 ; : : :; tok in output positions. For each clause c, the transformation procedure computes the following: 1. Prod(X ) = f hpl (ti1 ; : : : ; tij ); tol i j X 2 V ar(tol ); X 62 V ar(fti1 ; : : : ; tij )g and p(ti1 ; : : : ; tij ; to1 ; : : : ; tok ) is an atom in the body g is the set of producers of local variable X . 2. Consvar = fX 2 V ar(c) ? in(head) j X 2 out(head) or X occurs in an input position of an atom in the body g is the set of variables consumed at least once. 3. Unsry = f pl (ti1 ; : : : ; tij ) j V ar(tol ) \ Consvar = g [ f q0 (si1 ; : : : ; sik ) j predicate q does not have output positions g, where p() and q( ) are atoms in the body.
algorithm Transform (P : in; RP : out); begin RP := ; f* RP contains rewrite rules *g for each clause c: a(ti1 ; ; tik ; to1 ; ; tok ) B1 ; : : : Bn 2 P do begin INhead := V ar(fti1 ; ; tik g) Compute Consvar and Unsry; Compute Prod(X ) for every variable in V ar(c) ? INhead; for j := 1 to k0 do begin T := ftoj g; f * T is a set of terms *g Eliminate-local-variables(T ); RP := RP [ f aj (ti1 ; ; tik ) ! t j t 2 T g end; f* Following code derives rewrite rules corresponding to unnecessary computations. *g 0
T := Unsry;
Eliminate-local-variables(T ); RP := RP [ f ak (ti1 ; ; tik ) ! $(t) j t 2 T 0
end
g
end Transform. procedure Eliminate-local-variables(T ) f* This procedure goes on replacing the local variables in the set of terms T by the terms
corresponding to their producers as long as there are local varibles. Since producer-consumer relation of every well-moded clause is acyclic, this procedure is guaranteed to terminate. *g begin V := V ar(T ) ? INhead; while V 6= do
begin for each X 02 V do begin T := ; for each hpl (); ti 2 Prod(X ) do if t = X then T 0 := T 0 [ T:fX=pl ()g * Replace local var X by its producer-term. * else if t = f (X ) then begin T 0 := T 0 [ T:f X=f ?1 (pl ()) g; * Introduce inverse functions * RP := RP [ f f ?1 (f (X )) ! X g end ; T := T 0 end; V := V ar(T ) ? INhead end; end Eliminate-local-variables; f
g
f
g
Example 4: Let us illustrate the transformation with the following clause Modings: ce (in, in, out, out, in, in); mt (in, in, out, out); ap (in, in, out) ce(E1 From clauses (3) and (4) of the above compiling speci cation, we obtain the following PROLOG clauses. It is easy to see that these clauses are well-moded with moding: c : (in,in,out,out,in,in) and append : (in,in,out). c(seq([]), S, F, M, Psi, Omega) :c(skip, S, F, M, Psi, Omega). c(seq([P1 | Pr]), S, F, M, Psi, Omega) :c(P1, S, L1, M1, Psi, Omega), c(seq(Pr), L1, F, M2, Psi, Omega), append(M1, M2, M).
The PROLOG program can be used to compile a source program p by ex-
ecuting the query :- c(p, s, M, F, Psi0, Omega), where Psi0 is the initial symbol table which assigns appropriate memory locations (determined by hardware) to two prede ned channels input and output. Omega is the list of available free memory locations on the target computer. It is easy to verify that this query is well-moded. Occur-check: By the results of [16, 2], if no variable occurs more than once in output positions of head of each clause, the program is not subjected to occurcheck (NSTO) and can be run soundly on any PROLOG interpreter. The tool checked each clause for this property and proved that the PL0 complier is NSTO. Transformation: Our tool rst transforms the given PROLOG program (compiler in this case) into a term rewriting system and then proves the termination of the derived term rewriting system. In the following, we give the rewrite rules derived from the above two clauses and termination proof for the derived rewrite rules. 1. c1(seq(nnil); xs; x ; x ) ! c1(skip; xs; x ; x )
2. c2(seq(nnil); xs; x ; x ) ! c2(skip; xs; x ; x )
3. c1(seq(cons(xp1; xpr)); xs; x ; x ) ! c1(seq(xpr); c1(xp1; xs; x ; x ); x ; x ) 4. c2(seq(cons(xp1; xpr)); xs; x ; x ) ! append1(c2(xp1; xs; x ; x ); c2(seq(xpr); c1(xp1; xs; x ; x ); x ; x ))
Termination: The recursive path ordering rpos (described in the previous sec-
tion) is used for proving termination of the derived rewrite system. Since rpos is a simpil cation ordering, it is enough to show that left-hand-side of each rule is greater than the right-hand-side of that rule under rpos. We illustrate the proofs for rewrite rules 1 and 4 above using rpos with precedence: c1 c2 > append1 and seq > skip with LR status for c1 and c2 (this is a part of the precedence/status information generated by the tool in proving termination of the whole rewrite system). To prove c1(seq(nnil); xs; x ; x ) >rpos c1(skip; xs; x ; x ), it is enough (by subclause d.i in the de nition of rpos) to prove that (i) c1(seq(nnil); xs; x ; x ) >rpos skip (ii) c1(seq(nnil); xs; x ; x ) >rpos xs (iii) c1(seq(nnil); xs; x ; x ) >rpos x (iv) c1(seq(nnil); xs; x ; x ) >rpos x and (v) (seq(nnil); xs; x ; x ) >rpos (skip; ; xs; x ; x ) It is easy to see that (ii), (iii) and (iv) hold by subterm property (clause (a) in the de nition of rpos). Since seq > skip in the precedence, seq(nnil) >rpos skip by clause (b) and hence c1(seq(nnil); xs; x ; x ) >rpos skip by clause (a). This completes (i). By the de nition of lexicographic ordering, to prove (v) it is enough to prove seq(nnil) >rpos skip, which we have already done. This completes the proof for rewrite rule 1.
To prove c2(seq(cons(xp1; xpr)); xs; x ; x ) >rpos append1(c2(xp1; xs; x ; x ); c2(seq(xpr); c1(xp1;xs; x ; x ); x ; x )), by clause (b) and precedence c2 > append1, it is enough to prove (i) c2(seq(cons(xp1; xpr)); xs; x ; x ) >rpos c2(xp1; xs; x ; x ) and (ii) c2(seq(cons(xp1; xpr)); xs; x ; x ) >rpos c2(seq(xpr); c1(xp1; xs; x ; x ); x ; x )). We prove (ii) below and proof for (i) is similar (even easier). To prove (ii), it is enough to prove (by clause d.1) (1) c2(seq(cons(xp1; xpr)); xs; x ; x ) >rpos seq(xpr) (2) c2(seq(cons(xp1; xpr)); xs; x ; x ) >rpos c1(xp1; xs; x ; x ) (3) c2(seq(cons(xp1; xpr)); xs; x ; x ) >rpos x (4) c2(seq(cons(xp1; xpr)); xs; x ; x ) >rpos x
and (5) seq(cons(xp1; xpr)) >rpos seq(xpr) By subterm property, (3) and (4) hold. By clause (a), cons(xp1; xpr) >rpos xpr and hence by clause (c), seq(cons(xp1; xpr)) >rpos seq(xpr), which is same as (5). By clause (a), (5) implies (1). Since c1 c2 in the precedence and have LR status, proving (2) involves proofs of (6) c2(seq(cons(xp1; xpr)); xs; x ; x ) >rpos xp1, (7) c2(seq(cons(xp1; xpr)); xs; x ; x ) >rpos xs and (8) seq(cons(xp1; xpr)) >rpos xp1 in addition to (3) and (4). Since variables xp1 and xs are occurring in c2(seq(cons(xp1; xpr)); xs; x ; x ), by subterm property (6) and (7) hold. Proof of (8) again follows from subterm property. This completes proof for rewrite rule 4. 2 The above proof illustrates the highly detailed and tedious, mechanical checking that is often necessary in proving termination of the term rewriting system derived from a logic program. We believe that such checking should be largely left to a mechanical tool if errors are to be avoided. We have carried out the termination proof for the whole prototype compiler of the ProCoS level 0 langauage PL0 using our tool in an interactive fashion as described below. The tool (RRL module) tries to prove termination by showing that lefthand-side term is greater than right-hand-side term of every rule under rpos. It incrementally builds up the precedence relation and status information of the operators in the process. For proving lhs >rpos rhs, it (exhaustively) suggests many pairs in the precedence relation (which might be needed in the proof) and asks user to choose some pairs. Once user gives his choice of pairs, it updates the precedence relation and check whether lhs >rpos rhs is true, if so, it picks the next rewrite rule and proceed. If the pairs picked by the user are not enough for proving lhs >rpos rhs, RRL asks him to pick some more. If all the suggested pairs are exhausted and it is unable to prove lhs >rpos rhs, the tool suggests giving status LR or RL to some function symbols. Experience with the Tool: In the following, we give the details of the eort involved in proving the termination of the prototype compiler.
Number of nonunit PROLOG clauses : 32 Number of rewrite rules derived : 63 Number of interactions needed in the proof : 21 In summary, our tool has proved automatically that the ProCoS compiler can be safely executed without occur check and that it is terminating. However, there is another aspect that needs to be considered; the presence of cuts in the program. The eect of cuts is to chop of certain branches from the search space (SLD-tree). If the cuts are not used carefully, they can chop o certain success branches and it is possible that the compiler may not generate any code for some source programs, even though they satisfy the compiling speci cation. In other words, this would aect the completeness of the compiler. As far as the PL0 compiler is concerned, we could establish that the compiler generates code for all valid source programs by observing the structure of the clauses. However, in general, there is a need for further work for dealing with this aspect in an eective way.
8 Discussion In this paper, we have described a tool for proving correctness of compilers written in PROLOG. This tool is applied to establish correctness of the ProCoS PL0 compiler developed using re nement algebra approach. The versatility of the system described in the development of compilers based on the re nement algebra approach becomes evident by the following observations about the compiler for PL0 .
{ The clauses are well-moded; thus facilitating the application of our system
for proving the termination and occur-check freeness of the compiler. It may be noted that even though the methods of [25, 21, 22] are also for wellmoded programs, they have further requirements such as existence of admissible solution graphs [21] and uniqueness property [25] of clauses. There are many clauses in the prototype compiler for PL0 , which do not satisfy these properties. Hence, their methods cannot be used for proving termination of PL0 compiler. { Cuts in the clause appear at the end of the body of each clause.
However, as already discussed, there is a need to develop techniques and tools that aid in verifying the completeness of the compiler in the presence of cuts (even in the middle of the body of the clauses). Our experience shows that our system is quite useful in showing the correctness of compilers in PROLOG. Further, our system also helps in proving termination of concurrent logic programs such as GHC on the same lines and hence, would be applicable for compilers in GHC. We are currently working
on the enhancement of the system to cater to various other aspects already mentioned and also the applicability of the tools in the context of developing compilers using partial evaluation as proposed in [14].
References 1. K.R. Apt and D. Pedreschi (1991), Reasoning about Termination of Logic Programs, Technical report, University of Pisa, September 1991. 2. K.R. Apt and A. Pellegrini (1992), Why the Occur-check is Not a Problem, in Proc. of 4th Intl. Symp. on Programming Language Implementation and Logic Programming (PLILP'92), Springer-Verlag LNCS Vol 531. 3. J. Beer (1988), The Occur-check Problem Revisited, Journal of Logic Programming, 5, pp. 243-261. 4. M. Bezem (1989), Characterizing Termination of Logic Programs, Report CSR8912, CWI, Amsterdam. Also in Proc. of North American Conf. on Logic Programming NACLP'89. 5. J. Bowen, J. He and P. Pandya (1990), An Approach to Veri able Compiling Speci cation and Prototyping, in Proc. of 2nd Symp. on Programming Language Implementation and Logic Programming, PLILP'90 springer-Verlag LNCS Vol. 456. 6. P. Deransart and J. Maluszinski (1985), Relating Logic Programs and Attribute Grammers, Journal of Logic Programming 2, pp. 119-155. 7. P. Deransart, G. Ferrand and M. Teguia (1991), NSTO Programs (Not Subjected To Occur-check), in Proc. Intl. Logic Programming Symp, ILPS'91, pp. 533-547. 8. N. Dershowitz (1987), Termination of Rewriting, J. of Symbolic Computation, 3, pp. 69-116. 9. N. Dershowitz and J.-P. Jouannaud (1990), Rewrite Systems, in J. van Leeuwen, editor, Handbook of Theoretical Computer Science B: Formal Methods and Semantics, North-Holland, pp. 243-320. 10. D. De Schreye and K. Verschaetse (1992), Termination Analysis of De nite Logic Programs with respect to Call Patterns, K.U. Leuven, submitted for publication. 11. Jifeng He, P. Pandya and J. Bowen (1990), Compiling Speci cation for ProCoS Programming Language Level 0, ProCoS Workshop, Malente, April 1990. Also appears as Project Document, OU HJF 4/2. 12. C.A.R. Hoare (1990), Re nement Algebra Proves Correctness of Compiling Speci cations, Proc. 3rd Re nement Workshop (edited by C.C. Morgan and J.C.P. Woodcock), Springer-Verlag, Workshops in Computing series, pp. 33-48. 13. C.A.R. Hoare, J. He, J. Bowen and P. Pandya (1990), An Algebraic Approach to Veri able Compiling Speci cation and Prototyping of ProCoS level 0 Programming Language, Proc. of ESPRIT'90, Brussels (ed. Commission of European Communities), Kluwer Acadenuc Publishers, 1990. 14. N.D. Jones (1990), Partial Evaluation, Self-Application and Types, Proc. 17th ICALP, Springer-Verlag LNCS 443, pp. 639-59. 15. D. Kapur and H. Zhang (1989), An Overview of Rewrite Rule Laboratory (RRL), Proc. of Rewrite Techniques and Applications conference, RTA'89, Springer-Verlag LNCS vol. 355, pp 559-563. 16. M.R.K. Krishna Rao (1992), Occur-check in Well-moded Logic Programs, Proc. 7th Intl. Meeting of Young Computer Scientists, IMYCS'92, Smolenice Castle, Bratislava.
17. M.R.K. Krishna Rao, D. Kapur and R.K. Shyamasundar (1991), A Transformational Methodology for Proving termination of Logic Programs, Proc. Computer Science Logic, CSL'91, Springer-Verlag LNCS Vol. 626. pp. 213-216. 18. P. Lescanne (1983), Computer Experiments with the REVE Term Rewriting Systems Generator, in proc. 10th ACM POPL (1983), pp. 99-108. 19. J. W. Lloyd (1987), Foundations of Logic Programming, Springer-Verlag. 20. D. A. Plaisted (1984), The Occur-check Problem in Prolog, in Proc. Intl. Symp. on Logic Programming, pp. 272-280. 21. L. Pluemer (1990), Termination Proofs for Logic Programs, Ph. D. Thesis, University of Dortmund, Also appears as Springer-Verlag LNCS vol. 446. 22. L. Pluemer (1991), Automatic Termination Proofs for Prolog Programs Operating on Nonground Terms, in proc. Intl. Logic Programming Symposium, ILPS'91, pp. 503-17. 23. H.Sondergaard (1986), An Application of Abstract Interpretation of Logic Programs: Occur-check Reduction, in Proc. ESOP'86, LNCS vol. 213, pp. 327-336. 24. R.K. Shyamasundar, M.R.K. Krishna Rao and D. Kapur (1990), Rewriting Concepts in the Study of Termination of Logic Programs, Proc. ALPUK'92 conf. (edited by K. Broda), Springer-Verlag, Workshops in Computing series, pp. 3-20. 25. J.D. Ullman and A. van Gelder (1988), Ecient Tests for Top-Down Termination of Logical Rules, JACM, 35(2), pp. 345-373. 26. T. Vasak and J. Potter (1986), Characterization of Terminating Logic Programs, IEEE Symposium on Logic Programming, pp. 140-147.
This article was processed using the LATEX macro package with LLNCS style