123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225(**************************************************************************)(* *)(* This file is part of WP plug-in of Frama-C. *)(* *)(* Copyright (C) 2007-2023 *)(* CEA (Commissariat a l'energie atomique et aux energies *)(* alternatives) *)(* *)(* 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, version 2.1. *)(* *)(* It 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. *)(* *)(* See the GNU Lesser General Public License version 2.1 *)(* for more details (enclosed in the file licenses/LGPLv2.1). *)(* *)(**************************************************************************)(* -------------------------------------------------------------------------- *)(* --- Common Exportation Engine for Alt-Ergo and Why3 --- *)(* -------------------------------------------------------------------------- *)openLogicopenFormatopenPlibopenEngineopenExportmoduleMake(T:Term)=structopenTmoduleT=TmoduleE=Export.Make(T)moduleEnv=E.Envtypetrigger=(T.var,Fun.t)ftriggertypetypedef=(tau,Field.t,Fun.t)ftypedefletrecfull_trigger=function|TgAny->false|TgVar_->true|TgGet(a,k)->full_triggera&&full_triggerk|TgSet(a,k,v)->full_triggera&&full_triggerk&&full_triggerv|TgFun(_,xs)|TgProp(_,xs)->List.for_allfull_triggerxsletrecfull_triggers=function|[]->[]|ts::tgs->matchList.filterfull_triggertswith|[]->full_triggerstgs|ts->ts::full_triggerstgsclassvirtualengine=object(self)inheritE.engine(* -------------------------------------------------------------------------- *)(* --- Types --- *)(* -------------------------------------------------------------------------- *)methodt_int="int"methodt_real="real"methodt_bool="bool"methodt_prop="prop"methodpp_tvarfmtk=if1<=k&&k<=26thenfprintffmt"'%c"(char_of_int(int_of_char'a'+k-1))elsefprintffmt"'_%d"k(* -------------------------------------------------------------------------- *)(* --- Scope --- *)(* -------------------------------------------------------------------------- *)methodop_scope_=None(* -------------------------------------------------------------------------- *)(* --- Arrays --- *)(* -------------------------------------------------------------------------- *)methodpp_array_getfmtak=fprintffmt"@[<hov 2>%a[%a]@]"self#pp_atomaself#pp_flowkmethodpp_array_setfmtakv=fprintffmt"@[<hov 2>%a[%a@ <- %a]@]"self#pp_atomaself#pp_atomkself#pp_flowv(* -------------------------------------------------------------------------- *)(* --- Records --- *)(* -------------------------------------------------------------------------- *)methodvirtualop_record:string*stringmethodpp_get_fieldfmtrf=fprintffmt"%a.%s"self#pp_atomr(self#fieldf)methodpp_def_fieldsfmtfvs=letbase,fvs=matchT.record_withfvswith|None->None,fvs|Some(r,fvs)->Somer,fvsinbeginlet(left,right)=self#op_recordinfprintffmt"@[<hov 2>%s"left;Plib.iteri(funi(f,v)->(matchi,basewith|(Isingle|Ifirst),Somer->fprintffmt"@ %a with"self#pp_flowr|_->());(matchiwith|Ifirst|Imiddle->fprintffmt"@ @[<hov 2>%s = %a ;@]"(self#fieldf)self#pp_flowv|Isingle|Ilast->fprintffmt"@ @[<hov 2>%s = %a@]"(self#fieldf)self#pp_flowv))fvs;fprintffmt"@ %s@]"right;end(* -------------------------------------------------------------------------- *)(* --- Higher Order --- *)(* -------------------------------------------------------------------------- *)methodpp_apply(_:cmode)(_:term)(_:formatter)(_:termlist)=failwith"Qed.Export.Why: higher-order application"(* -------------------------------------------------------------------------- *)(* --- Higher Order --- *)(* -------------------------------------------------------------------------- *)methodpp_paramfmt((x,t):string*tau)=fprintffmt"%a:%a"self#pp_varxself#pp_tautmethodpp_lambda(_:formatter)(_:(string*tau)list)=failwith"Qed.Export.Why : lambda abstraction"(* -------------------------------------------------------------------------- *)(* --- Declarations --- *)(* -------------------------------------------------------------------------- *)methodvirtualpp_declare_adt:formatter->ADT.t->int->unitmethodvirtualpp_declare_def:formatter->ADT.t->int->tau->unitmethodvirtualpp_declare_sum:formatter->ADT.t->int->(Fun.t*taulist)list->unitmethoddeclare_typefmtadtn=function|Tabs->self#pp_declare_adtfmtadtn;pp_print_newlinefmt()|Tdefdef->self#pp_declare_deffmtadtndef;pp_print_newlinefmt()|Tsumcases->self#pp_declare_sumfmtadtncases;pp_print_newlinefmt()|Trecfts->beginFormat.fprintffmt"@[<hv 0>@[<hv 2>";self#pp_declare_adtfmtadtn;letleft,right=self#op_recordinfprintffmt" = %s"left;Plib.iteri(funindex(f,t)->matchindexwith|Isingle|Ilast->fprintffmt"@ @[<hov 2>%s : %a@]"(self#fieldf)self#pp_taut|Imiddle|Ifirst->fprintffmt"@ @[<hov 2>%s : %a@] ;"(self#fieldf)self#pp_taut)fts;fprintffmt"@] %s@]@\n"right;endmethodpp_declare_symboltfmtf=letname=link_name(self#linkf)inmatchtwith|Cprop->fprintffmt"predicate %s"name|Cterm->fprintffmt"function %s"namemethodvirtualpp_trigger:triggerprintermethodvirtualpp_intros:tau->stringlistprinter(* forall with no separator *)methoddeclare_prop~kindfmtlemmaxstgs(p:term)=self#globalbeginfun()->fprintffmt"@[<hv 2>%s %s:"kindlemma;letgroups=List.fold_left(fungroupsx->leta=self#bindxinlett=T.tau_of_varxinletxs=tryE.TauMap.findtgroupswithNot_found->[]inE.TauMap.addt(a::xs)groups)E.TauMap.emptyxsinletorder=E.TauMap.fold(funtxsorder->(t,List.sortString.comparexs)::order)groups[]inlettgs=full_triggerstgsinPlib.iteri(funindex(t,xs)->letdo_triggers=matchindexwith|Ifirst|Imiddle->false|Isingle|Ilast->tgs<>[]inifdo_triggersthenbeginletpp_or=Plib.pp_listcompact~sep:"|"inletpp_and=Plib.pp_listcompact~sep:","inletpp_triggers=pp_or(pp_andself#pp_trigger)infprintffmt"@ @[<hov 2>%a@]"(self#pp_introst)xs;fprintffmt"@ @[<hov 2>[%a].@]"pp_triggerstgs;endelsefprintffmt"@ @[<hov 2>%a.@]"(self#pp_introst)xs)order;fprintffmt"@ @[<hov 2>%a@]@]@\n"self#pp_proppendmethoddeclare_axiom=self#declare_prop~kind:"axiom"endend