123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240(****************************************************************************)(* *)(* This file is part of MOPSA, a Modular Open Platform for Static Analysis. *)(* *)(* Copyright (C) 2017-2019 The MOPSA Project. *)(* *)(* This program is free software: you can redistribute it and/or modify *)(* it under the terms of the GNU Lesser General Public License as published *)(* by the Free Software Foundation, either version 3 of the License, or *)(* (at your option) any later version. *)(* *)(* This program is distributed in the hope that it will be useful, *)(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)(* GNU Lesser General Public License for more details. *)(* *)(* You should have received a copy of the GNU Lesser General Public License *)(* along with this program. If not, see <http://www.gnu.org/licenses/>. *)(* *)(****************************************************************************)(** Tokens identifying control flows *)openMopsa_utilstypetoken=..typetoken+=T_curletdebugfmt=Debug.debug~channel:"framework.core.token"fmtlettoken_compare_chain=TypeExt.mk_compare_chain(funtk1tk2->matchtk1,tk2with|T_cur,T_cur->0|_->comparetk1tk2)letcompare_tokentk1tk2=TypeExt.comparetoken_compare_chaintk1tk2lettoken_print_chain=TypeExt.mk_print_chain(funfmttk->matchtkwith|T_cur->Format.fprintffmt"cur"|_->Exceptions.panic~loc:__LOC__"unknown token")letpp_tokenfmttk=TypeExt.printtoken_print_chainfmttkletregister_token(info:tokenTypeExt.info)=TypeExt.registerinfotoken_compare_chaintoken_print_chainopenContextmoduleTokenMap=structopenTopopenLatticemoduleMap=MapExt.Make(structtypet=tokenletcompare=compare_tokenletprint=pp_tokenend)type+'at='aMap.twith_topletbottom:'at=NtMap.emptylettop:'at=TOPletsingleton(tk:token)(env:'a):'at=Nt(Map.singletontkenv)letis_bottom(lattice:'alattice)(tmap:'at):bool=top_dfl1false(funm->Map.for_all(fun_v->lattice.is_bottomv)m)tmapletis_singletontmap=top_dfl1falseMap.is_singletontmapletis_empty(tmap:'at):bool=top_dfl1falseMap.is_emptytmapletis_top(lattice:'alattice)(tmap:'at):bool=top_dfl1true(fun_->false)tmapletsubset(lattice:'alattice)ctx(tmap1:'at)(tmap2:'at):bool=top_included(Map.for_all2zo(funtkv1->lattice.is_bottomv1)(* non-⊥ ⊈ ⊥ *)(fun_v2->true)(* ⊥ ⊆ non-⊥ *)(fun_v1v2->lattice.subsetctxv1v2))tmap1tmap2letjoin(lattice:'alattice)ctx(tmap1:'at)(tmap2:'at):'at=top_lift2(Map.map2zo(fun_v1->v1)(fun_v2->v2)(fun_v1v2->lattice.joinctxv1v2))tmap1tmap2letjoin_listlatticectxl=matchlwith|[]->bottom|hd::tl->List.fold_left(joinlatticectx)hdtlletmeet(lattice:'alattice)ctx(tmap1:'at)(tmap2:'at):'at=top_neutral2(funb1b2->Map.map2zo(fun_v1->lattice.bottom)(fun_v2->lattice.bottom)(fun_v1v2->lattice.meetctxv1v2)b1b2)tmap1tmap2letmeet_listlatticectxl=matchlwith|[]->bottom|hd::tl->List.fold_left(meetlatticectx)hdtlletwiden(lattice:'alattice)(ctx:'actx)(tmap1:'at)(tmap2:'at):'at=top_lift2(Map.map2zo(fun_v1->v1)(fun_v2->v2)(fun_v1v2->lattice.widenctxv1v2))tmap1tmap2letprintppprinter(tmap:'at):unit=letopenPrintinmatchtmapwith|TOP->pp_stringprinter"⊤"|NtmwhenMap.is_emptym->pp_stringprinter"⊥"|Ntm->pp_map(unformatpp_token)ppprinter(Map.bindingsm)letget(tk:token)(lattice:'alattice)(tmap:'at):'a=tryletm=top_to_exntmapintryMap.findtkmwithNot_found->lattice.bottomwithFound_TOP->lattice.topletmem(tk:token)(tmap:'at):bool=top_dfl1true(Map.memtk)tmapletfind(tk:token)(tmap:'at):'a=Map.findtk(top_to_exntmap)letfind_opt(tk:token)(tmap:'at):'aoption=top_apply(funm->Some(Map.findtkm))Nonetmapletset(tk:token)(a:'a)(lattice:'alattice)(tmap:'at):'at=top_lift1(funm->iflattice.is_bottomathenMap.removetkmelseMap.addtkam)tmapletcopy(tk1:token)(tk2:token)(lattice:'alattice)(tmap1:'at)(tmap2:'at):'at=settk2(gettk1latticetmap1)latticetmap2letremove(tk:token)(tmap:'at):'at=top_lift1(Map.removetk)tmapletfilter(f:token->'a->bool)(tmap:'at):'at=top_lift1(Map.filterf)tmapletpartition(f:token->'a->bool)(tmap:'at):'at*'at=matchtmapwith|TOP->TOP,TOP|Nta->letl,r=Map.partitionfainNtl,Ntrletmap(f:token->'a->'b)(tmap:'at):'bt=top_lift1(Map.mapif)tmapletfold(f:'b->token->'a->'b)(init:'b)(tmap:'at):'b=letm=top_to_exntmapinMap.fold(funtkaacc->facctka)minitletiter(f:token->'a->unit)(tmap:'at):unit=letm=top_to_exntmapinMap.iterfmletmerge(f:token->'aoption->'aoption->'aoption)(lattice:'alattice)(tmap1:'at)(tmap2:'at):'at=top_lift2(Map.map2zo(funtkv1->OptionExt.defaultlattice.bottom(ftk(Somev1)None))(funtkv2->OptionExt.defaultlattice.bottom(ftkNone(Somev2)))(funtkv1v2->OptionExt.defaultlattice.bottom(ftk(Somev1)(Somev2))))tmap1tmap2letmap2zof1f2f(tmap1:'at)(tmap2:'at):'at=top_lift2(Map.map2zof1f2f)tmap1tmap2letneutral2(f:token->'a->'a->'a)(tmap1:'at)(tmap2:'at):'at=top_lift2(Map.map2zo(funtkv1->v1)(funtkv2->v2)(funtkv1v2->ftkv1v2))tmap1tmap2letabsorb2(f:token->'a->'a->'a)(tmap1:'at)(tmap2:'at):'at=top_lift2(Map.merge(funtkov1ov2->matchov1,ov2with|None,_|_,None->None|Somev1,Somev2->Some(ftkv1v2)))tmap1tmap2end