123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483(**************************************************************************)(* *)(* 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). *)(* *)(**************************************************************************)openTacticalopenConditions(* -------------------------------------------------------------------------- *)(* --- Step Look Around --- *)(* -------------------------------------------------------------------------- *)letaroundfkn=matchfkwith|Somes->s|None->letrecscanfkin=matchf(k-i)with|Somes->s|None->matchf(k+i)with|Somes->s|None->letj=succiinifk+j<n||j<=kthenscanfkjnelseraiseNot_foundinscanfk1nlets_kinds=matchs.conditionwith|Have_|When_|Core_->"have"|Type_->"type"|Init_->"init"|Branch_->"branch"|Either_->"either"|State_->"state"letcheck_pattern~patternp=ifnot(Footprint.matchespattern(Lang.F.e_propp))thenraiseNot_foundletlookup_occur~occurp=Footprint.lookup~occur~inside:(Lang.F.e_propp)letlookup_step~kind~patternhsk=trylets=Conditions.step_athskinifs_kinds<>kindthenraiseNot_found;letp=Conditions.headsincheck_pattern~patternp;SomeswithNot_found->Noneletlookup_inside~kind~occurhsk=trylets=Conditions.step_athskinifs_kinds<>kindthenraiseNot_found;letp=Conditions.headsinSome(s,lookup_occur~occurp)withNot_found->Noneletlocate_step~at~kind~patternhs=around(lookup_step~kind~patternhs)at(Conditions.sizehs)letlocate_inside~at~kind~occurhs=around(lookup_inside~kind~occurhs)at(Conditions.sizehs)(* -------------------------------------------------------------------------- *)(* --- Selection of Json --- *)(* -------------------------------------------------------------------------- *)letpatternp=Footprint.pattern(Lang.F.e_propp)letoccurpt=Footprint.locate~inside:(Lang.F.e_propp)~select:tletj_selects="select",`Stringsletj_goal=j_select"clause-goal"letj_step=j_select"clause-step"letj_ingoal=j_select"inside-goal"letj_instep=j_select"inside-step"letj_compose=j_select"compose"letj_multi=j_select"multi"letj_kint=j_select"kint"letj_range=j_select"range"letj_ida="id",`Stringaletj_ats="at",`Ints.idletj_intz="val",`String(Integer.to_stringz)letj_mina="min",`Intaletj_maxb="max",`Intbletj_kinds="kind",`String(s_kinds)letj_patternp="pattern",`Stringpletj_ppatternp=j_pattern(patternp)letj_occurk="occur",`Intkletj_predp=lettgt=Pretty_utils.to_stringLang.F.pp_predpin"target",`Stringtgtletj_terme=lettgt=Pretty_utils.to_stringLang.F.pp_termein"target",`Stringtgtletrecjson_of_selection=function|Empty->`Null|Composecode->json_of_composecode|Clause(Goalp)->`Assoc[j_goal;j_predp;j_ppatternp]|Clause(Steps)->letp=Conditions.headsin`Assoc[j_step;j_ats;j_kinds;j_predp;j_ppatternp]|Inside(Goalp,e)->letn,m=occurpein`Assoc[j_ingoal;j_occurn;j_terme;j_patternm]|Inside(Steps,e)->letn,m=occur(Conditions.heads)ein`Assoc[j_instep;j_ats;j_kinds;j_occurn;j_terme;j_patternm]|Multies->`Assoc(j_multi::j_argses)andj_args=function|[]->[]|es->["args",`List(List.mapjson_of_selectiones)]andjson_of_compose=function|Cinta->`Assoc[j_kint;j_inta]|Range(a,b)->`Assoc[j_range;j_mina;j_maxb]|Code(_,id,es)->`Assoc(j_compose::j_idid::j_argses)(* -------------------------------------------------------------------------- *)(* --- Json to Selection --- *)(* -------------------------------------------------------------------------- *)let(>?)js(fd:string)=Json.fieldfdjslet(|>)jsop=opjsletj_patternjs=js>?"pattern"|>Json.stringletj_atjs=js>?"at"|>Json.intletj_kindjs=js>?"kind"|>Json.stringletj_occurjs=js>?"occur"|>Json.intletj_idjs=js>?"id"|>Json.stringletj_argsjs=js>?"args"|>Json.listletj_valjs=js>?"val"|>Json.string|>Integer.of_stringletj_minjs=js>?"min"|>Json.intletj_maxjs=js>?"max"|>Json.intletrecselection_of_json((hs,g)ass:sequent)js=tryletkey=js>?"select"|>Json.stringinmatchkeywith|"clause-goal"->check_pattern~pattern:(j_patternjs)g;Clause(Goalg)|"clause-step"->letpattern=j_patternjsinlets=locate_step~at:(j_atjs)~kind:(j_kindjs)~patternhsinClause(Steps)|"inside-goal"->letoccur=j_occurjs,j_patternjsinInside(Goalg,lookup_occur~occurg)|"inside-step"->letoccur=j_occurjs,j_patternjsinlets,e=locate_inside~at:(j_atjs)~kind:(j_kindjs)~occurhsinInside(Steps,e)|"compose"->letid=j_idjsinletargs=j_argsjsinTactical.composeid(List.map(selection_of_jsons)args)|"multi"->letargs=j_argsjsinTactical.multi@@List.map(selection_of_jsons)args|"kint"->Tactical.cint(j_valjs)|"range"->Tactical.range(j_minjs)(j_maxjs)|_->raiseNot_foundwithNot_found|Invalid_argument_->Emptyletselection_targetjs=js>?"target"|>Json.stringletjson_of_named=function|None->`Null|Somea->`AssocTactical.["id",`Stringa.vid;"title",`Stringa.title;"descr",`Stringa.descr;]letnamed_of_jsonfindjs=tryletvid=js>?"id"|>Json.stringinSome(findvid)withNot_found|Invalid_argument_->None(* -------------------------------------------------------------------------- *)(* --- Tactical Json Parameters --- *)(* -------------------------------------------------------------------------- *)letjson_of_param(tac:tactical)=function|Checkboxfd->identfd,Json.of_bool(tac#get_fieldfd)|Spinner(fd,_)->identfd,Json.of_int(tac#get_fieldfd)|Composer(fd,_)->identfd,json_of_selection(tac#get_fieldfd)|Selector(fd,options,equal)->identfd,`Stringbegintryleta=tac#get_fieldfdinletv=List.find(funv->equalv.valuea)optionsinv.vidwith_->"default"end|Search(fd,_,_)->identfd,json_of_named(tac#get_fieldfd)letparam_of_json(tac:tactical)seqjs=function|Checkboxfd->tac#set_fieldfd(tryJson.bool(Json.field(identfd)js)with_->defaultfd)|Spinner(fd,_)->tac#set_fieldfd(tryJson.int(Json.field(identfd)js)with_->defaultfd)|Composer(fd,_)->letsel=(tryselection_of_jsonseq(Json.field(identfd)js)with_->defaultfd)intac#set_fieldfdsel|Selector(fd,options,_)->tac#set_fieldfdbegintryletjid=Json.string(Json.field(identfd)js)inletv=List.find(funv->v.vid=jid)optionsinv.valuewith_->defaultfdend|Search(fd,_,find)->tac#set_fieldfdbegintrynamed_of_jsonfind(Json.field(identfd)js)with_->Noneendletjson_of_parameters(tac:tactical)=`Assoc(List.map(json_of_paramtac)tac#params)letparameters_of_json(tac:tactical)sequentjs=List.iter(param_of_jsontacsequentjs)tac#params(* -------------------------------------------------------------------------- *)(* --- Tactic Encoding --- *)(* -------------------------------------------------------------------------- *)typejtactic={header:string;tactic:string;params:Json.t;select:Json.t;strategy:stringoption;}letjtactic?strategy(tac:tactical)(sel:selection)={header=tac#title;tactic=tac#id;params=json_of_parameterstac;select=json_of_selectionsel;strategy;}letjson_of_tactictjs=letstrategy=matcht.strategywith|None->[]|Somes->["strategy",`Strings]inlettactical=["header",`Stringt.header;"tactic",`Stringt.tactic;"params",t.params;"select",t.select;"children",`Assocjs;]in`Assoc(strategy@tactical)letchildren_of_json=function|`Listjs->Wp_parameters.warning~current:false~once:true"Deprecated script(s) found ; consider using prover 'tip'";List.map(funj->"",j)js|`Assocfs->fs|_->[]lettactic_of_jsonjs=tryletheader=js>?"header"|>Json.stringinlettactic=js>?"tactic"|>Json.stringinletparams=tryjs>?"params"withNot_found->`Nullinletselect=tryjs>?"select"withNot_found->`Nullinletchildren=tryjs>?"children"|>children_of_jsonwithNot_found->[]inletstrategy=trySome(js>?"strategy"|>Json.string)withNot_found->NoneinSome({header;tactic;params;select;strategy},children)with_->None(* -------------------------------------------------------------------------- *)(* --- Prover Encoding --- *)(* -------------------------------------------------------------------------- *)letjson_of_verdict=function|VCS.NoResult|VCS.Computing_->`String"none"|VCS.Valid->`String"valid"|VCS.Unknown->`String"unknown"|VCS.Timeout->`String"timeout"|VCS.Stepout->`String"stepout"|VCS.Failed->`String"failed"letverdict_of_json=function|`String"valid"->VCS.Valid|`String"unknown"->VCS.Unknown|`String"timeout"->VCS.Timeout|`String"stepout"->VCS.Stepout|`String"failed"->VCS.Failed|_->VCS.NoResultletjson_of_result(p:VCS.prover)(r:VCS.result)=letopenVCSinletname="prover",`String(VCS.name_of_proverp)inletverdict="verdict",json_of_verdictr.verdictinlettime=ifr.prover_time>0.0then["time",`Floatr.prover_time]else[]inletsteps=ifr.prover_steps>0then["steps",`Intr.prover_steps]else[]in`Assoc(name::verdict::(time@steps))letprover_of_jsonjs=tryVCS.parse_prover(js>?"prover"|>Json.string)withNot_found->Noneletresult_of_jsonjs=letverdict=tryjs>?"verdict"|>verdict_of_jsonwith_->VCS.NoResultinlettime=tryjs>?"time"|>Json.floatwith_->0.0inletsteps=tryjs>?"steps"|>Json.intwith_->0inVCS.result~time~stepsverdict(* -------------------------------------------------------------------------- *)(* --- Script --- *)(* -------------------------------------------------------------------------- *)typejscript=alternativelistandalternative=|ProverofVCS.prover*VCS.result|Tacticofint*jtactic*(string*jscript)list(* pending goals *)|Errorofstring*Json.tletis_prover=functionProver_->true|Tactic_|Error_->falseletis_tactic=functionTactic_->true|Prover_|Error_->falseletpending=function|Prover(_,r)->ifVCS.is_validrthen0else1|Tactic(n,_,_)->n|Error_->1letrecpending_any=function|[]->1|[a]->pendinga|a::s->letn=pendingainifn=0then0elseminn(pending_anys)letrecsubgoalsn=function|[]->n|(_,js)::s->subgoals(n+pending_anyjs)slethas_proof=List.existsis_tacticleta_proverpr=Prover(p,r)leta_tactictacchildren=Tactic(subgoals0children,tac,children)(* -------------------------------------------------------------------------- *)(* --- Codecs --- *)(* -------------------------------------------------------------------------- *)letrecdecode=function|`Null->[]|`Listalts->List.mapalternativealts|js->[Error("Invalid Script",js)]andsubscript(key,js)=key,decodejsandalternativejs=matchprover_of_jsonjswith|Someprover->Prover(prover,result_of_jsonjs)|None->matchtactic_of_jsonjswith|Some(tactic,children)->a_tactictactic(List.mapsubscriptchildren)|None->Error("Invalid Tactic",js)letrecencodescript=`List(alternativesscript)andsubgoal(k,alt)=k,encodealtandalternatives=function|[]->[]|Prover(p,r)::scr->json_of_resultpr::alternativesscr|Tactic(_,t,s)::scr->json_of_tactict(List.mapsubgoals)::alternativesscr|Error_::scr->alternativesscrletconfigurejtacticsequent=trylettactical=Tactical.lookup~id:jtactic.tacticintactical#reset;parameters_of_jsontacticalsequentjtactic.params;Conditions.indexsequent;letselect=selection_of_jsonsequentjtactic.selectinSome(tactical,select)withNot_found->None(* -------------------------------------------------------------------------- *)(* --- Console --- *)(* -------------------------------------------------------------------------- *)classconsole~pool~title=objectvalmutablethe_title=titlemethodpool:Lang.F.pool=poolmethodinteractive=falsemethodget_title=the_titlemethodset_title:'a.'aformatter=funmsg->Pretty_utils.ksfprintf(funs->the_title<-s)msgmethodset_descr:'a.'aformatter=funmsg->Pretty_utils.ksfprintf(funs->ignores)msgmethodupdate_field:'a.?enabled:bool->?title:string->?tooltip:string->?range:bool->?vmin:int->?vmax:int->?filter:(Lang.F.term->bool)->'afield->unit=fun?enabled?title?tooltip?range?vmin?vmax?filterfield->ignoreenabled;ignoretitle;ignoretooltip;ignorefield;ignorevmin;ignorevmax;ignorerange;ignorefilter;()valmutableerrors=falsemethodhas_error=errorsmethodset_error:'a.'aformatter=funmsg->Pretty_utils.ksfprintf(funs->errors<-true;Wp_parameters.warning"[%s] %s"titles)msgend(* -------------------------------------------------------------------------- *)