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

« back to all changes in this revision

Viewing changes to contrib/xml/xmlcommand.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
(*    //   *   The HELM Project         /   The EU MoWGLI Project       *)
 
6
(*         *   University of Bologna                                    *)
 
7
(************************************************************************)
 
8
(*          This file is distributed under the terms of the             *)
 
9
(*           GNU Lesser General Public License Version 2.1              *)
 
10
(*                                                                      *)
 
11
(*                 Copyright (C) 2000-2004, HELM Team.                  *)
 
12
(*                       http://helm.cs.unibo.it                        *)
 
13
(************************************************************************)
 
14
 
 
15
(* CONFIGURATION PARAMETERS *)
 
16
 
 
17
let verbose = ref false;;
 
18
 
 
19
(* HOOKS *)
 
20
let print_proof_tree, set_print_proof_tree =
 
21
 let print_proof_tree = ref (fun _ _ _ _ _ _ -> None) in
 
22
  (fun () -> !print_proof_tree),
 
23
   (fun f ->
 
24
     print_proof_tree :=
 
25
     fun
 
26
      curi sigma0 pf proof_tree_to_constr proof_tree_to_flattened_proof_tree
 
27
      constr_to_ids
 
28
     ->
 
29
      Some
 
30
       (f curi sigma0 pf proof_tree_to_constr
 
31
        proof_tree_to_flattened_proof_tree constr_to_ids))
 
32
;;
 
33
 
 
34
(* UTILITY FUNCTIONS *)
 
35
 
 
36
let print_if_verbose s = if !verbose then print_string s;;
 
37
 
 
38
(* Next exception is used only inside print_coq_object and tag_of_string_tag *)
 
39
exception Uninteresting;;
 
40
 
 
41
(* NOT USED anymore, we back to the V6 point of view with global parameters 
 
42
 
 
43
(* Internally, for Coq V7, params of inductive types are associated     *)
 
44
(* not to the whole block of mutual inductive (as it was in V6) but to  *)
 
45
(* each member of the block; but externally, all params are required    *)
 
46
(* to be the same; the following function checks that the parameters    *)
 
47
(* of each inductive of a same block are all the same, then returns     *)
 
48
(* this number; it fails otherwise                                      *)
 
49
let extract_nparams pack =
 
50
 let module D = Declarations in
 
51
 let module U = Util in
 
52
 let module S = Sign in
 
53
 
 
54
  let {D.mind_nparams=nparams0} = pack.(0) in
 
55
  let arity0 = pack.(0).D.mind_user_arity in
 
56
  let params0, _ = S.decompose_prod_n_assum nparams0 arity0 in
 
57
  for i = 1 to Array.length pack - 1 do
 
58
    let {D.mind_nparams=nparamsi} = pack.(i) in
 
59
    let arityi = pack.(i).D.mind_user_arity in
 
60
    let paramsi, _ = S.decompose_prod_n_assum nparamsi arityi in
 
61
    if params0 <> paramsi then U.error "Cannot convert a block of inductive definitions with parameters specific to each inductive to a block of mutual inductive definitions with parameters global to the whole block"
 
62
  done;
 
63
  nparams0
 
64
 
 
65
*)
 
66
 
 
67
(* could_have_namesakes sp = true iff o is an object that could be cooked and *)
 
68
(* than that could exists in cooked form with the same name in a super        *)
 
69
(* section of the actual section                                              *)
 
70
let could_have_namesakes o sp =      (* namesake = omonimo in italian *)
 
71
 let module DK = Decl_kinds in
 
72
 let module D = Declare in
 
73
  let tag = Libobject.object_tag o in
 
74
   print_if_verbose ("Object tag: " ^ tag ^ "\n") ;
 
75
   match tag with
 
76
      "CONSTANT"        -> true   (* constants/parameters are non global *)
 
77
    | "INDUCTIVE"       -> true   (* mutual inductive types are never local   *)
 
78
    | "VARIABLE"        -> false  (* variables are local, so no namesakes     *)
 
79
    | _                 -> false  (* uninteresting thing that won't be printed*)
 
80
;;
 
81
 
 
82
(* filter_params pvars hyps *)
 
83
(* filters out from pvars (which is a list of lists) all the variables *)
 
84
(* that does not belong to hyps (which is a simple list)               *)
 
85
(* It returns a list of couples relative section path -- list of       *)
 
86
(* variable names.                                                     *)
 
87
let filter_params pvars hyps =
 
88
 let rec aux ids =
 
89
  function
 
90
     [] -> []
 
91
   | (id,he)::tl ->
 
92
      let ids' = id::ids in
 
93
      let ids'' =
 
94
       "cic:/" ^
 
95
        String.concat "/" (List.rev (List.map Names.string_of_id ids')) in
 
96
      let he' =
 
97
       ids'', List.rev (List.filter (function x -> List.mem x hyps) he) in
 
98
      let tl' = aux ids' tl in
 
99
       match he' with
 
100
          _,[] -> tl'
 
101
        | _,_  -> he'::tl'
 
102
 in
 
103
  let cwd = Lib.cwd () in
 
104
  let cwdsp = Libnames.make_path cwd (Names.id_of_string "dummy") in
 
105
  let modulepath = Cic2acic.get_module_path_of_section_path cwdsp in
 
106
   aux (Names.repr_dirpath modulepath) (List.rev pvars)
 
107
;;
 
108
 
 
109
type variables_type = 
 
110
   Definition of string * Term.constr * Term.types
 
111
 | Assumption of string * Term.constr
 
112
;;
 
113
 
 
114
(* The computation is very inefficient, but we can't do anything *)
 
115
(* better unless this function is reimplemented in the Declare   *)
 
116
(* module.                                                       *)
 
117
let search_variables () =
 
118
 let module N = Names in
 
119
  let cwd = Lib.cwd () in
 
120
  let cwdsp = Libnames.make_path cwd (Names.id_of_string "dummy") in
 
121
  let modulepath = Cic2acic.get_module_path_of_section_path cwdsp in
 
122
   let rec aux =
 
123
    function
 
124
       [] -> []
 
125
     | he::tl as modules ->
 
126
        let one_section_variables =
 
127
         let dirpath = N.make_dirpath (modules @ N.repr_dirpath modulepath) in
 
128
          let t = List.map N.string_of_id (Decls.last_section_hyps dirpath) in
 
129
           [he,t]
 
130
        in
 
131
         one_section_variables @ aux tl
 
132
   in
 
133
    aux
 
134
     (Cic2acic.remove_module_dirpath_from_dirpath
 
135
       ~basedir:modulepath cwd)
 
136
;;
 
137
 
 
138
(* FUNCTIONS TO PRINT A SINGLE OBJECT OF COQ *)
 
139
 
 
140
let rec join_dirs cwd =
 
141
 function
 
142
    []  -> cwd
 
143
  | he::tail ->
 
144
      (try
 
145
        Unix.mkdir cwd 0o775
 
146
       with _ -> () (* Let's ignore the errors on mkdir *)
 
147
      ) ;
 
148
     let newcwd = cwd ^ "/" ^ he in
 
149
      join_dirs newcwd tail
 
150
;;
 
151
 
 
152
let filename_of_path xml_library_root tag =
 
153
 let module N = Names in
 
154
  match xml_library_root with
 
155
     None -> None  (* stdout *)
 
156
   | Some xml_library_root' ->
 
157
      let tokens = Cic2acic.token_list_of_kernel_name tag in
 
158
       Some (join_dirs xml_library_root' tokens)
 
159
;;
 
160
 
 
161
let body_filename_of_filename =
 
162
 function
 
163
    Some f -> Some (f ^ ".body")
 
164
  | None   -> None
 
165
;;
 
166
 
 
167
let types_filename_of_filename =
 
168
 function
 
169
    Some f -> Some (f ^ ".types")
 
170
  | None   -> None
 
171
;;
 
172
 
 
173
let prooftree_filename_of_filename =
 
174
 function
 
175
    Some f -> Some (f ^ ".proof_tree")
 
176
  | None   -> None
 
177
;;
 
178
 
 
179
let theory_filename xml_library_root =
 
180
 let module N = Names in
 
181
  match xml_library_root with
 
182
    None -> None  (* stdout *)
 
183
  | Some xml_library_root' ->
 
184
     let toks = List.map N.string_of_id (N.repr_dirpath (Lib.library_dp ())) in
 
185
     (* theory from A/B/C/F.v goes into A/B/C/F.theory *)
 
186
     let alltoks = List.rev toks in
 
187
       Some (join_dirs xml_library_root' alltoks ^ ".theory")
 
188
 
 
189
let print_object uri obj sigma proof_tree_infos filename =
 
190
 (* function to pretty print and compress an XML file *)
 
191
(*CSC: Unix.system "gzip ..." is an horrible non-portable solution. *)
 
192
 let pp xml filename =
 
193
  Xml.pp xml filename ;
 
194
  match filename with
 
195
     None -> ()
 
196
   | Some fn ->
 
197
      let fn' =
 
198
       let rec escape s n =
 
199
        try
 
200
         let p = String.index_from s n '\'' in
 
201
          String.sub s n (p - n) ^ "\\'" ^ escape s (p+1)
 
202
        with Not_found -> String.sub s n (String.length s - n)
 
203
       in
 
204
        escape fn 0
 
205
      in
 
206
       ignore (Unix.system ("gzip " ^ fn' ^ ".xml"))
 
207
 in
 
208
  let (annobj,_,constr_to_ids,_,ids_to_inner_sorts,ids_to_inner_types,_,_) =
 
209
   Cic2acic.acic_object_of_cic_object sigma obj in
 
210
  let (xml, xml') = Acic2Xml.print_object uri ids_to_inner_sorts annobj in
 
211
  let xmltypes =
 
212
   Acic2Xml.print_inner_types uri ids_to_inner_sorts ids_to_inner_types in
 
213
  pp xml filename ;
 
214
  begin
 
215
   match xml' with
 
216
      None -> ()
 
217
    | Some xml' -> pp xml' (body_filename_of_filename filename)
 
218
  end ;
 
219
  pp xmltypes (types_filename_of_filename filename) ;
 
220
  match proof_tree_infos with
 
221
     None -> ()
 
222
   | Some (sigma0,proof_tree,proof_tree_to_constr,
 
223
           proof_tree_to_flattened_proof_tree) ->
 
224
      let xmlprooftree =
 
225
       print_proof_tree ()
 
226
        uri sigma0 proof_tree proof_tree_to_constr
 
227
        proof_tree_to_flattened_proof_tree constr_to_ids
 
228
      in
 
229
       match xmlprooftree with
 
230
          None -> ()
 
231
        | Some xmlprooftree ->
 
232
           pp xmlprooftree (prooftree_filename_of_filename filename)
 
233
;;
 
234
 
 
235
let string_list_of_named_context_list =
 
236
 List.map
 
237
  (function (n,_,_) -> Names.string_of_id n)
 
238
;;
 
239
 
 
240
(* Function to collect the variables that occur in a term. *)
 
241
(* Used only for variables (since for constants and mutual *)
 
242
(* inductive types this information is already available.  *)
 
243
let find_hyps t =
 
244
 let module T = Term in
 
245
  let rec aux l t =
 
246
   match T.kind_of_term t with
 
247
      T.Var id when not (List.mem id l) ->
 
248
       let (_,bo,ty) = Global.lookup_named id in
 
249
        let boids = 
 
250
         match bo with
 
251
            Some bo' -> aux l bo'
 
252
          | None -> l
 
253
        in
 
254
         id::(aux boids ty)
 
255
    | T.Var _
 
256
    | T.Rel _
 
257
    | T.Meta _
 
258
    | T.Evar _
 
259
    | T.Sort _ -> l
 
260
    | T.Cast (te,_, ty) -> aux (aux l te) ty
 
261
    | T.Prod (_,s,t) -> aux (aux l s) t
 
262
    | T.Lambda (_,s,t) -> aux (aux l s) t
 
263
    | T.LetIn (_,s,_,t) -> aux (aux l s) t
 
264
    | T.App (he,tl) -> Array.fold_left (fun i x -> aux i x) (aux l he) tl
 
265
    | T.Const con ->
 
266
       let hyps = (Global.lookup_constant con).Declarations.const_hyps in
 
267
        map_and_filter l hyps @ l
 
268
    | T.Ind ind
 
269
    | T.Construct (ind,_) ->
 
270
       let hyps = (fst (Global.lookup_inductive ind)).Declarations.mind_hyps in
 
271
        map_and_filter l hyps @ l
 
272
    | T.Case (_,t1,t2,b) ->
 
273
       Array.fold_left (fun i x -> aux i x) (aux (aux l t1) t2) b
 
274
    | T.Fix (_,(_,tys,bodies))
 
275
    | T.CoFix (_,(_,tys,bodies)) ->
 
276
       let r = Array.fold_left (fun i x -> aux i x) l tys in
 
277
        Array.fold_left (fun i x -> aux i x) r bodies
 
278
  and map_and_filter l =
 
279
   function
 
280
      [] -> []
 
281
    | (n,_,_)::tl when not (List.mem n l) -> n::(map_and_filter l tl)
 
282
    | _::tl -> map_and_filter l tl
 
283
  in
 
284
   aux [] t
 
285
;;
 
286
 
 
287
(* Functions to construct an object *)
 
288
 
 
289
let mk_variable_obj id body typ =
 
290
 let hyps,unsharedbody =
 
291
  match body with
 
292
     None -> [],None
 
293
   | Some bo -> find_hyps bo, Some (Unshare.unshare bo)
 
294
 in
 
295
  let hyps' = find_hyps typ @ hyps in
 
296
  let hyps'' = List.map Names.string_of_id hyps' in
 
297
  let variables = search_variables () in
 
298
  let params = filter_params variables hyps'' in
 
299
   Acic.Variable
 
300
    (Names.string_of_id id, unsharedbody, Unshare.unshare typ, params)
 
301
;;
 
302
 
 
303
(* Unsharing is not performed on the body, that must be already unshared. *)
 
304
(* The evar map and the type, instead, are unshared by this function.     *)
 
305
let mk_current_proof_obj is_a_variable id bo ty evar_map env =
 
306
 let unshared_ty = Unshare.unshare ty in
 
307
 let metasenv =
 
308
  List.map
 
309
   (function
 
310
     (n, {Evd.evar_concl = evar_concl ;
 
311
          Evd.evar_hyps = evar_hyps}
 
312
      ) ->
 
313
       (* We map the named context to a rel context and every Var to a Rel *)
 
314
       let final_var_ids,context =
 
315
        let rec aux var_ids =
 
316
         function
 
317
            [] -> var_ids,[]
 
318
          | (n,None,t)::tl ->
 
319
              let final_var_ids,tl' = aux (n::var_ids) tl in
 
320
              let t' = Term.subst_vars var_ids t in
 
321
               final_var_ids,(n, Acic.Decl (Unshare.unshare t'))::tl'
 
322
          | (n,Some b,t)::tl ->
 
323
              let final_var_ids,tl' = aux (n::var_ids) tl in
 
324
              let b' = Term.subst_vars var_ids b in
 
325
               (* t will not be exported to XML. Thus no unsharing performed *)
 
326
               final_var_ids,(n, Acic.Def  (Unshare.unshare b',t))::tl'
 
327
        in
 
328
         aux [] (List.rev (Environ.named_context_of_val evar_hyps))
 
329
       in
 
330
        (* We map the named context to a rel context and every Var to a Rel *)
 
331
        (n,context,Unshare.unshare (Term.subst_vars final_var_ids evar_concl))
 
332
   ) (Evarutil.non_instantiated evar_map)
 
333
 in
 
334
  let id' = Names.string_of_id id in
 
335
   if metasenv = [] then
 
336
    let ids =
 
337
     Names.Idset.union
 
338
      (Environ.global_vars_set env bo) (Environ.global_vars_set env ty) in
 
339
    let hyps0 = Environ.keep_hyps env ids in
 
340
    let hyps = string_list_of_named_context_list hyps0 in
 
341
    (* Variables are the identifiers of the variables in scope *)
 
342
    let variables = search_variables () in
 
343
    let params = filter_params variables hyps in
 
344
     if is_a_variable then
 
345
      Acic.Variable (id',Some bo,unshared_ty,params)
 
346
     else
 
347
      Acic.Constant (id',Some bo,unshared_ty,params)
 
348
   else
 
349
    Acic.CurrentProof (id',metasenv,bo,unshared_ty)
 
350
;;
 
351
 
 
352
let mk_constant_obj id bo ty variables hyps =
 
353
 let hyps = string_list_of_named_context_list hyps in
 
354
 let ty = Unshare.unshare ty in
 
355
 let params = filter_params variables hyps in
 
356
  match bo with
 
357
     None ->
 
358
      Acic.Constant (Names.string_of_id id,None,ty,params)
 
359
   | Some c ->
 
360
      Acic.Constant
 
361
       (Names.string_of_id id, Some (Unshare.unshare (Declarations.force c)),
 
362
         ty,params)
 
363
;;
 
364
 
 
365
let mk_inductive_obj sp mib packs variables nparams hyps finite =
 
366
 let module D = Declarations in
 
367
  let hyps = string_list_of_named_context_list hyps in
 
368
  let params = filter_params variables hyps in
 
369
(*  let nparams = extract_nparams packs in *)
 
370
   let tys =
 
371
    let tyno = ref (Array.length packs) in
 
372
    Array.fold_right
 
373
     (fun p i ->
 
374
       decr tyno ;
 
375
       let {D.mind_consnames=consnames ;
 
376
            D.mind_typename=typename } = p
 
377
       in
 
378
        let arity = Inductive.type_of_inductive (Global.env()) (mib,p) in
 
379
        let lc = Inductiveops.arities_of_constructors (Global.env ()) (sp,!tyno) in
 
380
        let cons =
 
381
         (Array.fold_right (fun (name,lc) i -> (name,lc)::i)
 
382
          (Array.mapi
 
383
           (fun j x ->(x,Unshare.unshare lc.(j))) consnames)
 
384
          []
 
385
         )
 
386
        in
 
387
         (typename,finite,Unshare.unshare arity,cons)::i
 
388
     ) packs []
 
389
   in
 
390
    Acic.InductiveDefinition (tys,params,nparams)
 
391
;;
 
392
 
 
393
(* The current channel for .theory files *)
 
394
let theory_buffer = Buffer.create 4000;;
 
395
 
 
396
let theory_output_string ?(do_not_quote = false) s = 
 
397
  (* prepare for coqdoc post-processing *)
 
398
  let s = if do_not_quote then s else "(** #"^s^"\n#*)\n" in
 
399
  print_if_verbose s;
 
400
   Buffer.add_string theory_buffer s
 
401
;;
 
402
 
 
403
let kind_of_global_goal = function
 
404
  | Decl_kinds.Global, Decl_kinds.DefinitionBody _ -> "DEFINITION","InteractiveDefinition"
 
405
  | Decl_kinds.Global, (Decl_kinds.Proof k) -> "THEOREM",Decl_kinds.string_of_theorem_kind k
 
406
  | Decl_kinds.Local, _ -> assert false
 
407
 
 
408
let kind_of_inductive isrecord kn =
 
409
 "DEFINITION",
 
410
 if (fst (Global.lookup_inductive (kn,0))).Declarations.mind_finite
 
411
 then if isrecord then "Record" else "Inductive"
 
412
 else "CoInductive"
 
413
;;
 
414
 
 
415
let kind_of_variable id =
 
416
  let module DK = Decl_kinds in
 
417
  match Decls.variable_kind id with
 
418
    | DK.IsAssumption DK.Definitional -> "VARIABLE","Assumption"
 
419
    | DK.IsAssumption DK.Logical -> "VARIABLE","Hypothesis"
 
420
    | DK.IsAssumption DK.Conjectural -> "VARIABLE","Conjecture"
 
421
    | DK.IsDefinition DK.Definition -> "VARIABLE","LocalDefinition"
 
422
    | DK.IsProof _ -> "VARIABLE","LocalFact"
 
423
    | _ -> Util.anomaly "Unsupported variable kind"
 
424
;;
 
425
 
 
426
let kind_of_constant kn = 
 
427
  let module DK = Decl_kinds in
 
428
  match Decls.constant_kind kn with
 
429
    | DK.IsAssumption DK.Definitional -> "AXIOM","Declaration"
 
430
    | DK.IsAssumption DK.Logical -> "AXIOM","Axiom"
 
431
    | DK.IsAssumption DK.Conjectural ->
 
432
        Pp.warning "Conjecture not supported in dtd (used Declaration instead)";
 
433
        "AXIOM","Declaration"
 
434
    | DK.IsDefinition DK.Definition -> "DEFINITION","Definition"
 
435
    | DK.IsDefinition DK.Example -> 
 
436
        Pp.warning "Example not supported in dtd (used Definition instead)";
 
437
        "DEFINITION","Definition"
 
438
    | DK.IsDefinition DK.Coercion ->
 
439
        Pp.warning "Coercion not supported in dtd (used Definition instead)";
 
440
        "DEFINITION","Definition"
 
441
    | DK.IsDefinition DK.SubClass ->
 
442
        Pp.warning "SubClass not supported in dtd (used Definition instead)";
 
443
        "DEFINITION","Definition"
 
444
    | DK.IsDefinition DK.CanonicalStructure ->
 
445
        Pp.warning "CanonicalStructure not supported in dtd (used Definition instead)";
 
446
        "DEFINITION","Definition"
 
447
    | DK.IsDefinition DK.Fixpoint ->
 
448
        Pp.warning "Fixpoint not supported in dtd (used Definition instead)";
 
449
        "DEFINITION","Definition"
 
450
    | DK.IsDefinition DK.CoFixpoint ->
 
451
        Pp.warning "CoFixpoint not supported in dtd (used Definition instead)";
 
452
        "DEFINITION","Definition"
 
453
    | DK.IsDefinition DK.Scheme ->
 
454
        Pp.warning "Scheme not supported in dtd (used Definition instead)";
 
455
        "DEFINITION","Definition"
 
456
    | DK.IsDefinition DK.StructureComponent ->
 
457
        Pp.warning "StructureComponent not supported in dtd (used Definition instead)";
 
458
        "DEFINITION","Definition"
 
459
    | DK.IsDefinition DK.IdentityCoercion ->
 
460
        Pp.warning "IdentityCoercion not supported in dtd (used Definition instead)";
 
461
        "DEFINITION","Definition"
 
462
    | DK.IsDefinition DK.Instance ->
 
463
        Pp.warning "Instance not supported in dtd (used Definition instead)";
 
464
        "DEFINITION","Definition" 
 
465
    | DK.IsDefinition DK.Method ->
 
466
        Pp.warning "Method not supported in dtd (used Definition instead)";
 
467
        "DEFINITION","Definition" 
 
468
    | DK.IsProof (DK.Theorem|DK.Lemma|DK.Corollary|DK.Fact|DK.Remark as thm) ->
 
469
        "THEOREM",DK.string_of_theorem_kind thm
 
470
    | DK.IsProof _ ->
 
471
        Pp.warning "Unsupported theorem kind (used Theorem instead)";
 
472
        "THEOREM",DK.string_of_theorem_kind DK.Theorem
 
473
;;
 
474
 
 
475
let kind_of_global r =
 
476
  let module Ln = Libnames in
 
477
  let module DK = Decl_kinds in
 
478
  match r with
 
479
  | Ln.IndRef kn | Ln.ConstructRef (kn,_) -> 
 
480
      let isrecord =
 
481
        try let _ = Recordops.lookup_projections kn in true
 
482
        with Not_found -> false in
 
483
      kind_of_inductive isrecord (fst kn)
 
484
  | Ln.VarRef id -> kind_of_variable id
 
485
  | Ln.ConstRef kn -> kind_of_constant kn
 
486
;;
 
487
 
 
488
let print_object_kind uri (xmltag,variation) =
 
489
  let s =
 
490
    Printf.sprintf "<ht:%s uri=\"%s\" as=\"%s\"/>\n" xmltag uri variation
 
491
  in
 
492
  theory_output_string s
 
493
;;
 
494
 
 
495
(* print id dest                                                          *)
 
496
(*  where sp   is the qualified identifier (section path) of a            *)
 
497
(*             definition/theorem, variable or inductive definition       *)
 
498
(*  and   dest is either None (for stdout) or (Some filename)             *)
 
499
(* pretty prints via Xml.pp the object whose identifier is id on dest     *)
 
500
(* Note: it is printed only (and directly) the most cooked available      *)
 
501
(*       form of the definition (all the parameters are                   *)
 
502
(*       lambda-abstracted, but the object can still refer to variables)  *)
 
503
let print internal glob_ref kind xml_library_root =
 
504
 let module D = Declarations in
 
505
 let module De = Declare in
 
506
 let module G = Global in
 
507
 let module N = Names in
 
508
 let module Nt = Nametab in
 
509
 let module T = Term in
 
510
 let module X = Xml in
 
511
 let module Ln = Libnames in
 
512
  (* Variables are the identifiers of the variables in scope *)
 
513
  let variables = search_variables () in
 
514
  let tag,obj =
 
515
   match glob_ref with
 
516
      Ln.VarRef id ->
 
517
       (* this kn is fake since it is not provided by Coq *)
 
518
       let kn = 
 
519
        let (mod_path,dir_path) = Lib.current_prefix () in
 
520
        N.make_kn mod_path dir_path (N.label_of_id id)
 
521
       in
 
522
       let (_,body,typ) = G.lookup_named id in
 
523
        Cic2acic.Variable kn,mk_variable_obj id body typ
 
524
    | Ln.ConstRef kn ->
 
525
       let id = N.id_of_label (N.con_label kn) in
 
526
       let {D.const_body=val0 ; D.const_type = typ ; D.const_hyps = hyps} =
 
527
        G.lookup_constant kn in
 
528
       let typ = Typeops.type_of_constant_type (Global.env()) typ in
 
529
        Cic2acic.Constant kn,mk_constant_obj id val0 typ variables hyps
 
530
    | Ln.IndRef (kn,_) ->
 
531
       let mib = G.lookup_mind kn in
 
532
       let {D.mind_nparams=nparams;
 
533
            D.mind_packets=packs ;
 
534
            D.mind_hyps=hyps;
 
535
            D.mind_finite=finite} = mib in
 
536
          Cic2acic.Inductive kn,mk_inductive_obj kn mib packs variables nparams hyps finite
 
537
    | Ln.ConstructRef _ ->
 
538
       Util.error ("a single constructor cannot be printed in XML")
 
539
  in
 
540
  let fn = filename_of_path xml_library_root tag in
 
541
  let uri = Cic2acic.uri_of_kernel_name tag in
 
542
   if not internal then print_object_kind uri kind;
 
543
   print_object uri obj Evd.empty None fn
 
544
;;
 
545
 
 
546
let print_ref qid fn =
 
547
  let ref = Nametab.global qid in
 
548
  print false ref (kind_of_global ref) fn
 
549
 
 
550
(* show dest                                                  *)
 
551
(*  where dest is either None (for stdout) or (Some filename) *)
 
552
(* pretty prints via Xml.pp the proof in progress on dest     *)
 
553
let show_pftreestate internal fn (kind,pftst) id =
 
554
 let pf = Tacmach.proof_of_pftreestate pftst in
 
555
 let typ = (Proof_trees.goal_of_proof pf).Evd.evar_concl in
 
556
 let val0,evar_map,proof_tree_to_constr,proof_tree_to_flattened_proof_tree,
 
557
     unshared_pf
 
558
 =
 
559
  Proof2aproof.extract_open_pftreestate pftst in
 
560
 let env = Global.env () in
 
561
 let obj =
 
562
  mk_current_proof_obj (fst kind = Decl_kinds.Local) id val0 typ evar_map env in
 
563
 let uri =
 
564
  match kind with
 
565
     Decl_kinds.Local, _ ->
 
566
      let uri =
 
567
       "cic:/" ^ String.concat "/"
 
568
        (Cic2acic.token_list_of_path (Lib.cwd ()) id Cic2acic.TVariable)
 
569
      in
 
570
      let kind_of_var = "VARIABLE","LocalFact" in
 
571
       if not internal then print_object_kind uri kind_of_var;
 
572
      uri
 
573
   | Decl_kinds.Global, _ ->
 
574
      let uri = Cic2acic.uri_of_declaration id Cic2acic.TConstant in
 
575
       if not internal then print_object_kind uri (kind_of_global_goal kind);
 
576
       uri
 
577
 in
 
578
  print_object uri obj evar_map
 
579
   (Some (Tacmach.evc_of_pftreestate pftst,unshared_pf,proof_tree_to_constr,
 
580
    proof_tree_to_flattened_proof_tree)) fn
 
581
;;
 
582
 
 
583
let show fn =
 
584
 let pftst = Pfedit.get_pftreestate () in
 
585
 let (id,kind,_,_) = Pfedit.current_proof_statement () in
 
586
  show_pftreestate false fn (kind,pftst) id
 
587
;;
 
588
 
 
589
 
 
590
(* Let's register the callbacks *)
 
591
let xml_library_root =
 
592
  try
 
593
   Some (Sys.getenv "COQ_XML_LIBRARY_ROOT")
 
594
  with Not_found -> None
 
595
;;
 
596
 
 
597
let proof_to_export = ref None (* holds the proof-tree to export *)
 
598
;;
 
599
 
 
600
let _ =
 
601
  Pfedit.set_xml_cook_proof
 
602
   (function pftreestate -> proof_to_export := Some pftreestate)
 
603
;;
 
604
 
 
605
let _ =
 
606
  Declare.set_xml_declare_variable
 
607
   (function (sp,kn) ->
 
608
     let id = Libnames.basename sp in
 
609
     print false (Libnames.VarRef id) (kind_of_variable id) xml_library_root ;
 
610
     proof_to_export := None)
 
611
;;
 
612
 
 
613
let _ =
 
614
  Declare.set_xml_declare_constant
 
615
   (function (internal,kn) ->
 
616
     match !proof_to_export with
 
617
        None ->
 
618
          print internal (Libnames.ConstRef kn) (kind_of_constant kn) 
 
619
            xml_library_root
 
620
      | Some pftreestate ->
 
621
         (* It is a proof. Let's export it starting from the proof-tree *)
 
622
         (* I saved in the Pfedit.set_xml_cook_proof callback.          *)
 
623
        let fn = filename_of_path xml_library_root (Cic2acic.Constant kn) in
 
624
         show_pftreestate internal fn pftreestate 
 
625
          (Names.id_of_label (Names.con_label kn)) ;
 
626
         proof_to_export := None)
 
627
;;
 
628
 
 
629
let _ =
 
630
  Declare.set_xml_declare_inductive
 
631
   (function (isrecord,(sp,kn)) ->
 
632
      print false (Libnames.IndRef (kn,0)) (kind_of_inductive isrecord kn) 
 
633
        xml_library_root)
 
634
;;
 
635
 
 
636
let _ =
 
637
  Vernac.set_xml_start_library
 
638
   (function () ->
 
639
     Buffer.reset theory_buffer;
 
640
     theory_output_string "<?xml version=\"1.0\" encoding=\"latin1\"?>\n";
 
641
     theory_output_string ("<!DOCTYPE html [\n" ^
 
642
      "<!ENTITY % xhtml-lat1.ent    SYSTEM \"http://helm.cs.unibo.it/dtd/xhtml-lat1.ent\">\n" ^
 
643
      "<!ENTITY % xhtml-special.ent SYSTEM \"http://helm.cs.unibo.it/dtd/xhtml-special.ent\">\n" ^
 
644
      "<!ENTITY % xhtml-symbol.ent  SYSTEM \"http://helm.cs.unibo.it/dtd/xhtml-symbol.ent\">\n\n" ^
 
645
      "%xhtml-lat1.ent;\n" ^
 
646
      "%xhtml-special.ent;\n" ^
 
647
      "%xhtml-symbol.ent;\n" ^
 
648
      "]>\n\n");
 
649
     theory_output_string "<html xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:ht=\"http://www.cs.unibo.it/helm/namespaces/helm-theory\" xmlns:helm=\"http://www.cs.unibo.it/helm\">\n";
 
650
     theory_output_string "<head></head>\n<body>\n")
 
651
;;
 
652
 
 
653
let _ =
 
654
  Vernac.set_xml_end_library
 
655
   (function () ->
 
656
      theory_output_string "</body>\n</html>\n";
 
657
      let ofn = theory_filename xml_library_root in
 
658
       begin
 
659
        match ofn with
 
660
           None ->
 
661
             Buffer.output_buffer stdout theory_buffer ;
 
662
         | Some fn ->
 
663
            let ch = open_out (fn ^ ".v") in
 
664
             Buffer.output_buffer ch theory_buffer ;
 
665
             close_out ch
 
666
       end ;
 
667
       Option.iter 
 
668
        (fun fn ->
 
669
          let coqdoc = Filename.concat (Envars.coqbin ()) ("coqdoc" ^ Coq_config.exec_extension) in
 
670
          let options = " --html -s --body-only --no-index --latin1 --raw-comments" in
 
671
          let dir = Option.get xml_library_root in
 
672
          let command cmd =
 
673
           if Sys.command cmd <> 0 then
 
674
            Util.anomaly ("Error executing \"" ^ cmd ^ "\"")
 
675
          in
 
676
           command (coqdoc^options^" -d "^dir^" "^fn^".v");
 
677
           let dot = if fn.[0]='/' then "." else "" in
 
678
           command ("mv "^dir^"/"^dot^"*.html "^fn^".xml ");
 
679
           command ("rm "^fn^".v");
 
680
           print_string("\nWriting on file \"" ^ fn ^ ".xml\" was successful\n"))
 
681
       ofn)
 
682
;;
 
683
 
 
684
let _ = Lexer.set_xml_output_comment (theory_output_string ~do_not_quote:true) ;;
 
685
 
 
686
let uri_of_dirpath dir =
 
687
  "/" ^ String.concat "/" 
 
688
    (List.map Names.string_of_id (List.rev (Names.repr_dirpath dir)))
 
689
;;
 
690
 
 
691
let _ =
 
692
  Lib.set_xml_open_section
 
693
    (fun _ ->
 
694
      let s = "cic:" ^ uri_of_dirpath (Lib.cwd ()) in
 
695
      theory_output_string ("<ht:SECTION uri=\""^s^"\">"))
 
696
;;
 
697
 
 
698
let _ =
 
699
  Lib.set_xml_close_section
 
700
    (fun _ -> theory_output_string "</ht:SECTION>")
 
701
;;
 
702
 
 
703
let _ =
 
704
  Library.set_xml_require
 
705
    (fun d -> theory_output_string 
 
706
      (Printf.sprintf "<b>Require</b> <a helm:helm_link=\"href\" href=\"theory:%s.theory\">%s</a>.<br/>"
 
707
       (uri_of_dirpath d) (Names.string_of_dirpath d)))
 
708
;;