]> matita.cs.unibo.it Git - helm.git/blob - helm/software/components/content_pres/content2pres.ml
DOOMSDAY 1.0:
[helm.git] / helm / software / components / content_pres / content2pres.ml
1 (* Copyright (C) 2003-2005, HELM Team.
2  * 
3  * This file is part of HELM, an Hypertextual, Electronic
4  * Library of Mathematics, developed at the Computer Science
5  * Department, University of Bologna, Italy.
6  * 
7  * HELM is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  * 
12  * HELM is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with HELM; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
20  * MA  02111-1307, USA.
21  * 
22  * For details, see the HELM World-Wide-Web page,
23  * http://cs.unibo.it/helm/.
24  *)
25
26 (***************************************************************************)
27 (*                                                                         *)
28 (*                            PROJECT HELM                                 *)
29 (*                                                                         *)
30 (*                Andrea Asperti <asperti@cs.unibo.it>                     *)
31 (*                              17/06/2003                                 *)
32 (*                                                                         *)
33 (***************************************************************************)
34
35 (* $Id$ *)
36
37 module P = Mpresentation
38 module B = Box
39 module Con = Content
40
41 let p_mtr a b = Mpresentation.Mtr(a,b)
42 let p_mtd a b = Mpresentation.Mtd(a,b)
43 let p_mtable a b = Mpresentation.Mtable(a,b)
44 let p_mtext a b = Mpresentation.Mtext(a,b)
45 let p_mi a b = Mpresentation.Mi(a,b)
46 let p_mo a b = Mpresentation.Mo(a,b)
47 let p_mrow a b = Mpresentation.Mrow(a,b)
48 let p_mphantom a b = Mpresentation.Mphantom(a,b)
49
50 let rec split n l =
51   if n = 0 then [],l
52   else let l1,l2 = 
53     split (n-1) (List.tl l) in
54     (List.hd l)::l1,l2
55   
56 let get_xref = function
57   | `Declaration d  
58   | `Hypothesis d -> d.Con.dec_id
59   | `Proof p -> p.Con.proof_id
60   | `Definition d -> d.Con.def_id
61   | `Joint jo -> jo.Con.joint_id
62
63 let hv_attrs =
64   RenderingAttrs.spacing_attributes `BoxML
65   @ RenderingAttrs.indent_attributes `BoxML
66
67 let make_row items concl =
68   B.b_hv hv_attrs (items @ [ concl ])
69 (*   match concl with 
70       B.V _ -> |+ big! +|
71         B.b_v attrs [B.b_h [] items; B.b_indent concl]
72     | _ ->  |+ small +|
73         B.b_h attrs (items@[B.b_space; concl]) *)
74
75 let make_concl ?(attrs=[]) verb concl =
76   B.b_hv (hv_attrs @ attrs) [ B.b_kw verb; concl ]
77 (*   match concl with 
78       B.V _ -> |+ big! +|
79         B.b_v attrs [ B.b_kw verb; B.b_indent concl]
80     | _ ->  |+ small +|
81         B.b_h attrs [ B.b_kw verb; B.b_space; concl ] *)
82
83 let make_args_for_apply term2pres args =
84  let make_arg_for_apply is_first arg row = 
85   let res =
86    match arg with 
87       Con.Aux n -> assert false
88     | Con.Premise prem -> 
89         let name = 
90           (match prem.Con.premise_binder with
91              None -> "previous"
92            | Some s -> s) in
93         (B.b_object (P.Mi ([], name)))::row
94     | Con.Lemma lemma -> 
95         let lemma_attrs = [
96           Some "helm", "xref", lemma.Con.lemma_id;
97           Some "xlink", "href", lemma.Con.lemma_uri ]
98         in
99         (B.b_object (P.Mi(lemma_attrs,lemma.Con.lemma_name)))::row 
100     | Con.Term t -> 
101         if is_first then
102           (term2pres t)::row
103         else (B.b_object (P.Mi([],"?")))::row
104     | Con.ArgProof _ 
105     | Con.ArgMethod _ -> 
106         (B.b_object (P.Mi([],"?")))::row
107   in
108    if is_first then res else B.skip::res
109  in
110   match args with 
111     hd::tl -> 
112       make_arg_for_apply true hd 
113         (List.fold_right (make_arg_for_apply false) tl [])
114   | _ -> assert false
115
116 let get_name = function
117   | Some s -> s
118   | None -> "_"
119
120 let add_xref id = function
121   | B.Text (attrs, t) -> B.Text (((Some "helm", "xref", id) :: attrs), t)
122   | _ -> assert false (* TODO, add_xref is meaningful for all boxes *)
123
124 let rec justification term2pres p = 
125   if ((p.Con.proof_conclude.Con.conclude_method = "Exact") or
126      ((p.Con.proof_context = []) &
127       (p.Con.proof_apply_context = []) &
128       (p.Con.proof_conclude.Con.conclude_method = "Apply"))) then
129     let pres_args = 
130       make_args_for_apply term2pres p.Con.proof_conclude.Con.conclude_args in
131     B.H([],
132       (B.b_kw "by")::B.b_space::
133       B.Text([],"(")::pres_args@[B.Text([],")")]), None 
134   else (B.b_kw "by"),
135     Some (B.b_toggle [B.b_kw "proof";proof2pres true term2pres p])
136      
137 and proof2pres is_top_down term2pres p =
138   let rec proof2pres is_top_down p omit_dot =
139     let indent = 
140       let is_decl e = 
141         (match e with 
142            `Declaration _
143          | `Hypothesis _ -> true
144          | _ -> false) in
145       ((List.filter is_decl p.Con.proof_context) != []) in 
146     let omit_conclusion = (not indent) && (p.Con.proof_context != []) in
147     let concl = 
148       (match p.Con.proof_conclude.Con.conclude_conclusion with
149          None -> None
150        | Some t -> Some (term2pres t)) in
151     let body =
152         let presconclude = 
153           conclude2pres is_top_down p.Con.proof_conclude indent omit_conclusion
154            omit_dot in
155         let presacontext = 
156           acontext2pres
157            (p.Con.proof_conclude.Con.conclude_method = "BU_Conversion")
158            p.Con.proof_apply_context presconclude indent
159            (p.Con.proof_conclude.Con.conclude_method = "BU_Conversion")
160         in
161          context2pres p.Con.proof_context presacontext
162   in
163     match p.Con.proof_name with
164       None -> body
165     | Some name ->
166         let action = 
167          match concl with
168             None -> body
169           | Some ac ->
170              let concl =
171                make_concl ~attrs:[ Some "helm", "xref", p.Con.proof_id ]
172                  "proof of" ac in
173              B.b_toggle [ concl; body ]
174         in
175          B.indent action
176
177   and context2pres c continuation =
178     (* we generate a subtable for each context element, for selection
179        purposes 
180        The table generated by the head-element does not have an xref;
181        the whole context-proof is already selectable *)
182     match c with
183       [] -> continuation
184     | hd::tl -> 
185         let continuation' =
186           List.fold_right
187             (fun ce continuation ->
188               let xref = get_xref ce in
189               B.V([Some "helm", "xref", xref ],
190                 [B.H([Some "helm", "xref", "ce_"^xref],
191                      [ce2pres_in_proof_context_element ce]);
192                  continuation])) tl continuation in
193          let hd_xref= get_xref hd in
194          B.V([],
195              [B.H([Some "helm", "xref", "ce_"^hd_xref],
196                [ce2pres_in_proof_context_element hd]);
197              continuation'])
198         
199   and ce2pres_in_joint_context_element = function
200     | `Inductive _ -> assert false (* TODO *)
201     | (`Declaration _) as x -> ce2pres x
202     | (`Hypothesis _) as x  -> ce2pres x
203     | (`Proof _) as x       -> ce2pres x
204     | (`Definition _) as x  -> ce2pres x
205   
206   and ce2pres_in_proof_context_element = function 
207     | `Joint ho -> 
208       B.H ([],(List.map ce2pres_in_joint_context_element ho.Content.joint_defs))
209     | (`Declaration _) as x -> ce2pres x 
210     | (`Hypothesis _) as x  -> ce2pres x 
211     | (`Proof _) as x       -> ce2pres x
212     | (`Definition _) as x  -> ce2pres x 
213   
214   and ce2pres =
215     function 
216         `Declaration d -> 
217          let ty = term2pres d.Con.dec_type in
218          B.H ([],
219            [(B.b_kw "assume");
220             B.b_space;
221             B.Object ([], P.Mi([],get_name d.Con.dec_name));
222             B.Text([],":");
223             ty;
224             B.Text([],".")])
225       | `Hypothesis h ->
226           let ty = term2pres h.Con.dec_type in
227           B.H ([],
228             [(B.b_kw "suppose");
229              B.b_space;
230              ty;
231              B.b_space;
232              B.Text([],"(");
233              B.Object ([], P.Mi ([],get_name h.Con.dec_name));
234              B.Text([],")");
235              B.Text([],".")])
236       | `Proof p -> 
237            proof2pres false p false
238       | `Definition d -> 
239           let term = term2pres d.Con.def_term in
240           B.H ([],
241             [ B.b_kw "let"; B.b_space;
242               B.Object ([], P.Mi([],get_name d.Con.def_name));
243               B.Text([],Utf8Macro.unicode_of_tex "\\def");
244               term])
245
246   and acontext2pres is_top_down ac continuation indent in_bu_conversion =
247     List.fold_right
248       (fun p continuation ->
249         let hd = 
250           if indent then
251             B.indent (proof2pres is_top_down p in_bu_conversion)
252           else 
253             proof2pres is_top_down p in_bu_conversion
254         in
255          B.V([Some "helm","xref",p.Con.proof_id],
256            [B.H([Some "helm","xref","ace_"^p.Con.proof_id],[hd]);
257             continuation])) ac continuation 
258
259   and conclude2pres is_top_down conclude indent omit_conclusion omit_dot =
260     let tconclude_body = 
261       match conclude.Con.conclude_conclusion with
262         Some t (*when not omit_conclusion or
263          (* CSC: I ignore the omit_conclusion flag in this case.   *)
264          (* CSC: Is this the correct behaviour? In the stylesheets *)
265          (* CSC: we simply generated nothing (i.e. the output type *)
266          (* CSC: of the function should become an option.          *)
267          conclude.Con.conclude_method = "BU_Conversion" *) ->
268           let concl = term2pres t in 
269           if conclude.Con.conclude_method = "BU_Conversion" then
270             B.b_hv []
271              (make_concl "that is equivalent to" concl ::
272               if is_top_down then [B.b_space ; B.Text([],"done.")] else [])
273           else if conclude.Con.conclude_method = "FalseInd" then
274            (* false ind is in charge to add the conclusion *)
275            falseind conclude
276           else  
277             let conclude_body = conclude_aux conclude in
278             let ann_concl = 
279               if  conclude.Con.conclude_method = "Intros+LetTac"
280                || conclude.Con.conclude_method = "ByInduction"
281                || conclude.Con.conclude_method = "TD_Conversion"
282               then
283                B.Text([],"")
284               else if omit_conclusion then B.Text([],"done.")
285               else B.b_hv []
286                ((if not is_top_down || omit_dot then [make_concl "we proved" concl; B.Text([],if not is_top_down then "(previous)" else "")] else [B.Text([],"done")]) @ if not omit_dot then [B.Text([],".")] else [])
287             in
288              B.V ([], [conclude_body; ann_concl])
289       | _ -> conclude_aux conclude
290     in
291      if indent then 
292        B.indent (B.H ([Some "helm", "xref", conclude.Con.conclude_id],
293                      [tconclude_body]))
294      else 
295        B.H ([Some "helm", "xref", conclude.Con.conclude_id],[tconclude_body])
296
297   and conclude_aux conclude =
298     if conclude.Con.conclude_method = "TD_Conversion" then
299       let expected = 
300         (match conclude.Con.conclude_conclusion with 
301            None -> B.Text([],"NO EXPECTED!!!")
302          | Some c -> term2pres c) in
303       let subproof = 
304         (match conclude.Con.conclude_args with
305           [Con.ArgProof p] -> p
306          | _ -> assert false) in
307       let synth = 
308         (match subproof.Con.proof_conclude.Con.conclude_conclusion with
309            None -> B.Text([],"NO SYNTH!!!")
310          | Some c -> (term2pres c)) in
311       B.V 
312         ([],
313         [make_concl "we need to  prove" expected;
314          make_concl "or equivalently" synth;
315          B.Text([],".");
316          proof2pres true subproof false])
317     else if conclude.Con.conclude_method = "BU_Conversion" then
318       assert false
319     else if conclude.Con.conclude_method = "Exact" then
320       let arg = 
321         (match conclude.Con.conclude_args with 
322            [Con.Term t] -> term2pres t
323          | [Con.Premise p] -> 
324              (match p.Con.premise_binder with
325              | None -> assert false; (* unnamed hypothesis ??? *)
326              | Some s -> B.Text([],s))
327          | err -> assert false) in
328       (match conclude.Con.conclude_conclusion with 
329          None ->
330           B.b_h [] [B.b_kw "by"; B.b_space; arg]
331        | Some c -> let conclusion = term2pres c in
332           B.b_h [] [B.b_kw "by"; B.b_space; arg]
333        )
334     else if conclude.Con.conclude_method = "Intros+LetTac" then
335       (match conclude.Con.conclude_args with
336          [Con.ArgProof p] -> proof2pres true p false
337        | _ -> assert false)
338 (* OLD CODE 
339       let conclusion = 
340       (match conclude.Con.conclude_conclusion with 
341          None -> B.Text([],"NO Conclusion!!!")
342        | Some c -> term2pres c) in
343       (match conclude.Con.conclude_args with
344          [Con.ArgProof p] -> 
345            B.V 
346             ([None,"align","baseline 1"; None,"equalrows","false";
347               None,"columnalign","left"],
348               [B.H([],[B.Object([],proof2pres p false)]);
349                B.H([],[B.Object([],
350                 (make_concl "we proved 1" conclusion))])]);
351        | _ -> assert false)
352 *)
353     else if (conclude.Con.conclude_method = "Case") then
354       case conclude
355     else if (conclude.Con.conclude_method = "ByInduction") then
356       byinduction conclude
357     else if (conclude.Con.conclude_method = "Exists") then
358       exists conclude
359     else if (conclude.Con.conclude_method = "AndInd") then
360       andind conclude
361     else if (conclude.Con.conclude_method = "FalseInd") then
362       falseind conclude
363     else if (conclude.Con.conclude_method = "Rewrite") then
364       let justif1,justif2 = 
365         (match (List.nth conclude.Con.conclude_args 6) with
366            Con.ArgProof p -> justification term2pres p
367          | _ -> assert false) in
368       let term1 = 
369         (match List.nth conclude.Con.conclude_args 2 with
370            Con.Term t -> term2pres t
371          | _ -> assert false) in 
372       let term2 = 
373         (match List.nth conclude.Con.conclude_args 5 with
374            Con.Term t -> term2pres t
375          | _ -> assert false) in
376 (*
377       B.V ([], 
378          B.H ([],[
379           (B.b_kw "rewrite");
380           B.b_space; term1;
381           B.b_space; (B.b_kw "with");
382           B.b_space; term2;
383           B.b_space; justif1])::
384             match justif2 with None -> [] | Some j -> [B.indent j])
385 *) B.V([], [justif1 ; B.H([],[B.b_kw "we proved (" ; term2 ; B.b_kw "=" ; term1; B.b_kw ") (previous)."]); B.b_kw "by _"])
386     else if conclude.Con.conclude_method = "Eq_chain" then
387       let justification p =
388         let j1,j2 = justification term2pres p in
389           j1 :: B.b_space :: (match j2 with Some j -> [j] | None -> [])
390       in
391       let rec aux args =
392         match args with
393           | [] -> []
394           | (Con.ArgProof p)::(Con.Term t)::tl -> 
395               B.HOV(RenderingAttrs.indent_attributes `BoxML,([B.b_kw "=";B.b_space;term2pres t;B.b_space]@justification p))::(aux tl)
396           | _ -> assert false 
397       in
398       let hd = 
399         match List.hd conclude.Con.conclude_args with
400           | Con.Term t -> t 
401           | _ -> assert false 
402       in
403       B.HOV([],[term2pres hd; (* B.b_space; *)
404               B.V ([],aux (List.tl conclude.Con.conclude_args))])
405     else if conclude.Con.conclude_method = "Apply" then
406       let pres_args = 
407         make_args_for_apply term2pres conclude.Con.conclude_args in
408       B.H([],
409         (B.b_kw "by")::
410         B.b_space::
411         B.Text([],"(")::pres_args@[B.Text([],")")])
412     else 
413       B.V ([], [
414         B.b_kw ("Apply method" ^ conclude.Con.conclude_method ^ " to");
415         (B.indent (B.V ([], args2pres conclude.Con.conclude_args)))])
416
417   and args2pres l = List.map arg2pres l
418
419   and arg2pres =
420     function
421         Con.Aux n -> B.b_kw ("aux " ^ n)
422       | Con.Premise prem -> B.b_kw "premise"
423       | Con.Lemma lemma -> B.b_kw "lemma"
424       | Con.Term t -> term2pres t
425       | Con.ArgProof p -> proof2pres true p false
426       | Con.ArgMethod s -> B.b_kw "method"
427  
428    and case conclude =
429      let proof_conclusion = 
430        (match conclude.Con.conclude_conclusion with
431           None -> B.b_kw "No conclusion???"
432         | Some t -> term2pres t) in
433      let arg,args_for_cases = 
434        (match conclude.Con.conclude_args with
435            Con.Aux(_)::Con.Aux(_)::Con.Term(_)::arg::tl ->
436              arg,tl
437          | _ -> assert false) in
438      let case_on =
439        let case_arg = 
440          (match arg with
441             Con.Aux n -> B.b_kw "an aux???"
442            | Con.Premise prem ->
443               (match prem.Con.premise_binder with
444                  None -> B.b_kw "the previous result"
445                | Some n -> B.Object ([], P.Mi([],n)))
446            | Con.Lemma lemma -> B.Object ([], P.Mi([],lemma.Con.lemma_name))
447            | Con.Term t -> 
448                term2pres t
449            | Con.ArgProof p -> B.b_kw "a proof???"
450            | Con.ArgMethod s -> B.b_kw "a method???")
451       in
452         (make_concl "we proceed by cases on" case_arg) in
453      let to_prove =
454         (make_concl "to prove" proof_conclusion) in
455      B.V ([], case_on::to_prove::(make_cases args_for_cases))
456
457    and byinduction conclude =
458      let proof_conclusion = 
459        (match conclude.Con.conclude_conclusion with
460           None -> B.b_kw "No conclusion???"
461         | Some t -> term2pres t) in
462      let inductive_arg,args_for_cases = 
463        (match conclude.Con.conclude_args with
464            Con.Aux(n)::_::tl ->
465              let l1,l2 = split (int_of_string n) tl in
466              let last_pos = (List.length l2)-1 in
467              List.nth l2 last_pos,l1
468          | _ -> assert false) in
469      let induction_on =
470        let arg = 
471          (match inductive_arg with
472             Con.Aux n -> B.b_kw "an aux???"
473            | Con.Premise prem ->
474               (match prem.Con.premise_binder with
475                  None -> B.b_kw "the previous result"
476                | Some n -> B.Object ([], P.Mi([],n)))
477            | Con.Lemma lemma -> B.Object ([], P.Mi([],lemma.Con.lemma_name))
478            | Con.Term t -> 
479                term2pres t
480            | Con.ArgProof p -> B.b_kw "a proof???"
481            | Con.ArgMethod s -> B.b_kw "a method???") in
482         (make_concl "we proceed by induction on" arg) in
483      let to_prove =
484         (make_concl "to prove" proof_conclusion) in
485      B.V ([], induction_on::to_prove:: B.Text([],".")::(make_cases args_for_cases))
486
487     and make_cases l = List.map make_case l
488
489     and make_case =  
490       function 
491         Con.ArgProof p ->
492           let name =
493             (match p.Con.proof_name with
494                None -> B.b_kw "no name for case!!"
495              | Some n -> B.Object ([], P.Mi([],n))) in
496           let indhyps,args =
497              List.partition 
498                (function
499                    `Hypothesis h -> h.Con.dec_inductive
500                  | _ -> false) p.Con.proof_context in
501           let pattern_aux =
502              List.fold_right
503                (fun e p -> 
504                   let dec  = 
505                     (match e with 
506                        `Declaration h 
507                      | `Hypothesis h -> 
508                          let name = get_name h.Con.dec_name in
509                          [B.b_space;
510                           B.Text([],"(");
511                           B.Object ([], P.Mi ([],name));
512                           B.Text([],":");
513                           (term2pres h.Con.dec_type);
514                           B.Text([],")")]
515                      | _ -> assert false (*[B.Text ([],"???")]*)) in
516                   dec@p) args [] in
517           let pattern = 
518             B.H ([],
519                (B.b_kw "case"::B.b_space::name::pattern_aux)@
520                 [B.b_space;
521                  B.Text([], ".")]) in
522           let subconcl = 
523             (match p.Con.proof_conclude.Con.conclude_conclusion with
524                None -> B.b_kw "No conclusion!!!"
525              | Some t -> term2pres t) in
526           let asubconcl = B.indent (make_concl "the thesis becomes" subconcl) in
527           let induction_hypothesis = 
528             (match indhyps with
529               [] -> []
530             | _ -> 
531                let text = B.indent (B.b_kw "by induction hypothesis we know") in
532                let make_hyp =
533                  function 
534                    `Hypothesis h ->
535                      let name = 
536                        (match h.Con.dec_name with
537                           None -> "useless"
538                         | Some s -> s) in
539                      B.indent (B.H ([],
540                        [term2pres h.Con.dec_type;
541                         B.b_space;
542                         B.Text([],"(");
543                         B.Object ([], P.Mi ([],name));
544                         B.Text([],")");
545                         B.Text([],".")]))
546                    | _ -> assert false in
547                let hyps = List.map make_hyp indhyps in
548                text::hyps) in          
549           (* let acontext = 
550                acontext2pres_old p.Con.proof_apply_context true in *)
551           let body =
552            conclude2pres true p.Con.proof_conclude true true false in
553           let presacontext = 
554            let acontext_id =
555             match p.Con.proof_apply_context with
556                [] -> p.Con.proof_conclude.Con.conclude_id
557              | {Con.proof_id = id}::_ -> id
558            in
559             B.Action([None,"type","toggle"],
560               [ B.indent (add_xref acontext_id (B.b_kw "Proof"));
561                 acontext2pres
562                  (p.Con.proof_conclude.Con.conclude_method = "BU_Conversion")
563                  p.Con.proof_apply_context body true
564                  (p.Con.proof_conclude.Con.conclude_method = "BU_Conversion")
565               ]) in
566           B.V ([], pattern::induction_hypothesis@[asubconcl;B.Text([],".");presacontext])
567        | _ -> assert false 
568
569      and falseind conclude =
570        let proof_conclusion = 
571          (match conclude.Con.conclude_conclusion with
572             None -> B.b_kw "No conclusion???"
573           | Some t -> term2pres t) in
574        let case_arg = 
575          (match conclude.Con.conclude_args with
576              [Con.Aux(n);_;case_arg] -> case_arg
577            | _ -> assert false;
578              (* 
579              List.map (ContentPp.parg 0) conclude.Con.conclude_args;
580              assert false *)) in
581        let arg = 
582          (match case_arg with
583              Con.Aux n -> assert false
584            | Con.Premise prem ->
585               (match prem.Con.premise_binder with
586                  None -> [B.b_kw "Contradiction, hence"]
587                | Some n -> 
588                    [ B.Object ([],P.Mi([],n)); B.skip;
589                      B.b_kw "is contradictory, hence"])
590            | Con.Lemma lemma -> 
591                [ B.Object ([], P.Mi([],lemma.Con.lemma_name)); B.skip;
592                  B.b_kw "is contradictory, hence" ]
593            | _ -> assert false) in
594             (* let body = proof2pres {proof with Con.proof_context = tl} false in *)
595        make_row arg proof_conclusion
596
597      and andind conclude =
598        let proof,case_arg = 
599          (match conclude.Con.conclude_args with
600              [Con.Aux(n);_;Con.ArgProof proof;case_arg] -> proof,case_arg
601            | _ -> assert false;
602              (* 
603              List.map (ContentPp.parg 0) conclude.Con.conclude_args;
604              assert false *)) in
605        let arg = 
606          (match case_arg with
607              Con.Aux n -> assert false
608            | Con.Premise prem ->
609               (match prem.Con.premise_binder with
610                  None -> []
611                | Some n -> [(B.b_kw "by"); B.b_space; B.Object([], P.Mi([],n))])
612            | Con.Lemma lemma -> 
613                [(B.b_kw "by");B.skip;
614                 B.Object([], P.Mi([],lemma.Con.lemma_name))]
615            | _ -> assert false) in
616        match proof.Con.proof_context with
617          `Hypothesis hyp1::`Hypothesis hyp2::tl ->
618             let preshyp1 = 
619               B.H ([],
620                [B.Text([],"(");
621                 B.Object ([], P.Mi([],get_name hyp1.Con.dec_name));
622                 B.Text([],")");
623                 B.skip;
624                 term2pres hyp1.Con.dec_type]) in
625             let preshyp2 = 
626               B.H ([],
627                [B.Text([],"(");
628                 B.Object ([], P.Mi([],get_name hyp2.Con.dec_name));
629                 B.Text([],")");
630                 B.skip;
631                 term2pres hyp2.Con.dec_type]) in
632             (* let body = proof2pres {proof with Con.proof_context = tl} false in *)
633             let body= conclude2pres false proof.Con.proof_conclude false true false in
634             let presacontext = 
635               acontext2pres false proof.Con.proof_apply_context body false false
636             in
637             B.V 
638               ([],
639                [B.H ([],arg@[B.skip; B.b_kw "we have"]);
640                 preshyp1;
641                 B.b_kw "and";
642                 preshyp2;
643                 presacontext]);
644          | _ -> assert false
645
646      and exists conclude =
647        let proof = 
648          (match conclude.Con.conclude_args with
649              [Con.Aux(n);_;Con.ArgProof proof;_] -> proof
650            | _ -> assert false;
651              (* 
652              List.map (ContentPp.parg 0) conclude.Con.conclude_args;
653              assert false *)) in
654        match proof.Con.proof_context with
655            `Declaration decl::`Hypothesis hyp::tl
656          | `Hypothesis decl::`Hypothesis hyp::tl ->
657            let presdecl = 
658              B.H ([],
659                [(B.b_kw "let");
660                 B.skip;
661                 B.Object ([], P.Mi([],get_name decl.Con.dec_name));
662                 B.Text([],":"); term2pres decl.Con.dec_type]) in
663            let suchthat =
664              B.H ([],
665                [(B.b_kw "such that");
666                 B.skip;
667                 B.Text([],"(");
668                 B.Object ([], P.Mi([],get_name hyp.Con.dec_name));
669                 B.Text([],")");
670                 B.skip;
671                 term2pres hyp.Con.dec_type]) in
672             (* let body = proof2pres {proof with Con.proof_context = tl} false in *)
673             let body= conclude2pres false proof.Con.proof_conclude false true false in
674             let presacontext = 
675               acontext2pres false proof.Con.proof_apply_context body false false
676             in
677             B.V 
678               ([],
679                [presdecl;
680                 suchthat;
681                 presacontext]);
682          | _ -> assert false
683
684     in
685     proof2pres is_top_down p false
686
687 exception ToDo
688
689 let counter = ref 0
690
691 let conjecture2pres term2pres (id, n, context, ty) =
692  B.b_indent
693   (B.b_hv [Some "helm", "xref", id]
694      ((B.b_toggle [
695         B.b_h [] [B.b_text [] "{...}"; B.b_space];
696         B.b_hv [] (List.map
697           (function
698              | None ->
699                  B.b_h []
700                    [ B.b_object (p_mi [] "_") ;
701                      B.b_object (p_mo [] ":?") ;
702                      B.b_object (p_mi [] "_")]
703              | Some (`Declaration d)
704              | Some (`Hypothesis d) ->
705                  let { Content.dec_name =
706                      dec_name ; Content.dec_type = ty } = d
707                  in
708                    B.b_h []
709                      [ B.b_object
710                          (p_mi []
711                             (match dec_name with
712                                  None -> "_"
713                                | Some n -> n));
714                        B.b_text [] ":";
715                        term2pres ty ]
716              | Some (`Definition d) ->
717                  let
718                      { Content.def_name = def_name ;
719                        Content.def_term = bo } = d
720                  in
721                    B.b_h []
722                      [ B.b_object (p_mi []
723                                      (match def_name with
724                                           None -> "_"
725                                         | Some n -> n)) ;
726                        B.b_text [] (Utf8Macro.unicode_of_tex "\\Assign");
727                        term2pres bo]
728              | Some (`Proof p) ->
729                  let proof_name = p.Content.proof_name in
730                    B.b_h []
731                      [ B.b_object (p_mi []
732                                      (match proof_name with
733                                           None -> "_"
734                                         | Some n -> n)) ;
735                        B.b_text [] (Utf8Macro.unicode_of_tex "\\Assign");
736                        proof2pres true term2pres p])
737           (List.rev context)) ] ::
738          [ B.b_h []
739            [ B.b_text [] (Utf8Macro.unicode_of_tex "\\vdash");
740              B.b_object (p_mi [] (string_of_int n)) ;
741              B.b_text [] ":" ;
742              term2pres ty ]])))
743
744 let metasenv2pres term2pres = function
745   | None -> []
746   | Some metasenv' ->
747       (* Conjectures are in their own table to make *)
748       (* diffing the DOM trees easier.              *)
749       [B.b_v []
750         ((B.b_kw ("Conjectures:" ^
751             (let _ = incr counter; in (string_of_int !counter)))) ::
752          (List.map (conjecture2pres term2pres) metasenv'))]
753
754 let params2pres params =
755   let param2pres uri =
756     B.b_text [Some "xlink", "href", UriManager.string_of_uri uri]
757       (UriManager.name_of_uri uri)
758   in
759   let rec spatiate = function
760     | [] -> []
761     | hd :: [] -> [hd]
762     | hd :: tl -> hd :: B.b_text [] ", " :: spatiate tl
763   in
764   match params with
765   | [] -> []
766   | p ->
767       let params = spatiate (List.map param2pres p) in
768       [B.b_space;
769        B.b_h [] (B.b_text [] "[" :: params @ [ B.b_text [] "]" ])]
770
771 let recursion_kind2pres params kind =
772   let kind =
773     match kind with
774     | `Recursive _ -> "Recursive definition"
775     | `CoRecursive -> "CoRecursive definition"
776     | `Inductive _ -> "Inductive definition"
777     | `CoInductive _ -> "CoInductive definition"
778   in
779   B.b_h [] (B.b_kw kind :: params2pres params)
780
781 let inductive2pres term2pres ind =
782   let constructor2pres decl =
783     B.b_h [] [
784       B.b_text [] ("| " ^ get_name decl.Content.dec_name ^ ":");
785       B.b_space;
786       term2pres decl.Content.dec_type
787     ]
788   in
789   B.b_v []
790     (B.b_h [] [
791       B.b_kw (ind.Content.inductive_name ^ " of arity");
792       B.smallskip;
793       term2pres ind.Content.inductive_type ]
794     :: List.map constructor2pres ind.Content.inductive_constructors)
795
796 let joint_def2pres term2pres def =
797   match def with
798   | `Inductive ind -> inductive2pres term2pres ind
799   | _ -> assert false (* ZACK or raise ToDo? *)
800
801 let content2pres term2pres (id,params,metasenv,obj) =
802   match obj with
803   | `Def (Content.Const, thesis, `Proof p) ->
804       let name = get_name p.Content.proof_name in
805       B.b_v
806         [Some "helm","xref","id"]
807         ([ B.b_h [] (B.b_kw ("theorem " ^ name) :: params2pres params @ [B.b_kw ":"]);
808            B.indent (term2pres thesis) ; B.b_kw "." ] @
809          metasenv2pres term2pres metasenv @
810          [proof2pres true term2pres p ; B.b_kw "qed."])
811   | `Def (_, ty, `Definition body) ->
812       let name = get_name body.Content.def_name in
813       B.b_v
814         [Some "helm","xref","id"]
815         ([B.b_h []
816            (B.b_kw ("definition " ^ name) :: params2pres params @ [B.b_kw ":"]);
817           B.indent (term2pres ty)] @
818           metasenv2pres term2pres metasenv @
819           [B.b_kw ":=";
820            B.indent (term2pres body.Content.def_term);
821            B.b_kw "."])
822   | `Decl (_, `Declaration decl)
823   | `Decl (_, `Hypothesis decl) ->
824       let name = get_name decl.Content.dec_name in
825       B.b_v
826         [Some "helm","xref","id"]
827         ([B.b_h [] (B.b_kw ("Axiom " ^ name) :: params2pres params);
828           B.b_kw "Type:";
829           B.indent (term2pres decl.Content.dec_type)] @
830           metasenv2pres term2pres metasenv)
831   | `Joint joint ->
832       B.b_v []
833         (recursion_kind2pres params joint.Content.joint_kind
834         :: List.map (joint_def2pres term2pres) joint.Content.joint_defs)
835   | _ -> raise ToDo
836
837 let content2pres ~ids_to_inner_sorts =
838   content2pres
839     (fun ?(prec=90) annterm ->
840       let ast, ids_to_uris =
841         TermAcicContent.ast_of_acic ids_to_inner_sorts annterm
842       in
843        CicNotationPres.box_of_mpres
844         (CicNotationPres.render ids_to_uris ~prec
845           (TermContentPres.pp_ast ast)))