123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191(******************************************************************************)(* This file is part of Waterproof-lib. *)(* *)(* Waterproof-lib is free software: you can redistribute it and/or modify *)(* it under the terms of the GNU General Public License as published by *)(* the Free Software Foundation, either version 3 of the License, or *)(* (at your option) any later version. *)(* *)(* Waterproof-lib 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 General Public License for more details. *)(* *)(* You should have received a copy of the GNU General Public License *)(* along with Waterproof-lib. If not, see <https://www.gnu.org/licenses/>. *)(* *)(******************************************************************************)openProofopenProof_bullet(** The majority of the code below is copied and adapted directly from
the source code of the Rocq theorem prover itself, namely from Proof_bullet.ml. *)(** Preparatory definitions that are useful for both defined modes. *)letbullet_eqb1b2=matchb1,b2with|Dashn1,Dashn2->n1=n2|Starn1,Starn2->n1=n2|Plusn1,Plusn2->n1=n2|_->falseletpr_bulletb=matchbwith|Dashn->Pp.(str(String.maken'-'))|Starn->Pp.(str(String.maken'*'))|Plusn->Pp.(str(String.maken'+'))typesuggestion=|Suggestoft(* this bullet is mandatory here *)|Unfinishedoft(* no mandatory bullet here, but this bullet is unfinished *)|NoBulletInUse(* No mandatory bullet (or brace) here, no bullet pending,
some focused goals exists. *)|NeedClosingBrace(* Some unfocussed goal exists "{" needed to focus them *)|ProofFinished(* No more goal anywhere *)letsuggest_on_solved_goalsugg=matchsuggwith|NeedClosingBrace->Pp.(str"Try closing this subproof by typing a space and curly brace \" }\".")|NoBulletInUse->Pp.mt()|ProofFinished->Pp.mt()|Suggestb->Pp.(str"Write a bullet "++pr_bulletb++str" to embark on the next subproof.")|Unfinishedb->Pp.(str"The current subproof with bullet "++pr_bulletb++str" is unfinished.")(* give always a message. *)letsuggest_on_errorsugg=matchsuggwith|NeedClosingBrace->Pp.(str"Try closing this subproof by typing a space and curly brace \" }\".")|NoBulletInUse->assertfalse(* This should never raise an error. *)|ProofFinished->Pp.(str"No more goals.")|Suggestb->Pp.(str"Write a bullet "++pr_bulletb++str" to embark on the next subproof.")|Unfinishedb->Pp.(str"Current bullet "++pr_bulletb++str" is not finished.")letbullet_kind=(new_focus_kind():tlistfocus_kind)letbullet_cond=done_cond~loose_end:truebullet_kindletget_bulletspr=ifis_last_focusbullet_kindprthenget_at_focusbullet_kindprelse[]lethas_bulletbulpr=letrechas_bullet=function|b'::_whenbullet_eqbulb'->true|_::l->has_bulletl|[]->falseinhas_bullet(get_bulletspr)(* pop a bullet from proof [pr]. There should be at least one
bullet in use. If pop impossible (pending proofs on this level
of bullet or higher) then raise [Proof.CannotUnfocusThisWay]. *)letpoppr=matchget_bulletsprwith|b::_->Some(unfocusbullet_kindpr(),b)|_->Noneletpush(b:t)pr=focusbullet_cond(b::get_bulletspr)1prletsuggest_bullet(prf:Proof.t):suggestion=ifis_doneprfthenProofFinishedelseifnot(no_focused_goalprf)then(* No suggestion if a bullet is not mandatory, look for an unfinished bullet *)matchget_bulletsprfwith|b::_->Unfinishedb|_->NoBulletInUseelse(* There is no goal under focus but some are unfocussed,
let us look at the bullet needed. *)letrecloopprf=matchpopprfwith|Some(prf,b)->(* pop went well, this means that there are no more goals
*under this* bullet b, see if a new b can be pushed. *)begintryignore(pushbprf);SuggestbwithewhenCErrors.noncriticale->(* b could not be pushed, so we must look for a outer bullet *)loopprfend|None->(* No pop was possible, but there are still
subgoals somewhere: there must be a "}" to use. *)NeedClosingBraceinloopprf(** Definitions for the bullet behavior "Waterproof Strict Subproofs".
This is the same as the ordinary "Strict Subproofs" bullet behavior,
except that the suggestions and error messages are slightly different. *)moduleStrict=structexceptionFailedBulletoft*suggestionlet_=CErrors.register_handler(function|FailedBullet(b,sugg)->letprefix=Pp.(str"Wrong bullet "++pr_bulletb++str": ")inSomePp.(str"[Focus]"++spc()++prefix++suggest_on_errorsugg)|_->None)letrecpop_until(prf:Proof.t)bul:Proof.t=letprf',b=Option.get(popprf)inifbullet_eqbulbthenprf'elsepop_untilprf'bulletputpbul=tryifnot(has_bulletbulp)then(* bullet is not in use, so pushing it is always ok unless
no goal under focus. *)pushbulpelsematchsuggest_bulletpwith|Suggestsuggested_bulletwhenbullet_eqbulsuggested_bullet->(* suggested_bullet is mandatory and you gave the right one *)letp'=pop_untilpbulinpushbulp'(* the bullet you gave is in use but not the right one *)|sugg->raise(FailedBullet(bul,sugg))withNoSuchGoals_->(* push went bad *)raise(FailedBullet(bul,suggest_bulletp))letstrict={name="Waterproof Strict Subproofs";put=put;suggest=(funprf->suggest_on_solved_goal(suggest_bulletprf))}endlet_=register_behaviorStrict.strict(** Definitions for the bullet behavior "Waterproof Relaxed Subproofs."
A bullet point will unfocus all finished subproofs, and will focus a new subproof. *)moduleRelaxed=struct(** Unfocus as many proofs as possible: this should correspond to unfocusing
all subproofs that are finished. *)letrecpop_until(prf:Proof.t):Proof.t=tryletprf',b=Option.get(popprf)inpop_untilprf'withewhenCErrors.noncriticale->prf(** The intention here is to unfocus all finished subproofs, and then
start a new bullet. *)letputpbul=letprf=pop_untilpinpushbulprfletwp_relaxed_bullets={name="Waterproof Relaxed Subproofs";put=put;suggest=(funprf->suggest_on_solved_goal(suggest_bulletprf))}endlet_=register_behaviorRelaxed.wp_relaxed_bullets