• Nenhum resultado encontrado

7.4 Compilation

7.4.4 Compilation of Proofs to Coq

FoCaLiZe computational language has been designed with Coq and OCaml backends in mind; the features available in this language (such as local denitions, pattern-matching, and tuples) are available in both OCaml and Coq and are trivially translated. The proof language however is very dierent because it has been designed to be convenient for Zenon.

Zenon output to the Coq language actually gives a Coq toplevel theorem, from its statement with the Theorem keyword to the end of the proof with the Qed keyword. For example, a Zenon proof of a property a : A depending on a previously known property b : B will be a toplevel Coq theorem Theorem a : A. Proof. ... b ... Qed.

In order to integrate this in a FoCaLiZe development compiled to Coq, we need to add

7.4. COMPILATION

arguments for λ-lifting. The Section mechanism of Coq is a way to perform implicit λ- lifting: inside a section, Variables can be declared and used in the denitions, statements, and proofs of the section; from outside the section, each symbol getsλ-lifted with respect to all the variables it uses. The FoCaLiZe compiler wraps all the toplevel theorems generated by Zenon into sections so on the previous example, the compiled Coq le shall be

Section Proof_of_a . Variable b : B.

Theorem a : A.

Proof . ... b ...

Qed .

End Proof_of_a .

which is synonym of Theorem a (b : B) : A.

Proof . ... b ...

Qed .

so from outside the section, a has type B -> A as expected.

Coq sections seem very convenient in this case because it seems that we only need to wrap the output of Zenon in a section to get the expected λ-lifted theorem. There is a bad corner-case, however, which introduces some complexity: if Zenon nds a proof which does not use one of the hypotheses, then this hypothesis does not get lifted by the section mechanism and then the set of lifted methods does not correspond to the set of decl-dependencies computed by the dependency calculus. For example, if Zenon is able to prove A without using the hypothesisb : B, the obtained section

Section Proof_of_a . Variable b : B.

Theorem a : A.

Proof . Qed ....

End Proof_of_a .

is now a synonym of Theorem a : A.

Proof . Qed ....

7.4. COMPILATION

and a has type A instead of the expected type B -> A.

The compiler cannot foresee this problem because it has no access to the actual deni- tion of the logical method, which will be computed by Zenon after the compiler has exited, but only to the proof script which might contain useless dependencies. Fortunately, this issue can be solved by doing a second proof on the same theorem in which all the expected decl-dependencies are enforced before exploiting the proof provided by Zenon. The actual generated code is

Section Proof_of_A . Variable b : B.

Theorem for_zenon_a : A.

Proof . Qed ....

Theorem a : A.

Proof .

assert ( __force_use_b := b).

apply for_zenon_a ; auto . Qed .

End Proof_of_same_is_not_different .

This issue is very specic to Coq and its interaction with Zenon. In the case of Focalide, no section mechanism is available in Dedukti but Zenon Modulo is able to output a Dedukti term (and nothing more) which can be plugged in any context. The other distinctions between Zenon and Zenon Modulo will be discussed in Chapter 9.

7.4. COMPILATION

Chapter 8

Computational Part: Compiling ML to Dedukti

As we have seen, the interesting part of the Focalide backend is the translation of the computational and logical languages to Dedukti. This chapter describes the two dicult points in the translation of the computational language, the next chapter will show how Deduction modulo and its implementation in Zenon Modulo can be extended to accept the rewrite system that we are going to introduce now. Most features of the computational language can be translated in a very simple, shallow way: variables are translated by variables, applications by applications, and abstractions by abstractions. The interesting part of the translation of the computational language is the translation of pattern matching and recursion. We encode pattern matching in Dedukti in Section 8.1 and recursion in Section 8.2. Section 8.3 is devoted to a comparison with the techniques of the literature.

8.1 Pattern Matching

Dedukti's pattern matching diers from the one of functional languages such as Fo- CaLiZe in two important ways:

ˆ Locality: in Dedukti, pattern matching is only allowed at toplevel, introduction of new rewrite rules is a global process whereas the match . . . with construct is local.

ˆ Overlapping: rewrite rules are requested to be conuent whereas overlapping of pat- terns is solved by their ordering.

8.1. PATTERN MATCHING

For these reasons, we need to compile FoCaLiZe pattern matching to simpler constructs which are expressible in Dedukti. In our context, the eciency of the produced Dedukti code is not fundamental because denitions using pattern matching in FoCaLiZe are usually simple. The main reasons for this is that complex pattern matchings are hard to specify and that Zenon support for pattern matching is limited. Hence we want to avoid complex compilation techniques such as decision trees [121] because the generated code would be hard to reason about automatically.

We start by solving the locality issue in Section 8.1.1. To solve the overlapping is- sue, we dene two program transformation functions. The rst one, called serialization, compiles pattern matchings with arbitrary number of branches to a simpler form with ex- actly two branches. The second one, called attening, simplies the nesting of patterns.

Serialization is dened in Section 8.1.2 and attening is dened in Section 8.1.3. After these two transformations, the programs can be expressed in Dedukti, this is the topic of Section 8.1.4.