123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585(** Signature for lattices.
Functors for common lattices. *)modulePretty=GoblintCil.Pretty(* module type Rel =
sig
type t
type relation = Less | Equal | Greater | Uncomparable
val rel : t -> t -> relation
val in_rel : t -> relation -> t -> bool
end *)(* partial order: elements might not be comparable and no bot/top -> join etc. might fail with exception Uncomparable *)exceptionUncomparablemoduletypePO=sigincludePrintable.Svalleq:t->t->boolvaljoin:t->t->tvalmeet:t->t->tvalwiden:t->t->t(** [widen x y] assumes [leq x y]. Solvers guarantee this by calling [widen old (join old new)]. *)valnarrow:t->t->t(** If [leq x y = false], then [pretty_diff () (x, y)] should explain why. *)valpretty_diff:unit->(t*t)->Pretty.docendmoduletypeBot=sigtypetvalbot:unit->tvalis_bot:t->boolendmoduletypeTop=sigtypetvaltop:unit->tvalis_top:t->boolend(* complete lattice *)moduletypeS=sigincludePOincludeBotwithtypet:=tincludeTopwithtypet:=tendexceptionTopValue(** Exception raised by a topless lattice in place of a top value.
Surrounding lattice functors may handle this on their own. *)exceptionBotValue(** Exception raised by a bottomless lattice in place of a bottom value.
Surrounding lattice functors may handle this on their own. *)exceptionInvalid_widenofPretty.doclet()=Printexc.register_printer(function|Invalid_widendoc->Some(GobPretty.sprintf"Lattice.Invalid_widen(%a)"Pretty.insertdoc)|_->None(* for other exceptions *))letassert_valid_widen~leq~pretty_diffxy=ifnot(leqxy)thenraise(Invalid_widen(pretty_diff()(x,y)))moduleUnitConf(N:Printable.Name)=structincludePrintable.UnitConf(N)letleq__=trueletjoin__=()letwiden=joinletmeet__=()letnarrow=meetlettop()=()letis_top_=trueletbot()=()letis_bot_=trueletpretty_diff()_=Pretty.text"UnitConf: impossible"endmoduleUnit=UnitConf(structletname="()"end)moduleNoBotTop=structlettop()=raiseTopValueletis_top_=falseletbot()=raiseBotValueletis_bot_=falseendmoduleFake(Base:Printable.S)=structincludeBaseletleq=equalletjoinxy=ifequalxythenxelseraiseTopValueletwiden=joinletmeetxy=ifequalxythenxelseraiseBotValueletnarrow=meetincludeNoBotTopletpretty_diff()(x,y)=Pretty.dprintf"%s: %a not equal %a"(Base.name())prettyxprettyyendmoduletypePD=sigincludePrintable.Svaldummy:tendmoduleFakeSingleton(Base:PD)=structincludeBaseletleqxy=trueletjoinxy=xletwiden=joinletmeetxy=xletnarrow=meetlettop()=Base.dummyletbot()=Base.dummyletis_top_=trueletis_bot_=trueletpretty_diff()_=Pretty.text"FakeSingleton: impossible"endmoduleReverse(Base:S)=structincludeBase(* include StdCousot (* this isn't good *) *)letwiden=Base.meetletnarrow=Base.joinletbot=Base.topletis_bot=Base.is_toplettop=Base.botletis_top=Base.is_botletleqxy=Base.leqyxletjoinxy=Base.meetxyletmeetxy=Base.joinxyletname()="Reversed ("^name()^")"letpretty_diff()(x,y)=Pretty.dprintf"%s: %a not leq %a"(name())prettyxprettyyletprintXml=Base.printXmlletarbitrary=Base.arbitraryend(* HAS SIDE-EFFECTS ---- PLEASE INSTANCIATE ONLY ONCE!!! *)moduleHConsed(Arg:sigvalassume_idempotent:boolend)(Base:S)=structincludePrintable.HConsed(Base)letlift_f2fxy=f(unliftx)(unlifty)letnarrowxy=ifArg.assume_idempotent&&x.BatHashcons.tag=y.BatHashcons.tagthenxelselift(lift_f2Base.narrowxy)letwidenxy=ifx.BatHashcons.tag=y.BatHashcons.tagthenxelselift(lift_f2Base.widenxy)letmeetxy=ifArg.assume_idempotent&&x.BatHashcons.tag=y.BatHashcons.tagthenxelselift(lift_f2Base.meetxy)letjoinxy=ifx.BatHashcons.tag=y.BatHashcons.tagthenxelselift(lift_f2Base.joinxy)letleqxy=(x.BatHashcons.tag=y.BatHashcons.tag)||lift_f2Base.leqxyletis_top=lift_fBase.is_topletis_bot=lift_fBase.is_botlettop()=lift(Base.top())letbot()=lift(Base.bot())letpretty_diff()(x,y)=Base.pretty_diff()(x.BatHashcons.obj,y.BatHashcons.obj)endmoduleHashCached(M:S)=structincludePrintable.HashCached(M)letleq=lift_f2M.leqletjoin=lift_f2'M.joinletmeet=lift_f2'M.meetletwiden=lift_f2'M.widenletnarrow=lift_f2'M.narrowletbot()=lift@@M.bot()letis_bot=lift_fM.is_botlettop()=lift@@M.top()letis_top=lift_fM.is_topletpretty_diff()((x:t),(y:t)):Pretty.doc=M.pretty_diff()(unliftx,unlifty)endmoduleFlatConf(Conf:Printable.LiftConf)(Base:Printable.S)=structincludePrintable.LiftConf(Conf)(Base)letbot()=`Botletis_botx=x=`Botlettop()=`Topletis_topx=x=`Topletleq(x:t)(y:t)=match(x,y)with|(_,`Top)->true|(`Top,_)->false|(`Bot,_)->true|(_,`Bot)->false|(`Liftedx,`Liftedy)->Base.equalxyletpretty_diff()((x:t),(y:t)):Pretty.doc=ifleqxythenPretty.text"No Changes"elsePretty.dprintf"%a instead of %a"prettyxprettyyletjoinxy=match(x,y)with|(`Top,_)->`Top|(_,`Top)->`Top|(`Bot,x)->x|(x,`Bot)->x|(`Liftedx,`Liftedy)whenBase.equalxy->`Liftedx|_->`Topletwiden=joinletmeetxy=match(x,y)with|(`Bot,_)->`Bot|(_,`Bot)->`Bot|(`Top,x)->x|(x,`Top)->x|(`Liftedx,`Liftedy)whenBase.equalxy->`Liftedx|_->`Botletnarrow=meetendmoduleFlat=FlatConf(Printable.DefaultConf)moduleLiftConf(Conf:Printable.LiftConf)(Base:PO)=structincludePrintable.LiftConf(Conf)(Base)letbot()=`Botletis_botx=x=`Botlettop()=`Topletis_topx=x=`Topletleqxy=match(x,y)with|(_,`Top)->true|(`Top,_)->false|(`Bot,_)->true|(_,`Bot)->false|(`Liftedx,`Liftedy)->Base.leqxyletpretty_diff()((x:t),(y:t)):Pretty.doc=match(x,y)with|(`Liftedx,`Liftedy)->Base.pretty_diff()(x,y)|_->ifleqxythenPretty.text"No Changes"elsePretty.dprintf"%a instead of %a"prettyxprettyyletjoinxy=match(x,y)with|(`Top,_)->`Top|(_,`Top)->`Top|(`Bot,x)->x|(x,`Bot)->x|(`Liftedx,`Liftedy)->try`Lifted(Base.joinxy)withTopValue|Uncomparable->`Topletmeetxy=match(x,y)with|(`Bot,_)->`Bot|(_,`Bot)->`Bot|(`Top,x)->x|(x,`Top)->x|(`Liftedx,`Liftedy)->try`Lifted(Base.meetxy)withBotValue|Uncomparable->`Botletwidenxy=match(x,y)with|(`Liftedx,`Liftedy)->begintry`Lifted(Base.widenxy)withTopValue|Uncomparable->`Topend|_->yletnarrowxy=match(x,y)with|(`Liftedx,`Liftedy)->begintry`Lifted(Base.narrowxy)withBotValue|Uncomparable->`Botend|(_,`Bot)->`Bot|(`Top,y)->y|_->xendmoduleLift=LiftConf(Printable.DefaultConf)moduleLift2Conf(Conf:Printable.Lift2Conf)(Base1:PO)(Base2:PO)=structincludePrintable.Lift2Conf(Conf)(Base1)(Base2)letbot()=`Botletis_botx=x=`Botlettop()=`Topletis_topx=x=`Topletleqxy=match(x,y)with|(_,`Top)->true|(`Top,_)->false|(`Bot,_)->true|(_,`Bot)->false|(`Lifted1x,`Lifted1y)->Base1.leqxy|(`Lifted2x,`Lifted2y)->Base2.leqxy|_->falseletpretty_diff()((x:t),(y:t)):Pretty.doc=matchx,ywith|`Lifted1x,`Lifted1y->Base1.pretty_diff()(x,y)|`Lifted2x,`Lifted2y->Base2.pretty_diff()(x,y)|_whenleqxy->Pretty.text"No Changes"|_->Pretty.dprintf"%a instead of %a"prettyxprettyyletjoinxy=match(x,y)with|(`Top,_)->`Top|(_,`Top)->`Top|(`Bot,x)->x|(x,`Bot)->x|(`Lifted1x,`Lifted1y)->begintry`Lifted1(Base1.joinxy)withTopValue->`Topend|(`Lifted2x,`Lifted2y)->begintry`Lifted2(Base2.joinxy)withTopValue->`Topend|_->`Topletmeetxy=match(x,y)with|(`Bot,_)->`Bot|(_,`Bot)->`Bot|(`Top,x)->x|(x,`Top)->x|(`Lifted1x,`Lifted1y)->begintry`Lifted1(Base1.meetxy)withBotValue->`Botend|(`Lifted2x,`Lifted2y)->begintry`Lifted2(Base2.meetxy)withBotValue->`Botend|_->`Botletwidenxy=match(x,y)with|(`Lifted1x,`Lifted1y)->`Lifted1(Base1.widenxy)|(`Lifted2x,`Lifted2y)->`Lifted2(Base2.widenxy)|_->yletnarrowxy=match(x,y)with|(`Lifted1x,`Lifted1y)->`Lifted1(Base1.narrowxy)|(`Lifted2x,`Lifted2y)->`Lifted2(Base2.narrowxy)|(_,`Bot)->`Bot|(`Top,y)->y|_->xendmoduleLift2=Lift2Conf(Printable.DefaultConf)moduleProdConf(C:Printable.ProdConfiguration)(Base1:S)(Base2:S)=structopenstruct(* open to avoid leaking P and causing conflicts *)moduleP=Printable.ProdConf(C)(Base1)(Base2)endtypet=Base1.t*Base2.t[@@derivinglattice]include(P:moduletypeofPwithtypet:=t)letpretty_diff()((x1,x2:t),(y1,y2:t)):Pretty.doc=ifBase1.leqx1y1thenBase2.pretty_diff()(x2,y2)elseBase1.pretty_diff()(x1,y1)endmoduleProd=ProdConf(structletexpand_fst=trueletexpand_snd=trueend)moduleProdSimple=ProdConf(structletexpand_fst=falseletexpand_snd=falseend)moduleProd3(Base1:S)(Base2:S)(Base3:S)=structopenstruct(* open to avoid leaking P and causing conflicts *)moduleP=Printable.Prod3(Base1)(Base2)(Base3)endtypet=Base1.t*Base2.t*Base3.t[@@derivinglattice]include(P:moduletypeofPwithtypet:=t)letpretty_diff()((x1,x2,x3:t),(y1,y2,y3:t)):Pretty.doc=ifnot(Base1.leqx1y1)thenBase1.pretty_diff()(x1,y1)elseifnot(Base2.leqx2y2)thenBase2.pretty_diff()(x2,y2)elseBase3.pretty_diff()(x3,y3)endmoduleLiftBot(Base:S)=structincludePrintable.LiftBot(Base)letbot()=`Botletis_botx=x=`Botlettop()=`Lifted(Base.top())letis_topx=matchxwith|`Liftedx->Base.is_topx|`Bot->falseletleqxy=match(x,y)with|(`Bot,_)->true|(_,`Bot)->false|(`Liftedx,`Liftedy)->Base.leqxyletpretty_diff()((x:t),(y:t)):Pretty.doc=matchx,ywith|`Liftedx,`Liftedy->Base.pretty_diff()(x,y)|_->Pretty.dprintf"%s: %a not leq %a"(name())prettyxprettyyletjoinxy=match(x,y)with|(`Bot,x)->x|(x,`Bot)->x|(`Liftedx,`Liftedy)->`Lifted(Base.joinxy)letmeetxy=match(x,y)with|(`Bot,_)->`Bot|(_,`Bot)->`Bot|(`Liftedx,`Liftedy)->try`Lifted(Base.meetxy)withBotValue->`Botletwidenxy=match(x,y)with|(`Liftedx,`Liftedy)->`Lifted(Base.widenxy)|_->yletnarrowxy=match(x,y)with|(`Liftedx,`Liftedy)->begintry`Lifted(Base.narrowxy)withBotValue->`Botend|(_,`Bot)->`Bot|_->xendmoduleLiftTop(Base:S)=structincludePrintable.LiftTop(Base)lettop()=`Topletis_topx=x=`Topletbot()=`Lifted(Base.bot())letis_botx=matchxwith|`Liftedx->Base.is_botx|`Top->falseletleqxy=match(x,y)with|(_,`Top)->true|(`Top,_)->false|(`Liftedx,`Liftedy)->Base.leqxyletjoinxy=match(x,y)with|(`Top,x)->`Top|(x,`Top)->`Top|(`Liftedx,`Liftedy)->try`Lifted(Base.joinxy)withTopValue->`Topletmeetxy=match(x,y)with|(`Top,x)->x|(x,`Top)->x|(`Liftedx,`Liftedy)->`Lifted(Base.meetxy)letwidenxy=match(x,y)with|(`Liftedx,`Liftedy)->begintry`Lifted(Base.widenxy)withTopValue->`Topend|_->yletnarrowxy=match(x,y)with|(`Liftedx,`Liftedy)->`Lifted(Base.narrowxy)|(`Top,y)->y|_->xletpretty_diff()(x,y)=match(x,y)with|`Liftedx,`Liftedy->Base.pretty_diff()(x,y)|_->Pretty.dprintf"%s: %a not leq %a"(name())prettyxprettyyendmoduleLiszt(Base:S)=structincludePrintable.Liszt(Base)includeNoBotTopletleq=letfaccxy=Base.leqxy&&accinList.fold_left2ftrueletjoin=List.map2Base.joinletwiden=joinletmeet=List.map2Base.meetletnarrow=meetletpretty_diff()((x:t),(y:t)):Pretty.doc=Pretty.dprintf"%a not leq %a"prettyxprettyyendmoduletypeNum=sigvalx:unit->intendmoduleProdList(Base:S)(N:Num)=structincludePrintable.Liszt(Base)letbot()=BatList.make(N.x())(Base.bot())letis_bot=List.for_allBase.is_botlettop()=BatList.make(N.x())(Base.top())letis_top=List.for_allBase.is_topletleq=letfaccxy=Base.leqxy&&accinList.fold_left2ftrueletjoin=List.map2Base.joinletwiden=List.map2Base.widenletmeet=List.map2Base.meetletnarrow=List.map2Base.narrowletpretty_diff()((x:t),(y:t)):Pretty.doc=Pretty.dprintf"%a not leq %a"prettyxprettyyendmoduleChain(P:Printable.ChainParams):Swithtypet=int=structincludePrintable.StdincludePrintable.Chain(P)letbot()=0letis_botx=x=0lettop()=P.n()-1letis_topx=x=P.n()-1letleqxy=x<=yletjoinxy=maxxyletwiden=joinletmeetxy=minxyletnarrow=meetletpretty_diff()((x:t),(y:t)):Pretty.doc=Pretty.dprintf"%a not leq %a"prettyxprettyyend