aboutsummaryrefslogtreecommitdiff
path: root/vernac/recLemmas.ml
diff options
context:
space:
mode:
Diffstat (limited to 'vernac/recLemmas.ml')
-rw-r--r--vernac/recLemmas.ml102
1 files changed, 102 insertions, 0 deletions
diff --git a/vernac/recLemmas.ml b/vernac/recLemmas.ml
new file mode 100644
index 0000000000..e6d428968c
--- /dev/null
+++ b/vernac/recLemmas.ml
@@ -0,0 +1,102 @@
+(************************************************************************)
+(* * The Coq Proof Assistant / The Coq Development Team *)
+(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
+(* <O___,, * (see CREDITS file for the list of authors) *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(* * (see LICENSE file for the text of the license) *)
+(************************************************************************)
+
+open Util
+open Constr
+open Declarations
+
+module RelDecl = Context.Rel.Declaration
+
+let find_mutually_recursive_statements sigma thms =
+ let n = List.length thms in
+ let inds = List.map (fun (id,(t,impls)) ->
+ let (hyps,ccl) = EConstr.decompose_prod_assum sigma t in
+ let x = (id,(t,impls)) in
+ let whnf_hyp_hds = EConstr.map_rel_context_in_env
+ (fun env c -> fst (Reductionops.whd_all_stack env sigma c))
+ (Global.env()) hyps in
+ let ind_hyps =
+ List.flatten (List.map_i (fun i decl ->
+ let t = RelDecl.get_type decl in
+ match EConstr.kind sigma t with
+ | Ind ((kn,_ as ind),u) when
+ let mind = Global.lookup_mind kn in
+ mind.mind_finite <> Declarations.CoFinite ->
+ [ind,x,i]
+ | _ ->
+ []) 0 (List.rev (List.filter Context.Rel.Declaration.is_local_assum whnf_hyp_hds))) in
+ let ind_ccl =
+ let cclenv = EConstr.push_rel_context hyps (Global.env()) in
+ let whnf_ccl,_ = Reductionops.whd_all_stack cclenv Evd.empty ccl in
+ match EConstr.kind sigma whnf_ccl with
+ | Ind ((kn,_ as ind),u) when
+ let mind = Global.lookup_mind kn in
+ Int.equal mind.mind_ntypes n && mind.mind_finite == Declarations.CoFinite ->
+ [ind,x,0]
+ | _ ->
+ [] in
+ ind_hyps,ind_ccl) thms in
+ let inds_hyps,ind_ccls = List.split inds in
+ let of_same_mutind ((kn,_),_,_) = function ((kn',_),_,_) -> Names.MutInd.equal kn kn' in
+ (* Check if all conclusions are coinductive in the same type *)
+ (* (degenerated cartesian product since there is at most one coind ccl) *)
+ let same_indccl =
+ List.cartesians_filter (fun hyp oks ->
+ if List.for_all (of_same_mutind hyp) oks
+ then Some (hyp::oks) else None) [] ind_ccls in
+ let ordered_same_indccl =
+ List.filter (List.for_all_i (fun i ((kn,j),_,_) -> Int.equal i j) 0) same_indccl in
+ (* Check if some hypotheses are inductive in the same type *)
+ let common_same_indhyp =
+ List.cartesians_filter (fun hyp oks ->
+ if List.for_all (of_same_mutind hyp) oks
+ then Some (hyp::oks) else None) [] inds_hyps in
+ let ordered_inds,finite,guard =
+ match ordered_same_indccl, common_same_indhyp with
+ | indccl::rest, _ ->
+ assert (List.is_empty rest);
+ (* One occ. of common coind ccls and no common inductive hyps *)
+ if not (List.is_empty common_same_indhyp) then
+ Flags.if_verbose Feedback.msg_info (Pp.str "Assuming mutual coinductive statements.");
+ flush_all ();
+ indccl, true, []
+ | [], _::_ ->
+ let () = match same_indccl with
+ | ind :: _ ->
+ if List.distinct_f Names.ind_ord (List.map pi1 ind)
+ then
+ Flags.if_verbose Feedback.msg_info
+ (Pp.strbrk
+ ("Coinductive statements do not follow the order of "^
+ "definition, assuming the proof to be by induction."));
+ flush_all ()
+ | _ -> ()
+ in
+ let possible_guards = List.map (List.map pi3) inds_hyps in
+ (* assume the largest indices as possible *)
+ List.last common_same_indhyp, false, possible_guards
+ | _, [] ->
+ CErrors.user_err Pp.(str
+ ("Cannot find common (mutual) inductive premises or coinductive" ^
+ " conclusions in the statements."))
+ in
+ (finite,guard,None), ordered_inds
+
+let look_for_possibly_mutual_statements sigma = function
+ | [id,(t,impls)] ->
+ (* One non recursively proved theorem *)
+ None,[id,(t,impls)],None
+ | _::_ as thms ->
+ (* More than one statement and/or an explicit decreasing mark: *)
+ (* we look for a common inductive hyp or a common coinductive conclusion *)
+ let recguard,ordered_inds = find_mutually_recursive_statements sigma thms in
+ let thms = List.map pi2 ordered_inds in
+ Some recguard,thms, Some (List.map (fun (_,_,i) -> succ i) ordered_inds)
+ | [] -> CErrors.anomaly (Pp.str "Empty list of theorems.")