123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348(************************************************************************)(* * 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) *)(************************************************************************)openHipatternopenNamesopenConstropenEConstropenVarsopenUtilopenDeclarationsmoduleRelDecl=Context.Rel.Declarationtypeflags={qflag:bool;reds:RedFlags.reds;}let(=?)fgi1i2j1j2=letc=fi1i2inifInt.equalc0thengj1j2elseclet(==?)fghi1i2j1j2k1k2=letc=fgi1i2j1j2inifInt.equalc0thenhk1k2elsectype('a,'b)sum=Leftof'a|Rightof'btypecounter=bool->metavariablemoduleEnv:sigtypettypeuidvalempty:tvaladd:flags->Environ.env->Evd.evar_map->EConstr.t->t->t*uidvalfind:uid->t->EConstr.tvalrepr:uid->intvalhole:uidend=structmoduleCM=Map.Make(Constr)typet={max_uid:int;repr:intCM.t;data:Constr.tInt.Map.t;}typeuid=intletempty={max_uid=1;(* uid 0 is reserved for Meta 1 *)repr=CM.singleton(Constr.mkMeta1)0;data=Int.Map.singleton0(Constr.mkMeta1);}lethole=0(* This is nonsense, but backwards compatibility mandates it *)letaddflagsenvsigmace=letc=Reductionops.clos_norm_flagsflags.redsenvsigmacinletc=EConstr.to_constr~abort_on_undefined_evars:falsesigmacinmatchCM.find_optce.reprwith|Somei->e,i|None->leti=e.max_uidinlete={max_uid=i+1;repr=CM.addcie.repr;data=Int.Map.addice.data;}ine,iletfindide=EConstr.of_constr(Int.Map.findide.data)letreprid=idendtypeatom={atom:Env.uid}letrepr_atomstatea=Env.finda.atomstateletcompare_atoma1a2=Int.compare(Env.repra1.atom)(Env.repra2.atom)letmeta_succm=m+1letrecnb_prod_afternc=matchConstr.kindcwith|Prod(_,_,b)->ifn>0thennb_prod_after(n-1)belse1+(nb_prod_after0b)|_->0letconstruct_nhypsenvind=letind=on_sndEInstance.makeindinletnparams=(fst(Global.lookup_inductive(fstind))).mind_nparamsinletconstr_types=Inductiveops.arities_of_constructorsenvindinlethypc=nb_prod_afternparams(EConstr.Unsafe.to_constrc)inArray.maphypconstr_types(* indhyps builds the array of arrays of constructor hyps for (ind largs)*)letind_hypsenvsigmanevarindlargs=letind=on_sndEInstance.makeindinlettypes=Inductiveops.arities_of_constructorsenvindinletmyhypst=letnparam_decls=Context.Rel.length(fst(Global.lookup_inductive(fstind))).mind_params_ctxtinlett1=Termops.prod_applist_declssigmanparam_declstlargsinlett2=snd(decompose_prod_n_declssigmanevart1)infst(decompose_prod_declssigmat2)inArray.mapmyhypstypesletspecial_whd~flagsenvsigmat=Reductionops.clos_whd_flagsflags.redsenvsigmattypekind_of_formula=Arrowofconstr*constr|Falseofpinductive*constrlist|Andofpinductive*constrlist*bool|Orofpinductive*constrlist*bool|Existsofpinductive*constrlist|Forallofconstr*constr|AtomofEConstr.tletpopt=Vars.lift(-1)tletfresh_atom~flagsstateenvsigmaatm=letst,uid=Env.addflagsenvsigmaatm!stateinlet()=state:=stin{atom=uid}lethole_atom={atom=Env.hole}letkind_of_formula~flagsenvsigmaterm=letcciterm=special_whd~flagsenvsigmaterminmatchmatch_with_imp_termenvsigmaccitermwithSome(a,b)->Arrow(a,popb)|_->matchmatch_with_forall_termenvsigmaccitermwithSome(_,a,b)->Forall(a,b)|_->matchmatch_with_nodep_indenvsigmaccitermwithSome(i,l,n)->letind,u=EConstr.destIndsigmaiinletu=EConstr.EInstance.kindsigmauinlet(mib,mip)=Global.lookup_inductiveindinletnconstr=Array.lengthmip.mind_consnamesinifInt.equalnconstr0thenFalse((ind,u),l)elselethas_realargs=(n>0)inletis_trivial=letis_constantn=Int.equaln0inArray.existsis_constantmip.mind_consnrealargsinifInductiveops.mis_is_recursive(ind,mib,mip)||(has_realargs&¬is_trivial)thenAtomccitermelseifInt.equalnconstr1thenAnd((ind,u),l,is_trivial)elseOr((ind,u),l,is_trivial)|_->matchmatch_with_sigma_typeenvsigmaccitermwithSome(i,l)->let(ind,u)=EConstr.destIndsigmaiinletu=EConstr.EInstance.kindsigmauinExists((ind,u),l)|_->Atomccitermtypeatoms={positive:atomlist;negative:atomlist}type_side=|Hyp:bool->[`Hyp]side(* true if treated as hint *)|Concl:[`Goal]sideletno_atoms=(false,{positive=[];negative=[]})letbuild_atoms(typea)~flagsstateenvsigmametagen(side:aside)cciterm=lettrivial=reffalseandpositive=ref[]andnegative=ref[]inletrecbuild_recsubstpolaritycciterm=matchkind_of_formula~flagsenvsigmaccitermwithFalse(_,_)->ifnotpolaritythentrivial:=true|Arrow(a,b)->build_recsubst(notpolarity)a;build_recsubstpolarityb|And(i,l,b)|Or(i,l,b)->ifbthenbeginletunsigned=fresh_atom~flagsstateenvsigma(substnlsubst0cciterm)inifpolaritythenpositive:=unsigned::!positiveelsenegative:=unsigned::!negativeend;letv=ind_hypsenvsigma0ilinletgi_decl=build_recsubstpolarity(lifti(RelDecl.get_typedecl))inletfl=List.fold_left_ig(1-(List.lengthl))()linifpolarity&&(* we have a constant constructor *)Array.exists(function[]->true|_->false)vthentrivial:=true;Array.iterfv|Exists(i,l)->letvar=mkMeta(metagentrue)inletv=(ind_hypsenvsigma1il).(0)inletgi_decl=build_rec(var::subst)polarity(lifti(RelDecl.get_typedecl))inList.fold_left_ig(2-(List.lengthl))()v|Forall(_,b)->letvar=mkMeta(metagentrue)inbuild_rec(var::subst)polarityb|Atomt->letunsigned=fresh_atom~flagsstateenvsigma(substnlsubst0t)inifnot(isMetasigma(repr_atom!stateunsigned))then(* discarding wildcard atoms *)ifpolaritythenpositive:=unsigned::!positiveelsenegative:=unsigned::!negativeinbeginmatchsidewithConcl->build_rec[]truecciterm|Hypfalse->build_rec[]falsecciterm|Hyptrue->letrels,head=decompose_prodsigmacciterminletsubst=List.rev_map(fun_->mkMeta(metagentrue))relsinbuild_recsubstfalsehead;trivial:=false(* special for hints *)end;(!trivial,{positive=!positive;negative=!negative})typeright_pattern=Rarrow|Rand|Ror|Rfalse|Rforall|Rexistsofmetavariable*constr*booltypeleft_arrow_pattern=LLatom|LLfalseofpinductive*constrlist|LLandofpinductive*constrlist|LLorofpinductive*constrlist|LLforallofconstr|LLexistsofpinductive*constrlist|LLarrowofconstr*constr*constrtypeleft_pattern=Lfalse|Landofpinductive|Lorofpinductive|Lforallofmetavariable*constr*bool|Lexistsofpinductive|LAofatom*left_arrow_patterntype_identifier=|GoalId:[`Goal]identifier|FormulaId:GlobRef.t->[`Hyp]identifierletgoal_id=GoalIdletformula_idenvgr=FormulaId(Environ.QGlobRef.canonizeenvgr)type_pattern=|LeftPattern:left_pattern->[`Hyp]pattern|RightPattern:right_pattern->[`Goal]patterntype'at={id:'aidentifier;constr:atom;pat:'apattern;atoms:atoms;}typeany_formula=AnyFormula:'at->any_formulaexceptionIs_atomofEConstr.tletbuild_formula(typea)~flagsstateenvsigma(side:aside)(nam:aidentifier)typmetagen:Env.t*(at,atom)sum=tryletstate=refstateinletm=meta_succ(metagenfalse)inlettrivial,atoms=ifflags.qflagthenbuild_atoms~flagsstateenvsigmametagensidetypelseno_atomsinletpattern:apattern=matchsidewithConcl->letpat=matchkind_of_formula~flagsenvsigmatypwithFalse(_,_)->Rfalse|Atoma->raise(Is_atoma)|And(_,_,_)->Rand|Or(_,_,_)->Ror|Exists(i,l)->letd=RelDecl.get_type(List.last(ind_hypsenvsigma0il).(0))inRexists(m,d,trivial)|Forall(_,a)->Rforall|Arrow(a,b)->RarrowinRightPatternpat|Hyp_->letpat=matchkind_of_formula~flagsenvsigmatypwithFalse(i,_)->Lfalse|Atoma->raise(Is_atoma)|And(i,_,b)->ifbthenraise(Is_atomtyp)elseLandi|Or(i,_,b)->ifbthenraise(Is_atomtyp)elseLori|Exists(ind,_)->Lexistsind|Forall(d,_)->Lforall(m,d,trivial)|Arrow(a,b)->letnfa=fresh_atom~flagsstateenvsigmaainLA(nfa,matchkind_of_formula~flagsenvsigmaawithFalse(i,l)->LLfalse(i,l)|Atomt->LLatom|And(i,l,_)->LLand(i,l)|Or(i,l,_)->LLor(i,l)|Arrow(a,c)->LLarrow(a,c,b)|Exists(i,l)->LLexists(i,l)|Forall(_,_)->LLforalla)inLeftPatternpatinlettyp=fresh_atom~flagsstateenvsigmatypin!state,Left{id=nam;constr=typ;pat=pattern;atoms=atoms}withIs_atoma->letstate=refstateinleta=fresh_atom~flagsstateenvsigmaain!state,Righta(* already in nf *)