123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984(************************************************************************)(* * 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) *)(************************************************************************)moduleCVars=VarsopenLtac_pluginopenPpopenUtilopenNamesopenConstropenEConstropenVarsopenCClosureopenEnvironopenGlob_termopenLocusopenTacexpropenCoqlibopenMod_substopenTacinterpopenLibobjectopenPrinteropenDeclareopenRing_astopenProofview.Notationsleterrormsg=CErrors.user_errPp.(strmsg)(****************************************************************************)(* controlled reduction *)typeprotect_flag=Eval|Prot|Rectypeprotection=Environ.env->Evd.evar_map->EConstr.t->GlobRef.t->(Int.t->protect_flag)optionletglobal_head_of_constrsigmac=letf,args=decompose_appsigmacintryfst(EConstr.destRefsigmaf)withDestKO->CErrors.anomaly(str"global_head_of_constr.")letglobal_of_constr_nofailsigmac=tryfst@@EConstr.destRefsigmacwithDestKO->GlobRef.VarRef(Id.of_string"dummy")letmk_atomc=CClosure.mk_atom(EConstr.Unsafe.to_constrc)letrecmk_clos_butsigmaf_mapnt=let(f,args)=EConstr.decompose_appsigmatinmatchf_map(global_of_constr_nofailsigmaf)with|Sometag->letmapit=tag_argsigmaf_mapn(tagi)tinifArray.is_emptyargsthenmap(-1)felsemk_red(FApp(map(-1)f,Array.mapimapargs))|None->mk_atomtandtag_argsigmaf_mapntagc=matchtagwith|Eval->mk_clos(Esubst.subs_idn,UVars.Instance.empty)(EConstr.Unsafe.to_constrc)|Prot->mk_atomc|Rec->mk_clos_butsigmaf_mapncletinterp_mapenvlt=leteqg1g2=QGlobRef.equalenvg1g2intrySome(List.assoc_feqtl)withNot_found->Noneletprotect_maps:protectionString.Map.tref=refString.Map.emptyletadd_mapsm=protect_maps:=String.Map.addsm!protect_mapsletlookup_mapmap=tryString.Map.findmap!protect_mapswithNot_found->CErrors.user_err(str"Map "++qsmap++str"not found.")letprotect_redmapenvsigmac=lettab=create_tab()inletinfos=Evarutil.create_clos_infosenvsigmaRedFlags.allinletmap=lookup_mapmapenvsigmacinletrecevalnc=matchEConstr.kindsigmacwith|Prod(na,t,u)->EConstr.mkProd(na,evalnt,eval(n+1)u)|_->EConstr.of_constr@@norm_valinfostab(mk_clos_butsigmamapnc)ineval0cletprotect_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="coq-core.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_set~strict:trueunivsinlettypes=(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(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="coq-core.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=lazy(EConstr.of_constr(UnivGen.constr_of_monomorphic_global(Global.env())(Coqlib.lib_refn)))letgen_referencen=lazy(Coqlib.lib_refn)letcoq_mk_Setoid=gen_constant"plugins.ring.Build_Setoid_Theory"letcoq_None=gen_reference"core.option.None"letcoq_Some=gen_reference"core.option.Some"letcoq_eq=gen_constant"core.eq.type"letcoq_cons=gen_reference"core.list.cons"letcoq_nil=gen_reference"core.list.nil"letlappfargs=mkApp(Lazy.forcef,args)letplappsigmafargs=letsigma,fc=Evd.fresh_global(Global.env())sigma(Lazy.forcef)insigma,mkApp(fc,args)letdest_rel0sigmat=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"letrecdest_relsigmat=matchEConstr.kindsigmatwith|Prod(_,_,c)->dest_relsigmac|_->dest_rel0sigmat(****************************************************************************)(* Library linking *)letplugin_dir="setoid_ring"letcdir=["Coq";plugin_dir]letplugin_modules=List.map(fund->cdir@d)[["Ring_theory"];["Ring_polynom"];["Ring_tac"];["InitialRing"];["Field_tac"];["Field_theory"]]letmy_constantc=lazy(EConstr.of_constr(UnivGen.constr_of_monomorphic_global(Global.env())@@Coqlib.gen_reference_in_modules"Ring"plugin_modulesc))[@@ocaml.warning"-3"]letmy_referencec=lazy(Coqlib.gen_reference_in_modules"Ring"plugin_modulesc)[@@ocaml.warning"-3"]letznew_ring_path=DirPath.make(List.mapId.of_string["InitialRing";plugin_dir;"Coq"])letzltacs=lazy(KerName.make(ModPath.MPfileznew_ring_path)(Label.makes))letmk_cstls=lazy(Coqlib.coq_reference"ring"ls)[@@ocaml.warning"-3"]letpol_csts=mk_cst[plugin_dir;"Ring_polynom"]s(* Ring theory *)(* almost_ring defs *)letcoq_almost_ring_theory=my_constant"almost_ring_theory"(* setoid and morphism utilities *)letcoq_eq_setoid=my_reference"Eqsth"letcoq_eq_morph=my_reference"Eq_ext"letcoq_eq_smorph=my_reference"Eq_s_ext"(* ring -> almost_ring utilities *)letcoq_ring_theory=my_constant"ring_theory"letcoq_mk_reqe=my_constant"mk_reqe"(* semi_ring -> almost_ring utilities *)letcoq_semi_ring_theory=my_constant"semi_ring_theory"letcoq_mk_seqe=my_constant"mk_seqe"letcoq_abstract=my_constant"Abstract"letcoq_comp=my_constant"Computational"letcoq_morph=my_constant"Morphism"(* power function *)letltac_inv_morph_nothing=zltac"inv_morph_nothing"(* hypothesis *)letcoq_mkhypo=my_reference"mkhypo"letcoq_hypo=my_reference"hypo"(* Equality: do not evaluate but make recursive call on both sides *)letmap_with_eqarg_mapenvsigmac=let(req,_,_)=dest_relsigmacininterp_mapenv((global_head_of_constrsigmareq,(function-1->Prot|_->Rec))::List.map(fun(c,map)->(Lazy.forcec,map))arg_map)letmap_without_eqarg_mapenv__=interp_mapenv(List.map(fun(c,map)->(Lazy.forcec,map))arg_map)let_=add_map"ring"(map_with_eq[coq_cons,(function-1->Eval|2->Rec|_->Prot);coq_nil,(function-1->Eval|_->Prot);my_reference"IDphi",(function_->Eval);my_reference"gen_phiZ",(function_->Eval);(* Pphi_dev: evaluate polynomial and coef operations, protect
ring operations and make recursive call on the var map *)pol_cst"Pphi_dev",(function-1|8|9|10|12|14->Eval|11|13->Rec|_->Prot);pol_cst"Pphi_pow",(function-1|8|9|10|13|15|17->Eval|11|16->Rec|_->Prot);(* PEeval: evaluate polynomial, protect ring
operations and make recursive call on the var map *)pol_cst"PEeval",(function-1|10|13->Eval|8|12->Rec|_->Prot)])(****************************************************************************)(* 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,lappcoq_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=lappcoq_mk_reqe[|r;add;mul;opp;req;m1;m2;m3|]letop_smorphraddmulreqm1m2=lappcoq_mk_seqe[|r;add;mul;req;m1;m2|]letring_equalityenvsigma(r,add,mul,opp,req)=matchEConstr.kindsigmareqwith|App(f,[|_|])wheneq_constr_nounivssigmaf(Lazy.forcecoq_eq)->letsigma,setoid=plappsigmacoq_eq_setoid[|r|]inletsigma,op_morph=matchoppwithSomeopp->plappsigmacoq_eq_morph[|r;add;mul;opp|]|None->plappsigmacoq_eq_smorph[|r;add;mul|]inletsigma,setoid=Typing.solve_evarsenvsigmasetoidinletsigma,op_morph=Typing.solve_evarsenvsigmaop_morphin(setoid,op_morph)|_->letsigma,setoid=setoid_of_relationenvsigmarreqinletsignature=[Some(r,Somereq);Some(r,Somereq)],Some(r,Somereq)inletadd_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.")inletmul_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.")inletop_morph=matchoppwith|Someopp->(letopp_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"\"");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"\"");op_smorphraddmulreqadd_m_lemmul_m_lem)in(setoid,op_morph)letbuild_setoid_paramsenvsigmaraddmuloppreqeqth=matcheqthwithSometh->th|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|])wheneq_constr_nounivssigmaf(Lazy.forcecoq_almost_ring_theory)->(None,r,zero,one,add,mul,Somesub,Someopp,req)|App(f,[|r;zero;one;add;mul;req|])wheneq_constr_nounivssigmaf(Lazy.forcecoq_semi_ring_theory)->(Sometrue,r,zero,one,add,mul,None,None,req)|App(f,[|r;zero;one;add;mul;sub;opp;req|])wheneq_constr_nounivssigmaf(Lazy.forcecoq_ring_theory)->(Somefalse,r,zero,one,add,mul,Somesub,Someopp,req)|_->error"bad ring structure"letreflect_coeffrkind=(* We build an ill-typed terms on purpose... *)matchrkindwithAbstract->Lazy.forcecoq_abstract|Computationalc->lappcoq_comp[|c|]|Morphismm->lappcoq_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_ofenvsigmacinplappsigmacoq_mkhypo[|t;c|]letmake_hyp_listenvsigmalH=letsigma,carrier=Evd.fresh_globalenvsigma(Lazy.forcecoq_hypo)inletsigma,l=List.fold_right(func(sigma,l)->letsigma,c=make_hypenvsigmacinplappsigmacoq_cons[|carrier;c;l|])lH(plappsigmacoq_nil[|carrier|])inletsigma,l'=Typing.solve_evarsenvsigmalinsigma,l'letinterp_powerenvsigmapow=letsigma,carrier=Evd.fresh_globalenvsigma(Lazy.forcecoq_hypo)inmatchpowwith|None->lett=ArgArg(Loc.tag(Lazy.forceltac_inv_morph_nothing))inletsigma,c=plappsigmacoq_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=plappsigmacoq_Some[|carrier;spec|]insigma,(tac,pow)letinterp_signenvsigmasign=letsigma,carrier=Evd.fresh_globalenvsigma(Lazy.forcecoq_hypo)inmatchsignwith|None->plappsigmacoq_None[|carrier|]|Somespec->letsigma,spec=make_hypenvsigma(ic_unsafeenvsigmaspec)inplappsigmacoq_Some[|carrier;spec|](* Same remark on ill-typed terms ... *)letinterp_divenvsigmadiv=letsigma,carrier=Evd.fresh_globalenvsigma(Lazy.forcecoq_hypo)inmatchdivwith|None->plappsigmacoq_None[|carrier|]|Somespec->letsigma,spec=make_hypenvsigma(ic_unsafeenvsigmaspec)inplappsigmacoq_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(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_rel0sigmatin[t1;t2]|_->rlletmake_term_listenvsigmacarrierrl=letsigma,l=List.fold_right(funx(sigma,l)->plappsigmacoq_cons[|carrier;x;l|])rl(plappsigmacoq_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;"Coq"])letfield_ltacs=lazy(KerName.make(ModPath.MPfilenew_field_path)(Label.makes))let_=add_map"field"(map_with_eq[coq_cons,(function-1->Eval|2->Rec|_->Prot);coq_nil,(function-1->Eval|_->Prot);my_reference"IDphi",(function_->Eval);my_reference"gen_phiZ",(function_->Eval);(* display_linear: evaluate polynomials and coef operations, protect
field operations and make recursive call on the var map *)my_reference"display_linear",(function-1|9|10|11|13|15|16->Eval|12|14->Rec|_->Prot);my_reference"display_pow_linear",(function-1|9|10|11|14|16|18|19->Eval|12|17->Rec|_->Prot);(* Pphi_dev: evaluate polynomial and coef operations, protect
ring operations and make recursive call on the var map *)pol_cst"Pphi_dev",(function-1|8|9|10|12|14->Eval|11|13->Rec|_->Prot);pol_cst"Pphi_pow",(function-1|8|9|10|13|15|17->Eval|11|16->Rec|_->Prot);(* PEeval: evaluate polynomial, protect ring
operations and make recursive call on the var map *)pol_cst"PEeval",(function-1|10|13->Eval|8|12->Rec|_->Prot);(* FEeval: evaluate polynomial, protect field
operations and make recursive call on the var map *)my_reference"FEeval",(function-1|12|15->Eval|10|14->Rec|_->Prot)]);;let_=add_map"field_cond"(map_without_eq[coq_cons,(function-1->Eval|2->Rec|_->Prot);coq_nil,(function-1->Eval|_->Prot);my_reference"IDphi",(function_->Eval);my_reference"gen_phiZ",(function_->Eval);(* PCond: evaluate denum list, protect ring
operations and make recursive call on the var map *)my_reference"PCond",(function-1|11|14->Eval|9|13->Rec|_->Prot)]);;let_=Redexpr.declare_reduction"simpl_field_expr"(protect_red"field")letafield_theory=my_reference"almost_field_theory"letfield_theory=my_reference"field_theory"letsfield_theory=my_reference"semi_field_theory"letaf_ar=my_reference"AF_AR"letf_r=my_reference"F_R"letsf_sr=my_reference"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(Lazy.forceafield_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(Lazy.forcefield_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(Lazy.forcesfield_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,[|_|])wheneq_constr_nounivssigmaf(Lazy.forcecoq_eq)->letc=UnivGen.constr_of_monomorphic_global(Global.env())Coqlib.(lib_ref"core.eq.congr")inletc=EConstr.of_constrcinmkApp(c,[|r;r;inv|])|_->let_setoid=setoid_of_relationenvsigmarreqinletsignature=[Some(r,Somereq)],Some(r,Somereq)inletinv_m,inv_m_lem=tryRewrite.Internal.default_morphismenvsigmasignatureinvwithNot_found->error"field inverse should be declared as a morphism"ininv_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(sth,ext)=build_setoid_paramsenvsigmaraddmuloppreqeqthinleteqth=Some(sth,ext)inlet_=add_theory0envsigmanamertheqthmorphthcst_tac(None,None)powersignodivinletsigma,(pow_tac,pspec)=interp_powerenvsigmapowerinletsigma,sspec=interp_signenvsigmasigninletsigma,dspec=interp_divenvsigmaodivinletinv_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