aboutsummaryrefslogtreecommitdiffhomepage
path: root/contrib/xml/xmlcommand.ml
blob: 1206892cf9d0847050b1e2d0eecdd288176e7cbe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
(******************************************************************************)
(*                                                                            *)
(*                               PROJECT HELM                                 *)
(*                                                                            *)
(*                     A tactic to print Coq objects in XML                   *)
(*                                                                            *)
(*                Claudio Sacerdoti Coen <sacerdot@cs.unibo.it>               *)
(*                                 02/12/1999                                 *)
(*                                                                            *)
(* This module defines the functions that implements the new commands         *)
(*                                                                            *)
(******************************************************************************)


(* CONFIGURATION PARAMETERS *)

let dtdname = "http://localhost:8081/getdtd?url=cic.dtd";;
let verbose = ref false;; (* always set to true during a "Print XML All" *)



exception ImpossiblePossible;;
type formal_parameters =
   Actual of string
 | Possible of string
;;


(* LOCAL MODULES *)

(* Next local module because I can't use the standard module Str in a tactic, *)
(* so I reimplement the part of it I need                                     *)
module Str =
 struct
  exception WrongTermSuffix of string;;

  (* substitute character c1 with c2 in string str *)
  let rec substitute str c1 c2 =
   try
    let pos = String.index str c1 in
     str.[pos] <- c2 ;
     substitute str c1 c2
   with
    Not_found -> str ;;

  (* change the suffix suf1 with suf2 in the string str *)
  let change_suffix str suf1 suf2 =
   let module S = String in
    let len  = S.length str
    and lens = S.length suf1 in
     if S.sub str (len - lens) lens = suf1 then
      (S.sub str 0 (len - lens)) ^ suf2
     else
      raise (WrongTermSuffix str) ;;
 end
;;

(* UTILITY FUNCTIONS *)

let print_if_verbose s = if !verbose then print_string s;;

let ext_of_tag =
 function
    "CONSTANT"        -> "con"
  | "MUTUALINDUCTIVE" -> "ind"
  | "VARIABLE"        -> "var"
  | _                 -> "err" (* uninteresting thing that won't be printed *)
;;

(*CSC: ORRENDO!!! MODIFICARE V7*)
let tag_of_sp sp =
 let module G = Global in
  try
   let _ = G.lookup_constant sp in "CONSTANT"
  with
   Not_found ->
    try
     let _ = G.lookup_mind sp in "MUTUALINDUCTIVE"
    with
     Not_found ->
      (* We could only hope it is a variable *)
      "VARIABLE"
;;

(* could_have_namesakes sp = true iff o is an object that could be cooked and *)
(* than that could exists in cooked form with the same name in a super        *)
(* section of the actual section                                              *)
let could_have_namesakes o sp =      (* namesake = omonimo in italian *)
 let module D = Declare in
  let tag = Libobject.object_tag o in
   match tag with
      "CONSTANT" ->
        (match D.constant_strength sp with
            D.DischargeAt _  -> false (* a local definition *)
          | D.NeverDischarge -> true  (* a non-local one    *)
        )
    | "VARIABLE"        -> false  (* variables are local, so no namesakes     *)
    | "MUTUALINDUCTIVE" -> true   (* mutual inductive types are never local   *)
    | _                 -> false  (* uninteresting thing that won't be printed*)
;;

(* uri_of_path sp is a broken (wrong) uri pointing to the object whose        *)
(* section path is sp                                                         *)
let uri_of_path sp =
 let ext_of_sp sp = ext_of_tag (tag_of_sp sp) in
  let module S = String in
   let str = Names.string_of_path sp in
    let uri = Str.substitute str '#' '/' in
     let uri' = "cic:" ^ uri in
      let uri'' = Str.change_suffix uri' ".cci" ("." ^ ext_of_sp sp) in
       uri''
;;

let string_of_sort =
 let module T = Term in
  function
     T.Prop(T.Pos)  -> "Set"
   | T.Prop(T.Null) -> "Prop"
   | T.Type(_)      -> "Type"
;;

let string_of_name =
 let module N = Names in
  function
     N.Name id -> N.string_of_id id
   | _         -> Util.anomaly "this should not happen"
;;

(* A SIMPLE DATA STRUCTURE AND SOME FUNCTIONS TO MANAGE THE CURRENT *)
(* ENVIRONMENT (= [l1, ..., ln] WHERE li IS THE LIST OF VARIABLES   *)
(* DECLARED IN THE i-th SUPER-SECTION OF THE CURRENT SECTION        *)

(*CSC: commento sbagliato ed obsoleto *)
(* list of variables availables in the actual section *)
let pvars = ref [];;

let pvars_to_string pvars =
 let rec aux =
  function
     [] -> (0, "")
   | he::tl -> 
      let (n,s) = aux tl in
       (n + 1,
        string_of_int n ^ ": " ^ (String.concat " ") (List.rev he) ^
         match s with "" -> "" | _ -> " " ^ s 
       )
 in
  snd (aux (List.rev pvars))
;;

exception XmlCommandInternalError;;

let add_to_pvars v =
 match !pvars with
    []       -> raise XmlCommandInternalError
  | (he::tl) -> pvars := (v::he)::tl
;;

let get_depth_of_var v =
 let rec aux n =
  function
     [] -> None
   | (he::tl) -> if List.mem v he then Some n else aux (n + 1) tl
 in
  aux 0 !pvars
;;

(* FUNCTIONS TO CREATE IDENTIFIERS *)

(* seed to create the next identifier *)
let next_id = ref 0;;

(* reset_id () reset the identifier seed to 0 *)
let reset_id () =
 next_id := 0
;;

(* get_next_id () returns fresh identifier *)
let get_next_id () =
 let res = 
  "i" ^ string_of_int !next_id
 in
  incr next_id ;
  res
;;

(* FUNCTION TO PRINT A SINGLE TERM OF CIC *)

(* print_term t l where t is a term of Cic returns a stream of XML tokens *)
(* suitable to be printed via the pretty printer Xml.pp. l is the list of *)
(* bound names                                                            *)
let print_term l csr =
 let module N = Names in
 let module T = Term in
 let module X = Xml in
  let rec names_to_ids =
   function
      [] -> []
    | (N.Name id)::l -> id::(names_to_ids l)
    | _ -> names_to_ids l
  in
  let rec term_display l cstr =
   (* kind_of_term helps doing pattern matching hiding the lower level of *)
   (* coq coding of terms (the one of the logical framework)              *)
   match T.kind_of_term cstr with
     T.IsRel n  ->
      (match List.nth l (n - 1) with
          N.Name id ->
            X.xml_empty "REL"
             ["value",(string_of_int n) ;
              "binder",(N.string_of_id id) ;
              "id", get_next_id ()]
        | N.Anonymous -> raise XmlCommandInternalError
     )
   | T.IsVar id ->
      let depth =
       match get_depth_of_var (N.string_of_id id) with
          None -> "?" (* when printing via Show XML Proof or Print XML id *)
                      (* no infos about variables uri are known           *)
        | Some n -> string_of_int n
      in
       X.xml_empty "VAR"
        ["relUri",depth ^ "," ^ (N.string_of_id id) ;
         "id", get_next_id ()]
   | T.IsMeta n ->
      X.xml_empty "META" ["no",(string_of_int n) ; "id", get_next_id ()]
   | T.IsSort s ->
      X.xml_empty "SORT" ["value",(string_of_sort s) ; "id", get_next_id ()]
   | T.IsCast (t1,t2) ->
      X.xml_nempty "CAST" ["id", get_next_id ()]
       [< X.xml_nempty "term" [] (term_display l t1) ;
          X.xml_nempty "type" [] (term_display l t2)
       >]
   | T.IsLetIn (nid,s,_,d)->
      let nid' = N.next_name_away nid (names_to_ids l) in
       X.xml_nempty "LETIN" ["id", get_next_id ()]
        [< X.xml_nempty "term" [] (term_display l s) ;
           X.xml_nempty "target" ["binder",(N.string_of_id nid')]
            (term_display ((N.Name nid')::l) d)
        >]
   | T.IsProd (N.Name _ as nid, t1, t2) ->
      let nid' = N.next_name_away nid (names_to_ids l) in
       X.xml_nempty "PROD" ["id", get_next_id ()]
        [< X.xml_nempty "source" [] (term_display l t1) ;
           X.xml_nempty "target" ["binder",(N.string_of_id nid')]
            (term_display ((N.Name nid')::l) t2)
        >]
   | T.IsProd (N.Anonymous as nid, t1, t2) ->
      X.xml_nempty "PROD" ["id", get_next_id ()]
       [< X.xml_nempty "source" [] (term_display l t1) ;
          X.xml_nempty "target" [] (term_display (nid::l) t2)
       >]
   | T.IsLambda (N.Name _ as nid, t1, t2) ->
      let nid' = N.next_name_away nid (names_to_ids l) in
       X.xml_nempty "LAMBDA" ["id", get_next_id ()]
        [< X.xml_nempty "source" [] (term_display l t1) ;
           X.xml_nempty "target" ["binder",(N.string_of_id nid')]
            (term_display ((N.Name nid')::l) t2)
        >]
   | T.IsLambda (N.Anonymous as nid, t1, t2) ->
      X.xml_nempty "LAMBDA" ["id", get_next_id ()]
       [< X.xml_nempty "source" [] (term_display l t1) ;
          X.xml_nempty "target" [] (term_display (nid::l) t2) >]
   | T.IsApp (h,t) ->
      X.xml_nempty "APPLY" ["id", get_next_id ()]
       [< (term_display l h) ;
          (Array.fold_right (fun x i -> [< (term_display l x) ; i >]) t [<>])
       >]
   | T.IsConst (sp,_) ->
      X.xml_empty "CONST" ["uri",(uri_of_path sp) ; "id", get_next_id ()]
   | T.IsMutInd ((sp,i),_) ->
      X.xml_empty "MUTIND"
       ["uri",(uri_of_path sp) ;
        "noType",(string_of_int i) ;
        "id", get_next_id ()]
   | T.IsMutConstruct (((sp,i),j),_) ->
      X.xml_empty "MUTCONSTRUCT"
       ["uri",(uri_of_path sp) ;
        "noType",(string_of_int i) ;
        "noConstr",(string_of_int j) ;
        "id", get_next_id ()]
   | T.IsMutCase ((_,((sp,i),_,_,_,_)),ty,term,a) ->
      let (uri, typeno) = (uri_of_path sp),i in
       X.xml_nempty "MUTCASE"
        ["uriType",uri ; "noType",(string_of_int typeno) ; "id",get_next_id ()]
        [< X.xml_nempty "patternsType" [] [< (term_display l ty) >] ;
	   X.xml_nempty "inductiveTerm" [] [< (term_display l term) >] ;
	   Array.fold_right
            (fun x i ->
              [< X.xml_nempty "pattern" [] [< term_display l x >] ; i>]
            ) a [<>]
        >]
   | T.IsFix ((ai,i),(t,f,b)) ->
      X.xml_nempty "FIX" ["noFun", (string_of_int i) ; "id",get_next_id ()]
       [< Array.fold_right
           (fun (fi,ti,bi,ai) i ->
             [< X.xml_nempty "FixFunction"
                 ["name", (string_of_name fi); "recIndex", (string_of_int ai)]
	         [< X.xml_nempty "type" [] [< term_display l ti >] ;
	            X.xml_nempty "body" [] [< term_display ((List.rev f)@l) bi >]
	         >] ;
                i
             >]
           )
	   (Array.mapi (fun j x -> (x,t.(j),b.(j),ai.(j)) ) (Array.of_list f) )
           [<>]
       >]
   | T.IsCoFix (i,(t,f,b)) ->
      X.xml_nempty "COFIX" ["noFun", (string_of_int i) ; "id",get_next_id ()]
       [< Array.fold_right
           (fun (fi,ti,bi) i ->
            [< X.xml_nempty "CofixFunction" ["name", (string_of_name fi)]
	        [< X.xml_nempty "type" [] [< term_display l ti >] ;
	           X.xml_nempty "body" [] [< term_display ((List.rev f)@l) bi >]
	        >] ;
               i
            >]
	   )
	   (Array.mapi (fun j x -> (x,t.(j),b.(j)) ) (Array.of_list f) ) [<>]
       >]
   | T.IsXtra _ ->
      Util.anomaly "Xtra node in a term!!!"
   | T.IsEvar _ ->
      Util.anomaly "Evar node in a term!!!"
  in
    (*CSC: ad l vanno andrebbero aggiunti i nomi da non *)
    (*CSC: mascherare (costanti? variabili?)            *)
    term_display l csr
;;

(* FUNCTIONS TO PRINT A SINGLE OBJECT OF COQ *)

(* print_current_proof term type id conjectures                            *)
(*  where term        is the term of the proof in progress p               *)
(*  and   type        is the type of p                                     *)
(*  and   id          is the identifier (name) of p                        *)
(*  and   conjectures is the list of conjectures (cic terms)               *)
(* returns a stream of XML tokens suitable to be pretty printed via Xml.pp *)
let print_current_proof c typ id mv =
 let module X = Xml in
  reset_id () ;
  [< X.xml_cdata "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n" ;
     X.xml_cdata ("<!DOCTYPE CurrentProof SYSTEM \"" ^ dtdname ^ "\">\n\n") ;
     X.xml_nempty "CurrentProof" ["name",id ; "id", get_next_id ()]
       [< List.fold_right
           (fun (j,t) i ->
             [< X.xml_nempty "Conjecture" ["no",(string_of_int j)]
                 [< print_term [] t >] ; i >])
           mv [<>] ;
          X.xml_nempty "body" [] [< print_term [] c >] ;
          X.xml_nempty "type"  [] [< print_term [] typ >]
       >]
  >]
;;

(* print_axiom id type params                                              *)
(*  where type        is the type of an axiom a                            *)
(*  and   id          is the identifier (name) of a                        *)
(*  and   params      is the list of formal params for a                   *)
(* returns a stream of XML tokens suitable to be pretty printed via Xml.pp *)
let print_axiom id typ fv =
 let module X = Xml in
 let module N = Names in
  reset_id () ;
  [< X.xml_cdata "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n" ;
     X.xml_cdata ("<!DOCTYPE Axiom SYSTEM \"" ^ dtdname ^ "\">\n\n") ;
     X.xml_nempty "Axiom"
      (["name",(N.string_of_id id) ; "id", get_next_id ()] @
       match fv with
          Possible _ -> raise ImpossiblePossible
        | Actual fv' -> ["params",fv']
      ) [< X.xml_nempty "type" [] (print_term [] typ) >]
  >]
;;

(* print_definition id term type params                                    *)
(*  where id          is the identifier (name) of a definition d           *)
(*  and   term        is the term (body) of d                              *)
(*  and   type        is the type of d                                     *)
(*  and   params      is the list of formal params for d                   *)
(* returns a stream of XML tokens suitable to be pretty printed via Xml.pp *)
let print_definition id c typ fv =
 let module X = Xml in
 let module N = Names in
  reset_id () ;
  [< X.xml_cdata "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n" ;
     X.xml_cdata ("<!DOCTYPE Definition SYSTEM \"" ^ dtdname ^ "\">\n\n") ;
     X.xml_nempty "Definition"
      (["name",(N.string_of_id id) ; "id", get_next_id ()] @
       match fv with
          Possible fv' -> ["params",fv' ; "paramMode","POSSIBLE"]
        | Actual fv' -> ["params",fv'])
      [< X.xml_nempty "body" [] (print_term [] c) ;
         X.xml_nempty "type"  [] (print_term [] typ) >]
  >]
;;

(* print_variable id type                                                  *)
(*  where id          is the identifier (name) of a variable v             *)
(*  and   type        is the type of v                                     *)
(* returns a stream of XML tokens suitable to be pretty printed via Xml.pp *)
let print_variable id typ =
 let module X = Xml in
 let module N = Names in
  reset_id () ;
  [< X.xml_cdata "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n" ;
     X.xml_cdata ("<!DOCTYPE Variable SYSTEM \"" ^ dtdname ^ "\">\n\n") ;
     X.xml_nempty "Variable" ["name",(N.string_of_id id) ; "id", get_next_id ()]
      (X.xml_nempty "type" [] (print_term [] typ))
  >]
;;

(* print_mutual_inductive_packet p                                           *)
(*  where p is a mutual inductive packet (an inductive definition in a block *)
(*          of mutual inductive definitions)                                 *)
(* returns a stream of XML tokens suitable to be pretty printed via Xml.pp   *)
(* Used only by print_mutual_inductive                                       *)
let print_mutual_inductive_packet names p =
 let module D = Declarations in
 let module N = Names in
 let module T = Term in
 let module X = Xml in
  let {D.mind_consnames=consnames ;
       D.mind_typename=typename ;
       D.mind_nf_lc=lc ;
       D.mind_nf_arity=arity ;
       D.mind_finite=finite} = p
  in
   [< X.xml_nempty "InductiveType"
       ["name",(N.string_of_id typename) ;
        "inductive",(string_of_bool finite)
       ]
       [<
          X.xml_nempty "arity" [] (print_term [] (T.body_of_type arity)) ;
          (Array.fold_right
           (fun (name,lc) i ->
             [< X.xml_nempty "Constructor" ["name",(N.string_of_id name)]
                 (print_term names lc) ;
                i
             >])
	   (Array.mapi (fun j x -> (x,T.body_of_type lc.(j)) ) consnames )
           [<>]
          )
       >]
   >]
;;

(* print_mutual_inductive packs params nparams                             *)
(*  where packs       is the list of inductive definitions in the block of *)
(*                    mutual inductive definitions b                       *)
(*  and   params      is the list of formal params for b                   *)
(*  and   nparams     is the number of "parameters" in the arity of the    *)
(*                    mutual inductive types                               *)
(* returns a stream of XML tokens suitable to be pretty printed via Xml.pp *)
let print_mutual_inductive packs fv nparams =
 let module D = Declarations in
 let module X = Xml in
 let module N = Names in
  let names =
   List.map
    (fun p -> let {D.mind_typename=typename} = p in N.Name(typename))
    (Array.to_list packs)
  in
   reset_id () ;
   [< X.xml_cdata "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n" ;
      X.xml_cdata ("<!DOCTYPE InductiveDefinition SYSTEM \"" ^
       dtdname ^ "\">\n\n") ;
      X.xml_nempty "InductiveDefinition"
       (["noParams",string_of_int nparams ; "id",get_next_id ()] @
        (match fv with
            Possible fv' -> ["params",fv' ; "paramMode","POSSIBLE"]
          | Actual fv' -> ["params",fv']))
       [< (Array.fold_right
            (fun x i -> [< print_mutual_inductive_packet names x ; i >])
            packs
            [< >]
          )
       >]
   >]
;;

(* print id dest                                                          *)
(*  where id   is the identifier (name) of a definition/theorem or of an  *)
(*             inductive definition                                       *)
(*  and   dest is either None (for stdout) or (Some filename)             *)
(* pretty prints via Xml.pp the object whose identifier is id on dest     *)
(* Note: it is printed only (and directly) the most cooked available      *)
(*       form of the definition (all the parameters are                   *)
(*       lambda-abstracted, but the object can still refer to variables)  *)
let print id fn =
 let module D = Declarations in
 let module G = Global in
 let module N = Names in
 let module T = Term in
 let module X = Xml in
  let str = N.string_of_id id in
  let sp = Nametab.sp_of_id N.CCI id in
  let pp_cmds =
   begin
    try
     let {D.const_body=val0 ; D.const_type = typ} = G.lookup_constant sp in
     let typ = T.body_of_type typ in
      begin
       match val0 with
          None -> print_axiom id typ (Actual "")
        | Some lcvr ->
           match !lcvr with
              D.Cooked c -> print_definition id c typ (Actual "")
            | D.Recipe _ ->
               print_string " COOKING THE RECIPE\n" ;
               ignore (D.cook_constant lcvr) ;
               let {D.const_body=val0 ; D.const_type = typ} =
                G.lookup_constant sp in
               let typ = T.body_of_type typ in
                begin
                 match val0 with
                   Some {contents= D.Cooked c} ->
                    print_definition id c typ (Actual "")
                 | _ -> Util.error "COOKING FAILED"
                end
          end
    with
     Not_found ->
      try
       let {D.mind_packets=packs ; D.mind_nparams=nparams} =
        G.lookup_mind sp
       in
        print_mutual_inductive packs (Actual "") nparams
      with
       Not_found ->
        try
         let (_,typ) = G.lookup_named id in
          print_variable id (T.body_of_type typ)
        with
         Not_found -> Util.anomaly ("print: this should not happen")
   end
  in
   Xml.pp pp_cmds fn
;;
 
(* show dest                                                  *)
(*  where dest is either None (for stdout) or (Some filename) *)
(* pretty prints via Xml.pp the proof in progress on dest     *)
let show fn =
(*
 let pftst = Pfedit.get_pftreestate () in
 let id = Pfedit.get_proof () in
 let pf = Tacmach.proof_of_pftreestate pftst in
 let typ = (Proof_trees.goal_of_proof pf).Evd.concl in
 (*CSC: ntrefiner copied verbatim from natural, used, but _not_ understood *)
 let val0, mv = Ntrefiner.nt_extract_open_proof (Vartab.initial_sign ()) pf in
 let mv_t = List.map (function i, (t, _) -> i,t) mv in
  Xml.pp (print_current_proof val0 typ id mv_t) fn
*) ()
;;

(* FUNCTIONS TO PRINT AN ENTIRE SECTION OF COQ *)

(* list of (name, uncooked sp, most cooked sp, uncooked leaf object,  *)
(*          list of possible variables, directory name)               *)
(* used to collect informations on the uncooked and most cooked forms *)
(* of objects that could be cooked (have namesakes)                   *)
let toprint = ref [];;

(* makes a filename from a directory name, a section path and an extension *)
let mkfilename dn sp ext =
 let rec join_dirs cwd =
   function
      [] -> ""
    | he::tail ->
       let newcwd = cwd ^ "/" ^ he in
        (try
          Unix.mkdir newcwd 0o775
         with _ -> () (* Let's ignore the errors on mkdir *)
        ) ;
        he ^ "/" ^ join_dirs newcwd tail
 in
  let module N = Names in
   match dn with
      None         -> None
    | Some basedir ->
       let (dirs, filename, _) = N.repr_path sp in
        let dirs = List.rev dirs in (* misteries of Coq *)
         Some (basedir ^ "/" ^ join_dirs basedir dirs ^
               N.string_of_id filename ^ "." ^ ext ^ ".xml")
;;

(* Next exception is used only inside print_object *)
exception Uninteresting;;

(* print_object leaf_object id section_path directory_name formal_vars      *)
(*  where leaf_object    is a leaf object                                   *)
(*  and   id             is the identifier (name) of the definition/theorem *)
(*                       or of the inductive definition o                   *)
(*  and   section_path   is the section path of o                           *)
(*  and   directory_name is the base directory in which putting the print   *)
(*  and   formal_vars    is the list of parameters (variables) of o         *)
(* pretty prints via Xml.pp the object o in the right directory deduced     *)
(* from directory_name and section_path                                     *)
(* Note: it is printed only the uncooked available form of the object plus  *)
(*       the list of parameters of the object deduced from it's most cooked *)
(*       form                                                               *)
let print_object o id sp dn fv =
 let module D = Declarations in
 let module G = Global in
 let module N = Names in
 let module T = Term in
 let module X = Xml in
  let lobj = o in
  let tag = Libobject.object_tag lobj in
  let pp_cmds () =
   match tag with
      "CONSTANT" ->
         (*CSC: QUI CI SONO ANCHE LE VARIABILI, CREDO, CHIAMATE const_hyps *)
         let {D.const_body=val0 ; D.const_type = typ} = G.lookup_constant sp in
         let typ = T.body_of_type typ in
          begin
           match val0 with
              None -> print_axiom id typ fv
            | Some lcvr ->
               match !lcvr with
                  D.Cooked c -> print_definition id c typ fv
                | D.Recipe _ -> Util.anomaly "trying to print a recipe"
          end
    | "MUTUALINDUCTIVE" ->
         (*CSC: QUI CI SONO ANCHE LE VARIABILI, CREDO, CHIAMATE mind_hyps *)
         let {D.mind_packets=packs ; D.mind_nparams=nparams} =
          G.lookup_mind sp
         in
           print_mutual_inductive packs fv nparams
    | "VARIABLE" ->
        (*CHE COSA E' IL PRIMO ARGOMENTO?*)
        let (_,typ) = G.lookup_named id in
         add_to_pvars (N.string_of_id id) ;
         print_variable id (T.body_of_type typ)
    | "CLASS"
    | "COERCION"
    | _ -> raise Uninteresting
  and fileext = ext_of_tag tag
  in
   try
    Xml.pp (pp_cmds ()) (mkfilename dn sp fileext)
   with
    Uninteresting -> ()
;;

(* print_library_segment state bprintleaf directory_name                      *)
(*  where state          is a list of (section-path, node)                    *)
(*  and   bprintleaf     is true iff the leaf objects should be printed       *)
(*  and   directory_name is the name of the base directory in which to print  *)
(*                       the files                                            *)
(* print via print_node all the nodes (leafs excluded if bprintleaf is false) *)(* in state                                                                   *)
let rec print_library_segment state bprintleaf dn =
  List.iter
   (function (sp, node) ->
     print_if_verbose (Names.string_of_path sp ^ "\n") ;
     print_node node (Names.basename sp) sp bprintleaf dn ;
     print_if_verbose "\n"
   ) state
(* print_node node id section_path bprintleaf directory_name             *)
(* prints a single node (and all it's subnodes via print_library_segment *)
and print_node n id sp bprintleaf dn =
 let module L = Lib in
  match n with
     L.Leaf o ->
      print_if_verbose "LEAF\n" ;
      if bprintleaf then
       begin
        let to_print =
         try
          let _ =
           List.find (function (x,_,_,_,_,_) -> x=id) !toprint
          in
           false
         with Not_found -> true
        in
         if to_print then
          (* this is an uncooked term or a local (with no namesakes) term *)
          begin
           if could_have_namesakes o sp then
            (* this is an uncooked term *)
            toprint := (id,sp,sp,o,!pvars,dn)::!toprint
           else
            (* this is a local term *)
            print_object o id sp dn (Possible (pvars_to_string !pvars)) ;
            print_if_verbose ("OK, stampo " ^ Names.string_of_id id ^ "\n")
          end
         else
          (* update the least cooked sp *)
          toprint :=
           List.map
            (function
               (id',usp,_,uo,pv,dn) when id' = id -> (id,usp,sp,uo,pv,dn)
             | t -> t
            ) !toprint
       end
   | L.OpenedSection s -> print_if_verbose ("OpenDir " ^ s ^ "\n")
   | L.ClosedSection (s,state) ->
      print_if_verbose("ClosedDir " ^ s ^ "\n") ;
      if bprintleaf then
       begin
        (* open a new scope *)
        pvars := []::!pvars ;
        print_library_segment state bprintleaf dn ;
        (* close the scope *)
        match !pvars with
           [] -> raise XmlCommandInternalError
         | he::tl -> pvars := tl
       end ;
      print_if_verbose "/ClosedDir\n"
   | L.Module s ->
      print_if_verbose ("Module " ^ s ^ "\n")
   | L.FrozenState _ ->
      print_if_verbose ("FrozenState\n")
;;

(* print_closed_section module_name node directory_name                      *)
(*  where module_name is the name of a module                                *)
(*  and   node is the library segment of the module                          *)
(*  and   directory_name is the base directory in which to put the xml files *)
(* prints all the leaf objects of the tree rooted in node using              *)
(* print_library_segment on all its sons                                     *)
let print_closed_section s ls dn =
 let module L = Lib in
 let module C = Cooking in
  toprint := [] ;
  (*CSC: this should always be empty yet! But just to be sure... :-) *)
  pvars := [] ;
  print_if_verbose ("Module " ^ s ^ ":\n") ;
  print_library_segment ls true dn ;
  print_if_verbose "\nNow saving cooking information: " ;
  List.iter
   (function
      (id,usp,csp,uo,pv,dn) ->
       print_if_verbose ("\nCooked=" ^ (Names.string_of_path csp) ^
        "\tUncooked=" ^ (Names.string_of_path usp)) ;
       let formal_vars = C.add_cooking_information csp pv in
        pvars := pv ;
        (*CSC Actual was Some *)
        print_object uo id usp dn (Actual formal_vars)
   ) !toprint ;
  print_if_verbose "\n/Module\n" ;
;;

(* printModule identifier directory_name                                     *)
(*  where identifier     is the name of a module (section) d                 *)
(*  and   directory_name is the directory in which to root all the xml files *)
(* prints all the xml files and directories corresponding to the subsections *)
(* and terms of the module d                                                 *)
(* Note: the terms are printed in their uncooked form plus the informations  *)
(* on the parameters of their most cooked form                               *)
let printModule id dn =
 let module L = Library in
 let module N = Names in
 let module X = Xml in
  let str = N.string_of_id id in 
  let sp = Lib.make_path id N.OBJ in
  let ls = L.module_segment (Some str) in
   print_if_verbose ("MODULE_BEGIN " ^ str ^ " " ^ N.string_of_path sp ^ " " ^
    L.module_filename str ^ "\n") ;
   print_closed_section str ls dn ;
   print_if_verbose ("MODULE_END " ^ str ^ " " ^ N.string_of_path sp ^ " " ^
    L.module_filename str ^ "\n")
;;

(* print All () prints what is the structure of the current environment of *)
(* Coq. No terms are printed. Useful only for debugging                    *)
let printAll () =
 let state = Library.module_segment None in
  let oldverbose = !verbose in
   verbose := true ;
   print_library_segment state false None ;
   let ml = Library.loaded_modules () in
    List.iter (function i -> printModule (Names.id_of_string i) None) ml ;
    verbose := oldverbose
;;