123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195(** Partitioning domains. *)moduletypeCollapse=sigincludePrintable.Svalcollapse:t->t->boolvalleq:t->t->boolvaljoin:t->t->tendmoduleSet(S:Collapse)=structincludeSetDomain.Make(S)letleqs1s2=letpvf1=exists(funvf2->S.leqvf1vf2)s2infor_allps1letjoin(s1:t)(s2:t)=ifequals1s2thens1else(* Ok, so for each element vf2 in s2, we check in s1 for elements that
* collapse with it and join with them. These are put in res and removed
* from s1 as we don't need to compare with them anymore. *)letfvf2(s1,res)=let(s1_match,s1_rest)=partition(funvf1->S.collapsevf1vf2)s1in(s1_rest,add(foldS.joins1_matchvf2)res)inlet(s1',res)=foldfs2(s1,empty())inunions1'res(* TODO: inter-based meet is unsound? *)letmeet__=failwith"PartitonDomain.Set.meet: unsound"letcollapse(s1:t)(s2:t):bool=letfvf2=exists(funvf1->S.collapsevf1vf2)s1inexistsfs2letaddes=joins(singletone)letwiden=joinendmoduletypeCollapseSet=sigincludeSetDomain.Svalcollapse:t->t->boolendmoduleMake(S:CollapseSet)=structincludeSetDomain.Make(S)moduleS=Stypeset=S.ttypeelem=S.eltletshow_="Partitions"letleqxy=for_all(funp->exists(S.leqp)y)xletjoin(s1:t)(s2:t):t=(* Ok, so for each element vf2 in s2, we check in s1 for elements that
* collapse with it and join with them. These are put in res and removed
* from s1 as we don't need to compare with them anymore. *)letf(x:set)zs=let(joinem,rest)=partition(S.collapsex)zsinadd(foldS.joinjoinemx)restinfoldfs1s2letmeetxsys=letf(x:set)(zs:t):t=letpz=not(S.disjointxz)inletjoinem=filterpysinletjoined=foldS.interjoinemxinifS.is_emptyjoinedthenzselseaddjoinedzsinfoldfxs(empty())letfind_class(x:elem)(p:t):set=lets=S.singletonxintrychoose(filter(S.collapses)p)withNot_found->sletclosure(p:t)(s:set):set=letfxres=letxc=find_classxpinS.joinxcresinS.foldfs(S.empty())letadd(s:set)(p:t):t=joinp(singletons)letwiden=joinletnarrow=meetendmoduleSetSet(Base:Printable.S)=structmoduleB=SetDomain.Make(Base)moduleE=SetDomain.ToppedSet(B)(structlettopname="Bot"end)includeEtypeset=B.ttypepartition=tletshow_="Partitions"(* Top and bottom are reversed:
Bottom will be All (equations), i.e. contradiction,
Top will be empty set, i.e. no equations. *)lettop=E.botletbot=E.topletis_top=E.is_botletis_bot=E.is_topletleqyx=ifis_botythentrueelseifis_botxthenfalseelsefor_all(funp->exists(B.leqp)y)xletpretty_diff()(y,x)=ifE.is_topxthen(GoblintCil.Pretty.(dprintf"%a not leq bot"prettyy))else((* based on DisjointDomain.PairwiseSet *)letx_not_leq=filter(funp->not(exists(funq->B.leqpq)y))xinletp_not_leq=choosex_not_leqinGoblintCil.Pretty.(dprintf"%a:\n"B.prettyp_not_leq++fold(funqacc->dprintf"not leq %a because %a\n"B.prettyqB.pretty_diff(p_not_leq,q)++acc)ynil))letmeetxsys=ifis_botxs||is_botysthenbot()elseletf(x:set)(zs:partition):partition=letpz=B.disjointxzinlet(rest,joinem)=partitionpzsinletjoined=foldB.unionjoinemxinaddjoinedrestinfoldfxsysletjoinxsys=ifis_botxsthenyselseifis_botysthenxselseletf(x:set)(zs:partition):partition=letpz=not(B.disjointxz)inletjoinem=filterpysinifis_emptyjoinemthenzselseletjoined=foldB.interjoinemxinifB.cardinaljoined>1thenaddjoinedzselsezsinfoldfxs(empty())(* TODO: unused *)letremovexss=ifis_botssthensselseletf(z:set)(zz:partition)=letres=B.removexzinifB.cardinalres>1thenaddreszzelsezzinfoldfss(empty())letadd_eq(x,y)ss=ifBase.equalxythensselseletmyset=B.addy(B.singletonx)inmeetss(singletonmyset)letfilterfss=ifis_botssthensselseletf(z:set)(zz:partition)=letres=B.filterfzinifB.cardinalres>1thenaddreszzelsezzinfoldfss(empty())letfind_class(x:Base.t)(ss:t):setoption=trySome(E.choose(E.filter(B.memx)ss))withNot_found->Noneletwiden=joinletnarrow=meetletprintXmlf(xs:t)=matchxswith|`Top->BatPrintf.fprintff"<value>\n<data>\ntop\n</data>\n</value>\n"|`Liftedn->BatPrintf.fprintff"<value>\n<map>\n";iter(BatPrintf.fprintff"<key>\nCluster\n</key>\n%a"B.printXml)xs;BatPrintf.fprintff"</map>\n</value>\n"endmoduleExpPartitions=SetSet(CilType.Exp)