123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471openNamesopenPpopenConstropenLibnamesletmk_prefixpreid=Id.of_string(pre^Id.to_stringid)letmk_rel_id=mk_prefix"R_"letmk_correct_idid=Nameops.add_suffix(mk_rel_idid)"_correct"letmk_complete_idid=Nameops.add_suffix(mk_rel_idid)"_complete"letmk_equation_idid=Nameops.add_suffixid"_equation"letfresh_idavoids=Namegen.next_ident_away_in_goal(Global.env())(Id.of_strings)(Id.Set.of_listavoid)letfresh_nameavoids=Name(fresh_idavoids)letget_nameavoid?(default="H")=function|Anonymous->fresh_nameavoiddefault|Namen->Namenletarray_get_starta=Array.init(Array.lengtha-1)(funi->a.(i))letlocateqid=Nametab.locateqidletlocate_indref=matchlocaterefwithGlobRef.IndRefx->x|_->raiseNot_foundletlocate_constantref=matchlocaterefwithGlobRef.ConstRefx->x|_->raiseNot_foundletlocate_with_msgmsgfx=tryfxwithNot_found->CErrors.user_errmsgletfilter_mapfilterf=letrecit=function|[]->[]|e::l->iffilterethenfe::itlelseitlinitletchop_rlambda_n=letrecchop_lambda_naccnrt=ifn==0then(List.revacc,rt)elsematchDAst.getrtwith|Glob_term.GLambda(name,_,k,t,b)->chop_lambda_n((name,t,None)::acc)(n-1)b|Glob_term.GLetIn(name,_,v,t,b)->chop_lambda_n((name,v,t)::acc)(n-1)b|_->CErrors.user_err(str"chop_rlambda_n: Not enough Lambdas")inchop_lambda_n[]letchop_rprod_n=letrecchop_prod_naccnrt=ifn==0then(List.revacc,rt)elsematchDAst.getrtwith|Glob_term.GProd(name,_,k,t,b)->chop_prod_n((name,t)::acc)(n-1)b|_->CErrors.user_err(str"chop_rprod_n: Not enough products")inchop_prod_n[]letlist_union_eqeq_funl1l2=letrecurec=function|[]->l2|a::l->ifList.exists(eq_funa)l2thenureclelsea::ureclinurecl1letlist_add_set_eqeq_funxl=ifList.exists(eq_funx)lthenlelsex::lletcoq_constants=UnivGen.constr_of_monomorphic_global(Global.env())@@Coqlib.lib_refsletfind_referencesls=letdp=Names.DirPath.make(List.rev_mapId.of_stringsl)inNametab.locate(make_qualiddp(Id.of_strings))leteq=lazy(EConstr.of_constr(coq_constant"core.eq.type"))letrefl_equal=lazy(EConstr.of_constr(coq_constant"core.eq.refl"))letwith_full_printfa=letold_implicit_args=Impargs.is_implicit_args()andold_strict_implicit_args=Impargs.is_strict_implicit_args()andold_contextual_implicit_args=Impargs.is_contextual_implicit_args()inletold_rawprint=!Flags.raw_printinletold_printuniverses=!Constrextern.print_universesinletold_printallowmatchdefaultclause=Detyping.print_allow_match_default_clause()inConstrextern.print_universes:=true;Goptions.set_bool_option_valueDetyping.print_allow_match_default_opt_namefalse;Flags.raw_print:=true;Impargs.make_implicit_argsfalse;Impargs.make_strict_implicit_argsfalse;Impargs.make_contextual_implicit_argsfalse;Dumpglob.pause();tryletres=fainImpargs.make_implicit_argsold_implicit_args;Impargs.make_strict_implicit_argsold_strict_implicit_args;Impargs.make_contextual_implicit_argsold_contextual_implicit_args;Flags.raw_print:=old_rawprint;Constrextern.print_universes:=old_printuniverses;Goptions.set_bool_option_valueDetyping.print_allow_match_default_opt_nameold_printallowmatchdefaultclause;Dumpglob.pop_output();reswithreraise->Impargs.make_implicit_argsold_implicit_args;Impargs.make_strict_implicit_argsold_strict_implicit_args;Impargs.make_contextual_implicit_argsold_contextual_implicit_args;Flags.raw_print:=old_rawprint;Constrextern.print_universes:=old_printuniverses;Goptions.set_bool_option_valueDetyping.print_allow_match_default_opt_nameold_printallowmatchdefaultclause;Dumpglob.pop_output();raisereraise(**********************)typefunction_info={function_constant:Constant.t;graph_ind:inductive;equation_lemma:Constant.toption;correctness_lemma:Constant.toption;completeness_lemma:Constant.toption;rect_lemma:Constant.toption;rec_lemma:Constant.toption;prop_lemma:Constant.toption;sprop_lemma:Constant.toption;is_general:bool(* Has this function been defined using general recursive definition *)}(* type function_db = function_info list *)(* let function_table = ref ([] : function_db) *)letfrom_function=Summary.refCmap_env.empty~name:"functions_db_fn"letfrom_graph=Summary.refIndmap.empty~name:"functions_db_gr"(*
let rec do_cache_info finfo = function
| [] -> raise Not_found
| (finfo'::finfos as l) ->
if finfo' == finfo then l
else if finfo'.function_constant = finfo.function_constant
then finfo::finfos
else
let res = do_cache_info finfo finfos in
if res == finfos then l else finfo'::l
let cache_Function (_,(finfos)) =
let new_tbl =
try do_cache_info finfos !function_table
with Not_found -> finfos::!function_table
in
if new_tbl != !function_table
then function_table := new_tbl
*)letcache_Functionfinfos=from_function:=Cmap_env.addfinfos.function_constantfinfos!from_function;from_graph:=Indmap.addfinfos.graph_indfinfos!from_graphletsubst_Function(subst,finfos)=letdo_subst_conc=Mod_subst.subst_constantsubstcanddo_subst_indi=Mod_subst.subst_indsubstiinletfunction_constant'=do_subst_confinfos.function_constantinletgraph_ind'=do_subst_indfinfos.graph_indinletequation_lemma'=Option.Smart.mapdo_subst_confinfos.equation_lemmainletcorrectness_lemma'=Option.Smart.mapdo_subst_confinfos.correctness_lemmainletcompleteness_lemma'=Option.Smart.mapdo_subst_confinfos.completeness_lemmainletrect_lemma'=Option.Smart.mapdo_subst_confinfos.rect_lemmainletrec_lemma'=Option.Smart.mapdo_subst_confinfos.rec_lemmainletprop_lemma'=Option.Smart.mapdo_subst_confinfos.prop_lemmainletsprop_lemma'=Option.Smart.mapdo_subst_confinfos.sprop_lemmainiffunction_constant'==finfos.function_constant&&graph_ind'==finfos.graph_ind&&equation_lemma'==finfos.equation_lemma&&correctness_lemma'==finfos.correctness_lemma&&completeness_lemma'==finfos.completeness_lemma&&rect_lemma'==finfos.rect_lemma&&rec_lemma'==finfos.rec_lemma&&prop_lemma'==finfos.prop_lemma&&sprop_lemma'==finfos.sprop_lemmathenfinfoselse{function_constant=function_constant';graph_ind=graph_ind';equation_lemma=equation_lemma';correctness_lemma=correctness_lemma';completeness_lemma=completeness_lemma';rect_lemma=rect_lemma';rec_lemma=rec_lemma';prop_lemma=prop_lemma';sprop_lemma=sprop_lemma';is_general=finfos.is_general}letdischarge_Functionfinfos=Somefinfosletpr_ocstenvsigmac=Option.fold_right(funvacc->Printer.pr_global_env(Termops.vars_of_envenv)(ConstRefv))c(mt())letpr_infoenvsigmaf_info=str"function_constant := "++Printer.pr_global_env(Termops.vars_of_envenv)(ConstReff_info.function_constant)++fnl()++str"function_constant_type := "++(tryPrinter.pr_lconstr_envenvsigma(fst(Typeops.type_of_global_in_contextenv(GlobRef.ConstReff_info.function_constant)))withewhenCErrors.noncriticale->mt())++fnl()++str"equation_lemma := "++pr_ocstenvsigmaf_info.equation_lemma++fnl()++str"completeness_lemma :="++pr_ocstenvsigmaf_info.completeness_lemma++fnl()++str"correctness_lemma := "++pr_ocstenvsigmaf_info.correctness_lemma++fnl()++str"rect_lemma := "++pr_ocstenvsigmaf_info.rect_lemma++fnl()++str"rec_lemma := "++pr_ocstenvsigmaf_info.rec_lemma++fnl()++str"prop_lemma := "++pr_ocstenvsigmaf_info.prop_lemma++fnl()++str"graph_ind := "++Printer.pr_global_env(Termops.vars_of_envenv)(IndReff_info.graph_ind)++fnl()letpr_tableenvsigmatb=letl=Cmap_env.fold(funkvacc->v::acc)tb[]inPp.prlist_with_sepfnl(pr_infoenvsigma)lletin_Function:function_info->Libobject.obj=letopenLibobjectindeclare_object@@superglobal_object"FUNCTIONS_DB"~cache:cache_Function~subst:(Somesubst_Function)~discharge:discharge_Functionletfind_or_noneid=trySome(matchNametab.locate(qualid_of_identid)with|GlobRef.ConstRefc->c|_->CErrors.anomaly(Pp.str"Not a constant."))withNot_found->Noneletfind_Function_infosf=Cmap_env.find_optf!from_functionletfind_Function_of_graphind=Indmap.find_optind!from_graphletupdate_Functionfinfo=(* Pp.msgnl (pr_info finfo); *)Lib.add_leaf(in_Functionfinfo)letadd_Functionis_generalf=letf_id=Label.to_id(Constant.labelf)inletequation_lemma=find_or_none(mk_equation_idf_id)andcorrectness_lemma=find_or_none(mk_correct_idf_id)andcompleteness_lemma=find_or_none(mk_complete_idf_id)andrect_lemma=find_or_none(Nameops.add_suffixf_id"_rect")andrec_lemma=find_or_none(Nameops.add_suffixf_id"_rec")andprop_lemma=find_or_none(Nameops.add_suffixf_id"_ind")andsprop_lemma=find_or_none(Nameops.add_suffixf_id"_sind")andgraph_ind=matchNametab.locate(qualid_of_ident(mk_rel_idf_id))with|GlobRef.IndRefind->ind|_->CErrors.anomaly(Pp.str"Not an inductive.")inletfinfos={function_constant=f;equation_lemma;completeness_lemma;correctness_lemma;rect_lemma;rec_lemma;prop_lemma;sprop_lemma;graph_ind;is_general}inupdate_Functionfinfosletpr_tableenvsigma=pr_tableenvsigma!from_function(*********************************)(* Debugging *)let{Goptions.get=do_rewrite_dependent}=Goptions.declare_bool_option_and_ref~key:["Functional";"Induction";"Rewrite";"Dependent"]~value:true()let{Goptions.get=do_observe}=Goptions.declare_bool_option_and_ref~key:["Function_debug"]~value:false()letobservestrm=ifdo_observe()thenFeedback.msg_debugstrmelse()letdebug_queue=Stack.create()letprint_debug_queuebe=ifnot(Stack.is_emptydebug_queue)thenletlmsg,goal=Stack.popdebug_queueinifbthenFeedback.msg_debug(hov1(lmsg++(str" raised exception "++CErrors.printe)++str" on goal"++fnl()++goal))elseFeedback.msg_debug(hov1(str" from "++lmsg++str" on goal"++fnl()++goal))(* print_debug_queue false e; *)letdo_observe_tac~headerstac=letopenProofview.NotationsinletopenProofviewinGoal.enter(fungl->letgoal=Printer.Debug.pr_goalglinletenv,sigma=(Goal.envgl,Goal.sigmagl)inlets=senvsigmainletlmsg=seq[header;str" : "++s]intclLIFT(NonLogical.make(fun()->Feedback.msg_debug(s++fnl())))>>=fun()->tclOR(Stack.push(lmsg,goal)debug_queue;tac>>=funv->ignore(Stack.popdebug_queue);Proofview.tclUNITv)(fun(exn,info)->ifnot(Stack.is_emptydebug_queue)thenprint_debug_queuetrueexn;tclZERO~infoexn))letobserve_tac~headerstac=ifdo_observe()thendo_observe_tac~headerstacelsetaclet{Goptions.get=is_strict_tcc}=Goptions.declare_bool_option_and_ref~key:["Function_raw_tcc"]~value:false()exceptionBuilding_graphofexnexceptionDefining_principleofexnexceptionToShowofexnletjmeq()=tryCoqlib.check_required_libraryCoqlib.jmeq_module_name;EConstr.of_constr@@UnivGen.constr_of_monomorphic_global(Global.env())@@Coqlib.lib_ref"core.JMeq.type"withewhenCErrors.noncriticale->raise(ToShowe)letjmeq_refl()=tryCoqlib.check_required_libraryCoqlib.jmeq_module_name;EConstr.of_constr@@UnivGen.constr_of_monomorphic_global(Global.env())@@Coqlib.lib_ref"core.JMeq.refl"withewhenCErrors.noncriticale->raise(ToShowe)leth_introsl=Tacticals.tclMAP(funx->Tactics.Simple.introx)lleth_id=Id.of_string"h"lethrec_id=Id.of_string"hrec"letwell_founded=function|()->EConstr.of_constr(coq_constant"core.wf.well_founded")letacc_rel=function()->EConstr.of_constr(coq_constant"core.wf.acc")letacc_inv_id=function|()->EConstr.of_constr(coq_constant"core.wf.acc_inv")letwell_founded_ltof()=EConstr.of_constr(coq_constant"num.nat.well_founded_ltof")letltof_ref=function()->find_reference["Coq";"Arith";"Wf_nat"]"ltof"letmake_eq()=tryEConstr.of_constr(UnivGen.constr_of_monomorphic_global(Global.env())(Coqlib.lib_ref"core.eq.type"))withewhenCErrors.noncriticale->assertfalseletevaluable_of_global_referencer=(* Tacred.evaluable_of_global_reference (Global.env ()) *)matchrwith|GlobRef.ConstRefsp->Evaluable.EvalConstRefsp|GlobRef.VarRefid->Evaluable.EvalVarRefid|_->assertfalseletlist_rewrite(rev:bool)(eqs:(EConstr.constr*bool)list)=letopenTacticalsin(tclREPEAT(List.fold_right(fun(eq,b)i->tclORELSE((ifbthenEquality.rewriteLRelseEquality.rewriteRL)eq)i)(ifrevthenList.reveqselseeqs)(tclFAIL(mt()))))letdecompose_lambda_nsigman=ifn<0thenCErrors.user_errPp.(str"decompose_lambda_n: integer parameter must be positive");letreclamdec_reclnc=ifInt.equaln0then(l,c)elsematchEConstr.kindsigmacwith|Lambda(x,t,c)->lamdec_rec((x,t)::l)(n-1)c|Cast(c,_,_)->lamdec_reclnc|_->CErrors.user_errPp.(str"decompose_lambda_n: not enough abstractions")inlamdec_rec[]nletlamnnenvb=letopenEConstrinletreclamrec=function|0,env,b->b|n,(v,t)::l,b->lamrec(n-1,l,mkLambda(v,t,b))|_->assertfalseinlamrec(n,env,b)(* compose_lam [xn:Tn;..;x1:T1] b = [x1:T1]..[xn:Tn]b *)letcompose_lamlb=lamn(List.lengthl)lb(* prodn n [xn:Tn;..;x1:T1;Gamma] b = (x1:T1)..(xn:Tn)b *)letprodnnenvb=letopenEConstrinletrecprodrec=function|0,env,b->b|n,(v,t)::l,b->prodrec(n-1,l,mkProd(v,t,b))|_->assertfalseinprodrec(n,env,b)(* compose_prod [xn:Tn;..;x1:T1] b = (x1:T1)..(xn:Tn)b *)letcompose_prodlb=prodn(List.lengthl)lbtypetcc_lemma_value=Undefined|Valueofconstr|Not_needed(* We only "purify" on exceptions. XXX: What is this doing here? *)letfunind_purifyfx=letst=Vernacstate.freeze_full_state()intryfxwithe->lete=Exninfo.captureeinVernacstate.unfreeze_full_statest;Exninfo.iraisee