diff options
Diffstat (limited to 'contrib/funind/indfun_main.ml4')
-rw-r--r-- | contrib/funind/indfun_main.ml4 | 160 |
1 files changed, 122 insertions, 38 deletions
diff --git a/contrib/funind/indfun_main.ml4 b/contrib/funind/indfun_main.ml4 index 7b3d8cbd..61f26d30 100644 --- a/contrib/funind/indfun_main.ml4 +++ b/contrib/funind/indfun_main.ml4 @@ -13,37 +13,72 @@ open Topconstr open Indfun_common open Indfun open Genarg +open Pcoq -TACTIC EXTEND newfuninv - [ "functional" "inversion" ident(hyp) ident(fname) ] -> - [ - Invfun.invfun hyp fname - ] -END +let pr_binding prc = function + | loc, Rawterm.NamedHyp id, c -> hov 1 (Ppconstr.pr_id id ++ str " := " ++ cut () ++ prc c) + | loc, Rawterm.AnonHyp n, c -> hov 1 (int n ++ str " := " ++ cut () ++ prc c) + +let pr_bindings prc prlc = function + | Rawterm.ImplicitBindings l -> + brk (1,1) ++ str "with" ++ brk (1,1) ++ + Util.prlist_with_sep spc prc l + | Rawterm.ExplicitBindings l -> + brk (1,1) ++ str "with" ++ brk (1,1) ++ + Util.prlist_with_sep spc (fun b -> str"(" ++ pr_binding prlc b ++ str")") l + | Rawterm.NoBindings -> mt () + + +let pr_with_bindings prc prlc (c,bl) = + prc c ++ hv 0 (pr_bindings prc prlc bl) -let pr_fun_ind_using prc _ _ opt_c = - match opt_c with +let pr_fun_ind_using prc prlc _ opt_c = + match opt_c with | None -> mt () - | Some c -> spc () ++ hov 2 (str "using" ++ spc () ++ prc c) + | Some c -> spc () ++ hov 2 (str "using" ++ spc () ++ pr_with_bindings prc prlc c) ARGUMENT EXTEND fun_ind_using - TYPED AS constr_opt + TYPED AS constr_with_bindings_opt PRINTED BY pr_fun_ind_using -| [ "using" constr(c) ] -> [ Some c ] +| [ "using" constr_with_bindings(c) ] -> [ Some c ] | [ ] -> [ None ] END -let pr_intro_as_pat prc _ _ pat = - str "as" ++ spc () ++ pr_intro_pattern pat +TACTIC EXTEND newfuninv + [ "functional" "inversion" ident(hyp) ident(fname) fun_ind_using(princl)] -> + [ + fun g -> + let fconst = const_of_id fname in + let princ = + match princl with + | None -> + let f_ind_id = + ( + Indrec.make_elimination_ident + fname + (Tacticals.elimination_sort_of_goal g) + ) + in + let princ = const_of_id f_ind_id in + princ + | Some princ -> destConst (fst princ) + in + Invfun.invfun hyp fconst princ g + ] +END +let pr_intro_as_pat prc _ _ pat = + match pat with + | Some pat -> spc () ++ str "as" ++ spc () ++ pr_intro_pattern pat + | None -> mt () -ARGUMENT EXTEND with_names TYPED AS intro_pattern PRINTED BY pr_intro_as_pat -| [ "as" simple_intropattern(ipat) ] -> [ ipat ] -| [] ->[ IntroAnonymous ] +ARGUMENT EXTEND with_names TYPED AS intro_pattern_opt PRINTED BY pr_intro_as_pat +| [ "as" simple_intropattern(ipat) ] -> [ Some ipat ] +| [] ->[ None ] END @@ -61,16 +96,25 @@ let is_rec scheme_info = let choose_dest_or_ind scheme_info = if is_rec scheme_info then Tactics.new_induct - else - Tactics.new_destruct + else Tactics.new_destruct TACTIC EXTEND newfunind - ["new" "functional" "induction" constr(c) fun_ind_using(princl) with_names(pat)] -> + ["functional" "induction" ne_constr_list(cl) fun_ind_using(princl) with_names(pat)] -> [ + let pat = + match pat with + | None -> IntroAnonymous + | Some pat -> pat + in + let c = match cl with + | [] -> assert false + | [c] -> c + | c::cl -> applist(c,cl) + in let f,args = decompose_app c in fun g -> - let princ = + let princ,bindings = match princl with | None -> (* No principle is given let's find the good one *) let fname = @@ -86,7 +130,7 @@ TACTIC EXTEND newfunind (Tacticals.elimination_sort_of_goal g) ) in - mkConst(const_of_id princ_name ) + mkConst(const_of_id princ_name ),Rawterm.NoBindings | Some princ -> princ in let princ_type = Tacmach.pf_type_of g princ in @@ -98,12 +142,46 @@ TACTIC EXTEND newfunind in List.map (fun c -> Tacexpr.ElimOnConstr c) (args@c_list) in - let princ' = Some (princ,Rawterm.NoBindings) in - choose_dest_or_ind + let princ' = Some (princ,bindings) in + let princ_vars = + List.fold_right + (fun a acc -> + try Idset.add (destVar a) acc + with _ -> acc + ) + args + Idset.empty + in + let old_idl = List.fold_right Idset.add (Tacmach.pf_ids_of_hyps g) Idset.empty in + let old_idl = Idset.diff old_idl princ_vars in + let subst_and_reduce g = + let idl = + Util.map_succeed + (fun id -> + if Idset.mem id old_idl then failwith ""; + id + ) + (Tacmach.pf_ids_of_hyps g) + in + let flag = + Rawterm.Cbv + {Rawterm.all_flags + with Rawterm.rDelta = false; + } + in + Tacticals.tclTHEN + (Tacticals.tclMAP (fun id -> Tacticals.tclTRY (Equality.subst [id])) idl ) + (Hiddentac.h_reduce flag Tacticals.allClauses) + g + in + Tacticals.tclTHEN + (choose_dest_or_ind princ_infos args_as_induction_constr princ' - pat g + pat) + subst_and_reduce + g ] END @@ -111,7 +189,7 @@ END VERNAC ARGUMENT EXTEND rec_annotation2 [ "{" "struct" ident(id) "}"] -> [ Struct id ] | [ "{" "wf" constr(r) ident_opt(id) "}" ] -> [ Wf(r,id) ] -| [ "{" "mes" constr(r) ident_opt(id) "}" ] -> [ Mes(r,id) ] +| [ "{" "measure" constr(r) ident_opt(id) "}" ] -> [ Mes(r,id) ] END @@ -130,7 +208,7 @@ VERNAC ARGUMENT EXTEND rec_definition2 let check_one_name () = if List.length names > 1 then Util.user_err_loc - (Util.dummy_loc,"GenFixpoint", + (Util.dummy_loc,"Function", Pp.str "the recursive argument needs to be specified"); in let check_exists_args an = @@ -138,7 +216,7 @@ VERNAC ARGUMENT EXTEND rec_definition2 let id = match an with Struct id -> id | Wf(_,Some id) -> id | Mes(_,Some id) -> id | Wf(_,None) | Mes(_,None) -> failwith "check_exists_args" in (try ignore(Util.list_index (Name id) names - 1); annot with Not_found -> Util.user_err_loc - (Util.dummy_loc,"GenFixpoint", + (Util.dummy_loc,"Function", Pp.str "No argument named " ++ Nameops.pr_id id) ) with Failure "check_exists_args" -> check_one_name ();annot @@ -160,16 +238,11 @@ VERNAC ARGUMENT EXTEND rec_definitions2 END -VERNAC COMMAND EXTEND GenFixpoint - ["GenFixpoint" rec_definitions2(recsl)] -> +VERNAC COMMAND EXTEND Function + ["Function" rec_definitions2(recsl)] -> [ do_generate_principle false recsl] END -VERNAC COMMAND EXTEND IGenFixpoint - ["IGenFixpoint" rec_definitions2(recsl)] -> - [ do_generate_principle true recsl] -END - VERNAC ARGUMENT EXTEND fun_scheme_arg | [ ident(princ_name) ":=" "Induction" "for" ident(fun_name) "Sort" sort(s) ] -> [ (princ_name,fun_name,s) ] @@ -181,17 +254,28 @@ VERNAC ARGUMENT EXTEND fun_scheme_args END VERNAC COMMAND EXTEND NewFunctionalScheme - ["New" "Functional" "Scheme" fun_scheme_args(fas) ] -> + ["Functional" "Scheme" fun_scheme_args(fas) ] -> [ - New_arg_principle.make_scheme fas + try + Functional_principles_types.make_scheme fas + with Functional_principles_types.No_graph_found -> + match fas with + | (_,fun_name,_)::_ -> + begin + make_graph fun_name; + try Functional_principles_types.make_scheme fas + with Functional_principles_types.No_graph_found -> + Util.error ("Cannot generate induction principle(s)") + end + | _ -> assert false (* we can only have non empty list *) ] END VERNAC COMMAND EXTEND NewFunctionalCase - ["New" "Functional" "Case" fun_scheme_arg(fas) ] -> + ["Functional" "Case" fun_scheme_arg(fas) ] -> [ - New_arg_principle.make_case_scheme fas + Functional_principles_types.make_case_scheme fas ] END |