12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485(**************************************************************************)(* *)(* SPDX-License-Identifier LGPL-2.1 *)(* Copyright (C) *)(* CEA (Commissariat à l'énergie atomique et aux énergies alternatives) *)(* *)(**************************************************************************)openLangopenConditionsopenTactical(** Useful **)letstr_case="Case"letsub_casesphi=function|[]->List.map(funt->phistr_case(F.p_boolt))|[descr]->List.map(funt->phidescr(F.p_boolt))|infos->List.map2(funinfot->phiinfo(F.p_boolt))infos(* split into n sequents: [hyps] |- [subcases]_i *)letf_replace_goalinfossubcases(hyps,_)=letsub_casedescrp=descr,(hyps,p)insub_casessub_caseinfossubcases(* split into n sequents: [subcases]_i, hyps/[hyp] |- goal
in fact, [hyp] is replaced by [subcases]_i *)letf_replace_hyphypinfossubcasessequent=letsub_casedescrp=descr,Conditions.(replace~at:hyp.id(update_condhyp~descr(Whenp))sequent)insub_casessub_caseinfossubcases(* -------------------------------------------------------------------------- *)(* --- FNC (goal) and FND (hyp) tacticals --- *)(* -------------------------------------------------------------------------- *)letnf_conj_argse=matchF.reprewith|Qed.Logic.Andxs->xs|_->[e]letnf_disj_argse=matchF.reprewith|Qed.Logic.Orxs->xs|_->[e]letf_nf_goale~depth=f_replace_goal["CNF"](nf_conj_args(WpTac.e_cnf~depthe))letf_nf_hypse~depth=f_replace_hyps["DNF"](nf_disj_args(WpTac.e_dnf~depthe))letmatch_selection=function|Clause(Goalp)->lete=Lang.F.e_proppinifWpTac.is_cnfethenNoneelseSome(true,e,f_nf_goale)|Clause(Steps)->beginmatchs.conditionwith|(Typep|Havep|Whenp|Corep|Initp)->lete=Lang.F.e_proppinifWpTac.is_dnfethenNoneelseSome(false,e,f_nf_hypse)|_->Noneend|Inside(_,_)|Compose_|Empty|Multi_->Noneclassnormal_form=objectinheritTactical.make~id:"Wp.normal_form"~title:"Intuition"~descr:"Decompose into conjunctive or disjunctive normal form."~params:[]methodselectfeedback(s:Tactical.selection)=matchmatch_selectionswith|Some(pol,_,continuation)->feedback#set_title(ifpolthen"Intuition (CNF)"else"Intuition (DNF)");letdepth=(-1)inApplicable(continuation~depth)|_->Not_applicableendlettactical=Tactical.export(newnormal_form)letstrategy=Strategy.maketactical~arguments:[](* -------------------------------------------------------------------------- *)