We have written a proof checker that can take as input a proof exported from Nuprl, and outputs a script (a list of commands), which can then be evaluated within Coq to construct a library and check the validity of the proof: if the library is valid, the proof is valid. The translator from Nuprl to Coq is written in OCaml. Nuprl uses an XML-like format to export definitions, rules, and proofs. The files exported from Nuprl contain a proof as well as all its dependencies, which form a sub-library of Nuprl's library. Our OCaml program converts such an XML-like file into a script to reconstruct the corresponding sub-library within our Coq implementation of Nuprl.
To generate such files, you first need to connect to Nuprl. (If you
don't already have an account, look at
http://www.nuprl.org/html/NuprlSystem.html
to see how to get an
account.) Then in the Evaluator run:
primitive_export b1 b2 t l
where b1
is a Boolean (true/false) that indicates whether or not to
overwrite the file; b2
is a Boolean that indicates whether or not to
include the dependency information used to the graph used to find the
list of objects to export; t
is a token which is going to be used as
base for the filename; l
is a list of objects used as seed for
closure of objects to export.
A token is a sequence of characters delimited by backquotes. For the
objects, you'll have to click on an object somewhere in the library to
copy a pointer to the object, and then type C-y to paste the
pointer---it has to be preceded by ioid
.
It is usually safe to use true for b1
and b2
.
The file will be exported to
/usr/nuprl/public/tmp/primitive-export/.term-list. If b1
is
false, then the file will be exported to
/usr/nuprl/public/tmp/primitive-export/-.term-list.
The interface to our Coq formalization is essentially in
../rules/proof_with_lib_non_dep.v
. It contains, among other things,
definitions of complete and incomplete proofs, of a library of
definitions and facts, and of what it means for a library to be valid.
It also provides a simple script language to manipulate the library:
to build proofs and add new definitions.
In addition to using this tool to automatically check Nuprl proofs,
one can use it as a standalone tool to build new proofs. See
../rules/proof_with_lib_non_dep_example1.v
for a simple example.
To run the code below, in addition to Coq, you'll need ocamlbuild
,
batteries
, and menhir
, which you can get through opam.
To try our proof checker run (1 and 2 are to build our Coq formalization):
-
(cs ..; ./create_makefile.sh)
-
(cd ..; make)
-
make
to create a binary. This will createParse.native
-
Then to convert the
uall_wf
proof, type:`./Parse.native --i uall_wf.term-list --o uall_output.v`
This will create the
uall_output.v
file containing everything you need to check the proof using our Coq framework.To actually check the proof in coq, either open that
uall_output.v
file with a Coq editor and run the whole thing, or type`coqc -R ../axiom_choice axiom_choice -R ../bar_induction bar_induction -R ../cequiv cequiv -R ../close close -R ../computation computation -R ../continuity continuity -R ../per per -R ../rules rules -R ../terms terms -R ../util util uall_output.v`
This directory contains two examples so far:
-
uall_wf.term-list
This contains a proof that the
uall
(i.e., uniform universal quantifier) operator is well-formed in the sense that it builds propositions out of families of propositions. -
true_wf.term-list
This contains a proof that the proposition True is indeed a proposition.
We selected these examples because they are simple enough to be proven fully automatically in Nuprl. Because these proofs are automatically generated, they use a large amount of fundamental rules, as well as definitions and proofs already stored in the current library.
As hinted above, the main file is Parse.ml
. It contains the
translator from Nuprl proofs to proofs in our verified
re-implementation of Nuprl in Coq. It uses: NuprlTerms.ml
, which
contains the abstract syntax for Nuprl terms; ParseNuprlAscii.ml
,
which contains the parser of XML-file that Nuprl generates.
To extend the tool with a new rule, you have to:
-
Provide a proof for the validity of the rule (either from the kernel of rules we have already validated, or by producing a new proof).
-
Add support for this rule in our Coq checker of Nuprl proofs in
../rules/proof_with_lib_non_dep.v
. There are a few things to add such as: a new constructor forproof_step
; a description of what it means for such a rule to be valid invalid_proof_node_context
; etc. Best is to look at an example such asproof_step_function_equality
and do something similar for the new rule. -
Add support for this rule in our proof translator in
Parse.ml
by adding a new case to the functionprint_proof_tree
. Again, the best thing to do is to look at an example.