123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981(************************************************************************)(* * 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) *)(************************************************************************)moduleCVars=VarsopenLtac_pluginopenPpopenUtilopenNamesopenConstropenEConstropenVarsopenEnvironopenGlob_termopenLocusopenTacexpropenRocqlibopenMod_substopenTacinterpopenLibobjectopenPrinteropenDeclareopenRing_astopenProofview.Notationsleterrormsg=CErrors.user_errPp.(strmsg)(****************************************************************************)(* controlled reduction *)typeprotect_flag=Eval|Prot|Rectype'areduction=Full|Argof'atypeprotection={with_eq:bool;arguments:((unit->GlobRef.t)*(int->protect_flag)reduction)list;}typerprotection={r_with_eq:bool;r_arguments:(GlobRef.t*(int->protect_flag)reduction)list;}letinterp_mapenvsigmalc=matchEConstr.destRefsigmacwith|exceptionDestKO->None|(t,_)->leteqg1g2=QGlobRef.equalenvg1g2inmatchList.assoc_feqtl.r_argumentswith|exceptionNot_found->None|Full->SomeFull|Argf->Some(Argf)letfresh_rel(n,data)c=letn=n+1in(n,c::data),mkRelnletrecmk_clos_butenvsigmaf_mapaccut=let(f,args)=EConstr.decompose_appsigmatinmatchinterp_mapenvsigmaf_mapfwith|SomeFull->(accu,t)|Some(Argtag)->letfoldiaccut=tag_argenvsigmaf_mapaccu(tagi)tinifArray.is_emptyargsthen(accu,t)elselet(accu,args)=Array.fold_left_map_ifoldaccuargsinaccu,mkApp(f,args)|None->fresh_relaccutandtag_argenvsigmaf_mapaccutagc=matchtagwith|Eval->accu,c|Prot->fresh_relaccuc|Rec->mk_clos_butenvsigmaf_mapaccucletprotect_maps:protectionString.Map.tref=refString.Map.emptyletadd_mapsm=protect_maps:=String.Map.addsm!protect_mapsletdest_relsigmat=matchEConstr.kindsigmatwith|App(f,args)whenArray.lengthargs>=2->letrel=mkApp(f,Array.subargs0(Array.lengthargs-2))inifclosed0sigmarelthen(rel,args.(Array.lengthargs-2),args.(Array.lengthargs-1))elseerror"ring: cannot find relation (not closed)"|_->error"ring: cannot find relation"letlookup_mapmap=letmap=matchString.Map.find_optmap!protect_mapswith|Somemap->map|None->CErrors.user_err(str"Map "++qsmap++str"not found.")inletr_arguments=List.map(fun(c,map)->(c(),map))map.argumentsinletr_with_eq=map.with_eqin{r_with_eq;r_arguments}letprotect_redmapenvsigmac=letmap=lookup_mapmapinletrecevalnc=matchEConstr.kindsigmacwith|Prod(na,t,u)->EConstr.mkProd(na,evalnt,eval(n+1)u)|_->letrels=List.initn(funi->mkRel(n-i))inletnormc=let(_,subterms),c=mk_clos_butenvsigmamap(n,rels)cinletc=Reductionops.clos_norm_flagsRedFlags.allenvsigmacinletsubst=List.revsubtermsinEConstr.Vars.substlsubstcinifmap.r_with_eqthenlet(rel,a1,a2)=dest_relsigmacinmkApp(rel,[|norma1;norma2|])elsenormcineval0cletprotect_tacmap=Tactics.reduct_option~check:false(protect_redmap,DEFAULTcast)Noneletprotect_tac_inmapid=Tactics.reduct_option~check:false(protect_redmap,DEFAULTcast)(Some(id,Locus.InHyp))(****************************************************************************)letrecclosed_undersigmacsett=trylet(gr,_)=destRefsigmatinGlobRef.Set_env.memgrcsetwithDestKO->matchEConstr.kindsigmatwith|Cast(c,_,_)->closed_undersigmacsetc|App(f,l)->closed_undersigmacsetf&&Array.for_all(closed_undersigmacset)l|_->falseletclosed_termargs_=matchargswith|[t;l]->lett=Option.get(Value.to_constrt)inletl=List.map(func->Value.cast(Genarg.topwitStdarg.wit_ref)c)(Option.get(Value.to_listl))inProofview.tclEVARMAP>>=funsigma->letcs=List.fold_rightGlobRef.Set_env.addlGlobRef.Set_env.emptyinifclosed_undersigmacstthenProofview.tclUNIT()elseTacticals.tclFAIL(mt())|_->assertfalseletclosed_term_ast=lettacname={mltac_plugin="rocq-runtime.plugins.ring";mltac_tactic="closed_term";}inlet()=Tacenv.register_ml_tactictacname[|closed_term|]inlettacname={mltac_name=tacname;mltac_index=0;}infunl->letl=List.map(fungr->ArgArg(Loc.taggr))linCAst.make(TacFun([Name(Id.of_string"t")],CAst.make(TacML(tacname,[TacGeneric(None,Genarg.in_gen(Genarg.glbwitStdarg.wit_constr)(DAst.make@@GVar(Id.of_string"t"),None));TacGeneric(None,Genarg.in_gen(Genarg.glbwit(Genarg.wit_listStdarg.wit_ref))l)]))))(*
let _ = add_tacdef false ((Loc.ghost,Id.of_string"ring_closed_term"
*)(****************************************************************************)leticenvsigmac=letc,uctx=Constrintern.interp_constrenvsigmacin(Evd.from_ctxuctx,c)letic_unsafeenvsigmac=(*FIXME remove *)fst(Constrintern.interp_constrenvsigmac)letdecl_constantnameunivsc=letopenConstrinletvars=CVars.universes_of_constrcinletunivs=UState.restrict_universe_contextunivsvarsinlet()=Global.push_context_setunivsinlettypes=(Typeops.infer(Global.env())c).uj_typeinletunivs=UState.Monomorphic_entryUniv.ContextSet.empty,UnivNames.empty_bindersin(* UnsafeMonomorphic: we always do poly:false *)UnsafeMonomorphic.mkConst(declare_constant~name~kind:Decls.(IsProofLemma)(DefinitionEntry(definition_entry~opaque:true~types~univsc)))letdecl_constantnasuffunivsc=letna=Namegen.next_global_ident_away(Global.safe_env())(Nameops.add_suffixnasuff)Id.Set.emptyindecl_constantnaunivsc(* Calling a global tactic *)letltac_calltac(args:glob_tactic_arglist)=CAst.make@@TacArg(TacCall(CAst.make(ArgArg(Loc.tag@@Lazy.forcetac),args)))letconstr_ofsigmav=matchValue.to_constrvwith|Somec->EConstr.to_constrsigmac|None->failwith"Ring.exec_tactic: anomaly"lettactic_res=ref[||]letget_res=letopenTacexprinletname={mltac_plugin="rocq-runtime.plugins.ring";mltac_tactic="get_res";}inletentry={mltac_name=name;mltac_index=0}inlettacargsist=letn=Tacinterp.Value.cast(Genarg.topwitStdarg.wit_int)(List.hdargs)inletiniti=Id.Map.find(Id.of_string("x"^string_of_inti))ist.lfunintactic_res:=Array.initninit;Proofview.tclUNIT()inTacenv.register_ml_tacticname[|tac|];entryletexec_tacticenvsigmanfargs=letfoldarg(i,vars,lfun)=letid=Id.of_string("x"^string_of_inti)inletx=Reference(ArgVarCAst.(makeid))in(succi,x::vars,Id.Map.addid(Value.of_constrarg)lfun)inlet(_,args,lfun)=List.fold_rightfoldargs(0,[],Id.Map.empty)inletist={(Tacinterp.default_ist())withTacinterp.lfun=lfun;}in(* Build the getter *)letlid=List.initn(funi->Id.of_string("x"^string_of_inti))inletn=Genarg.in_gen(Genarg.glbwitStdarg.wit_int)ninletget_res=CAst.make(TacML(get_res,[TacGeneric(None,n)]))inletgetter=Tacexp(CAst.make(TacFun(List.map(funn->Namen)lid,get_res)))in(* Evaluate the whole result *)let_,pv=Proofview.initsigma[env,EConstr.mkProp]inlettac=Tacinterp.eval_tactic_istist(ltac_callf(args@[getter]))inlet((),pv,_,_,_)=Proofview.apply~name:(Id.of_string"ring")~poly:false(Global.env())tacpvinletsigma=Evd.minimize_universes(Proofview.returnpv)inletnfc=constr_ofsigmacinArray.mapnf!tactic_res,Evd.universe_context_setsigmaletgen_constantn=();fun()->(EConstr.of_constr(UnivGen.constr_of_monomorphic_global(Global.env())(Rocqlib.lib_refn)))letgen_referencen=();fun()->(Rocqlib.lib_refn)letrocq_mk_Setoid=gen_constant"plugins.ring.Build_Setoid_Theory"letrocq_None=gen_reference"core.option.None"letrocq_Some=gen_reference"core.option.Some"letrocq_eq=gen_reference"core.eq.type"letrocq_cons=gen_reference"core.list.cons"letrocq_nil=gen_reference"core.list.nil"letlappfargs=mkApp(f(),args)letplappsigmafargs=letsigma,fc=Evd.fresh_global(Global.env())sigma(f())insigma,mkApp(fc,args)(****************************************************************************)(* Library linking *)letplugin_dir="setoid_ring"letcdir=["Stdlib";plugin_dir]letznew_ring_path=DirPath.make(List.mapId.of_string["InitialRing";plugin_dir;"Stdlib"])letzltacs=lazy(KerName.make(ModPath.MPfileznew_ring_path)(Label.makes))(* Ring theory *)(* almost_ring defs *)letrocq_almost_ring_theory=gen_reference"plugins.ring.almost_ring_theory"(* setoid and morphism utilities *)letrocq_eq_setoid=gen_reference"plugins.ring.Eqsth"letrocq_eq_morph=gen_reference"plugins.ring.Eq_ext"letrocq_eq_smorph=gen_reference"plugins.ring.Eq_s_ext"(* ring -> almost_ring utilities *)letrocq_ring_theory=gen_reference"plugins.ring.ring_theory"letrocq_mk_reqe=gen_constant"plugins.ring.mk_reqe"(* semi_ring -> almost_ring utilities *)letrocq_semi_ring_theory=gen_reference"plugins.ring.semi_ring_theory"letrocq_mk_seqe=gen_constant"plugins.ring.mk_seqe"letrocq_abstract=gen_constant"plugins.ring.Abstract"letrocq_comp=gen_constant"plugins.ring.Computational"letrocq_morph=gen_constant"plugins.ring.Morphism"(* power function *)letltac_inv_morph_nothing=zltac"inv_morph_nothing"(* hypothesis *)letrocq_mkhypo=gen_reference"plugins.ring.mkhypo"letrocq_hypo=gen_reference"plugins.ring.hypo"(* Equality: do not evaluate but make recursive call on both sides *)letmap_with_eqarg_map={with_eq=true;arguments=arg_map}letmap_without_eqarg_map={with_eq=false;arguments=arg_map}letbase_red=[rocq_cons,Arg(function2->Rec|_->Prot);rocq_nil,Arg(function_->Prot);gen_reference"plugins.ring.IDphi",Full;gen_reference"plugins.ring.gen_phiZ",Full;]letring_red=[(* Pphi_dev: evaluate polynomial and coef operations, protect
ring operations and make recursive call on the var map *)gen_reference"plugins.ring.Pphi_dev",Arg(function8|9|10|12|14->Eval|11|13->Rec|_->Prot);gen_reference"plugins.ring.Pphi_pow",Arg(function8|9|10|13|15|17->Eval|11|16->Rec|_->Prot);(* PEeval: evaluate polynomial, protect ring
operations and make recursive call on the var map *)gen_reference"plugins.ring.eval",Arg(function10|13->Eval|8|12->Rec|_->Prot)]let_=add_map"ring"(map_with_eq@@base_red@ring_red)(****************************************************************************)(* Ring database *)moduleCmap=Map.Make(Constr)letfrom_carrier=Summary.refCmap.empty~name:"ring-tac-carrier-table"letprint_rings()=Feedback.msg_notice(strbrk"The following ring structures have been declared:");Cmap.iter(fun_carrierring->letenv=Global.env()inletsigma=Evd.from_envenvinFeedback.msg_notice(hov2(Ppconstr.pr_idring.ring_name++spc()++str"with carrier "++pr_constr_envenvsigmaring.ring_carrier++spc()++str"and equivalence relation "++pr_constr_envenvsigmaring.ring_req)))!from_carrierletring_for_carrierr=Cmap.findr!from_carrierletfind_ring_structureenvsigmal=matchlwith|t::cl'->letty=Retyping.get_type_ofenvsigmatinletcheckc=letty'=Retyping.get_type_ofenvsigmacinifnot(Reductionops.is_convenvsigmatyty')thenCErrors.user_err(str"Arguments of ring_simplify do not have all the same type.")inList.itercheckcl';(tryring_for_carrier(EConstr.to_constr~abort_on_undefined_evars:falsesigmaty)withNot_found->CErrors.user_err(str"Cannot find a declared ring structure over"++spc()++str"\""++pr_econstr_envenvsigmaty++str"\"."))|[]->assertfalseletadd_entrye=from_carrier:=Cmap.adde.ring_carriere!from_carrierletsubst_th(subst,th)=letc'=subst_mpssubstth.ring_carrierinleteq'=subst_mpssubstth.ring_reqinletset'=subst_mpssubstth.ring_setoidinletext'=subst_mpssubstth.ring_extinletmorph'=subst_mpssubstth.ring_morphinletth'=subst_mpssubstth.ring_thinletthm1'=subst_mpssubstth.ring_lemma1inletthm2'=subst_mpssubstth.ring_lemma2inlettac'=Tacsubst.subst_tacticsubstth.ring_cst_tacinletpow_tac'=Tacsubst.subst_tacticsubstth.ring_pow_tacinletpretac'=Tacsubst.subst_tacticsubstth.ring_pre_tacinletposttac'=Tacsubst.subst_tacticsubstth.ring_post_tacinifc'==th.ring_carrier&&eq'==th.ring_req&&Constr.equalset'th.ring_setoid&&ext'==th.ring_ext&&morph'==th.ring_morph&&th'==th.ring_th&&thm1'==th.ring_lemma1&&thm2'==th.ring_lemma2&&tac'==th.ring_cst_tac&&pow_tac'==th.ring_pow_tac&&pretac'==th.ring_pre_tac&&posttac'==th.ring_post_tacthenthelse{ring_name=th.ring_name;ring_carrier=c';ring_req=eq';ring_setoid=set';ring_ext=ext';ring_morph=morph';ring_th=th';ring_cst_tac=tac';ring_pow_tac=pow_tac';ring_lemma1=thm1';ring_lemma2=thm2';ring_pre_tac=pretac';ring_post_tac=posttac'}lettheory_to_obj:ring_info->obj=declare_object@@global_object_nodischarge"tactic-new-ring-theory"~cache:add_entry~subst:(Somesubst_th)letsetoid_of_relationenvsigmaar=tryletsigma,refl=Rewrite.get_reflexive_proofenvsigmaarinletsigma,sym=Rewrite.get_symmetric_proofenvsigmaarinletsigma,trans=Rewrite.get_transitive_proofenvsigmaarinsigma,lapprocq_mk_Setoid[|a;r;refl;sym;trans|]withNot_found->CErrors.user_err(str"Cannot find a setoid structure for relation "++pr_econstr_envenvsigmar++str".")letop_morphraddmuloppreqm1m2m3=lapprocq_mk_reqe[|r;add;mul;opp;req;m1;m2;m3|]letop_smorphraddmulreqm1m2=lapprocq_mk_seqe[|r;add;mul;req;m1;m2|]letring_equalityenvsigma(r,add,mul,opp,req)=matchEConstr.kindsigmareqwith|App(f,[|_|])whenisRefXenvsigma(rocq_eq())f->letsigma,setoid=plappsigmarocq_eq_setoid[|r|]inletsigma,op_morph=matchoppwithSomeopp->plappsigmarocq_eq_morph[|r;add;mul;opp|]|None->plappsigmarocq_eq_smorph[|r;add;mul|]inletsigma,setoid=Typing.solve_evarsenvsigmasetoidinletsigma,op_morph=Typing.solve_evarsenvsigmaop_morphin(sigma,setoid,op_morph)|_->letsigma,setoid=setoid_of_relationenvsigmarreqinletsignature=[Some(r,Somereq);Some(r,Somereq)],Some(r,Somereq)inletsigma,add_m,add_m_lem=tryRewrite.Internal.default_morphismenvsigmasignatureaddwithNot_found->CErrors.user_err(str"Ring addition "++pr_econstr_envenvsigmaadd++str" should be declared as a morphism.")inletsigma,mul_m,mul_m_lem=tryRewrite.Internal.default_morphismenvsigmasignaturemulwithNot_found->CErrors.user_err(str"Ring multiplication "++pr_econstr_envenvsigmamul++str" should be declared as a morphism.")inletsigma,op_morph=matchoppwith|Someopp->(letsigma,opp_m,opp_m_lem=tryRewrite.Internal.default_morphismenvsigma([Some(r,Somereq)],Some(r,Somereq))oppwithNot_found->CErrors.user_err(str"Ring opposite "++pr_econstr_envenvsigmaopp++str" should be declared as a morphism.")inletop_morph=op_morphraddmuloppreqadd_m_lemmul_m_lemopp_m_leminFlags.if_verboseFeedback.msg_info(str"Using setoid \""++pr_econstr_envenvsigmareq++str"\""++spc()++str"and morphisms \""++pr_econstr_envenvsigmaadd_m++str"\","++spc()++str"\""++pr_econstr_envenvsigmamul_m++str"\""++spc()++str"and \""++pr_econstr_envenvsigmaopp_m++str"\"");sigma,op_morph)|None->(Flags.if_verboseFeedback.msg_info(str"Using setoid \""++pr_econstr_envenvsigmareq++str"\""++spc()++str"and morphisms \""++pr_econstr_envenvsigmaadd_m++str"\""++spc()++str"and \""++pr_econstr_envenvsigmamul_m++str"\"");sigma,op_smorphraddmulreqadd_m_lemmul_m_lem)in(sigma,setoid,op_morph)letbuild_setoid_paramsenvsigmaraddmuloppreqeqth=matcheqthwithSome(a,b)->sigma,a,b|None->ring_equalityenvsigma(r,add,mul,opp,req)letdest_ringenvsigmath_spec=letth_typ=Retyping.get_type_ofenvsigmath_specinmatchEConstr.kindsigmath_typwithApp(f,[|r;zero;one;add;mul;sub;opp;req|])whenisRefXenvsigma(rocq_almost_ring_theory())f->(None,r,zero,one,add,mul,Somesub,Someopp,req)|App(f,[|r;zero;one;add;mul;req|])whenisRefXenvsigma(rocq_semi_ring_theory())f->(Sometrue,r,zero,one,add,mul,None,None,req)|App(f,[|r;zero;one;add;mul;sub;opp;req|])whenisRefXenvsigma(rocq_ring_theory())f->(Somefalse,r,zero,one,add,mul,Somesub,Someopp,req)|_->error"bad ring structure"letreflect_coeffrkind=(* We build an ill-typed terms on purpose... *)matchrkindwithAbstract->rocq_abstract()|Computationalc->lapprocq_comp[|c|]|Morphismm->lapprocq_morph[|m|]letinterp_cst_tacenvsigmarkkind(zero,one,add,mul,opp)cst_tac=matchcst_tacwithSome(CstTact)->Tacintern.glob_tactict|Some(Closedlc)->closed_term_ast(List.mapSmartlocate.global_with_aliaslc)|None->lett=ArgArg(Loc.tag@@Lazy.forceltac_inv_morph_nothing)inCAst.make(TacArg(TacCall(CAst.make(t,[]))))letmake_hypenvsigmac=lett=Retyping.get_type_ofenvsigmacinplappsigmarocq_mkhypo[|t;c|]letmake_hyp_listenvsigmalH=letsigma,carrier=Evd.fresh_globalenvsigma(rocq_hypo())inletsigma,l=List.fold_right(func(sigma,l)->letsigma,c=make_hypenvsigmacinplappsigmarocq_cons[|carrier;c;l|])lH(plappsigmarocq_nil[|carrier|])inletsigma,l'=Typing.solve_evarsenvsigmalinsigma,l'letinterp_powerenvsigmapow=letsigma,carrier=Evd.fresh_globalenvsigma(rocq_hypo())inmatchpowwith|None->lett=ArgArg(Loc.tag(Lazy.forceltac_inv_morph_nothing))inletsigma,c=plappsigmarocq_None[|carrier|]insigma,(CAst.make(TacArg(TacCall(CAst.make(t,[])))),c)|Some(tac,spec)->lettac=matchtacwith|CstTact->Tacintern.glob_tactict|Closedlc->closed_term_ast(List.mapSmartlocate.global_with_aliaslc)inletspec=ic_unsafeenvsigmaspecinletsigma,spec=make_hypenvsigmaspecinletsigma,pow=plappsigmarocq_Some[|carrier;spec|]insigma,(tac,pow)letinterp_signenvsigmasign=letsigma,carrier=Evd.fresh_globalenvsigma(rocq_hypo())inmatchsignwith|None->plappsigmarocq_None[|carrier|]|Somespec->letsigma,spec=make_hypenvsigma(ic_unsafeenvsigmaspec)inplappsigmarocq_Some[|carrier;spec|](* Same remark on ill-typed terms ... *)letinterp_divenvsigmadiv=letsigma,carrier=Evd.fresh_globalenvsigma(rocq_hypo())inmatchdivwith|None->plappsigmarocq_None[|carrier|]|Somespec->letsigma,spec=make_hypenvsigma(ic_unsafeenvsigmaspec)inplappsigmarocq_Some[|carrier;spec|](* Same remark on ill-typed terms ... *)letadd_theory0envsigmanamertheqthmorphthcst_tac(pre,post)powersigndiv=check_required_library(cdir@["Ring_base"]);let(kind,r,zero,one,add,mul,sub,opp,req)=dest_ringenvsigmarthinlet(sigma,sth,ext)=build_setoid_paramsenvsigmaraddmuloppreqeqthinletsigma,(pow_tac,pspec)=interp_powerenvsigmapowerinletsigma,sspec=interp_signenvsigmasigninletsigma,dspec=interp_divenvsigmadivinletrk=reflect_coeffmorphthinletparams,ctx=exec_tacticenvsigma5(zltac"ring_lemmas")[sth;ext;rth;pspec;sspec;dspec;rk]inletlemma1=params.(3)inletlemma2=params.(4)inletlemma1=decl_constantname"_ring_lemma1"ctxlemma1inletlemma2=decl_constantname"_ring_lemma2"ctxlemma2inletcst_tac=interp_cst_tacenvsigmamorphthkind(zero,one,add,mul,opp)cst_tacinletpretac=matchprewithSomet->Tacintern.glob_tactict|_->CAst.make(TacId[])inletposttac=matchpostwithSomet->Tacintern.glob_tactict|_->CAst.make(TacId[])inletr=EConstr.to_constrsigmarinletreq=EConstr.to_constrsigmareqinletsth=EConstr.to_constrsigmasthinlet_=Lib.add_leaf(theory_to_obj{ring_name=name;ring_carrier=r;ring_req=req;ring_setoid=sth;ring_ext=params.(1);ring_morph=params.(2);ring_th=params.(0);ring_cst_tac=cst_tac;ring_pow_tac=pow_tac;ring_lemma1=lemma1;ring_lemma2=lemma2;ring_pre_tac=pretac;ring_post_tac=posttac})in()letic_coeff_specenvsigma=function|Computationalt->Computational(ic_unsafeenvsigmat)|Morphismt->Morphism(ic_unsafeenvsigmat)|Abstract->Abstractletset_oncesrv=ifOption.is_empty!rthenr:=Somevelseerror(s^" cannot be set twice")letprocess_ring_modsenvsigmal=letkind=refNoneinletset=refNoneinletcst_tac=refNoneinletpre=refNoneinletpost=refNoneinletsign=refNoneinletpower=refNoneinletdiv=refNoneinList.iter(functionRing_kindk->set_once"ring kind"kind(ic_coeff_specenvsigmak)|Const_tact->set_once"tactic recognizing constants"cst_tact|Pre_tact->set_once"preprocess tactic"pret|Post_tact->set_once"postprocess tactic"postt|Setoid(sth,ext)->set_once"setoid"set(ic_unsafeenvsigmasth,ic_unsafeenvsigmaext)|Pow_spec(t,spec)->set_once"power"power(t,spec)|Sign_spect->set_once"sign"signt|Div_spect->set_once"div"divt)l;letk=match!kindwithSomek->k|None->Abstractin(k,!set,!cst_tac,!pre,!post,!power,!sign,!div)letadd_theoryidrthl=letenv=Global.env()inletsigma=Evd.from_envenvinletsigma,rth=icenvsigmarthinlet(k,set,cst,pre,post,power,sign,div)=process_ring_modsenvsigmalinadd_theory0envsigmaidrthsetkcst(pre,post)powersigndiv(*****************************************************************************)(* The tactics consist then only in a lookup in the ring database and
call the appropriate ltac. *)letmake_args_listsigmarlt=matchrlwith|[]->let(_,t1,t2)=dest_relsigmatin[t1;t2]|_->rlletmake_term_listenvsigmacarrierrl=letsigma,l=List.fold_right(funx(sigma,l)->plappsigmarocq_cons[|carrier;x;l|])rl(plappsigmarocq_nil[|carrier|])inTyping.solve_evarsenvsigmalletcargc=Tacinterp.Value.of_constr(EConstr.of_constrc)lettacargexpr=Tacinterp.Value.of_closure(Tacinterp.default_ist())exprletltac_ring_structuree=letreq=carge.ring_reqinletsth=carge.ring_setoidinletext=carge.ring_extinletmorph=carge.ring_morphinletth=carge.ring_thinletcst_tac=tacarge.ring_cst_tacinletpow_tac=tacarge.ring_pow_tacinletlemma1=carge.ring_lemma1inletlemma2=carge.ring_lemma2inletpretac=tacarg(CAst.make(TacFun([Anonymous],e.ring_pre_tac)))inletposttac=tacarg(CAst.make(TacFun([Anonymous],e.ring_post_tac)))in[req;sth;ext;morph;th;cst_tac;pow_tac;lemma1;lemma2;pretac;posttac]letring_lookup(f:Value.t)lHrlt=Proofview.Goal.enterbeginfungl->letsigma=Tacmach.projectglinletenv=Proofview.Goal.envglinletrl=make_args_listsigmarltinlete=find_ring_structureenvsigmarlinletsigma,l=make_term_listenvsigma(EConstr.of_constre.ring_carrier)rlinletrl=Value.of_constrlinletsigma,l=make_hyp_listenvsigmalHinletlH=Value.of_constrlinletring=ltac_ring_structureeinProofview.tclTHEN(Proofview.Unsafe.tclEVARSsigma)(Value.applyf(ring@[lH;rl]))end(***********************************************************************)letnew_field_path=DirPath.make(List.mapId.of_string["Field_tac";plugin_dir;"Stdlib"])letfield_ltacs=lazy(KerName.make(ModPath.MPfilenew_field_path)(Label.makes))let_=add_map"field"(map_with_eq@@base_red@ring_red@[(* display_linear: evaluate polynomials and coef operations, protect
field operations and make recursive call on the var map *)gen_reference"plugins.field.display_linear",Arg(function9|10|11|13|15|16->Eval|12|14->Rec|_->Prot);gen_reference"plugins.field.display_pow_linear",Arg(function9|10|11|14|16|18|19->Eval|12|17->Rec|_->Prot);(* FEeval: evaluate polynomial, protect field
operations and make recursive call on the var map *)gen_reference"plugins.field.FEeval",Arg(function12|15->Eval|10|14->Rec|_->Prot)]);;let_=add_map"field_cond"(map_without_eq@@base_red@[(* PCond: evaluate denum list, protect ring
operations and make recursive call on the var map *)gen_reference"plugins.field.PCond",Arg(function11|14->Eval|9|13->Rec|_->Prot)]);;let_=Redexpr.declare_reduction"simpl_field_expr"(protect_red"field")letafield_theory=gen_reference"plugins.field.almost_field_theory"letfield_theory=gen_reference"plugins.field.field_theory"letsfield_theory=gen_reference"plugins.field.semi_field_theory"letaf_ar=gen_reference"plugins.field.AF_AR"letf_r=gen_reference"plugins.field.F_R"letsf_sr=gen_reference"plugins.field.SF_SR"letdest_fieldenvsigmath_spec=letth_typ=Retyping.get_type_ofenvsigmath_specinmatchEConstr.kindsigmath_typwith|App(f,[|r;zero;one;add;mul;sub;opp;div;inv;req|])whenisRefXenvsigma(afield_theory())f->letsigma,rth=plappsigmaaf_ar[|r;zero;one;add;mul;sub;opp;div;inv;req;th_spec|]in(None,r,zero,one,add,mul,Somesub,Someopp,div,inv,req,rth)|App(f,[|r;zero;one;add;mul;sub;opp;div;inv;req|])whenisRefXenvsigma(field_theory())f->letsigma,rth=plappsigmaf_r[|r;zero;one;add;mul;sub;opp;div;inv;req;th_spec|]in(Somefalse,r,zero,one,add,mul,Somesub,Someopp,div,inv,req,rth)|App(f,[|r;zero;one;add;mul;div;inv;req|])whenisRefXenvsigma(sfield_theory())f->letsigma,rth=plappsigmasf_sr[|r;zero;one;add;mul;div;inv;req;th_spec|]in(Sometrue,r,zero,one,add,mul,None,None,div,inv,req,rth)|_->error"bad field structure"letfield_from_carrier=Summary.refCmap.empty~name:"field-tac-carrier-table"letprint_fields()=Feedback.msg_notice(strbrk"The following field structures have been declared:");Cmap.iter(fun_carrierfi->letenv=Global.env()inletsigma=Evd.from_envenvinFeedback.msg_notice(hov2(Id.printfi.field_name++spc()++str"with carrier "++pr_constr_envenvsigmafi.field_carrier++spc()++str"and equivalence relation "++pr_constr_envenvsigmafi.field_req)))!field_from_carrierletfield_for_carrierr=Cmap.findr!field_from_carrierletfind_field_structureenvsigmal=check_required_library(cdir@["Field_tac"]);matchlwith|t::cl'->letty=Retyping.get_type_ofenvsigmatinletcheckc=letty'=Retyping.get_type_ofenvsigmacinifnot(Reductionops.is_convenvsigmatyty')thenCErrors.user_err(str"Arguments of field_simplify do not have all the same type.")inList.itercheckcl';(tryfield_for_carrier(EConstr.to_constrsigmaty)withNot_found->CErrors.user_err(str"Cannot find a declared field structure over"++spc()++str"\""++pr_econstr_envenvsigmaty++str"\"."))|[]->assertfalseletadd_field_entrye=field_from_carrier:=Cmap.adde.field_carriere!field_from_carrierletsubst_th(subst,th)=letc'=subst_mpssubstth.field_carrierinleteq'=subst_mpssubstth.field_reqinletthm1'=subst_mpssubstth.field_okinletthm2'=subst_mpssubstth.field_simpl_eq_okinletthm3'=subst_mpssubstth.field_simpl_okinletthm4'=subst_mpssubstth.field_simpl_eq_in_okinletthm5'=subst_mpssubstth.field_condinlettac'=Tacsubst.subst_tacticsubstth.field_cst_tacinletpow_tac'=Tacsubst.subst_tacticsubstth.field_pow_tacinletpretac'=Tacsubst.subst_tacticsubstth.field_pre_tacinletposttac'=Tacsubst.subst_tacticsubstth.field_post_tacinifc'==th.field_carrier&&eq'==th.field_req&&thm1'==th.field_ok&&thm2'==th.field_simpl_eq_ok&&thm3'==th.field_simpl_ok&&thm4'==th.field_simpl_eq_in_ok&&thm5'==th.field_cond&&tac'==th.field_cst_tac&&pow_tac'==th.field_pow_tac&&pretac'==th.field_pre_tac&&posttac'==th.field_post_tacthenthelse{field_name=th.field_name;field_carrier=c';field_req=eq';field_cst_tac=tac';field_pow_tac=pow_tac';field_ok=thm1';field_simpl_eq_ok=thm2';field_simpl_ok=thm3';field_simpl_eq_in_ok=thm4';field_cond=thm5';field_pre_tac=pretac';field_post_tac=posttac'}letftheory_to_obj:field_info->obj=declare_object@@global_object_nodischarge"tactic-new-field-theory"~cache:add_field_entry~subst:(Somesubst_th)letfield_equalityenvsigmarinvreq=matchEConstr.kindsigmareqwith|App(f,[|_|])whenisRefXenvsigma(rocq_eq())f->letc=UnivGen.constr_of_monomorphic_global(Global.env())Rocqlib.(lib_ref"core.eq.congr")inletc=EConstr.of_constrcinsigma,mkApp(c,[|r;r;inv|])|_->let_setoid=setoid_of_relationenvsigmarreqinletsignature=[Some(r,Somereq)],Some(r,Somereq)inletsigma,inv_m,inv_m_lem=tryRewrite.Internal.default_morphismenvsigmasignatureinvwithNot_found->error"field inverse should be declared as a morphism"insigma,inv_m_lemletadd_field_theory0envsigmanameftheqthmorphthcst_tacinj(pre,post)powersignodiv=letopenConstrincheck_required_library(cdir@["Field_tac"]);let(sigma,fth)=icenvsigmafthinlet(kind,r,zero,one,add,mul,sub,opp,div,inv,req,rth)=dest_fieldenvsigmafthinlet(sigma,sth,ext)=build_setoid_paramsenvsigmaraddmuloppreqeqthinleteqth=Some(sth,ext)inlet_=add_theory0envsigmanamertheqthmorphthcst_tac(pre,post)powersignodivinletsigma,(pow_tac,pspec)=interp_powerenvsigmapowerinletsigma,sspec=interp_signenvsigmasigninletsigma,dspec=interp_divenvsigmaodivinletsigma,inv_m=field_equalityenvsigmarinvreqinletrk=reflect_coeffmorphthinletparams,ctx=exec_tacticenvsigma9(field_ltac"field_lemmas")[sth;ext;inv_m;fth;pspec;sspec;dspec;rk]inletlemma1=params.(3)inletlemma2=params.(4)inletlemma3=params.(5)inletlemma4=params.(6)inletcond_lemma=matchinjwith|Somethm->mkApp(params.(8),[|EConstr.to_constrsigmathm|])|None->params.(7)inletlemma1=decl_constantname"_field_lemma1"ctxlemma1inletlemma2=decl_constantname"_field_lemma2"ctxlemma2inletlemma3=decl_constantname"_field_lemma3"ctxlemma3inletlemma4=decl_constantname"_field_lemma4"ctxlemma4inletcond_lemma=decl_constantname"_lemma5"ctxcond_lemmainletcst_tac=interp_cst_tacenvsigmamorphthkind(zero,one,add,mul,opp)cst_tacinletpretac=matchprewithSomet->Tacintern.glob_tactict|_->CAst.make(TacId[])inletposttac=matchpostwithSomet->Tacintern.glob_tactict|_->CAst.make(TacId[])inletr=EConstr.to_constrsigmarinletreq=EConstr.to_constrsigmareqinlet_=Lib.add_leaf(ftheory_to_obj{field_name=name;field_carrier=r;field_req=req;field_cst_tac=cst_tac;field_pow_tac=pow_tac;field_ok=lemma1;field_simpl_eq_ok=lemma2;field_simpl_ok=lemma3;field_simpl_eq_in_ok=lemma4;field_cond=cond_lemma;field_pre_tac=pretac;field_post_tac=posttac})in()letprocess_field_modsenvsigmal=letkind=refNoneinletset=refNoneinletcst_tac=refNoneinletpre=refNoneinletpost=refNoneinletinj=refNoneinletsign=refNoneinletpower=refNoneinletdiv=refNoneinList.iter(functionRing_mod(Ring_kindk)->set_once"field kind"kind(ic_coeff_specenvsigmak)|Ring_mod(Const_tact)->set_once"tactic recognizing constants"cst_tact|Ring_mod(Pre_tact)->set_once"preprocess tactic"pret|Ring_mod(Post_tact)->set_once"postprocess tactic"postt|Ring_mod(Setoid(sth,ext))->set_once"setoid"set(ic_unsafeenvsigmasth,ic_unsafeenvsigmaext)|Ring_mod(Pow_spec(t,spec))->set_once"power"power(t,spec)|Ring_mod(Sign_spect)->set_once"sign"signt|Ring_mod(Div_spect)->set_once"div"divt|Injecti->set_once"infinite property"inj(ic_unsafeenvsigmai))l;letk=match!kindwithSomek->k|None->Abstractin(env,sigma,k,!set,!inj,!cst_tac,!pre,!post,!power,!sign,!div)letadd_field_theoryidtmods=letenv=Global.env()inletsigma=Evd.from_envenvinlet(env,sigma,k,set,inj,cst_tac,pre,post,power,sign,div)=process_field_modsenvsigmamodsinadd_field_theory0envsigmaidtsetkcst_tacinj(pre,post)powersigndivletltac_field_structuree=letreq=carge.field_reqinletcst_tac=tacarge.field_cst_tacinletpow_tac=tacarge.field_pow_tacinletfield_ok=carge.field_okinletfield_simpl_ok=carge.field_simpl_okinletfield_simpl_eq_ok=carge.field_simpl_eq_okinletfield_simpl_eq_in_ok=carge.field_simpl_eq_in_okinletcond_ok=carge.field_condinletpretac=tacarg(CAst.make(TacFun([Anonymous],e.field_pre_tac)))inletposttac=tacarg(CAst.make(TacFun([Anonymous],e.field_post_tac)))in[req;cst_tac;pow_tac;field_ok;field_simpl_ok;field_simpl_eq_ok;field_simpl_eq_in_ok;cond_ok;pretac;posttac]letfield_lookup(f:Value.t)lHrlt=Proofview.Goal.enterbeginfungl->letsigma=Tacmach.projectglinletenv=Proofview.Goal.envglinletrl=make_args_listsigmarltinlete=find_field_structureenvsigmarlinletsigma,c=make_term_listenvsigma(EConstr.of_constre.field_carrier)rlinletrl=Value.of_constrcinletsigma,l=make_hyp_listenvsigmalHinletlH=Value.of_constrlinletfield=ltac_field_structureeinProofview.tclTHEN(Proofview.Unsafe.tclEVARSsigma)(Value.applyf(field@[lH;rl]))end