diff options
| -rw-r--r-- | plugins/decl_mode/decl_mode.ml | 23 | ||||
| -rw-r--r-- | plugins/decl_mode/decl_mode.mli | 6 | ||||
| -rw-r--r-- | plugins/decl_mode/decl_proof_instr.ml | 50 | ||||
| -rw-r--r-- | plugins/decl_mode/decl_proof_instr.mli | 2 | ||||
| -rw-r--r-- | proofs/proof.ml | 57 | ||||
| -rw-r--r-- | proofs/proof.mli | 36 | ||||
| -rw-r--r-- | proofs/proof_global.ml | 15 | ||||
| -rw-r--r-- | proofs/proof_global.mli | 18 | ||||
| -rw-r--r-- | toplevel/vernacentries.ml | 15 |
9 files changed, 157 insertions, 65 deletions
diff --git a/plugins/decl_mode/decl_mode.ml b/plugins/decl_mode/decl_mode.ml index 232edda0fd..af6aa4bf59 100644 --- a/plugins/decl_mode/decl_mode.ml +++ b/plugins/decl_mode/decl_mode.ml @@ -66,7 +66,7 @@ type command_mode = | Mode_none let mode_of_pftreestate pts = - (* spiwack: it was "top_goal_..." but this should be fine *) + (* spiwack: it used to be "top_goal_..." but this should be fine *) let { it = goals ; sigma = sigma } = Proof.V82.subgoals pts in let goal = List.hd goals in if info.get (Goal.V82.extra sigma goal) = None then @@ -96,10 +96,25 @@ let get_stack pts = let info = get_info sigma (List.hd goals) in info.pm_stack + +let proof_focus = Proof.new_focus_kind () +let proof_cond = Proof.no_cond proof_focus + +let focus p = + let inf = get_stack p in + Proof.focus proof_cond inf 1 p + +let unfocus = Proof.unfocus proof_focus + +let maximal_unfocus = Proof_global.maximal_unfocus proof_focus + let get_top_stack pts = - let { it = gl ; sigma = sigma } = Proof.V82.top_goal pts in - let info = get_info sigma gl in - info.pm_stack + try + Proof.get_at_focus proof_focus pts + with Proof.NoSuchFocus -> + let { it = gl ; sigma = sigma } = Proof.V82.top_goal pts in + let info = get_info sigma gl in + info.pm_stack let get_last env = try diff --git a/plugins/decl_mode/decl_mode.mli b/plugins/decl_mode/decl_mode.mli index 72c46c7e7d..4e636598f9 100644 --- a/plugins/decl_mode/decl_mode.mli +++ b/plugins/decl_mode/decl_mode.mli @@ -70,3 +70,9 @@ val get_stack : Proof.proof -> stack_info list val get_top_stack : Proof.proof -> stack_info list val get_last: Environ.env -> identifier + +val focus : Proof.proof -> unit + +val unfocus : Proof.proof -> unit + +val maximal_unfocus : Proof.proof -> unit diff --git a/plugins/decl_mode/decl_proof_instr.ml b/plugins/decl_mode/decl_proof_instr.ml index cee4d7271d..549b1f1465 100644 --- a/plugins/decl_mode/decl_proof_instr.ml +++ b/plugins/decl_mode/decl_proof_instr.ml @@ -111,17 +111,15 @@ let assert_postpone id t = (* start a proof *) -let proof_focus = Proof.new_focus_kind () -let proof_cond = Proof.no_cond proof_focus let start_proof_tac gls= let info={pm_stack=[]} in tcl_change_info info gls let go_to_proof_mode () = - Pfedit.by start_proof_tac ; + Pfedit.by start_proof_tac; let p = Proof_global.give_me_the_proof () in - Proof.focus proof_cond 1 p + Decl_mode.focus p (* closing gaps *) @@ -154,12 +152,14 @@ let mark_rule_as_done = function (* post-instruction focus management *) +(* spiwack: This used to fail if there was no focusing command + above, but I don't think it ever happened. I hope it doesn't mess + things up*) let goto_current_focus pts = - Proof.unfocus proof_focus pts + Decl_mode.maximal_unfocus pts let goto_current_focus_or_top pts = - try goto_current_focus pts - with Util.UserError _ -> () + goto_current_focus pts (* return *) @@ -172,6 +172,7 @@ let close_tactic_mode pts = goto_current_focus pts2 let return_from_tactic_mode () = + (* arnaud: la commande return ne fonctionne pas *) Util.anomaly "Todo: Decl_proof_instr.return_from_tactic_mode" (* end proof/claim *) @@ -180,7 +181,12 @@ let close_block bt pts = if Proof.no_focused_goal pts then goto_current_focus pts else - let stack =get_stack pts in + let stack = + if Proof.is_done pts then + get_top_stack pts + else + get_stack pts + in match bt,stack with B_claim, Claim::_ | B_focus, Focus_claim::_ | B_proof, [] -> (goto_current_focus pts) @@ -197,7 +203,7 @@ let close_block bt pts = | ET_Induction -> error "\"end induction\" expected." end | _,_ -> anomaly "Lonely suppose on stack." - + (* utility for suppose / suppose it is *) @@ -577,8 +583,8 @@ let instr_claim _thus st gls0 = let ninfo1 = {pm_stack= (if _thus then Focus_claim else Claim)::info.pm_stack} in tclTHENS (assert_postpone id st.st_it) - [tcl_change_info ninfo1; - thus_tac] gls0 + [thus_tac; + tcl_change_info ninfo1] gls0 (* tactics for assume *) @@ -1294,12 +1300,9 @@ let understand_my_constr c gls = let rec frob = function GEvar _ -> GHole (dummy_loc,QuestionMark Expand) | rc -> map_glob_constr frob rc in Pretyping.Default.understand_tcc (sig_sig gls) env ~expected_type:(pf_concl gls) (frob rawc) -let set_refine,my_refine = -let refine = ref (fun (_:open_constr) -> (assert false : tactic) ) in -((fun tac -> refine:= tac), -(fun c gls -> - let oc = understand_my_constr c gls in - !refine oc gls)) +let my_refine c gls = + let oc = understand_my_constr c gls in + Refine.refine oc gls (* end focus/claim *) @@ -1438,12 +1441,16 @@ let rec postprocess pts instr = | Pcut _ | Psuffices _ | Passume _ | Plet _ | Pconsider (_,_) | Pcast (_,_) | Pgiven _ | Ptake _ | Pdefine (_,_,_) | Prew (_,_) -> () | Pclaim _ | Pfocus _ | Psuppose _ | Pcase _ | Pper _ - | Pescape -> Proof.focus proof_cond 1 pts + | Pescape -> Decl_mode.focus pts | Pend (B_elim ET_Induction) -> begin let pfterm = List.hd (Proof.partial_proof pts) in let { it = gls ; sigma = sigma } = Proof.V82.subgoals pts in - let env = Goal.V82.env sigma (List.hd gls) in + let env = try + Goal.V82.env sigma (List.hd gls) + with Failure "hd" -> + Global.env () + in try Inductiveops.control_only_guard env pfterm; goto_current_focus_or_top pts @@ -1469,7 +1476,10 @@ let do_instr raw_instr pts = interp_proof_instr (get_its_info gl) sigma env glob_instr in Pfedit.by (tclTHEN (eval_instr instr) clean_tmp) else () end; - postprocess pts raw_instr.instr + postprocess pts raw_instr.instr; + (* spiwack: this should restore a compatible semantics with + v8.3 where we never stayed focused on 0 goal. *) + Decl_mode.maximal_unfocus pts let proof_instr raw_instr = let p = Proof_global.give_me_the_proof () in diff --git a/plugins/decl_mode/decl_proof_instr.mli b/plugins/decl_mode/decl_proof_instr.mli index 0a2ab571ff..b27939b3ca 100644 --- a/plugins/decl_mode/decl_proof_instr.mli +++ b/plugins/decl_mode/decl_proof_instr.mli @@ -109,5 +109,3 @@ val init_tree: (int option * Declarations.recarg Rtree.t) array -> (Names.Idset.t * Decl_mode.split_tree) option) -> Decl_mode.split_tree - -val set_refine : (Evd.open_constr -> Proof_type.tactic) -> unit diff --git a/proofs/proof.ml b/proofs/proof.ml index 44f1cce723..b932e95f9a 100644 --- a/proofs/proof.ml +++ b/proofs/proof.ml @@ -31,8 +31,13 @@ open Term -type focus_kind = int -type focus_condition = focus_kind -> Proofview.proofview -> bool +type _focus_kind = int +type 'a focus_kind = _focus_kind +type focus_info = Obj.t +type _focus_condition = + (_focus_kind -> Proofview.proofview -> bool) * + (_focus_kind -> focus_info -> focus_info) +type 'a focus_condition = _focus_condition let next_kind = ref 0 let new_focus_kind () = @@ -40,6 +45,13 @@ let new_focus_kind () = incr next_kind; r +(* Auxiliary function to define conditions: + [check kind1 kind2 inf] returns [inf] if [kind1] and [kind2] match. + Otherwise it raises [CheckNext] *) +exception CheckNext +let check kind1 kind2 inf = + if kind1=kind2 then inf else raise CheckNext + (* To be authorized to unfocus one must meet the condition prescribed by the action which focused.*) (* spiwack: we could consider having a list of authorized focus_kind instead @@ -47,9 +59,11 @@ let new_focus_kind () = (* [no_cond] only checks that the unfocusing command uses the right [focus_kind]. *) let no_cond k0 k _ = k0 = k +let no_cond k = no_cond k , check k (* [done_cond] checks that the unfocusing command uses the right [focus_kind] and that the focused proofview is complete. *) let done_cond k0 k p = k0 = k && Proofview.finished p +let done_cond k = done_cond k , check k (* Subpart of the type of proofs. It contains the parts of the proof which @@ -58,9 +72,9 @@ type proof_state = { (* Current focused proofview *) proofview: Proofview.proofview; (* History of the focusings, provides information on how - to unfocus the proof. + to unfocus the proof and the extra information stored while focusing. The list is empty when the proof is fully unfocused. *) - focus_stack: (focus_condition*Proofview.focus_context) list; + focus_stack: (_focus_condition*focus_info*Proofview.focus_context) list; (* Extra information which can be freely used to create new behaviours. *) intel: Store.t } @@ -94,7 +108,7 @@ let start goals = } let rec unroll_focus pv = function - | (_,ctx)::stk -> unroll_focus (Proofview.unfocus ctx pv) stk + | (_,_,ctx)::stk -> unroll_focus (Proofview.unfocus ctx pv) stk | [] -> pv (* spiwack: a proof is considered completed even if its still focused, if the focus @@ -126,15 +140,15 @@ let return p = of proofs, they are not meant to be exported in the .mli ***) (* An auxiliary function to push a {!focus_context} on the focus stack. *) -let push_focus kind context pr = - pr.state <- { pr.state with focus_stack = (kind,context)::pr.state.focus_stack } +let push_focus cond inf context pr = + pr.state <- { pr.state with focus_stack = (cond,inf,context)::pr.state.focus_stack } exception FullyUnfocused (* An auxiliary function to read the kind of the next focusing step *) let cond_of_focus pr = match pr.state.focus_stack with - | (cond,_)::_ -> cond + | (cond,_,_)::_ -> cond | _ -> raise FullyUnfocused (* An auxiliary function to pop and read the last {!Proofview.focus_context} @@ -159,16 +173,16 @@ let pop_undo pr = (* This function focuses the proof [pr] between indices [i] and [j] *) -let _focus cond i j pr = +let _focus cond inf i j pr = let (focused,context) = Proofview.focus i j pr.state.proofview in - push_focus cond context pr; + push_focus cond inf context pr; pr.state <- { pr.state with proofview = focused } (* This function unfocuses the proof [pr], it raises [FullyUnfocused], if the proof is already fully unfocused. This function does not care about the condition of the current focus. *) let _unfocus pr = - let (_,fc) = pop_focus pr in + let (_,_,fc) = pop_focus pr in pr.state <- { pr.state with proofview = Proofview.unfocus fc pr.state.proofview } @@ -214,9 +228,9 @@ let add_undo effect pr = (* Focus command (focuses on the [i]th subgoal) *) (* spiwack: there could also, easily be a focus-on-a-range tactic, is there a need for it? *) -let focus cond i pr = +let focus cond inf i pr = save pr; - _focus cond i i pr + _focus cond (Obj.repr inf) i i pr (* Unfocus command. Fails if the proof is not focused. *) @@ -224,7 +238,7 @@ let unfocus kind pr = let starting_point = save_state pr in try let cond = cond_of_focus pr in - if cond kind pr.state.proofview then + if fst cond kind pr.state.proofview then (_unfocus pr; push_undo starting_point pr) else @@ -232,6 +246,21 @@ let unfocus kind pr = with FullyUnfocused -> Util.error "This proof is not focused" +let get_at_point kind ((_,get),inf,_) = get kind inf +exception NoSuchFocus +exception GetDone of Obj.t +let get_in_focus_stack kind stack = + try + List.iter begin fun pt -> + try + raise (GetDone (get_at_point kind pt)) + with CheckNext -> () + end stack; + raise NoSuchFocus + with GetDone x -> x +let get_at_focus kind pr = + Obj.magic (get_in_focus_stack kind pr.state.focus_stack) + let no_focused_goal p = Proofview.finished p.state.proofview diff --git a/proofs/proof.mli b/proofs/proof.mli index ab1c0b8345..bb651dea11 100644 --- a/proofs/proof.mli +++ b/proofs/proof.mli @@ -64,32 +64,44 @@ val add_undo : (unit -> unit) -> proof -> unit (*** Focusing actions ***) -(* [focus_kind] is the type used by focusing and unfocusing +(* ['a focus_kind] is the type used by focusing and unfocusing commands to synchronise. Focusing and unfocusing commands use - a particular focus_kind, and if they don't match, the unfocusing command - will fail. *) -type focus_kind -val new_focus_kind : unit -> focus_kind + a particular ['a focus_kind], and if they don't match, the unfocusing command + will fail. + When focusing with an ['a focus_kind], an information of type ['a] is + stored at the focusing point. An example use is the "induction" tactic + of the declarative mode where sub-tactics must be aware of the current + induction argument. *) +type 'a focus_kind +val new_focus_kind : unit -> 'a focus_kind (* To be authorized to unfocus one must meet the condition prescribed by - the action which focused.*) -type focus_condition + the action which focused. + Conditions always carry a focus kind, and inherit their type parameter + from it.*) +type 'a focus_condition (* [no_cond] only checks that the unfocusing command uses the right [focus_kind]. *) -val no_cond : focus_kind -> focus_condition +val no_cond : 'a focus_kind -> 'a focus_condition (* [done_cond] checks that the unfocusing command uses the right [focus_kind] and that the focused proofview is complete. *) -val done_cond : focus_kind -> focus_condition +val done_cond : 'a focus_kind -> 'a focus_condition (* focus command (focuses on the [i]th subgoal) *) -(* there could also, easily be a focus-on-a-range tactic, is there +(* spiwack: there could also, easily be a focus-on-a-range tactic, is there a need for it? *) -val focus : focus_condition -> int -> proof -> unit +val focus : 'a focus_condition -> 'a -> int -> proof -> unit exception FullyUnfocused (* Unfocusing command. Raises [FullyUnfocused] if the proof is not focused. *) -val unfocus : focus_kind -> proof -> unit +val unfocus : 'a focus_kind -> proof -> unit + +(* [get_at_focus k] gets the information stored at the closest focus point + of kind [k]. + Raises [NoSuchFocus] if there is no focus point of kind [k]. *) +exception NoSuchFocus +val get_at_focus : 'a focus_kind -> proof -> 'a (* returns [true] if there is no goal under focus. *) val no_focused_goal : proof -> bool diff --git a/proofs/proof_global.ml b/proofs/proof_global.ml index 3e8c71482a..bcd9d6e0d3 100644 --- a/proofs/proof_global.ml +++ b/proofs/proof_global.ml @@ -281,6 +281,21 @@ let close_proof () = | Proof.HasUnresolvedEvar -> Util.error "Attempt to save a proof with existential variables still non-instantiated" + +(**********************************************************) +(* *) +(* Utility functions *) +(* *) +(**********************************************************) + +let maximal_unfocus k p = + begin try while Proof.no_focused_goal p do + Proof.unfocus k p + done + with Util.UserError _ -> (* arnaud: attention à ça si je fini par me décider à mettre une vrai erreur pour Proof.unfocus *) + () + end + module V82 = struct let get_current_initial_conclusions () = let p = give_me_the_proof () in diff --git a/proofs/proof_global.mli b/proofs/proof_global.mli index a589732046..5f57c25ac5 100644 --- a/proofs/proof_global.mli +++ b/proofs/proof_global.mli @@ -72,18 +72,28 @@ val suspend : unit -> unit val resume_last : unit -> unit val resume : Names.identifier -> unit -(** @raise NoSuchProof if it doesn't find *) +(** @raise NoSuchProof if it doesn't find one. *) -(* Runs a tactic on the current proof. Raises [NoCurrentProof] is there is +(** Runs a tactic on the current proof. Raises [NoCurrentProof] is there is no current proof. *) val run_tactic : unit Proofview.tactic -> unit -(* Sets the tactic to be used when a tactic line is closed with [...] *) +(** Sets the tactic to be used when a tactic line is closed with [...] *) val set_endline_tactic : unit Proofview.tactic -> unit -(* Appends the endline tactic of the current proof to a tactic. *) +(** Appends the endline tactic of the current proof to a tactic. *) val with_end_tac : unit Proofview.tactic -> unit Proofview.tactic +(**********************************************************) +(* *) +(* Utility functions *) +(* *) +(**********************************************************) + +(** [maximal_unfocus k p] unfocuses [p] until [p] has at least a + focused goal or that the last focus isn't of kind [k]. *) +val maximal_unfocus : 'a Proof.focus_kind -> Proof.proof -> unit + module V82 : sig val get_current_initial_conclusions : unit -> Names.identifier *(Term.types list * Decl_kinds.goal_kind * Tacexpr.declaration_hook) end diff --git a/toplevel/vernacentries.ml b/toplevel/vernacentries.ml index f4fc8714be..ccbaa6d306 100644 --- a/toplevel/vernacentries.ml +++ b/toplevel/vernacentries.ml @@ -670,7 +670,7 @@ let pop_bullet pr = b | [] -> Util.anomaly "Tried to pop bullet from an empty stack" let push_bullet b pr = - Proof.focus bullet_cond 1 pr ; + Proof.focus bullet_cond () 1 pr ; set_bullets (b::get_bullets pr) pr let put_bullet p bul = @@ -690,10 +690,7 @@ let vernac_solve n bullet tcom b = solve_nth n (Tacinterp.hide_interp tcom None) ~with_end_tac:b; (* in case a strict subtree was completed, go back to the top of the prooftree *) - begin try while Proof.no_focused_goal p do - Proof.unfocus command_focus p - done - with Util.UserError _ -> () end; + Proof_global.maximal_unfocus command_focus p; print_subgoals(); if !pcoq <> None then (Option.get !pcoq).solve n @@ -1252,8 +1249,8 @@ let vernac_backtrack snum pnum naborts = let vernac_focus gln = let p = Proof_global.give_me_the_proof () in match gln with - | None -> Proof.focus focus_command_cond 1 p; print_subgoals () - | Some n -> Proof.focus focus_command_cond n p; print_subgoals () + | None -> Proof.focus focus_command_cond () 1 p; print_subgoals () + | Some n -> Proof.focus focus_command_cond () n p; print_subgoals () (* Unfocuses one step in the focus stack. *) @@ -1273,8 +1270,8 @@ let subproof_cond = Proof.done_cond subproof_kind let vernac_subproof gln = let p = Proof_global.give_me_the_proof () in begin match gln with - | None -> Proof.focus subproof_cond 1 p - | Some n -> Proof.focus subproof_cond n p + | None -> Proof.focus subproof_cond () 1 p + | Some n -> Proof.focus subproof_cond () n p end ; print_subgoals () |
