123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304(************************************************************************)(* * The Coq Proof Assistant / The Coq Development Team *)(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)(* <O___,, * (see CREDITS file for the list of authors) *)(* \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) *)(************************************************************************)openNames(**
- Get types of existentials ;
- Flatten dependency tree (prefix order) ;
- Replace existentials by de Bruijn indices in term, applied to the right arguments ;
- Apply term prefixed by quantification on "existentials".
*)letcheck_evarsenvevm=Evar.Map.iter(funkeyevi->ifEvd.is_obligation_evarevmkeythen()elseletloc,k=Evd.evar_sourceeviinPretype_errors.error_unsolvable_implicit?locenvevmkeyNone)(Evd.undefined_mapevm)typeobligation_info=(Names.Id.t*Constr.types*Evar_kinds.tLoc.located*(bool*Evar_kinds.obligation_definition_status)*Int.Set.t*unitProofview.tacticoption)arraytypeoblinfo={ev_name:int*Id.t;ev_hyps:EConstr.named_context;ev_status:bool*Evar_kinds.obligation_definition_status;ev_chop:intoption;ev_src:Evar_kinds.tLoc.located;ev_typ:Constr.types;ev_tac:unitProofview.tacticoption;ev_deps:Int.Set.t}(** Substitute evar references in t using de Bruijn indices,
where n binders were passed through. *)letsuccfix(depth,fixrels)=(succdepth,List.mapsuccfixrels)letsubst_evar_constrevmevsnidft=letseen=refInt.Set.emptyinlettransparent=refId.Set.emptyinletevar_infoid=CList.assoc_fEvar.equalidevsinletrecsubstrec(depth,fixrels)c=matchEConstr.kindevmcwith|Constr.Evar(k,args)->let{ev_name=id,idstr;ev_hyps=hyps;ev_chop=chop}=tryevar_infokwithNot_found->CErrors.anomaly~label:"eterm"Pp.(str"existential variable "++int(Evar.reprk)++str" not found.")inseen:=Int.Set.addid!seen;(* Evar arguments are created in inverse order,
and we must not apply to defined ones (i.e. LetIn's)
*)letargs=letargs=Evd.expand_existentialevm(k,args)inletn=matchchopwithNone->0|Somec->cinletl,r=CList.chopn(List.revargs)inList.revrinletargs=letrecauxhypsargsacc=letopenContext.Named.Declarationinmatch(hyps,args)with|LocalAssum_::tlh,c::tla->auxtlhtla(substrec(depth,fixrels)c::acc)|LocalDef_::tlh,_::tla->auxtlhtlaacc|[],[]->acc|_,_->acc(*failwith "subst_evars: invalid argument"*)inauxhypsargs[]inifList.exists(funx->matchEConstr.kindevmxwith|Constr.Reln->Int.List.memnfixrels|_->false)argsthentransparent:=Id.Set.addidstr!transparent;EConstr.mkApp(idfidstr,Array.of_listargs)|Constr.Fix_->EConstr.map_with_bindersevmsuccfixsubstrec(depth,1::fixrels)c|_->EConstr.map_with_bindersevmsuccfixsubstrec(depth,fixrels)cinlett'=substrec(0,[])tin(EConstr.to_constrevmt',!seen,!transparent)(** Substitute variable references in t using de Bruijn indices,
where n binders were passed through. *)letsubst_varsaccnt=letvar_indexid=Util.List.indexId.equalidaccinletrecsubstrecdepthc=matchConstr.kindcwith|Constr.Varv->(tryConstr.mkRel(depth+var_indexv)withNot_found->c)|_->Constr.map_with_binderssuccsubstrecdepthcinsubstrec0t(** Rewrite type of an evar ([ H1 : t1, ... Hn : tn |- concl ])
to a product : forall H1 : t1, ..., forall Hn : tn, concl.
Changes evars and hypothesis references to variable references.
*)letetype_of_evarevmevshypsconcl=letopenContext.Named.Declarationinletrecauxaccn=function|decl::tl->(lett',s,trans=subst_evar_constrevmevsnEConstr.mkVar(Context.Named.Declaration.get_typedecl)inlett''=subst_varsacc0t'inletrest,s',trans'=aux(Context.Named.Declaration.get_iddecl::acc)(succn)tlinlets'=Int.Set.unionss'inlettrans'=Id.Set.uniontranstrans'inmatchdeclwith|LocalDef(id,c,_)->letc',s'',trans''=subst_evar_constrevmevsnEConstr.mkVarcinletc'=subst_varsacc0c'in(Term.mkNamedProd_or_LetIn(LocalDef(EConstr.Unsafe.to_binder_annotid,c',t''))rest,Int.Set.unions''s',Id.Set.uniontrans''trans')|LocalAssum(id,_)->(Term.mkNamedProd_or_LetIn(LocalAssum(EConstr.Unsafe.to_binder_annotid,t''))rest,s',trans'))|[]->lett',s,trans=subst_evar_constrevmevsnEConstr.mkVarconclin(subst_varsacc0t',s,trans)inaux[]0(List.revhyps)lettrunc_named_contextnctx=letlen=List.lengthctxinCList.firstn(len-n)ctxletrecchop_productnt=letpopt=Vars.lift(-1)tinifInt.equaln0thenSometelsematchConstr.kindtwith|Constr.Prod(_,_,b)->ifVars.noccurn1bthenchop_product(predn)(popb)elseNone|_->Noneletevar_dependenciesevmoev=letone_stepdeps=Evar.Set.fold(funevs->letevi=Evd.find_undefinedevmevinletdeps'=Evd.evars_of_filtered_evar_infoevmeviinifEvar.Set.memoevdeps'theninvalid_arg("Ill-formed evar map: cycle detected for evar "^Pp.string_of_ppcmds@@Evar.printoev)elseEvar.Set.uniondeps's)depsdepsinletrecauxdeps=letdeps'=one_stepdepsinifEvar.Set.equaldepsdeps'thendepselseauxdeps'inaux(Evar.Set.singletonoev)letmove_after((id,ev,deps)asobl)l=letrecauxrestdeps=function|((id',_,_)asobl')::tl->letrestdeps'=Evar.Set.removeid'restdepsinifEvar.Set.is_emptyrestdeps'thenobl'::obl::tlelseobl'::auxrestdeps'tl|[]->[obl]inaux(Evar.Set.removeiddeps)lletsort_dependenciesevl=letrecauxlfoundlist=matchlwith|((id,ev,deps)asobl)::tl->letfound'=Evar.Set.unionfound(Evar.Set.singletonid)inifEvar.Set.subsetdepsfound'thenauxtlfound'(obl::list)elseaux(move_afterobltl)foundlist|[]->List.revlistinauxevlEvar.Set.empty[]typeobligation_name_lifter=(Names.Id.t->EConstr.t)->EConstr.t->Constr.tletretrieve_obligationsenvnameevmfs?deps?statustty=(* 'Serialize' the evars *)letnc=Environ.named_contextenvinletnc_len=Context.Named.lengthncinletevm=Evarutil.nf_evar_map_undefinedevminletevl=Evd.undefined_mapevminletevl=matchdepswith|None->evl|Somedeps->Evar.Map.filter(funev_->Evar.Set.memevdeps)evlinletevl=Evar.Map.bindingsevlinletevl=List.map(fun(id,ev)->(id,ev,evar_dependenciesevmid))evlinletsevl=sort_dependenciesevlinletevl=List.map(fun(id,ev,_)->(id,ev))sevlinletevn=leti=ref(-1)inList.rev_map(fun(id,ev)->incri;(id,(!i,Id.of_string(Id.to_stringname^"_obligation_"^string_of_int(succ!i))),ev))evlinletevts=(* Remove existential variables in types and build the corresponding products *)List.fold_right(fun(id,(n,nstr),ev)evs->lethyps=Evd.evar_filtered_contextevinlethyps=trunc_named_contextnc_lenhypsinletevtyp,deps,transp=etype_of_evarevmevshyps(Evd.evar_conclev)inletevtyp,hyps,chop=matchchop_productfsevtypwith|Somet->(t,trunc_named_contextfshyps,fs)|None->(evtyp,hyps,0)inletloc,k=Evd.evar_source(Evd.find_undefinedevmid)inletstatus=matchkwith|Evar_kinds.QuestionMark{Evar_kinds.qm_obligation=o}->o|_->(matchstatuswith|Someo->o|None->Evar_kinds.Define(not(Program.get_proofs_transparency())))inletforce_status,status,chop=matchstatuswith|Evar_kinds.Definetrueasstat->ifnot(Int.equalchopfs)then(true,Evar_kinds.Definefalse,None)else(false,stat,Somechop)|s->(false,s,None)inletinfo={ev_name=(n,nstr);ev_hyps=hyps;ev_status=(force_status,status);ev_chop=chop;ev_src=(loc,k);ev_typ=evtyp;ev_deps=deps;ev_tac=None}in(id,info)::evs)evn[]inlett',_,transparent=(* Substitute evar refs in the term by variables *)subst_evar_constrevmevts0EConstr.mkVartinletty,_,_=subst_evar_constrevmevts0EConstr.mkVartyinletevars=List.map(fun(ev,info)->let{ev_name=_,name;ev_status=force_status,status;ev_src=src;ev_typ=typ;ev_deps=deps;ev_tac=tac}=infoinletforce_status,status=matchstatuswith|Evar_kinds.DefinetruewhenId.Set.memnametransparent->(true,Evar_kinds.Definefalse)|_->(force_status,status)in(name,typ,src,(force_status,status),deps,tac))evtsinletevnames=List.map(fun(ev,info)->(ev,sndinfo.ev_name))evtsinletevmapfc=Util.pi1(subst_evar_constrevmevts0fc)in(Array.of_list(List.revevars),(evnames,evmap),t',ty)