123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258(************************************************************************)(* * 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) *)(************************************************************************)openUtilopenNamesopenNameopsopenConstropenConstrexpropenEConstropenLibnameslet()=CErrors.register_handlerbeginfunction|Rewrite.RewriteFailure(env,sigma,e)->lete=Himsg.explain_pretype_errorenvsigmaeinSomePp.(str"setoid rewrite failed: "++e)|_->NoneendmoduleTC=Typeclassesletclasses_dirpath=Names.DirPath.make(List.mapId.of_string["Classes";"Coq"])letinit_setoid()=ifis_dirpath_prefix_ofclasses_dirpath(Lib.cwd())then()elseCoqlib.check_required_library["Coq";"Setoids";"Setoid"]typerewrite_attributes={polymorphic:bool;global:bool}letrewrite_attributes=letopenAttributes.NotationsinAttributes.(polymorphic++program++locality)>>=fun((polymorphic,program),locality)->letglobal=not(Locality.make_section_localitylocality)inAttributes.Notations.return{polymorphic;global}(** Utility functions *)letfind_referencedirs=Coqlib.find_reference"generalized rewriting"dirs[@@warning"-3"]letlazy_find_referencedirs=letgr=lazy(find_referencedirs)infun()->Lazy.forcegrmodulePropGlobal=structletmorphisms=["Coq";"Classes";"Morphisms"]letrespectful_ref=lazy_find_referencemorphisms"respectful"letproper_class=letr=lazy(find_referencemorphisms"Proper")infunenvsigma->TC.class_infoenvsigma(Lazy.forcer)letproper_projenvsigma=mkConst(Option.get(List.hd(proper_classenvsigma).TC.cl_projs).TC.meth_const)end(* By default the strategy for "rewrite_db" is top-down *)letmkappcsl=CAst.make@@CAppExpl((qualid_of_ident(Id.of_strings),None),l)letdeclare_an_instancensargs=(((CAst.make@@Namen),None),CAst.make@@CAppExpl((qualid_of_strings,None),args))letdeclare_instanceaaeqns=declare_an_instancens[a;aeq]letget_localityb=ifbthenHints.SuperGlobalelseHints.Localletanew_instanceattsbinders(name,t)fields=letlocality=get_localityatts.globalinlet_id=Classes.new_instance~poly:atts.polymorphicnamebinderst(true,CAst.make@@CRecord(fields))~localityHints.empty_hint_infoin()letdeclare_instance_reflattsbindersaaeqnlemma=letinstance=declare_instanceaaeq(add_suffixn"_Reflexive")"Coq.Classes.RelationClasses.Reflexive"inanew_instanceattsbindersinstance[(qualid_of_ident(Id.of_string"reflexivity"),lemma)]letdeclare_instance_symattsbindersaaeqnlemma=letinstance=declare_instanceaaeq(add_suffixn"_Symmetric")"Coq.Classes.RelationClasses.Symmetric"inanew_instanceattsbindersinstance[(qualid_of_ident(Id.of_string"symmetry"),lemma)]letdeclare_instance_transattsbindersaaeqnlemma=letinstance=declare_instanceaaeq(add_suffixn"_Transitive")"Coq.Classes.RelationClasses.Transitive"inanew_instanceattsbindersinstance[(qualid_of_ident(Id.of_string"transitivity"),lemma)]letdeclare_relationatts?(binders=[])aaeqnreflsymmtrans=init_setoid();letinstance=declare_instanceaaeq(add_suffixn"_relation")"Coq.Classes.RelationClasses.RewriteRelation"inlet()=anew_instanceattsbindersinstance[]inmatch(refl,symm,trans)with(None,None,None)->()|(Somelemma1,None,None)->declare_instance_reflattsbindersaaeqnlemma1|(None,Somelemma2,None)->declare_instance_symattsbindersaaeqnlemma2|(None,None,Somelemma3)->declare_instance_transattsbindersaaeqnlemma3|(Somelemma1,Somelemma2,None)->let()=declare_instance_reflattsbindersaaeqnlemma1indeclare_instance_symattsbindersaaeqnlemma2|(Somelemma1,None,Somelemma3)->let()=declare_instance_reflattsbindersaaeqnlemma1inlet()=declare_instance_transattsbindersaaeqnlemma3inletinstance=declare_instanceaaeqn"Coq.Classes.RelationClasses.PreOrder"inanew_instanceattsbindersinstance[(qualid_of_ident(Id.of_string"PreOrder_Reflexive"),lemma1);(qualid_of_ident(Id.of_string"PreOrder_Transitive"),lemma3)]|(None,Somelemma2,Somelemma3)->let()=declare_instance_symattsbindersaaeqnlemma2inlet()=declare_instance_transattsbindersaaeqnlemma3inletinstance=declare_instanceaaeqn"Coq.Classes.RelationClasses.PER"inanew_instanceattsbindersinstance[(qualid_of_ident(Id.of_string"PER_Symmetric"),lemma2);(qualid_of_ident(Id.of_string"PER_Transitive"),lemma3)]|(Somelemma1,Somelemma2,Somelemma3)->let()=declare_instance_reflattsbindersaaeqnlemma1inlet()=declare_instance_symattsbindersaaeqnlemma2inlet()=declare_instance_transattsbindersaaeqnlemma3inletinstance=declare_instanceaaeqn"Coq.Classes.RelationClasses.Equivalence"inanew_instanceattsbindersinstance[(qualid_of_ident(Id.of_string"Equivalence_Reflexive"),lemma1);(qualid_of_ident(Id.of_string"Equivalence_Symmetric"),lemma2);(qualid_of_ident(Id.of_string"Equivalence_Transitive"),lemma3)]letcHole=CAst.make@@CHole(None,Namegen.IntroAnonymous,None)letproper_projectionenvsigmarty=letrel_vectnm=Array.initm(funi->mkRel(n+m-i))inletctx,inst=decompose_prod_assumsigmatyinletmor,args=destAppsigmainstinletinstarg=mkApp(r,rel_vect0(List.lengthctx))inletapp=mkApp(PropGlobal.proper_projenvsigma,Array.appendargs[|instarg|])init_mkLambda_or_LetInappctxletdeclare_projectionnameinstance_idr=letenv=Global.env()inletpoly=Environ.is_polymorphicenvrinletsigma=Evd.from_envenvinletsigma,c=Evd.fresh_globalenvsigmarinletty=Retyping.get_type_ofenvsigmacinletbody=proper_projectionenvsigmactyinletsigma,typ=Typing.type_ofenvsigmabodyinletctx,typ=decompose_prod_assumsigmatypinlettyp=letn=letrecauxt=matchEConstr.kindsigmatwith|App(f,[|a;a';rel;rel'|])whenisRefXsigma(PropGlobal.respectful_ref())f->succ(auxrel')|_->0inletinit=matchEConstr.kindsigmatypwithApp(f,args)whenisRefXsigma(PropGlobal.respectful_ref())f->mkApp(f,fst(Array.chop(Array.lengthargs-2)args))|_->typinauxinitinletctx,ccl=Reductionops.splay_prod_nenvsigma(3*n)typinit_mkProd_or_LetIncclctxinlettypes=Some(it_mkProd_or_LetIntypctx)inletkind=Decls.(IsDefinitionDefinition)inletimpargs,udecl=[],UState.default_univ_declinletcinfo=Declare.CInfo.make~name~impargs~typ:types()inletinfo=Declare.Info.make~kind~udecl~poly()inlet_r:GlobRef.t=Declare.declare_definition~cinfo~info~opaque:false~bodysigmain()letadd_setoidattsbindersaaeqtn=init_setoid();let()=declare_instance_reflattsbindersaaeqn(mkappc"Seq_refl"[a;aeq;t])inlet()=declare_instance_symattsbindersaaeqn(mkappc"Seq_sym"[a;aeq;t])inlet()=declare_instance_transattsbindersaaeqn(mkappc"Seq_trans"[a;aeq;t])inletinstance=declare_instanceaaeqn"Coq.Classes.RelationClasses.Equivalence"inanew_instanceattsbindersinstance[(qualid_of_ident(Id.of_string"Equivalence_Reflexive"),mkappc"Seq_refl"[a;aeq;t]);(qualid_of_ident(Id.of_string"Equivalence_Symmetric"),mkappc"Seq_sym"[a;aeq;t]);(qualid_of_ident(Id.of_string"Equivalence_Transitive"),mkappc"Seq_trans"[a;aeq;t])]letadd_morphism_as_parameterattsmn:unit=init_setoid();letinstance_id=add_suffixn"_Proper"inletenv=Global.env()inletevd=Evd.from_envenvinletpoly=atts.polymorphicinletkind=Decls.(IsAssumptionLogical)inletimpargs,udecl=[],UState.default_univ_declinletevd,types=Rewrite.Internal.build_morphism_signatureenvevdminletevd,pe=Declare.prepare_parameter~poly~udecl~typesevdinletcst=Declare.declare_constant~name:instance_id~kind(Declare.ParameterEntrype)inletcst=GlobRef.ConstRefcstinClasses.Internal.add_instance(PropGlobal.proper_classenvevd)Hints.empty_hint_infoatts.globalcst;declare_projectionninstance_idcstletadd_morphism_interactiveatts~tacticmn:Declare.Proof.t=init_setoid();letinstance_id=add_suffixn"_Proper"inletenv=Global.env()inletevd=Evd.from_envenvinletevd,morph=Rewrite.Internal.build_morphism_signatureenvevdminletpoly=atts.polymorphicinletkind=Decls.(IsDefinitionInstance)inlethook{Declare.Hook.S.dref;_}=dref|>function|GlobRef.ConstRefcst->Classes.Internal.add_instance(PropGlobal.proper_classenvevd)Hints.empty_hint_infoatts.global(GlobRef.ConstRefcst);declare_projectionninstance_id(GlobRef.ConstRefcst)|_->assertfalseinlethook=Declare.Hook.makehookinFlags.silently(fun()->letcinfo=Declare.CInfo.make~name:instance_id~typ:morph()inletinfo=Declare.Info.make~poly~hook~kind()inletlemma=Declare.Proof.start~cinfo~infoevdinfst(Declare.Proof.bytacticlemma))()letadd_morphismatts~tacticbindersmsn=init_setoid();letinstance_id=add_suffixn"_Proper"inletinstance_name=(CAst.make@@Nameinstance_id),Noneinletinstance_t=CAst.make@@CAppExpl((Libnames.qualid_of_string"Coq.Classes.Morphisms.Proper",None),[cHole;s;m])inletlocality=get_localityatts.globalinlet_id,lemma=Classes.new_instance_interactive~locality~poly:atts.polymorphicinstance_namebindersinstance_t~tac:tactic~hook:(declare_projectionninstance_id)Hints.empty_hint_infoNoneinlemma(* no instance body -> always open proof *)