aboutsummaryrefslogtreecommitdiff
path: root/library
diff options
context:
space:
mode:
authorletouzey2012-03-23 16:49:52 +0000
committerletouzey2012-03-23 16:49:52 +0000
commit85a16702cc7561f9a96eed9c2d707b9711130f09 (patch)
tree76acae0330eb6ddf125f48e7f1c5994d24b05296 /library
parent5c915de161fe453914525e5920d1a165bba8fa43 (diff)
A unified backtrack mechanism, with a basic "Show Script" as side-effect
Migrate the backtracking code from ide_slave.ml into a new backtrack.ml. In particular the history stack of commands that used to be there is now non-coqide-specific. ** Adapted commands ** - "Show Script": a basic functional version is restored (and the printing of scripts at Qed in coqtop). No indentation, one Coq command per line, based on the vernac_expr asts recorded in the history stack, printed via Ppvernac. - "Back n" : now mimics the backtrack of coqide: it goes n steps back (both commands and proofs), and maybe more if needed to avoid re-entering a proof (it outputs a warning in this case). - "BackTo n" : still try to go back to state n, but it also handles the proof state, and it may end on some state n' <= n if needed to avoid re-entering a proof. Ideally, it could someday be used by ProofGeneral instead of the complex Backtrack command. ** Compatible commands ** - "Backtrack" is left intact from compatibility with current ProofGeneral. We simply re-synchronize the command history stack after each Backtrack. - "Undo" is kept as a standard command, not a backtracking one, a bit like "Focus". Same for "Restart" and "Abort". All of these are now accepted in coqide (Undo simply triggers a warning). - Undocumented command "Undo To n" (counting from start of proof instead of from end) also keep its semantics, it is simply made compatible with the new stack mechanism. ** New restrictions ** We now forbid backtracking commands (Reset* / Back*) inside files when Load'ing or compiling, or inside VernacList/VernacTime/VernacFail. Too much work dealing with these situation that nobody uses. ** Internal details ** Internally, the command stack differs a bit from what was in Ide_slave earlier (which was inspired by lisp code in ProofGeneral). We now tag commands that are unreachable by a backtrack, due to some proof being finished, aborted, restarted, or partly Undo'ed. This induce a bit of bookkeeping during Qed/Abort/Restart/Undo, but then the backtracking code is straightforward: we simply search backward the first reachable state starting from the desired place. We don't depend anymore on the proof names (apart in the last proof block), It's more robust this way (think of re-entering a M.foo from an outside proof foo). Many internal clarifications in Lib, Vernac, etc. For instance "Reset Initial" is now just a BackTo 1, while "Reset foo" now calls (Lib.label_before_name "foo"), and performs a BackTo to the corresponding label. Concerning Coqide, we directly suppress the regular printing of goals via a flag in Vernacentries. This avoid relying on a classification of commands in Ide_slave as earlier. git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/coq/trunk@15085 85f007b7-540e-0410-9357-904b9bb8a0f7
Diffstat (limited to 'library')
-rw-r--r--library/lib.ml83
-rw-r--r--library/lib.mli42
2 files changed, 36 insertions, 89 deletions
diff --git a/library/lib.ml b/library/lib.ml
index 54087ce1c0..40a427e491 100644
--- a/library/lib.ml
+++ b/library/lib.ml
@@ -573,44 +573,16 @@ let reset_to_gen test =
let reset_to sp = reset_to_gen (fun x -> fst x = sp)
-let reset_name (loc,id) =
- let (sp,_) =
- try
- find_entry_p (fun (sp,_) -> let (_,spi) = repr_path (fst sp) in id = spi)
- with Not_found ->
- user_err_loc (loc,"reset_name",pr_id id ++ str ": no such entry")
- in
- reset_to sp
-
-let is_mod_node = function
- | OpenedModule _ | OpenedSection _
- | ClosedModule _ | ClosedSection _ -> true
- | Leaf o -> let t = object_tag o in t = "MODULE" || t = "MODULE TYPE"
- || t = "MODULE ALIAS"
- | _ -> false
-
-(* Reset on a module or section name in order to bypass constants with
- the same name *)
-
-let reset_mod (loc,id) =
- let (_,before) =
- try
- find_split_p (fun (sp,node) ->
- let (_,spi) = repr_path (fst sp) in id = spi
- && is_mod_node node)
- with Not_found ->
- user_err_loc (loc,"reset_mod",pr_id id ++ str ": no such entry")
- in
- set_lib_stk before
+let first_command_label = 1
-let mark_end_of_command, current_command_label, set_command_label =
- let n = ref 0 in
+let mark_end_of_command, current_command_label, reset_command_label =
+ let n = ref (first_command_label-1) in
(fun () ->
match !lib_stk with
(_,Leaf o)::_ when object_tag o = "DOT" -> ()
| _ -> incr n;add_anonymous_leaf (inLabel !n)),
(fun () -> !n),
- (fun x -> n:=x)
+ (fun x -> n:=x;add_anonymous_leaf (inLabel x))
let is_label_n n x =
match x with
@@ -623,21 +595,21 @@ let is_label_n n x =
let reset_label n =
if n >= current_command_label () then
error "Cannot backtrack to the current label or a future one";
- let res = reset_to_gen (is_label_n n) in
+ reset_to_gen (is_label_n n);
(* forget state numbers after n only if reset succeeded *)
- set_command_label (n-1);
- res
+ reset_command_label n
-let rec back_stk n stk =
- match stk with
- (sp,Leaf o)::tail when object_tag o = "DOT" ->
- if n=0 then sp else back_stk (n-1) tail
- | _::tail -> back_stk n tail
- | [] -> error "Reached begin of command history"
+(** Search the last label registered before defining [id] *)
-let back n =
- reset_to (back_stk n !lib_stk);
- set_command_label (current_command_label () - n - 1)
+let label_before_name (loc,id) =
+ let found = ref false in
+ let search = function
+ | (_,Leaf o) when !found && object_tag o = "DOT" -> true
+ | (sp,_) -> (if id = snd (repr_path (fst sp)) then found := true); false
+ in
+ match find_entry_p search with
+ | (_,Leaf o) -> outLabel o
+ | _ -> raise Not_found
(* State and initialization. *)
@@ -657,29 +629,6 @@ let init () =
path_prefix := initial_prefix;
init_summaries()
-(* Initial state. *)
-
-let initial_state = ref None
-
-let declare_initial_state () =
- let name = add_anonymous_entry (FrozenState (freeze_summaries())) in
- initial_state := Some name
-
-let reset_initial () =
- match !initial_state with
- | None ->
- error "Resetting to the initial state is possible only interactively"
- | Some sp ->
- begin match split_lib sp with
- | (_,[_,FrozenState fs as hd],before) ->
- lib_stk := hd::before;
- recalc_path_prefix ();
- set_command_label 0;
- unfreeze_summaries fs
- | _ -> assert false
- end
-
-
(* Misc *)
let mp_of_global ref =
diff --git a/library/lib.mli b/library/lib.mli
index df931f060f..781ecfe32e 100644
--- a/library/lib.mli
+++ b/library/lib.mli
@@ -62,17 +62,6 @@ val add_leaves : Names.identifier -> Libobject.obj list -> Libnames.object_name
val add_frozen_state : unit -> unit
-(** Adds a "dummy" entry in lib_stk with a unique new label number. *)
-val mark_end_of_command : unit -> unit
-
-(** Returns the current label number *)
-val current_command_label : unit -> int
-
-(** [reset_label n] resets [lib_stk] to the label n registered by
- [mark_end_of_command()]. It forgets the label and anything
- registered after it. The label should be strictly in the past. *)
-val reset_label : int -> unit
-
(** {6 ... } *)
(** The function [contents_after] returns the current library segment,
starting from a given section path. If not given, the entire segment
@@ -151,15 +140,28 @@ val remove_section_part : Libnames.global_reference -> Names.dir_path
val open_section : Names.identifier -> unit
val close_section : unit -> unit
-(** {6 Backtracking (undo). } *)
+(** {6 Backtracking } *)
-val reset_to : Libnames.object_name -> unit
-val reset_name : Names.identifier Pp.located -> unit
-val reset_mod : Names.identifier Pp.located -> unit
+(** NB: The next commands are low-level ones, do not use them directly
+ otherwise the command history stack in [Backtrack] will be out-of-sync.
+ Also note that [reset_initial] is now [reset_label first_command_label] *)
-(** [back n] resets to the place corresponding to the {% $ %}n{% $ %}-th call of
- [mark_end_of_command] (counting backwards) *)
-val back : int -> unit
+(** Adds a "dummy" entry in lib_stk with a unique new label number. *)
+val mark_end_of_command : unit -> unit
+
+(** Returns the current label number *)
+val current_command_label : unit -> int
+
+(** The first label number *)
+val first_command_label : int
+
+(** [reset_label n] resets [lib_stk] to the label n registered by
+ [mark_end_of_command()]. It forgets anything registered after
+ this label. The label should be strictly in the past. *)
+val reset_label : int -> unit
+
+(** search the label registered immediately before adding some definition *)
+val label_before_name : Names.identifier Pp.located -> int
(** {6 We can get and set the state of the operations (used in [States]). } *)
@@ -170,10 +172,6 @@ val unfreeze : frozen -> unit
val init : unit -> unit
-val declare_initial_state : unit -> unit
-val reset_initial : unit -> unit
-
-
(** XML output hooks *)
val set_xml_open_section : (Names.identifier -> unit) -> unit
val set_xml_close_section : (Names.identifier -> unit) -> unit