123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103(****************************************************************************)(* *)(* 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/>. *)(* *)(****************************************************************************)(**
Bot - Lift operations to a bottom element.
*)(** {2 Types} *)type'awith_bot=BOT|Nbof'a(** Adds a bottom element to a type. *)(** {2 Operator lifting} *)letbot_lift1(f:'a->'b)(a:'awith_bot):'bwith_bot=matchawithBOT->BOT|Nbx->Nb(fx)letbot_lift2(f:'a->'b->'c)(a:'awith_bot)(b:'bwith_bot):'cwith_bot=matcha,bwithBOT,_|_,BOT->BOT|Nbx,Nby->Nb(fxy)letbot_absorb1(f:'a->'bwith_bot)(a:'awith_bot):'bwith_bot=matchawithBOT->BOT|Nbx->fxletbot_absorb2(f:'a->'b->'cwith_bot)(a:'awith_bot)(b:'bwith_bot):'cwith_bot=matcha,bwithBOT,_|_,BOT->BOT|Nbx,Nby->fxyletbot_neutral2(f:'a->'a->'a)(a:'awith_bot)(b:'awith_bot):'awith_bot=matcha,bwithBOT,_->b|_,BOT->a|Nbx,Nby->Nb(fxy)letbot_apply(f:'a->'b->'a)(a:'a)(b:'bwith_bot):'a=matchbwithBOT->a|Nbx->faxletbot_apply2(a1:'a)(a2:'a)(f:'b->'b->'a)(b1:'bwith_bot)(b2:'bwith_bot):'a=matchb1,b2with|BOT,BOT->a1|BOT,_|_,BOT->a2|Nbx1,Nbx2->fx1x2letbot_merge2ab=matcha,bwithNbx,Nby->Nb(x,y)|_->BOTletbot_equal(f:'a->'b->bool)(a:'awith_bot)(b:'bwith_bot):bool=matcha,bwithBOT,BOT->true|Nbx,Nby->fxy|_->falseletbot_included(f:'a->'b->bool)(a:'awith_bot)(b:'bwith_bot):bool=matcha,bwithBOT,_->true|Nbx,Nby->fxy|_->falseletbot_compare(cmp:'a->'a->int)(a:'awith_bot)(b:'awith_bot):int=matcha,bwithBOT,BOT->0|BOT,_->-1|_,BOT->1|Nbx,Nby->cmpxyletbot_dfl1(dfl:'b)(f:'a->'c)(a:'awith_bot):'c=matchawithBOT->dfl|Nbx->fxletbot_dfl2(dfl:'c)(f:'a->'b->'c)(a:'awith_bot)(b:'bwith_bot):'c=matcha,bwithBOT,_|_,BOT->dfl|Nbx,Nby->fxyletlist_remove_bot(a:'awith_botlist):'alist=List.fold_left(funaccx->matchxwithNby->y::acc|BOT->acc)[](List.reva)(** {2 Exceptions} *)exceptionFound_BOTletraise_bot()=raiseFound_BOTletcatch_bot(dfl:'b)(f:'a->'b)(a:'a):'b=tryfawithFound_BOT->dflletbot_to_exn(a:'awith_bot):'a=matchawithBOT->raiseFound_BOT|Nbx->xletexn_to_bot(f:'a->'b)(x:'a):'bwith_bot=tryNb(fx)withFound_BOT->BOTletnobotmsg(a:'awith_bot):'a=matchawithBOT->failwith(msg^": unexpected ⊥")|Nbx->x(** {2 Printing} *)letbot_string="⊥"letbot_to_stringfx=matchxwithBOT->bot_string|Nbx->fxletbot_printfchx=matchxwithBOT->output_stringchbot_string|Nbx->fchxletbot_fprintfchx=matchxwithBOT->Format.pp_print_stringchbot_string|Nbx->fchxletbot_bprintfchx=matchxwithBOT->Buffer.add_stringchbot_string|Nbx->fchx