123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111(************************************************************************)(* * The Coq Proof Assistant / The Coq Development Team *)(* v * Copyright INRIA, CNRS and contributors *)(* <O___,, * (see version control and CREDITS file for authors & dates) *)(* \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) *)(************************************************************************)openUtilopenConstropenDeclarationsmoduleRelDecl=Context.Rel.Declarationletfind_mutually_recursive_statementssigmathms=letn=List.lengththmsinletinds=List.map(funx->lettyp=Declare.CInfo.get_typxinlet(hyps,ccl)=EConstr.decompose_prod_assumsigmatypinletwhnf_hyp_hds=EConstr.map_rel_context_in_env(funenvc->fst(Reductionops.whd_all_stackenvsigmac))(Global.env())hypsinletind_hyps=List.flatten(List.map_i(funidecl->lett=RelDecl.get_typedeclinmatchEConstr.kindsigmatwith|Ind((kn,_asind),u)whenletmind=Global.lookup_mindkninmind.mind_finite<>Declarations.CoFinite->[ind,x,i]|_->[])0(List.rev(List.filterContext.Rel.Declaration.is_local_assumwhnf_hyp_hds)))inletind_ccl=letcclenv=EConstr.push_rel_contexthyps(Global.env())inletwhnf_ccl,_=Reductionops.whd_all_stackcclenvEvd.emptycclinmatchEConstr.kindsigmawhnf_cclwith|Ind((kn,_asind),u)whenletmind=Global.lookup_mindkninInt.equalmind.mind_ntypesn&&mind.mind_finite==Declarations.CoFinite->[ind,x,0]|_->[]inind_hyps,ind_ccl)thmsinletinds_hyps,ind_ccls=List.splitindsinletof_same_mutind((kn,_),_,_)=function((kn',_),_,_)->Environ.QMutInd.equal(Global.env())knkn'in(* Check if all conclusions are coinductive in the same type *)(* (degenerated cartesian product since there is at most one coind ccl) *)letsame_indccl=List.cartesians_filter(funhypoks->ifList.for_all(of_same_mutindhyp)oksthenSome(hyp::oks)elseNone)[]ind_cclsinletordered_same_indccl=List.filter(List.for_all_i(funi((kn,j),_,_)->Int.equalij)0)same_indcclin(* Check if some hypotheses are inductive in the same type *)letcommon_same_indhyp=List.cartesians_filter(funhypoks->ifList.for_all(of_same_mutindhyp)oksthenSome(hyp::oks)elseNone)[]inds_hypsinletordered_inds,finite,guard=matchordered_same_indccl,common_same_indhypwith|indccl::rest,_->assert(List.is_emptyrest);(* One occ. of common coind ccls and no common inductive hyps *)ifnot(List.is_emptycommon_same_indhyp)thenFlags.if_verboseFeedback.msg_info(Pp.str"Assuming mutual coinductive statements.");flush_all();indccl,true,[]|[],_::_->let()=matchsame_indcclwith|ind::_->ifList.distinct_fNames.Ind.CanOrd.compare(List.mappi1ind)thenFlags.if_verboseFeedback.msg_info(Pp.strbrk("Coinductive statements do not follow the order of "^"definition, assuming the proof to be by induction."));flush_all()|_->()inletpossible_guards=List.map(List.mappi3)inds_hypsin(* assume the largest indices as possible *)List.lastcommon_same_indhyp,false,possible_guards|_,[]->CErrors.user_errPp.(str("Cannot find common (mutual) inductive premises or coinductive"^" conclusions in the statements."))in(finite,guard,None),ordered_indstypemutual_info=|NonMutualofEConstr.tDeclare.CInfo.t|Mutualof{mutual_info:Declare.Proof.mutual_info;cinfo:EConstr.tDeclare.CInfo.tlist;possible_guards:intlist}letlook_for_possibly_mutual_statementssigmathms:mutual_info=matchthmswith|[thm]->(* One non recursively proved theorem *)NonMutualthm|_::_asthms->(* More than one statement and/or an explicit decreasing mark: *)(* we look for a common inductive hyp or a common coinductive conclusion *)letrecguard,ordered_inds=find_mutually_recursive_statementssigmathmsinletcinfo=List.mappi2ordered_indsinMutual{mutual_info=recguard;cinfo;possible_guards=List.map(fun(_,_,i)->succi)ordered_inds}|[]->CErrors.anomaly(Pp.str"Empty list of theorems.")