~ubuntu-branches/ubuntu/wily/coq-doc/wily

« back to all changes in this revision

Viewing changes to proofs/pfedit.ml

  • Committer: Bazaar Package Importer
  • Author(s): Stéphane Glondu, Stéphane Glondu, Samuel Mimram
  • Date: 2010-01-07 22:50:39 UTC
  • mfrom: (1.2.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20100107225039-n3cq82589u0qt0s2
Tags: 8.2pl1-1
[ Stéphane Glondu ]
* New upstream release (Closes: #563669)
  - remove patches
* Packaging overhaul:
  - use git, advertise it in Vcs-* fields of debian/control
  - use debhelper 7 and dh with override
  - use source format 3.0 (quilt)
* debian/control:
  - set Maintainer to d-o-m, set Uploaders to Sam and myself
  - add Homepage field
  - bump Standards-Version to 3.8.3
* Register PDF documentation into doc-base
* Add debian/watch
* Update debian/copyright

[ Samuel Mimram ]
* Change coq-doc's description to mention that it provides documentation in
  pdf format, not postscript, closes: #543545.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
(************************************************************************)
 
2
(*  v      *   The Coq Proof Assistant  /  The Coq Development Team     *)
 
3
(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
 
4
(*   \VV/  **************************************************************)
 
5
(*    //   *      This file is distributed under the terms of the       *)
 
6
(*         *       GNU Lesser General Public License Version 2.1        *)
 
7
(************************************************************************)
 
8
 
 
9
(* $Id: pfedit.ml 11745 2009-01-04 18:43:08Z herbelin $ *)
 
10
 
 
11
open Pp
 
12
open Util
 
13
open Names
 
14
open Nameops
 
15
open Sign
 
16
open Term
 
17
open Declarations
 
18
open Entries
 
19
open Environ
 
20
open Evd
 
21
open Typing
 
22
open Refiner
 
23
open Proof_trees
 
24
open Tacexpr
 
25
open Proof_type
 
26
open Lib
 
27
open Safe_typing
 
28
 
 
29
(*********************************************************************)
 
30
(* Managing the proofs state                                         *)
 
31
(* Mainly contributed by C. Murthy                                   *)
 
32
(*********************************************************************)
 
33
 
 
34
type proof_topstate = {
 
35
  mutable top_end_tac : tactic option;
 
36
  top_init_tac : tactic option;
 
37
  top_compute_guard : bool;
 
38
  top_goal : goal;
 
39
  top_strength : Decl_kinds.goal_kind;
 
40
  top_hook : declaration_hook }
 
41
 
 
42
let proof_edits =
 
43
  (Edit.empty() : (identifier,pftreestate,proof_topstate) Edit.t)
 
44
 
 
45
let get_all_proof_names () = Edit.dom proof_edits
 
46
 
 
47
let msg_proofs use_resume =
 
48
  match Edit.dom proof_edits with
 
49
    | [] -> (spc () ++ str"(No proof-editing in progress).")
 
50
    | l ->  (str"." ++ fnl () ++ str"Proofs currently edited:" ++ spc () ++
 
51
               (prlist_with_sep pr_spc pr_id (get_all_proof_names ())) ++
 
52
               str"." ++
 
53
               (if use_resume then (fnl () ++ str"Use \"Resume\" first.")
 
54
                else (mt ()))
 
55
)
 
56
 
 
57
let undo_default = 50
 
58
let undo_limit = ref undo_default
 
59
 
 
60
(*********************************************************************)
 
61
(*    Functions for decomposing and modifying the proof state        *)
 
62
(*********************************************************************)
 
63
 
 
64
let get_state () =
 
65
  match Edit.read proof_edits with
 
66
    | None -> errorlabstrm "Pfedit.get_state"
 
67
          (str"No focused proof" ++ msg_proofs true)
 
68
    | Some(_,pfs,ts) -> (pfs,ts)
 
69
 
 
70
let get_topstate ()    = snd(get_state())
 
71
let get_pftreestate () = fst(get_state())
 
72
 
 
73
let get_end_tac () = let ts = get_topstate () in ts.top_end_tac
 
74
 
 
75
let get_goal_context n =
 
76
  let pftree = get_pftreestate () in
 
77
  let goal = nth_goal_of_pftreestate n pftree in
 
78
  (project goal, pf_env goal)
 
79
 
 
80
let get_current_goal_context () = get_goal_context 1
 
81
 
 
82
let set_current_proof = Edit.focus proof_edits
 
83
 
 
84
let resume_proof (loc,id) = 
 
85
  try 
 
86
    Edit.focus proof_edits id
 
87
  with Invalid_argument "Edit.focus" ->
 
88
    user_err_loc(loc,"Pfedit.set_proof",str"No such proof" ++ msg_proofs false)
 
89
 
 
90
let suspend_proof () =
 
91
  try 
 
92
    Edit.unfocus proof_edits
 
93
  with Invalid_argument "Edit.unfocus" ->
 
94
    errorlabstrm "Pfedit.suspend_current_proof"
 
95
      (str"No active proof" ++ (msg_proofs true))
 
96
      
 
97
let resume_last_proof () =
 
98
  match (Edit.last_focused proof_edits) with
 
99
    | None ->
 
100
        errorlabstrm "resume_last" (str"No proof-editing in progress.")
 
101
    | Some p -> 
 
102
        Edit.focus proof_edits p
 
103
          
 
104
let get_current_proof_name () =
 
105
  match Edit.read proof_edits with
 
106
    | None ->
 
107
        errorlabstrm "Pfedit.get_proof"
 
108
          (str"No focused proof" ++ msg_proofs true)
 
109
    | Some(na,_,_) -> na
 
110
 
 
111
let add_proof (na,pfs,ts) =
 
112
  Edit.create proof_edits (na,pfs,ts,!undo_limit+1)
 
113
 
 
114
let delete_proof_gen = Edit.delete proof_edits
 
115
 
 
116
let delete_proof (loc,id) =
 
117
  try 
 
118
    delete_proof_gen id
 
119
  with (UserError ("Edit.delete",_)) ->
 
120
    user_err_loc
 
121
      (loc,"Pfedit.delete_proof",str"No such proof" ++ msg_proofs false)
 
122
      
 
123
let mutate f =
 
124
  try 
 
125
    Edit.mutate proof_edits (fun _ pfs -> f pfs)
 
126
  with Invalid_argument "Edit.mutate" ->
 
127
    errorlabstrm "Pfedit.mutate"
 
128
      (str"No focused proof" ++ msg_proofs true)
 
129
 
 
130
let start (na,ts) =
 
131
  let pfs = mk_pftreestate ts.top_goal in
 
132
  let pfs = Option.fold_right solve_pftreestate ts.top_init_tac pfs in
 
133
  add_proof(na,pfs,ts)
 
134
    
 
135
let restart_proof () =
 
136
  match Edit.read proof_edits with
 
137
    | None -> 
 
138
        errorlabstrm "Pfedit.restart"
 
139
          (str"No focused proof to restart" ++ msg_proofs true)
 
140
    | Some(na,_,ts) -> 
 
141
        delete_proof_gen na;
 
142
        start (na,ts);
 
143
        set_current_proof na
 
144
 
 
145
let proof_term () =
 
146
  extract_pftreestate (get_pftreestate())
 
147
    
 
148
(* Detect is one has completed a subtree of the initial goal *)
 
149
let subtree_solved () = 
 
150
  let pts = get_pftreestate () in
 
151
  is_complete_proof (proof_of_pftreestate pts) & 
 
152
  not (is_top_pftreestate pts)
 
153
 
 
154
let tree_solved () = 
 
155
  let pts = get_pftreestate () in
 
156
  is_complete_proof (proof_of_pftreestate pts)
 
157
 
 
158
let top_tree_solved () = 
 
159
  let pts = get_pftreestate () in
 
160
  is_complete_proof (proof_of_pftreestate (top_of_tree pts))
 
161
 
 
162
(*********************************************************************)
 
163
(*                 Undo functions                                    *)
 
164
(*********************************************************************)
 
165
 
 
166
let set_undo = function
 
167
  | None -> undo_limit := undo_default
 
168
  | Some n -> 
 
169
      if n>=0 then 
 
170
        undo_limit := n
 
171
      else 
 
172
        error "Cannot set a negative undo limit"
 
173
 
 
174
let get_undo () = Some !undo_limit
 
175
 
 
176
let undo n =
 
177
  try 
 
178
    Edit.undo proof_edits n; 
 
179
       (* needed because the resolution of a subtree is done in 2 steps 
 
180
       then a sequence of undo can lead to a focus on a completely solved 
 
181
       subtree - this solution only works properly if undoing one step *)
 
182
    if subtree_solved() then  Edit.undo proof_edits 1
 
183
  with (Invalid_argument "Edit.undo") ->
 
184
    errorlabstrm "Pfedit.undo" (str"No focused proof" ++ msg_proofs true)
 
185
 
 
186
(* Undo current focused proof to reach depth [n]. This is used in
 
187
   [vernac_backtrack]. *)
 
188
let undo_todepth n =
 
189
  try 
 
190
    Edit.undo_todepth proof_edits n
 
191
  with (Invalid_argument "Edit.undo") ->
 
192
    errorlabstrm "Pfedit.undo" (str"No focused proof" ++ msg_proofs true)
 
193
 
 
194
(* Return the depth of the current focused proof stack, this is used
 
195
   to put informations in coq prompt (in emacs mode). *)
 
196
let current_proof_depth() = 
 
197
  try
 
198
    Edit.depth proof_edits
 
199
  with (Invalid_argument "Edit.depth") -> -1
 
200
 
 
201
(*********************************************************************)
 
202
(*                  Proof cooking                                    *)
 
203
(*********************************************************************)
 
204
 
 
205
let xml_cook_proof = ref (fun _ -> ())
 
206
let set_xml_cook_proof f = xml_cook_proof := f
 
207
 
 
208
let cook_proof k =
 
209
  let (pfs,ts) = get_state() 
 
210
  and ident = get_current_proof_name () in
 
211
  let {evar_concl=concl} = ts.top_goal
 
212
  and strength = ts.top_strength in
 
213
  let pfterm = extract_pftreestate pfs in
 
214
  !xml_cook_proof (strength,pfs);
 
215
  k pfs;
 
216
  (ident,
 
217
   ({ const_entry_body = pfterm;
 
218
      const_entry_type = Some concl;
 
219
      const_entry_opaque = true;
 
220
      const_entry_boxed = false},
 
221
    ts.top_compute_guard, strength, ts.top_hook))
 
222
 
 
223
let current_proof_statement () = 
 
224
  let ts = get_topstate() in
 
225
  (get_current_proof_name (), ts.top_strength, 
 
226
   ts.top_goal.evar_concl, ts.top_hook)
 
227
 
 
228
(*********************************************************************)
 
229
(*              Abort   functions                                    *)
 
230
(*********************************************************************)
 
231
 
 
232
let refining () = [] <> (Edit.dom proof_edits)
 
233
 
 
234
let check_no_pending_proofs () =
 
235
  if refining () then 
 
236
    errorlabstrm "check_no_pending_proofs"
 
237
      (str"Proof editing in progress" ++ (msg_proofs false) ++ fnl() ++
 
238
         str"Use \"Abort All\" first or complete proof(s).")
 
239
 
 
240
let delete_current_proof () = delete_proof_gen (get_current_proof_name ())
 
241
 
 
242
let delete_all_proofs () = Edit.clear proof_edits
 
243
 
 
244
(*********************************************************************)
 
245
(*   Modifying the end tactic of the current profftree               *)
 
246
(*********************************************************************)
 
247
let set_end_tac tac =
 
248
  let top = get_topstate () in
 
249
  top.top_end_tac <- Some tac
 
250
 
 
251
(*********************************************************************)
 
252
(*              Modifying the current prooftree                      *)
 
253
(*********************************************************************)
 
254
 
 
255
let start_proof na str sign concl ?init_tac ?(compute_guard=false) hook =
 
256
  let top_goal = mk_goal sign concl None in
 
257
  let ts = { 
 
258
    top_end_tac = None;
 
259
    top_init_tac = init_tac;
 
260
    top_compute_guard = compute_guard;
 
261
    top_goal = top_goal;
 
262
    top_strength = str;
 
263
    top_hook = hook}
 
264
  in
 
265
  start(na,ts);
 
266
  set_current_proof na
 
267
 
 
268
let solve_nth k tac =
 
269
  let pft = get_pftreestate () in
 
270
  if not (List.mem (-1) (cursor_of_pftreestate pft)) then
 
271
    mutate (solve_nth_pftreestate k tac)
 
272
  else 
 
273
    error "cannot apply a tactic when we are descended behind a tactic-node"
 
274
 
 
275
let by tac = mutate (solve_pftreestate tac)
 
276
 
 
277
let instantiate_nth_evar_com n c =
 
278
  mutate (Evar_refiner.instantiate_pf_com n c)
 
279
 
 
280
let traverse n = mutate (traverse n)
 
281
 
 
282
(* [traverse_to path]
 
283
 
 
284
   Traverses the current proof to get to the location specified by
 
285
   [path].
 
286
 
 
287
   ALGORITHM: The algorithm works on reversed paths. One just has to remove
 
288
   the common part on the reversed paths.
 
289
 
 
290
*)
 
291
 
 
292
let common_ancestor l1 l2 =
 
293
  let rec common_aux l1 l2 =
 
294
    match l1, l2 with
 
295
      | a1::l1', a2::l2' when a1 = a2 -> common_aux l1' l2'
 
296
      | _, _ -> List.rev l1, List.length l2
 
297
  in
 
298
  common_aux (List.rev l1) (List.rev l2)
 
299
      
 
300
let rec traverse_up = function
 
301
  | 0 -> (function pf -> pf)
 
302
  | n -> (function pf -> Refiner.traverse 0 (traverse_up (n - 1) pf))
 
303
 
 
304
let rec traverse_down = function
 
305
  | [] -> (function pf -> pf)
 
306
  | n::l -> (function pf -> Refiner.traverse n (traverse_down l pf))
 
307
 
 
308
let traverse_to path =
 
309
  let up_and_down path pfs =
 
310
    let cursor = cursor_of_pftreestate pfs in
 
311
    let down_list, up_count = common_ancestor path cursor in
 
312
    traverse_down down_list (traverse_up up_count pfs)
 
313
  in
 
314
  mutate (up_and_down path)
 
315
 
 
316
(* traverse the proof tree until it reach the nth subgoal *)
 
317
let traverse_nth_goal n = mutate (nth_unproven n)
 
318
 
 
319
let traverse_prev_unproven () = mutate prev_unproven
 
320
 
 
321
let traverse_next_unproven () = mutate next_unproven
 
322
 
 
323
(* The goal focused on *)
 
324
let focus_n = ref 0
 
325
let make_focus n = focus_n := n
 
326
let focus () = !focus_n
 
327
let focused_goal () = let n = !focus_n in if n=0 then 1 else n
 
328
 
 
329
let reset_top_of_tree () = 
 
330
  mutate top_of_tree
 
331
 
 
332
let reset_top_of_script () = 
 
333
  mutate (fun pts -> 
 
334
        try
 
335
         up_until_matching_rule is_proof_instr pts
 
336
        with Not_found -> top_of_tree pts)
 
337