123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167(**************************************************************************)(* *)(* This file is part of WP plug-in of Frama-C. *)(* *)(* Copyright (C) 2007-2024 *)(* 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). *)(* *)(**************************************************************************)(* -------------------------------------------------------------------------- *)(* --- Logical Language --- *)(* -------------------------------------------------------------------------- *)openCil_typesopenCil_datatypeopenCtypesopenQedopenQed.Logicletdkey_pretty=Wp_parameters.register_category"pretty"(* -------------------------------------------------------------------------- *)letbasenamedefname=letreclookupdefskn=ifk<nthenletc=s.[k]inif('a'<=c&&c<='z')||('A'<=c&&c<='Z')thenString.subsk1elselookupdefs(succk)nelsedefinlookupdefname0(String.lengthname)(* -------------------------------------------------------------------------- *)(* Naming Prefixes
Names starting with a lower-case character belong to logic language
or external model(s).
'pointer' Pointer type
'Lit_<hex>' String Literal Values
'Str_<eid>' String Literal Pointers
'S_<s>' Structure <s>
'U_<u>' Union <u>
'F_<c>_<f>' Field <f> in compound <c>
'A_<t>' ACSL Logic type <t>
'C_<c>' ACSL Constructor <c>
'P_<p>' ACSL Predicate <p> (see LogicUsage.get_name)
'L_<f>' ACSL Logic function <f> (see LogicUsage.get_name)
'FixP_<p>' ACSL Recursive Predicate <p> (see LogicUsage.get_name)
'FixL_<f>' ACSL Recursive Logic function <f> (see LogicUsage.get_name)
'Q_<l>' ACSL Lemma or Axiom
'S_<n>' Set comprehension predicate
'Is<phi>' Typing predicate for type <phi>
'Null<phi>' Null value for type <phi>
*)letavoid_leading_backlashs=ifs.[0]='\\'thenlets=Bytes.of_stringsinBytes.sets0'_';Bytes.to_stringselsesletcomp_idc=letprefix=ifc.cstructthen'S'else'U'inifc.corig_name=""thenPrintf.sprintf"%c%d"prefixc.ckeyelsePrintf.sprintf"%c%d_%s"prefixc.ckeyc.corig_nameletfield_idf=letc=f.fcompinifc.corig_name=""thenPrintf.sprintf"F%d_%s"c.ckeyf.fnameelsePrintf.sprintf"F%d_%s_%s"c.ckeyc.corig_namef.fnameletinit_id(f:'a->string)(x:'a)="Init_"^(fx)letcomp_init_id=init_idcomp_idletfield_init_id=init_idfield_idlettype_idl=Printf.sprintf"A_%s"l.lt_nameletlogic_idf=letname=avoid_leading_backlash(LogicUsage.get_namef)iniff.l_type=NonethenPrintf.sprintf"P_%s"nameelsePrintf.sprintf"L_%s"nameletctor_idc=Printf.sprintf"C_%s"(avoid_leading_backlashc.ctor_name)letlemma_idl=Printf.sprintf"Q_%s"(avoid_leading_backlashl)(* -------------------------------------------------------------------------- *)typelibrary=stringtypedatakind=KValue|KInittypeadt=|Mtypeofmdt(* Model type *)|Mrecordofmdt*fields(* Model record-type *)|Atypeoflogic_type_info(* Logic Type *)|Compofcompinfo*datakind(* C-code struct or union *)|Wtypeofstringlist*string*stringlist(** Why3 imported type *)(** name to print to the provers *)andmdt=stringexternand'aextern={ext_id:int;ext_link:'a;ext_library:library;(** a library which it depends on *)ext_debug:string;(** just for printing during debugging *)}andfields={mutablefields:fieldlist}andfield=|Mfieldofmdt*fields*string*tau|Cfieldoffieldinfo*datakindandtau=(field,adt)Logic.datatypeletpointer=Context.create"Lang.pointer"letfloats=Context.create"Lang.floats"letnew_extern_id=ref(-1)letnew_extern~debug~library~link=incrnew_extern_id;{ext_id=!new_extern_id;ext_library=library;ext_debug=debug;ext_link=link}letext_compareab=Datatype.Int.comparea.ext_idb.ext_id(* -------------------------------------------------------------------------- *)(* --- Sorting & Typing --- *)(* -------------------------------------------------------------------------- *)letsort_of_object=function|C_int_->Logic.Sint|C_pointer_|C_comp_|C_array_->Logic.Sdata|C_floatf->Qed.Kind.of_tau(Context.getfloatsf)letinit_sort_of_object=function|C_int_|C_float_|C_pointer_->Logic.Sbool|C_comp_|C_array_->Logic.Sdataletsort_of_ctypet=sort_of_object(Ctypes.object_oft)letsort_of_ltypet=matchLogic_utils.unroll_type~unroll_typedef:falsetwith|Ctypetyp->sort_of_ctypetyp|Ltype_|Lvar_|Larrow_->Logic.Sdata|Lboolean->Logic.Sbool|Linteger->Logic.Sint|Lreal->Logic.Sreallett_int=Logic.Intlett_bool=Logic.Boollett_real=Logic.Reallett_prop=Logic.Proplett_addr()=Context.getpointerlett_floatf=Context.getfloatsflett_compc=Logic.Data(Comp(c,KValue),[])lett_initc=Logic.Data(Comp(c,KInit),[])lett_arraya=Logic.Array(Logic.Int,a)lett_farrayab=Logic.Array(a,b)lett_datatypeadtts=Logic.Data(adt,ts)letrect_matrixan=ifn>0thent_matrix(t_arraya)(predn)elsealetrectau_of_object=function|C_int_->Logic.Int|C_floatf->t_floatf|C_pointer_->Context.getpointer|C_compc->t_compc|C_array{arr_element=typ}->t_array(tau_of_ctypetyp)andtau_of_ctypetyp=tau_of_object(Ctypes.object_oftyp)letpoly=Context.create"Wp.Lang.poly"letrecinit_of_object=function|C_int_|C_float_|C_pointer_->Logic.Bool|C_compc->t_initc|C_array{arr_element=typ}->t_array(init_of_ctypetyp)andinit_of_ctypetyp=init_of_object(Ctypes.object_oftyp)letrecvarpolykx=function|[]->Warning.error"Unbound type parameter <%s>"x|y::ys->ifx=ythenkelsevarpoly(succk)xystypet_builtin=|E_mdtofmdt|E_why3ofstringlist*string*stringlist|E_polyof(taulist->tau)letbuiltin_types=Context.create"Wp.Lang.builtin_types"letfind_builtinname=Context.getbuiltin_typesnameletadtlt=trymatchfind_builtinlt.lt_namewith|E_mdtm->Mtypem|E_why3(p,m,s)->Wtype(p,m,s)|E_poly_->assertfalsewithNot_found->Atypeltletatypeltts=trymatchfind_builtinlt.lt_namewith|E_mdtm->Logic.Data(Mtypem,ts)|E_why3(p,m,s)->Logic.Data(Wtype(p,m,s),ts)|E_polyftau->ftautswithNot_found->Logic.Data(Atypelt,ts)letrectau_of_ltypet=matchLogic_utils.unroll_type~unroll_typedef:falsetwith|Lboolean->Logic.Bool|Linteger->Logic.Int|Lreal->Logic.Real|Ctypetyp->tau_of_ctypetyp|Lvarx->Logic.Tvar(varpoly1x(Context.getpoly))|Larrow_->Warning.error"array type non-supported(%a)"Printer.pp_logic_typet|Ltype(lt,lts)->atypelt(List.maptau_of_ltypelts)lettau_of_return=functionNone->Logic.Prop|Somet->tau_of_ltypet(* -------------------------------------------------------------------------- *)(* --- Datatypes --- *)(* -------------------------------------------------------------------------- *)moduleADT=structtypet=adtletbasename=function|Mtypea->basename"M"a.ext_link|Mrecord(r,_)->basename"R"r.ext_link|Comp(c,KValue)->basename(ifc.cstructthen"S"else"U")c.corig_name|Comp(c,KInit)->basename(ifc.cstructthen"IS"else"IU")c.corig_name|Atypelt->basename"A"lt.lt_name|Wtype(_,_,s)->letrecbasedef=function[]->def|w::ws->basewwsinbase"w"sletdebug=function|Mtypea->a.ext_debug|Mrecord(a,_)->a.ext_debug|Comp(c,KValue)->comp_idc|Comp(c,KInit)->comp_init_idc|Atypelt->type_idlt|Wtype(p,m,s)->String.concat"."(p@m::s)lethash=function|Mtypea|Mrecord(a,_)->FCHashtbl.hasha|Comp(c,KValue)->Compinfo.hashc|Comp(c,KInit)->13*Compinfo.hashc|Atypelt->Logic_type_info.hashlt|Wtype(p,m,s)->Hashtbl.hash@@(p@m::s)letcompareab=ifa==bthen0elsematcha,bwith|Mtypea,Mtypeb->ext_compareab|Mtype_,_->(-1)|_,Mtype_->(+1)|Mrecord(a,_),Mrecord(b,_)->ext_compareab|Mrecord_,_->(-1)|_,Mrecord_->(+1)|Comp(a,KValue),Comp(b,KValue)|Comp(a,KInit),Comp(b,KInit)->Compinfo.compareab|Comp(_,KValue),Comp(_,KInit)->(-1)|Comp(_,KInit),Comp(_,KValue)->(+1)|Comp_,_->(-1)|_,Comp_->(+1)|Atypea,Atypeb->Logic_type_info.compareab|Atype_,_->(-1)|_,Atype_->(+1)|Wtype(p,m,s),Wtype(p',m',s')->Stdlib.compare(p,m,s)(p',m',s')letequalab=(compareab=0)letprettyfmta=Format.pp_print_stringfmt(debuga)end(* -------------------------------------------------------------------------- *)(* --- Datatypes --- *)(* -------------------------------------------------------------------------- *)letget_builtin_type~name=matchfind_builtinnamewith|E_mdtm->Mtypem|E_why3(p,m,s)->Wtype(p,m,s)|E_poly_->assertfalseletmem_builtin_type~name=tryignore(find_builtinname);truewithNot_found->falseletis_builtinlt=mem_builtin_type~name:lt.lt_nameletis_builtin_type~name=function|Data(Mtypem,_)->begintrymatchfind_builtinnamewith|E_mdtm0->m==m0|_->falsewithNot_found->falseend|Data(Wtype(p,m,s),_)->begintrymatchfind_builtinnamewith|E_why3(p0,m0,s0)->(p,m,s)=(p0,m0,s0)|_->falsewithNot_found->falseend|_->falseletdatatype~libraryname=letm=new_extern~link:name~library~debug:nameinMtypemletfield_observers=ref[]letfield_observefd=List.iter(funk->kfd)!field_observers;fdleton_fieldf=field_observers:=f::!field_observersletcfield?(kind=KValue)fd=field_observe@@Cfield(fd,kind)letrecord~link~libraryfts=letm=new_extern~link~library~debug:linkinletr={fields=[]}inletfs=List.map(fun(f,t)->field_observe@@Mfield(m,r,f,t))ftsinr.fields<-fs;Mrecord(m,r)letfieldtf=matchtwith|Mrecord(_,r)->begintryList.find(functionMfield(_,_,g,_)->f=g|_->false)r.fieldswithNot_found->Wp_parameters.fatal"No field <%s> in record"fend|_->Wp_parameters.fatal"No field <%s> in type '%a'"fADT.prettytletcompc=Comp(c,KValue)letcomp_initc=Comp(c,KInit)letfields_of_adt=function|Mrecord(_,r)->r.fields|Comp(c,k)->List.map(funf->Cfield(f,k))(Option.value~default:[]c.cfields)|_->[]letfields_of_tau=function|Recordfts->List.mapfstfts|Data(adt,_)->fields_of_adtadt|_->[]letfields_of_field=function|Mfield(_,r,_,_)->r.fields|Cfield(f,k)->List.map(funf->Cfield(f,k))(Option.value~default:[]f.fcomp.cfields)lettau_of_field=function|Mfield(_,_,_,t)->t|Cfield(f,KValue)->tau_of_ctypef.ftype|Cfield(f,KInit)->init_of_ctypef.ftypelettau_of_record=function|Mfield(mdt,fs,_,_)->Logic.Data(Mrecord(mdt,fs),[])|Cfield(f,KValue)->t_compf.fcomp|Cfield(f,KInit)->t_initf.fcompmoduleField=structtypet=fieldletdebug=function|Mfield(_,_,f,_)->f|Cfield(f,KValue)->field_idf|Cfield(f,KInit)->field_init_idflethash=function|Mfield(_,_,f,_)->FCHashtbl.hashf|Cfield(f,KValue)->Fieldinfo.hashf|Cfield(f,KInit)->13*Fieldinfo.hashfletcomparefg=iff==gthen0elsematchf,gwith|Mfield(_,_,f,_),Mfield(_,_,g,_)->String.comparefg|Mfield_,Cfield_->(-1)|Cfield_,Mfield_->(+1)|Cfield(f,KValue),Cfield(g,KValue)|Cfield(f,KInit),Cfield(g,KInit)->Fieldinfo.comparefg|Cfield(_,KInit),Cfield(_,KValue)->(-1)|Cfield(_,KValue),Cfield(_,KInit)->(+1)letequalfg=(comparefg=0)letprettyfmtf=Format.pp_print_stringfmt(debugf)letsort=function|Mfield(_,_,_,s)->Qed.Kind.of_taus|Cfield(f,KValue)->sort_of_object(Ctypes.object_off.ftype)|Cfield(f,KInit)->init_sort_of_object(Ctypes.object_off.ftype)end(* -------------------------------------------------------------------------- *)(* --- Functions & Predicates --- *)(* -------------------------------------------------------------------------- *)typelfun=|ACSLofCil_types.logic_info(** Registered in Definition.t, only *)|CTORofCil_types.logic_ctor_info(** Not registered in Definition.t, directly converted/printed *)|FUNoflsymbol(** Generated or External function *)andlsymbol={m_category:lfuncategory;m_params:sortlist;m_result:sort;m_typeof:tauoptionlist->tau;m_source:source;m_coloring:bool;}andsource=|GeneratedofWpContext.contextoption*string|ExternofEngine.linkextern|Wsymbolofstringlist*string*stringlist(* package, module, name *)letlfun_observers=ref[]letlfun_observelf=List.iter(funk->klf)!lfun_observers;lfleton_lfunf=lfun_observers:=f::!lfun_observersletacsllf=lfun_observe(ACSLlf)letctorcf=lfun_observe(CTORcf)letlsymbolm=lfun_observe(FUNm)lettau_of_lfunphits=matchphiwith|ACSLf->tau_of_returnf.l_type|CTORc->ifc.ctor_type.lt_params=[]thenLogic.Data(Atypec.ctor_type,[])elseraiseNot_found|FUNm->matchm.m_resultwith|Sint->Int|Sreal->Real|Sbool->Bool|_->m.m_typeoftsletis_coloring_lfun=function|ACSL_|CTOR_->false|FUN{m_coloring}->m_coloringtypebalance=Nary|Left|Rightletnot_found_=raiseNot_foundletgenerated?(context=false)name=letctxt=ifcontextthenSome(WpContext.get_context())elseNoneinGenerated(ctxt,name)letsymbolf?library?context?link?(balance=Nary)(* specify a default for link *)?(category=Logic.Function)?(params=[])?(sort=Logic.Sdata)?(result:tauoption)?(coloring=false)?(typecheck:(tauoptionlist->tau)option)name=letbuffer=Buffer.create80inFormat.kfprintf(funfmt->Format.pp_print_flushfmt();letname=Buffer.contentsbufferinletsource=matchlibrarywith|None->assert(link=None);generated?contextname|Someth->letconvn=function|Nary->Engine.F_calln|Left->Engine.F_leftn|Right->Engine.F_rightninletlink=matchlinkwith|None->convnamebalance|Someinfo->infoinExtern(new_extern~library:th~link~debug:name)inlettypeof=matchtypecheckwithSomephi->phi|None->matchresultwithSomet->fun_->t|None->not_foundinletresult=matchresultwithSomet->Kind.of_taut|None->sortinlsymbol{m_category=category;m_params=params;m_result=result;m_typeof=typeof;m_source=source;m_coloring=coloring;})(Format.formatter_of_bufferbuffer)nameletextern_s~library?link?category?params?sort?result?coloring?typecheckname=symbolf~library?category?params?sort?result?coloring?typecheck?link"%s"nameletextern_f~library?link?balance?category?params?sort?result?coloring?typecheckname=symbolf~library?category?params?link?balance?sort?result?coloring?typechecknameletextern_p~library?bool?prop?link?(params=[])?(coloring=false)()=letlink=matchbool,prop,linkwith|Someb,Somep,None->Engine.F_bool_prop(b,p)|_,_,Someinfo->info|_,_,_->assertfalseinletdebug=Export.debuglinkinlsymbol{m_category=Logic.Function;m_params=params;m_result=Logic.Sprop;m_typeof=not_found;m_source=Extern(new_extern~library~link~debug);m_coloring=coloring;}letextern_fp~library?(params=[])?link?(coloring=false)phi=letlink=matchlinkwith|None->Engine.F_callphi|Somelink->Engine.F_calllinkinlsymbol{m_category=Logic.Function;m_params=params;m_result=Logic.Sprop;m_typeof=not_found;m_source=Extern(new_extern~library~link~debug:phi);m_coloring=coloring;}letgenerated_f?context?category?params?sort?result?coloringname=symbolf?context?category?params?sort?result?coloringnameletgenerated_p?context?(coloring=false)name=lsymbol{m_category=Logic.Function;m_params=[];m_result=Logic.Sprop;m_typeof=not_found;m_source=generated?contextname;m_coloring=coloring;}letextern_tname~link~library=new_extern~link~library~debug:nameletimported_t~package~theory~name=Wtype(package,theory,name)letimported_f~package~theory~name?(params=[])?(result=Logic.Sprop)?(typecheck=not_found)()=lsymbol{m_category=Logic.Function;m_params=params;m_result=result;m_typeof=typecheck;m_source=Wsymbol(package,theory,name);m_coloring=false;}moduleFun=structtypet=lfunletdebug=function|ACSLf->logic_idf|CTORc->ctor_idc|FUN({m_source=Generated(_,n)})->n|FUN({m_source=Externe})->e.ext_debug|FUN({m_source=Wsymbol(p,m,s)})->String.concat"."(p@m::s)lethash=function|ACSLf->Logic_info.hashf|CTORc->Logic_ctor_info.hashc|FUN({m_source=Generated(_,n)})->Datatype.String.hashn|FUN({m_source=Externe})->e.ext_id|FUN({m_source=Wsymbol(p,m,s)})->Datatype.String.hash@@String.concat"."(p@m::s)letcompare_contextc1c2=matchc1,c2with|None,None->0|None,_->(-1)|_,None->(+1)|Somec1,Somec2->WpContext.S.comparec1c2letcompare_sources1s2=matchs1,s2with|Generated(m1,f1),Generated(m2,f2)->letcmp=String.comparef1f2inifcmp<>0thencmpelsecompare_contextm1m2|Generated_,_->(-1)|_,Generated_->(+1)|Externf,Externg->ext_comparefg|Extern_,_->(-1)|_,Extern_->(+1)|Wsymbol(p,m,s),Wsymbol(p',m',s')->Stdlib.compare(p,m,s)(p',m',s')letcomparefg=iff==gthen0elsematchf,gwith|FUN{m_source=mf},FUN{m_source=mg}->compare_sourcemfmg|FUN_,_->(-1)|_,FUN_->(+1)|ACSLf,ACSLg->Logic_info.comparefg|ACSL_,_->(-1)|_,ACSL_->(+1)|CTORc,CTORd->Logic_ctor_info.comparecdletequalfg=(comparefg=0)letprettyfmtf=Format.pp_print_stringfmt(debugf)letcategory=function|FUNm->m.m_category|ACSL_->Logic.Function|CTOR_->Logic.Constructorletsort=function|FUNm->m.m_result|ACSL{l_type=None}->Logic.Sprop|ACSL{l_type=Somet}->sort_of_ltypet|CTOR_->Logic.Sdataletparameters=ref(fun_->[])letparams=function|FUNm->m.m_params|CTORct->List.mapsort_of_ltypect.ctor_params|(ACSL_)asf->!parametersfendletparametersphi=Fun.parameters:=phiclassvirtualidprinting=object(self)methodvirtualsanitize:string->stringmethodsanitize_type=self#sanitizemethodsanitize_field=self#sanitizemethodsanitize_fun=self#sanitizemethoddatatype=function|Mtypea->a.ext_link|Mrecord(a,_)->a.ext_link|Comp(c,KValue)->self#sanitize_type(comp_idc)|Comp(c,KInit)->self#sanitize_type(comp_init_idc)|Atypelt->self#sanitize_type(type_idlt)|Wtype(p,m,s)->String.concat"."(p@m::s)methodfield=function|Mfield(_,_,f,_)->self#sanitize_fieldf|Cfield(f,KValue)->self#sanitize_field(field_idf)|Cfield(f,KInit)->self#sanitize_field(field_init_idf)methodlink=function|ACSLf->Engine.F_call(self#sanitize_fun(logic_idf))|CTORc->Engine.F_call(self#sanitize_fun(ctor_idc))|FUN({m_source=Generated(_,n)})->Engine.F_call(self#sanitize_funn)|FUN({m_source=Externe})->e.ext_link|FUN({m_source=Wsymbol(p,m,s)})->Engine.F_call(String.concat"."(p@m::s))endletname_of_lfun=function|ACSLf->logic_idf|CTORc->ctor_idc|FUN({m_source=Generated(_,f)})->f|FUN({m_source=Externe})->e.ext_debug|FUN({m_source=Wsymbol(p,m,s)})->String.concat"."(p@m::s)letcontext_of_lfun=function|ACSL_|CTOR_|FUN({m_source=(Extern_|Wsymbol_)})->None|FUN({m_source=Generated(ctxt,_)})->ctxtletname_of_field=function|Mfield(_,_,f,_)->f|Cfield(f,KValue)->field_idf|Cfield(f,KInit)->field_init_idf(* -------------------------------------------------------------------------- *)(* --- Terms --- *)(* -------------------------------------------------------------------------- *)moduleF=structmoduleQZERO=Qed.Term.Make(ADT)(Field)(Fun)(* -------------------------------------------------------------------------- *)(* --- Qed Projectified State --- *)(* -------------------------------------------------------------------------- *)moduleDATA=Datatype.Make(structtypet=QZERO.stateletname="Wp.Qed"letrehash=Datatype.identityletstructural_descr=Structural_descr.t_unknownletreprs=[QZERO.get_state()]letequal=Datatype.undefinedletcompare=Datatype.undefinedlethash=Datatype.undefinedletcopy_old=QZERO.create()letpretty=Datatype.undefinedletmem_project__=falseend)moduleSTATE=State_builder.Register(DATA)(structtypet=QZERO.stateletcreate=QZERO.createletclear=QZERO.clr_stateletget=QZERO.get_stateletset=QZERO.set_stateletclear_some_projects__=falseend)(structletname="Wp.Qed"letdependencies=[Ast.self]letunique_name=nameend)include(STATE:sigend)(* For OCaml-4.0 *)(* -------------------------------------------------------------------------- *)(* --- Term API --- *)(* -------------------------------------------------------------------------- *)modulePretty=Qed.Pretty.Make(QZERO)moduleQED=structincludeQZEROlettypeof?(field=tau_of_field)?(record=tau_of_record)?(call=tau_of_lfun)e=QZERO.typeof~field~record~calleendincludeQED(* Hide force parameter. *)letset_builtinf=QZERO.set_builtinfletset_builtin'f=QZERO.set_builtin'fletset_builtin_eqf=QZERO.set_builtin_eqfletset_builtin_leqf=QZERO.set_builtin_leqfletset_builtin_getf=QZERO.set_builtin_getfletset_builtin_fieldf=QZERO.set_builtin_fieldf(* -------------------------------------------------------------------------- *)(* --- Term Extensions --- *)(* -------------------------------------------------------------------------- *)typeunop=term->termtypebinop=term->term->termlete_zero=QED.constant(e_zintZ.zero)lete_one=QED.constant(e_zintZ.one)lete_minus_one=QED.constant(e_zintZ.minus_one)lete_minus_one_real=QED.constant(e_realQ.minus_one)lete_one_real=QED.constant(e_realQ.one)lete_zero_real=QED.constant(e_realQ.zero)lete_int64z=e_zint(Z.of_string(Int64.to_stringz))lete_factke=e_times(Z.of_intk)elete_bigintz=e_zint(Z.of_string(Integer.to_stringz))lete_rangeab=e_sum[b;e_one;e_oppa]lete_setfieldrfv=(*TODO:NUPW: check for UNIONS *)letr=List.map(fung->g,ifField.equalfgthenvelsee_getfieldrg)(fields_of_fieldf)ine_recordr(* -------------------------------------------------------------------------- *)(* --- Predicates --- *)(* -------------------------------------------------------------------------- *)typepred=termtypecmp=term->term->predtypeoperator=pred->pred->predletp_boolt=tlete_propt=tletp_boolsxs=xslete_propsxs=xslete_liftf=fletp_liftf=fletis_zeroe=matchQED.reprewith|Kintz->Integer.equalzInteger.zero|_->falseleteqp=equalletcomparep=compareletis_ptrue=is_trueletis_pfalse=is_falseletis_equalab=is_true(e_eqab)letis_inte=trytypeofe=Qed.Logic.IntwithNot_found->falseletis_reale=trytypeofe=Qed.Logic.RealwithNot_found->falseletis_prope=trymatchtypeofewithQed.Logic.Prop|Qed.Logic.Bool->true|_->falsewithNot_found->falseletis_arithe=trymatchtypeofewithQed.Logic.Int|Qed.Logic.Real->true|_->falsewithNot_found->falseletp_equal=e_eqletp_equals=List.map(fun(x,y)->p_equalxy)letp_neq=e_neqletp_leq=e_leqletp_lt=e_ltletp_positivee=e_leqe_zeroeletp_true=e_trueletp_false=e_falseletp_not=e_notletp_bind=e_bindletp_forall=e_forallletp_exists=e_existsletp_subst=e_substletp_subst_var=e_subst_varletp_andpq=e_and[p;q]letp_orpq=e_or[p;q]letp_implyhp=e_imply[h]pletp_hypshsp=e_implyhspletp_equiv=e_equivletp_if=e_ifletp_conj=e_andletp_disj=e_orletp_allfxs=e_and(List.mapfxs)letp_anyfxs=e_or(List.mapfxs)lete_varse=List.sortVar.compare(Vars.elements(varse))letp_vars=e_varsletp_call=e_fun~result:Propletp_close=e_close_forallletoccursxt=Vars.memx(varst)letintersectab=Vars.intersect(varsa)(varsb)letoccursp=occursletintersectp=intersectletvarsp=varsletp_expr=reprlete_expr=reprletpp_tau=Pretty.pp_tauletcontext_pp=Context.create"Lang.F.pp"letpp_termfmte=ifWp_parameters.has_dkeydkey_prettythenQED.debugfmteelsematchContext.get_optcontext_ppwith|Someenv->Pretty.pp_term_envenvfmte|None->letenv=Pretty.knownPretty.empty(QED.varse)inPretty.pp_termenvfmteletpp_pred=pp_termletpp_varfmtx=pp_termfmt(e_varx)letpp_varsfmtxs=beginFormat.fprintffmt"@[<hov 2>{";Vars.iter(funx->Format.fprintffmt"@ %a"pp_varx)xs;Format.fprintffmt" }@]";endletdebugp=QED.debugtypeenv=Pretty.envletenvxs=Pretty.knownPretty.emptyxsletmarker=Pretty.marksletmark_e=QED.markletmark_p=QED.markletdefinefenvm=List.fold_left(funenvt->letx,env_x=Pretty.freshenvtinfenvxt;env_x)env(QED.defsm)letpp_eterm=Pretty.pp_termletpp_epred=Pretty.pp_termmodulePmap=TmapmodulePset=Tsetletset_builtin_1fr=set_builtinf(function[e]->re|_->raiseNot_found)letset_builtin_2fr=set_builtinf(function[a;b]->rab|_->raiseNot_found)letset_builtin_2'fr=set_builtin'f(function[a;b]->rab|_->raiseNot_found)letset_builtin_eqp=set_builtin_eqendopenFmoduleN=structlet(+)=e_addlet(~-:)x=e_sube_zeroxlet(-)=e_sublet(*)=e_mullet(/)=e_divlet(mod)=e_modlet(=)=p_equallet(<)=p_ltlet(>)xy=p_ltyxlet(<=)=p_leqlet(>=)xy=p_leqyxlet(<>)=p_neqlet(==>)=p_implylet(&&:)=p_andlet(||:)=p_orletnot=p_notlet($)=e_funlet($$)=p_callend(* -------------------------------------------------------------------------- *)(* --- Local Assumptions --- *)(* -------------------------------------------------------------------------- *)typegamma={mutablehyps:predlist;}letcpool=Context.create"Lang.pool"letcgamma=Context.create"Lang.gamma"letadd_varspool=function|None->()|Somexs->F.add_varspoolxsletnew_pool?copy?(vars=Vars.empty)()=letpool=F.pool?copy()inF.add_varspoolvars;poolletnew_gamma?copy()=matchcopywith|None->{hyps=[]}|Someg->{hyps=g.hyps}letget_pool()=Context.getcpoolletget_gamma()=Context.getcgammalethas_gamma()=Context.definedcgammaletfreshvar?basenametau=F.fresh(Context.getcpool)?basenametauletfreshenx=F.alpha(Context.getcpool)xletlocal?pool?vars?gammaf=letpool=matchpoolwithNone->F.pool()|Somep->pinadd_varspoolvars;letgamma=matchgammawithNone->{hyps=[]}|Someg->ginContext.bindcpoolpool(Context.bindcgammagammaf)letsigma()=F.sigma~pool:(Context.getcpool)()letalpha()=letsigma=sigma()inletalpha=refTmap.emptyinletlookupex=tryTmap.finde!alphawithNot_found->lety=F.Subst.freshsigma(F.tau_of_varx)inletey=e_varyinalpha:=Tmap.addeey!alpha;eyinletcomputee=matchF.reprewith|Fvarx->lookupex|_->raiseNot_foundinF.Subst.add_funsigmacompute;sigmaletsubstxsvs=letsigma=sigma()inbegintryList.iter2(funxv->F.Subst.addsigma(e_varx)v)xsvswithInvalid_argument_->raise(Invalid_argument"Wp.Lang.Subst.sigma")end;sigmalete_substf=letsigma=sigma()inF.Subst.add_funsigmaf;F.e_substsigmaletp_substf=letsigma=sigma()inF.Subst.add_funsigmaf;F.p_substsigma(* -------------------------------------------------------------------------- *)(* --- Hypotheses --- *)(* -------------------------------------------------------------------------- *)letmasked=reffalseletwithout_assumejobx=if!maskedthenjobxelsetrymasked:=true;lety=jobxinmasked:=false;ywitherr->masked:=false;raiseerrletassumep=ifp!=p_true&¬!maskedthenletd=Context.getcgammaind.hyps<-p::d.hypslethypothesesg=g.hypsletget_hypotheses()=(Context.getcgamma).hypsletfilter_hypothesesxs=letd=Context.getcgammainletvars=List.fold_rightVars.addxsVars.emptyinletmatchesp=Vars.intersectvars(varspp)inleths_with_vars,hs_without_vars=List.partitionmatchesd.hypsind.hyps<-hs_without_vars;hs_with_vars(** For why3_api but circular dependency *)moduleFor_export=structtypespecific_equality={for_tau:(tau->bool);mk_new_eq:F.binop;}(** delay the create at most as possible (due to constants handling in qed) *)letstate=refNoneletinit=ref(fun()->())letadd_initf=letold=!initininit:=(fun()->old();f())letget_state()=match!statewith|None->letst=QZERO.create()inQZERO.in_statest!init();state:=Somest;st|Somest->stletrebuild?cachet=QZERO.rebuild_in_state(get_state())?cachetletset_builtinfc=add_init(fun()->QZERO.set_builtin~force:truefc)letset_builtin'fc=add_init(fun()->QZERO.set_builtin'~force:truefc)letset_builtin_eqfc=add_init(fun()->QZERO.set_builtin_eq~force:truefc)letset_builtin_leqfc=add_init(fun()->QZERO.set_builtin_leq~force:truefc)letin_statefv=QZERO.in_state(get_state())fvend(* -------------------------------------------------------------------------- *)(* --- Simplifier --- *)(* -------------------------------------------------------------------------- *)exceptionContradictionclasstypesimplifier=objectmethodname:stringmethodcopy:simplifiermethodassume:F.pred->unitmethodtarget:F.pred->unitmethodfixpoint:unitmethodinfer:F.predlistmethodequivalent_exp:F.term->F.termmethodweaker_hyp:F.pred->F.predmethodequivalent_branch:F.pred->F.predmethodstronger_goal:F.pred->F.predendletis_atomic_pred=function|Neq_|Eq_|Leq_|Lt_|Fun_->true|_->falseletis_literalp=matchreprpwith|Notp->is_atomic_pred(reprp)|_->is_atomic_pred(reprp)letiter_consequence_literalsf_literalp=letf_literal=(funp->ifQED.lc_closedpthenf_literalpelse())inletrecaux_posp=matchreprpwith|Andps->List.iteraux_posps|Notp->aux_negp|Bind((Forall|Exists),_,a)->aux_pos(QED.lc_repra)|repwhenis_atomic_predrep->f_literalp|_->()andaux_negp=matchreprpwith|Imply(hs,p)->List.iteraux_poshs;aux_negp|Orps->List.iteraux_negps|Notp->aux_posp|Bind((Forall|Exists),_,a)->aux_neg(QED.lc_repra)|repwhenis_atomic_predrep->f_literal(e_notp)|_->()inaux_posp(* -------------------------------------------------------------------------- *)