123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189(************************************************************************)(* * 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) *)(************************************************************************)openCErrorsopenUtilopenNamesopenNameopsopenTermopsopenConstropenContextopenEvarutilopenTactypes(** {6 Evar-based clauses} *)typehole={hole_evar:EConstr.constr;hole_type:EConstr.types;hole_deps:bool;hole_name:Name.t;hole_evar_key:Evar.t;}typeclause={cl_holes:holelist;cl_concl:EConstr.types;}letqhyp_eqh1h2=matchh1,h2with|NamedHypn1,NamedHypn2->lident_eqn1n2|AnonHypi1,AnonHypi2->Int.equali1i2|_->falseletcheck_bindingsbl=matchList.duplicatesqhyp_eq(List.map(fun{CAst.v=x}->fstx)bl)with|NamedHyps::_->user_err?loc:s.CAst.locPp.(str"The variable "++Id.prints.CAst.v++str" occurs more than once in binding list.");|AnonHypn::_->user_errPp.(str"The position "++intn++str" occurs more than once in binding list.")|[]->()letexplain_no_such_bound_variablemvl{CAst.v=id;loc}=letopenPpinletexpl=matchmvlwith|[]->str"(no bound variables at all in the expression)."|[id]->str"(possible name is: "++Id.printid++str")."|_->str"(possible names are: "++pr_enumId.printmvl++str")."inuser_err?loc(str"No such bound variable "++Id.printid++spc()++expl)leterror_not_right_number_missing_argumentsn=user_errPp.(strbrk"Not the right number of missing arguments (expected "++intn++str").")letmake_evar_clauseenvsigma?lent=letopenEConstrinletopenVarsinletbound=matchlenwith|None->-1|Somen->assert(0<=n);ninletrecclrec(sigma,holes)instnt=ifn=0then(sigma,holes,t)elsematchEConstr.kindsigmatwith|Cast(t,_,_)->clrec(sigma,holes)instnt|Prod(na,t1,t2)->(* Share the evar instances as we are living in the same context *)letinst,ctx,args,subst=matchinstwith|None->(* Dummy type *)lethypnaming=RenameExistingBut(VarSet.variables(Global.env()))inletctx,_,args,subst=push_rel_context_to_named_context~hypnamingenvsigmamkPropinSome(ctx,args,subst),ctx,args,subst|Some(ctx,args,subst)->inst,ctx,args,substinlet(sigma,evk)=new_pure_evar~typeclass_candidate:falsectxsigma(csubst_substsigmasubstt1)inletev=mkEvar(evk,args)inletdep=not(noccurnsigma1t2)inlethole={hole_evar=ev;hole_type=t1;hole_deps=dep;(* We fix it later *)hole_name=na.binder_name;hole_evar_key=evk;}inlett2=subst1evt2inclrec(sigma,hole::holes)inst(predn)t2|LetIn(na,b,_,t)->clrec(sigma,holes)instn(subst1bt)|_->(sigma,holes,t)inlet(sigma,holes,t)=clrec(sigma,[])Noneboundtinletholes=List.revholesinletclause={cl_concl=t;cl_holes=holes}in(sigma,clause)letevar_with_nameholes({CAst.v=id}aslid)=letmaph=matchh.hole_namewith|Anonymous->None|Nameid'->ifId.equalidid'thenSomehelseNoneinlethole=List.map_filtermapholesinmatchholewith|[]->letfoldhaccu=matchh.hole_namewith|Anonymous->accu|Nameid->id::accuinletmvl=List.fold_rightfoldholes[]inexplain_no_such_bound_variablemvllid|h::_->h.hole_evarletevar_of_binderholes=function|NamedHyps->evar_with_nameholess|AnonHypn->tryletnondeps=List.filter(funhole->nothole.hole_deps)holesinleth=List.nthnondeps(predn)inh.hole_evarwithewhenCErrors.noncriticale->user_errPp.(str"No such binder.")letdefine_with_typesigmaenvevc=letopenEConstrinlett=Retyping.get_type_ofenvsigmaevinletty=Retyping.get_type_ofenvsigmacinletj=Environ.make_judgectyinlet(sigma,j,_trace)=Coercion.inh_conv_coerce_to~program_mode:false~resolve_tc:trueenvsigmajtinlet(ev,_)=destEvarsigmaevinletsigma=Evd.defineevj.Environ.uj_valsigmainsigmaletsolve_evar_clauseenvsigmahyp_onlyclause=function|NoBindings->sigma|ImplicitBindingslargs->letopenEConstrinletfoldholesh=ifh.hole_depsthen(* Some subsequent term uses the hole *)let(ev,_)=destEvarsigmah.hole_evarinletis_dephole=occur_evarsigmaevhole.hole_typeinletin_hyp=List.existsis_depholesinletin_ccl=occur_evarsigmaevclause.cl_conclinletdep=ifhyp_onlythenin_hyp&¬in_cclelsein_hyp||in_cclinleth={hwithhole_deps=dep}inh::holeselse(* The hole does not occur anywhere *)h::holesinletholes=List.fold_leftfold[](List.revclause.cl_holes)inletmaph=ifh.hole_depsthenSomeh.hole_evarelseNoneinletevs=List.map_filtermapholesinletlen=List.lengthevsinifInt.equallen(List.lengthlargs)thenletfoldsigmaevarg=define_with_typesigmaenvevarginletsigma=List.fold_left2foldsigmaevslargsinsigmaelseerror_not_right_number_missing_argumentslen|ExplicitBindingslbind->let()=check_bindingslbindinletfoldsigma{CAst.v=(binder,c)}=letev=evar_of_binderclause.cl_holesbinderindefine_with_typesigmaenvevcinletsigma=List.fold_leftfoldsigmalbindinsigmaletcheck_evar_clauseenvsigmasigma'eq_clause=letfh=ifh.hole_depsthenSomeh.hole_evar_keyelseNoneinmatchTacticals.check_evar_listenvsigma'(Evar.Set.of_list(List.map_filterfeq_clause.cl_holes))sigmawith|[]->()|evkl->letfilterh=ifList.exists(Evar.equalh.hole_evar_key)evklthenSomeh.hole_nameelseNoneinletbindings=List.map_filterfiltereq_clause.cl_holesinLoc.raise(Logic.RefinerError(env,sigma,UnresolvedBindingsbindings))