12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640(************************************************************************)(* * The Rocq Prover / The Rocq 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) *)(************************************************************************)openConstropenNamesopenPpopenLazymoduleNamedDecl=Context.Named.DeclarationmoduleERelevance=EConstr.ERelevanceletdebug_zify=CDebug.create~name:"zify"()(* The following [constr] are necessary for constructing the proof terms *)letzifystr=EConstr.of_constr(UnivGen.constr_of_monomorphic_global(Global.env())(Rocqlib.lib_ref("ZifyClasses."^str)))(** classes *)letrocq_InjTyp=lazy(Rocqlib.lib_ref"ZifyClasses.InjTyp")letrocq_BinOp=lazy(Rocqlib.lib_ref"ZifyClasses.BinOp")letrocq_UnOp=lazy(Rocqlib.lib_ref"ZifyClasses.UnOp")letrocq_CstOp=lazy(Rocqlib.lib_ref"ZifyClasses.CstOp")letrocq_BinRel=lazy(Rocqlib.lib_ref"ZifyClasses.BinRel")letrocq_PropBinOp=lazy(Rocqlib.lib_ref"ZifyClasses.PropBinOp")letrocq_PropUOp=lazy(Rocqlib.lib_ref"ZifyClasses.PropUOp")letrocq_BinOpSpec=lazy(Rocqlib.lib_ref"ZifyClasses.BinOpSpec")letrocq_UnOpSpec=lazy(Rocqlib.lib_ref"ZifyClasses.UnOpSpec")letrocq_Saturate=lazy(Rocqlib.lib_ref"ZifyClasses.Saturate")(* morphism like lemma *)letmkapp2=lazy(zify"mkapp2")letmkapp=lazy(zify"mkapp")leteq_refl=lazy(zify"eq_refl")leteq=lazy(zify"eq")letmkrel=lazy(zify"mkrel")letiff_refl=lazy(zify"iff_refl")leteq_iff=lazy(zify"eq_iff")letrew_iff=lazy(zify"rew_iff")letrew_iff_rev=lazy(zify"rew_iff_rev")(* propositional logic *)letop_and=lazy(zify"and")letop_and_morph=lazy(zify"and_morph")letop_or=lazy(zify"or")letop_or_morph=lazy(zify"or_morph")letop_impl_morph=lazy(zify"impl_morph")letop_iff=lazy(zify"iff")letop_iff_morph=lazy(zify"iff_morph")letop_not=lazy(zify"not")letop_not_morph=lazy(zify"not_morph")letop_True=lazy(zify"True")letop_I=lazy(zify"I")(** [unsafe_to_constr c] returns a [Constr.t] without considering an evar_map.
This is useful for calling Constr.hash *)letunsafe_to_constr=EConstr.Unsafe.to_constrletpr_constrenvevde=Printer.pr_econstr_envenvevdeletgl_pr_constre=letgenv=Global.env()inletevd=Evd.from_envgenvinpr_constrgenvevdeletwhd=Reductionops.clos_whd_flagsRedFlags.allletis_convertibleenvevdt1t2=Reductionops.(is_convenvevdt1t2)(** [get_type_of] performs beta reduction ;
Is it ok for Retyping.get_type_of (Zpower_nat n q) to return (fun _ : nat => Z) q ? *)letget_type_ofenvevde=Tacred.cbv_betaenvevd(Retyping.get_type_ofenvevde)(* arguments are dealt with in a second step *)letrecfind_optionpredl=matchlwith|[]->raiseNot_found|e::l->(matchpredewithSomer->r|None->find_optionpredl)moduleConstrMap=structopenNames.GlobReftype'at='alistMap.tletaddgrem=Map.updategr(functionNone->Some[e]|Somel->Some(e::l))mletempty=Map.emptyletfindevdhm=matchMap.find(fst(EConstr.destRefevdh))mwith|e::_->e|[]->assertfalseletfind_allevdhm=Map.find(fst(EConstr.destRefevdh))mletfoldfmacc=Map.fold(funklacc->List.fold_left(funacce->fkeacc)accl)maccendmoduleHConstr=structmoduleM=Map.Make(structtypet=EConstr.tletcomparecc'=Constr.compare(unsafe_to_constrc)(unsafe_to_constrc')end)type'at='aM.tletaddhem=M.addhemletempty=M.emptyletfind=M.findend(** [get_projections_from_constant (evd,c) ]
returns an array of constr [| a1,.. an|] such that [c] is defined as
Definition c := mk a1 .. an with mk a constructor.
ai is therefore either a type parameter or a projection.
*)letget_projections_from_constant(evd,i)=matchEConstr.kindevd(whd(Global.env())evdi)with|App(c,a)->a|_->raise(CErrors.user_errPp.(str"The hnf of term "++pr_constr(Global.env())evdi++str" should be an application i.e. (c a1 ... an)"))(** An instance of type, say T, is registered into a hashtable, say TableT. *)type'adecl={decl:EConstr.t;(* Registered type instance *)deriv:'a(* Projections of insterest *)}moduleEInjT=structtypet={isid:bool;(* S = T -> inj = fun x -> x*)source:EConstr.t;(* S *)target:EConstr.t;(* T *)(* projections *)inj:EConstr.t;(* S -> T *)pred:EConstr.t;(* T -> Prop *)cstr:EConstr.toption(* forall x, pred (inj x) *)}leteq_injevdi1i2=i1.isid=i2.isid&&EConstr.eq_constrevdi1.inji2.injend(** [classify_op] classify injected operators and detect special cases. *)typeclassify_op=|OpInj(* e.g. Z.of_nat -> \x.x *)|OpSame(* e.g. Z.add -> Z.add *)|OpConv(* e.g. Pos.ge == \x.y. Z.ge (Z.pos x) (Z.pos y)
\x.y. Z.pos (Pos.add x y) == \x.y. Z.add (Z.pos x) (Z.pos y)
Z.succ == (\x.x + 1)
*)|OpOther(*let pp_classify_op = function
| OpInj -> Pp.str "Identity"
| OpSame -> Pp.str "Same"
| OpConv -> Pp.str "Conv"
| OpOther -> Pp.str "Other"
*)letnamex=Context.make_annot(Name.mk_name(Names.Id.of_stringx))ERelevance.relevantletmkconvert_unopi1i2optop=(* fun x => inj (op x) *)letop=EConstr.mkLambda(name"x",i1.EInjT.source,EConstr.mkApp(i2.EInjT.inj,[|EConstr.mkApp(op,[|EConstr.mkRel1|])|]))in(* fun x => top (inj x) *)lettop=EConstr.mkLambda(name"x",i1.EInjT.source,EConstr.mkApp(top,[|EConstr.mkApp(i1.EInjT.inj,[|EConstr.mkRel1|])|]))in(op,top)letmkconvert_binopi1i2i3optop=(* fun x y => inj (op x y) *)letop=EConstr.mkLambda(name"x",i1.EInjT.source,EConstr.mkLambda(name"y",i1.EInjT.source,EConstr.mkApp(i3.EInjT.inj,[|EConstr.mkApp(op,[|EConstr.mkRel2;EConstr.mkRel1|])|])))in(* fun x y => top (inj x) (inj y) *)lettop=EConstr.mkLambda(name"x",i1.EInjT.source,EConstr.mkLambda(name"y",i2.EInjT.source,EConstr.mkApp(top,[|EConstr.mkApp(i1.EInjT.inj,[|EConstr.mkRel2|]);EConstr.mkApp(i2.EInjT.inj,[|EConstr.mkRel1|])|])))in(op,top)letmkconvert_relirtr=lettr=EConstr.mkLambda(name"x",i.EInjT.source,EConstr.mkLambda(name"y",i.EInjT.source,EConstr.mkApp(tr,[|EConstr.mkApp(i.EInjT.inj,[|EConstr.mkRel2|]);EConstr.mkApp(i.EInjT.inj,[|EConstr.mkRel1|])|])))in(r,tr)(** [classify_op mkconvert op top] takes the injection [inj] for the origin operator [op]
and the destination operator [top] -- both [op] and [top] are closed terms *)letclassify_opmkconvertinjoptop=letenv=Global.env()inletevd=Evd.from_envenvinifis_convertibleenvevdinjopthenOpInjelseifEConstr.eq_constrevdoptopthenOpSameelseletop,top=mkconvertoptopinifis_convertibleenvevdoptopthenOpConvelseOpOther(*let classify_op mkconvert tysrc op top =
let res = classify_op mkconvert tysrc op top in
Feedback.msg_debug
Pp.(
str "classify_op:" ++ gl_pr_constr op ++ str " " ++ gl_pr_constr top
++ str " " ++ pp_classify_op res ++ fnl ());
res
*)moduleEBinOpT=structtypet={(* Op : source1 -> source2 -> source3 *)source1:EConstr.t;source2:EConstr.t;source3:EConstr.t;target1:EConstr.t;target2:EConstr.t;target3:EConstr.t;inj1:EInjT.t(* InjTyp source1 target1 *);inj2:EInjT.t(* InjTyp source2 target2 *);inj3:EInjT.t(* InjTyp source3 target3 *);bop:EConstr.t(* BOP *);tbop:EConstr.t(* TBOP *);tbopinj:EConstr.t(* TBOpInj *);classify_binop:classify_op}endmoduleECstOpT=structtypet={source:EConstr.t;target:EConstr.t;inj:EInjT.t;cst:EConstr.t;cstinj:EConstr.t;is_construct:bool}endmoduleEUnOpT=structtypet={source1:EConstr.t;source2:EConstr.t;target1:EConstr.t;target2:EConstr.t;uop:EConstr.t;inj1_t:EInjT.t;inj2_t:EInjT.t;tuop:EConstr.t;tuopinj:EConstr.t;classify_unop:classify_op;is_construct:bool}endmoduleEBinRelT=structtypet={source:EConstr.t;target:EConstr.t;inj:EInjT.t;brel:EConstr.t;tbrel:EConstr.t;brelinj:EConstr.t;classify_rel:classify_op}endmoduleEPropBinOpT=structtypet={op:EConstr.t;op_iff:EConstr.t}endmoduleEPropUnOpT=structtypet={op:EConstr.t;op_iff:EConstr.t}endmoduleESatT=structtypet={parg1:EConstr.t;parg2:EConstr.t;satOK:EConstr.t}endmoduleESpecT=structtypet={spec:EConstr.t}end(* Different type of declarations *)typedecl_kind=|PropOpofEPropBinOpT.tdecl|PropUnOpofEPropUnOpT.tdecl|InjTypofEInjT.tdecl|BinRelofEBinRelT.tdecl|BinOpofEBinOpT.tdecl|UnOpofEUnOpT.tdecl|CstOpofECstOpT.tdecl|SaturateofESatT.tdecl|UnOpSpecofESpecT.tdecl|BinOpSpecofESpecT.tdecllettarget_injd=matchdwith|BinOpd->Somed.deriv.EBinOpT.inj3|UnOpd->Somed.deriv.EUnOpT.inj2_t|CstOpd->Somed.deriv.inj|_->Nonetypeterm_kind=ApplicationofEConstr.constr|OtherTermofEConstr.constrmoduletypeElt=sigtypeelt(** name *)valname:stringvalgref:GlobRef.tLazy.tvaltable:(term_kind*decl_kind)ConstrMap.trefvalcast:eltdecl->decl_kindvaldest:decl_kind->eltdecloption(** [get_key] is the type-index used as key for the instance *)valget_key:int(** [mk_elt evd i [a0,..,an]] returns the element of the table
built from the type-instance i and the arguments (type indexes and projections)
of the type-class constructor. *)valmk_elt:Evd.evar_map->EConstr.t->EConstr.tarray->elt(* val arity : int*)endlettable=Summary.ref~name:"zify_table"ConstrMap.emptyletsaturate=Summary.ref~name:"zify_saturate"ConstrMap.emptyletspecs=Summary.ref~name:"zify_specs"ConstrMap.emptylettable_cache=refConstrMap.emptyletsaturate_cache=refConstrMap.emptyletspecs_cache=refConstrMap.empty(** Each type-class gives rise to a different table.
They only differ on how projections are extracted. *)moduleEInj=structopenEInjTtypeelt=EInjT.tletname="EInj"letgref=rocq_InjTyplettable=tableletcastx=InjTypxletdest=functionInjTypx->Somex|_->Noneletis_cstr_trueevdc=matchEConstr.kindevdcwith|Lambda(_,_,c)->EConstr.eq_constr_nounivsevdc(Lazy.forceop_True)|_->falseletmk_eltevdi(a:EConstr.tarray)=letisid=EConstr.eq_constr_nounivsevda.(0)a.(1)in{isid;source=a.(0);target=a.(1);inj=a.(2);pred=a.(3);cstr=(ifis_cstr_trueevda.(3)thenNoneelseSomea.(4))}letget_key=0endletget_injevdc=leta=get_projections_from_constant(evd,c)inEInj.mk_eltevdcaletrecdecomp_typeevdty=matchEConstr.kind_of_typeevdtywith|EConstr.ProdType(_,t1,rst)->t1::decomp_typeevdrst|_->[ty]letpp_typeenvevdl=Pp.prlist_with_sep(fun_->Pp.str" -> ")(pr_constrenvevd)lletcheck_typevdexptyop=letenv=Global.env()inletty=Retyping.get_type_ofenvevdopinletty=decomp_typeevdtyinifList.for_all2(EConstr.eq_constr_nounivsevd)tyexptythen()elseraise(CErrors.user_errPp.(str": Cannot register operator "++pr_constrenvevdop++str". It has type "++pp_typeenvevdty++str" instead of expected type "++pp_typeenvevdexpty))moduleEBinOp=structtypeelt=EBinOpT.topenEBinOpTletname="BinOp"letgref=rocq_BinOplettable=tableletmk_eltevdia=leti1=get_injevda.(7)inleti2=get_injevda.(8)inleti3=get_injevda.(9)inletbop=a.(6)inlettbop=a.(10)incheck_typevdEInjT.[i1.source;i2.source;i3.source]bop;{source1=a.(0);source2=a.(1);source3=a.(2);target1=a.(3);target2=a.(4);target3=a.(5);inj1=i1;inj2=i2;inj3=i3;bop;tbop;tbopinj=a.(11);classify_binop=classify_op(mkconvert_binopi1i2i3)i3.EInjT.inja.(6)tbop}letget_key=6letcastx=BinOpxletdest=functionBinOpx->Somex|_->Noneend(*let debug_term msg c =
let genv = Global.env () in
Feedback.msg_debug
Pp.(str msg ++ str " " ++ pr_constr genv (Evd.from_env genv) c);
c
*)moduleECstOp=structtypeelt=ECstOpT.topenECstOpTletname="CstOp"letgref=rocq_CstOplettable=tableletcastx=CstOpxletdest=functionCstOpx->Somex|_->NoneletisConstructevdc=matchEConstr.kindevdcwith|Construct_|Int_|Float_->true|_->falseletmk_eltevdia={source=a.(0);target=a.(1);inj=get_injevda.(3);cst=a.(4);cstinj=a.(5);is_construct=isConstructevda.(2)}letget_key=2endmoduleEUnOp=structtypeelt=EUnOpT.topenEUnOpTletname="UnOp"letgref=rocq_UnOplettable=tableletcastx=UnOpxletdest=functionUnOpx->Somex|_->Noneletmk_eltevdia=leti1=get_injevda.(5)inleti2=get_injevda.(6)inletuop=a.(4)incheck_typevdEInjT.[i1.source;i2.source]uop;lettuop=a.(7)in{source1=a.(0);source2=a.(1);target1=a.(2);target2=a.(3);uop;inj1_t=i1;inj2_t=i2;tuop;tuopinj=a.(8);is_construct=EConstr.isConstructevduop;classify_unop=classify_op(mkconvert_unopi1i2)i2.EInjT.injuoptuop}letget_key=4endmoduleEBinRel=structtypeelt=EBinRelT.topenEBinRelTletname="BinRel"letgref=rocq_BinRellettable=tableletcastx=BinRelxletdest=functionBinRelx->Somex|_->Noneletmk_eltevdia=leti=get_injevda.(3)inletbrel=a.(2)inlettbrel=a.(4)incheck_typevdEInjT.[i.source;i.source;EConstr.mkProp]brel;{source=a.(0);target=a.(1);inj=get_injevda.(3);brel;tbrel;brelinj=a.(5);classify_rel=classify_op(mkconvert_reli)i.EInjT.injbreltbrel}letget_key=2endmoduleEPropBinOp=structtypeelt=EPropBinOpT.topenEPropBinOpTletname="PropBinOp"letgref=rocq_PropBinOplettable=tableletcastx=PropOpxletdest=functionPropOpx->Somex|_->Noneletmk_eltevdia={op=a.(0);op_iff=a.(1)}letget_key=0endmoduleEPropUnOp=structtypeelt=EPropUnOpT.topenEPropUnOpTletname="PropUOp"letgref=rocq_PropUOplettable=tableletcastx=PropUnOpxletdest=functionPropUnOpx->Somex|_->Noneletmk_eltevdia={op=a.(0);op_iff=a.(1)}letget_key=0endletconstr_of_term_kind=functionApplicationc->c|OtherTermc->cletzify_register_locality=letopenAttributes.NotationsinAttributes.explicit_hint_locality>>=function|Somev->let()=Locality.check_locality_nodischargevinreturnv|None->return(ifLib.sections_are_opened()thenHints.LocalelseHints.SuperGlobal)moduletypeS=sigvalregister:Hints.hint_locality->Libnames.qualid->unitvalprint:unit->unitendmoduleMakeTable(E:Elt):S=struct(** Given a term [c] and its arguments ai,
we construct a HConstr.t table that is
indexed by ai for i = E.get_key.
The elements of the table are built using E.mk_elt c [|a0,..,an|]
*)letmake_elt(evd,i)=leta=get_projections_from_constant(evd,i)inE.mk_eltevdialetsafe_refevdc=tryfst(EConstr.destRefevdc)withDestKO->CErrors.user_errPp.(str"Add Zify "++strE.name++str": the term "++gl_pr_constrc++str" should be a global reference")letregister_hintevdtelt=matchEConstr.kindevdtwith|App(c,_)->letgr=safe_refevdcinE.table:=ConstrMap.addgr(Applicationt,E.castelt)!E.table|_->letgr=safe_refevdtinE.table:=ConstrMap.addgr(OtherTermt,E.castelt)!E.tableletregister_constrenvevdc=letc=EConstr.of_constrcinlett=get_type_ofenvevdcinmatchEConstr.kindevdtwith|App(intyp,args)whenEConstr.isRefXenvevd(Lazy.forceE.gref)intyp->letstyp=args.(E.get_key)inletelt={decl=c;deriv=make_elt(evd,c)}inregister_hintevdstypelt|_->letenv=Global.env()inraise(CErrors.user_errPp.(str"Cannot register "++pr_constrenvevdc++str". It has type "++pr_constrenvevdt++str" instead of type "++Printer.pr_global(Lazy.forceE.gref)++str" X1 ... Xn"))letregister_obj:Libobject.locality*Constr.constr->Libobject.obj=letcache_constrc=letenv=Global.env()inletevd=Evd.from_envenvinregister_constrenvevdcinletsubst_constr(subst,c)=Mod_subst.subst_mpssubstcinLibobject.declare_object@@Libobject.object_with_locality("register-zify-"^E.name)~cache:cache_constr~subst:(Somesubst_constr)~discharge:(fun_->assertfalse)(** [register c] is called from the VERNACULAR ADD [name] reference(t).
The term [c] is interpreted and
registered as a [superglobal_object_nodischarge].
TODO: pre-compute [get_type_of] - [cache_constr] is using another environment.
*)letregisterlocalc=tryletc=UnivGen.constr_of_monomorphic_global(Global.env())(Nametab.locatec)inlet_=Lib.add_leaf(register_obj(local,c))in()withNot_found->raise(CErrors.user_errPp.(Libnames.pr_qualidc++str" does not exist."))letpp_keys()=letenv=Global.env()inletevd=Evd.from_envenvinConstrMap.fold(fun_(k,d)acc->matchE.destdwith|None->acc|Some_->Pp.(pr_constrenvevd(constr_of_term_kindk)++str" "++acc))!E.table(Pp.str"")letprint()=Feedback.msg_info(pp_keys())endmoduleInjTable=MakeTable(EInj)moduleESat=structtypeelt=ESatT.topenESatTletname="Saturate"letgref=rocq_Saturatelettable=saturateletcastx=Saturatexletdest=functionSaturatex->Somex|_->Noneletmk_eltevdia={parg1=a.(2);parg2=a.(3);satOK=a.(5)}letget_key=1endmoduleEUnopSpec=structopenESpecTtypeelt=ESpecT.tletname="UnopSpec"letgref=rocq_UnOpSpeclettable=specsletcastx=UnOpSpecxletdest=functionUnOpSpecx->Somex|_->Noneletmk_eltevdia={spec=a.(4)}letget_key=2endmoduleEBinOpSpec=structopenESpecTtypeelt=ESpecT.tletname="BinOpSpec"letgref=rocq_BinOpSpeclettable=specsletcastx=BinOpSpecxletdest=functionBinOpSpecx->Somex|_->Noneletmk_eltevdia={spec=a.(5)}letget_key=3endmoduleBinOp=MakeTable(EBinOp)moduleUnOp=MakeTable(EUnOp)moduleCstOp=MakeTable(ECstOp)moduleBinRel=MakeTable(EBinRel)modulePropBinOp=MakeTable(EPropBinOp)modulePropUnOp=MakeTable(EPropUnOp)moduleSaturate=MakeTable(ESat)moduleUnOpSpec=MakeTable(EUnopSpec)moduleBinOpSpec=MakeTable(EBinOpSpec)letinit_cache()=table_cache:=!table;saturate_cache:=!saturate;specs_cache:=!specsopenEInjT(** Get constr of lemma and projections in ZifyClasses. *)(** Module [CstrTable] records terms [x] injected into [inj x]
together with the corresponding type constraint.
The terms are stored by side-effect during the traversal
of the goal. It must therefore be cleared before calling
the main tactic.
*)moduleCstrTable=structmoduleHConstr=Hashtbl.Make(structtypet=EConstr.tlethashc=Constr.hash(unsafe_to_constrc)letequalcc'=Constr.equal(unsafe_to_constrc)(unsafe_to_constrc')end)lettable:EConstr.tHConstr.t=HConstr.create10letregisterevdt(i:EConstr.t)=HConstr.addtabletiletget()=letl=HConstr.fold(funkiacc->(k,i)::acc)table[]inHConstr.cleartable;l(** [gen_cstr table] asserts (cstr k) for each element of the table (k,cstr).
NB: the constraint is only asserted if it does not already exist in the context.
*)letgen_cstrtable=Proofview.Goal.enter(fungl->letenv=Proofview.Goal.envglinletevd=Proofview.Goal.sigmaglin(* Build the table of existing hypotheses *)lethas_hyp=lethyps_table=HConstr.create20inlet()=List.iter(fundecl->HConstr.addhyps_table(NamedDecl.get_typedecl)())(EConstr.named_contextenv)infunc->letm=HConstr.memhyps_tablecinifnotmthenHConstr.addhyps_tablec();min(* Add the constraint (cstr k) if it is not already present *)letgenkcstr=Proofview.Goal.enter(fungl->letenv=Proofview.Goal.envglinletterm=EConstr.mkApp(cstr,[|k|])inlettypes=get_type_ofenvevdterminifhas_hyptypesthenTacticals.tclIDTACelseletn=Tactics.fresh_id_in_envId.Set.empty(Names.Id.of_string"cstr")envinTactics.pose_proof(Names.Namen)term)inList.fold_left(funacc(k,i)->Tacticals.tclTHEN(genki)acc)Tacticals.tclIDTACtable)endtypeprf=|Term(* source is built from constructors.
target = compute(inj source)
inj source == target *)|Same(* target = source
inj source == inj target *)|ConvofEConstr.t(* inj source == target *)|PrfofEConstr.t*EConstr.t(** [eq_proof typ source target] returns (target = target : source = target) *)leteq_prooftypsourcetarget=EConstr.mkCast(EConstr.mkApp(forceeq_refl,[|typ;target|]),DEFAULTcast,EConstr.mkApp(forceeq,[|typ;source;target|]))letinterp_prfevdinjsourceprf=letinj_source=ifinj.EInjT.isidthensourceelseEConstr.mkApp(inj.EInjT.inj,[|source|])inmatchprfwith|Term->lettarget=Tacred.compute(Global.env())evdinj_sourcein(target,EConstr.mkApp(forceeq_refl,[|inj.target;target|]))|Same->(inj_source,EConstr.mkApp(forceeq_refl,[|inj.target;inj_source|]))|Convtrm->(trm,eq_proofinj.targetinj_sourcetrm)|Prf(target,prf)->(target,prf)letpp_prfprf=matchprfwith|Term->Pp.str"Term"|Same->Pp.str"Same"|Convt->Pp.(str"Conv "++gl_pr_constrt)|Prf(_,_)->Pp.str"Prf "letinterp_prfevdinjsourceprf=lett,prf'=interp_prfevdinjsourceprfindebug_zify(fun()->Pp.(str"interp_prf "++gl_pr_constrinj.EInjT.inj++str" "++gl_pr_constrsource++str" = "++gl_pr_constrt++str" by "++gl_pr_constrprf'++str" from "++pp_prfprf++fnl()));(t,prf')letmkvarevdinje=(matchinj.cstrwithNone->()|Somectr->CstrTable.registerevdectr);Sameletpp_prfevdinjsrcprf=lett,prf'=interp_prfevdinjsrcprfinPp.(gl_pr_constrinj.EInjT.inj++str" "++gl_pr_constrsrc++str" = "++gl_pr_constrt++str" by "++matchprfwith|Term->Pp.str"Term"|Same->Pp.str"Same"|Convt->Pp.str"Conv"|Prf(_,p)->Pp.str"Prf "++gl_pr_constrp)letconv_of_termevdopisidarg=Tacred.compute(Global.env())evd(ifisidthenargelseEConstr.mkApp(op,[|arg|]))letapp_unopenvevdsrcunopargprf=letcunop=unop.EUnOpT.classify_unopinletdefaulta'prf'=lettarget=EConstr.mkApp(unop.EUnOpT.tuop,[|a'|])inletevd,h=Typing.checked_appvectenvevd(forcemkapp)[|unop.source1;unop.source2;unop.target1;unop.target2|]inevd,EUnOpT.(Prf(target,EConstr.mkApp(h,[|unop.uop;unop.inj1_t.EInjT.inj;unop.inj2_t.EInjT.inj;unop.tuop;unop.tuopinj;arg;a';prf'|])))inmatchprfwith|Term->(ifunop.EUnOpT.is_constructthenevd,Term(* Keep rebuilding *)elsematchcunopwith|OpInj->evd,Conv(conv_of_termevdunop.EUnOpT.uopfalsearg)|OpSame->evd,Same|_->leta',prf=interp_prfevdunop.EUnOpT.inj1_targprfindefaulta'prf)|Same->(matchcunopwith|OpSame->evd,Same|OpInj->evd,Same|OpConv->evd,Conv(EConstr.mkApp(unop.EUnOpT.tuop,[|EConstr.mkApp(unop.EUnOpT.inj1_t.EInjT.inj,[|arg|])|]))|OpOther->leta',prf'=interp_prfevdunop.EUnOpT.inj1_targprfindefaulta'prf')|Conva'->(matchcunopwith|OpSame|OpConv->evd,Conv(EConstr.mkApp(unop.EUnOpT.tuop,[|a'|]))|OpInj->evd,Conva'|_->leta',prf=interp_prfevdunop.EUnOpT.inj1_targprfindefaulta'prf)|Prf(a',prf')->defaulta'prf'letapp_unopenvevdsrcunopargprf=let(evd',r)asres=app_unopenvevdsrcunopargprfindebug_zify(fun()->Pp.(str"\napp_unop "++pp_prfevdunop.EUnOpT.inj1_targprf++str" => "++pp_prfevd'unop.EUnOpT.inj2_tsrcr));resletapp_binopenvevdsrcbinoparg1prf1arg2prf2=EBinOpT.(letmkAppa1a2=EConstr.mkApp(binop.tbop,[|a1;a2|])inletto_convinjarg=function|Term->conv_of_termevdinj.EInjT.injinj.EInjT.isidarg|Same->ifinj.EInjT.isidthenargelseEConstr.mkApp(inj.EInjT.inj,[|arg|])|Convt->t|Prf_->failwith"Prf is not convertible"inletdefaulta1prf1a2prf2=letres=mkAppa1a2inletevd,head=Typing.checked_appvectenvevd(forcemkapp2)[|binop.source1;binop.source2;binop.source3;binop.target1;binop.target2;binop.target3|]inletprf=EBinOpT.(EConstr.mkApp(head,[|binop.bop;binop.inj1.EInjT.inj;binop.inj2.EInjT.inj;binop.inj3.EInjT.inj;binop.tbop;binop.tbopinj;arg1;a1;prf1;arg2;a2;prf2|]))inevd,Prf(res,prf)inmatch(binop.EBinOpT.classify_binop,prf1,prf2)with|OpSame,Same,Same->evd,Same|OpSame,Term,Same|OpSame,Same,Term->evd,Same|OpSame,(Term|Same|Conv_),(Term|Same|Conv_)->lett1=to_convbinop.EBinOpT.inj1arg1prf1inlett2=to_convbinop.EBinOpT.inj1arg2prf2inevd,Conv(mkAppt1t2)|_,_,_->leta1,prf1=interp_prfevdbinop.inj1arg1prf1inleta2,prf2=interp_prfevdbinop.inj2arg2prf2indefaulta1prf1a2prf2)typetyped_constr={constr:EConstr.t;typ:EConstr.t;inj:EInjT.t}(* [arrow] is the term (fun (x:Prop) (y : Prop) => x -> y) *)letarrow=letnamex=Context.make_annot(Name.mk_name(Names.Id.of_stringx))ERelevance.relevantinEConstr.mkLambda(name"x",EConstr.mkProp,EConstr.mkLambda(name"y",EConstr.mkProp,EConstr.mkProd(Context.make_annotNames.AnonymousERelevance.relevant,EConstr.mkRel2,EConstr.mkRel2)))letis_propenvsigmaterm=letsort=Retyping.get_sort_ofenvsigmaterminEConstr.ESorts.is_propsigmasortletis_arrowenvevdap1p2=is_propenvevdp1&&is_prop(EConstr.push_rel(Context.Rel.Declaration.LocalAssum(a,p1))env)evdp2&&(a.Context.binder_name=Names.Anonymous||EConstr.Vars.noccurnevd1p2)(** [get_operator env evd e] expresses [e] as an application (c a)
where c is the head symbol and [a] is the array of arguments.
The function also transforms (x -> y) as (arrow x y) *)letget_operatorbarrowenvevde=lete'=EConstr.whd_evarevdeinmatchEConstr.kindevde'with|Prod(a,p1,p2)->ifbarrow&&is_arrowenvevdap1p2then(arrow,[|p1;p2|],false)elseraiseNot_found|App(c,a)->(letc'=EConstr.whd_evarevdcinmatchEConstr.kindevdc'with|Construct_(* e.g. Z0 , Z.pos *)|Const_(* e.g. Z.max *)|Proj_|Lambda_(* e.g projections *)|Ind_(* e.g. eq *)->(c',a,false)|_->raiseNot_found)|Const_->(e',[||],false)|Construct_->(e',[||],true)|Int_|Float_->(e',[||],true)|_->raiseNot_foundletdecompose_appenvevde=matchEConstr.kindevdewith|Prod(a,p1,p2)whenis_arrowenvevdap1p2->(arrow,[|p1;p2|])|App(c,a)->(c,a)|_->(EConstr.whd_evarevde,[||])type'oppropop={op:'op;op_constr:EConstr.t;op_iff:EConstr.t}letmk_propopopc1c2={op;op_constr=c1;op_iff=c2}typeprop_binop=AND|OR|IFF|IMPLtypeprop_unop=NOTtypeprop_op=|BINOPofprop_binoppropop*EConstr.t*EConstr.t|UNOPofprop_unoppropop*EConstr.t|OTHEROPofEConstr.t*EConstr.tarrayletclassify_propenvevde=matchEConstr.kindevdewith|Prod(a,p1,p2)whenis_arrowenvevdap1p2->BINOP(mk_propopIMPLarrow(forceop_impl_morph),p1,p2)|App(c,a)->(matchArray.lengthawith|1->ifEConstr.eq_constr_nounivsevd(forceop_not)cthenUNOP(mk_propopNOTc(forceop_not_morph),a.(0))elseOTHEROP(c,a)|2->ifEConstr.eq_constr_nounivsevd(forceop_and)cthenBINOP(mk_propopANDc(forceop_and_morph),a.(0),a.(1))elseifEConstr.eq_constr_nounivsevd(forceop_or)cthenBINOP(mk_propopORc(forceop_or_morph),a.(0),a.(1))elseifEConstr.eq_constr_nounivsevd(forceop_iff)cthenBINOP(mk_propopIFFc(forceop_iff_morph),a.(0),a.(1))elseOTHEROP(c,a)|_->OTHEROP(c,a))|_->OTHEROP(e,[||])letcheck_target_injevdinjd=matchinj,target_injdwith|None,_->true|Some_,None->false|Somei1,Somei2->EInjT.eq_injevdi1i2(** [match_operator env evd hd arg inj (t,d)]
- hd is head operator of t
- If t = OtherTerm _, then t = hd
- If t = Application _, then
we extract the relevant number of arguments from arg
and check for convertibility *)letmatch_operatorenvevdhdargsinj(t,d)=letdecompti=letn=Array.lengthargsinlett'=EConstr.mkApp(hd,Array.subargs0(n-i))inifis_convertibleenvevdt'tthenSome(d,t)elseNoneinifcheck_target_injevdinjdthenmatchtwith|OtherTermt->Some(d,t)|Applicationt->(matchdwith|CstOp_->decompt0|UnOp_->decompt1|BinOp_->decompt2|BinRel_->decompt2|PropOp_->decompt2|PropUnOp_->decompt1|_->None)elseNoneletpp_trans_exprenvevderes=debug_zify(fun()->Pp.(str"\ntrans_expr "++pp_prfevde.inje.constrres));resletrectrans_exprenvevde=letinj=e.injinlete=e.constrintryletc,a,is_constant=get_operatorfalseenvevdeinifis_constantthenevd,Termelseletk,t=find_option(match_operatorenvevdca(Someinj))(ConstrMap.find_allevdc!table_cache)inletn=Array.lengthainmatchkwith|CstOp{deriv=c'}->ECstOpT.(ifc'.is_constructthenevd,Termelseevd,Prf(c'.cst,c'.cstinj))|UnOp{deriv=unop}->letevd,prf=trans_exprenvevd{constr=a.(n-1);typ=unop.EUnOpT.source1;inj=unop.EUnOpT.inj1_t}inapp_unopenvevdeunopa.(n-1)prf|BinOp{deriv=binop}->letevd,prf1=trans_exprenvevd{constr=a.(n-2);typ=binop.EBinOpT.source1;inj=binop.EBinOpT.inj1}inletevd,prf2=trans_exprenvevd{constr=a.(n-1);typ=binop.EBinOpT.source2;inj=binop.EBinOpT.inj2}inapp_binopenvevdebinopa.(n-2)prf1a.(n-1)prf2|d->evd,mkvarevdinjewithNot_found|DestKO->evd,mkvarevdinjelettrans_exprenvevde=tryletevd,prf=trans_exprenvevdeinevd,pp_trans_exprenvevdeprfwithNot_found->raise(CErrors.user_err(Pp.str"Missing injection for type "++Printer.pr_leconstr_envenvevde.typ))typeprfp=|TProofofEConstr.t*EConstr.t(** Proof of tranformed proposition *)|CProofofEConstr.t(** Transformed proposition is convertible *)|IProof(** Transformed proposition is identical *)letpp_prfp=function|TProof(t,prf)->Pp.str"TProof "++gl_pr_constrt++Pp.str" by "++gl_pr_constrprf|CProoft->Pp.str"CProof "++gl_pr_constrt|IProof->Pp.str"IProof"lettrans_binrelenvevdsrcropa1prf1a2prf2=EBinRelT.(match(rop.classify_rel,prf1,prf2)with|OpSame,Same,Same->evd,IProof|(OpSame|OpConv),Convt1,Convt2->evd,CProof(EConstr.mkApp(rop.tbrel,[|t1;t2|]))|(OpSame|OpConv),(Same|Term|Conv_),(Same|Term|Conv_)->leta1',_=interp_prfevdrop.inja1prf1inleta2',_=interp_prfevdrop.inja2prf2inevd,CProof(EConstr.mkApp(rop.tbrel,[|a1';a2'|]))|_,_,_->leta1',prf1=interp_prfevdrop.inja1prf1inleta2',prf2=interp_prfevdrop.inja2prf2in(* XXX do we need to check more of this application or check other applications?
This one found necessary in #16803 *)letevd,h=Typing.checked_appvectenvevd(forcemkrel)[|rop.source;rop.target|]inevd,TProof(EConstr.mkApp(rop.EBinRelT.tbrel,[|a1';a2'|]),EConstr.mkApp(h,[|rop.brel;rop.EBinRelT.inj.EInjT.inj;rop.EBinRelT.tbrel;rop.EBinRelT.brelinj;a1;a1';prf1;a2;a2';prf2|])))lettrans_binrelenvevdsrcropa1prf1a2prf2=letevd,res=trans_binrelenvevdsrcropa1prf1a2prf2indebug_zify(fun()->Pp.(str"\ntrans_binrel "++pp_prfpres));evd,resletmkprftp=EConstr.(matchpwith|IProof->(t,mkApp(forceiff_refl,[|t|]))|CProoft'->(t',mkApp(forceeq_iff,[|t;t';eq_proofmkProptt'|]))|TProof(t',p)->(t',p))letmkprftp=lett',p=mkprftpindebug_zify(fun()->Pp.(str"mkprf "++gl_pr_constrt++str" <-> "++gl_pr_constrt'++str" by "++gl_pr_constrp));(t',p)lettrans_bin_propop_constrop_ifft1p1t2p2=match(p1,p2)with|IProof,IProof->IProof|CProoft1',IProof->CProof(EConstr.mkApp(op_constr,[|t1';t2|]))|IProof,CProoft2'->CProof(EConstr.mkApp(op_constr,[|t1;t2'|]))|CProoft1',CProoft2'->CProof(EConstr.mkApp(op_constr,[|t1';t2'|]))|_,_->lett1',p1=mkprft1p1inlett2',p2=mkprft2p2inTProof(EConstr.mkApp(op_constr,[|t1';t2'|]),EConstr.mkApp(op_iff,[|t1;t2;t1';t2';p1;p2|]))lettrans_bin_propop_constrop_ifft1p1t2p2=letprf=trans_bin_propop_constrop_ifft1p1t2p2indebug_zify(fun()->pp_prfpprf);prflettrans_un_propop_constrop_iffp1prf1=matchprf1with|IProof->IProof|CProofp1'->CProof(EConstr.mkApp(op_constr,[|p1'|]))|TProof(p1',prf)->TProof(EConstr.mkApp(op_constr,[|p1'|]),EConstr.mkApp(op_iff,[|p1;p1';prf|]))letrectrans_propenvevde=matchclassify_propenvevdewith|BINOP({op_constr;op_iff},p1,p2)->letevd,prf1=trans_propenvevdp1inletevd,prf2=trans_propenvevdp2inevd,trans_bin_propop_constrop_iffp1prf1p2prf2|UNOP({op_constr;op_iff},p1)->letevd,prf1=trans_propenvevdp1inevd,trans_un_propop_constrop_iffp1prf1|OTHEROP(c,a)->(tryletk,t=find_option(match_operatorenvevdcaNone)(ConstrMap.find_allevdc!table_cache)inletn=Array.lengthainmatchkwith|BinRel{decl=br;deriv=rop}->letevd,a1=trans_exprenvevd{constr=a.(n-2);typ=rop.EBinRelT.source;inj=rop.EBinRelT.inj}inletevd,a2=trans_exprenvevd{constr=a.(n-1);typ=rop.EBinRelT.source;inj=rop.EBinRelT.inj}intrans_binrelenvevderopa.(n-2)a1a.(n-1)a2|_->evd,IProofwithNot_found|DestKO->evd,IProof)lettrans_check_propenvevdt=ifis_propenvevdtthenletevd,p=trans_propenvevdtinevd,Somepelseevd,Noneletget_hyp_typ=function|NamedDecl.LocalDef(h,_,ty)|NamedDecl.LocalAssum(h,ty)->(h.Context.binder_name,EConstr.of_constrty)lettrans_hypsenvevdl=List.fold_left(fun(evd,acc)decl->leth,ty=get_hyp_typdeclinmatchtrans_check_propenvevdtywith|evd,None->evd,acc|evd,Somep'->evd,(h,ty,p')::acc)(evd,[])llettrans_hypht0prfp=debug_zify(fun()->Pp.(str"trans_hyp: "++pp_prfpprfp++fnl()));matchprfpwith|IProof->Tacticals.tclIDTAC(* Should detect before *)|CProoft'->Proofview.Goal.enter(fungl->letenv=Proofview.Goal.envglinletevd=Proofview.Goal.sigmaglinlett'=Reductionops.nf_betaiotaenvevdt'inTactics.change_in_hyp~check:trueNone(Tactics.make_change_argt')(h,Locus.InHypTypeOnly))|TProof(t',prf)->Tacticals.(Proofview.Goal.enter(fungl->letenv=Proofview.Goal.envglinletevd=Proofview.Goal.sigmaglinlettarget=Reductionops.nf_betaiotaenvevdt'inleth'=Tactics.fresh_id_in_envId.Set.emptyhenvinletprf=EConstr.mkApp(forcerew_iff,[|t0;target;prf;EConstr.mkVarh|])intclTHEN(Tactics.pose_proof(Name.Nameh')prf)(tclTRY(tclTHEN(Tactics.clear[h])(Tactics.rename_hyp[(h',h)])))))lettrans_conclprfp=debug_zify(fun()->Pp.(str"trans_concl: "++pp_prfpprfp++fnl()));matchprfpwith|IProof->Tacticals.tclIDTAC|CProoft->Proofview.Goal.enter(fungl->letenv=Proofview.Goal.envglinletevd=Proofview.Goal.sigmaglinlett'=Reductionops.nf_betaiotaenvevdtinTactics.change_conclt')|TProof(t,prf)->Proofview.Goal.enter(fungl->letenv=Proofview.Goal.envglinletevd=Proofview.Goal.sigmaglinlettyp=get_type_ofenvevdprfinmatchEConstr.kindevdtypwith|App(c,a)whenArray.lengtha=2->Tactics.apply(EConstr.mkApp(Lazy.forcerew_iff_rev,[|a.(0);a.(1);prf|]))|_->raise(CErrors.anomalyPp.(str"zify cannot transform conclusion")))lettclTHENOptetactac'=matchewithNone->tac'|Somee'->Tacticals.tclTHEN(tace')tac'letelim_bindingxtty=Proofview.Goal.enter(fungl->letenv=Proofview.Goal.envglinleth=Tactics.fresh_id_in_envId.Set.empty(Nameops.add_prefix"heq_"x)envinTacticals.tclTHEN(Tactics.pose_proof(Nameh)(eq_proofty(EConstr.mkVarx)t))(Tacticals.tclTRY(Tactics.clear_body[x])))letdo_lettac(h:Constr.named_declaration)=matchhwith|Context.Named.Declaration.LocalAssum_->Tacticals.tclIDTAC|Context.Named.Declaration.LocalDef(id,t,ty)->Proofview.Goal.enter(fungl->letenv=Proofview.Goal.envglinletevd=Proofview.Goal.sigmaglintryletx=id.Context.binder_nameinignore(leteq=Lazy.forceeqinfind_option(match_operatorenvevdeq[|EConstr.of_constrty;EConstr.mkVarx;EConstr.of_constrt|]None)(ConstrMap.find_allevdeq!table_cache));tacx(EConstr.of_constrt)(EConstr.of_constrty)withNot_found->Tacticals.tclIDTAC)letiter_let_auxtac=Proofview.Goal.enter(fungl->letenv=Proofview.Goal.envglinletsign=Environ.named_contextenvininit_cache();Tacticals.tclMAP(do_lettac)sign)letiter_let(tac:Ltac_plugin.Tacinterp.Value.t)=iter_let_aux(fun(id:Names.Id.t)tty->Ltac_plugin.Tacinterp.Value.applytac[Ltac_plugin.Tacinterp.Value.of_constr(EConstr.mkVarid);Ltac_plugin.Tacinterp.Value.of_constrt;Ltac_plugin.Tacinterp.Value.of_constrty])letelim_let=iter_let_auxelim_bindingletzify_tac=Proofview.Goal.enter(fungl->Rocqlib.check_required_library["Stdlib";"micromega";"ZifyClasses"];Rocqlib.check_required_library["Stdlib";"micromega";"ZifyInst"];init_cache();letevd=Proofview.Goal.sigmaglinletenv=Proofview.Goal.envglinletsign=Environ.named_contextenvinletconcl=Proofview.Goal.conclglinletevd,concl=trans_check_propenvevdconclinletevd,hyps=trans_hypsenvevdsigninletl=CstrTable.get()inProofview.tclTHEN(Proofview.Unsafe.tclEVARSevd)(tclTHENOptconcltrans_concl(Tacticals.tclTHEN(Tacticals.tclTHENLIST(List.rev_map(fun(h,p,t)->trans_hyphpt)hyps))(CstrTable.gen_cstrl))))typepscript=SetofNames.Id.t*EConstr.t|PoseofNames.Id.t*EConstr.ttypespec_env={map:Names.Id.tHConstr.t;spec_name:Names.Id.t;term_name:Names.Id.t;fresh:Nameops.Subscript.t;proofs:pscriptlist}letregister_constr{map;spec_name;term_name;fresh;proofs}cthm=lettname=Nameops.add_subscriptterm_namefreshinletsname=Nameops.add_subscriptspec_namefreshin(EConstr.mkVartname,{map=HConstr.addctnamemap;spec_name;term_name;fresh=Nameops.Subscript.succfresh;proofs=Set(tname,c)::Pose(sname,thm)::proofs})letfresh_subscriptenv=letctx=(Environ.named_context_valenv).Environ.env_named_mapinNameops.Subscript.succ(Names.Id.Map.fold(funid_s->let_,s'=Nameops.get_subscriptidinletcmp=Nameops.Subscript.comparess'inifcmp=0thenselseifcmp<0thens'elses)ctxNameops.Subscript.zero)letinit_envsnametnames={map=HConstr.empty;spec_name=sname;term_name=tname;fresh=s;proofs=[]}letrecspec_of_termenvevd(senv:spec_env)t=letget_nametenv=tryEConstr.mkVar(HConstr.findtsenv.map)withNot_found->tinletc,a=decompose_appenvevdtinifa=[||]then(* The term cannot be decomposed. *)(get_nametsenv,senv)else(* recursively analyse the sub-terms *)leta',senv'=Array.fold_right(fune(l,senv)->letr,senv=spec_of_termenvevdsenvein(r::l,senv))a([],senv)inleta'=Array.of_lista'inlett'=EConstr.mkApp(c,a')intry(EConstr.mkVar(HConstr.findt'senv'.map),senv')withNot_found->(trymatchsnd(ConstrMap.findevdc!specs_cache)with|UnOpSpecs|BinOpSpecs->letthm=EConstr.mkApp(s.deriv.ESpecT.spec,a')inregister_constrsenv't'thm|_->(get_namet'senv',senv')withNot_found|DestKO->(t',senv'))letinterp_pscripts=matchswith|Set(id,c)->Tacticals.tclTHEN(Tactics.letin_tacNone(Names.Nameid)cNone{Locus.onhyps=None;Locus.concl_occs=Locus.AllOccurrences})(Tacticals.tclTRY(Tactics.clear_body[id]))|Pose(id,c)->Tactics.pose_proof(Names.Nameid)cletrecinterp_pscriptsl=matchlwith|[]->Tacticals.tclIDTAC|s::l->Tacticals.tclTHEN(interp_pscripts)(interp_pscriptsl)letspec_of_hyps=Proofview.Goal.enter(fungl->letenv=Proofview.Goal.envglinletconcl=Proofview.Goal.conclglinletevd=Proofview.Goal.sigmaglinletterms=concl::List.mapNamedDecl.get_type(EConstr.named_contextenv)inlets=fresh_subscriptenvinletenv=List.fold_left(funacct->snd(spec_of_termenvevdacct))(init_env(Names.Id.of_string"H")(Names.Id.of_string"z")s)termsininterp_pscripts(List.revenv.proofs))letiter_specs=spec_of_hypsletfind_hypevdtl=trySome(EConstr.mkVar(fst(List.find(fun(h,t')->EConstr.eq_constrevdtt')l)))withNot_found->Noneletfind_proofevdtl=ifEConstr.eq_constrevdt(Lazy.forceop_True)thenSome(Lazy.forceop_I)elseletl=List.map(fundecl->NamedDecl.get_iddecl,NamedDecl.get_typedecl)linfind_hypevdtl(** [sat_constr env evd sub taclist hyps c d]= (sub',taclist',hyps') where
- sub' is a fresh subscript obtained from sub
- taclist' is obtained from taclist by posing the lemma 'd' applied to 'c'
- hyps' is obtained from hyps'
taclist and hyps are threaded to avoid adding duplicates
*)letsat_constrenvevdhyps(sub,taclist,prfs)cd=matchEConstr.kindevdcwith|App(c,args)->ifArray.lengthargs=2thenleth1=Tacred.cbv_betaenvevd(EConstr.mkApp(d.ESatT.parg1,[|args.(0)|]))inleth2=Tacred.cbv_betaenvevd(EConstr.mkApp(d.ESatT.parg2,[|args.(1)|]))inletn=Nameops.add_subscript(Names.Id.of_string"__sat")subinlettrm=match(find_proofevdh1hyps,find_proofevdh2hyps)with|Someh1,Someh2->(EConstr.mkApp(d.ESatT.satOK,[|args.(0);args.(1);h1;h2|]))|Someh1,_->EConstr.mkApp(d.ESatT.satOK,[|args.(0);args.(1);h1|])|_,_->EConstr.mkApp(d.ESatT.satOK,[|args.(0);args.(1)|])inletrtrm=Tacred.cbv_betaenvevdtrminlettyp=Retyping.get_type_ofenvevdrtrminmatchfind_hypevdtypprfswith|None->(Nameops.Subscript.succsub,(Tactics.pose_proof(Names.Namen)rtrm::taclist),(n,typ)::prfs)|Some_->(sub,taclist,prfs)else(sub,taclist,prfs)|_->(sub,taclist,prfs)letget_all_satenvevdc=List.fold_left(funacce->matchewith_,Saturates->s::acc|_->acc)[](tryConstrMap.find_allevdc!saturate_cachewithDestKO|Not_found->[])letsaturate=Proofview.Goal.enter(fungl->init_cache();lettable=CstrTable.HConstr.create20inletconcl=Proofview.Goal.conclglinletenv=Proofview.Goal.envglinlethyps=EConstr.named_contextenvinletevd=Proofview.Goal.sigmaglinletrecsatt=matchEConstr.kindevdtwith|App(c,args)->satc;Array.itersatargs;ifArray.lengthargs=2thenletds=get_all_satenvevdcinifds=[]||CstrTable.HConstr.memtabletthen()elseList.iter(funx->CstrTable.HConstr.addtabletx.deriv)dselse()|Prod(a,t1,t2)whena.Context.binder_name=Names.Anonymous->satt1;satt2|_->()in(* Collect all the potential saturation lemma *)satconcl;let()=List.iter(fundecl->sat(NamedDecl.get_typedecl))hypsinlets0=fresh_subscriptenvinlet(_,tacs,_)=CstrTable.HConstr.fold(funcdacc->sat_constrenvevdhypsacccd)table(s0,[],[])inTacticals.tclTHENLISTtacs)