123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223(****************************************************************************)(* *)(* 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/>. *)(* *)(****************************************************************************)(** Reduced product of value abstractions with n-ary reduction rules *)openCore.AllopenSig.Abstraction.ValueopenSig.Reduction.ValueopenCommonopenMopsa_utilsmoduleMakeValuePair(V1:VALUE)(V2:VALUE):VALUEwithtypet=V1.t*V2.t=structincludeLattices.Pair.Make(V1)(V2)letid=V_pair(V1.id,V2.id)letname="framework.combiners.value.product"letdisplay=matchV2.idwith|V_empty->V1.display|_->"("^V1.display^" ∧ "^V2.display^")"letaccept_typet=V1.accept_typet&&V2.accept_typetletprintprinter(v1,v2)=pp_obj_listprinter[pboxV1.printv1;pboxV2.printv2]~lopen:""~lsep:" ∧ "~lclose:""letv1_man(man:('v,t)value_man):(('v,V1.t)value_man)={manwithget=(funa->man.geta|>fst);set=(funxa->let(v1,v2)=man.getainifx==v1thenaelseman.set(x,v2)a);}letv2_man(man:('v,t)value_man):(('v,V2.t)value_man)={manwithget=(funa->man.geta|>snd);set=(funxa->let(v1,v2)=man.getainifx==v2thenaelseman.set(v1,x)a);}letevalmane=letr1=V1.eval(v1_manman)einletr2=V2.eval(v2_manman)ein(r1,r2)letfilterbtv=letr1=V1.filterbt(fstv)inletr2=V2.filterbt(sndv)in(r1,r2)letbackwardmanever=letr1=V1.backward(v1_manman)e(map_vexprfstve)rinletr2=V2.backward(v2_manman)e(map_vexprsndve)rinmap2_vexpr(funv1->assertfalse)(funv2->assertfalse)(funv1v2->(v1,v2))r1r2letcomparemanopbe1v1e2v2=let(r11,r12)=V1.compare(v1_manman)opbe1(fstv1)e2(fstv2)inlet(r21,r22)=V2.compare(v2_manman)opbe1(sndv1)e2(sndv2)in(r11,r21),(r12,r22)leteval_extmane=letr1=V1.eval_ext(v1_manman)einletr2=V2.eval_ext(v2_manman)einOptionExt.neutral2man.meetr1r2letbackward_extmaneevr=letr1=V1.backward_ext(v1_manman)eevrinletr2=V2.backward_ext(v2_manman)eevrinOptionExt.neutral2(merge_vexprman.meet)r1r2letcompare_extmanopbe1v1e2v2=letr1=V1.compare_ext(v1_manman)opbe1v1e2v2inletr2=V2.compare_ext(v2_manman)opbe1v1e2v2inOptionExt.neutral2(fun(r11,r12)(r21,r22)->(man.meetr11r21),(man.meetr12r22))r1r2letavalueavalv=OptionExt.neutral2(meet_avalueaval)(V1.avalueaval(fstv))(V2.avalueaval(sndv))letaskmanquery=OptionExt.neutral2(meet_queryquery)(V1.ask(v1_manman)query)(V2.ask(v2_manman)query)endmoduleMake(V:VALUE)(R:sigvalrules:(moduleVALUE_REDUCTION)listend):VALUEwithtypet=V.t=structincludeVletrman={get=(fun(typea)(idx:aid)(v:t)->letrecaux:typeb.bid->b->a=funidyv->matchidy,vwith|V_empty,()->raiseNot_found|V_pair(hd,tl),(vhd,vtl)->begintryauxhdvhdwithNot_found->auxtlvtlend|_->matchequal_ididyidxwith|SomeEq->v|None->raiseNot_foundinauxidv);set=(fun(typea)(idx:aid)(x:a)(v:t)->letrecaux:typeb.bid->b->b=funidyv->matchidy,vwith|V_empty,()->raiseNot_found|V_pair(hd,tl),(vhd,vtl)->begintryauxhdvhd,vtlwithNot_found->vhd,auxtlvtlend|_->matchequal_ididyidxwith|SomeEq->x|None->raiseNot_foundinauxidv)}letreduce(v:t):t=letapplyv=List.fold_left(funaccr->letmoduleReduction=(valr:VALUE_REDUCTION)inReduction.reducermanacc)vR.rulesinletreclfpv=letv'=applyvinifsubsetvv'thenvelselfpv'inlfpvletreduce_man(man:('v,t)value_man)a=man.set(reduce(man.geta))aletreduce_vexprve=map_vexprreduceveletreduce_man_vexprmanve=map_vexpr(reduce_manman)veletreduce_pair((v1,v2)asv)=letv1'=reducev1inletv2'=reducev2inifv1==v1'&&v2==v2'thenvelse(v1',v2')letreduce_man_pair(man:('v,t)value_man)(a1,a2)=letv1=man.geta1inletv2=man.geta2inlet(v1',v2')=reduce_pair(v1,v2)inman.setv1'a1,man.setv2'a2letevalmane=V.evalmane|>reduceletfilterbtv=V.filterbtv|>reduceletbackwardmanever=V.backwardmanever|>reduce_vexprletcomparemanopbe1v1e2v2=V.comparemanopbe1v1e2v2|>reduce_pairleteval_extmane=V.eval_extmane|>OptionExt.lift(reduce_manman)letbackward_extmanever=V.backward_extmanever|>OptionExt.lift(reduce_man_vexprman)letcompare_extmanopbe1v1e2v2=V.compare_extmanopbe1v1e2v2|>OptionExt.lift(reduce_man_pairman)endletmake(values:(moduleVALUE)list)(rules:(moduleVALUE_REDUCTION)list):(moduleVALUE)=letrecaux=function|[]->assertfalse|[v]->v|hd::tl->letv=auxtlin(moduleMakeValuePair(valhd:VALUE)(valv:VALUE):VALUE)inletv=auxvaluesin(moduleMake(valv)(structletrules=rulesend))