123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166(************************************************************************)(* * 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) *)(************************************************************************)openUtilopenConstropenEConstropenVarsopenTermopsopenReductionopsexceptionUFAILofconstr*constr(*
RIGID-only Martelli-Montanari style unification for CLOSED terms
I repeat : t1 and t2 must NOT have ANY free deBruijn
sigma is kept normal with respect to itself but is lazily applied
to the equation set. Raises UFAIL with a pair of terms
*)letpopt=Vars.lift(-1)tletsubst_metasubstt=letsubst=List.map(fun(m,c)->(m,EConstr.Unsafe.to_constrc))substinEConstr.of_constr(subst_metasubst(EConstr.Unsafe.to_constrt))letunifenvevdt1t2=letbige=Queue.create()andsigma=ref[]inletbindit=sigma:=(i,t)::(List.map(function(n,tn)->(n,subst_meta[i,t]tn))!sigma)inletrechead_reducet=(* forbids non-sigma-normal meta in head position*)matchEConstr.kindevdtwithMetai->(tryhead_reduce(Int.List.associ!sigma)withNot_found->t)|_->tinQueue.add(t1,t2)bige;trywhiletruedolett1,t2=Queue.takebigeinletnt1=head_reduce(whd_betaiotazetaenvevdt1)andnt2=head_reduce(whd_betaiotazetaenvevdt2)inmatch(EConstr.kindevdnt1),(EConstr.kindevdnt2)withMetai,Metaj->ifnot(Int.equalij)thenifi<jthenbindjnt1elsebindint2|Metai,_->lett=subst_meta!sigmant2inifInt.Set.is_empty(free_relsevdt)&¬(occur_metavariableevdit)thenbinditelseraise(UFAIL(nt1,nt2))|_,Metai->lett=subst_meta!sigmant1inifInt.Set.is_empty(free_relsevdt)&¬(occur_metavariableevdit)thenbinditelseraise(UFAIL(nt1,nt2))|Cast(_,_,_),_->Queue.add(strip_outer_castevdnt1,nt2)bige|_,Cast(_,_,_)->Queue.add(nt1,strip_outer_castevdnt2)bige|(Prod(_,a,b),Prod(_,c,d))|(Lambda(_,a,b),Lambda(_,c,d))->Queue.add(a,c)bige;Queue.add(popb,popd)bige|Case(cia,ua,pmsa,pa,iva,ca,va),Case(cib,ub,pmsb,pb,ivb,cb,vb)->letenv=Global.env()inlet(cia,(pa,_),iva,ca,va)=EConstr.expand_caseenvevd(cia,ua,pmsa,pa,iva,ca,va)inlet(cib,(pb,_),iva,cb,vb)=EConstr.expand_caseenvevd(cib,ub,pmsb,pb,ivb,cb,vb)inQueue.add(pa,pb)bige;Queue.add(ca,cb)bige;letl=Array.lengthvainifnot(Int.equall(Array.lengthvb))thenraise(UFAIL(nt1,nt2))elsefori=0tol-1doQueue.add(va.(i),vb.(i))bigedone|App(ha,va),App(hb,vb)->Queue.add(ha,hb)bige;letl=Array.lengthvainifnot(Int.equall(Array.lengthvb))thenraise(UFAIL(nt1,nt2))elsefori=0tol-1doQueue.add(va.(i),vb.(i))bigedone|_->ifnot(eq_constr_nounivsevdnt1nt2)thenraise(UFAIL(nt1,nt2))done;assertfalse(* this place is unreachable but needed for the sake of typing *)withQueue.Empty->!sigmaletvalueevdit=letaddxy=ifx<0thenyelseify<0thenxelsex+yinletrecvauxterm=ifisMetaevdterm&&Int.equal(destMetaevdterm)ithen0elseletfvt=addv(vauxt)inletvr=EConstr.foldevdf(-1)terminifvr<0then-1elsevr+1invauxtmoduleItem=structtypet=int*constrletrepri=iletcompare(i1,c1)(i2,c2)=letc=Int.comparei1i2inifc=0thenConstr.compare(EConstr.Unsafe.to_constrc1)(EConstr.Unsafe.to_constrc2)elsecletis_ground(m,_)=Int.equalm0endtypeinstance=Realof(int*constr)*int|Phantomofconstrletmk_rel_instevdt=letnew_rel=ref1inletrel_env=ref[]inletrecrenum_recdt=matchEConstr.kindevdtwithMetan->(trymkRel(d+(Int.List.assocn!rel_env))withNot_found->letm=!new_relinincrnew_rel;rel_env:=(n,m)::!rel_env;mkRel(m+d))|_->EConstr.map_with_bindersevdsuccrenum_recdtinletnt=renum_rec0tin(!new_rel-1,nt)letunif_atomsstateenvevdidomt1t2=trylett1=Formula.repr_atomstatet1inlett=Int.List.associ(unifenvevdt1(Formula.repr_atomstatet2))inifisMetaevdtthenSome(Phantomdom)elseSome(Real(mk_rel_instevdt,valueevdit1))withUFAIL(_,_)->None|Not_found->Some(Phantomdom)letrenum_metas_fromknt=(* requires n = max (free_rels t) *)letl=List.initn(funi->mkMeta(k+i))insubstlltletmore_generalenvevd(m1,t1)(m2,t2)=m1>m2&&letmt1=renum_metas_from0m1t1andmt2=renum_metas_fromm1m2t2intryletsigma=unifenvevdmt1mt2inletp(n,t)=n<m1||isMetaevdtinList.for_allpsigmawithUFAIL(_,_)->false