123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372(**************************************************************************)(* *)(* This file is part of WP plug-in of Frama-C. *)(* *)(* Copyright (C) 2007-2025 *)(* 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). *)(* *)(**************************************************************************)openCil_datatypemoduleC=Cil_typesmoduleCpp=Cil_printermoduleL=Wp_parametersmoduleT=Why3.TheorymoduleF=FilepathmoduleW=Why3moduleWConf=Why3.WhyconfmoduleLB=LogicBuiltinsmoduleLT=Logic_typingletdkey=L.register_category~help:"Importer Why3 -> ACSL""why3:import"(* -------------------------------------------------------------------------- *)(* --- Why3 Environment --- *)(* -------------------------------------------------------------------------- *)letwhy3_envloadpath=letmain=WConf.get_main@@WConf.read_configNoneinW.Env.create_env@@WConf.loadpathmain@F.to_string_listloadpathletextract_paththname=letsegments=String.split_on_char'.'thnameinmatchList.revsegmentswith|hd::tl->hd,List.revtl|[]->"",[]letof_infixs=letrecunwrap_anys=function|[]->s|prefix::others->ifString.starts_with~prefixsthenletn=String.lengthsinletp=String.lengthprefixinPrintf.sprintf"(%s)"@@String.subsp(n-p)elseunwrap_anysothersinunwrap_anys["prefix ";"infix ";"mixfix "]letacsl_name(id:W.Ident.ident)=let(path,name,scope)=T.restore_pathidinmatchList.revscopewith|(t::q)->String.concat"::"(path@name::List.rev_appendq[of_infixt])|[]->""letpp_idfmt(id:W.Ident.ident)=Format.pp_print_stringfmtid.id_string(* -------------------------------------------------------------------------*)(* --- Types - *)(* -------------------------------------------------------------------------*)typetvars=C.logic_typeW.Ty.Mtv.ttypewhy3module={types:(C.logic_type_info*C.location)list;logics:(C.logic_info*C.location)list;}typeenv={wenv:W.Env.env;tenv:C.logic_type_infoW.Ty.Hts.t;lenv:C.logic_infoW.Term.Hls.t;lils:W.Term.lsymbolLogic_info.Hashtbl.t;lcts:W.Term.lsymbolLogic_ctor_info.Hashtbl.t;ltts:W.Ty.tysymbolLogic_type_info.Hashtbl.t;menv:why3moduleDatatype.String.Hashtbl.t;}typemenv={mutablelti:(C.logic_type_info*C.location)list;mutableli:(C.logic_info*C.location)list;}letcreatewenv=lettenv=W.Ty.Hts.create0inletlenv=W.Term.Hls.create0inletlils=Logic_info.Hashtbl.create0inletlcts=Logic_ctor_info.Hashtbl.create0inletltts=Logic_type_info.Hashtbl.create0inletmenv=Datatype.String.Hashtbl.create0in{wenv;tenv;lenv;lils;lcts;ltts;menv}(* -------------------------------------------------------------------------- *)(* --- Built-in --- *)(* -------------------------------------------------------------------------- *)letadd_builtin(tenv)tslt_namelt_params=W.Ty.Hts.addtenvtsC.{lt_name;lt_params;lt_def=None;lt_attr=[]}letfind_tsenvpkgthyname=letth=Why3.Env.read_theoryenv.wenvpkgthyintryWhy3.Theory.ns_find_tsth.th_exportnamewithNot_found->L.fatal"Cannot find %s.%s.%s"(String.concat"."pkg)thy(String.concat"."name)letadd_builtinsenv=beginletts_list=find_tsenv["list"]"List"["list"]inletts_set=find_tsenv["set"]"Set"["set"]inadd_builtinenv.tenvts_list"\\list"["A"];add_builtinenv.tenvts_set"set"["A"];end(* -------------------------------------------------------------------------- *)(* --- Location handling --- *)(* -------------------------------------------------------------------------- *)letconvert_location(wloc:Why3.Loc.positionoption):C.location=matchwlocwith|Someloc->let(file,lstart,cstart,lend,cend)=Why3.Loc.getlocinletpstart={Filepath.pos_path=F.of_stringfile;pos_lnum=lstart;pos_bol=0;pos_cnum=cstart;}inletpend={Filepath.pos_path=F.of_stringfile;pos_lnum=lend;pos_bol=0;pos_cnum=cend;}in(pstart,pend)|None->(Position.unknown,Position.unknown)(* -------------------------------------------------------------------------- *)(* --- Type conversion --- *)(* -------------------------------------------------------------------------- *)lettvars_of_txs(txs:W.Ty.tvsymbollist):stringlist*tvars=List.iter(fun(tv:W.Ty.tvsymbol)->L.debug~level:3"Name of : %a"pp_idtv.tv_name)txs;List.fold_right(fun(tv:W.Ty.tvsymbol)(txs,tvs)->letx=tv.tv_name.id_stringinx::txs,W.Ty.Mtv.addtv(C.Lvarx)tvs)txs([],W.Ty.Mtv.empty)letreclt_of_tyenvmenv(tvs:tvars)(ty:W.Ty.ty):C.logic_type=matchty.ty_nodewith|Tyvarx->W.Ty.Mtv.findxtvs|Tyapp(s,[])whenW.Ty.(ts_equalsts_int)->C.Linteger|Tyapp(s,[])whenW.Ty.(ts_equalsts_real)->C.Lreal|Tyapp(s,[])whenW.Ty.(ts_equalsts_bool)->C.Lboolean|Tyapp(s,[a;b])whenW.Ty.(ts_equalsts_func)->letta=lt_of_tyenvmenvtvsainlettb=lt_of_tyenvmenvtvsbinC.Larrow([ta],tb)|Tyapp(s,ts)->C.Ltype(lt_of_tsenvmenvs[],List.map(lt_of_tyenvmenvtvs)ts)andlt_of_tsenvmenv(ts:W.Ty.tysymbol)(cs:W.Decl.constructorlist):C.logic_type_info=tryW.Ty.Hts.findenv.tenvtswithNot_found->letlt_params,tvars=tvars_of_txsts.ts_argsinletlt_name=acsl_namets.ts_nameinletlti=C.{lt_name;lt_params;lt_def=None;lt_attr=[];}inlti.lt_def<-(matchts.ts_defwith|Range_|Float_->None|NoDef->Some(C.LTsum(List.map(cli_of_constrenvmenvlti)cs))|Aliasty->Some(C.LTsyn(lt_of_tyenvmenvtvarsty)));W.Ty.Hts.addenv.tenvtslti;menv.lti<-(lti,(convert_locationts.ts_name.id_loc))::menv.lti;Logic_type_info.Hashtbl.addenv.lttsltits;ltiandcli_of_constrenvmenvctor_type(ls,_:W.Decl.constructor):C.logic_ctor_info=let_,tvars=tvars_of_txs@@W.Ty.Stv.elements@@W.Term.ls_ty_freevarslsinletl_profile=List.mapi(lv_of_tyenvmenvtvars)ls.ls_argsinletctor_params=List.map(fun(lv:C.logic_var)->lv.lv_type)l_profileinletctor_name=acsl_namels.ls_nameinletctor=Cil_types.{ctor_name;ctor_type;ctor_params}inLogic_ctor_info.Hashtbl.addenv.lctsctorls;ctor(* -------------------------------------------------------------------------- *)(* --- Functions conversion --- *)(* -------------------------------------------------------------------------- *)andlv_of_tyenvmenv(tvars:tvars)(index)(ty:W.Ty.ty):C.logic_var=Cil_const.make_logic_var_formal(Printf.sprintf"x%d"index)@@(lt_of_tyenvmenvtvarsty)andlt_of_ty_opt(lt_opt)=matchlt_optwith|None->C.CtypeCil_const.voidType(* Same as logic_typing *)|Sometr->trletli_of_lsenvmenv(ls:W.Term.lsymbol):C.logic_info=letl_tparams,tvars=tvars_of_txs@@W.Ty.Stv.elements@@W.Term.ls_ty_freevarslsinletl_type=Option.map(lt_of_tyenvmenvtvars)ls.ls_valueinletl_profile=List.mapi(lv_of_tyenvmenvtvars)ls.ls_argsinletl_args=List.map(fun(lv:C.logic_var)->lv.lv_type)l_profileinletl_result=lt_of_ty_optl_typeinletl_params=ifl_args=[]thenl_resultelseC.Larrow(l_args,l_result)inletl_name=acsl_namels.ls_nameinletlv=Cil_const.make_logic_var_globall_namel_paramsinletli=C.{l_var_info=lv;l_labels=[];l_tparams;l_type;l_profile;l_body=C.LBnone;}inW.Term.Hls.addenv.lenvlsli;menv.li<-(li,(convert_locationls.ls_name.id_loc))::menv.li;Logic_info.Hashtbl.addenv.lilslils;liletadd_tsenvmenv(ts:W.Ty.tysymbol)(cs:W.Decl.constructorlist)=L.debug~dkey"Importing type %a: %s"pp_idts.ts_name(acsl_namets.ts_name);ignore@@lt_of_tsenvmenvtscsletadd_lsenvmenv(ls:W.Term.lsymbol)=L.debug~dkey"Importing logic %a: %s"pp_idls.ls_name(acsl_namels.ls_name);ignore@@li_of_lsenvmenvls(* -------------------------------------------------------------------------- *)(* --- Theory --- *)(* -------------------------------------------------------------------------- *)letget_theoryenv(theory_name)(theory_path)=tryW.Env.read_theoryenv.wenvtheory_paththeory_namewithW.Env.LibraryNotFound_->L.error"Library %s not found"theory_name;W.Theory.ignore_theoryletparse_theoryenv(theory:W.Theory.theory)(menv)=beginList.iter(fun(tdecl:T.tdecl)->matchtdecl.td_nodewith|Decldecl->beginmatchdecl.d_nodewith|Dtypets->add_tsenvmenvts[]|Dparamls->add_lsenvmenvls|Ddatads->List.iter(fun(ts,cs)->add_tsenvmenvtscs)ds|Dlogicds->List.iter(fun(ls,_)->add_lsenvmenvls)ds|Dind(_,ds)->List.iter(fun(ls,_)->add_lsenvmenvls)ds|Dprop_->()end|Use_|Clone_|Meta_->())theory.th_decls;endletkind_of_lt(lt:C.logic_type):LB.kind=matchltwith|C.Linteger->LB.Z|C.Lreal->LB.R|C.Lboolean->LB.B|_->LB.Aletsort_of_lt(lt:C.logic_type):Qed.Logic.sort=matchltwith|C.Linteger->Qed.Logic.Sint|C.Lreal->Qed.Logic.Sreal|_->Qed.Logic.Sdataletsort_of_result=function|Somelt->sort_of_ltlt|None->Qed.Logic.Spropletregister_builtinenvm=beginletadd_builtin(ls:W.Term.lsymbol)acsl_nameprofileresult=let(package,theory,name)=T.restore_pathls.ls_nameinletkinds=List.mapkind_of_ltprofileinletparams=List.mapsort_of_ltprofileinLB.add_builtinacsl_namekinds@@Lang.imported_f~package~theory~name~params~result()inletadd_builtin_lili=letls=Logic_info.Hashtbl.findenv.lilsliinletprofile=List.map(funlv->lv.C.lv_type)li.l_profileinletresult=sort_of_resultli.l_typeinadd_builtinlsli.l_var_info.lv_nameprofileresultinletadd_builtin_ctorctor=letls=Logic_ctor_info.Hashtbl.findenv.lctsctorinletprofile=ctor.Cil_types.ctor_paramsinletresult=Qed.Logic.Sdatainadd_builtinlsctor.ctor_nameprofileresultinletadd_builtin_tlti=letty=Logic_type_info.Hashtbl.findenv.lttsltiinlet(package,theory,name)=T.restore_pathty.ts_nameinLB.add_builtin_typelti.lt_name@@Lang.imported_t~package~theory~name;beginmatchlti.lt_defwith|SomeC.LTsumctors->List.iteradd_builtin_ctorctors|_->()endinList.iter(fun(lti,_)->add_builtin_tlti)m.types;List.iter(fun(li,_)->add_builtin_lili)m.logics;endletimport_theoryenvthname=tryDatatype.String.Hashtbl.findenv.menvthnamewithNot_found->L.debug~dkey"Parsing Why3 theory %s.@."thname;lettheory_name,theory_path=extract_paththnameinletmenv:menv={li=[];lti=[]}inlettheory=get_theoryenvtheory_nametheory_pathinparse_theoryenvtheorymenv;letm={types=List.revmenv.lti;logics=List.revmenv.li}inDatatype.String.Hashtbl.addenv.menvthnamem;register_builtinenvm;m(* -------------------------------------------------------------------------- *)(* --- Module registration --- *)(* -------------------------------------------------------------------------- *)moduleEnv=WpContext.StaticGenerator(Datatype.Unit)(structtypekey=unittypedata=envletname="Wp.Why3Import.Env"letcompile()=letenv=create@@why3_env@@L.Library.get()inadd_builtinsenv;envend)letimporter(ctxt:LT.module_builder)(_:C.location)(m:stringlist)=beginL.debug~dkey"Importing Why3 theory %s.@."(String.concat"::"m);letthname=String.concat"."minletm=import_theory(Env.get())thnameinList.iter(fun(lti,loc)->ctxt.add_logic_typeloclti)m.types;List.iter(fun(li,loc)->ctxt.add_logic_functionlocli)m.logics;endletregistered=reffalseletregister()=ifnot!registeredthenbeginregistered:=true;Acsl_extension.register_module_importer~plugin:"wp""why3"importer;endlet()=Cmdline.run_after_extended_stageregister(* -------------------------------------------------------------------------- *)