diff options
Diffstat (limited to 'contrib/jprover/jprover.ml4')
-rw-r--r-- | contrib/jprover/jprover.ml4 | 554 |
1 files changed, 0 insertions, 554 deletions
diff --git a/contrib/jprover/jprover.ml4 b/contrib/jprover/jprover.ml4 deleted file mode 100644 index 5fd763c3..00000000 --- a/contrib/jprover/jprover.ml4 +++ /dev/null @@ -1,554 +0,0 @@ -(*i camlp4deps: "parsing/grammar.cma" i*) - -open Jlogic - -module JA = Jall -module JT = Jterm -module T = Tactics -module TCL = Tacticals -module TM = Tacmach -module N = Names -module PT = Proof_type -module HT = Hiddentac -module PA = Pattern -module HP = Hipattern -module TR = Term -module PR = Printer -module RO = Reductionops -module UT = Util -module RA = Rawterm - -module J=JA.JProver(JLogic) (* the JProver *) - -(*i -module NO = Nameops -module TO = Termops -module RE = Reduction -module CL = Coqlib -module ID = Inductiveops -module CV = Clenv -module RF = Refiner -i*) - -(* Interface to JProver: *) -(* type JLogic.inf_step = rule * (string * Jterm.term) * (string * Jterm.term) *) -type jp_inf_step = JLogic.inf_step -type jp_inference = JLogic.inference (* simply a list of [inf_step] *) - -(* Definitions for rebuilding proof tree from JProver: *) -(* leaf, one-branch, two-branch, two-branch, true, false *) -type jpbranch = JP0 | JP1 | JP2 | JP2' | JPT | JPF -type jptree = | JPempty (* empty tree *) - | JPAx of jp_inf_step (* Axiom node *) - | JPA of jp_inf_step * jptree - | JPB of jp_inf_step * jptree * jptree - -(* Private debugging tools: *) -(*i*) -let mbreak s = Format.print_flush (); print_string ("-break at: "^s); - Format.print_flush (); let _ = input_char stdin in () -(*i*) -let jp_error re = raise (JT.RefineError ("jprover", JT.StringError re)) - -(* print Coq constructor *) -let print_constr ct = Pp.ppnl (PR.pr_lconstr ct); Format.print_flush () - -let rec print_constr_list = function - | [] -> () - | ct::r -> print_constr ct; print_constr_list r - -let print_constr_pair op c1 c2 = - print_string (op^"("); - print_constr c1; - print_string ","; - print_constr c2; - print_string ")\n" - - -(* Parsing modules for Coq: *) -(* [is_coq_???] : testing functions *) -(* [dest_coq_???] : destructors *) - -let is_coq_true ct = (HP.is_unit_type ct) && not (HP.is_equation ct) - -let is_coq_false = HP.is_empty_type - -(* return two subterms *) -let dest_coq_and ct = - match (HP.match_with_conjunction ct) with - | Some (hdapp,args) -> -(*i print_constr hdapp; print_constr_list args; i*) - begin - match args with - | s1::s2::[] -> -(*i print_constr_pair "and" s1 s2; i*) - (s1,s2) - | _ -> jp_error "dest_coq_and" - end - | None -> jp_error "dest_coq_and" - -let is_coq_or = HP.is_disjunction - -(* return two subterms *) -let dest_coq_or ct = - match (HP.match_with_disjunction ct) with - | Some (hdapp,args) -> -(*i print_constr hdapp; print_constr_list args; i*) - begin - match args with - | s1::s2::[] -> -(*i print_constr_pair "or" s1 s2; i*) - (s1,s2) - | _ -> jp_error "dest_coq_or" - end - | None -> jp_error "dest_coq_or" - -let is_coq_not = HP.is_nottype - -let dest_coq_not ct = - match (HP.match_with_nottype ct) with - | Some (hdapp,arg) -> -(*i print_constr hdapp; print_constr args; i*) -(*i print_string "not "; - print_constr arg; i*) - arg - | None -> jp_error "dest_coq_not" - - -let is_coq_impl ct = - match TR.kind_of_term ct with - | TR.Prod (_,_,b) -> (not (Termops.dependent (TR.mkRel 1) b)) - | _ -> false - - -let dest_coq_impl c = - match TR.kind_of_term c with - | TR.Prod (_,b,c) -> -(*i print_constr_pair "impl" b c; i*) - (b, c) - | _ -> jp_error "dest_coq_impl" - -(* provide new variables for renaming of universal variables *) -let new_counter = - let ctr = ref 0 in - fun () -> incr ctr;!ctr - -(* provide new symbol name for unknown Coq constructors *) -let new_ecounter = - let ectr = ref 0 in - fun () -> incr ectr;!ectr - -(* provide new variables for address naming *) -let new_acounter = - let actr = ref 0 in - fun () -> incr actr;!actr - -let is_coq_forall ct = - match TR.kind_of_term (RO.whd_betaiota ct) with - | TR.Prod (_,_,b) -> Termops.dependent (TR.mkRel 1) b - | _ -> false - -(* return the bounded variable (as a string) and the bounded term *) -let dest_coq_forall ct = - match TR.kind_of_term (RO.whd_betaiota ct) with - | TR.Prod (_,_,b) -> - let x ="jp_"^(string_of_int (new_counter())) in - let v = TR.mkVar (N.id_of_string x) in - let c = TR.subst1 v b in (* substitute de Bruijn variable by [v] *) -(*i print_constr_pair "forall" v c; i*) - (x, c) - | _ -> jp_error "dest_coq_forall" - - -(* Apply [ct] to [t]: *) -let sAPP ct t = - match TR.kind_of_term (RO.whd_betaiota ct) with - | TR.Prod (_,_,b) -> - let c = TR.subst1 t b in - c - | _ -> jp_error "sAPP" - - -let is_coq_exists ct = - if not (HP.is_conjunction ct) then false - else let (hdapp,args) = TR.decompose_app ct in - match args with - | _::la::[] -> - begin - try - match TR.destLambda la with - | (N.Name _,_,_) -> true - | _ -> false - with _ -> false - end - | _ -> false - -(* return the bounded variable (as a string) and the bounded term *) -let dest_coq_exists ct = - let (hdapp,args) = TR.decompose_app ct in - match args with - | _::la::[] -> - begin - try - match TR.destLambda la with - | (N.Name x,t1,t2) -> - let v = TR.mkVar x in - let t3 = TR.subst1 v t2 in -(*i print_constr_pair "exists" v t3; i*) - (N.string_of_id x, t3) - | _ -> jp_error "dest_coq_exists" - with _ -> jp_error "dest_coq_exists" - end - | _ -> jp_error "dest_coq_exists" - - -let is_coq_and ct = - if (HP.is_conjunction ct) && not (is_coq_exists ct) - && not (is_coq_true ct) then true - else false - - -(* Parsing modules: *) - -let jtbl = Hashtbl.create 53 (* associate for unknown Coq constr. *) -let rtbl = Hashtbl.create 53 (* reverse table of [jtbl] *) - -let dest_coq_symb ct = - N.string_of_id (TR.destVar ct) - -(* provide new names for unknown Coq constr. *) -(* [ct] is the unknown constr., string [s] is appended to the name encoding *) -let create_coq_name ct s = - try - Hashtbl.find jtbl ct - with Not_found -> - let t = ("jp_"^s^(string_of_int (new_ecounter()))) in - Hashtbl.add jtbl ct t; - Hashtbl.add rtbl t ct; - t - -let dest_coq_app ct s = - let (hd, args) = TR.decompose_app ct in -(*i print_constr hd; - print_constr_list args; i*) - if TR.isVar hd then - (dest_coq_symb hd, args) - else (* unknown constr *) - (create_coq_name hd s, args) - -let rec parsing2 c = (* for function symbols, variables, constants *) - if (TR.isApp c) then (* function symbol? *) - let (f,args) = dest_coq_app c "fun_" in - JT.fun_ f (List.map parsing2 args) - else if TR.isVar c then (* identifiable variable or constant *) - JT.var_ (dest_coq_symb c) - else (* unknown constr *) - JT.var_ (create_coq_name c "var_") - -(* the main parsing function *) -let rec parsing c = - let ct = Reduction.whd_betadeltaiota (Global.env ()) c in -(* let ct = Reduction.whd_betaiotazeta (Global.env ()) c in *) - if is_coq_true ct then - JT.true_ - else if is_coq_false ct then - JT.false_ - else if is_coq_not ct then - JT.not_ (parsing (dest_coq_not ct)) - else if is_coq_impl ct then - let (t1,t2) = dest_coq_impl ct in - JT.imp_ (parsing t1) (parsing t2) - else if is_coq_or ct then - let (t1,t2) = dest_coq_or ct in - JT.or_ (parsing t1) (parsing t2) - else if is_coq_and ct then - let (t1,t2) = dest_coq_and ct in - JT.and_ (parsing t1) (parsing t2) - else if is_coq_forall ct then - let (v,t) = dest_coq_forall ct in - JT.forall v (parsing t) - else if is_coq_exists ct then - let (v,t) = dest_coq_exists ct in - JT.exists v (parsing t) - else if TR.isApp ct then (* predicate symbol with arguments *) - let (p,args) = dest_coq_app ct "P_" in - JT.pred_ p (List.map parsing2 args) - else if TR.isVar ct then (* predicate symbol without arguments *) - let p = dest_coq_symb ct in - JT.pred_ p [] - else (* unknown predicate *) - JT.pred_ (create_coq_name ct "Q_") [] - -(*i - print_string "??";print_constr ct; - JT.const_ ("err_"^(string_of_int (new_ecounter()))) -i*) - - -(* Translate JProver terms into Coq constructors: *) -(* The idea is to retrieve it from [rtbl] if it exists indeed, otherwise - create one. *) -let rec constr_of_jterm t = - if (JT.is_var_term t) then (* a variable *) - let v = JT.dest_var t in - try - Hashtbl.find rtbl v - with Not_found -> TR.mkVar (N.id_of_string v) - else if (JT.is_fun_term t) then (* a function symbol *) - let (f,ts) = JT.dest_fun t in - let f' = try Hashtbl.find rtbl f with Not_found -> TR.mkVar (N.id_of_string f) in - TR.mkApp (f', Array.of_list (List.map constr_of_jterm ts)) - else jp_error "constr_of_jterm" - - -(* Coq tactics for Sequent Calculus LJ: *) -(* Note that for left-rule a name indicating the being applied rule - in Coq's Hints is required; for right-rule a name is also needed - if it will pass some subterm to the left-hand side. - However, all of these can be computed by the path [id] of the being - applied rule. -*) - -let assoc_addr = Hashtbl.create 97 - -let short_addr s = - let ad = - try - Hashtbl.find assoc_addr s - with Not_found -> - let t = ("jp_H"^(string_of_int (new_acounter()))) in - Hashtbl.add assoc_addr s t; - t - in - N.id_of_string ad - -(* and-right *) -let dyn_andr = - T.split RA.NoBindings - -(* For example, the following implements the [and-left] rule: *) -let dyn_andl id = (* [id1]: left child; [id2]: right child *) - let id1 = (short_addr (id^"_1")) and id2 = (short_addr (id^"_2")) in - (TCL.tclTHEN (T.simplest_elim (TR.mkVar (short_addr id))) (T.intros_using [id1;id2])) - -let dyn_orr1 = - T.left RA.NoBindings - -let dyn_orr2 = - T.right RA.NoBindings - -let dyn_orl id = - let id1 = (short_addr (id^"_1")) and id2 = (short_addr (id^"_2")) in - (TCL.tclTHENS (T.simplest_elim (TR.mkVar (short_addr id))) - [T.intro_using id1; T.intro_using id2]) - -let dyn_negr id = - let id1 = id^"_1_1" in - HT.h_intro (short_addr id1) - -let dyn_negl id = - T.simplest_elim (TR.mkVar (short_addr id)) - -let dyn_impr id = - let id1 = id^"_1_1" in - HT.h_intro (short_addr id1) - -let dyn_impl id gl = - let t = TM.pf_get_hyp_typ gl (short_addr id) in - let ct = Reduction.whd_betadeltaiota (Global.env ()) t in (* unfolding *) - let (_,b) = dest_coq_impl ct in - let id2 = (short_addr (id^"_1_2")) in - (TCL.tclTHENLAST - (TCL.tclTHENS (T.cut b) [T.intro_using id2;TCL.tclIDTAC]) - (T.apply_term (TR.mkVar (short_addr id)) - [TR.mkMeta (Evarutil.new_meta())])) gl - -let dyn_allr c = (* [c] must be an eigenvariable which replaces [v] *) - HT.h_intro (N.id_of_string c) - -(* [id2] is the path of the instantiated term for [id]*) -let dyn_alll id id2 t gl = - let id' = short_addr id in - let id2' = short_addr id2 in - let ct = TM.pf_get_hyp_typ gl id' in - let ct' = Reduction.whd_betadeltaiota (Global.env ()) ct in (* unfolding *) - let ta = sAPP ct' t in - TCL.tclTHENS (T.cut ta) [T.intro_using id2'; T.apply (TR.mkVar id')] gl - -let dyn_exl id id2 c = (* [c] must be an eigenvariable *) - (TCL.tclTHEN (T.simplest_elim (TR.mkVar (short_addr id))) - (T.intros_using [(N.id_of_string c);(short_addr id2)])) - -let dyn_exr t = - T.one_constructor 1 (RA.ImplicitBindings [t]) - -let dyn_falsel = dyn_negl - -let dyn_truer = - T.one_constructor 1 RA.NoBindings - -(* Do the proof by the guidance of JProver. *) - -let do_one_step inf = - let (rule, (s1, t1), (s2, t2)) = inf in - begin -(*i if not (Jterm.is_xnil_term t2) then - begin - print_string "1: "; JT.print_term stdout t2; print_string "\n"; - print_string "2: "; print_constr (constr_of_jterm t2); print_string "\n"; - end; -i*) - match rule with - | Andl -> dyn_andl s1 - | Andr -> dyn_andr - | Orl -> dyn_orl s1 - | Orr1 -> dyn_orr1 - | Orr2 -> dyn_orr2 - | Impr -> dyn_impr s1 - | Impl -> dyn_impl s1 - | Negr -> dyn_negr s1 - | Negl -> dyn_negl s1 - | Allr -> dyn_allr (JT.dest_var t2) - | Alll -> dyn_alll s1 s2 (constr_of_jterm t2) - | Exr -> dyn_exr (Tactics.inj_open (constr_of_jterm t2)) - | Exl -> dyn_exl s1 s2 (JT.dest_var t2) - | Ax -> T.assumption (*i TCL.tclIDTAC i*) - | Truer -> dyn_truer - | Falsel -> dyn_falsel s1 - | _ -> jp_error "do_one_step" - (* this is impossible *) - end -;; - -(* Parameter [tr] is the reconstucted proof tree from output of JProver. *) -let do_coq_proof tr = - let rec rec_do trs = - match trs with - | JPempty -> TCL.tclIDTAC - | JPAx h -> do_one_step h - | JPA (h, t) -> TCL.tclTHEN (do_one_step h) (rec_do t) - | JPB (h, left, right) -> TCL.tclTHENS (do_one_step h) [rec_do left; rec_do right] - in - rec_do tr - - -(* Rebuild the proof tree from the output of JProver: *) - -(* Since some universal variables are not necessarily first-order, - lazy substitution may happen. They are recorded in [rtbl]. *) -let reg_unif_subst t1 t2 = - let (v,_,_) = JT.dest_all t1 in - Hashtbl.add rtbl v (TR.mkVar (N.id_of_string (JT.dest_var t2))) - -let count_jpbranch one_inf = - let (rule, (_, t1), (_, t2)) = one_inf in - begin - match rule with - | Ax -> JP0 - | Orr1 | Orr2 | Negl | Impr | Alll | Exr | Exl -> JP1 - | Andr | Orl -> JP2 - | Negr -> if (JT.is_true_term t1) then JPT else JP1 - | Andl -> if (JT.is_false_term t1) then JPF else JP1 - | Impl -> JP2' (* reverse the sons of [Impl] since [dyn_impl] reverses them *) - | Allr -> reg_unif_subst t1 t2; JP1 - | _ -> jp_error "count_jpbranch" - end - -let replace_by r = function - (rule, a, b) -> (r, a, b) - -let rec build_jptree inf = - match inf with - | [] -> ([], JPempty) - | h::r -> - begin - match count_jpbranch h with - | JP0 -> (r,JPAx h) - | JP1 -> let (r1,left) = build_jptree r in - (r1, JPA(h, left)) - | JP2 -> let (r1,left) = build_jptree r in - let (r2,right) = build_jptree r1 in - (r2, JPB(h, left, right)) - | JP2' -> let (r1,left) = build_jptree r in (* for [Impl] *) - let (r2,right) = build_jptree r1 in - (r2, JPB(h, right, left)) - | JPT -> let (r1,left) = build_jptree r in (* right True *) - (r1, JPAx (replace_by Truer h)) - | JPF -> let (r1,left) = build_jptree r in (* left False *) - (r1, JPAx (replace_by Falsel h)) - end - - -(* The main function: *) -(* [limits] is the multiplicity limit. *) -let jp limits gls = - let concl = TM.pf_concl gls in - let ct = concl in -(*i print_constr ct; i*) - Hashtbl.clear jtbl; (* empty the hash tables *) - Hashtbl.clear rtbl; - Hashtbl.clear assoc_addr; - let t = parsing ct in -(*i JT.print_term stdout t; i*) - try - let p = (J.prover limits [] t) in -(*i print_string "\n"; - JLogic.print_inf p; i*) - let (il,tr) = build_jptree p in - if (il = []) then - begin - Pp.msgnl (Pp.str "Proof is built."); - do_coq_proof tr gls - end - else UT.error "Cannot reconstruct proof tree from JProver." - with e -> Pp.msgnl (Pp.str "JProver fails to prove this:"); - JT.print_error_msg e; - UT.error "JProver terminated." - -(* an unfailed generalization procedure *) -let non_dep_gen b gls = - let concl = TM.pf_concl gls in - if (not (Termops.dependent b concl)) then - T.generalize [b] gls - else - TCL.tclIDTAC gls - -let rec unfail_gen = function - | [] -> TCL.tclIDTAC - | h::r -> - TCL.tclTHEN - (TCL.tclORELSE (non_dep_gen h) (TCL.tclIDTAC)) - (unfail_gen r) - -(* -(* no argument, which stands for no multiplicity limit *) -let jp gls = - let ls = List.map (fst) (TM.pf_hyps_types gls) in -(*i T.generalize (List.map TR.mkVar ls) gls i*) - (* generalize the context *) - TCL.tclTHEN (TCL.tclTRY T.red_in_concl) - (TCL.tclTHEN (unfail_gen (List.map TR.mkVar ls)) - (jp None)) gls -*) -(* -let dyn_jp l gls = - assert (l = []); - jp -*) - -(* one optional integer argument for the multiplicity *) -let jpn n gls = - let ls = List.map (fst) (TM.pf_hyps_types gls) in - TCL.tclTHEN (TCL.tclTRY T.red_in_concl) - (TCL.tclTHEN (unfail_gen (List.map TR.mkVar ls)) - (jp n)) gls - -TACTIC EXTEND jprover - [ "jp" natural_opt(n) ] -> [ jpn n ] -END - -(* -TACTIC EXTEND Andl - [ "Andl" ident(id)] -> [ ... (Andl id) ... ]. -END -*) |