1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059(************************************************************************)(* * 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) *)(************************************************************************)openPpopenCErrorsopenUtilopenNamesopenConstropenContextopenEConstropenVarsopenReductionopenTacticalsopenTacticsopenPretype_errorsopenEvdopenTactypesopenLocusopenLocusopsopenElimschemesopenEnvironopenTermopsopenEConstropenLibnamesopenProofview.NotationsopenContext.Named.DeclarationmoduleNamedDecl=Context.Named.Declaration(* module RelDecl = Context.Rel.Declaration *)moduleTC=Typeclasses(** Typeclass-based generalized rewriting. *)(** 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)infunenv(evd,cstrs)->let(evd,c)=Evd.fresh_globalenvevd(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. *)letextends_undefinedevarsevars'=letfevevifound=found||not(Evd.memevarsev)infold_undefinedfevars'falseletapp_poly_checkenvevarsfargs=let(evars,cstrs),fc=fenvevarsinletevars,t=Typing.solve_evarsenvevars(mkApp(fc,args))in(evars,cstrs),tletapp_poly_nocheckenvevarsfargs=letevars,fc=fenvevarsinevars,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=TC.resolve_one_typeclassenv(goalevarsevars)goalinifextends_undefined(goalevarsevars)evars'thenraiseNot_foundelseapp_poly_checkenv(evars',cstrevarsevars)proof_method[|carrier;relation;c|]withewhenCErrors.noncriticale->raiseNot_foundleteq_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->Nonetypehypinfo={prf:constr;car:constr;rel:constr;sort:bool;(* true = Prop; false = Type *)c1:constr;c2:constr;holes:Clenv.holelist;}leterror_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|])->(* This treats the special case `g (R x y)`, turning it into
the relation `(fun x y => g (R x y))`. Useful when g is negation in particular. *)let(f',argl,argr)=decompose_app_relenvevdarginletty=Retyping.get_type_ofenvevdarglinletty'=Retyping.get_type_ofenvevdargrinletr=Retyping.relevance_of_typeenvevdtyinletr'=Retyping.relevance_of_typeenvevdty'inletf''=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()inifnot(Reductionops.is_arityenvevdty)thenNoneelsematchReductionops.splay_arityenvevdtywith|[_,ty2;_,ty1],concl->ifnoccurnevd1ty2thenSome(rel,ty1,subst1mkPropty2,concl,t1,t2)elseNone|_->assertfalseletdecompose_app_rel_errorenvevdt=matchdecompose_app_relenvevdtwith|Somee->e|None->error_no_relation()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}=clinmatchdecompose_app_relenvsigmatwith|None->None|Some(equiv,ty1,ty2,concl,c1,c2)->matchevd_convertibleenvsigmaty1ty2with|None->None|Somesigma->letargs=Array.map_of_list(funh->h.Clenv.hole_evar)holesinletvalue=mkApp(c,args)inSome(sigma,{prf=value;car=ty1;rel=equiv;sort=Sorts.is_prop(ESorts.kindsigmaconcl);c1=c1;c2=c2;holes})inmatchfind_relctypewith|Somec->c|None->letctx,t'=Reductionops.splay_prodenvsigmactypein(* Search for underlying eq *)lett'=it_mkProd_or_LetInt'(List.map(fun(n,t)->LocalAssum(n,t))ctx)inmatchfind_relt'with|Somec->c|None->user_errPp.(str"Cannot find an homogeneous relation to rewrite.")(** Utility functions *)moduleGlobalBindings(M:sigvalrelation_classes:stringlistvalmorphisms:stringlistvalrelation:stringlist*stringvalapp_poly:env->evars->(env->evars->evars*constr)->constrarray->evars*constrvalarrow:env->evars->evars*constrend)=structopenMopenContext.Rel.Declarationletrelation:env->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"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->TC.class_infoenvsigma(Lazy.forcer)letproper_proxy_class=letr=lazy(find_referencemorphisms"ProperProxy")infunenvsigma->TC.class_infoenvsigma(Lazy.forcer)letproper_projenvsigma=mkConst(Option.get(List.hd(proper_classenvsigma).TC.cl_projs).TC.meth_const)letproper_typeenv(sigma,cstrs)=letl=(proper_classenvsigma).TC.cl_implinlet(sigma,c)=Evd.fresh_globalenvsigmalin(sigma,cstrs),cletproper_proxy_typeenv(sigma,cstrs)=letl=(proper_proxy_classenvsigma).TC.cl_implinlet(sigma,c)=Evd.fresh_globalenvsigmalin(sigma,cstrs),cletproper_proofenvevarscarrierrelationx=letevars,goal=app_polyenvevarsproper_proxy_type[|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_relationenvevarsty=letevars',ty=Evarsolve.refresh_universes~onlyalg:true~status:(Evd.UnivFlexiblefalse)(Somefalse)env(fstevars)tyinapp_polyenv(evars',sndevars)relation[|ty|](** 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',b'=Evarsolve.refresh_universes~onlyalg:true~status:(Evd.UnivFlexiblefalse)(Somefalse)env(fstevars)b'inletevars,newarg=app_polyenv(evars',sndevars)respectful[|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")|[]->relletrefresh_univsenvevarsty=letevars',ty=Evarsolve.refresh_universes~onlyalg:true~status:(Evd.UnivFlexiblefalse)(Somefalse)env(fstevars)tyin(evars',sndevars),tyletpointwise_or_dep_relationenvevarsntcarrel=letevars,car=refresh_univsenvevarscarinifnoccurn(goalevarsevars)1car&&noccurn(goalevarsevars)1relthenapp_polyenvevarspointwise_relation[|t;lift(-1)car;lift(-1)rel|]elseapp_polyenvevarsforall_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(tryletenv'=push_rel_contextrelsenvinmatchdecompose_app_relenv'sigmatwith|None->None|Some(equiv,ty1,ty2,concl,c1,c2)->let(evars,evset),inst=app_polyenv'(sigma,Evar.Set.empty)rewrite_relation_class[|ty1;equiv|]inletsigma,_=TC.resolve_one_typeclassenv'evarsinstin(* We check that the relation is homogeneous *after* launching resolution,
as this convertibility test might be expensive in general (e.g. this
slows down mathcomp-odd-order). *)matchevd_convertibleenvsigmaty1ty2with|None->None|Somesigma->Some(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=letevd,car=Evarsolve.refresh_universes~onlyalg:true(Somefalse)envevdcarinlet(evd,sort)=Evarutil.new_Type~rigid:Evd.univ_flexibleevdinapp_poly_checkenv(evd,cstrs)coq_inverse[|car;car;sort;rel|]endletget_type_of_refreshenvevarst=letevars',tty=Evarsolve.get_type_of_refreshenv(fstevars)tin(evars',sndevars),ttyletsort_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)letget_symmetric_proofb=ifbthenPropGlobal.get_symmetric_proofelseTypeGlobal.get_symmetric_proofletrewrite_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(cb:EConstr.twith_bindingsdelayed_open)=letsigma,cbl=cbenvsigmainletsigma,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=TC.resolve_typeclasses~filter:(no_constraintscstrs)~fail:trueenvsigmainletsigma=solve_remaining_byenvsigmaholesbyinletnfc=Reductionops.nf_evarsigma(Reductionops.nf_metaenvsigmac)inletc1=nfc1andc2=nfc2andrew_car=nfcarandrel=nfrelandprf=nfprfinletty1=Retyping.get_type_ofenvsigmac1inletty2=Retyping.get_type_ofenvsigmac2inbeginmatchReductionops.infer_conv~pb:CUMULenvsigmaty2ty1with|None->None|Somesigma->letrew_evars=sigma,cstrsinletrew_prf=RewPrf(rel,prf)inletrew={rew_evars;rew_prf;rew_car;rew_from=c1;rew_to=c2;}inletrew=ifl2rthenrewelsesymmetryenvsortrewinSomerewendwith|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_globalenv(evars,cstrs)gr=let(sigma,c)=Evd.fresh_globalenvevarsgrin(sigma,cstrs),cletmake_eqenvsigma=new_globalenvsigmaCoqlib.(lib_ref"core.eq.type")letmake_eq_reflenvsigma=new_globalenvsigmaCoqlib.(lib_ref"core.eq.refl")letget_rew_prfenvevarsr=matchr.rew_prfwith|RewPrf(rel,prf)->evars,(rel,prf)|RewCastc->letevars,eq=make_eqenvevarsinletevars,eq_refl=make_eq_reflenvevarsinletrel=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,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 *)letevars',appmtype'=Evarsolve.refresh_universes~status:(Evd.UnivFlexiblefalse)~onlyalg:true(Somefalse)env(fstevars)appmtype'inletcl_args=[|appmtype';signature;appm|]inletevars,app=app_poly_sortbenv(evars',sndevars)(ifbthenPropGlobal.proper_typeelseTypeGlobal.proper_type)cl_argsinletdosub,appsub=ifbthenPropGlobal.do_subrelation,PropGlobal.apply_subrelationelseTypeGlobal.do_subrelation,TypeGlobal.apply_subrelationinlet_,dosub=app_poly_sortbenvevarsdosub[||]inlet_,appsub=app_poly_nocheckenvevarsappsub[||]inletdosub_id=Id.of_string"do_subrelation"inletenv'=EConstr.push_named(LocalDef(make_annotdosub_idSorts.Relevant,dosub,appsub))envinletevars,morph=new_cstr_evarevarsenv'appin(* Replace the free [dosub_id] in the evar by the global reference *)letmorph=Vars.replace_vars[dosub_id,dosub]morphinevars,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_prfenvevarsrin[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_prfenvres.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}letfold_match?(force=false)envsigmac=letcase=destCasesigmacinlet(ci,p,iv,c,brs)=EConstr.expand_caseenvsigmacaseinletcty=Retyping.get_type_ofenvsigmacinletdep,pred,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,cst|None->raiseNot_foundinletapp=letind,args=Inductiveops.find_mrectypeenvsigmactyinletpars,args=List.chopci.ci_nparargsinletmeths=Array.to_listbrsinapplist(mkConstsk,pars@[pred]@meths@args@[c])insk,env,appletunfold_matchenvsigmaskapp=matchEConstr.kindsigmaappwith|App(f',args)whenQConstant.equalenv(fst(destConstsigmaf'))sk->letv=Environ.constant_value_inenv(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)elseletevars,argty=get_type_of_refreshenvevarsarginletstate,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_morphismsthenletevars,mty=get_type_of_refreshenvevarsminletevars,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=subst1mkPropbinletevars,tx=get_type_of_refreshenvevarsxinletevars,tb=get_type_of_refreshenvevarsbinletarr=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. *)lettransitivitystateenvunfreshcstr(res:rewrite_result_info)(next:'apure_strategy):'a*rewrite_result=letcstr=matchcstrwith|_,Some_->cstr|prop,None->prop,get_opt_rew_relres.rew_prfinletstate,nextres=next.strategy{state;env;unfresh;cstr;term1=res.rew_to;ty1=res.rew_car;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=iffstcstrthenPropGlobal.transitive_typeelseTypeGlobal.transitive_typeinletevars,prfty=app_poly_sort(fstcstr)envres'.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_typeelseTypeGlobal.proper_proxy_typeinletevars,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->transitivitystateenvunfreshcstrressnd}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.choice(Strategies.progressapp)(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'=TC.resolve_typeclassesenv~filter:TC.all_evars~split:false~fail:trueevars'inEvd.set_typeclass_evarsevars'oldtcsletnf_zeta=Reductionops.clos_norm_flags(CClosure.RedFlags.mkflags[CClosure.RedFlags.fZETA])exceptionRewriteFailureofEnviron.env*Evd.evar_map*pretype_errortyperesult=(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(str"Unsolved constraint remaining: "++spc()++Termops.pr_evar_infoenvevars(Evd.findevarsev)++str"."))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.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~cast:false~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~cast:false~check:falsenewtDEFAULTcastinProofview.Goal.enterbeginfungl->letconcl=Proofview.Goal.conclglinletenv=Proofview.Goal.envglinletstate=Proofview.Goal.stateglinletsigma=Tacmach.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(env,evd,e))endlettactic_init_setoid()=tryinit_setoid();Proofview.tclUNIT()withewhenCErrors.noncriticale->let_,info=Exninfo.captureeinTacticals.tclFAIL~info(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|Tacticals.FailError(n,pp)->tclFAILn~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_constr((_,c):_*EConstr.tdelayed_open)l2roccs=();fun({state=();env=env}asinput)->letcsigma=let(sigma,c)=cenvsigmain(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=|Composetypenary_strategy=Choicetype('constr,'redexpr)strategy_ast=|StratId|StratFail|StratRefl|StratUnaryofunary_strategy*('constr,'redexpr)strategy_ast|StratBinaryofbinary_strategy*('constr,'redexpr)strategy_ast*('constr,'redexpr)strategy_ast|StratNAryofnary_strategy*('constr,'redexpr)strategy_astlist|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')|StratNAry(s,strs)->StratNAry(s,List.map(map_strategyfg)strs)|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)|StratNAry(Choice,strs)->str"choice"++spc()++prlist_with_sepspc(funstr->paren(pr_strategyprcprrstr))strs|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_ast=function|StratId->Strategies.id|StratFail->Strategies.fail|StratRefl->Strategies.refl|StratUnary(f,s)->lets'=strategy_of_astsinletf'=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_astsinlett'=strategy_of_asttinletf'=matchfwith|Compose->Strategies.seqinf's't'|StratNAry(Choice,strs)->letstrs=List.map(strategy_of_ast)strsinbeginmatchstrswith|[]->assertfalse|s::strs->List.fold_leftStrategies.choicesstrsend|StratConstr(c,b)->{strategy=apply_glob_constrcbAllOccurrences}|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)=renv(goalevarsevars)in(Strategies.reducer_interp).strategy{inputwithevars=(sigma,cstrevarsevars)})}|StratFoldc->Strategies.fold_glob(fstc)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_LetInappctxletbuild_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|]inletevd',t=new_cstr_evar!evdenvdefaultinevd:=evd')rel)cstrsinletmorph=e_app_polyenvevdPropGlobal.proper_type[|t;sig_;m|]inletevd=solve_constraintsenv!evdinevd,morphletdefault_morphismenvsigmasignm=lett=Retyping.get_type_ofenvsigmaminletevars,_,sign,cstrs=PropGlobal.build_signature(sigma,Evar.Set.empty)envt(fstsign)(sndsign)inletevars,morph=app_poly_checkenvevarsPropGlobal.proper_type[|t;sign;m|]inletevars,mor=TC.resolve_one_typeclassenv(goalevarsevars)morphinmor,proper_projectionenvsigmamormorph(** 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.projectglinletenv=Tacmach.pf_envglinletsigma,hi=decompose_applied_relationenvevars(c,l)inletbut=matchclausewith|Someid->Tacmach.pf_get_hyp_typidgl|None->Reductionops.nf_evarevars(Tacmach.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.projectglintactic_init_setoid()<*>Proofview.tclOR(tclPROGRESS(tclTHEN(Proofview.Unsafe.tclEVARSevd)(cl_rewrite_clause_newtac~progress:true~abs:(Someabs)~origsigmastratcl)))(fun(e,info)->matchewith|e->Proofview.tclZERO~infoe)endlet_=Hook.setEquality.general_setoid_rewrite_clausegeneral_s_rewrite(** [setoid_]{reflexivity,symmetry,transitivity} tactics *)letnot_declared~infoenvsigmatyrel=tclFAIL~info(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.projectglinletconcl=Proofview.Goal.conclglinProofview.tclORELSEbegintryletrel,ty1,ty2,concl,_,_=decompose_app_rel_errorenvsigmaconclinlet(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_rel_errorenvsigmaconclinnot_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_proofmoduleInternal=structletbuild_signatureenvsigmamcstrfinalcstr=letevars=(sigma,Evar.Set.empty)inlet((sigma,_),_,sig_,cstr)=PropGlobal.build_signatureevarsenvmcstrfinalcstrinsigma,sig_,cstrletbuild_morphism_signature=build_morphism_signatureletdefault_morphism=default_morphismend