12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210(************************************************************************)(* * 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) *)(************************************************************************)openPpopenCErrorsopenUtilopenNamesopenNameopsopenConstropenContextopenEConstropenVarsopenReductionopenTacticals.NewopenTacticsopenPretype_errorsopenTypeclassesopenConstrexpropenEvdopenTactypesopenLocusopenLocusopsopenElimschemesopenEnvironopenTermopsopenEConstropenLibnamesopenProofview.NotationsopenContext.Named.DeclarationmoduleNamedDecl=Context.Named.Declaration(* module RelDecl = Context.Rel.Declaration *)(** Typeclass-based generalized rewriting. *)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}(** Constants used by the tactic. *)letclasses_dirpath=Names.DirPath.make(List.mapId.of_string["Classes";"Coq"])letinit_relation_classes()=ifis_dirpath_prefix_ofclasses_dirpath(Lib.cwd())then()elseCoqlib.check_required_library["Coq";"Classes";"RelationClasses"]letinit_setoid()=ifis_dirpath_prefix_ofclasses_dirpath(Lib.cwd())then()elseCoqlib.check_required_library["Coq";"Setoids";"Setoid"]letfind_referencedirs=Coqlib.find_reference"generalized rewriting"dirs[@@warning"-3"]letlazy_find_referencedirs=letgr=lazy(find_referencedirs)infun()->Lazy.forcegrtypeevars=evar_map*Evar.Set.t(* goal evars, constraint evars *)letfind_globaldirs=letgr=lazy(find_referencedirs)infun(evd,cstrs)->let(evd,c)=Evarutil.new_globalevd(Lazy.forcegr)in(evd,cstrs),c(** Utility for dealing with polymorphic applications *)(** Global constants. *)letcoq_eq_ref()=Coqlib.lib_ref"core.eq.type"letcoq_eq=find_global["Coq";"Init";"Logic"]"eq"letcoq_f_equal=find_global["Coq";"Init";"Logic"]"f_equal"letcoq_all=find_global["Coq";"Init";"Logic"]"all"letimpl=find_global["Coq";"Program";"Basics"]"impl"(** Bookkeeping which evars are constraints so that we can
remove them at the end of the tactic. *)letgoalevarsevars=fstevarsletcstrevarsevars=sndevarsletnew_cstr_evar(evd,cstrs)envt=(* We handle the typeclass resolution of constraints ourselves *)let(evd',t)=Evarutil.new_evarenvevd~typeclass_candidate:falsetinletev,_=destEvarevd'tin(evd',Evar.Set.addevcstrs),t(** Building or looking up instances. *)lete_new_cstr_evarenvevarst=letevd',t=new_cstr_evar!evarsenvtinevars:=evd';t(** Building or looking up instances. *)letextends_undefinedevarsevars'=letfevevifound=found||not(Evd.memevarsev)infold_undefinedfevars'falseletapp_poly_checkenvevarsfargs=let(evars,cstrs),fc=fevarsinletevars,t=Typing.solve_evarsenvevars(mkApp(fc,args))in(evars,cstrs),tletapp_poly_nocheckenvevarsfargs=letevars,fc=fevarsinevars,mkApp(fc,args)letapp_poly_sortb=ifbthenapp_poly_nocheckelseapp_poly_checkletfind_class_proofproof_typeproof_methodenvevarscarrierrelation=tryletevars,goal=app_poly_checkenvevarsproof_type[|carrier;relation|]inletevars',c=Typeclasses.resolve_one_typeclassenv(goalevarsevars)goalinifextends_undefined(goalevarsevars)evars'thenraiseNot_foundelseapp_poly_checkenv(evars',cstrevarsevars)proof_method[|carrier;relation;c|]withewhenCErrors.noncriticale->raiseNot_found(** Utility functions *)moduleGlobalBindings(M:sigvalrelation_classes:stringlistvalmorphisms:stringlistvalrelation:stringlist*stringvalapp_poly:env->evars->(evars->evars*constr)->constrarray->evars*constrvalarrow:evars->evars*constrend)=structopenMopenContext.Rel.Declarationletrelation:evars->evars*constr=find_global(fstrelation)(sndrelation)letreflexive_type=find_globalrelation_classes"Reflexive"letreflexive_proof=find_globalrelation_classes"reflexivity"letsymmetric_type=find_globalrelation_classes"Symmetric"letsymmetric_proof=find_globalrelation_classes"symmetry"lettransitive_type=find_globalrelation_classes"Transitive"lettransitive_proof=find_globalrelation_classes"transitivity"letforall_relation=find_globalmorphisms"forall_relation"letpointwise_relation=find_globalmorphisms"pointwise_relation"letforall_relation_ref=lazy_find_referencemorphisms"forall_relation"letpointwise_relation_ref=lazy_find_referencemorphisms"pointwise_relation"letrespectful=find_globalmorphisms"respectful"letrespectful_ref=lazy_find_referencemorphisms"respectful"letdefault_relation=find_global["Coq";"Classes";"SetoidTactics"]"DefaultRelation"letcoq_forall=find_globalmorphisms"forall_def"letsubrelation=find_globalrelation_classes"subrelation"letdo_subrelation=find_globalmorphisms"do_subrelation"letapply_subrelation=find_globalmorphisms"apply_subrelation"letrewrite_relation_class=find_globalrelation_classes"RewriteRelation"letproper_class=letr=lazy(find_referencemorphisms"Proper")infunenvsigma->class_infoenvsigma(Lazy.forcer)letproper_proxy_class=letr=lazy(find_referencemorphisms"ProperProxy")infunenvsigma->class_infoenvsigma(Lazy.forcer)letproper_projenvsigma=mkConst(Option.get(List.hd(proper_classenvsigma).cl_projs).meth_const)letproper_typeenv(sigma,cstrs)=letl=(proper_classenvsigma).cl_implinlet(sigma,c)=Evarutil.new_globalsigmalin(sigma,cstrs),cletproper_proxy_typeenv(sigma,cstrs)=letl=(proper_proxy_classenvsigma).cl_implinlet(sigma,c)=Evarutil.new_globalsigmalin(sigma,cstrs),cletproper_proofenvevarscarrierrelationx=letevars,goal=app_polyenvevars(proper_proxy_typeenv)[|carrier;relation;x|]innew_cstr_evarevarsenvgoalletget_reflexive_proofenv=find_class_proofreflexive_typereflexive_proofenvletget_symmetric_proofenv=find_class_proofsymmetric_typesymmetric_proofenvletget_transitive_proofenv=find_class_prooftransitive_typetransitive_proofenvletmk_relationenvevda=app_polyenvevdrelation[|a|](** Build an inferred signature from constraints on the arguments and expected output
relation *)letbuild_signatureevarsenvm(cstrs:(types*typesoption)optionlist)(finalcstr:(types*typesoption)option)=letmk_reltyevarsnewenvtyobj=matchobjwith|None|Some(_,None)->letevars,relty=mk_relationenvevarstyinifclosed0(goalevarsevars)tythenletenv'=Environ.reset_with_named_context(Environ.named_context_valenv)envinnew_cstr_evarevarsenv'reltyelsenew_cstr_evarevarsnewenvrelty|Some(x,Somerel)->evars,relinletrecauxenvevarstyl=lett=Reductionops.whd_allenv(goalevarsevars)tyinmatchEConstr.kind(goalevarsevars)t,lwith|Prod(na,ty,b),obj::cstrs->letb=Reductionops.nf_betaiotaenv(goalevarsevars)binifnoccurn(goalevarsevars)1b(* non-dependent product *)thenletty=Reductionops.nf_betaiotaenv(goalevarsevars)tyinlet(evars,b',arg,cstrs)=auxenvevars(subst1mkPropb)cstrsinletevars,relty=mk_reltyevarsenvtyobjinletevars,newarg=app_polyenvevarsrespectful[|ty;b';relty;arg|]inevars,mkProd(na,ty,b),newarg,(ty,Somerelty)::cstrselselet(evars,b,arg,cstrs)=aux(push_rel(LocalAssum(na,ty))env)evarsbcstrsinletty=Reductionops.nf_betaiotaenv(goalevarsevars)tyinletpred=mkLambda(na,ty,b)inletliftarg=mkLambda(na,ty,arg)inletevars,arg'=app_polyenvevarsforall_relation[|ty;pred;liftarg|]inifOption.is_emptyobjthenevars,mkProd(na,ty,b),arg',(ty,None)::cstrselseuser_errPp.(str"build_signature: no constraint can apply on a dependent argument")|_,obj::_->anomaly~label:"build_signature"(Pp.str"not enough products.")|_,[]->(matchfinalcstrwith|None|Some(_,None)->lett=Reductionops.nf_betaiotaenv(fstevars)tyinletevars,rel=mk_reltyevarsenvtNoneinevars,t,rel,[t,Somerel]|Some(t,Somerel)->evars,t,rel,[t,Somerel])inauxenvevarsmcstrs(** Folding/unfolding of the tactic constants. *)letunfold_implnsigmat=matchEConstr.kindsigmatwith|App(arrow,[|a;b|])(* when eq_constr arrow (Lazy.force impl) *)->mkProd(make_annotnSorts.Relevant,a,lift1b)|_->assertfalseletunfold_allsigmat=matchEConstr.kindsigmatwith|App(id,[|a;b|])(* when eq_constr id (Lazy.force coq_all) *)->(matchEConstr.kindsigmabwith|Lambda(n,ty,b)->mkProd(n,ty,b)|_->assertfalse)|_->assertfalseletunfold_forallsigmat=matchEConstr.kindsigmatwith|App(id,[|a;b|])(* when eq_constr id (Lazy.force coq_all) *)->(matchEConstr.kindsigmabwith|Lambda(n,ty,b)->mkProd(n,ty,b)|_->assertfalse)|_->assertfalseletarrow_morphismenvevdntatbab=letap=is_Prop(goalevarsevd)taandbp=is_Prop(goalevarsevd)tbinifap&&bpthenapp_polyenvevdimpl[|a;b|],unfold_implnelseifapthen(* Domain in Prop, CoDomain in Type *)(app_polyenvevdarrow[|a;b|]),unfold_impln(* (evd, mkProd (Anonymous, a, b)), (fun x -> x) *)elseifbpthen(* Dummy forall *)(app_polyenvevdcoq_all[|a;mkLambda(make_annotnSorts.Relevant,a,lift1b)|]),unfold_forallelse(* None in Prop, use arrow *)(app_polyenvevdarrow[|a;b|]),unfold_implnletrecdecomp_pointwisesigmanc=ifInt.equaln0thencelsematchEConstr.kindsigmacwith|App(f,[|a;b;relb|])whenisRefXsigma(pointwise_relation_ref())f->decomp_pointwisesigma(predn)relb|App(f,[|a;b;arelb|])whenisRefXsigma(forall_relation_ref())f->decomp_pointwisesigma(predn)(Reductionops.beta_applistsigma(arelb,[mkRel1]))|_->invalid_arg"decomp_pointwise"letrecapply_pointwisesigmarel=function|arg::args->(matchEConstr.kindsigmarelwith|App(f,[|a;b;relb|])whenisRefXsigma(pointwise_relation_ref())f->apply_pointwisesigmarelbargs|App(f,[|a;b;arelb|])whenisRefXsigma(forall_relation_ref())f->apply_pointwisesigma(Reductionops.beta_applistsigma(arelb,[arg]))args|_->invalid_arg"apply_pointwise")|[]->relletpointwise_or_dep_relationenvevdntcarrel=ifnoccurn(goalevarsevd)1car&&noccurn(goalevarsevd)1relthenapp_polyenvevdpointwise_relation[|t;lift(-1)car;lift(-1)rel|]elseapp_polyenvevdforall_relation[|t;mkLambda(make_annotnSorts.Relevant,t,car);mkLambda(make_annotnSorts.Relevant,t,rel)|]letlift_cstrenvevars(args:constrlist)ctycstr=letstartevarsenvcar=matchcstrwith|None|Some(_,None)->letevars,rel=mk_relationenvevarscarinnew_cstr_evarevarsenvrel|Some(ty,Somerel)->evars,relinletrecauxevarsenvprodn=ifInt.equaln0thenstartevarsenvprodelseletsigma=goalevarsevarsinmatchEConstr.kindsigma(Reductionops.whd_allenvsigmaprod)with|Prod(na,ty,b)->ifnoccurnsigma1bthenletb'=lift(-1)binletevars,rb=auxevarsenvb'(predn)inapp_polyenvevarspointwise_relation[|ty;b';rb|]elseletevars,rb=auxevars(push_rel(LocalAssum(na,ty))env)b(predn)inapp_polyenvevarsforall_relation[|ty;mkLambda(na,ty,b);mkLambda(na,ty,rb)|]|_->raiseNot_foundinletrecfindenvcty=function|[]->None|arg::args->tryletevars,found=auxevarsenvty(succ(List.lengthargs))inSome(evars,found,c,ty,arg::args)withNot_found->letsigma=goalevarsevarsinletty=Reductionops.whd_allenvsigmatyinfindenv(mkApp(c,[|arg|]))(prod_applistsigmaty[arg])argsinfindenvctyargsletunlift_cstrenvsigma=function|None->None|Somecodom->Some(decomp_pointwise(goalevarssigma)1codom)(** Looking up declared rewrite relations (instances of [RewriteRelation]) *)letis_applied_rewrite_relationenvsigmarelst=matchEConstr.kindsigmatwith|App(c,args)whenArray.lengthargs>=2->lethead=ifisAppsigmacthenfst(destAppsigmac)elsecinifisRefXsigma(coq_eq_ref())headthenNoneelse(tryletparams,args=Array.chop(Array.lengthargs-2)argsinletenv'=push_rel_contextrelsenvinlet(evars,(evar,_))=Evarutil.new_type_evarenv'sigmaEvd.univ_flexibleinletevars,inst=app_polyenv(evars,Evar.Set.empty)rewrite_relation_class[|evar;mkApp(c,params)|]inlet_=Typeclasses.resolve_one_typeclassenv'(goalevarsevars)instinSome(it_mkProd_or_LetIntrels)withewhenCErrors.noncriticale->None)|_->Noneendlettype_app_polyenvenvevdfargs=letevars,c=app_poly_nocheckenvevdfargsinletevd',t=Typing.type_ofenv(goalevarsevars)cin(evd',cstrevarsevars),cmodulePropGlobal=structmoduleConsts=structletrelation_classes=["Coq";"Classes";"RelationClasses"]letmorphisms=["Coq";"Classes";"Morphisms"]letrelation=["Coq";"Relations";"Relation_Definitions"],"relation"letapp_poly=app_poly_nocheckletarrow=find_global["Coq";"Program";"Basics"]"arrow"letcoq_inverse=find_global["Coq";"Program";"Basics"]"flip"endmoduleG=GlobalBindings(Consts)includeGincludeConstsletinverseenvevdcarrel=type_app_polyenvenvevdcoq_inverse[|car;car;mkProp;rel|](* app_poly env evd coq_inverse [| car ; car; mkProp; rel |] *)endmoduleTypeGlobal=structmoduleConsts=structletrelation_classes=["Coq";"Classes";"CRelationClasses"]letmorphisms=["Coq";"Classes";"CMorphisms"]letrelation=relation_classes,"crelation"letapp_poly=app_poly_checkletarrow=find_global["Coq";"Classes";"CRelationClasses"]"arrow"letcoq_inverse=find_global["Coq";"Classes";"CRelationClasses"]"flip"endmoduleG=GlobalBindings(Consts)includeGincludeConstsletinverseenv(evd,cstrs)carrel=let(evd,sort)=Evarutil.new_Type~rigid:Evd.univ_flexibleevdinapp_poly_checkenv(evd,cstrs)coq_inverse[|car;car;sort;rel|]endletsort_of_relenvevmrel=ESorts.kindevm(Reductionops.sort_of_arityenvevm(Retyping.get_type_ofenvevmrel))letis_applied_rewrite_relation=PropGlobal.is_applied_rewrite_relation(* let _ = *)(* Hook.set Equality.is_applied_rewrite_relation is_applied_rewrite_relation *)letsplit_head=functionhd::tl->hd,tl|[]->assert(false)leteq_pb(ty,env,x,yaspb)(ty',env',x',y'aspb')=letequalxy=Constr.equal(EConstr.Unsafe.to_constrx)(EConstr.Unsafe.to_constry)inpb==pb'||(ty==ty'&&equalxx'&&equalyy')letproblem_inclusionxy=List.for_all(funpb->List.exists(funpb'->eq_pbpbpb')y)xletevd_convertibleenvevdxy=try(* Unfortunately, the_conv_x might say they are unifiable even if some
unsolvable constraints remain, so we check that this unification
does not introduce any new problem. *)let_,pbs=Evd.extract_all_conv_pbsevdinletevd'=Evarconv.unify_delayenvevdxyinlet_,pbs'=Evd.extract_all_conv_pbsevd'inifevd'==evd||problem_inclusionpbs'pbsthenSomeevd'elseNonewithewhenCErrors.noncriticale->Noneletconvertibleenvevdxy=Reductionops.is_conv_leqenvevdxytypehypinfo={prf:constr;car:constr;rel:constr;sort:bool;(* true = Prop; false = Type *)c1:constr;c2:constr;holes:Clenv.holelist;}letget_symmetric_proofb=ifbthenPropGlobal.get_symmetric_proofelseTypeGlobal.get_symmetric_proofleterror_no_relation()=user_errPp.(str"Cannot find a relation to rewrite.")letrecdecompose_app_relenvevdt=(* Head normalize for compatibility with the old meta mechanism *)lett=Reductionops.whd_betaiotaenvevdtinmatchEConstr.kindevdtwith|App(f,[||])->assertfalse|App(f,[|arg|])->let(f',argl,argr)=decompose_app_relenvevdarginletty=Retyping.get_type_ofenvevdarglinletr=Retyping.relevance_of_typeenvevdtyinletf''=mkLambda(make_annot(NameNamegen.default_dependent_ident)r,ty,mkLambda(make_annot(Name(Id.of_string"y"))r,lift1ty,mkApp(lift2f,[|mkApp(lift2f',[|mkRel2;mkRel1|])|])))in(f'',argl,argr)|App(f,args)->letlen=Array.lengthargsinletfargs=Array.subargs0(Array.lengthargs-2)inletrel=mkApp(f,fargs)inrel,args.(len-2),args.(len-1)|_->error_no_relation()letdecompose_app_relenvevdt=let(rel,t1,t2)=decompose_app_relenvevdtinletty=tryRetyping.get_type_of~lax:trueenvevdrelwithRetyping.RetypeError_->error_no_relation()inlet()=ifnot(Reductionops.is_arityenvevdty)thenerror_no_relation()in(rel,t1,t2)letdecompose_applied_relationenvsigma(c,l)=letopenContext.Rel.Declarationinletctype=Retyping.get_type_ofenvsigmacinletfind_relty=letsigma,cl=Clenv.make_evar_clauseenvsigmatyinletsigma=Clenv.solve_evar_clauseenvsigmatruecllinlet{Clenv.cl_holes=holes;Clenv.cl_concl=t}=clinlet(equiv,c1,c2)=decompose_app_relenvsigmatinletty1=Retyping.get_type_ofenvsigmac1inletty2=Retyping.get_type_ofenvsigmac2inmatchevd_convertibleenvsigmaty1ty2with|None->None|Somesigma->letsort=sort_of_relenvsigmaequivinletargs=Array.map_of_list(funh->h.Clenv.hole_evar)holesinletvalue=mkApp(c,args)inSome(sigma,{prf=value;car=ty1;rel=equiv;sort=Sorts.is_propsort;c1=c1;c2=c2;holes})inmatchfind_relctypewith|Somec->c|None->letctx,t'=Reductionops.splay_prodenvsigmactypein(* Search for underlying eq *)matchfind_rel(it_mkProd_or_LetInt'(List.map(fun(n,t)->LocalAssum(n,t))ctx))with|Somec->c|None->user_errPp.(str"Cannot find an homogeneous relation to rewrite.")letrewrite_db="rewrite"letconv_transparent_state=TransparentState.cst_fullletrewrite_transparent_state()=Hints.Hint_db.transparent_state(Hints.searchtable_maprewrite_db)letrewrite_core_unif_flags={Unification.modulo_conv_on_closed_terms=None;Unification.use_metas_eagerly_in_conv_on_closed_terms=true;Unification.use_evars_eagerly_in_conv_on_closed_terms=true;Unification.modulo_delta=TransparentState.empty;Unification.modulo_delta_types=TransparentState.full;Unification.check_applied_meta_types=true;Unification.use_pattern_unification=true;Unification.use_meta_bound_pattern_unification=true;Unification.allowed_evars=Evarsolve.AllowedEvars.all;Unification.restrict_conv_on_strict_subterms=false;Unification.modulo_betaiota=false;Unification.modulo_eta=true;}(* Flags used for the setoid variant of "rewrite" and for the strategies
"hints"/"old_hints"/"terms" of "rewrite_strat", and for solving pre-existing
evars in "rewrite" (see unify_abs) *)letrewrite_unif_flags=letflags=rewrite_core_unif_flagsin{Unification.core_unify_flags=flags;Unification.merge_unify_flags=flags;Unification.subterm_unify_flags=flags;Unification.allow_K_in_toplevel_higher_order_unification=true;Unification.resolve_evars=true}letrewrite_core_conv_unif_flags={rewrite_core_unif_flagswithUnification.modulo_conv_on_closed_terms=Someconv_transparent_state;Unification.modulo_delta_types=conv_transparent_state;Unification.modulo_betaiota=true}(* Fallback flags for the setoid variant of "rewrite" *)letrewrite_conv_unif_flags=letflags=rewrite_core_conv_unif_flagsin{Unification.core_unify_flags=flags;Unification.merge_unify_flags=flags;Unification.subterm_unify_flags=flags;Unification.allow_K_in_toplevel_higher_order_unification=true;Unification.resolve_evars=true}(* Flags for "setoid_rewrite c"/"rewrite_strat -> c" *)letgeneral_rewrite_unif_flags()=letts=rewrite_transparent_state()inletcore_flags={rewrite_core_unif_flagswithUnification.modulo_conv_on_closed_terms=Somets;Unification.use_evars_eagerly_in_conv_on_closed_terms=true;Unification.modulo_delta=ts;Unification.modulo_delta_types=TransparentState.full;Unification.modulo_betaiota=true}in{Unification.core_unify_flags=core_flags;Unification.merge_unify_flags=core_flags;Unification.subterm_unify_flags={core_flagswithUnification.modulo_delta=TransparentState.empty};Unification.allow_K_in_toplevel_higher_order_unification=true;Unification.resolve_evars=true}letrefresh_hypinfoenvsigma(is,cb)=letsigma,cbl=Tacinterp.interp_open_constr_with_bindingsisenvsigmacbinletsigma,hypinfo=decompose_applied_relationenvsigmacblinlet{c1;c2;car;rel;prf;sort;holes}=hypinfoinsigma,(car,rel,prf,c1,c2,holes,sort)(** FIXME: write this in the new monad interface *)letsolve_remaining_byenvsigmaholesby=matchbywith|None->sigma|Sometac->letmaph=ifh.Clenv.hole_depsthenNoneelsematchEConstr.kindsigmah.Clenv.hole_evarwith|Evar(evk,_)->Someevk|_->Nonein(* Only solve independent holes *)letindep=List.map_filtermapholesinletist={Geninterp.lfun=Id.Map.empty;poly=false;extra=Geninterp.TacStore.empty}inletsolve_tac=matchtacwith|Genarg.GenArg(Genarg.Glbwittag,tac)->Ftactic.run(Geninterp.interptagisttac)(fun_->Proofview.tclUNIT())inletsolve_tac=tclCOMPLETEsolve_tacinletsolvesigmaevk=letevi=trySome(Evd.find_undefinedsigmaevk)withNot_found->Noneinmatcheviwith|None->sigma(* Evar should not be defined, but just in case *)|Someevi->letenv=Environ.reset_with_named_contextevi.evar_hypsenvinletty=evi.evar_conclinletname,poly=Id.of_string"rewrite",falseinletc,sigma=Proof.refine_by_tactic~name~polyenvsigmatysolve_tacinEvd.defineevk(EConstr.of_constrc)sigmainList.fold_leftsolvesigmaindepletno_constraintscstrs=funev_->not(Evar.Set.memevcstrs)letpoly_inversesort=ifsortthenPropGlobal.inverseelseTypeGlobal.inversetyperewrite_proof=|RewPrfofconstr*constr(** A Relation (R : rew_car -> rew_car -> Prop) and a proof of R rew_from rew_to *)|RewCastofcast_kind(** A proof of convertibility (with casts) *)typerewrite_result_info={rew_car:constr;(** A type *)rew_from:constr;(** A term of type rew_car *)rew_to:constr;(** A term of type rew_car *)rew_prf:rewrite_proof;(** A proof of rew_from == rew_to *)rew_evars:evars;}typerewrite_result=|Fail|Identity|Successofrewrite_result_infotype'astrategy_input={state:'a;(* a parameter: for instance, a state *)env:Environ.env;unfresh:Id.Set.t;(* Unfresh names *)term1:constr;ty1:types;(* first term and its type (convertible to rew_from) *)cstr:(bool(* prop *)*constroption);evars:evars}type'apure_strategy={strategy:'astrategy_input->'a*rewrite_result(* the updated state and the "result" *)}typestrategy=unitpure_strategyletsymmetryenvsortrew=let{rew_evars=evars;rew_car=car;}=rewinlet(rew_evars,rew_prf)=matchrew.rew_prfwith|RewCast_->(rew.rew_evars,rew.rew_prf)|RewPrf(rel,prf)->tryletevars,symprf=get_symmetric_proofsortenvevarscarrelinletprf=mkApp(symprf,[|rew.rew_from;rew.rew_to;prf|])in(evars,RewPrf(rel,prf))withNot_found->letevars,rel=poly_inversesortenvevarscarrelin(evars,RewPrf(rel,prf))in{rewwithrew_from=rew.rew_to;rew_to=rew.rew_from;rew_prf;rew_evars;}(* Matching/unifying the rewriting rule against [t] *)letunify_eqn(car,rel,prf,c1,c2,holes,sort)l2rflagsenv(sigma,cstrs)byt=tryletleft=ifl2rthenc1elsec2inletsigma=Unification.w_unify~flagsenvsigmaCONVlefttinletsigma=Typeclasses.resolve_typeclasses~filter:(no_constraintscstrs)~fail:trueenvsigmainletevd=solve_remaining_byenvsigmaholesbyinletnfc=Reductionops.nf_evarevd(Reductionops.nf_metaenvevdc)inletc1=nfc1andc2=nfc2andrew_car=nfcarandrel=nfrelandprf=nfprfinletty1=Retyping.get_type_ofenvevdc1inletty2=Retyping.get_type_ofenvevdc2inlet()=ifnot(convertibleenvevdty2ty1)thenraiseReduction.NotConvertibleinletrew_evars=evd,cstrsinletrew_prf=RewPrf(rel,prf)inletrew={rew_evars;rew_prf;rew_car;rew_from=c1;rew_to=c2;}inletrew=ifl2rthenrewelsesymmetryenvsortrewinSomerewwith|ewhennoncriticale->Noneletunify_abs(car,rel,prf,c1,c2)l2rsortenv(sigma,cstrs)t=tryletleft=ifl2rthenc1elsec2in(* The pattern is already instantiated, so the next w_unify is
basically an eq_constr, except when preexisting evars occur in
either the lemma or the goal, in which case the eq_constr also
solved this evars *)letsigma=Unification.w_unify~flags:rewrite_unif_flagsenvsigmaCONVlefttinletrew_evars=sigma,cstrsinletrew_prf=RewPrf(rel,prf)inletrew={rew_car=car;rew_from=c1;rew_to=c2;rew_prf;rew_evars;}inletrew=ifl2rthenrewelsesymmetryenvsortrewinSomerewwith|ewhennoncriticale->Nonetyperewrite_flags={under_lambdas:bool;on_morphisms:bool}letdefault_flags={under_lambdas=true;on_morphisms=true;}letget_opt_rew_rel=functionRewPrf(rel,prf)->Somerel|_->Noneletnew_global(evars,cstrs)gr=let(sigma,c)=Evarutil.new_globalevarsgrin(sigma,cstrs),cletmake_eqsigma=new_globalsigmaCoqlib.(lib_ref"core.eq.type")letmake_eq_reflsigma=new_globalsigmaCoqlib.(lib_ref"core.eq.refl")letget_rew_prfevarsr=matchr.rew_prfwith|RewPrf(rel,prf)->evars,(rel,prf)|RewCastc->letevars,eq=make_eqevarsinletevars,eq_refl=make_eq_reflevarsinletrel=mkApp(eq,[|r.rew_car|])inevars,(rel,mkCast(mkApp(eq_refl,[|r.rew_car;r.rew_from|]),c,mkApp(rel,[|r.rew_from;r.rew_to|])))letpoly_subrelationsort=ifsortthenPropGlobal.subrelationelseTypeGlobal.subrelationletresolve_subrelationenvcarrelsortprfrel'res=ifTermops.eq_constr(fstres.rew_evars)relrel'thenreselseletevars,app=app_poly_checkenvres.rew_evars(poly_subrelationsort)[|car;rel;rel'|]inletevars,subrel=new_cstr_evarevarsenvappinletappsub=mkApp(subrel,[|res.rew_from;res.rew_to;prf|])in{reswithrew_prf=RewPrf(rel',appsub);rew_evars=evars}letresolve_morphismenvmargsargs'(b,cstr)evars=letevars,morph_instance,proj,sigargs,m',args,args'=letfirst=match(Array.findi(fun_b->not(Option.is_emptyb))args')with|Somei->i|None->invalid_arg"resolve_morphism"inletmorphargs,morphobjs=Array.chopfirstargsinletmorphargs',morphobjs'=Array.chopfirstargs'inletappm=mkApp(m,morphargs)inletevd,appmtype=Typing.type_ofenv(goalevarsevars)appminletevars=evd,sndevarsinletcstrs=List.map(Option.map(funr->r.rew_car,get_opt_rew_relr.rew_prf))(Array.to_listmorphobjs')in(* Desired signature *)letevars,appmtype',signature,sigargs=ifbthenPropGlobal.build_signatureevarsenvappmtypecstrscstrelseTypeGlobal.build_signatureevarsenvappmtypecstrscstrin(* Actual signature found *)letcl_args=[|appmtype';signature;appm|]inletevars,app=app_poly_sortbenvevars(ifbthenPropGlobal.proper_typeenvelseTypeGlobal.proper_typeenv)cl_argsinletenv'=letdosub,appsub=ifbthenPropGlobal.do_subrelation,PropGlobal.apply_subrelationelseTypeGlobal.do_subrelation,TypeGlobal.apply_subrelationinEConstr.push_named(LocalDef(make_annot(Id.of_string"do_subrelation")Sorts.Relevant,snd(app_poly_sortbenvevarsdosub[||]),snd(app_poly_nocheckenvevarsappsub[||])))envinletevars,morph=new_cstr_evarevarsenv'appinevars,morph,morph,sigargs,appm,morphobjs,morphobjs'inletprojargs,subst,evars,respars,typeargs=Array.fold_left2(fun(acc,subst,evars,sigargs,typeargs')xy->let(carrier,relation),sigargs=split_headsigargsinmatchrelationwith|Somerelation->letcarrier=substlsubstcarrierandrelation=substlsubstrelationin(matchywith|None->letevars,proof=(ifbthenPropGlobal.proper_proofelseTypeGlobal.proper_proof)envevarscarrierrelationxin[proof;x;x]@acc,subst,evars,sigargs,x::typeargs'|Somer->letevars,proof=get_rew_prfevarsrin[sndproof;r.rew_to;x]@acc,subst,evars,sigargs,r.rew_to::typeargs')|None->ifnot(Option.is_emptyy)thenuser_errPp.(str"Cannot rewrite inside dependent arguments of a function");x::acc,x::subst,evars,sigargs,x::typeargs')([],[],evars,sigargs,[])argsargs'inletproof=applist(proj,List.revprojargs)inletnewt=applist(m',List.revtypeargs)inmatchresparswith[a,Somer]->evars,proof,substlsubsta,substlsubstr,newt|_->assert(false)letapply_constraintenvcarrelprfcstrres=matchsndcstrwith|None->res|Somer->resolve_subrelationenvcarrel(fstcstr)prfrresletcoerceenvcstrres=letevars,(rel,prf)=get_rew_prfres.rew_evarsresinletres={reswithrew_evars=evars}inapply_constraintenvres.rew_carrelprfcstrresletapply_ruleunify:occurrences_countpure_strategy={strategy=fun{state=occs;env;term1=t;ty1=ty;cstr;evars}->letunif=ifisEvar(goalevarsevars)tthenNoneelseunifyenvevarstinmatchunifwith|None->(occs,Fail)|Somerew->letb,occs=update_occurrence_counteroccsinifnotbthen(occs,Fail)elseifTermops.eq_constr(fstrew.rew_evars)trew.rew_tothen(occs,Identity)elseletres={rewwithrew_car=ty}inletres=Success(coerceenvcstrres)in(occs,res)}letapply_lemmal2rflagsocbyloccs:strategy={strategy=fun({state=();env;term1=t;evars=(sigma,cstrs)}asinput)->letsigma,c=ocsigmainletsigma,hypinfo=decompose_applied_relationenvsigmacinlet{c1;c2;car;rel;prf;sort;holes}=hypinfoinletrew=(car,rel,prf,c1,c2,holes,sort)inletevars=(sigma,cstrs)inletunifyenvevarst=letrew=unify_eqnrewl2rflagsenvevarsbytinmatchrewwith|None->None|Somerew->Somerewinletloccs,res=(apply_ruleunify).strategy{inputwithstate=initialize_occurrence_counterloccs;evars}incheck_used_occurrencesloccs;(),res}lete_app_polyenvevarsfargs=letevars',c=app_poly_nocheckenv!evarsfargsinevars:=evars';cletmake_leibniz_proofenvctyr=letevars=refr.rew_evarsinletprf=matchr.rew_prfwith|RewPrf(rel,prf)->letrel=e_app_polyenvevarscoq_eq[|ty|]inletprf=e_app_polyenvevarscoq_f_equal[|r.rew_car;ty;mkLambda(make_annotAnonymousSorts.Relevant,r.rew_car,c);r.rew_from;r.rew_to;prf|]inRewPrf(rel,prf)|RewCastk->r.rew_prfin{rew_car=ty;rew_evars=!evars;rew_from=subst1r.rew_fromc;rew_to=subst1r.rew_toc;rew_prf=prf}letreset_envenv=letenv'=Global.env_of_context(Environ.named_context_valenv)inEnviron.push_rel_context(Environ.rel_contextenv)env'letfold_match?(force=false)envsigmac=letcase=destCasesigmacinlet(ci,p,iv,c,brs)=EConstr.expand_caseenvsigmacaseinletcty=Retyping.get_type_ofenvsigmacinletdep,pred,exists,sk=letenv',ctx,body=letctx,pred=decompose_lam_assumsigmapinletenv'=push_rel_contextctxenvinenv',ctx,predinletsortp=Retyping.get_sort_family_ofenv'sigmabodyinletsortc=Retyping.get_sort_family_ofenvsigmactyinletdep=not(noccurnsigma1body)inletpred=ifdepthenpelseit_mkProd_or_LetIn(subst1mkPropbody)(List.tlctx)inletsk=ifsortp==Sorts.InPropthenifsortc==Sorts.InPropthenifdepthencase_dep_scheme_kind_from_propelsecase_scheme_kind_from_propelse(ifdepthencase_dep_scheme_kind_from_type_in_propelsecase_scheme_kind_from_type)else((* sortc <> InProp by typing *)ifdepthencase_dep_scheme_kind_from_typeelsecase_scheme_kind_from_type)inmatchInd_tables.lookup_schemeskci.ci_indwith|Somecst->dep,pred,true,cst|None->raiseNot_foundinletapp=letind,args=Inductiveops.find_mrectypeenvsigmactyinletpars,args=List.chopci.ci_nparargsinletmeths=List.map(funbr->br)(Array.to_listbrs)inapplist(mkConstsk,pars@[pred]@meths@args@[c])insk,(ifexiststhenenvelsereset_envenv),appletunfold_matchenvsigmaskapp=matchEConstr.kindsigmaappwith|App(f',args)whenQConstant.equalenv(fst(destConstsigmaf'))sk->letv=Environ.constant_value_in(Global.env())(sk,Univ.Instance.empty)(*FIXME*)inletv=EConstr.of_constrvinReductionops.whd_betaenvsigma(mkApp(v,args))|_->appletis_rew_cast=functionRewCast_->true|_->falseletsubtermallflags(s:'apure_strategy):'apure_strategy=letrecaux{state;env;unfresh;term1=t;ty1=ty;cstr=(prop,cstr);evars}=letcstr'=Option.map(func->(ty,Somec))cstrinmatchEConstr.kind(goalevarsevars)twith|App(m,args)->letrewrite_argsstatesuccess=letstate,(args',evars',progress)=Array.fold_left(fun(state,(acc,evars,progress))arg->ifnot(Option.is_emptyprogress)&¬allthenstate,(None::acc,evars,progress)elseletargty=Retyping.get_type_ofenv(goalevarsevars)arginletstate,res=s.strategy{state;env;unfresh;term1=arg;ty1=argty;cstr=(prop,None);evars}inletres'=matchreswith|Identity->letprogress=ifOption.is_emptyprogressthenSomefalseelseprogressin(None::acc,evars,progress)|Successr->(Somer::acc,r.rew_evars,Sometrue)|Fail->(None::acc,evars,progress)instate,res')(state,([],evars,success))argsinletres=matchprogresswith|None->Fail|Somefalse->Identity|Sometrue->letargs'=Array.of_list(List.revargs')inifArray.exists(function|None->false|Somer->not(is_rew_castr.rew_prf))args'thenletevars',prf,car,rel,c2=resolve_morphismenvmargsargs'(prop,cstr')evars'inletres={rew_car=ty;rew_from=t;rew_to=c2;rew_prf=RewPrf(rel,prf);rew_evars=evars'}inSuccessreselseletargs'=Array.map2(funaoriganew->matchanewwithNone->aorig|Somer->r.rew_to)argsargs'inletres={rew_car=ty;rew_from=t;rew_to=mkApp(m,args');rew_prf=RewCastDEFAULTcast;rew_evars=evars'}inSuccessresinstate,resinifflags.on_morphismsthenletmty=Retyping.get_type_ofenv(goalevarsevars)minletevars,cstr',m,mty,argsl,args=letargsl=Array.to_listargsinletlift=ifpropthenPropGlobal.lift_cstrelseTypeGlobal.lift_cstrinmatchliftenvevarsargslmmtyNonewith|Some(evars,cstr',m,mty,args)->evars,Somecstr',m,mty,args,Array.of_listargs|None->evars,None,m,mty,argsl,argsinletstate,m'=s.strategy{state;env;unfresh;term1=m;ty1=mty;cstr=(prop,cstr');evars}inmatchm'with|Fail->rewrite_argsstateNone(* Standard path, try rewrite on arguments *)|Identity->rewrite_argsstate(Somefalse)|Successr->(* We rewrote the function and get a proof of pointwise rel for the arguments.
We just apply it. *)letprf=matchr.rew_prfwith|RewPrf(rel,prf)->letapp=ifpropthenPropGlobal.apply_pointwiseelseTypeGlobal.apply_pointwiseinRewPrf(app(goalevarsevars)relargsl,mkApp(prf,args))|x->xinletres={rew_car=Reductionops.hnf_prod_appvectenv(goalevarsevars)r.rew_carargs;rew_from=mkApp(r.rew_from,args);rew_to=mkApp(r.rew_to,args);rew_prf=prf;rew_evars=r.rew_evars}inletres=matchprfwith|RewPrf(rel,prf)->Success(apply_constraintenvres.rew_carrelprf(prop,cstr)res)|_->Successresinstate,reselserewrite_argsstateNone|Prod(n,x,b)whennoccurn(goalevarsevars)1b->letb=subst1mkPropbinlettx=Retyping.get_type_ofenv(goalevarsevars)xandtb=Retyping.get_type_ofenv(goalevarsevars)binletarr=ifpropthenPropGlobal.arrow_morphismelseTypeGlobal.arrow_morphisminlet(evars',mor),unfold=arrenvevarsn.binder_nametxtbxbinletstate,res=aux{state;env;unfresh;term1=mor;ty1=ty;cstr=(prop,cstr);evars=evars'}inletres=matchreswith|Successr->Success{rwithrew_to=unfold(goalevarsr.rew_evars)r.rew_to}|Fail|Identity->resinstate,res|Prod(n,dom,codom)->letlam=mkLambda(n,dom,codom)inlet(evars',app),unfold=ifeq_constr(fstevars)tymkPropthen(app_poly_sortpropenvevarscoq_all[|dom;lam|]),TypeGlobal.unfold_allelseletforall=ifpropthenPropGlobal.coq_forallelseTypeGlobal.coq_forallin(app_poly_sortpropenvevarsforall[|dom;lam|]),TypeGlobal.unfold_forallinletstate,res=aux{state;env;unfresh;term1=app;ty1=ty;cstr=(prop,cstr);evars=evars'}inletres=matchreswith|Successr->Success{rwithrew_to=unfold(goalevarsr.rew_evars)r.rew_to}|Fail|Identity->resinstate,res(* TODO: real rewriting under binders: introduce x x' (H : R x x') and rewrite with
H at any occurrence of x. Ask for (R ==> R') for the lambda. Formalize this.
B. Barras' idea is to have a context of relations, of length 1, with Σ for gluing
dependent relations and using projections to get them out.
*)|Lambda(n,t,b)whenflags.under_lambdas->letunfresh,n'=letid=matchn.binder_namewith|Anonymous->Namegen.default_dependent_ident|Nameid->idinletid=Tactics.fresh_id_in_envunfreshidenvinId.Set.addidunfresh,{nwithbinder_name=Nameid}inletunfresh=matchn'.binder_namewith|Anonymous->unfresh|Nameid->Id.Set.addidunfreshinletopenContext.Rel.Declarationinletenv'=EConstr.push_rel(LocalAssum(n',t))envinletbty=Retyping.get_type_ofenv'(goalevarsevars)binletunlift=ifpropthenPropGlobal.unlift_cstrelseTypeGlobal.unlift_cstrinletstate,b'=s.strategy{state;env=env';unfresh;term1=b;ty1=bty;cstr=(prop,unliftenvevarscstr);evars}inletres=matchb'with|Successr->letr=matchr.rew_prfwith|RewPrf(rel,prf)->letpoint=ifpropthenPropGlobal.pointwise_or_dep_relationelseTypeGlobal.pointwise_or_dep_relationinletevars,rel=pointenvr.rew_evarsn'.binder_nametr.rew_carrelinletprf=mkLambda(n',t,prf)in{rwithrew_prf=RewPrf(rel,prf);rew_evars=evars}|x->rinSuccess{rwithrew_car=mkProd(n,t,r.rew_car);rew_from=mkLambda(n,t,r.rew_from);rew_to=mkLambda(n,t,r.rew_to)}|Fail|Identity->b'instate,res|Case(ci,u,pms,p,iv,c,brs)->let(ci,p,iv,c,brs)=EConstr.expand_caseenv(goalevarsevars)(ci,u,pms,p,iv,c,brs)inletcty=Retyping.get_type_ofenv(goalevarsevars)cinletevars',eqty=app_poly_sortpropenvevarscoq_eq[|cty|]inletcstr'=Someeqtyinletstate,c'=s.strategy{state;env;unfresh;term1=c;ty1=cty;cstr=(prop,cstr');evars=evars'}inletstate,res=matchc'with|Successr->letcase=mkCase(EConstr.contract_caseenv(goalevarsevars)(ci,lift1p,map_invert(lift1)iv,mkRel1,Array.map(lift1)brs))inletres=make_leibniz_proofenvcasetyrinstate,Success(coerceenv(prop,cstr)res)|Fail|Identity->ifArray.for_all(Int.equal0)ci.ci_cstr_ndeclsthenletevars',eqty=app_poly_sortpropenvevarscoq_eq[|ty|]inletcstr=Someeqtyinletstate,found,brs'=Array.fold_left(fun(state,found,acc)br->ifnot(Option.is_emptyfound)then(state,found,funx->lift1br::accx)elseletstate,res=s.strategy{state;env;unfresh;term1=br;ty1=ty;cstr=(prop,cstr);evars}inmatchreswith|Successr->(state,Somer,funx->mkRel1::accx)|Fail|Identity->(state,None,funx->lift1br::accx))(state,None,funx->[])brsinmatchfoundwith|Somer->letctxc=mkCase(EConstr.contract_caseenv(goalevarsevars)(ci,lift1p,map_invert(lift1)iv,lift1c,Array.of_list(List.rev(brs'c'))))instate,Success(make_leibniz_proofenvctxctyr)|None->state,c'elsematchtrySome(fold_matchenv(goalevarsevars)t)withNot_found->Nonewith|None->state,c'|Some(cst,_,t')->letstate,res=aux{state;env;unfresh;term1=t';ty1=ty;cstr=(prop,cstr);evars}inletres=matchreswith|Successprf->Success{prfwithrew_from=t;rew_to=unfold_matchenv(goalevarsevars)cstprf.rew_to}|x'->c'instate,resinletres=matchreswith|Successr->Success(coerceenv(prop,cstr)r)|Fail|Identity->resinstate,res|_->state,Failin{strategy=aux}letall_subterms=subtermtruedefault_flagsletone_subterm=subtermfalsedefault_flags(** Requires transitivity of the rewrite step, if not a reduction.
Not tail-recursive. *)lettransitivitystateenvunfreshprop(res:rewrite_result_info)(next:'apure_strategy):'a*rewrite_result=letstate,nextres=next.strategy{state;env;unfresh;term1=res.rew_to;ty1=res.rew_car;cstr=(prop,get_opt_rew_relres.rew_prf);evars=res.rew_evars}inletres=matchnextreswith|Fail->Fail|Identity->Successres|Successres'->matchres.rew_prfwith|RewCastc->Success{res'withrew_from=res.rew_from}|RewPrf(rew_rel,rew_prf)->matchres'.rew_prfwith|RewCast_->Success{reswithrew_to=res'.rew_to}|RewPrf(res'_rel,res'_prf)->lettrans=ifpropthenPropGlobal.transitive_typeelseTypeGlobal.transitive_typeinletevars,prfty=app_poly_sortpropenvres'.rew_evarstrans[|res.rew_car;rew_rel|]inletevars,prf=new_cstr_evarevarsenvprftyinletprf=mkApp(prf,[|res.rew_from;res'.rew_from;res'.rew_to;rew_prf;res'_prf|])inSuccess{res'withrew_from=res.rew_from;rew_evars=evars;rew_prf=RewPrf(res'_rel,prf)}instate,res(** Rewriting strategies.
Inspired by ELAN's rewriting strategies:
http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.21.4049
*)moduleStrategies=structletfail:'apure_strategy={strategy=fun{state}->state,Fail}letid:'apure_strategy={strategy=fun{state}->state,Identity}letrefl:'apure_strategy={strategy=fun{state;env;term1=t;ty1=ty;cstr=(prop,cstr);evars}->letevars,rel=matchcstrwith|None->letmkr=ifpropthenPropGlobal.mk_relationelseTypeGlobal.mk_relationinletevars,rty=mkrenvevarstyinnew_cstr_evarevarsenvrty|Somer->evars,rinletevars,proof=letproxy=ifpropthenPropGlobal.proper_proxy_typeenvelseTypeGlobal.proper_proxy_typeenvinletevars,mty=app_poly_sortpropenvevarsproxy[|ty;rel;t|]innew_cstr_evarevarsenvmtyinletres=Success{rew_car=ty;rew_from=t;rew_to=t;rew_prf=RewPrf(rel,proof);rew_evars=evars}instate,res}letprogress(s:'apure_strategy):'apure_strategy={strategy=funinput->letstate,res=s.strategyinputinmatchreswith|Fail->state,Fail|Identity->state,Fail|Successr->state,Successr}letseqfirstsnd:'apure_strategy={strategy=fun({env;unfresh;cstr}asinput)->letstate,res=first.strategyinputinmatchreswith|Fail->state,Fail|Identity->snd.strategy{inputwithstate}|Successres->transitivitystateenvunfresh(fstcstr)ressnd}letchoicefstsnd:'apure_strategy={strategy=funinput->letstate,res=fst.strategyinputinmatchreswith|Fail->snd.strategy{inputwithstate}|Identity|Success_->state,res}lettry_str:'apure_strategy=choicestridletcheck_interruptstrinput=Control.check_for_interrupt();strinputletfix(f:'apure_strategy->'apure_strategy):'apure_strategy=letrecauxinput=(f{strategy=funinput->check_interruptauxinput}).strategyinputin{strategy=aux}letany(s:'apure_strategy):'apure_strategy=fix(funany->try_(seqsany))letrepeat(s:'apure_strategy):'apure_strategy=seqs(anys)letbu(s:'apure_strategy):'apure_strategy=fix(funs'->seq(choice(progress(all_subtermss'))s)(try_s'))lettd(s:'apure_strategy):'apure_strategy=fix(funs'->seq(choices(progress(all_subtermss')))(try_s'))letinnermost(s:'apure_strategy):'apure_strategy=fix(funins->choice(one_subtermins)s)letoutermost(s:'apure_strategy):'apure_strategy=fix(funout->choices(one_subtermout))letlemmascs:'apure_strategy=List.fold_left(funtac(l,l2r,by)->choicetac(apply_lemmal2rrewrite_unif_flagslbyAllOccurrences))failcsletinj_openhint=();funsigma->letctx=UState.of_context_sethint.Autorewrite.rew_ctxinletsigma=Evd.merge_universe_contextsigmactxin(sigma,(EConstr.of_constrhint.Autorewrite.rew_lemma,NoBindings))letold_hints(db:string):'apure_strategy=letrules=Autorewrite.find_rewritesdbinlemmas(List.map(funhint->(inj_openhint,hint.Autorewrite.rew_l2r,hint.Autorewrite.rew_tac))rules)lethints(db:string):'apure_strategy={strategy=fun({term1=t}asinput)->lett=EConstr.Unsafe.to_constrtinletrules=Autorewrite.find_matchesdbtinletlemmahint=(inj_openhint,hint.Autorewrite.rew_l2r,hint.Autorewrite.rew_tac)inletlems=List.maplemmarulesin(lemmaslems).strategyinput}letreduce(r:Redexpr.red_expr):'apure_strategy={strategy=fun{state=state;env=env;term1=t;ty1=ty;cstr=cstr;evars=evars}->letrfn,ckind=Redexpr.reduction_of_red_exprenvrinletsigma=goalevarsevarsinlet(sigma,t')=rfnenvsigmatinifTermops.eq_constrsigmat'tthenstate,Identityelsestate,Success{rew_car=ty;rew_from=t;rew_to=t';rew_prf=RewCastckind;rew_evars=sigma,cstrevarsevars}}letfold_globc:'apure_strategy={strategy=fun{state;env;term1=t;ty1=ty;cstr;evars}->(* let sigma, (c,_) = Tacinterp.interp_open_constr_with_bindings is env (goalevars evars) c in *)letsigma,c=Pretyping.understand_tccenv(goalevarsevars)cinletunfolded=tryTacred.try_red_productenvsigmacwithewhenCErrors.noncriticale->user_errPp.(str"fold: the term is not unfoldable!")intryletsigma=Unification.w_unifyenvsigmaCONV~flags:(Unification.elim_flags())unfoldedtinletc'=Reductionops.nf_evarsigmacinstate,Success{rew_car=ty;rew_from=t;rew_to=c';rew_prf=RewCastDEFAULTcast;rew_evars=(sigma,sndevars)}withewhenCErrors.noncriticale->state,Fail}end(** The strategy for a single rewrite, dealing with occurrences. *)(** A dummy initial clauseenv to avoid generating initial evars before
even finding a first application of the rewriting lemma, in setoid_rewrite
mode *)letrewrite_withl2rflagscoccs:strategy={strategy=fun({state=()}asinput)->letunifyenvevarst=let(sigma,cstrs)=evarsinlet(sigma,rew)=refresh_hypinfoenvsigmacinunify_eqnrewl2rflagsenv(sigma,cstrs)Nonetinletapp=apply_ruleunifyinletstrat=Strategies.fix(funaux->Strategies.choiceapp(subtermtruedefault_flagsaux))inletoccs,res=strat.strategy{inputwithstate=initialize_occurrence_counteroccs}incheck_used_occurrencesoccs;((),res)}letapply_strategy(s:strategy)envunfreshconcl(prop,cstr)evars=letty=Retyping.get_type_ofenv(goalevarsevars)conclinlet_,res=s.strategy{state=();env;unfresh;term1=concl;ty1=ty;cstr=(prop,Somecstr);evars}inresletsolve_constraintsenv(evars,cstrs)=letoldtcs=Evd.get_typeclass_evarsevarsinletevars'=Evd.set_typeclass_evarsevarscstrsinletevars'=Typeclasses.resolve_typeclassesenv~filter:all_evars~split:false~fail:trueevars'inEvd.set_typeclass_evarsevars'oldtcsletnf_zeta=Reductionops.clos_norm_flags(CClosure.RedFlags.mkflags[CClosure.RedFlags.fZETA])exceptionRewriteFailureofPp.ttyperesult=(evar_map*constroption*types)optionoptionletcl_rewrite_clause_aux?(abs=None)stratenvavoidsigmaconclis_hyp:result=letsigma,sort=Typing.sort_ofenvsigmaconclinletevdref=refsigmainletevars=(!evdref,Evar.Set.empty)inletevars,cstr=letprop,(evars,arrow)=ifSorts.is_propsortthentrue,app_poly_sorttrueenvevarsimpl[||]elsefalse,app_poly_sortfalseenvevarsTypeGlobal.arrow[||]inmatchis_hypwith|None->letevars,t=poly_inversepropenvevars(mkSortsort)arrowinevars,(prop,t)|Some_->evars,(prop,arrow)inleteq=apply_strategystratenvavoidconclcstrevarsinmatcheqwith|Fail->None|Identity->SomeNone|Successres->let(_,cstrs)=res.rew_evarsinletevars=solve_constraintsenvres.rew_evarsinlet()=Evar.Set.iter(funev->ifnot(Evd.is_definedevarsev)thenuser_err~hdr:"rewrite"(str"Unsolved constraint remaining: "++spc()++Termops.pr_evar_infoenvevars(Evd.findevarsev)))cstrsinletnewt=res.rew_toinletres=matchres.rew_prfwith|RewCastc->None|RewPrf(rel,p)->letp=nf_zetaenvevarspinletterm=matchabswith|None->p|Some(t,ty)->mkApp(mkLambda(make_annot(Name(Id.of_string"lemma"))Sorts.Relevant,ty,p),[|t|])inletproof=matchis_hypwith|None->term|Someid->mkApp(term,[|mkVarid|])inSomeproofinSome(Some(evars,res,newt))(** Insert a declaration after the last declaration it depends on *)letrecinsert_dependentenvsigmadeclaccuhyps=matchhypswith|[]->List.rev_appendaccu[decl]|ndecl::rem->ifoccur_var_in_declenvsigma(NamedDecl.get_idndecl)declthenList.rev_appendaccu(decl::hyps)elseinsert_dependentenvsigmadecl(ndecl::accu)remletassert_replacingidnewttac=letprf=Proofview.Goal.enterbeginfungl->letconcl=Proofview.Goal.conclglinletenv=Proofview.Goal.envglinletsigma=Tacmach.New.projectglinletctx=named_contextenvinletafter,before=List.split_when(NamedDecl.get_id%>Id.equalid)ctxinletnc=matchbeforewith|[]->assertfalse|d::rem->insert_dependentenvsigma(LocalAssum(make_annot(NamedDecl.get_idd)Sorts.Relevant,newt))[]after@reminletenv'=Environ.reset_with_named_context(val_of_named_contextnc)envinRefine.refine~typecheck:truebeginfunsigma->let(sigma,ev)=Evarutil.new_evarenv'sigmaconclinlet(sigma,ev')=Evarutil.new_evarenvsigmanewtinletmapd=letn=NamedDecl.get_iddinifId.equalnidthenev'elsemkVarninlet(e,_)=destEvarsigmaevin(sigma,mkEvar(e,List.mapmapnc))endendinProofview.tclTHENprf(Proofview.tclFOCUS22tac)letnewfailns=letinfo=Exninfo.reify()inProofview.tclZERO~info(Tacticals.FailError(n,lazys))letcl_rewrite_clause_newtac?abs?origsigma~progressstratclause=letopenProofview.Notationsin(* For compatibility *)letbeta=Tactics.reduct_in_concl~check:false(Reductionops.nf_betaiota,DEFAULTcast)inletbeta_hypid=Tactics.reduct_in_hyp~check:false~reorder:falseReductionops.nf_betaiota(id,InHyp)inlettreatsigmaresstate=matchreswith|None->newfail0(str"Nothing to rewrite")|SomeNone->ifprogressthennewfail0(str"Failed to progress")elseProofview.tclUNIT()|Some(Someres)->let(undef,prf,newt)=resinletfoldev_accu=ifEvd.memsigmaevthenaccuelseev::accuinletgls=List.rev(Evd.fold_undefinedfoldundef[])inletgls=List.map(fungl->Proofview.goal_with_stateglstate)glsinmatchclause,prfwith|Someid,Somep->lettac=tclTHENLIST[Refine.refine~typecheck:true(funh->(h,p));Proofview.Unsafe.tclNEWGOALSgls;]inProofview.Unsafe.tclEVARSundef<*>tclTHENFIRST(assert_replacingidnewttac)(beta_hypid)|Someid,None->Proofview.Unsafe.tclEVARSundef<*>convert_hyp~check:false~reorder:false(LocalAssum(make_annotidSorts.Relevant,newt))<*>beta_hypid|None,Somep->Proofview.Unsafe.tclEVARSundef<*>Proofview.Goal.enterbeginfungl->letenv=Proofview.Goal.envglinletmake=beginfunsigma->let(sigma,ev)=Evarutil.new_evarenvsigmanewtin(sigma,mkApp(p,[|ev|]))endinRefine.refine~typecheck:truemake<*>Proofview.Unsafe.tclNEWGOALSglsend|None,None->Proofview.Unsafe.tclEVARSundef<*>convert_concl~check:falsenewtDEFAULTcastinProofview.Goal.enterbeginfungl->letconcl=Proofview.Goal.conclglinletenv=Proofview.Goal.envglinletstate=Proofview.Goal.stateglinletsigma=Tacmach.New.projectglinletty=matchclausewith|None->concl|Someid->EConstr.of_constr(Environ.named_typeidenv)inletenv=matchclausewith|None->env|Someid->(* Only consider variables not depending on [id] *)letctx=named_contextenvinletfilterdecl=not(occur_var_in_declenvsigmaiddecl)inletnctx=List.filterfilterctxinEnviron.reset_with_named_context(val_of_named_contextnctx)envintryletres=cl_rewrite_clause_aux?absstratenvId.Set.emptysigmatyclauseinletsigma=matchorigsigmawithNone->sigma|Somesigma->sigmaintreatsigmaresstate<*>(* For compatibility *)beta<*>Proofview.shelve_unifiablewith|PretypeError(env,evd,(UnsatisfiableConstraints_ase))->raise(RewriteFailure(Himsg.explain_pretype_errorenvevde))endlettactic_init_setoid()=tryinit_setoid();Proofview.tclUNIT()withewhenCErrors.noncriticale->let_,info=Exninfo.captureeinTacticals.New.tclFAIL~info0(str"Setoid library not loaded")letcl_rewrite_clause_stratprogressstratclause=tactic_init_setoid()<*>(ifprogressthenProofview.tclPROGRESSelsefunx->x)(Proofview.tclOR(cl_rewrite_clause_newtac~progressstratclause)(fun(e,info)->matchewith|RewriteFailuree->tclZEROMSG~info(str"setoid rewrite failed: "++e)|Tacticals.FailError(n,pp)->tclFAIL~infon(str"setoid rewrite failed: "++Lazy.forcepp)|e->Proofview.tclZERO~infoe))(** Setoid rewriting when called with "setoid_rewrite" *)letcl_rewrite_clauselleft2rightoccsclause=letstrat=rewrite_withleft2right(general_rewrite_unif_flags())loccsincl_rewrite_clause_strattruestratclause(** Setoid rewriting when called with "rewrite_strat" *)letcl_rewrite_clause_stratstratclause=cl_rewrite_clause_stratfalsestratclauseletapply_glob_constristcl2roccs=();fun({state=();env=env}asinput)->letcsigma=let(sigma,c)=Tacinterp.interp_open_constristenvsigmacin(sigma,(c,NoBindings))inletflags=general_rewrite_unif_flags()in(apply_lemmal2rflagscNoneoccs).strategyinputletinterp_glob_constr_listenv=letmakec=();funsigma->letsigma,c=Pretyping.understand_tccenvsigmacin(sigma,(c,NoBindings))inList.map(func->makec,true,None)(* Syntax for rewriting with strategies *)typeunary_strategy=Subterms|Subterm|Innermost|Outermost|Bottomup|Topdown|Progress|Try|Any|Repeattypebinary_strategy=|Compose|Choicetype('constr,'redexpr)strategy_ast=|StratId|StratFail|StratRefl|StratUnaryofunary_strategy*('constr,'redexpr)strategy_ast|StratBinaryofbinary_strategy*('constr,'redexpr)strategy_ast*('constr,'redexpr)strategy_ast|StratConstrof'constr*bool|StratTermsof'constrlist|StratHintsofbool*string|StratEvalof'redexpr|StratFoldof'constrletrecmap_strategy(f:'a->'a2)(g:'b->'b2):('a,'b)strategy_ast->('a2,'b2)strategy_ast=function|StratId|StratFail|StratReflass->s|StratUnary(s,str)->StratUnary(s,map_strategyfgstr)|StratBinary(s,str,str')->StratBinary(s,map_strategyfgstr,map_strategyfgstr')|StratConstr(c,b)->StratConstr(fc,b)|StratTermsl->StratTerms(List.mapfl)|StratHints(b,id)->StratHints(b,id)|StratEvalr->StratEval(gr)|StratFoldc->StratFold(fc)letpr_ustrategy=function|Subterms->str"subterms"|Subterm->str"subterm"|Innermost->str"innermost"|Outermost->str"outermost"|Bottomup->str"bottomup"|Topdown->str"topdown"|Progress->str"progress"|Try->str"try"|Any->str"any"|Repeat->str"repeat"letparenp=str"("++p++str")"letrecpr_strategyprcprr=function|StratId->str"id"|StratFail->str"fail"|StratRefl->str"refl"|StratUnary(s,str)->pr_ustrategys++spc()++paren(pr_strategyprcprrstr)|StratBinary(Choice,str1,str2)->str"choice"++spc()++paren(pr_strategyprcprrstr1)++spc()++paren(pr_strategyprcprrstr2)|StratBinary(Compose,str1,str2)->pr_strategyprcprrstr1++str";"++spc()++pr_strategyprcprrstr2|StratConstr(c,true)->prcc|StratConstr(c,false)->str"<-"++spc()++prcc|StratTermscl->str"terms"++spc()++pr_sequenceprccl|StratHints(old,id)->letcmd=ifoldthen"old_hints"else"hints"instrcmd++spc()++strid|StratEvalr->str"eval"++spc()++prrr|StratFoldc->str"fold"++spc()++prccletrecstrategy_of_astist=function|StratId->Strategies.id|StratFail->Strategies.fail|StratRefl->Strategies.refl|StratUnary(f,s)->lets'=strategy_of_astistsinletf'=matchfwith|Subterms->all_subterms|Subterm->one_subterm|Innermost->Strategies.innermost|Outermost->Strategies.outermost|Bottomup->Strategies.bu|Topdown->Strategies.td|Progress->Strategies.progress|Try->Strategies.try_|Any->Strategies.any|Repeat->Strategies.repeatinf's'|StratBinary(f,s,t)->lets'=strategy_of_astistsinlett'=strategy_of_astisttinletf'=matchfwith|Compose->Strategies.seq|Choice->Strategies.choiceinf's't'|StratConstr(c,b)->{strategy=apply_glob_constristcbAllOccurrences}|StratHints(old,id)->ifoldthenStrategies.old_hintsidelseStrategies.hintsid|StratTermsl->{strategy=(fun({state=();env}asinput)->letl'=interp_glob_constr_listenv(List.mapfstl)in(Strategies.lemmasl').strategyinput)}|StratEvalr->{strategy=(fun({state=();env;evars}asinput)->let(sigma,r_interp)=Tacinterp.interp_red_expristenv(goalevarsevars)rin(Strategies.reducer_interp).strategy{inputwithevars=(sigma,cstrevarsevars)})}|StratFoldc->Strategies.fold_glob(fstc)(* By default the strategy for "rewrite_db" is top-down *)letmkappcsl=CAst.make@@CAppExpl((None,qualid_of_ident(Id.of_strings),None),l)letdeclare_an_instancensargs=(((CAst.make@@Namen),None),CAst.make@@CAppExpl((None,qualid_of_strings,None),args))letdeclare_instanceaaeqns=declare_an_instancens[a;aeq]letget_localityb=ifbthenGoptions.OptGlobalelseGoptions.OptLocalletanew_instanceattsbinders(name,t)fields=letlocality=get_localityatts.globalinlet_id=Classes.new_instance~poly:atts.polymorphicnamebinderst(true,CAst.make@@CRecord(fields))~locality~generalize:falseHints.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=letpoly=Global.is_polymorphicrinletenv=Global.env()inletsigma=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,opaque,scope=Decls.(IsDefinitionDefinition),false,Locality.GlobalLocality.ImportDefaultBehaviorinletimpargs,udecl=[],UState.default_univ_declinletcinfo=Declare.CInfo.make~name~impargs~typ:types()inletinfo=Declare.Info.make~scope~kind~udecl~poly()inlet_r:GlobRef.t=Declare.declare_definition~cinfo~info~opaque~bodysigmain()letbuild_morphism_signatureenvsigmam=letm,ctx=Constrintern.interp_constrenvsigmaminletsigma=Evd.from_ctxctxinlett=Retyping.get_type_ofenvsigmaminletcstrs=letrecauxt=matchEConstr.kindsigmatwith|Prod(na,a,b)->None::auxb|_->[]inauxtinletevars,t',sig_,cstrs=PropGlobal.build_signature(sigma,Evar.Set.empty)envtcstrsNoneinletevd=refevarsinlet_=List.iter(fun(ty,rel)->Option.iter(funrel->letdefault=e_app_polyenvevdPropGlobal.default_relation[|ty;rel|]inignore(e_new_cstr_evarenvevddefault))rel)cstrsinletmorph=e_app_polyenvevd(PropGlobal.proper_typeenv)[|t;sig_;m|]inletevd=solve_constraintsenv!evdinevd,morphletdefault_morphismsignm=letenv=Global.env()inletsigma=Evd.from_envenvinlett=Retyping.get_type_ofenvsigmaminletevars,_,sign,cstrs=PropGlobal.build_signature(sigma,Evar.Set.empty)envt(fstsign)(sndsign)inletevars,morph=app_poly_checkenvevars(PropGlobal.proper_typeenv)[|t;sign;m|]inletevars,mor=resolve_one_typeclassenv(goalevarsevars)morphinmor,proper_projectionenvsigmamormorphletadd_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])]letmake_tacticname=letopenTacexprinlettacqid=Libnames.qualid_of_stringnameinCAst.make@@TacArg(TacCall(CAst.make(tacqid,[])))letadd_morphism_as_parameterattsmn:unit=init_setoid();letinstance_id=add_suffixn"_Proper"inletenv=Global.env()inletevd=Evd.from_envenvinletpoly=atts.polymorphicinletkind,opaque,scope=Decls.(IsAssumptionLogical),false,Locality.GlobalLocality.ImportDefaultBehaviorinletimpargs,udecl=[],UState.default_univ_declinletevd,types=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_interactiveattsmn:Declare.Proof.t=init_setoid();letinstance_id=add_suffixn"_Proper"inletenv=Global.env()inletevd=Evd.from_envenvinletevd,morph=build_morphism_signatureenvevdminletpoly=atts.polymorphicinletkind=Decls.(IsDefinitionInstance)inlettac=make_tactic"Coq.Classes.SetoidTactics.add_morphism_tactic"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.by(Tacinterp.interptac)lemma))()letadd_morphismattsbindersmsn=init_setoid();letinstance_id=add_suffixn"_Proper"inletinstance_name=(CAst.make@@Nameinstance_id),Noneinletinstance_t=CAst.make@@CAppExpl((None,Libnames.qualid_of_string"Coq.Classes.Morphisms.Proper",None),[cHole;s;m])inlettac=Tacinterp.interp(make_tactic"add_morphism_tactic")inletlocality=get_localityatts.globalinlet_id,lemma=Classes.new_instance_interactive~locality~poly:atts.polymorphicinstance_namebindersinstance_t~generalize:false~tac~hook:(declare_projectionninstance_id)Hints.empty_hint_infoNoneinlemma(* no instance body -> always open proof *)(** Bind to "rewrite" too *)(** Taken from original setoid_replace, to emulate the old rewrite semantics where
lemmas are first instantiated and then rewrite proceeds. *)letcheck_evar_map_of_evars_defsenvevd=letmetas=Evd.meta_listevdinletcheck_freemetas_is_emptyrebus=Evd.Metaset.iter(funm->ifEvd.meta_definedevdmthen()elsebeginraise(Logic.RefinerError(env,evd,Logic.UnresolvedBindings[Evd.meta_nameevdm]))end)inList.iter(fun(_,binding)->matchbindingwithEvd.Cltyp(_,{Evd.rebus=rebus;Evd.freemetas=freemetas})->check_freemetas_is_emptyrebusfreemetas|Evd.Clval(_,({Evd.rebus=rebus1;Evd.freemetas=freemetas1},_),{Evd.rebus=rebus2;Evd.freemetas=freemetas2})->check_freemetas_is_emptyrebus1freemetas1;check_freemetas_is_emptyrebus2freemetas2)metas(* Find a subterm which matches the pattern to rewrite for "rewrite" *)letunification_rewritel2rc1c2sigmaprfcarrelbutenv=let(sigma,c')=try(* ~flags:(false,true) to allow to mark occurrences that must not be
rewritten simply by replacing them with let-defined definitions
in the context *)Unification.w_unify_to_subterm~flags:rewrite_unif_flagsenvsigma((ifl2rthenc1elsec2),but)with|exwhenPretype_errors.precatchable_exceptionex->(* ~flags:(true,true) to make Ring work (since it really
exploits conversion) *)Unification.w_unify_to_subterm~flags:rewrite_conv_unif_flagsenvsigma((ifl2rthenc1elsec2),but)inletnfc=Reductionops.nf_evarsigmacinletc1=ifl2rthennfc'elsenfc1andc2=ifl2rthennfc2elsenfc'andcar=nfcarandrel=nfrelincheck_evar_map_of_evars_defsenvsigma;letprf=nfprfinletprfty=nf(Retyping.get_type_ofenvsigmaprf)inletsort=sort_of_relenvsigmabutinletabs=prf,prftyinletprf=mkRel1inletres=(car,rel,prf,c1,c2)inabs,sigma,res,Sorts.is_propsortletget_hypgl(c,l)clausel2r=letevars=Tacmach.New.projectglinletenv=Tacmach.New.pf_envglinletsigma,hi=decompose_applied_relationenvevars(c,l)inletbut=matchclausewith|Someid->Tacmach.New.pf_get_hyp_typidgl|None->Reductionops.nf_evarevars(Tacmach.New.pf_conclgl)inunification_rewritel2rhi.c1hi.c2sigmahi.prfhi.carhi.relbutenvletgeneral_rewrite_flags={under_lambdas=false;on_morphisms=true}(** Setoid rewriting when called with "rewrite" *)letgeneral_s_rewritecll2roccs(c,l)~new_goals=Proofview.Goal.enterbeginfungl->letabs,evd,res,sort=get_hypgl(c,l)cll2rinletunifyenvevarst=unify_absresl2rsortenvevarstinletapp=apply_ruleunifyinletrecstrataux=Strategies.choiceapp(subtermtruegeneral_rewrite_flagsaux)inletsubstrat=Strategies.fixrecstratinletstrat={strategy=fun({state=()}asinput)->letoccs,res=substrat.strategy{inputwithstate=initialize_occurrence_counteroccs}incheck_used_occurrencesoccs;(),res}inletorigsigma=Tacmach.New.projectglintactic_init_setoid()<*>Proofview.tclOR(tclPROGRESS(tclTHEN(Proofview.Unsafe.tclEVARSevd)(cl_rewrite_clause_newtac~progress:true~abs:(Someabs)~origsigmastratcl)))(fun(e,info)->matchewith|RewriteFailuree->tclFAIL~info0(str"setoid rewrite failed: "++e)|e->Proofview.tclZERO~infoe)endlet_=Hook.setEquality.general_setoid_rewrite_clausegeneral_s_rewrite(** [setoid_]{reflexivity,symmetry,transitivity} tactics *)letnot_declared~infoenvsigmatyrel=tclFAIL~info0(str" The relation "++Printer.pr_econstr_envenvsigmarel++str" is not a declared "++strty++str" relation. Maybe you need to require the Coq.Classes.RelationClasses library")letsetoid_prooftyfnfallback=Proofview.Goal.enterbeginfungl->letenv=Proofview.Goal.envglinletsigma=Tacmach.New.projectglinletconcl=Proofview.Goal.conclglinProofview.tclORELSEbegintryletrel,_,_=decompose_app_relenvsigmaconclinlet(sigma,t)=Typing.type_ofenvsigmarelinletcar=snd(List.hd(fst(Reductionops.splay_prodenvsigmat)))in(tryinit_relation_classes()with_->raiseNot_found);fnenvsigmacarrelwithewhenCErrors.noncriticale->(* XXX what is the right test here as to whether e can be converted ? *)lete,info=Exninfo.captureeinProofview.tclZERO~infoeendbeginfunction|e->Proofview.tclORELSEfallbackbeginfunction(e',info)->matche'with|Hipattern.NoEquationFound->beginmatchewith|(Not_found,_)->letrel,_,_=decompose_app_relenvsigmaconclinnot_declared~infoenvsigmatyrel|(e,info)->Proofview.tclZERO~infoeend|e'->Proofview.tclZERO~infoe'endendendlettac_open((evm,_),c)tac=(tclTHEN(Proofview.Unsafe.tclEVARSevm)(tacc))letpoly_proofgetpgettenvevmcarrel=ifSorts.is_prop(sort_of_relenvevmrel)thengetpenv(evm,Evar.Set.empty)carrelelsegettenv(evm,Evar.Set.empty)carrelletsetoid_reflexivity=setoid_proof"reflexive"(funenvevmcarrel->tac_open(poly_proofPropGlobal.get_reflexive_proofTypeGlobal.get_reflexive_proofenvevmcarrel)(func->tclCOMPLETE(applyc)))(reflexivity_redtrue)letsetoid_symmetry=setoid_proof"symmetric"(funenvevmcarrel->tac_open(poly_proofPropGlobal.get_symmetric_proofTypeGlobal.get_symmetric_proofenvevmcarrel)(func->applyc))(symmetry_redtrue)letsetoid_transitivityc=setoid_proof"transitive"(funenvevmcarrel->tac_open(poly_proofPropGlobal.get_transitive_proofTypeGlobal.get_transitive_proofenvevmcarrel)(funproof->matchcwith|None->eapplyproof|Somec->apply_with_bindings(proof,ImplicitBindings[c])))(transitivity_redtruec)letsetoid_symmetry_inid=Proofview.Goal.enterbeginfungl->letenv=Proofview.Goal.envglinletsigma=Proofview.Goal.sigmaglinletctype=Retyping.get_type_ofenvsigma(mkVarid)inletbinders,concl=decompose_prod_assumsigmactypeinlet(equiv,args)=decompose_appsigmaconclinletrecsplit_last_two=function|[c1;c2]->[],(c1,c2)|x::y::z->letl,res=split_last_two(y::z)inx::l,res|_->user_errPp.(str"Cannot find an equivalence relation to rewrite.")inletothers,(c1,c2)=split_last_twoargsinlethe,c1,c2=mkApp(equiv,Array.of_listothers),c1,c2inletnew_hyp'=mkApp(he,[|c2;c1|])inletnew_hyp=it_mkProd_or_LetInnew_hyp'bindersin(tclTHENLAST(Tactics.assert_after_replacingidnew_hyp)(tclTHENLIST[intros;setoid_symmetry;apply(mkVarid);Tactics.assumption]))endlet_=Hook.setTactics.setoid_reflexivitysetoid_reflexivitylet_=Hook.setTactics.setoid_symmetrysetoid_symmetrylet_=Hook.setTactics.setoid_symmetry_insetoid_symmetry_inlet_=Hook.setTactics.setoid_transitivitysetoid_transitivityletget_lemma_prooffenvevmxy=let(evm,_),c=fenv(evm,Evar.Set.empty)xyinevm,cletget_reflexive_proof=get_lemma_proofPropGlobal.get_reflexive_proofletget_symmetric_proof=get_lemma_proofPropGlobal.get_symmetric_proofletget_transitive_proof=get_lemma_proofPropGlobal.get_transitive_proof