123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234(************************************************************************)(* * 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) *)(************************************************************************)(*i*)openNamesopenContextopenCErrorsopenUtilopenGlob_termopenConstrexpropenLibnamesopenTypeclassesopenPpopenLibobjectopenNameopsopenContext.Rel.DeclarationmoduleRelDecl=Context.Rel.Declaration(*i*)letgeneralizable_table=Summary.refId.Pred.empty~name:"generalizable-ident"letdeclare_generalizable_identtable{CAst.loc;v=id}=ifnot(Id.equalid(root_of_idid))thenuser_err?loc((Id.printid++str" is not declarable as generalizable identifier: it must have no trailing digits, quote, or _."));ifId.Pred.memidtablethenuser_err?loc((Id.printid++str" is already declared as a generalizable identifier."))elseId.Pred.addidtableletadd_generalizablegentable=matchgenwith|None->Id.Pred.empty|Some[]->Id.Pred.full|Somel->List.fold_left(funtablelid->declare_generalizable_identtablelid)tablelletcache_generalizable_type(local,cmd)=generalizable_table:=add_generalizablecmd!generalizable_tableletload_generalizable_type_(local,cmd)=generalizable_table:=add_generalizablecmd!generalizable_tableletin_generalizable:bool*lidentlistoption->obj=declare_object{(default_object"GENERALIZED-IDENT")withload_function=load_generalizable_type;cache_function=cache_generalizable_type;classify_function=(fun(local,_)->iflocalthenDisposeelseKeep)}letdeclare_generalizable~localgen=Lib.add_leaf(in_generalizable(local,gen))letfind_generalizable_identid=Id.Pred.mem(root_of_idid)!generalizable_tableletis_globalid=tryignore(Nametab.locate_extended(qualid_of_identid));truewithNot_found->falseletis_namedidenv=tryignore(Environ.lookup_namedidenv);truewithNot_found->falseletis_freevaridsenvx=not(Id.Set.memxids||is_namedxenv||is_globalx)(* Auxiliary functions for the inference of implicitly quantified variables. *)letungeneralizablelocid=user_err?loc(str"Unbound and ungeneralizable variable "++Id.printid++str".")letfree_vars_of_constr_exprc?(bound=Id.Set.empty)l=letfoundlocidbdvarsl=ifId.List.memidlthenlelseifis_freevarbdvars(Global.env())idtheniffind_generalizable_identidthenid::lelseungeneralizablelocidelselinletrecauxbdvarslc=matchCAst.(c.v)with|CRef(qid,_)whenqualid_is_identqid->foundc.CAst.loc(qualid_basenameqid)bdvarsl|CNotation(_,(InConstrEntry,"{ _ : _ | _ }"),({CAst.v=CRef(qid,_)}::_,[],[],[]))whenqualid_is_identqid&¬(Id.Set.mem(qualid_basenameqid)bdvars)->Constrexpr_ops.fold_constr_expr_with_binders(funal->Id.Set.addal)aux(Id.Set.add(qualid_basenameqid)bdvars)lc|_->Constrexpr_ops.fold_constr_expr_with_binders(funal->Id.Set.addal)auxbdvarslcinauxboundlcletgeneralizable_vars_of_glob_constr?(bound=Id.Set.empty)?(allowed=Id.Set.empty)=letrecvarsboundvsc=matchDAst.getcwith|GVarid->letloc=c.CAst.locinifis_freevarbound(Global.env())idthenifList.exists(fun{CAst.v}->Id.equalvid)vsthenvselseCAst.(make?locid)::vselsevs|_->Glob_ops.fold_glob_constr_with_bindersId.Set.addvarsboundvscinfunrt->letvars=List.rev(varsbound[]rt)inList.iter(fun{CAst.loc;v=id}->ifnot(Id.Set.memidallowed||find_generalizable_identid)thenungeneralizablelocid)vars;varsletmake_freshidsenvx=Namegen.next_ident_away_fromx(funx->not(is_freevaridsenvx))letnext_name_away_fromnaavoid=matchnawith|Anonymous->make_freshavoid(Global.env())(Id.of_string"anon")|Nameid->make_freshavoid(Global.env())idletrecis_class_argc=letopenConstrinmatchkindcwith|Prod(_,_,c)|Cast(c,_,_)|LetIn(_,_,_,c)->is_class_argc|_->letc,_=decompose_appcinmatchdestRefcwith|exceptionDestKO->false|r,_->is_classrletcombine_paramsavoidappliedneeded=letnamed,applied=List.partition(function(t,Some{CAst.loc;v=ExplByNameid})->letis_iddecl=Name.equal(Nameid)(RelDecl.get_namedecl)inifnot(List.existsis_idneeded)thenuser_err?loc(str"Wrong argument name: "++Id.printid);true|_->false)appliedinletnamed=List.map(funx->matchxwith(t,Some{CAst.loc;v=ExplByNameid})->id,t|_->assertfalse)namedinletrecauxidsavoidappneed=matchneedwith|[]->beginmatchappwith|[]->List.revids,avoid|(x,_)::_->user_err?loc:(Constrexpr_ops.constr_locx)(str"Typeclass does not expect more arguments")end|LocalDef_::need->auxidsavoidappneed|LocalAssum({binder_name=Nameid},_)::needwhenId.List.mem_associdnamed->aux(Id.List.associdnamed::ids)avoidappneed|decl::need->beginmatchapp,is_class_arg(get_typedecl)with|(x,_)::app,false->aux(x::ids)avoidappneed|[],false|_,true->letid'=next_name_away_from(RelDecl.get_namedecl)avoidinlett'=CAst.make@@CRef(qualid_of_identid',None)inaux(t'::ids)(Id.Set.addid'avoid)appneedendinaux[]avoidappliedneededletdestClassAppExplcl=letopenCAstinletloc=cl.locinmatchcl.vwith|CApp({v=CRef(ref,inst)},l)->CAst.make?loc(ref,l,inst)|CRef(ref,inst)->CAst.make?loc:cl.loc(ref,[],inst)|_->raiseNot_foundletimplicit_applicationenvty=letis_class=trylet({CAst.v=(qid,_,_)}asclapp)=destClassAppExpltyinifLibnames.idset_mem_qualidqidenvthenNoneelseletgr=Nametab.locateqidinOption.map(funcl->cl,clapp)(Typeclasses.class_infogr)withNot_found->Noneinmatchis_classwith|None->ty,env|Some(c,{CAst.loc;v=(id,par,inst)})->letavoid=Id.Set.unionenv(Id.Set.of_list(free_vars_of_constr_exprty~bound:env[]))inletargs,avoid=combine_paramsavoidpar(List.revc.cl_context)inCAst.make?loc@@CAppExpl((id,inst),args),avoidletwarn_ignoring_implicit_status=CWarnings.create~name:"ignoring-implicit-status"~category:CWarnings.CoreCategories.implicits(funna->strbrk"Ignoring implicit status of product binder "++Name.printna++strbrk" and following binders")letimplicits_of_glob_constr?(with_products=true)l=letadd_impl?locnabkl=matchbkwith|NonMaxImplicit->CAst.make?loc(Some(na,false))::l|MaxImplicit->CAst.make?loc(Some(na,true))::l|Explicit->CAst.make?locNone::linletrecauxc=matchDAst.getcwith|GProd(na,_,bk,t,b)->ifwith_productsthenadd_implnabk(auxb)elselet()=matchbkwith|NonMaxImplicit|MaxImplicit->warn_ignoring_implicit_statusna?loc:c.CAst.loc|Explicit->()in[]|GLambda(na,_,bk,t,b)->add_impl?loc:t.CAst.locnabk(auxb)|GLetIn(na,_,b,t,c)->auxc|GRec(fix_kind,nas,args,tys,bds)->letnb=matchfix_kindwith|GFix(_,n)->n|GCoFixn->ninList.fold_right(fun(na,_,bk,t,_)l->matchtwith|Some_->l|_->add_impl?loc:c.CAst.locnabkl)args.(nb)(auxbds.(nb))|_->[]inauxl