123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966(** Map domains. *)modulePretty=GoblintCil.PrettyopenPrettymoduletypePS=sigincludePrintable.Stypekey(** The type of the map keys. *)typevalue(** The type of the values. *)valadd:key->value->t->tvalremove:key->t->tvalfind:key->t->valuevalfind_opt:key->t->valueoptionvalmem:key->t->boolvaliter:(key->value->unit)->t->unitvalmap:(value->value)->t->tvalfilter:(key->value->bool)->t->tvalmapi:(key->value->value)->t->tvalfold:(key->value->'a->'a)->t->'a->'avaladd_list:(key*value)list->t->tvaladd_list_set:keylist->value->t->tvaladd_list_fun:keylist->(key->value)->t->tvalfor_all:(key->value->bool)->t->boolvalreflexive_subset_domain_for_all2:(value->value->bool)->t->t->boolvalidempotent_inter:(value->value->value)->t->t->tvalnonidempotent_inter:(value->value->value)->t->t->tvalidempotent_inter_filter:(value->value->valueoption)->t->t->tvalnonidempotent_inter_filter:(value->value->valueoption)->t->t->tvalidempotent_union:(value->value->value)->t->t->tvalnonidempotent_union:(value->value->value)->t->t->tvaldifference:(value->value->valueoption)->t->t->tvalcardinal:t->intvalchoose:t->key*valuevalsingleton:key->value->tvalempty:unit->tvalis_empty:t->boolvalexists:(key->value->bool)->t->boolvalbindings:t->(key*value)listendmoduletypeS=sigincludePSincludeLattice.Swithtypet:=tvalwiden_with_fct:(value->value->value)->t->t->t(* Widen using a custom widening function for value rather than the default one for value *)valjoin_with_fct:(value->value->value)->t->t->t(* Join using a custom join function for value rather than the default one for value *)valleq_with_fct:(value->value->bool)->t->t->bool(* Leq test using a custom leq function for value rather than the default one provided for value *)end(** Subsignature of {!S}, which is sufficient for {!Print}. *)moduletypeBindings=sigtypettypekeytypevaluevalfold:(key->value->'a->'a)->t->'a->'avaliter:(key->value->unit)->t->unitend(** Reusable output definitions for maps. *)modulePrint(D:Printable.S)(R:Printable.S)(M:Bindingswithtypekey=D.tandtypevalue=R.t)=structletpretty()map=letdoc=M.fold(funkvacc->acc++dprintf"%a ->@?@[%a@]\n"D.prettykR.prettyv)mapnilinifdoc=Pretty.nilthentext"{}"elsedprintf"@[{\n @[%a@]}@]"Pretty.insertdocletshowmap=GobPretty.sprintprettymapletprintXmlfmap=BatPrintf.fprintff"<value>\n<map>\n";M.iter(funkv->BatPrintf.fprintff"<key>\n%s</key>\n%a"(XmlUtil.escape(D.showk))R.printXmlv)map;BatPrintf.fprintff"</map>\n</value>\n"letto_yojsonmap=letl=M.fold(funkvacc->(D.showk,R.to_yojsonv)::acc)map[]in`AssoclendmoduletypeGroupable=sigincludePrintable.Stypegroup(* use [@@deriving show { with_path = false }] *)valcompare_group:group->group->intvalshow_group:group->stringvalto_group:t->groupend(** Reusable output definitions for maps with key grouping. *)modulePrintGroupable(D:Groupable)(R:Printable.S)(M:Bindingswithtypekey=D.tandtypevalue=R.t)=structincludePrint(D)(R)(M)moduleGroup=structtypet=D.group[@@derivingord]endmoduleGroupMap=Map.Make(Group)letpretty()mapping=letgroups=M.fold(funkvacc->GroupMap.update(D.to_groupk)(fundoc->letdoc=Option.valuedoc~default:Pretty.nilinletdoc'=doc++dprintf"%a ->@? @[%a@]\n"D.prettykR.prettyvinSomedoc')acc)mappingGroupMap.emptyinletpretty_groups()=GroupMap.fold(fungroupdocacc->acc++dprintf"@[%s {\n @[%a@]}@]\n"(D.show_groupgroup)Pretty.insertdoc)groupsnilindprintf"@[{\n @[%t@]}@]"pretty_groupsletshowmap=GobPretty.sprintprettymap(* TODO: groups in XML, JSON? *)endmoduletypeMapS=sigtypekeytype'atvalempty:'atvalis_empty:'at->boolvalmem:key->'at->boolvaladd:key->'a->'at->'atvalsingleton:key->'a->'atvalremove:key->'at->'atvalidempotent_union:('a->'a->'a)->'at->'at->'atvalnonidempotent_union:('a->'a->'a)->'at->'at->'atvalidempotent_inter:('a->'a->'a)->'at->'at->'atvalnonidempotent_inter:('a->'a->'a)->'at->'at->'atvalidempotent_inter_filter:('a->'a->'aoption)->'at->'at->'atvalnonidempotent_inter_filter:('a->'a->'aoption)->'at->'at->'atvaldifference:('a->'a->'aoption)->'at->'at->'atvalreflexive_compare:('a->'a->int)->'at->'at->intvalreflexive_equal:('a->'a->bool)->'at->'at->boolvalreflexive_subset_domain_for_all2:('a->'a->bool)->'at->'at->boolvaliter:(key->'a->unit)->'at->unitvalfold:(key->'a->'b->'b)->'at->'b->'bvalfor_all:(key->'a->bool)->'at->boolvalexists:(key->'a->bool)->'at->boolvalfilter:(key->'a->bool)->'at->'atvalcardinal:'at->intvalbindings:'at->(key*'a)listvalchoose:'at->(key*'a)valfind:key->'at->'avalfind_opt:key->'at->'aoptionvalmap:('a->'a)->'at->'atvalmapi:(key->'a->'a)->'at->'atendmoduleStdMap(K:Map.OrderedType):MapSwithtypekey=K.t=structincludeMap.Make(K)letreflexive_equalfxy=x==y||equalfxyletreflexive_comparefxy=ifx==ythen0elsecomparefxyletreflexive_subset_domain_for_all2fm1m2=(* For each key-value in m1, the same key must be in m2 with a geq value: *)letpkeyvalue=tryfvalue(findkeym2)withNot_found->falseinm1==m2||for_allpm1letnonidempotent_unionop=letfkv1v2=matchv1,v2with|Somev1,Somev2->Some(opv1v2)|Some_,_->v1|_,Some_->v2|_->Noneinmergefletidempotent_unionfm1m2=ifm1==m2thenm1elsenonidempotent_unionfm1m2letnonidempotent_interop=(* Similar to the previous, except we ignore elements that only occur in one
* of the mappings, so we start from an empty map *)letfkv1v2=matchv1,v2with|Somev1,Somev2->Some(opv1v2)|_->Noneinmergefletidempotent_interfm1m2=ifm1==m2thenm1elsenonidempotent_interfm1m2letnonidempotent_inter_filterop=letfkv1v2=matchv1,v2with|Somev1,Somev2->opv1v2|_->Noneinmergefletidempotent_inter_filterfm1m2=ifm1==m2thenm1elsenonidempotent_inter_filterfm1m2letdifferencef=merge(fun_v1v2->matchv1,v2with|Somev1,Somev2->fv1v2|Some_,None->v1|None,_->None)endmodulePatriciaMap(K:PatriciaTree.KEY):MapSwithtypekey=K.t=structincludePatriciaTree.MakeMap(K)(* The following intentionally do not use [(fun _ -> f)] to avoid extra closure allocations and applications from partial application. *)(* TODO: Benchmark this theory. *)letidempotent_unionf=idempotent_union(fun_vv'->fvv')letnonidempotent_unionf=nonidempotent_union(fun_vv'->fvv')letidempotent_interf=idempotent_inter(fun_vv'->fvv')letnonidempotent_interf=nonidempotent_inter_no_share(fun_vv'->fvv')letidempotent_inter_filterf=idempotent_inter_filter(fun_vv'->fvv')letnonidempotent_inter_filterf=nonidempotent_inter_filter_no_share(fun_vv'->fvv')letdifferencef=difference(fun_vv'->fvv')letreflexive_subset_domain_for_all2f=reflexive_subset_domain_for_all2(fun_vv'->fvv')letexistsfm=not(for_all(funkv->not(fkv))m)letbindings=to_listletchoose=unsigned_min_bindingendmoduleGenPMap(Domain:Printable.S)(M:MapSwithtypekey=Domain.t)(Range:Lattice.S):PSwithtypekey=Domain.tandtypevalue=Range.t=structincludePrintable.StdincludeMtypekey=Domain.ttypevalue=Range.ttypet=Range.tM.t(* key -> value mapping *)letname()="map"letequal=reflexive_equalRange.equalletcompare=reflexive_compareRange.comparelethashxs=fold(funkva->a+(Domain.hashk*Range.hashv))xs0letempty()=M.emptyletadd_listkeyvaluesm=List.fold_left(funacc(key,value)->addkeyvalueacc)mkeyvaluesletadd_list_setkeysvaluem=List.fold_left(funacckey->addkeyvalueacc)mkeysletadd_list_funkeysfm=List.fold_left(funacckey->addkey(fkey)acc)mkeysincludePrint(Domain)(Range)(structtypenonrect=ttypenonreckey=keytypenonrecvalue=valueletfold=foldletiter=iterend)(* uncomment to easily check pretty's grouping during a normal run, e.g. ./regtest 01 01: *)(* let add k v m = let _ = Logs.debug "%a" pretty m in M.add k v m *)letarbitrary()=QCheck.alwaysM.empty(* S TODO: non-empty map *)letreliftm=M.fold(funkvacc->M.add(Domain.reliftk)(Range.reliftv)acc)mM.emptyend(* TODO: why is HashCached.hash significantly slower as a functor compared to being inlined into PMap? *)moduleHashCached(M:S):Swithtypekey=M.keyandtypevalue=M.value=structincludeLattice.HashCached(M)typekey=M.keytypevalue=M.valueletaddkv=lift_f'(M.addkv)letremovek=lift_f'(M.removek)letfindk=lift_f(M.findk)letfind_optk=lift_f(M.find_optk)letmemk=lift_f(M.memk)letiterf=lift_f(M.iterf)letmapf=lift_f'(M.mapf)letmapif=lift_f'(M.mapif)letfoldfxa=M.foldf(unliftx)aletfilterf=lift_f'(M.filterf)letfor_allf=lift_f(M.for_allf)letcardinal=lift_fM.cardinalletchoose=lift_fM.chooseletsingletonkv=lift@@M.singletonkvletempty()=lift@@M.empty()letis_empty=lift_fM.is_emptyletexistsp=lift_f(M.existsp)letbindings=lift_fM.bindingsletadd_listkeyvalues=lift_f'(M.add_listkeyvalues)letadd_list_setkeysvalue=lift_f'(M.add_list_setkeysvalue)letadd_list_funkeysf=lift_f'(M.add_list_funkeysf)letidempotent_unionop=lift_f2'(M.idempotent_unionop)letnonidempotent_unionop=lift_f2'(M.nonidempotent_unionop)letidempotent_interop=lift_f2'(M.idempotent_interop)letnonidempotent_interop=lift_f2'(M.nonidempotent_interop)letidempotent_inter_filterop=lift_f2'(M.idempotent_inter_filterop)letnonidempotent_inter_filterop=lift_f2'(M.nonidempotent_inter_filterop)letdifferenceop=lift_f2'(M.differenceop)letreflexive_subset_domain_for_all2f=lift_f2(M.reflexive_subset_domain_for_all2f)letleq_with_fctf=lift_f2(M.leq_with_fctf)letjoin_with_fctf=lift_f2'(M.join_with_fctf)letwiden_with_fctf=lift_f2'(M.widen_with_fctf)letrelift=lift_f'M.reliftend(* TODO: this is very slow because every add/remove in a fold-loop relifts *)(* TODO: currently hardcoded to assume_idempotent *)moduleHConsed(M:S):Swithtypekey=M.keyandtypevalue=M.value=structincludeLattice.HConsed(structletassume_idempotent=falseend)(M)typekey=M.keytypevalue=M.valueletlift_f'fx=lift@@lift_ffxletlift_f2'fxy=lift@@lift_f2fxyletaddkv=lift_f'(M.addkv)letremovek=lift_f'(M.removek)letfindk=lift_f(M.findk)letfind_optk=lift_f(M.find_optk)letmemk=lift_f(M.memk)letiterf=lift_f(M.iterf)letmapf=lift_f'(M.mapf)letmapif=lift_f'(M.mapif)letfoldfxa=M.foldf(unliftx)aletfilterf=lift_f'(M.filterf)letfor_allf=lift_f(M.for_allf)letcardinal=lift_fM.cardinalletchoose=lift_fM.chooseletsingletonkv=lift@@M.singletonkvletempty()=lift@@M.empty()letis_empty=lift_fM.is_emptyletexistsp=lift_f(M.existsp)letbindings=lift_fM.bindingsletadd_listkeyvalues=lift_f'(M.add_listkeyvalues)letadd_list_setkeysvalue=lift_f'(M.add_list_setkeysvalue)letadd_list_funkeysf=lift_f'(M.add_list_funkeysf)letidempotent_unionop=lift_f2'(M.idempotent_unionop)letnonidempotent_unionop=lift_f2'(M.nonidempotent_unionop)letidempotent_interop=lift_f2'(M.idempotent_interop)letnonidempotent_interop=lift_f2'(M.nonidempotent_interop)letidempotent_inter_filterop=lift_f2'(M.idempotent_inter_filterop)letnonidempotent_inter_filterop=lift_f2'(M.nonidempotent_inter_filterop)letdifferenceop=lift_f2'(M.differenceop)letreflexive_subset_domain_for_all2f=lift_f2(M.reflexive_subset_domain_for_all2f)letleq_with_fctf=lift_f2(M.leq_with_fctf)letjoin_with_fctf=lift_f2'(M.join_with_fctf)letwiden_with_fctf=lift_f2'(M.widen_with_fctf)endmoduleTimed(M:S):Swithtypekey=M.keyandtypevalue=M.value=structlettimestrfarg=Timing.wrap(M.name())(Timing.wrapstrf)arg(* Printable.S *)typet=M.tletequalxy=time"equal"(M.equalx)yletcomparexy=time"compare"(M.comparex)ylethashx=time"hash"M.hashxlettagx=time"tag"M.tagx(* TODO: time these also? *)letname=M.nameletto_yojson=M.to_yojsonletshow=M.showletpretty=M.prettyletpretty_diff=M.pretty_diffletprintXml=M.printXmlletarbitrary=M.arbitrary(* Lattice.S *)lettop()=time"top"M.top()letis_topx=time"is_top"M.is_topxletbot()=time"bot"M.bot()letis_botx=time"is_bot"M.is_botxletleqxy=time"leq"(M.leqx)yletjoinxy=time"join"(M.joinx)yletmeetxy=time"meet"(M.meetx)yletwidenxy=time"widen"(M.widenx)yletnarrowxy=time"narrow"(M.narrowx)y(* MapDomain.S *)typekey=M.keytypevalue=M.valueletaddkvx=time"add"(M.addkv)xletremovekx=time"remove"(M.removek)xletfindkx=time"find"(M.findk)xletfind_optkx=time"find_opt"(M.find_optk)xletmemkx=time"mem"(M.memk)xletiterfx=time"iter"(M.iterf)xletmapfx=time"map"(M.mapf)xletmapifx=time"mapi"(M.mapif)xletfoldfxa=time"fold"(M.foldfx)aletfilterfx=time"filter"(M.filterf)xletfor_allfx=time"for_all"(M.for_allf)xletcardinalx=time"cardinal"M.cardinalxletchoosex=time"choose"M.choosexletsingletonkv=time"singleton"(M.singletonk)vletempty()=time"empty"M.empty()letis_emptyx=time"is_empty"M.is_emptyxletexistspx=time"exists"(M.existsp)xletbindingsx=time"bindings"M.bindingsxletadd_listxsx=time"add_list"(M.add_listxs)xletadd_list_setksvx=time"add_list_set"(M.add_list_setksv)xletadd_list_funksfx=time"add_list_fun"(M.add_list_funksf)xletidempotent_unionfxy=time"idempotent_union"(M.idempotent_unionfx)yletnonidempotent_unionfxy=time"nonidempotent_union"(M.nonidempotent_unionfx)yletidempotent_interfxy=time"idempotent_inter"(M.idempotent_interfx)yletnonidempotent_interfxy=time"nonidempotent_inter"(M.nonidempotent_interfx)yletidempotent_inter_filterfxy=time"idempotent_inter_filter"(M.idempotent_inter_filterfx)yletnonidempotent_inter_filterfxy=time"nonidempotent_inter_filter"(M.nonidempotent_inter_filterfx)yletdifferencefxy=time"difference"(M.differencefx)yletreflexive_subset_domain_for_all2fxy=time"reflexive_subset_domain_for_all2"(M.reflexive_subset_domain_for_all2fx)yletleq_with_fctfxy=time"leq_with_fct"(M.leq_with_fctfx)yletjoin_with_fctfxy=time"join_with_fct"(M.join_with_fctfx)yletwiden_with_fctfxy=time"widen_with_fct"(M.widen_with_fctfx)yletreliftx=M.reliftxendmoduleGenMapBot(Domain:Printable.S)(M:MapSwithtypekey=Domain.t)(Range:Lattice.S):Swithtypekey=Domain.tandtypevalue=Range.t=structincludeGenPMap(Domain)(M)(Range)letleq_with_fct=reflexive_subset_domain_for_all2letleq=leq_with_fctRange.leqletfindxm=tryfindxmwith|Not_found->Range.bot()lettop()=raiseLattice.TopValueletbot()=empty()letis_top_=falseletis_bot=is_emptyletpretty_diff()((m1:t),(m2:t)):Pretty.doc=letdiff_keykvacc_opt=matchfindkm2with|v2whennot(Range.leqvv2)->letacc=BatOption.map_default(funacc->acc++line)Pretty.nilacc_optinSome(acc++dprintf"Map: %a =@?@[%a@]"Domain.prettykRange.pretty_diff(v,v2))|exceptionLattice.BotValue->letacc=BatOption.map_default(funacc->acc++line)Pretty.nilacc_optinSome(acc++dprintf"Map: %a =@?@[%a not leq bot@]"Domain.prettykRange.prettyv)|v2->acc_optinmatchfolddiff_keym1Nonewith|Somew->w|None->Pretty.dprintf"No binding grew."letmeet=nonidempotent_interRange.meet(* TODO: idempotent_inter if not using int domain refinement *)letjoin_with_fct=idempotent_unionletjoin=join_with_fctRange.joinletwiden_with_fct=idempotent_unionletwiden=widen_with_fctRange.widenletnarrow=nonidempotent_interRange.narrow(* TODO: idempotent_inter if not using int domain refinement *)endmoduleMapBot(Domain:Printable.S)(Range:Lattice.S)=GenMapBot(Domain)(StdMap(Domain))(Range)modulePatriciaMapBot(Domain:Printable.S)(Range:Lattice.S)=GenMapBot(Domain)(PatriciaMap(structincludeDomainletto_int=tagend))(Range)moduleGenMapTop(Domain:Printable.S)(M:MapSwithtypekey=Domain.t)(Range:Lattice.S):Swithtypekey=Domain.tandtypevalue=Range.t=structincludeGenPMap(Domain)(M)(Range)letleq_with_fctfm1m2=reflexive_subset_domain_for_all2(Fun.flipf)m2m1letleq=leq_with_fctRange.leqletfindxm=tryfindxmwith|Not_found->Range.top()lettop()=empty()letbot()=raiseLattice.BotValueletis_top=is_emptyletis_bot_=false(* let cleanup m = fold (fun k v m -> if Range.is_top v then remove k m else m) m m *)letmeet=nonidempotent_unionRange.meet(* TODO: idempotent_union if not using int domain refinement *)letjoin_with_fct=idempotent_interletjoin=join_with_fctRange.joinletwiden_with_fctf=idempotent_interfletwiden=widen_with_fctRange.widenletnarrow=nonidempotent_unionRange.narrow(* TODO: idempotent_union if not using int domain refinement *)letpretty_diff()((m1:t),(m2:t)):Pretty.doc=letdiff_keykvacc_opt=matchfindkm1with|v1whennot(Range.leqv1v)->letacc=BatOption.map_default(funacc->acc++line)Pretty.nilacc_optinSome(acc++dprintf"Map: %a =@?@[%a@]"Domain.prettykRange.pretty_diff(v1,v))|exceptionLattice.TopValue->letacc=BatOption.map_default(funacc->acc++line)Pretty.nilacc_optinSome(acc++dprintf"Map: %a =@?@[top not leq %a@]"Domain.prettykRange.prettyv)|v1->acc_optinmatchfolddiff_keym2Nonewith|Somew->w|None->Pretty.dprintf"No binding grew."endmoduleMapTop(Domain:Printable.S)(Range:Lattice.S)=GenMapTop(Domain)(StdMap(Domain))(Range)modulePatriciaMapTop(Domain:Printable.S)(Range:Lattice.S)=GenMapTop(Domain)(PatriciaMap(structincludeDomainletto_int=tagend))(Range)exceptionFn_over_AllofstringmoduleLiftTop(Range:Lattice.S)(M:Swithtypevalue=Range.t):Swithtypekey=M.keyandtypevalue=Range.t=structincludeLattice.LiftTop(M)typekey=M.keytypevalue=M.valueletaddkv=function|`Top->`Top|`Liftedx->`Lifted(M.addkvx)letremovek=function|`Top->`Top|`Liftedx->`Lifted(M.removekx)letfindk=function|`Top->Range.top()|`Liftedx->M.findkxletfind_optk=function|`Top->Some(Range.top())|`Liftedx->M.find_optkxletmemk=function|`Top->true|`Liftedx->M.memkxletmapf=function|`Top->`Top|`Liftedx->`Lifted(M.mapfx)letadd_listxs=function|`Top->`Top|`Liftedx->`Lifted(M.add_listxsx)letadd_list_setksv=function|`Top->`Top|`Liftedx->`Lifted(M.add_list_setksvx)letadd_list_funksf=function|`Top->`Top|`Liftedx->`Lifted(M.add_list_funksfx)letidempotent_interfxy=matchx,ywith|`Liftedx,`Liftedy->`Lifted(M.idempotent_interfxy)|_->raise(Fn_over_All"idempotent_inter")letnonidempotent_interfxy=matchx,ywith|`Liftedx,`Liftedy->`Lifted(M.nonidempotent_interfxy)|_->raise(Fn_over_All"nonidempotent_inter")letidempotent_inter_filterfxy=matchx,ywith|`Liftedx,`Liftedy->`Lifted(M.idempotent_inter_filterfxy)|_->raise(Fn_over_All"idempotent_inter_filter")letnonidempotent_inter_filterfxy=matchx,ywith|`Liftedx,`Liftedy->`Lifted(M.nonidempotent_inter_filterfxy)|_->raise(Fn_over_All"nonidempotent_inter_filter")letidempotent_unionfxy=matchx,ywith|`Liftedx,`Liftedy->`Lifted(M.idempotent_unionfxy)|_->raise(Fn_over_All"idempotent_union")letnonidempotent_unionfxy=matchx,ywith|`Liftedx,`Liftedy->`Lifted(M.nonidempotent_unionfxy)|_->raise(Fn_over_All"nonidempotent_union")letdifferencefxy=matchx,ywith|`Liftedx,`Liftedy->`Lifted(M.differencefxy)|_->raise(Fn_over_All"difference")letfor_allf=function|`Top->raise(Fn_over_All"for_all")|`Liftedx->M.for_allfxletiterf=function|`Top->raise(Fn_over_All"iter")|`Liftedx->M.iterfxletfoldfxa=matchxwith|`Top->raise(Fn_over_All"fold")|`Liftedx->M.foldfxaletfilterfx=matchxwith|`Top->raise(Fn_over_All"filter")|`Liftedx->`Lifted(M.filterfx)letreflexive_subset_domain_for_all2fxy=match(x,y)with|(_,`Top)->true|(`Top,_)->false|(`Liftedx,`Liftedy)->M.reflexive_subset_domain_for_all2fxyletleq_with_fctfxy=match(x,y)with|(_,`Top)->true|(`Top,_)->false|(`Liftedx,`Liftedy)->M.leq_with_fctfxyletjoin_with_fctfxy=match(x,y)with|(`Top,x)->`Top|(x,`Top)->`Top|(`Liftedx,`Liftedy)->`Lifted(M.join_with_fctfxy)letwiden_with_fctfxy=match(x,y)with|(`Liftedx,`Liftedy)->`Lifted(M.widen_with_fctfxy)|_->yletcardinal=function|`Top->raise(Fn_over_All"cardinal")|`Liftedx->M.cardinalxletchoose=function|`Top->raise(Fn_over_All"choose")|`Liftedx->M.choosexletsingletonkv=`Lifted(M.singletonkv)letempty()=`Lifted(M.empty())letis_empty=function|`Top->false|`Liftedx->M.is_emptyxletexistsf=function|`Top->raise(Fn_over_All"exists")|`Liftedx->M.existsfxletbindings=function|`Top->raise(Fn_over_All"bindings")|`Liftedx->M.bindingsxletmapif=function|`Top->`Top|`Liftedx->`Lifted(M.mapifx)endmoduleGenMapBot_LiftTop(Domain:Printable.S)(M:MapSwithtypekey=Domain.t)(Range:Lattice.S):Swithtypekey=Domain.tandtypevalue=Range.t=structmoduleM=GenMapBot(Domain)(M)(Range)includeLiftTop(Range)(M)endmoduleMapBot_LiftTop(Domain:Printable.S)(Range:Lattice.S)=GenMapBot_LiftTop(Domain)(StdMap(Domain))(Range)modulePatriciaMapBot_LiftTop(Domain:Printable.S)(Range:Lattice.S)=GenMapBot_LiftTop(Domain)(PatriciaMap(structincludeDomainletto_int=tagend))(Range)moduleLiftBot(Range:Lattice.S)(M:Swithtypevalue=Range.t):Swithtypekey=M.keyandtypevalue=Range.t=structincludeLattice.LiftBot(M)typekey=M.keytypevalue=M.valueletaddkv=function|`Bot->`Bot|`Liftedx->`Lifted(M.addkvx)letremovek=function|`Bot->`Bot|`Liftedx->`Lifted(M.removekx)letfindk=function|`Bot->Range.bot()|`Liftedx->M.findkxletfind_optk=function|`Bot->Some(Range.bot())|`Liftedx->M.find_optkxletmemk=function|`Bot->false|`Liftedx->M.memkxletmapf=function|`Bot->`Bot|`Liftedx->`Lifted(M.mapfx)letadd_listxs=function|`Bot->`Bot|`Liftedx->`Lifted(M.add_listxsx)letadd_list_setksv=function|`Bot->`Bot|`Liftedx->`Lifted(M.add_list_setksvx)letadd_list_funksf=function|`Bot->`Bot|`Liftedx->`Lifted(M.add_list_funksfx)letidempotent_interfxy=matchx,ywith|`Liftedx,`Liftedy->`Lifted(M.idempotent_interfxy)|_->raise(Fn_over_All"idempotent_inter")letnonidempotent_interfxy=matchx,ywith|`Liftedx,`Liftedy->`Lifted(M.nonidempotent_interfxy)|_->raise(Fn_over_All"nonidempotent_inter")letidempotent_inter_filterfxy=matchx,ywith|`Liftedx,`Liftedy->`Lifted(M.idempotent_inter_filterfxy)|_->raise(Fn_over_All"idempotent_inter_filter")letnonidempotent_inter_filterfxy=matchx,ywith|`Liftedx,`Liftedy->`Lifted(M.nonidempotent_inter_filterfxy)|_->raise(Fn_over_All"nonidempotent_inter_filter")letidempotent_unionfxy=matchx,ywith|`Liftedx,`Liftedy->`Lifted(M.idempotent_unionfxy)|_->raise(Fn_over_All"idempotent_union")letnonidempotent_unionfxy=matchx,ywith|`Liftedx,`Liftedy->`Lifted(M.nonidempotent_unionfxy)|_->raise(Fn_over_All"nonidempotent_union")letdifferencefxy=matchx,ywith|`Liftedx,`Liftedy->`Lifted(M.differencefxy)|_->raise(Fn_over_All"difference")letfor_allf=function|`Bot->raise(Fn_over_All"for_all")|`Liftedx->M.for_allfxletiterf=function|`Bot->raise(Fn_over_All"iter")|`Liftedx->M.iterfxletfoldfxa=matchxwith|`Bot->raise(Fn_over_All"fold")|`Liftedx->M.foldfxaletfilterfx=matchxwith|`Bot->raise(Fn_over_All"filter")|`Liftedx->`Lifted(M.filterfx)letjoin_with_fctfxy=match(x,y)with|(`Bot,x)->x|(x,`Bot)->x|(`Liftedx,`Liftedy)->`Lifted(M.join_with_fctfxy)letwiden_with_fctfxy=match(x,y)with|(`Liftedx,`Liftedy)->`Lifted(M.widen_with_fctfxy)|_->yletreflexive_subset_domain_for_all2fxy=match(x,y)with|(`Bot,_)->true|(_,`Bot)->false|(`Liftedx,`Liftedy)->M.reflexive_subset_domain_for_all2fxyletleq_with_fctfxy=match(x,y)with|(`Bot,_)->true|(_,`Bot)->false|(`Liftedx,`Liftedy)->M.leq_with_fctfxyletcardinal=function|`Bot->raise(Fn_over_All"cardinal")|`Liftedx->M.cardinalxletchoose=function|`Bot->raise(Fn_over_All"choose")|`Liftedx->M.choosexletsingletonkv=`Lifted(M.singletonkv)letempty()=`Lifted(M.empty())letis_empty=function|`Bot->false|`Liftedx->M.is_emptyxletexistsf=function|`Bot->raise(Fn_over_All"exists")|`Liftedx->M.existsfxletbindings=function|`Bot->raise(Fn_over_All"bindings")|`Liftedx->M.bindingsxletmapif=function|`Bot->`Bot|`Liftedx->`Lifted(M.mapifx)endmoduleGenMapTop_LiftBot(Domain:Printable.S)(M:MapSwithtypekey=Domain.t)(Range:Lattice.S):Swithtypekey=Domain.tandtypevalue=Range.t=structmoduleM=GenMapTop(Domain)(M)(Range)includeLiftBot(Range)(M)endmoduleMapTop_LiftBot(Domain:Printable.S)(Range:Lattice.S)=GenMapTop_LiftBot(Domain)(StdMap(Domain))(Range)modulePatriciaMapTop_LiftBot(Domain:Printable.S)(Range:Lattice.S)=GenMapTop_LiftBot(Domain)(PatriciaMap(structincludeDomainletto_int=tagend))(Range)(** Map abstracted by a single (joined) key. *)moduleJoined(E:Lattice.S)(R:Lattice.S):Swithtypekey=E.tandtypevalue=R.t=structtypekey=E.ttypevalue=R.tincludeLattice.Prod(E)(R)letsingletoner=(e,r)letexistsp(e,r)=perletfor_allp(e,r)=perletmeme(e',_)=E.leqee'letchooseer=erletbindingser=[er]letremovee((e',_)aser)=ifE.leqe'ethen(E.bot(),R.bot())elseerletmapf(e,r)=(e,fr)letmapif(e,r)=(e,fer)letidempotent_interf(e,r)(e',r')=(E.meetee',frr')letnonidempotent_interf(e,r)(e',r')=(E.meetee',frr')letidempotent_inter_filterf(e,r)(e',r')=failwith"MapDomain.Joined.idempotent_inter_filter"(* TODO: ? *)letnonidempotent_inter_filterf(e,r)(e',r')=failwith"MapDomain.Joined.nonidempotent_inter_filter"(* TODO: ? *)letidempotent_unionf(e,r)(e',r')=(E.joinee',frr')letnonidempotent_unionf(e,r)(e',r')=(E.joinee',frr')letdifferencefm1m2=failwith"MapDomain.Joined.difference"(* TODO: ? *)letfoldf(e,r)a=feraletempty()=(E.bot(),R.bot())letadder(e',r')=(E.joinee',R.joinrr')letis_empty(e,_)=E.is_boteletiterf(e,r)=ferletcardinaler=ifis_emptyerthen0else1letfinde(e',r)=ifE.leqee'thenrelseraiseNot_foundletfind_opte(e',r)=ifE.leqee'thenSomerelseNoneletfilterps=failwith"MapDomain.Joined.filter"letadd_listersm=List.fold_left(funacc(e,r)->adderacc)mersletadd_list_setesrm=List.fold_left(funacce->adderacc)mesletadd_list_funesfm=List.fold_left(funacce->adde(fe)acc)mesletreflexive_subset_domain_for_all2___=failwith"MapDomain.Joined.reflexive_subset_domain_for_all2"letleq_with_fct___=failwith"MapDomain.Joined.leq_with_fct"letjoin_with_fct___=failwith"MapDomain.Joined.join_with_fct"letwiden_with_fct___=failwith"MapDomain.Joined.widen_with_fct"end