123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189(************************************************************************)(* * 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) *)(************************************************************************)openNamesopenEnvironopenUtilopenVernacexpropenContext.Named.DeclarationmoduleNamedDecl=Context.Named.Declarationletknown_names=Summary.ref[]~name:"proofusing-nameset"letrecclose_fwdenvsigmas=lets'=List.fold_left(funsdecl->letvb=matchdeclwith|LocalAssum_->Id.Set.empty|LocalDef(_,b,_)->Termops.global_vars_setenvsigmabinletvty=Termops.global_vars_setenvsigma(NamedDecl.get_typedecl)inletvbty=Id.Set.unionvbvtyinifId.Set.exists(funv->Id.Set.memvs)vbtythenId.Set.add(NamedDecl.get_iddecl)(Id.Set.unionsvbty)elses)s(EConstr.named_contextenv)inifId.Set.equalss'thenselseclose_fwdenvsigmas'letset_of_typeenvsigmaty=List.fold_left(funaccty->Id.Set.union(Termops.global_vars_setenvsigmaty)acc)Id.Set.emptytyletfull_setenv=List.fold_rightId.Set.add(List.mapNamedDecl.get_id(named_contextenv))Id.Set.emptyletprocess_exprenvsigmaev_ty=letrecaux=function|SsEmpty->Id.Set.empty|SsType->v_ty|SsSingl{CAst.v=id}->set_of_idid|SsUnion(e1,e2)->Id.Set.union(auxe1)(auxe2)|SsSubstr(e1,e2)->Id.Set.diff(auxe1)(auxe2)|SsComple->Id.Set.diff(full_setenv)(auxe)|SsFwdClosee->close_fwdenvsigma(auxe)andset_of_idid=ifId.to_stringid="All"thenfull_setenvelseifCList.mem_assoc_fId.equalid!known_namesthenaux(CList.assoc_fId.equalid!known_names)elseId.Set.singletonidinauxeletprocess_exprenvsigmaety=letv_ty=set_of_typeenvsigmatyinlets=Id.Set.unionv_ty(process_exprenvsigmaev_ty)inId.Set.elementsstypet=Names.Id.Set.tletdefinition_usingenvevd~using~terms=letl=process_exprenvevdusingtermsinNames.Id.Set.(List.fold_rightaddlempty)letname_setidexpr=known_names:=(id,expr)::!known_namesletminimize_hypsenvids=letrecauxids=letids'=Id.Set.fold(funidalive->letimpl_by_id=Id.Set.removeid(really_neededenv(Id.Set.singletonid))inifId.Set.is_emptyimpl_by_idthenaliveelseId.Set.diffaliveimpl_by_id)idsidsinifId.Set.equalidsids'thenidselseauxids'inauxidsletremove_ids_and_letsenvsids=letnot_idsid=not(Id.Set.memidids)inletno_bodyid=named_bodyidenv=Noneinletdepsid=really_neededenv(Id.Set.singletonid)in(Id.Set.filter(funid->not_idsid&&(no_bodyid||Id.Set.existsnot_ids(Id.Set.filterno_body(depsid))))s)letrecord_proof_usingexpr=Aux_file.record_in_aux"suggest_proof_using"exprletdebug_proof_using=CDebug.create~name:"proof-using"()(* Variables in [skip] come from after the definition, so don't count
for "All". Used in the variable case since the env contains the
variable itself. *)letsuggest_commonenvppidusedids_typskip=letmoduleS=Id.SetinletopenPpinletpr_setparenss=letwrapppcmds=ifparens&&S.cardinals>1thenstr"("++ppcmds++str")"elseppcmdsinwrap(prlist_with_sep(fun_->str" ")Id.print(S.elementss))inletneeded=minimize_hypsenv(remove_ids_and_letsenvusedids_typ)inletall_needed=really_neededenvneededinletall=List.fold_left(funalld->S.add(NamedDecl.get_idd)all)S.empty(named_contextenv)inletall=S.diffallskipinletfwd_typ=close_fwdenv(Evd.from_envenv)ids_typinlet()=debug_proof_using(fun()->str"All "++pr_setfalseall++fnl()++str"Type "++pr_setfalseids_typ++fnl()++str"needed "++pr_setfalseneeded++fnl()++str"all_needed "++pr_setfalseall_needed++fnl()++str"Type* "++pr_setfalsefwd_typ)inletvalid_exprs=ref[]inletvalide=valid_exprs:=e::!valid_exprsinifS.is_emptyneededthenvalid(str"Type");ifS.equalall_neededfwd_typthenvalid(str"Type*");ifS.equalallall_neededthenvalid(str"All");valid(pr_setfalseneeded);Feedback.msg_info(str"The proof of "++ppid++spc()++str"should start with one of the following commands:"++spc()++v0(prlist_with_sepcut(funx->str"Proof using "++x++str". ")!valid_exprs));ifAux_file.recording()thenlets=string_of_ppcmds(prlist_with_sep(fun_->str";")(funx->x)!valid_exprs)inrecord_proof_usingsletsuggest_proof_using=reffalselet()=Goptions.(declare_bool_option{optdepr=false;optkey=["Suggest";"Proof";"Using"];optread=(fun()->!suggest_proof_using);optwrite=((:=)suggest_proof_using)})letsuggest_constantenvkn=if!suggest_proof_usingthenbeginletopenDeclarationsinletbody=lookup_constantknenvinletused=Id.Set.of_list@@List.mapNamedDecl.get_idbody.const_hypsinletids_typ=global_vars_setenvbody.const_typeinsuggest_commonenv(Printer.pr_constantenvkn)usedids_typId.Set.emptyendletsuggest_variableenvid=if!suggest_proof_usingthenbeginmatchlookup_namedidenvwith|LocalDef(_,body,typ)->letids_typ=global_vars_setenvtypinletids_body=global_vars_setenvbodyinletused=Id.Set.unionids_bodyids_typinsuggest_commonenv(Id.printid)usedids_typ(Id.Set.singletonid)|LocalAssum_->assertfalseendletvalue=refNoneletusing_to_stringus=Pp.string_of_ppcmds(Ppvernac.pr_usingus)letusing_from_stringus=Pcoq.Entry.parseG_vernac.section_subset_expr(Pcoq.Parsable.make(Stream.of_stringus))letproof_using_opt_name=["Default";"Proof";"Using"]let()=Goptions.(declare_stringopt_option{optdepr=false;optkey=proof_using_opt_name;optread=(fun()->Option.mapusing_to_string!value);optwrite=(funb->value:=Option.mapusing_from_stringb);})letget_default_proof_using()=!value