123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102(************************************************************************)(* * The Rocq Prover / The Rocq Development Team *)(* v * Copyright INRIA, CNRS and contributors *)(* <O___,, * (see version control and CREDITS file for authors & dates) *)(* \VV/ **************************************************************)(* // * This file is distributed under the terms of the *)(* * GNU Lesser General Public License Version 2.1 *)(* * (see LICENSE file for the text of the license) *)(************************************************************************)openProofview.Notations(** Focussing tactics *)type'afocus=|Uniformof'a|Dependsof'alist(** Type of tactics potentially goal-dependent. If it contains a [Depends],
then the length of the inner list is guaranteed to be the number of
currently focused goals. Otherwise it means the tactic does not depend
on the current set of focused goals. *)type'at='afocusProofview.tacticletreturn(x:'a):'at=Proofview.tclUNIT(Uniformx)letbind(typea)(typeb)(m:at)(f:a->bt):bt=m>>=function|Uniformx->fx|Dependsl->letfarg=farg>>=function|Uniformx->(* We dispatch the uniform result on each goal under focus, as we know
that the [m] argument was actually dependent. *)Proofview.Goal.goals>>=fungoals->letans=List.map(fung->(g,x))goalsinProofview.tclUNITans|Dependsl->Proofview.Goal.goals>>=fungoals->Proofview.tclUNIT(List.combinegoalsl)in(* After the tactic has run, some goals which were previously
produced may have been solved by side effects. The values
attached to such goals must be discarded, otherwise the list of
result would not have the same length as the list of focused
goals, which is an invariant of the [Ftactic] module. It is the
reason why a goal is attached to each result above. *)letfilter(g,x)=g>>=fung->Proofview.Goal.unsolvedg>>=function|true->Proofview.tclUNIT(Somex)|false->Proofview.tclUNITNoneinProofview.tclDISPATCHL(List.mapfl)>>=funl->Proofview.Monad.List.map_filterfilter(List.concatl)>>=funfiltered->Proofview.tclUNIT(Dependsfiltered)letgoals=Proofview.Goal.goals>>=funl->Proofview.tclUNIT(Dependsl)letenterf=bindgoals(fungl->gl>>=fungl->Proofview.wrap_exceptions(fun()->fgl))letwith_envt=t>>=function|Uniforma->Proofview.tclENV>>=funenv->Proofview.tclUNIT(Uniform(env,a))|Dependsl->Proofview.Goal.goals>>=fungs->Proofview.Monad.(List.map(mapProofview.Goal.env)gs)>>=funenvs->Proofview.tclUNIT(Depends(List.combineenvsl))letlift(typea)(t:aProofview.tactic):at=Proofview.tclBINDt(funx->Proofview.tclUNIT(Uniformx))(** If the tactic returns unit, we can focus on the goals if necessary. *)letrunmk=m>>=function|Uniformv->kv|Dependsl->lettacs=List.mapklinProofview.tclDISPATCHtacslet(>>=)=bindlet(<*>)=funmn->bindm(fun()->n)moduleSelf=structtype'at='afocusProofview.tacticletreturn=returnlet(>>=)=bindlet(>>)=(<*>)letmapfx=x>>=funa->return(fa)endmoduleFtac=Monad.Make(Self)moduleList=Ftac.ListmoduleNotations=structlet(>>=)=bindlet(<*>)=funmn->bindm(fun()->n)end