123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377(**************************************************************************)(* *)(* 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 --- *)(* -------------------------------------------------------------------------- *)openWpApimoduleP=Server.PackagemoduleD=Server.DatamoduleR=Server.RequestmoduleS=Server.StatesmoduleMd=MarkdownmoduleAST=Server.Kernel_astletpackage=P.package~plugin:"wp"~name:"tip"~title:"WP Interactive Prover"()(* -------------------------------------------------------------------------- *)(* --- Proof Node --- *)(* -------------------------------------------------------------------------- *)letproofStatus=R.signal~package~name:"proofStatus"~descr:(Md.plain"Proof Status has changed")moduleNode=D.Index(Map.Make(ProofEngine.Node))(structletname="node"end)let()=letsnode=R.signature~input:(moduleNode)()inletset_title=R.resultsnode~name:"result"~descr:(Md.plain"Proof node title")(moduleD.Jstring)inletset_proved=R.resultsnode~name:"proved"~descr:(Md.plain"Proof node complete")(moduleD.Jbool)inletset_pending=R.resultsnode~name:"pending"~descr:(Md.plain"Pending children")(moduleD.Jint)inletset_size=R.resultsnode~name:"size"~descr:(Md.plain"Proof size")(moduleD.Jint)inletset_stats=R.resultsnode~name:"stats"~descr:(Md.plain"Node statistics")(moduleD.Jstring)inR.register_sig~package~kind:`GET~name:"getNodeInfos"~descr:(Md.plain"Proof node information")snode~signals:[proofStatus]beginfunrqnode->set_titlerq(ProofEngine.titlenode);set_provedrq(ProofEngine.provednode);set_pendingrq(ProofEngine.pendingnode);lets=ProofEngine.statsnodeinset_sizerq(Stats.subgoalss);set_statsrq(Pretty_utils.to_stringStats.prettys);end(* -------------------------------------------------------------------------- *)(* --- Proof Tree --- *)(* -------------------------------------------------------------------------- *)let()=letstate=R.signature~input:(moduleGoal)()inletset_current=R.resultstate~name:"current"~descr:(Md.plain"Current proof node")(moduleNode)inletset_parents=R.resultstate~name:"parents"~descr:(Md.plain"Proof node parents")(moduleD.Jlist(Node))inletset_pending=R.resultstate~name:"pending"~descr:(Md.plain"Pending proof nodes")(moduleD.Jint)inletset_index=R.resultstate~name:"index"~descr:(Md.plain"Current node index among pending nodes (else -1)")(moduleD.Jint)inletset_results=R.resultstate~name:"results"~descr:(Md.plain"Prover results for current node")(moduleD.Jlist(D.Jpair(Prover)(Result)))inletset_tactic=R.resultstate~name:"tactic"~descr:(Md.plain"Proof node tactic header (if any)")(moduleD.Jstring)inletset_children=R.resultstate~name:"children"~descr:(Md.plain"Proof node tactic children (id any)")(moduleD.Jlist(D.Jpair(D.Jstring)(Node)))inR.register_sig~package~kind:`GET~name:"getProofState"~descr:(Md.plain"Current Proof Status of a Goal")state~signals:[proofStatus]beginfunrqwpo->lettree=ProofEngine.proof~main:wpoinletcurrent,index=matchProofEngine.currenttreewith|`Main->ProofEngine.roottree,-1|`Internalnode->node,-1|`Leaf(idx,node)->node,idxinletrecparentsnode=matchProofEngine.parentnodewith|None->[]|Somep->p::parentspinlettactic=matchProofEngine.tacticalcurrentwith|None->""|Some{header}->headerinset_currentrqcurrent;set_parentsrq(parentscurrent);set_indexrqindex;set_pendingrq(ProofEngine.pendingcurrent);set_resultsrq(Wpo.get_results(ProofEngine.goalcurrent));set_tacticrqtactic;set_childrenrq(ProofEngine.childrencurrent);end(* -------------------------------------------------------------------------- *)(* --- Proof Tree Management --- *)(* -------------------------------------------------------------------------- *)let()=R.register~package~kind:`SET~name:"goForward"~descr:(Md.plain"Go to to first pending node, or root if none")~input:(moduleGoal)~output:(moduleD.Junit)beginfungoal->lettree=ProofEngine.proof~main:goalinProofEngine.forwardtree;R.emitproofStatus;endlet()=R.register~package~kind:`SET~name:"goToRoot"~descr:(Md.plain"Go to root of proof tree")~input:(moduleGoal)~output:(moduleD.Junit)beginfungoal->lettree=ProofEngine.proof~main:goalinProofEngine.gototree`Main;R.emitproofStatus;endlet()=R.register~package~kind:`SET~name:"goToIndex"~descr:(Md.plain"Go to k-th pending node of proof tree")~input:(moduleD.Jpair(Goal)(D.Jint))~output:(moduleD.Junit)beginfun(goal,index)->lettree=ProofEngine.proof~main:goalinProofEngine.gototree(`Leafindex);R.emitproofStatus;endlet()=R.register~package~kind:`SET~name:"goToNode"~descr:(Md.plain"Set current node of associated proof tree")~input:(moduleNode)~output:(moduleD.Junit)beginfunnode->lettree=ProofEngine.treenodeinProofEngine.gototree(`Nodenode);R.emitproofStatus;endlet()=R.register~package~kind:`SET~name:"removeNode"~descr:(Md.plain"Remove node from tree and go to parent")~input:(moduleNode)~output:(moduleD.Junit)beginfunnode->lettree=ProofEngine.treenodeinProofEngine.removetreenode;R.emitproofStatus;end(* -------------------------------------------------------------------------- *)(* --- Sequent Indexers --- *)(* -------------------------------------------------------------------------- *)moduleTerm=D.Tagged(structtypet=Lang.F.termletidt=Printf.sprintf"#e%d"(Lang.F.QED.idt)end)(structletname="term"end)modulePart=D.Tagged(structtypet=[`Term|`Goal|`Stepofint]letid=function|`Term->"#term"|`Goal->"#goal"|`Stepk->Printf.sprintf"#s%d"kend)(structletname="part"end)letof_part=function|Ptip.Term->"#term"|Ptip.Goal->"#goal"|Ptip.Steps->Printf.sprintf"#s%d"s.idletto_partsequent=function|`Term->Ptip.Term|`Goal->Ptip.Goal|`Stepk->tryPtip.Step(Conditions.step_atsequentk)withNot_found->Ptip.Term(* -------------------------------------------------------------------------- *)(* --- Sequent Printer --- *)(* -------------------------------------------------------------------------- *)letwraptagppfmtx=beginFormat.pp_open_stagfmt(Format.String_tagtag);ppfmtx;Format.pp_close_stagfmt();endclassprinter():Ptip.pseq=letterms:Ptip.term_wrapper=objectmethodwrapppfmtt=wrap(Term.gett)ppfmttendinletfocus:Ptip.term_wrapper=objectmethodwrapppfmtt=wrap"wp:focus"ppfmttendinlettarget:Ptip.term_wrapper=objectmethodwrapppfmtt=wrap"wp:target"ppfmttendinletparts:Ptip.part_marker=objectmethodwrapppfmtp=wrap(of_partp)ppfmtpmethodmark:'a.Ptip.part->'aPtip.printer->'aPtip.printer=funpppfmtx->wrap(of_partp)ppfmtxendinletautofocus=newPtip.autofocusinletplang=newPtip.plang~terms~focus~target~autofocusinletpcond=newPtip.pcond~parts~target:parts~autofocus~planginPtip.pseq~autofocus~plang~pcond(* -------------------------------------------------------------------------- *)(* --- Printer Registry --- *)(* -------------------------------------------------------------------------- *)letprintStatus=R.signal~package~name:"printStatus"~descr:(Md.plain"Updated TIP printer")modulePRINTER=State_builder.Ref(Datatype.Make(structincludeDatatype.Undefinedtypet=(string,printer)Hashtbl.tletname="WpTipApi.PRINTER.Datatype"letreprs=[Hashtbl.create0]letmem_project=Datatype.never_any_projectend))(structletname="WpApi.PRINTER"letdependencies=[Ast.self]letdefault()=Hashtbl.create0end)let()=Wpo.add_removed_hook(funwpo->letregistry=PRINTER.get()inHashtbl.removeregistrywpo.po_gid)let()=Wpo.add_cleared_hook(fun()->letregistry=PRINTER.get()inHashtbl.clearregistry)letlookup_printer(node:ProofEngine.node):printer=lettree=ProofEngine.treenodeinletwpo=ProofEngine.maintreeinletregistry=PRINTER.get()intryHashtbl.findregistrywpo.po_gidwithNot_found->letpp=newprinter()inHashtbl.addregistrywpo.po_gidpp;ppletselectionnode=letpp=lookup_printernodeinpp#selection(* -------------------------------------------------------------------------- *)(* --- PrintSequent Request --- *)(* -------------------------------------------------------------------------- *)letflags(typea)~name~descrtags:aR.input=(modulestructtypet=aletjtype=D.declare~package~name~descr(P.Junion(List.map(fun(tg,_)->P.Jtagtg)tags))letof_jsonjs=List.assoc(Json.stringjs)tagsend)letiformat:Plang.iformatR.input=flags~name:"iformat"~descr:(Md.plain"Integer constants format")["dec",`Dec;"hex",`Hex;"bin",`Bin]letrformat:Plang.rformatR.input=flags~name:"rformat"~descr:(Md.plain"Real constants format")["ratio",`Ratio;"float",`Float;"double",`Double]let()=letprintSequent=R.signature~output:(moduleD.Jtext)()inletget_node=R.paramprintSequent~name:"node"~descr:(Md.plain"Proof Node")(moduleNode)inletget_indent=R.param_optprintSequent~name:"indent"~descr:(Md.plain"Number of identation spaces")(moduleD.Jint)inletget_margin=R.param_optprintSequent~name:"margin"~descr:(Md.plain"Maximial text width")(moduleD.Jint)inletget_iformat=R.param_optprintSequent~name:"iformat"~descr:(Md.plain"Integer constants format")iformatinletget_rformat=R.param_optprintSequent~name:"rformat"~descr:(Md.plain"Real constants format")rformatinletget_autofocus=R.param_optprintSequent~name:"autofocus"~descr:(Md.plain"Auto-focus mode")(moduleD.Jbool)inletget_unmangled=R.param_optprintSequent~name:"unmangled"~descr:(Md.plain"Unmangled memory model")(moduleD.Jbool)inR.register_sig~package~kind:`EXEC~name:"printSequent"~descr:(Md.plain"Pretty-print the associated node")~signals:[printStatus]printSequentbeginfunrq()->letnode=get_noderqinletpp=lookup_printernodeinletindent=get_indentrqinletmargin=get_marginrqinOption.iterpp#set_iformat(get_iformatrq);Option.iterpp#set_rformat(get_rformatrq);Option.iterpp#set_focus_mode(get_autofocusrq);Option.iterpp#set_unmangled(get_unmangledrq);D.jpretty?indent?marginpp#pp_goal(ProofEngine.goalnode)end(* -------------------------------------------------------------------------- *)(* --- Selection Requests --- *)(* -------------------------------------------------------------------------- *)let()=R.register~package~kind:`SET~name:"clearSelection"~descr:(Md.plain"Reset node selection")~input:(moduleNode)~output:(moduleD.Junit)beginfunnode->letpp=lookup_printernodeinpp#reset;R.emitprintStatusendlet()=letsetSelection=R.signature~output:(moduleD.Junit)()inletget_node=R.paramsetSelection~name:"node"~descr:(Md.plain"Proof Node")(moduleNode)inletget_part=R.paramsetSelection~name:"part"~default:`Term~descr:(Md.plain"Selected part")(modulePart)inletget_term=R.param_optsetSelection~name:"term"~descr:(Md.plain"Selected term")(moduleTerm)inletget_extend=R.paramsetSelection~name:"extend"~descr:(Md.plain"Extending selection mode")~default:false(moduleD.Jbool)inR.register_sig~package~kind:`SET~name:"setSelection"~descr:(Md.plain"Set node selection")setSelectionbeginfunrq()->letnode=get_noderqinletpart=get_partrqinletterm=get_termrqinletextend=get_extendrqinletpp=lookup_printernodeinletpart=to_part(fstpp#sequent)partinpp#restore~focus:(ifextendthen`Extendelse`Focus)(part,term);R.emitprintStatusend(* -------------------------------------------------------------------------- *)