123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575(**************************************************************************)(* *)(* 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). *)(* *)(**************************************************************************)(* -------------------------------------------------------------------------- *)(* --- Logic Definitions --- *)(* -------------------------------------------------------------------------- *)openLogicUsageopenCil_typesopenCil_datatypeopenQed.LogicopenLangopenLang.Ftypetrigger=(var,lfun)Qed.Engine.ftriggertypetypedef=(tau,field,lfun)Qed.Engine.ftypedefletrecrev_iterf=function|[]->()|x::w->rev_iterfw;fxtypecluster={c_id:string;c_title:string;c_position:Filepath.positionoption;mutablec_age:int;mutablec_records:compinfolist;mutablec_irecords:compinfolist;mutablec_types:logic_type_infolist;mutablec_symbols:dfunlist;mutablec_lemmas:dlemmalist;}anddlemma={l_name:string;l_cluster:cluster;l_kind:predicate_kind;l_forall:varlist;l_triggers:triggerlistlist(* OR of AND triggers *);l_lemma:pred;}anddfun={d_lfun:lfun;d_cluster:cluster;d_types:int;d_params:varlist;d_definition:definition;}anddefinition=|Logicoftau(* return type of an abstract function *)|Functionoftau*recursion*term|Predicateofrecursion*pred|Inductiveofdlemmalistandrecursion=Def|RecmoduleTrigger=structopenQed.Engineletrecof_expmodet=matchF.reprtwith|Fvarx->TgVarx|Aget(a,k)->TgGet(of_expCterma,of_expCtermk)|Aset(a,k,v)->TgSet(of_expCterma,of_expCtermk,of_expCtermv)|Fun(f,ts)->letts=List.map(of_expCterm)tsinbeginmatchmodewith|Cterm->TgFun(f,ts)|Cprop->TgProp(f,ts)end|_->TgAnyletof_termt=of_expCtermtletof_predp=of_expCprop(F.e_propp)letreccollectxs=function|TgAny->xs|TgVarx->Vars.addxxs|TgGet(a,k)->collect(collectxsa)k|TgSet(a,k,v)->collect(collect(collectxsa)k)v|TgFun(_,ts)|TgProp(_,ts)->List.fold_leftcollectxstsletvars=collectVars.empty(* let rec pretty fmt = function
* | TgAny -> assert false
* | TgVar x -> Lang.F.QED.Var.pretty fmt x
* | TgGet(t,k) -> Format.fprintf fmt "@[<hov 2>%a[%a]@]" pretty t pretty k
* | TgSet(t,k,v) -> Format.fprintf fmt "@[<hov 2>%a[%a@ <- %a]@]" pretty t pretty k pretty v
* | TgFun(f,ts) ->
* | TgProp(f,ts) -> call Cprop f fmt ts *)end(* -------------------------------------------------------------------------- *)(* --- Registry --- *)(* -------------------------------------------------------------------------- *)moduleCluster=WpContext.Index(structtypekey=stringtypedata=clusterletname="Definitions.Cluster"letcompare=String.compareletpretty=Format.pp_print_stringend)moduleSymbol=WpContext.Index(structtypekey=lfuntypedata=dfunletname="Definitions.Symbol"letcompare=Lang.Fun.compareletpretty=Lang.Fun.prettyend)moduleLemma=WpContext.Index(structtypekey=stringtypedata=dlemmaletname="Definitions.Lemma"letcompare=String.compareletpretty=Format.pp_print_stringend)lettouchc=c.c_age<-succc.c_agelet()=beginSymbol.callback(fun_f->touchf.d_cluster;f.d_cluster.c_symbols<-f::f.d_cluster.c_symbols);Lemma.callback(fun_a->toucha.l_cluster;a.l_cluster.c_lemmas<-a::a.l_cluster.c_lemmas);endletfind_symbol=Symbol.findletdefine_symbolf=Symbol.definef.d_lfunfletupdate_symbolf=Symbol.updatef.d_lfunfletfind_name=Lemma.findletfind_lemmal=Lemma.findl.lem_nameletcompile_lemmaccl=Lemma.compile(fun_name->ccl)l.lem_nameletdefine_lemmal=Lemma.definel.l_namelletdefine_typect=begintouchc;c.c_types<-t::c.c_types;endletparametersf=ifWpContext.is_defined()thentryList.mapLang.F.QED.sort_of_var(Symbol.findf).d_paramswithNot_found->[]else[]let()=Lang.parametersparameters(* -------------------------------------------------------------------------- *)(* --- Helpers --- *)(* -------------------------------------------------------------------------- *)letcluster_idc=c.c_idletcluster_titlec=c.c_titleletcluster_positionc=c.c_positionletcluster_agec=c.c_ageletcluster_compareab=String.comparea.c_idb.c_idletpp_clusterfmtc=Format.pp_print_stringfmtc.c_idletiterf=Cluster.iter_sorted(fun_keyc->fc)letnewcluster~id?title?position()={c_id=id;c_title=(matchtitlewithSomet->t|None->id);c_position=position;c_age=0;c_types=[];c_records=[];c_irecords=[];c_symbols=[];c_lemmas=[];}letcluster~id?title?position()=Cluster.memoize(funid->newcluster~id?title?position())idletdummy()=cluster~id:"dummy"()letaxiomaticax=Cluster.memoize(funid->lettitle=Printf.sprintf"Axiomatic '%s'"ax.ax_nameinletposition=ax.ax_positioninletcluster=newcluster~id~title~position()incluster)(Printf.sprintf"A_%s"ax.ax_name)letsection=function|Toplevel0->cluster~id:"Axiomatic"~title:"Global Definitions"()|Topleveln->letid="Axiomatic"^string_of_intninlettitle=Printf.sprintf"Global Definitions (continued #%d)"nincluster~id~title()|Axiomaticax->axiomaticaxletcompinfoc=Cluster.memoize(funid->lettitle=ifc.cstructthenPrintf.sprintf"Struct '%s'"c.cnameelsePrintf.sprintf"Union '%s'"c.cnameinletcluster=newcluster~id~title()incluster.c_records<-[c];cluster)(Lang.comp_idc)leticompinfoc=Cluster.memoize(funid->lettitle=ifc.cstructthenPrintf.sprintf"Init Struct '%s'"c.cnameelsePrintf.sprintf"Init Union '%s'"c.cnameinletcluster=newcluster~id~title()incluster.c_irecords<-[c];cluster)(Lang.comp_init_idc)letmatrix()=cluster~id:"Matrix"~title:"Basic Arrays"()letcall_fun~resultlfuncces=Symbol.compile(Lang.localcc)lfun;e_fun~resultlfunesletcall_predlfuncces=Symbol.compile(Lang.localcc)lfun;p_calllfunes(* -------------------------------------------------------------------------- *)(* --- Cluster Dependencies --- *)(* -------------------------------------------------------------------------- *)moduleDT=Logic_type_info.SetmoduleDR=Compinfo.SetmoduleDS=Datatype.String.SetmoduleDF=Set.Make(Lang.Fun)moduleDC=Set.Make(structtypet=clusterletcompare=cluster_compareend)(* -------------------------------------------------------------------------- *)(* --- Markers (test and set) --- *)(* -------------------------------------------------------------------------- *)typeaxioms=cluster*logic_lemmalistclassvirtualvisitormain=object(self)valmutableterms=Tset.emptyvalmutabletypes=DT.emptyvalmutablecomps=DR.emptyvalmutableicomps=DR.emptyvalmutablesymbols=DF.emptyvalmutabledlemmas=DS.emptyvalmutablelemmas=DS.emptyvalmutableclusters=DC.emptyvalmutabletheories=DS.emptyvalmutablelocals=DC.addmainDC.emptymethodset_localc=locals<-DC.addclocalsmethoddo_localc=ifDC.memclocalsthentrueelse(self#vclusterc;false)methodprivatevtau_of_ltypelt=lettau=Lang.tau_of_ltypeltinself#vtautau;taumethodvtypet=ifnot(DT.memttypes)thenbegintypes<-DT.addttypes;letcluster=section(LogicUsage.section_of_typet)inifself#do_localcluster&¬(Lang.is_builtint)thenbeginletdef=matcht.lt_defwith|None->Qed.Engine.Tabs|Some(LTsynlt)->Qed.Engine.Tdef(self#vtau_of_ltypelt)|Some(LTsumcs)->letcases=List.map(func->Lang.ctorc,List.mapself#vtau_of_ltypec.ctor_params)csinQed.Engine.Tsumcasesinself#on_typetdef;endendmethodvcompr=ifnot(DR.memrcomps)thenbegincomps<-DR.addrcomps;letc=compinforinifself#do_localcthenbeginletfts=Option.map(List.map(funf->lett=Lang.tau_of_ctypef.ftypeinself#vtaut;cfieldf,t))r.cfieldsinself#on_comprfts;endendmethodvicompr=ifnot(DR.memricomps)thenbeginicomps<-DR.addricomps;letc=icompinforinifself#do_localcthenbeginletfts=Option.map(List.map(funf->lett=Lang.init_of_ctypef.ftypeinself#vtaut;cfield~kind:KInitf,t))r.cfieldsinself#on_icomprfts;endendmethodvfield=function|Mfield(a,_,_,_)->self#vlibrarya.ext_library|Cfield(f,KValue)->self#vcompf.fcomp|Cfield(f,KInit)->self#vicompf.fcompmethodvadt=function|Mtypea|Mrecord(a,_)->self#vlibrarya.ext_library|Comp(r,KValue)->self#vcompr|Comp(r,KInit)->self#vicompr|Atypet->self#vtypetmethodvtau=function|Prop|Bool|Int|Real|Tvar_->()|Array(a,b)->self#vtaua;self#vtaub|Record_->assertfalse|Data(a,ts)->self#vadta;List.iterself#vtautsmethodvparamx=self#vtau(tau_of_varx)methodprivaterepr~boolt=begintryself#vtau(Lang.F.typeoft);withNot_found->Wp_parameters.debug~level:2"@[<hov 2>Untyped term: %a@]"F.pp_termt;end;matchF.reprtwith|Fun(f,_)->self#vsymbolf|Rget(_,f)->self#vfieldf|Rdeffts->List.iter(fun(f,_)->self#vfieldf)fts|Fvarx->self#vparamx|Bind(_,qt,_)->self#vtauqt|True|False|Kint_|Kreal_|Bvar_|Times_|Add_|Mul_|Div_|Mod_|Aget_|Aset_|Apply_->()|Acst_->self#on_library"const"|Eq_|Neq_|Leq_|Lt_|And_|Or_|Not_|Imply_|If_->ifboolthenself#on_library"bool"methodvtermt=ifnot(Tset.memtterms)thenbeginterms<-Tset.addtterms;self#repr~bool:truet;F.lc_iterself#vtermt;endmethodvpredp=lett=F.e_proppinifnot(Tset.memtterms)thenbeginself#repr~bool:falset;F.lc_iter(fune->ifF.is_propethenself#vpred(F.p_boole)elseself#vterme)tendmethodprivatevdefinition=function|Logict->self#vtaut|Function(t,_,e)->self#vtaut;self#vterme|Predicate(_,p)->self#vpredp|Inductive_->()methodprivatevproperties=function|Logic_|Function_|Predicate_->()|Inductivecases->List.iter(funl->self#vdlemmal)casesmethodprivatevdfund=letold_terms=termsinterms<-Tset.empty;begintryList.iterself#vparamd.d_params;self#vdefinitiond.d_definition;self#vpropertiesd.d_definition;self#on_dfund;withe->terms<-old_terms;raiseeend;terms<-old_termsmethodprivatevlfunf=matchSymbol.findfwith|exceptionNot_found->Wp_parameters.fatal"Undefined symbol '%a'"Fun.prettyf|d->letc=d.d_clusterinifself#do_localcthenself#vdfundmethodvsymbolf=ifnot(DF.memfsymbols)thenbeginsymbols<-DF.addfsymbols;matchfwith|FUN{m_source=Externe}->self#vlibrarye.ext_library|FUN{m_source=Generated_}|ACSL_->self#vlfunf|CTORc->self#vadt(Lang.adtc.ctor_type)endmethodprivatevtrigger=function|Qed.Engine.TgAny->()|Qed.Engine.TgVarx->self#vparamx|Qed.Engine.TgGet(a,k)->beginself#vtriggera;self#vtriggerk;end|Qed.Engine.TgSet(a,k,v)->beginself#vtriggera;self#vtriggerk;self#vtriggerv;end|Qed.Engine.TgFun(f,tgs)|Qed.Engine.TgProp(f,tgs)->self#vsymbolf;List.iterself#vtriggertgsmethodprivatevdlemmaa=ifnot(DS.mema.l_namedlemmas)thenbegindlemmas<-DS.adda.l_namedlemmas;List.iterself#vparama.l_forall;List.iter(List.iterself#vtrigger)a.l_triggers;self#vpreda.l_lemma;endmethodvlemmalem=letl=lem.lem_nameinifnot(DS.memllemmas)thenbeginlemmas<-DS.addllemmas;tryleta=Lemma.findlinifself#do_locala.l_clusterthen(self#vdlemmaa;self#on_dlemmaa)withNot_found->Wp_parameters.fatal"Lemma '%s' undefined"lendmethodvclusterc=ifnot(DC.memcclusters)thenbeginclusters<-DC.addcclusters;self#on_clusterc;endmethodvlibrarythy=ifnot(DS.memthytheories)thenbegintheories<-DS.addthytheories;tryletdeps=LogicBuiltins.dependenciesthyinList.iterself#vlibrarydeps;self#on_librarythy;withNot_found->Wp_parameters.fatal~current:false"Unknown library '%s'"thyendmethodvgoal(axioms:axiomsoption)prop=matchaxiomswith|None->(* Visit a goal *)beginleths=LogicUsage.proof_context()inList.iterself#vlemmahs;self#vpredprop;end|Some(cluster,hs)->(* Visit the goal corresponding to a lemma *)beginself#section(cluster_titlecluster);self#set_localcluster;List.iterself#vlemmahs;self#vpredprop;endmethodvtypes=(* Visit the types *)rev_iterself#vcompmain.c_records;rev_iterself#vicompmain.c_irecords;rev_iterself#vtypemain.c_typesmethodvsymbols=(* Visit the definitions *)rev_iter(fund->self#vsymbold.d_lfun)main.c_symbols;methodvlemmas=(* Visit the lemmas *)rev_iter(funl->self#vdlemmal;self#on_dlemmal)main.c_lemmas;methodvself=(* Visit a cluster *)beginself#vtypes;self#vsymbols;self#vlemmas;endmethodvirtualsection:string->unitmethodvirtualon_library:string->unitmethodvirtualon_cluster:cluster->unitmethodvirtualon_type:logic_type_info->typedef->unitmethodvirtualon_comp:compinfo->(field*tau)listoption->unitmethodvirtualon_icomp:compinfo->(field*tau)listoption->unitmethodvirtualon_dlemma:dlemma->unitmethodvirtualon_dfun:dfun->unitend(* -------------------------------------------------------------------------- *)