123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351(************************************************************************)(* * The Rocq Prover / The Rocq 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) *)(************************************************************************)moduletypeOrderedType=sigtypetvalcompare:t->t->intendmoduletypeMonadS=sigtype+'atvalreturn:'a->'atval(>>=):'at->('a->'bt)->'btendmoduletypeS=Map.SmoduletypeUExtS=sigincludeCSig.UMapSmoduleSet:CSig.USetSwithtypeelt=keyvalget:key->'at->'avalset:key->'a->'at->'atvalmodify:key->(key->'a->'a)->'at->'atvaldomain:'at->Set.tvalbind:(key->'a)->Set.t->'atvalheight:'at->intvalfilter_range:(key->int)->'at->'atvalfilter_map:(key->'a->'boption)->'at->'bt(* in OCaml 4.11 *)valof_list:(key*'a)list->'atvalsymmetric_diff_fold:(key->'aoption->'aoption->'b->'b)->'at->'at->'b->'bmoduleSmart:sigvalmap:('a->'a)->'at->'atvalmapi:(key->'a->'a)->'at->'atendmoduleMonad(M:MonadS):sigvalfold:(key->'a->'b->'bM.t)->'at->'b->'bM.tvalmapi:(key->'a->'bM.t)->'at->'btM.tendendmoduletypeExtS=sigincludeCSig.MapSmoduleSet:CSig.SetSwithtypeelt=keyincludeUExtSwithtypekey:=keyandtype'at:='atandmoduleSet:=SetmoduleMonad(M:MonadS):sigincludemoduletypeofMonad(M)valfold_left:(key->'a->'b->'bM.t)->'at->'b->'bM.tvalfold_right:(key->'a->'b->'bM.t)->'at->'b->'bM.tendvalfold_left:(key->'a->'b->'b)->'at->'b->'bvalfold_right:(key->'a->'b->'b)->'at->'b->'bvalfold_left_map:(key->'a->'b->'b*'c)->'at->'b->'b*'ctvalfold_right_map:(key->'a->'b->'b*'c)->'at->'b->'b*'ctendmoduleMapExt(M:Map.OrderedType):sigtype'amap='aMap.Make(M).tvalset:M.t->'a->'amap->'amapvalget:M.t->'amap->'avalmodify:M.t->(M.t->'a->'a)->'amap->'amapvaldomain:'amap->Set.Make(M).tvalbind:(M.t->'a)->Set.Make(M).t->'amapvalfold_left:(M.t->'a->'b->'b)->'amap->'b->'bvalfold_right:(M.t->'a->'b->'b)->'amap->'b->'bvalfold_left_map:(M.t->'a->'b->'b*'c)->'amap->'b->'b*'cmapvalfold_right_map:(M.t->'a->'b->'b*'c)->'amap->'b->'b*'cmapvalheight:'amap->intvalfilter_range:(M.t->int)->'amap->'amapvalfilter_map:(M.t->'a->'boption)->'amap->'bmap(* in OCaml 4.11 *)valsymmetric_diff_fold:(M.t->'aoption->'aoption->'b->'b)->'amap->'amap->'b->'bvalof_list:(M.t*'a)list->'amapmoduleSmart:sigvalmap:('a->'a)->'amap->'amapvalmapi:(M.t->'a->'a)->'amap->'amapendmoduleMonad(MS:MonadS):sigvalfold:(M.t->'a->'b->'bMS.t)->'amap->'b->'bMS.tvalfold_left:(M.t->'a->'b->'bMS.t)->'amap->'b->'bMS.tvalfold_right:(M.t->'a->'b->'bMS.t)->'amap->'b->'bMS.tvalmapi:(M.t->'a->'bMS.t)->'amap->'bmapMS.tendend=struct(** This unsafe module is a way to access to the actual implementations of
OCaml sets and maps without reimplementing them ourselves. It is quite
dubious that these implementations will ever be changed... Nonetheless,
if this happens, we can still implement a less clever version of [domain].
*)moduleF=Map.Make(M)type'amap='aF.tmoduleS=Set.Make(M)typeset=S.ttype'a_map=|MEmpty|MNodeof{l:'amap;v:F.key;d:'a;r:'amap;h:int}type_set=|SEmpty|SNodeofset*M.t*set*intletmap_prj:'amap->'a_map=Obj.magicletmap_inj:'a_map->'amap=Obj.magicletset_prj:set->_set=Obj.magicletset_inj:_set->set=Obj.magicletrecsetkv(s:'amap):'amap=matchmap_prjswith|MEmpty->raiseNot_found|MNode{l;v=k';d=v';r;h}->letc=M.comparekk'inifc<0thenletl'=setkvlinifl==l'thenselsemap_inj(MNode{l=l';v=k';d=v';r;h})elseifc=0thenifv'==vthenselsemap_inj(MNode{l;v=k';d=v;r;h})elseletr'=setkvrinifr==r'thenselsemap_inj(MNode{l;v=k';d=v';r=r';h})letrecgetk(s:'amap):'a=matchmap_prjswith|MEmpty->assertfalse|MNode{l;v=k';d=v;r;h}->letc=M.comparekk'inifc<0thengetklelseifc=0thenvelsegetkrletrecmodifykf(s:'amap):'amap=matchmap_prjswith|MEmpty->raiseNot_found|MNode{l;v;d;r;h}->letc=M.comparekvinifc<0thenletl'=modifykflinifl==l'thenselsemap_inj(MNode{l=l';v;d;r;h})elseifc=0thenletd'=fvdinifd'==dthenselsemap_inj(MNode{l;v;d=d';r;h})elseletr'=modifykfrinifr==r'thenselsemap_inj(MNode{l;v;d;r=r';h})letrecdomain(s:'amap):set=matchmap_prjswith|MEmpty->set_injSEmpty|MNode{l;v;r;h;_}->set_inj(SNode(domainl,v,domainr,h))(** This function is essentially identity, but OCaml current stdlib does not
take advantage of the similarity of the two structures, so we introduce
this unsafe loophole. *)letrecbindf(s:set):'amap=matchset_prjswith|SEmpty->map_injMEmpty|SNode(l,k,r,h)->map_inj(MNode{l=bindfl;v=k;d=fk;r=bindfr;h})(** Dual operation of [domain]. *)letrecfold_leftf(s:'amap)accu=matchmap_prjswith|MEmpty->accu|MNode{l;v=k;d=v;r;h}->letaccu=fkv(fold_leftflaccu)infold_leftfracculetrecfold_rightf(s:'amap)accu=matchmap_prjswith|MEmpty->accu|MNode{l;v=k;d=v;r;h}->letaccu=fkv(fold_rightfraccu)infold_rightflacculetrecfold_left_mapf(s:'amap)accu=matchmap_prjswith|MEmpty->accu,map_injMEmpty|MNode{l;v=k;d=v;r;h}->letaccu,l=fold_left_mapflaccuinletaccu,v=fkvaccuinletaccu,r=fold_left_mapfraccuinaccu,map_inj(MNode{l;v=k;d=v;r;h})letrecfold_right_mapf(s:'amap)accu=matchmap_prjswith|MEmpty->accu,map_injMEmpty|MNode{l;v=k;d=v;r;h}->letaccu,r=fold_right_mapfraccuinletaccu,v=fkvaccuinletaccu,l=fold_right_mapflaccuinaccu,map_inj(MNode{l;v=k;d=v;r;h})letheights=matchmap_prjswith|MEmpty->0|MNode{h;_}->h(* Filter based on a range *)letfilter_rangein_rangem=letrecauxm=function|MEmpty->m|MNode{l;v;d;r;_}->letvr=in_rangevin(* the range is below the current value *)ifvr<0thenauxm(map_prjl)(* the range is above the current value *)elseifvr>0thenauxm(map_prjr)(* The current value is in the range *)elseletm=auxm(map_prjl)inletm=auxm(map_prjr)inF.addvdminauxF.empty(map_prjm)letfilter_mapfm=(* Waiting for the optimized version in OCaml >= 4.11 *)F.fold(funkvaccu->matchfkvwith|None->accu|Somev'->F.addkv'accu)mF.emptyletof_listl=letfoldaccu(x,v)=F.addxvaccuinList.fold_leftfoldF.emptyltype'asequenced=|End|MoreofM.t*'a*'aF.t*'asequencedletrecseq_consmrest=matchmap_prjmwith|MEmpty->rest|MNode{l;v;d;r;_}->seq_consl(More(v,d,r,rest))letrecfold_seqfacc=function|End->acc|More(k,v,m,r)->fkv@@fold_seqf(F.foldfmacc)rletmove_to_acc(m,acc)=matchmap_prjmwith|MEmpty->assertfalse|MNode{l;v;d;r;_}->l,More(v,d,r,acc)letrecsymmetric_cons((lm,la)asl)((rm,ra)asr)=iflm==rmthenla,raelseletlh=heightlminletrh=heightrminiflh==rhthensymmetric_cons(move_to_accl)(move_to_accr)elseiflh<rhthensymmetric_consl(move_to_accr)elsesymmetric_cons(move_to_accl)rletsymmetric_diff_foldflmrmacc=letrecauxsacc=matchswith|End,rs->fold_seq(funkv->fkNone(Somev))accrs|ls,End->fold_seq(funkv->fk(Somev)None)accls|(More(kl,vl,tl,rl)asls),(More(kr,vr,tr,rr)asrs)->letcmp=M.compareklkrinifcmp==0thenletrem=aux(symmetric_cons(tl,rl)(tr,rr))accinifvl==vrthenremelsefkl(Somevl)(Somevr)remelseifcmp<0thenfkl(Somevl)None@@aux(seq_constlrl,rs)accelsefkrNone(Somevr)@@aux(ls,seq_constrrr)accinaux(symmetric_cons(lm,End)(rm,End))accmoduleSmart=structletrecmapf(s:'amap)=matchmap_prjswith|MEmpty->map_injMEmpty|MNode{l;v=k;d=v;r;h}->letl'=mapflinletr'=mapfrinletv'=fvinifl==l'&&r==r'&&v==v'thenselsemap_inj(MNode{l=l';v=k;d=v';r=r';h})letrecmapif(s:'amap)=matchmap_prjswith|MEmpty->map_injMEmpty|MNode{l;v=k;d=v;r;h}->letl'=mapiflinletr'=mapifrinletv'=fkvinifl==l'&&r==r'&&v==v'thenselsemap_inj(MNode{l=l';v=k;d=v';r=r';h})endmoduleMonad(M:MonadS)=structopenMletrecfold_leftfsaccu=matchmap_prjswith|MEmpty->returnaccu|MNode{l;v=k;d=v;r;h}->fold_leftflaccu>>=funaccu->fkvaccu>>=funaccu->fold_leftfracculetrecfold_rightfsaccu=matchmap_prjswith|MEmpty->returnaccu|MNode{l;v=k;d=v;r;h}->fold_rightfraccu>>=funaccu->fkvaccu>>=funaccu->fold_rightflacculetfold=fold_leftletrecmapifs=matchmap_prjswith|MEmpty->return(map_injMEmpty)|MNode{l;v=k;d=v;r;h}->mapifl>>=funl->mapifr>>=funr->fkv>>=funv->return(map_inj(MNode{l;v=k;d=v;r;h}))endendmoduleMake(M:Map.OrderedType)=structincludeMap.Make(M)includeMapExt(M)end