123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531(**************************************************************************)(* *)(* 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). *)(* *)(**************************************************************************)(* -------------------------------------------------------------------------- *)(* --- Server API for WP --- *)(* -------------------------------------------------------------------------- *)moduleP=Server.PackagemoduleD=Server.DatamoduleR=Server.RequestmoduleS=Server.StatesmoduleMd=MarkdownmoduleAST=Server.Kernel_astletpackage=P.package~plugin:"wp"~name:"tac"~title:"WP Tactics"()(* -------------------------------------------------------------------------- *)(* --- Tacticals --- *)(* -------------------------------------------------------------------------- *)moduleJtactic:D.Swithtypet=Tactical.t=structtypet=Tactical.tletjtype=P.Jkey"tactic"letto_json(t:Tactical.t)=`Stringt#idletof_json(js:Json.t)=Tactical.lookup~id:(js|>Json.string)end(* -------------------------------------------------------------------------- *)(* --- Tactical Kind --- *)(* -------------------------------------------------------------------------- *)moduleJkind:D.Swithtypet=string=structincludeD.Jstringletjtype=D.declare~package~name:"kind"~descr:(Md.plain"Parameter kind")(Junion[Jtag"checkbox";Jtag"spinner";Jtag"selector";Jtag"browser";Jtag"editor";])end(* -------------------------------------------------------------------------- *)(* --- Tactical Status --- *)(* -------------------------------------------------------------------------- *)moduleJstatus:R.Outputwithtypet=Tactical.status=structtypet=Tactical.statusletjtype=D.declare~package~name:"status"~descr:(Md.plain"Tactical status")(Junion[Jtag"NotApplicable";Jtag"NotConfigured";Jtag"Applicable";])letto_json(s:Tactical.status)=matchswith|Not_applicable->`String"NotApplicable"|Not_configured->`String"NotConfigured"|Applicable_->`String"Applicable"end(* -------------------------------------------------------------------------- *)(* --- Named Value Encoding --- *)(* -------------------------------------------------------------------------- *)typevalue=V:'aTactical.named->valuemoduleJvalue=structtypet=valueletjtype=D.declare~package~name:"value"~descr:(Md.plain"Parameter option value")(Jrecord["id",Jkey"value";"label",Jstring;"title",Jstring])letof_json_=D.failure"not implemented"letto_json(Va)=`Assoc["id",`Stringa.vid;"label",`Stringa.title;"title",`Stringa.descr;]endletjvaluesvlist=List.map(funv->Vv)vlistletjoptions(typea)(values:aTactical.namedlist)(equal:a->a->bool):aD.data=letmoduleM=structtypet=aletjtype=P.Jstringletto_jsona=try`String(List.find(funv->equalv.Tactical.valuea)values).vidwithNot_found->`Nullletof_jsonjs:t=letid=Json.stringjsintry(List.find(funv->v.Tactical.vid=id)values).valuewithNot_found->D.failure"Incorrect value"endin(moduleM:(D.Swithtypet=a))letjbrowser(typea)(find:aTactical.finder):aTactical.namedoptionD.data=letmoduleM=structtypet=aTactical.namedoptionletjtype=P.Jstringletto_json=function|None->`String""|SomeTactical.{vid}->`Stringvidletof_jsonjs=letid=Json.stringjsintrySome(findid)withNot_found->Noneendin(moduleM:(D.Swithtypet=aTactical.namedoption))(* -------------------------------------------------------------------------- *)(* --- Selection Data --- *)(* -------------------------------------------------------------------------- *)moduleJselection:D.Swithtypet=Tactical.selection=structtypet=Tactical.selectionletjtype=D.Jtext.jtypeletrecppfmt=function|Tactical.Empty->Format.fprintffmt""|Clause(Goal_)->Format.fprintffmt"@{<#goal>Goal@}"|Clause(Steps)->Format.fprintffmt"@{<#s%d>Hyp. #%d@}"s.ids.id|Inside(Goal_,t)->letid=Lang.F.QED.idtinFormat.fprintffmt"@{<#goal>@{<#e%d>\"#%d\"@}@}"idid|Inside(Steps,t)->letid=Lang.F.QED.idtinFormat.fprintffmt"@{<#s%d>@{<#e%d>\"#%d\"@}@}"s.ididid|Composecc->pcfmtcc|Multi_->()andpcfmt=function|Tactical.Cintk->Integer.prettyfmtk|Range(a,b)->Format.fprintffmt"%d..%d"ab|Code(_,f,[])->Format.fprintffmt"%s()"f|Code(_,f,x::xs)->Format.fprintffmt"@[<hov 2>%s(%a"fppx;List.iter(Format.fprintffmt",@ %a"pp)xs;Format.fprintffmt")@]"letto_jsons=D.jprettyppsletof_json_=Tactical.Emptyend(* -------------------------------------------------------------------------- *)(* --- Tactic Parameters & Fields --- *)(* -------------------------------------------------------------------------- *)moduleJparam=(valD.jkey~kind:"param")moduleJparameter=structopenD.Recordtyperecordletrecord:recordsignature=signature()letid=fieldrecord~name:"id"~descr:(Md.plain"Parameter identifier")(moduleJparam)letkind=fieldrecord~name:"kind"~descr:(Md.plain"Parameter kind")(moduleJkind)letlabel=fieldrecord~name:"label"~descr:(Md.plain"Short name")(moduleD.Jstring)lettitle=fieldrecord~name:"title"~descr:(Md.plain"Description")(moduleD.Jstring)letenabled=fieldrecord~name:"enabled"~descr:(Md.plain"Enabled parameter")~default:true(moduleD.Jbool)letvalue=fieldrecord~name:"value"~descr:(Md.plain"Value (with respect to kind)")(moduleD.Jany)letvmin=optionrecord~name:"vmin"~descr:(Md.plain"Minimum range value (spinner only)")(moduleD.Jint)letvmax=optionrecord~name:"vmax"~descr:(Md.plain"Maximum range value (spinner only)")(moduleD.Jint)letvstep=optionrecord~name:"vstep"~descr:(Md.plain"Range step (spinner only)")(moduleD.Jint)letvlist=optionrecord~name:"vlist"~descr:(Md.plain"List of options (selector only)")(moduleD.Jlist(Jvalue))include(valpublish~package~name:"parameter"~descr:(Md.plain"Parameter configuration")record)endclassparameter~(tactic:Tactical.t)~(field:'aTactical.field)~(kind:string)~(data:'aD.data)?(range:intTactical.rangeoption)?(options:'aTactical.namedlistoption)()=letfd=Tactical.signaturefieldinobject(self)valmutablep_label=fd.titlevalmutablep_title=fd.descrvalmutablep_vmin=Nonevalmutablep_vmax=Nonevalmutablep_vstep=Nonevalmutablep_enabled=trueinitializerself#resetmethodid=Tactical.identfieldmethodreset=beginp_label<-fd.title;p_title<-fd.descr;p_vmin<-Option.bindrange(funrg->rg.vmin);p_vmax<-Option.bindrange(funrg->rg.vmax);p_vstep<-Option.map(funrg->rg.Tactical.vstep)range;p_enabled<-true;endmethodimport(js:D.json)=tactic#set_fieldfield(D.data_of_jsondatajs)methodupdate~id?enabled?title?tooltip?vmin?vmax()=ifid=fd.vidthenbeginOption.iter(fune->p_enabled<-e)enabled;Option.iter(funs->p_label<-s)title;Option.iter(funs->p_title<-s)tooltip;ifvmin<>Nonethenp_vmin<-vmin;ifvmax<>Nonethenp_vmax<-vmax;endmethodexport:D.json=letmoduleJ=JparameterinJ.default|>J.setJ.idfd.vid|>J.setJ.kindkind|>J.setJ.labelp_label|>J.setJ.titlep_title|>J.setJ.value(tactic#get_fieldfield|>D.data_to_jsondata)|>J.setJ.enabledp_enabled|>J.setJ.vminp_vmin|>J.setJ.vmaxp_vmax|>J.setJ.vstepp_vstep|>J.setJ.vlist(Option.mapjvaluesoptions)|>J.to_jsonendletmaketactic(param:Tactical.parameter):parameter=matchparamwith|Checkboxfield->newparameter~tactic~field~kind:"checkbox"~data:D.jbool()|Spinner(field,range)->newparameter~tactic~field~kind:"spinner"~data:D.jint~range()|Selector(field,options,equal)->letdata=joptionsoptionsequalinnewparameter~tactic~field~kind:"selector"~data~options()|Search(field,_,find)->letdata=jbrowserfindinnewparameter~tactic~field~kind:"browser"~data()|Composer(field,_)->newparameter~tactic~field~kind:"editor"~data:(moduleJselection)()moduleParameterConfig:D.Swithtypet=parameter=structtypet=parameterletjtype=Jparameter.jtypeletof_json_=D.failure"not implemented"letto_json(p:parameter)=p#exportend(* -------------------------------------------------------------------------- *)(* --- Tactical Configuration --- *)(* -------------------------------------------------------------------------- *)classconfigurator(tactic:Tactical.tactical)=letparameters=List.map(maketactic)tactic#paramsinobject(self)valmutablelocal:Lang.F.pooloption=Nonevalmutabletitle=tactic#titlevalmutabledescr=tactic#descrvalmutableerror=Nonevalmutablestatus=Tactical.Not_applicablevalmutableanchor:ProofEngine.nodeoption=Nonevalmutabletarget=Tactical.Empty(* Basics *)methodreset=beginlocal<-None;title<-tactic#title;descr<-tactic#descr;error<-None;anchor<-None;target<-Tactical.Empty;List.iter(funp->p#reset)parameters;endmethodid=tactic#idmethodparams=parametersmethodlookup~pid=List.find(funp->p#id=pid)parameters(* Feedback Interface *)methodpool=Option.getlocalmethodinteractive=truemethodhas_error=error<>Nonemethodget_title=titlemethodget_descr=descrmethodget_error=errormethodset_title:'a.'aTactical.formatter=funmsg->Pretty_utils.ksfprintf(funm->title<-m)msgmethodset_descr:'a.'aTactical.formatter=funmsg->Pretty_utils.ksfprintf(funm->descr<-m)msgmethodset_error:'a.'aTactical.formatter=funmsg->Pretty_utils.ksfprintf(funm->error<-Somem)msgmethodupdate_field:'a.?enabled:bool->?title:string->?tooltip:string->?range:bool->?vmin:int->?vmax:int->?filter:(Lang.F.term->bool)->'aTactical.field->unit=fun?enabled?title?tooltip?range?vmin?vmax?filterfield->ignorerange;ignorefilter;letid=Tactical.identfieldinList.iter(fun(p:parameter)->p#update~id?enabled?title?tooltip?vmin?vmax())parameters(* Processing *)methodstatus=statusmethodprivateselectnodepoolselection=trylocal<-Somepool;error<-None;title<-tactic#title;descr<-tactic#descr;anchor<-Somenode;target<-selection;status<-tactic#select(self:>Tactical.feedback)selection;local<-None;withexn->local<-None;status<-Not_applicable;anchor<-None;target<-Tactical.Empty;error<-Some(Printf.sprintf"Error (%s)"(Printexc.to_stringexn));ifnot@@Cmdline.catch_at_toplevelexnthenraiseexnmethodconfigurenodeselection=lettree=ProofEngine.treenodeinletpool=ProofEngine.pooltreeinletctxt=ProofEngine.tree_contexttreeinWpContext.on_contextctxt(self#selectnodepool)selectionmethodprivatecommittreenodeprocess=tryletjtactic=ProofScript.jtactictactictargetinletfork=ProofEngine.forktree~anchor:nodejtacticprocessinletchildren=snd@@ProofEngine.commitforkinList.mapsndchildrenwithexn->local<-None;anchor<-None;target<-Tactical.Empty;error<-Some(Printf.sprintf"Error (%s)"(Printexc.to_stringexn));ifnot@@Cmdline.catch_at_toplevelexnthenraiseexn;[]methodapply=matchanchor,statuswith|Somenode,Applicableprocess->lettree=ProofEngine.treenodeinletctxt=ProofEngine.tree_contexttreeinWpContext.on_contextctxt(self#committreenode)process|_->[]end(* -------------------------------------------------------------------------- *)(* --- Tactical Status --- *)(* -------------------------------------------------------------------------- *)(* indexed by tactical Id. *)letindex:(string,configurator)Hashtbl.t=Hashtbl.create0letconfiguratortactic=letid=tactic#idintryHashtbl.findindexidwithNot_found->letcfg=newconfiguratortacticinHashtbl.addindexidcfg;cfgletiterf=Tactical.iter(funt->f@@configuratort)lettactics=letmodel:configuratorS.model=S.model()inS.columnmodel~name:"label"~descr:(Md.plain"Tactic name")~data:(moduleD.Jstring)~get:(funcfg->cfg#get_title);S.columnmodel~name:"title"~descr:(Md.plain"Tactic description")~data:(moduleD.Jstring)~get:(funcfg->cfg#get_descr);S.optionmodel~name:"error"~descr:(Md.plain"Tactic error")~data:(moduleD.Jstring)~get:(funcfg->cfg#get_error);S.columnmodel~name:"status"~descr:(Md.plain"Tactic status")~data:(moduleJstatus)~get:(funcfg->cfg#status);S.columnmodel~name:"params"~descr:(Md.plain"Configuration parameters")~data:(moduleD.Jlist(ParameterConfig))~get:(funcfg->cfg#params);S.register_array~package~name:"tactical"~descr:(Md.plain"Tactical Configurations")~key:(funcfg->cfg#id)~keyName:"id"~keyType:Jtactic.jtype~itermodel(* -------------------------------------------------------------------------- *)(* --- Tactical Target Configuration --- *)(* -------------------------------------------------------------------------- *)let()=letconfigureTactics=R.signature~output:(moduleD.Junit)()inletget_node=R.paramconfigureTactics~name:"node"~descr:(Md.plain"Proof node target")(moduleWpTipApi.Node)inR.register_sig~package~kind:`EXEC~name:"configureTactics"~descr:(Md.plain"Configure all tactics")~signals:[WpTipApi.printStatus]configureTacticsbeginfunrq()->letnode=get_noderqinletselection=WpTipApi.selectionnodeiniter(funcfg->cfg#configurenodeselection);S.reloadtactics;end(* -------------------------------------------------------------------------- *)(* --- Tactical Parameter Configuration --- *)(* -------------------------------------------------------------------------- *)let()=letsetParameter=R.signature~output:(moduleD.Junit)()inletget_node=R.paramsetParameter~name:"node"~descr:(Md.plain"Proof node target")(moduleWpTipApi.Node)inletget_tactic=R.paramsetParameter~name:"tactic"~descr:(Md.plain"Tactic to configure")(moduleJtactic)inletget_param=R.paramsetParameter~name:"param"~descr:(Md.plain"Parameter to configure")(moduleJparam)inletget_value=R.paramsetParameter~name:"value"~descr:(Md.plain"New parameter value")(moduleD.Jany)inR.register_sig~package~kind:`EXEC~name:"setParameter"~descr:(Md.plain"Configure tactical parameter")setParameterbeginfunrq()->letnode=get_noderqinlettac=get_tacticrqinletpid=get_paramrqinletcfg=configuratortacinletprm=cfg#lookup~pidinletselection=WpTipApi.selectionnodeinprm#import(get_valuerq);cfg#configurenodeselection;S.updatetacticscfg;end(* -------------------------------------------------------------------------- *)(* --- Applying Tactic --- *)(* -------------------------------------------------------------------------- *)let()=R.register~package~kind:`EXEC~name:"applyTactic"~descr:(Md.plain"Applies the (configured) tactic")~input:(moduleJtactic)~output:(moduleD.Jlist(WpTipApi.Node))beginfuntactic->letcfg=configuratortacticinletchildren=cfg#applyinS.updatetacticscfg;childrenend(* -------------------------------------------------------------------------- *)