diff options
| author | jforest | 2006-04-12 09:54:19 +0000 |
|---|---|---|
| committer | jforest | 2006-04-12 09:54:19 +0000 |
| commit | 4c75f521efe522d067323c9396be9a4c36d84de4 (patch) | |
| tree | 5f46f9354496530f779dfb0bb4a48f7872339b16 | |
| parent | dc9ba033ad41065fc9a0b632f364a37689213d17 (diff) | |
Simplifying the proof of principles
git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/coq/trunk@8702 85f007b7-540e-0410-9357-904b9bb8a0f7
| -rw-r--r-- | contrib/funind/new_arg_principle.ml | 967 |
1 files changed, 372 insertions, 595 deletions
diff --git a/contrib/funind/new_arg_principle.ml b/contrib/funind/new_arg_principle.ml index 0c20d4e736..8ef23c482e 100644 --- a/contrib/funind/new_arg_principle.ml +++ b/contrib/funind/new_arg_principle.ml @@ -67,34 +67,45 @@ let make_refl_eq type_of_t t = mkApp(refl_equal_term,[|type_of_t;t|]) -let congruence g = +type static_fix_info = + { + idx : int; + name : identifier; + types : types + } + +type static_infos = + { + fixes_ids : identifier list; + ptes_to_fixes : static_fix_info Idmap.t + } + +type 'a dynamic_info = + { + nb_rec_hyps : int; + rec_hyps : identifier list ; + eq_hyps : identifier list; + info : 'a + } + +let finish_proof dynamic_infos g = observe_tac "finish" -(* (Auto.default_auto) *) -(* (Eauto.gen_eauto false (false,5) [] (Some [])) *) h_assumption g let refine c = - if do_observe () - then Tacmach.refine c - else Tacmach.refine_no_check c + Tacmach.refine_no_check c let thin l = - if do_observe () - then Tacmach.thin l - else Tacmach.thin_no_check l + Tacmach.thin_no_check l let cut_replacing id t tac :tactic= - if do_observe () - then - Tactics.cut_replacing id t (fun _ -> tac ) - else - tclTHENS (cut t) - [ tclTHEN (thin_no_check [id]) (introduction_no_check id); - tac - ] + tclTHENS (cut t) + [ tclTHEN (thin_no_check [id]) (introduction_no_check id); + tac + ] let intro_erasing id = tclTHEN (thin [id]) (introduction id) @@ -126,17 +137,15 @@ let is_incompatible_eq t = incompatible_constructor_terms t1 t2 | _ -> false -let change_hyp_with_using hyp_id t tac = cut_replacing hyp_id t tac -(* let prov_id = id_of_string "_____" in *) -(* tclTHENLIST *) -(* [ *) -(* (forward *) -(* (Some (tclCOMPLETE prove_equiv)) *) -(* (Genarg.IntroIdentifier prov_id) *) -(* new_hyp_typ) ; *) -(* clear [hyp_id]; *) -(* rename_hyp prov_id hyp_id *) -(* ] *) +let change_hyp_with_using hyp_id t tac = + fun g -> + let prov_id = pf_get_new_id hyp_id g in + tclTHENLIST + [ + forward (Some tac) (Genarg.IntroIdentifier prov_id) t; + thin [hyp_id]; + h_rename prov_id hyp_id + ] g exception TOREMOVE @@ -362,12 +371,12 @@ let change_eq env sigma hyp_id (context:Sign.rel_context) x t end_of_type = -let is_property ptes_to_fix t_x = +let is_property static_info t_x = if isApp t_x then let pte,args = destApp t_x in if isVar pte && array_for_all closed0 args - then Idmap.mem (destVar pte) ptes_to_fix + then Idmap.mem (destVar pte) static_info.ptes_to_fixes else false else false @@ -377,7 +386,106 @@ let isLetIn t = | _ -> false -let rec clean_hyp_with_heq fixes_ids ptes_to_fix hyp_id env sigma = +let h_reduce_with_zeta = + h_reduce + (Rawterm.Cbv + {Rawterm.all_flags + with Rawterm.rDelta = false; + }) + +(* +let rewrite_until_var arg_num : tactic = + let constr_eq = Lazy.force eq in + let replace_if_unify arg (pat,cl,id,lhs) : tactic = + fun g -> + try + let (evd,matched) = + Unification.w_unify_to_subterm + (pf_env g) ~mod_delta:false (pat,arg) cl.Clenv.env + in + let cl' = {cl with Clenv.env = evd } in + let c2 = Clenv.clenv_nf_meta cl' lhs in + (Equality.replace matched c2) g + with _ -> tclFAIL 0 (str "") g + in + let rewrite_on_step equalities : tactic = + fun g -> + match kind_of_term (pf_concl g) with + | App(_,args) when (not (test_var args arg_num)) -> +(* tclFIRST (List.map (fun a -> observe_tac (str "replace_if_unify") (replace_if_unify args.(arg_num) a)) equalities) g *) + tclFIRST (List.map (replace_if_unify args.(arg_num)) equalities) g + | _ -> + raise (Util.UserError("", (str "No more rewrite" ++ + pr_lconstr_env (pf_env g) (pf_concl g)))) + in + fun g -> + let equalities = + List.filter + ( + fun (_,_,id_t) -> + match kind_of_term id_t with + | App(f,_) -> eq_constr f constr_eq + | _ -> false + ) + (pf_hyps g) + in + let f (id,_,ctype) = + let c = mkVar id in + let eqclause = Clenv.make_clenv_binding g (c,ctype) Rawterm.NoBindings in + let clause_type = Clenv.clenv_type eqclause in + let f,args = decompose_app (clause_type) in + let rec split_last_two = function + | [c1;c2] -> (c1, c2) + | x::y::z -> + split_last_two (y::z) + | _ -> + error ("The term provided is not an equivalence") + in + let (c1,c2) = split_last_two args in + (c2,eqclause,id,c1) + in + let matching_hyps = List.map f equalities in + tclTRY (tclREPEAT (tclPROGRESS (rewrite_on_step matching_hyps))) g + +*) + + +let rewrite_until_var arg_num eq_ids : tactic = + let test_var g = + let _,args = destApp (pf_concl g) in + isVar args.(arg_num) + in + let rec do_rewrite eq_ids g = + if test_var g + then tclIDTAC g + else + match eq_ids with + | [] -> anomaly "Cannot find a way to prove recursive property"; + | eq_id::eq_ids -> + tclTHEN + (tclTRY (Equality.rewriteRL (mkVar eq_id))) + (do_rewrite eq_ids) + g + in + do_rewrite eq_ids + +let prove_rec_hyp eq_hyps fix_info = + tclTHEN + (rewrite_until_var (fix_info.idx - 1) eq_hyps) + (fun g -> + let _,pte_args = destApp (pf_concl g) in + let rec_hyp_proof = + mkApp(mkVar fix_info.name,array_get_start pte_args) + in + refine rec_hyp_proof g + ) + + + + + +let rec_pte_id = id_of_string "Hrec" +let clean_hyp_with_heq static_infos eq_hyps hyp_id env sigma = let coq_False = Coqlib.build_coq_False () in let coq_True = Coqlib.build_coq_True () in let coq_I = Coqlib.build_coq_I () in @@ -391,11 +499,7 @@ let rec clean_hyp_with_heq fixes_ids ptes_to_fix hyp_id env sigma = in tclTHENLIST [ - h_reduce - (Rawterm.Cbv - {Rawterm.all_flags - with Rawterm.rDelta = false; - }) + h_reduce_with_zeta (Tacticals.onHyp hyp_id) ; scan_type new_context new_typ_of_hyp @@ -405,10 +509,10 @@ let rec clean_hyp_with_heq fixes_ids ptes_to_fix hyp_id env sigma = then begin let (x,t_x,t') = destProd type_of_hyp in - if is_property ptes_to_fix t_x then + if is_property static_infos t_x then begin let pte,pte_args = (destApp t_x) in - let (_,_,fix_id,_) = Idmap.find (destVar pte) ptes_to_fix in + let fix_info = Idmap.find (destVar pte) static_infos.ptes_to_fixes in let popped_t' = pop t' in let real_type_of_hyp = it_mkProd_or_LetIn ~init:popped_t' context in let prove_new_type_of_hyp = @@ -421,13 +525,21 @@ let rec clean_hyp_with_heq fixes_ids ptes_to_fix hyp_id env sigma = fst (list_chop ~msg:"rec hyp : context_hyps" context_length (pf_ids_of_hyps g)) in - let rec_hyp_proof = mkApp(mkVar fix_id,array_get_start pte_args) in + let rec_pte_id = pf_get_new_id rec_pte_id g in let to_refine = applist(mkVar hyp_id, - List.rev_map mkVar (context_hyps_ids)@[rec_hyp_proof] + List.rev_map mkVar (rec_pte_id::context_hyps_ids) ) in - refine to_refine g + tclTHENLIST + [ + forward + (Some (prove_rec_hyp eq_hyps fix_info)) + (Genarg.IntroIdentifier rec_pte_id) + t_x; + refine to_refine + ] + g ) ] in @@ -514,9 +626,7 @@ let rec clean_hyp_with_heq fixes_ids ptes_to_fix hyp_id env sigma = thin [hyp_id],[] -let clean_goal_with_heq - fixes_ids ptes_to_fix continue_tac hyps body heq_id - = +let clean_goal_with_heq static_infos continue_tac dyn_infos = fun g -> let env = pf_env g and sigma = project g @@ -524,83 +634,87 @@ let clean_goal_with_heq let tac,new_hyps = List.fold_left ( fun (hyps_tac,new_hyps) hyp_id -> - let hyp_tac,new_hyp = - clean_hyp_with_heq fixes_ids ptes_to_fix hyp_id env sigma + clean_hyp_with_heq static_infos dyn_infos.eq_hyps hyp_id env sigma in (tclTHEN hyp_tac hyps_tac),new_hyp@new_hyps ) (tclIDTAC,[]) - hyps + dyn_infos.rec_hyps + in + let new_infos = + { dyn_infos with + rec_hyps = new_hyps; + nb_rec_hyps = List.length new_hyps + } in tclTHENLIST [ tac ; - (continue_tac new_hyps body) + (continue_tac new_infos) ] g -let treat_new_case fixes_ids ptes_to_fix nb_prod continue_tac hyps term body = - tclTHENLIST - [ - (* We first introduce the variables *) - tclDO (nb_prod - 1) intro; - (* Then the equation itself *) - intro; - (fun g' -> - (* We get infos on the equations introduced*) - let (heq_id,_,new_term_value_eq) = pf_last_hyp g' in - (* compute the new value of the body *) - let new_term_value = - match kind_of_term new_term_value_eq with - | App(f,[| _;_;args2 |]) -> args2 - | _ -> - observe (pr_gls g' ++ fnl () ++ str "last hyp is" ++ - pr_lconstr_env (pf_env g') new_term_value_eq - ); +let heq_id = id_of_string "Heq" + +let treat_new_case static_infos nb_prod continue_tac term dyn_infos = + fun g -> + let heq_id = pf_get_new_id heq_id g in + let nb_first_intro = nb_prod - 1 - dyn_infos.nb_rec_hyps in + tclTHENLIST + [ + (* We first introduce the variables *) + tclDO nb_first_intro (intro_avoiding dyn_infos.rec_hyps); + (* Then the equation itself *) + introduction_no_check heq_id; + (* Then the new hypothesis *) + tclMAP introduction_no_check dyn_infos.rec_hyps; + observe_tac "after_introduction" (fun g' -> + (* We get infos on the equations introduced*) + let new_term_value_eq = pf_type_of g' (mkVar heq_id) in + (* compute the new value of the body *) + let new_term_value = + match kind_of_term new_term_value_eq with + | App(f,[| _;_;args2 |]) -> args2 + | _ -> + observe (pr_gls g' ++ fnl () ++ str "last hyp is" ++ + pr_lconstr_env (pf_env g') new_term_value_eq + ); assert false - in + in let fun_body = - mkLambda(Anonymous,pf_type_of g' term,replace_term term (mkRel 1) body) + mkLambda(Anonymous, + pf_type_of g' term, + replace_term term (mkRel 1) dyn_infos.info + ) in let new_body = pf_nf_betaiota g' (mkApp(fun_body,[| new_term_value |])) in - (* and - 1- rewrite heq in all hyps - 2- call the cleanning tactic - *) - let tac_rew hyp_id = - tclTHENLIST - [ h_reduce - (Rawterm.Cbv - {Rawterm.all_flags - with Rawterm.rDelta = false; - }) - (Tacticals.onHyp hyp_id) - ; - tclTRY (Equality.general_rewrite_in true hyp_id (mkVar heq_id)) - ] + let new_infos = + {dyn_infos with + info = new_body; + eq_hyps = heq_id::dyn_infos.eq_hyps + } in - tclTHENLIST - [ - tclMAP tac_rew hyps; - ( clean_goal_with_heq fixes_ids ptes_to_fix continue_tac hyps new_body heq_id) - ] - g' + clean_goal_with_heq static_infos continue_tac new_infos g' ) ] + g -let rec new_do_prove_princ_for_struct +let do_prove_princ_for_struct (interactive_proof:bool) (fnames:constant list) - (ptes:identifier list) - (fixes:(int*constr*identifier*constr) Idmap.t) - (hyps: identifier list) - (term:constr) : tactic = - let fixes_ids = Idmap.fold (fun _ (_,_,id,_) acc -> id::acc) fixes [] in - let rec do_prove_princ_for_struct_aux do_finalize hyps term = + static_infos +(* (ptes:identifier list) *) +(* (fixes:(int*constr*identifier*constr) Idmap.t) *) +(* (hyps: identifier list) *) +(* (term:constr) *) + dyn_infos + : tactic = +(* let fixes_ids = Idmap.fold (fun _ (_,_,id,_) acc -> id::acc) fixes [] in *) + let rec do_prove_princ_for_struct_aux do_finalize dyn_infos : tactic = fun g -> (* observe (str "proving on " ++ Printer.pr_lconstr_env (pf_env g) term);*) - match kind_of_term term with + match kind_of_term dyn_infos.info with | Case(_,_,t,_) -> let g_nb_prod = nb_prod (pf_concl g) in let type_of_term = pf_type_of g t in @@ -609,19 +723,20 @@ let rec new_do_prove_princ_for_struct in tclTHENSEQ [ - h_generalize [term_eq]; + h_generalize (term_eq::List.map mkVar dyn_infos.rec_hyps); + thin dyn_infos.rec_hyps; pattern_option [[-1],t] None; - simplest_case t; + h_simplest_case t; (fun g' -> let g'_nb_prod = nb_prod (pf_concl g') in let nb_instanciate_partial = g'_nb_prod - g_nb_prod in - treat_new_case - fixes_ids fixes + observe_tac "treat_new_case" + (treat_new_case + static_infos nb_instanciate_partial (do_prove_princ_for_struct do_finalize) - hyps t - term + dyn_infos) g' ) @@ -634,471 +749,104 @@ let rec new_do_prove_princ_for_struct intro (fun g' -> let (id,_,_) = pf_last_hyp g' in - let new_term = pf_nf_betaiota g' (mkApp(term,[|mkVar id|])) in - do_prove_princ_for_struct do_finalize hyps new_term g' + let new_term = + pf_nf_betaiota g' + (mkApp(dyn_infos.info,[|mkVar id|])) + in + let new_infos = {dyn_infos with info = new_term} in + do_prove_princ_for_struct do_finalize new_infos g' ) g | _ -> - do_finalize hyps term g + do_finalize dyn_infos g end - | Cast(t,_,_) -> do_prove_princ_for_struct do_finalize hyps t g + | Cast(t,_,_) -> + do_prove_princ_for_struct do_finalize {dyn_infos with info = t} g | Const _ | Var _ | Meta _ | Evar _ | Sort _ | Construct _ | Ind _ -> - do_finalize hyps term g + do_finalize dyn_infos g | App(_,_) -> - let f,args = decompose_app term in + let f,args = decompose_app dyn_infos.info in begin match kind_of_term f with | Var _ | Construct _ | Rel _ | Evar _ | Meta _ | Ind _ -> - do_prove_princ_for_struct_args do_finalize hyps f args g + let new_infos = + { dyn_infos with + info = (f,args) + } + in + do_prove_princ_for_struct_args do_finalize new_infos g | Const c when not (List.mem c fnames) -> - do_prove_princ_for_struct_args do_finalize hyps f args g + let new_infos = + { dyn_infos with + info = (f,args) + } + in + do_prove_princ_for_struct_args do_finalize new_infos g | Const _ -> - do_finalize hyps term g + do_finalize dyn_infos g | _ -> - observe - (str "Applied binders not yet implemented: in "++ fnl () ++ - pr_lconstr_env (pf_env g) term ++ fnl () ++ - pr_lconstr_env (pf_env g) f ++ spc () ++ str "is applied") ; +(* observe *) +(* (str "Applied binders not yet implemented: in "++ fnl () ++ *) +(* pr_lconstr_env (pf_env g) term ++ fnl () ++ *) +(* pr_lconstr_env (pf_env g) f ++ spc () ++ str "is applied") ; *) tclFAIL 0 (str "TODO : Applied binders not yet implemented") g end | Fix _ | CoFix _ -> error ( "Anonymous local (co)fixpoints are not handled yet") | Prod _ -> assert false - - | LetIn (Name id,v,t,b) -> - do_prove_princ_for_struct do_finalize hyps (subst1 v b) g - | LetIn(Anonymous,_,_,b) -> - do_prove_princ_for_struct do_finalize hyps (pop b) g + | LetIn _ -> + let new_infos = + { dyn_infos with + info = nf_betaoiotazeta dyn_infos.info + } + in + + tclTHENLIST + [tclMAP + (fun hyp_id -> h_reduce_with_zeta (Tacticals.onHyp hyp_id)) + dyn_infos.rec_hyps; + h_reduce_with_zeta Tacticals.onConcl; + do_prove_princ_for_struct do_finalize new_infos + ] g | _ -> errorlabstrm "" (str "in do_prove_princ_for_struct found : "(* ++ *) (* pr_lconstr_env (pf_env g) term *) ) - and do_prove_princ_for_struct do_finalize hyps term g = + and do_prove_princ_for_struct do_finalize dyn_infos g = (* observe (str "proving with "++Printer.pr_lconstr term++ str " on goal " ++ pr_gls g); *) - do_prove_princ_for_struct_aux do_finalize hyps term g - and do_prove_princ_for_struct_args do_finalize hyps f_args' args :tactic = + do_prove_princ_for_struct_aux do_finalize dyn_infos g + and do_prove_princ_for_struct_args do_finalize dyn_infos (* f_args' args *) :tactic = fun g -> (* if Tacinterp.get_debug () <> Tactic_debug.DebugOff *) (* then msgnl (str "do_prove_princ_for_struct_args with " ++ *) (* pr_lconstr_env (pf_env g) f_args' *) (* ); *) + let (f_args',args) = dyn_infos.info in let tac = match args with | [] -> - do_finalize hyps f_args' + do_finalize {dyn_infos with info = f_args'} | arg::args -> - let do_finalize hyps new_arg = + let do_finalize dyn_infos = + let new_arg = dyn_infos.info in tclTRYD (do_prove_princ_for_struct_args do_finalize - hyps - (mkApp(f_args',[|new_arg|])) - args + {dyn_infos with info = (mkApp(f_args',[|new_arg|])), args} ) in - do_prove_princ_for_struct do_finalize hyps arg + do_prove_princ_for_struct do_finalize + {dyn_infos with info = arg } in tclTRYD(tac ) g in - do_prove_princ_for_struct (fun hyps term -> congruence) hyps term - - - - - - - - - - - - - - - - - - - - - - - - - -type rewrite_dir = - | LR - | RL - -let rew_all ?(rev_order=false) lr : tactic = - let rew = - match lr with - | LR -> Equality.rewriteLR - | RL -> Equality.rewriteRL - in - let order = - if rev_order then List.rev else fun x -> x - in - fun g -> - onHyps - pf_hyps - (fun l -> tclMAP (fun (id,_,_) -> tclTRY (rew (mkVar id))) (order l)) - g -let rew_all_in_list ?(rev_order=false) idl lr : tactic = - let rew = - match lr with - | LR -> Equality.rewriteLR - | RL -> Equality.rewriteRL - in - let order = - if rev_order then List.rev else fun x -> x - in - fun g -> - tclMAP (fun id -> tclTRY (rew (mkVar id))) (order idl) g - - -let rewrite_and_try_tac ?(rev_order=false) lr tac eqs : tactic = - let rew = - match lr with - | LR -> Equality.rewriteLR - | RL -> Equality.rewriteRL - in - let order = - if rev_order then List.rev else fun x -> x - in - let rec rewrite_and_try_tac = function - | [] -> tclCOMPLETE tac - | id::idl -> - let other_tac = rewrite_and_try_tac idl in - tclFIRST - [ - other_tac; - - - tclTHEN - (rew (mkVar id)) - (tclFIRST - [ - other_tac; - tclCOMPLETE tac - ] - ) - ] - in - rewrite_and_try_tac (order eqs) - - - -let test_var args arg_num = - isVar args.(arg_num) - - - -let rewrite_until_var arg_num : tactic = - let constr_eq = (Coqlib.build_coq_eq_data ()).Coqlib.eq in - let replace_if_unify arg (pat,cl,id,lhs) : tactic = - fun g -> - try - let (evd,matched) = - Unification.w_unify_to_subterm - (pf_env g) ~mod_delta:false (pat,arg) cl.Clenv.env - in - let cl' = {cl with Clenv.env = evd } in - let c2 = Clenv.clenv_nf_meta cl' lhs in - (Equality.replace matched c2) g - with _ -> tclFAIL 0 (str "") g - in - let rewrite_on_step equalities : tactic = - fun g -> - match kind_of_term (pf_concl g) with - | App(_,args) when (not (test_var args arg_num)) -> -(* tclFIRST (List.map (fun a -> observe_tac (str "replace_if_unify") (replace_if_unify args.(arg_num) a)) equalities) g *) - tclFIRST (List.map (replace_if_unify args.(arg_num)) equalities) g - | _ -> - raise (Util.UserError("", (str "No more rewrite" ++ - pr_lconstr_env (pf_env g) (pf_concl g)))) - in - fun g -> - let equalities = - List.filter - ( - fun (_,_,id_t) -> - match kind_of_term id_t with - | App(f,_) -> eq_constr f constr_eq - | _ -> false - ) - (pf_hyps g) - in - let f (id,_,ctype) = - let c = mkVar id in - let eqclause = Clenv.make_clenv_binding g (c,ctype) Rawterm.NoBindings in - let clause_type = Clenv.clenv_type eqclause in - let f,args = decompose_app (clause_type) in - let rec split_last_two = function - | [c1;c2] -> (c1, c2) - | x::y::z -> - split_last_two (y::z) - | _ -> - error ("The term provided is not an equivalence") - in - let (c1,c2) = split_last_two args in - (c2,eqclause,id,c1) - in - let matching_hyps = List.map f equalities in - tclTRY (tclREPEAT (tclPROGRESS (rewrite_on_step matching_hyps))) g - - - -let case_eq tac eqs body term g = -(* msgnl (str "case_eq on " ++ pr_lconstr_env (pf_env g) term); *) - let type_of_term = pf_type_of g term in - let term_eq = - make_refl_eq type_of_term term + let do_finish_proof dyn_infos = + clean_goal_with_heq + static_infos + finish_proof dyn_infos in - let ba_fun ba : tactic = - fun g -> - tclTHENSEQ - [intro_patterns [](* ba.branchnames *); - fun g -> - let (id,_,new_term_value_eq) = pf_last_hyp g in - let new_term_value = - match kind_of_term new_term_value_eq with - | App(f,[| _;_;args2 |]) -> args2 - | _ -> - Pp.msgnl (pr_gls g ++ fnl () ++ str "last hyp is" ++ - pr_lconstr_env (pf_env g) new_term_value_eq - ); - assert false - in - let fun_body = - mkLambda(Anonymous,type_of_term,replace_term term (mkRel 1) body) - in - let new_body = mkApp(fun_body,[| new_term_value |]) in - tac (pf_nf_betaiota g new_body) (id::eqs) g - ] - g - in - ( - tclTHENSEQ - [ - h_generalize [term_eq]; - pattern_option [[-1],term] None; - case_then_using Genarg.IntroAnonymous (ba_fun) None ([],[]) term - ] - ) - g - - - -(* let my_reflexivity : tactic = *) -(* let test_eq = *) -(* lazy (eq_constr (Coqlib.build_coq_eq ())) *) -(* in *) -(* let build_reflexivity = *) -(* lazy (fun ty t -> mkApp((Coqlib.build_coq_eq_data ()).Coqlib.refl,[|ty;t|])) *) -(* in *) -(* fun g -> *) -(* begin *) -(* match kind_of_term (pf_concl g) with *) -(* | App(eq,[|ty;t1;t2|]) when (Lazy.force test_eq) eq -> *) -(* if not (Termops.occur_existential t1) *) -(* then tclTHEN (h_change None (mkApp(eq,[|ty;t1;t1|])) onConcl ) (apply ((Lazy.force build_reflexivity) ty t1)) *) -(* else if not (Termops.occur_existential t2) *) -(* then tclTHEN (h_change None (mkApp(eq,[|ty;t2;t2|])) onConcl ) (apply ((Lazy.force build_reflexivity) ty t2)) *) -(* else tclFAIL 0 (str "") *) - -(* | _ -> tclFAIL 0 (str "") *) -(* end g *) - -let eauto : tactic = - fun g -> - tclFIRST - [ - Eauto.e_assumption - ; - h_exact (Coqlib.build_coq_I ()); - tclCOMPLETE - (Eauto.gen_eauto false (false,1) [] (Some [])) - ] - g - -let do_eauto eqs :tactic = - tclFIRST - [ -(* rewrite_and_try_tac LR eauto eqs; *) -(* rewrite_and_try_tac RL eauto eqs; *) - rewrite_and_try_tac ~rev_order:true LR eauto eqs; -(* rewrite_and_try_tac ~rev_order:true RL eauto eqs *) - ] - -let conclude fixes eqs g = -(* let clear_fixes = *) -(* let l = Idmap.fold (fun _ (_,_,id,_) acc -> id::acc) fixes [] in *) -(* h_clear false l *) -(* in *) - match kind_of_term (pf_concl g) with - | App(pte,args) -> - let tac = - if isVar pte - then - try - let idxs,body,this_fix_id,new_type = Idmap.find (destVar pte) fixes - in - let idx = idxs - 1 in - tclTHEN - (rewrite_until_var idx) - (* If we have an IH then with use the fixpoint *) - (Eauto.e_resolve_constr (mkVar this_fix_id)) - (* And left the generated subgoals to eauto *) - with Not_found -> (* this is not a pte *) - tclIDTAC - else tclIDTAC - in - tclTHENSEQ [tac; do_eauto eqs ] - g - | _ -> do_eauto eqs g - - -let finalize_proof interactive_proof fixes hyps fnames term eqs = - tclORELSE - ( - tclFIRST -(* ( *) -(* (List.map *) -(* (fun id -> tclTHEN (Eauto.e_resolve_constr (mkVar id)) *) -(* (tclCOMPLETE (conclude fixes eqs))) hyps *) -(* )@ *) - (List.map - (fun id -> - let tac = - tclTHENLIST - [ - (Eauto.e_resolve_constr (mkVar id)); - (tclCOMPLETE (conclude fixes eqs)) - ] - in - rewrite_and_try_tac RL tac eqs - ) - hyps - ) - - ) - (if interactive_proof then tclIDTAC else tclFAIL 0 (str "")) - - - - -let do_prove_princ_for_struct interactive_proof - (* (rec_pos:int option) *) (fnames:constant list) - (ptes:identifier list) (fixes:(int*constr*identifier*constr) Idmap.t) (hyps: identifier list) - (term:constr) : tactic = - let finalize_proof term eqs = - finalize_proof (* rec_pos *) interactive_proof fixes hyps fnames term eqs - in - let rec do_prove_princ_for_struct do_finalize term eqs g = -(* if Tacinterp.get_debug () <> Tactic_debug.DebugOff *) -(* then msgnl (str "Proving with body : " ++ pr_lconstr_env (pf_env g) term); *) - let tac = - fun g -> - match kind_of_term term with - | Case(_,_,t,_) -> - observe_tac "case_eq" - (case_eq (do_prove_princ_for_struct do_finalize) eqs term t) g - | Lambda(n,t,b) -> - begin - match kind_of_term( pf_concl g) with - | Prod _ -> - tclTHEN - intro - (fun g' -> - let (id,_,_) = pf_last_hyp g' in - let new_term = pf_nf_betaiota g' (mkApp(term,[|mkVar id|])) in - do_prove_princ_for_struct do_finalize new_term eqs g' - ) g - | _ -> - do_finalize term eqs g - end - | Cast(t,_,_) -> do_prove_princ_for_struct do_finalize t eqs g - | Const _ | Var _ | Meta _ | Evar _ | Sort _ | Construct _ | Ind _ -> - do_finalize term eqs g - | App(_,_) -> - let f,args = decompose_app term in - begin - match kind_of_term f with - | Var _ | Construct _ | Rel _ | Evar _ | Meta _ | Ind _ -> - do_prove_princ_for_struct_args do_finalize f args eqs g - | Const c when not (List.mem c fnames) -> - do_prove_princ_for_struct_args do_finalize f args eqs g - | Const _ -> - do_finalize term eqs g - | _ -> - observe - (str "Applied binders not yet implemented: in "++ fnl () ++ - pr_lconstr_env (pf_env g) term ++ fnl () ++ - pr_lconstr_env (pf_env g) f ++ spc () ++ str "is applied") ; - tclFAIL 0 (str "TODO : Applied binders not yet implemented") g - end - | Fix _ | CoFix _ -> - error ( "Anonymous local (co)fixpoints are not handled yet") - | Prod _ -> assert false - | LetIn (Name id,v,t,b) -> - do_prove_princ_for_struct do_finalize (subst1 v b) eqs g - | LetIn(Anonymous,_,_,b) -> - do_prove_princ_for_struct do_finalize (pop b) eqs g - | _ -> - errorlabstrm "" (str "in do_prove_princ_for_struct found : "(* ++ *) -(* pr_lconstr_env (pf_env g) term *) - ) - - in - tac g - and do_prove_princ_for_struct_args do_finalize f_args' args eqs :tactic = - fun g -> -(* if Tacinterp.get_debug () <> Tactic_debug.DebugOff *) -(* then msgnl (str "do_prove_princ_for_struct_args with " ++ *) -(* pr_lconstr_env (pf_env g) f_args' *) -(* ); *) - let tac = - match args with - | [] -> - do_finalize f_args' - | arg::args -> - let do_finalize new_arg eqs = - tclTRYD - (do_prove_princ_for_struct_args - do_finalize - (mkApp(f_args',[|new_arg|])) - args - eqs - ) - in - do_prove_princ_for_struct do_finalize arg - in - tclTRYD(tac eqs) g - - in - do_prove_princ_for_struct - (finalize_proof) - term - [] - - -let do_prove_princ_for_struct - (interactive_proof:bool) - (fnames:constant list) - (ptes:identifier list) - (fixes:(int*constr*identifier*constr) Idmap.t) - (hyps: identifier list) - (term:constr) - = - observe (str "start_proof"); - new_do_prove_princ_for_struct - (interactive_proof:bool) - (fnames:constant list) - (ptes:identifier list) - (fixes:(int*constr*identifier*constr) Idmap.t) - (hyps: identifier list) - (term:constr) + observe_tac "do_prove_princ_for_struct" + (do_prove_princ_for_struct do_finish_proof dyn_infos) let is_pte_type t = isSort (snd (decompose_prod t)) @@ -1114,9 +862,16 @@ let instanciate_hyps_with_args (do_prove:identifier list -> tactic) hyps args_id let instanciate_one_hyp hid = tclORELSE ( (* we instanciate the hyp if possible *) - tclTHENLIST - [h_generalize [mkApp(mkVar hid,args)]; - intro_erasing hid] +(* tclTHENLIST *) +(* [h_generalize [mkApp(mkVar hid,args)]; *) +(* intro_erasing hid] *) + fun g -> + let prov_hid = pf_get_new_id hid g in + tclTHENLIST[ + forward None (Genarg.IntroIdentifier prov_hid) (mkApp(mkVar hid,args)); + thin [hid]; + h_rename prov_hid hid + ] g ) ( (* if not then we are in a mutual function block @@ -1134,19 +889,26 @@ let instanciate_hyps_with_args (do_prove:identifier list -> tactic) hyps args_id in (* if no args then no instanciation ! *) if args_id = [] - then do_prove hyps + then + tclTHENLIST [ + tclMAP (fun hyp_id -> h_reduce_with_zeta (Tacticals.onHyp hyp_id)) hyps; + do_prove hyps + ] else - tclTHEN - (tclMAP instanciate_one_hyp hyps) - (fun g -> - let all_g_hyps_id = - List.fold_right Idset.add (pf_ids_of_hyps g) Idset.empty - in - let remaining_hyps = - List.filter (fun id -> Idset.mem id all_g_hyps_id) hyps - in - do_prove remaining_hyps g - ) + tclTHENLIST + [ + tclMAP (fun hyp_id -> h_reduce_with_zeta (Tacticals.onHyp hyp_id)) hyps; + tclMAP instanciate_one_hyp hyps; + (fun g -> + let all_g_hyps_id = + List.fold_right Idset.add (pf_ids_of_hyps g) Idset.empty + in + let remaining_hyps = + List.filter (fun id -> Idset.mem id all_g_hyps_id) hyps + in + do_prove remaining_hyps g + ) + ] let prove_princ_for_struct interactive_proof fun_num fnames all_funs _naprams : tactic = @@ -1200,9 +962,7 @@ let prove_princ_for_struct interactive_proof fun_num fnames all_funs _naprams : let this_fix_id = fresh_id !avoid "fix___" in avoid := this_fix_id::!avoid; (* let this_body = substl (List.rev fnames_as_constr) ca.(i) in *) - let this_body = substl (List.rev (Array.to_list all_funs)) ca.(i) in - let new_type = prod_applist typearray.(i) true_params - and new_body = Reductionops.nf_beta (applist(this_body,true_params)) in + let new_type = prod_applist typearray.(i) true_params in let new_type_args,_ = decompose_prod new_type in let nargs = List.length new_type_args in let pte_args = @@ -1213,7 +973,13 @@ let prove_princ_for_struct interactive_proof fun_num fnames all_funs _naprams : in let app_pte = applist(mkVar pte_id,pte_args) in let new_type = compose_prod new_type_args app_pte in - let fix_info = idxs.(i) - offset + 1,new_body,this_fix_id ,new_type in + let fix_info = + { + idx = idxs.(i) - offset + 1; + name = this_fix_id; + types = new_type + } + in pte_to_fix := Idmap.add pte_id fix_info !pte_to_fix; fix_info::acc ) @@ -1254,30 +1020,40 @@ let prove_princ_for_struct interactive_proof fun_num fnames all_funs _naprams : let pre_info,infos = list_chop fun_num infos in match pre_info,infos with | [],[] -> tclIDTAC g - | _,(idx,_,fix_id,_)::infos' -> + | _,this_fix_info::infos' -> let other_fix_info = - List.map (fun (idx,_,fix_id,fix_typ) -> fix_id,idx,fix_typ) (pre_info@infos') + List.map + (fun fix_info -> fix_info.name,fix_info.idx,fix_info.types) + (pre_info@infos') in tclORELSE - (h_mutual_fix fix_id idx other_fix_info) - (tclFAIL 1000 (str "bad index" ++ str (string_of_int idx) ++ + (h_mutual_fix this_fix_info.name this_fix_info.idx other_fix_info) + (tclFAIL 1000 (str "bad index" ++ + str (string_of_int this_fix_info.idx) ++ str "offset := " ++ (str (string_of_int offset)))) g | _,[] -> anomaly "Not a valid information" in - let do_prove pte_to_fix args branches : tactic = + let do_prove ptes_to_fixes args branches : tactic = fun g -> + let static_infos = + { + ptes_to_fixes = ptes_to_fixes; + fixes_ids = + Idmap.fold + (fun _ fix_info acc -> fix_info.name::acc) + ptes_to_fixes [] + } + in match kind_of_term (pf_concl g) with | App(pte,pte_args) when isVar pte -> begin let pte = destVar pte in try - let (_idx,_new_body,_this_fix_id,_new_type) = - try Idmap.find pte pte_to_fix with _ -> raise Not_Rec - in - let nparams = List.length !params in - let args_as_constr = List.map mkVar args in + if not (Idmap.mem pte ptes_to_fixes) then raise Not_Rec; + let nparams = List.length !params in + let args_as_constr = List.map mkVar args in let rec_num,new_body = let idx' = list_index pte (List.rev !predicates) - 1 in let f = fnames.(idx') in @@ -1294,12 +1070,11 @@ let prove_princ_for_struct interactive_proof fun_num fnames all_funs _naprams : Reductionops.nf_beta (applist(new_body,List.rev args_as_constr)) in - let do_prove = + let do_prove branches applied_body = do_prove_princ_for_struct interactive_proof (Array.to_list fnames) - !predicates - pte_to_fix + static_infos branches applied_body in @@ -1315,10 +1090,17 @@ let prove_princ_for_struct interactive_proof fun_num fnames all_funs _naprams : (Equality.replace (array_last pte_args) applied_body) g ) [ - do_prove; + clean_goal_with_heq + static_infos do_prove + { + nb_rec_hyps = List.length branches; + rec_hyps = branches; + info = applied_body; + eq_hyps = []; + } ; try let id = List.nth (List.rev args_as_constr) (rec_num) in -(* observe (str "choosen var := "++ pr_lconstr id); *) + (* observe (str "choosen var := "++ pr_lconstr id); *) (tclTHENSEQ [(h_simplest_case id); Tactics.intros_reflexivity @@ -1332,16 +1114,26 @@ let prove_princ_for_struct interactive_proof fun_num fnames all_funs _naprams : let fname = destConst (fst (decompose_app (array_last pte_args))) in tclTHEN (unfold_in_concl [([],Names.EvalConstRef fname)]) - (observe_tac "" (fun g' -> - do_prove_princ_for_struct - interactive_proof - (Array.to_list fnames) - !predicates - pte_to_fix - branches - (array_last (snd (destApp (pf_concl g')))) - g' - )) + (observe_tac "" + (fun g' -> + let body = array_last (snd (destApp (pf_concl g'))) in + let dyn_infos = + { nb_rec_hyps = List.length branches; + rec_hyps = branches; + info = body; + eq_hyps = [] + } + in + let do_prove = + do_prove_princ_for_struct + interactive_proof + (Array.to_list fnames) + static_infos + in + clean_goal_with_heq static_infos + do_prove dyn_infos g' + ) + ) g end | _ -> assert false @@ -1352,16 +1144,6 @@ let prove_princ_for_struct interactive_proof fun_num fnames all_funs _naprams : (fun g -> observe_tac "introducing predicate" (intro_with_remembrance predicates princ_info.npredicates) g); (fun g -> observe_tac "introducing branches" (intro_with_remembrance branches princ_info.nbranches) g); (fun g -> observe_tac "declaring fix(es)" mk_fixes g); -(* (fun g -> *) -(* let args = ref [] in *) -(* tclTHENLIST *) -(* [ *) -(* (fun g -> observe_tac "introducing args" (intro_with_remembrance args princ_info.nargs) g); *) -(* (fun g -> observe_tac "instanciating rec hyps" (instanciate_hyps_with_args !branches (List.rev !args)) g); *) -(* (fun g -> observe_tac "proving" (fun g -> do_prove !pte_to_fix !args g) g) *) -(* ] *) -(* g *) -(* ) *) (fun g -> let nb_prod_g = nb_prod (pf_concl g) in tclTHENLIST [ @@ -1758,24 +1540,19 @@ let generate_functional_principle hook ; try - let tim1 = System.get_time () in + let _tim1 = System.get_time () in Pfedit.by (proof_tac (Array.map mkConst funs) mutr_nparams); - let tim2 = System.get_time () in - let _ = if do_observe () - then - begin - let dur1 = System.time_difference tim1 tim2 in - Pp.msgnl (str ("Time to compute proof: ") ++ str (string_of_float dur1)); - end - in + let _tim2 = System.get_time () in +(* begin *) +(* let dur1 = System.time_difference tim1 tim2 in *) +(* Pp.msgnl (str ("Time to compute proof: ") ++ str (string_of_float dur1)); *) +(* end; *) let do_save = not (do_observe ()) && not interactive_proof in let _ = try Options.silently Command.save_named true; - let dur2 = System.time_difference tim2 (System.get_time ()) in - if do_observe () - then - Pp.msgnl (str ("Time to check proof: ") ++ str (string_of_float dur2)); + let _dur2 = System.time_difference _tim2 (System.get_time ()) in +(* Pp.msgnl (str ("Time to check proof: ") ++ str (string_of_float dur2)); *) Options.if_verbose (fun () -> Pp.msgnl ( |
