]> matita.cs.unibo.it Git - helm.git/blob - helm/ocaml/cic_omdoc/cic2content.ml
- added rendering of constants/variable with/without body
[helm.git] / helm / ocaml / cic_omdoc / cic2content.ml
1 (* Copyright (C) 2000, 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 (*                             16/6/2003                                   *)
32 (*                                                                        *)
33 (**************************************************************************)
34
35 let object_prefix = "obj:";;
36 let declaration_prefix = "decl:";;
37 let definition_prefix = "def:";;
38 let inductive_prefix = "ind:";;
39 let joint_prefix = "joint:";;
40 let proof_prefix = "proof:";;
41 let conclude_prefix = "concl:";;
42 let premise_prefix = "prem:";;
43 let lemma_prefix = "lemma:";;
44
45 (* e se mettessi la conversione di BY nell'apply_context ? *)
46 (* sarebbe carino avere l'invariante che la proof2pres
47 generasse sempre prove con contesto vuoto *)
48  
49 let gen_id prefix seed =
50  let res = prefix ^ string_of_int !seed in
51   incr seed ;
52   res
53 ;;
54
55 let name_of = function
56     Cic.Anonymous -> None
57   | Cic.Name b -> Some b;;
58  
59 exception Not_a_proof;;
60 exception NotImplemented;;
61 exception NotApplicable;;
62    
63 (* we do not care for positivity, here, that in any case is enforced by
64    well typing. Just a brutal search *)
65
66 let rec occur uri = 
67   let module C = Cic in
68   function
69       C.Rel _ -> false
70     | C.Var _ -> false
71     | C.Meta _ -> false
72     | C.Sort _ -> false
73     | C.Implicit _ -> assert false
74     | C.Prod (_,s,t) -> (occur uri s) or (occur uri t)
75     | C.Cast (te,ty) -> (occur uri te)
76     | C.Lambda (_,s,t) -> (occur uri s) or (occur uri t) (* or false ?? *)
77     | C.LetIn (_,s,t) -> (occur uri s) or (occur uri t)
78     | C.Appl l -> 
79         List.fold_left 
80           (fun b a -> 
81              if b then b  
82              else (occur uri a)) false l
83     | C.Const (_,_) -> false
84     | C.MutInd (uri1,_,_) -> if uri = uri1 then true else false
85     | C.MutConstruct (_,_,_,_) -> false
86     | C.MutCase _ -> false (* presuming too much?? *)
87     | C.Fix _ -> false (* presuming too much?? *)
88     | C.CoFix (_,_) -> false (* presuming too much?? *)
89 ;;
90
91 let get_id = 
92   let module C = Cic in
93   function
94       C.ARel (id,_,_,_) -> id
95     | C.AVar (id,_,_) -> id
96     | C.AMeta (id,_,_) -> id
97     | C.ASort (id,_) -> id
98     | C.AImplicit _ -> raise NotImplemented
99     | C.AProd (id,_,_,_) -> id
100     | C.ACast (id,_,_) -> id
101     | C.ALambda (id,_,_,_) -> id
102     | C.ALetIn (id,_,_,_) -> id
103     | C.AAppl (id,_) -> id
104     | C.AConst (id,_,_) -> id
105     | C.AMutInd (id,_,_,_) -> id
106     | C.AMutConstruct (id,_,_,_,_) -> id
107     | C.AMutCase (id,_,_,_,_,_) -> id
108     | C.AFix (id,_,_) -> id
109     | C.ACoFix (id,_,_) -> id
110 ;;
111
112 let test_for_lifting ~ids_to_inner_types ~ids_to_inner_sorts= 
113   let module C = Cic in
114   let module C2A = Cic2acic in
115   (* atomic terms are never lifted, according to my policy *)
116   function
117       C.ARel (id,_,_,_) -> false
118     | C.AVar (id,_,_) -> 
119          (try 
120             ignore (Hashtbl.find ids_to_inner_types id).C2A.annsynthesized;
121             true;
122           with Not_found -> false) 
123     | C.AMeta (id,_,_) -> 
124          (try 
125             Hashtbl.find ids_to_inner_sorts id = "Prop"
126           with Not_found -> assert false)
127     | C.ASort (id,_) -> false
128     | C.AImplicit _ -> raise NotImplemented
129     | C.AProd (id,_,_,_) -> false
130     | C.ACast (id,_,_) -> 
131          (try 
132             ignore (Hashtbl.find ids_to_inner_types id).C2A.annsynthesized;
133             true;
134           with Not_found -> false)
135     | C.ALambda (id,_,_,_) -> 
136          (try 
137             ignore (Hashtbl.find ids_to_inner_types id).C2A.annsynthesized;
138             true;
139           with Not_found -> false)
140     | C.ALetIn (id,_,_,_) -> 
141          (try 
142             ignore (Hashtbl.find ids_to_inner_types id).C2A.annsynthesized;
143             true;
144           with Not_found -> false)
145     | C.AAppl (id,_) ->
146          (try 
147             ignore (Hashtbl.find ids_to_inner_types id).C2A.annsynthesized;
148             true;
149           with Not_found -> false) 
150     | C.AConst (id,_,_) -> 
151          (try 
152             ignore (Hashtbl.find ids_to_inner_types id).C2A.annsynthesized;
153             true;
154           with Not_found -> false) 
155     | C.AMutInd (id,_,_,_) -> false
156     | C.AMutConstruct (id,_,_,_,_) -> 
157        (try 
158             ignore (Hashtbl.find ids_to_inner_types id).C2A.annsynthesized;
159             true;
160           with Not_found -> false)
161         (* oppure: false *)
162     | C.AMutCase (id,_,_,_,_,_) ->
163          (try 
164             ignore (Hashtbl.find ids_to_inner_types id).C2A.annsynthesized;
165             true;
166           with Not_found -> false)
167     | C.AFix (id,_,_) ->
168           (try 
169             ignore (Hashtbl.find ids_to_inner_types id).C2A.annsynthesized;
170             true;
171           with Not_found -> false)
172     | C.ACoFix (id,_,_) ->
173          (try 
174             ignore (Hashtbl.find ids_to_inner_types id).C2A.annsynthesized;
175             true;
176           with Not_found -> false)
177 ;;
178
179 (* transform a proof p into a proof list, concatenating the last 
180 conclude element to the apply_context list, in case context is
181 empty. Otherwise, it just returns [p] *)
182
183 let flat seed p = 
184  let module K = Content in
185   if (p.K.proof_context = []) then
186     if p.K.proof_apply_context = [] then [p]
187     else 
188       let p1 =
189         { p with
190           K.proof_context = []; 
191           K.proof_apply_context = []
192         } in
193       p.K.proof_apply_context@[p1]
194   else 
195     [p]
196 ;;
197
198 let rec serialize seed = 
199   function 
200     [] -> []
201   | a::l -> (flat seed a)@(serialize seed l) 
202 ;;
203
204 (* top_down = true if the term is a LAMBDA or a decl *)
205 let generate_conversion seed top_down id inner_proof ~ids_to_inner_types =
206  let module C2A = Cic2acic in
207  let module K = Content in
208  let exp = (try ((Hashtbl.find ids_to_inner_types id).C2A.annexpected)
209             with Not_found -> None)
210  in
211  match exp with
212      None -> inner_proof
213    | Some expty ->
214        if inner_proof.K.proof_conclude.K.conclude_method = "Intros+LetTac" then
215          { K.proof_name = inner_proof.K.proof_name;
216             K.proof_id   = gen_id proof_prefix seed;
217             K.proof_context = [] ;
218             K.proof_apply_context = [];
219             K.proof_conclude = 
220               { K.conclude_id = gen_id conclude_prefix seed; 
221                 K.conclude_aref = id;
222                 K.conclude_method = "TD_Conversion";
223                 K.conclude_args = 
224                   [K.ArgProof {inner_proof with K.proof_name = None}];
225                 K.conclude_conclusion = Some expty
226               };
227           }
228         else
229           { K.proof_name =  inner_proof.K.proof_name;
230             K.proof_id   = gen_id proof_prefix seed;
231             K.proof_context = [] ;
232             K.proof_apply_context = [{inner_proof with K.proof_name = None}];
233             K.proof_conclude = 
234               { K.conclude_id = gen_id conclude_prefix seed; 
235                 K.conclude_aref = id;
236                 K.conclude_method = "BU_Conversion";
237                 K.conclude_args =  
238                  [K.Premise 
239                   { K.premise_id = gen_id premise_prefix seed;
240                     K.premise_xref = inner_proof.K.proof_id; 
241                     K.premise_binder = None;
242                     K.premise_n = None
243                   } 
244                  ]; 
245                 K.conclude_conclusion = Some expty
246               };
247           }
248 ;;
249
250 let generate_exact seed t id name ~ids_to_inner_types =
251   let module C2A = Cic2acic in
252   let module K = Content in
253     { K.proof_name = name;
254       K.proof_id   = gen_id proof_prefix seed ;
255       K.proof_context = [] ;
256       K.proof_apply_context = [];
257       K.proof_conclude = 
258         { K.conclude_id = gen_id conclude_prefix seed; 
259           K.conclude_aref = id;
260           K.conclude_method = "Exact";
261           K.conclude_args = [K.Term t];
262           K.conclude_conclusion = 
263               try Some (Hashtbl.find ids_to_inner_types id).C2A.annsynthesized
264               with Not_found -> None
265         };
266     }
267 ;;
268
269 let generate_intros_let_tac seed id n s is_intro inner_proof name ~ids_to_inner_types =
270   let module C2A = Cic2acic in
271   let module C = Cic in
272   let module K = Content in
273     { K.proof_name = name;
274       K.proof_id  = gen_id proof_prefix seed ;
275       K.proof_context = [] ;
276       K.proof_apply_context = [];
277       K.proof_conclude = 
278         { K.conclude_id = gen_id conclude_prefix seed; 
279           K.conclude_aref = id;
280           K.conclude_method = "Intros+LetTac";
281           K.conclude_args = [K.ArgProof inner_proof];
282           K.conclude_conclusion = 
283             try Some 
284              (Hashtbl.find ids_to_inner_types id).C2A.annsynthesized
285             with Not_found -> 
286               (match inner_proof.K.proof_conclude.K.conclude_conclusion with
287                  None -> None
288               | Some t -> 
289                   if is_intro then Some (C.AProd ("gen"^id,n,s,t))
290                   else Some (C.ALetIn ("gen"^id,n,s,t)))
291         };
292     }
293 ;;
294
295 let build_decl_item seed id n s ~ids_to_inner_sorts =
296  let module K = Content in
297  let sort =
298    try
299     Some (Hashtbl.find ids_to_inner_sorts (Cic2acic.source_id_of_id id))
300    with Not_found -> None
301  in
302  match sort with
303  | Some "Prop" ->
304     `Hypothesis
305       { K.dec_name = name_of n;
306         K.dec_id = gen_id declaration_prefix seed; 
307         K.dec_inductive = false;
308         K.dec_aref = id;
309         K.dec_type = s
310       }
311  | _ ->
312     `Declaration
313       { K.dec_name = name_of n;
314         K.dec_id = gen_id declaration_prefix seed; 
315         K.dec_inductive = false;
316         K.dec_aref = id;
317         K.dec_type = s
318       }
319 ;;
320
321 let rec build_subproofs_and_args seed l ~ids_to_inner_types ~ids_to_inner_sorts =
322   let module C = Cic in
323   let module K = Content in
324   let rec aux =
325     function
326       [] -> [],[]
327     | t::l1 -> 
328        let subproofs,args = aux l1 in
329         if (test_for_lifting t ~ids_to_inner_types ~ids_to_inner_sorts) then
330           let new_subproof = 
331             acic2content 
332               seed ~name:"H" ~ids_to_inner_types ~ids_to_inner_sorts t in
333           let new_arg = 
334             K.Premise
335               { K.premise_id = gen_id premise_prefix seed;
336                 K.premise_xref = new_subproof.K.proof_id;
337                 K.premise_binder = new_subproof.K.proof_name;
338                 K.premise_n = None
339               } in
340           new_subproof::subproofs,new_arg::args
341         else 
342           let hd = 
343             (match t with 
344                C.ARel (idr,idref,n,b) ->
345                  let sort = 
346                    (try Hashtbl.find ids_to_inner_sorts idr 
347                     with Not_found -> "Type") in 
348                  if sort ="Prop" then 
349                     K.Premise 
350                       { K.premise_id = gen_id premise_prefix seed;
351                         K.premise_xref = idr;
352                         K.premise_binder = Some b;
353                         K.premise_n = Some n
354                       }
355                  else (K.Term t)
356              | C.AConst(id,uri,[]) ->
357                  let sort = 
358                    (try Hashtbl.find ids_to_inner_sorts id 
359                     with Not_found -> "Type") in 
360                  if sort ="Prop" then 
361                     K.Lemma 
362                       { K.lemma_id = gen_id lemma_prefix seed;
363                         K.lemma_name = UriManager.name_of_uri uri;
364                         K.lemma_uri = UriManager.string_of_uri uri
365                       }
366                  else (K.Term t)
367              | C.AMutConstruct(id,uri,tyno,consno,[]) ->
368                  let sort = 
369                    (try Hashtbl.find ids_to_inner_sorts id 
370                     with Not_found -> "Type") in 
371                  if sort ="Prop" then 
372                     let inductive_types =
373                       (let o,_ = 
374                          CicEnvironment.get_obj CicUniv.empty_ugraph uri
375                        in
376                          match o with 
377                              Cic.Constant _ -> assert false
378                            | Cic.Variable _ -> assert false
379                            | Cic.CurrentProof _ -> assert false
380                            | Cic.InductiveDefinition (l,_,_) -> l 
381                       ) in
382                     let (_,_,_,constructors) = 
383                       List.nth inductive_types tyno in 
384                     let name,_ = List.nth constructors (consno - 1) in
385                     K.Lemma 
386                       { K.lemma_id = gen_id lemma_prefix seed;
387                         K.lemma_name = name;
388                         K.lemma_uri = 
389                           UriManager.string_of_uri uri ^ "#xpointer(1/" ^
390                           string_of_int (tyno+1) ^ "/" ^ string_of_int consno ^
391                           ")"
392                       }
393                  else (K.Term t) 
394              | _ -> (K.Term t)) in
395           subproofs,hd::args
396   in 
397   match (aux l) with
398     [p],args -> 
399       [{p with K.proof_name = None}], 
400         List.map 
401           (function 
402               K.Premise prem when prem.K.premise_xref = p.K.proof_id ->
403                K.Premise {prem with K.premise_binder = None}
404             | i -> i) args
405   | p,a as c -> c
406
407 and
408
409 build_def_item seed id n t ~ids_to_inner_sorts ~ids_to_inner_types =
410  let module K = Content in
411   try
412    let sort = Hashtbl.find ids_to_inner_sorts id in
413    if sort = "Prop" then
414        (let p = 
415         (acic2content seed ?name:(name_of n) ~ids_to_inner_sorts  ~ids_to_inner_types t)
416        in 
417         `Proof p;)
418    else 
419       `Definition
420         { K.def_name = name_of n;
421           K.def_id = gen_id definition_prefix seed; 
422           K.def_aref = id;
423           K.def_term = t
424         }
425   with
426    Not_found -> assert false
427
428 (* the following function must be called with an object of sort
429 Prop. For debugging purposes this is tested again, possibly raising an 
430 Not_a_proof exception *)
431
432 and acic2content seed ?name ~ids_to_inner_sorts ~ids_to_inner_types t =
433   let rec aux ?name t =
434   let module C = Cic in
435   let module K = Content in
436   let module C2A = Cic2acic in
437   let t1 =
438     match t with 
439       C.ARel (id,idref,n,b) as t ->
440         let sort = Hashtbl.find ids_to_inner_sorts id in
441         if sort = "Prop" then
442           generate_exact seed t id name ~ids_to_inner_types 
443         else raise Not_a_proof
444     | C.AVar (id,uri,exp_named_subst) as t ->
445         let sort = Hashtbl.find ids_to_inner_sorts id in
446         if sort = "Prop" then
447           generate_exact seed t id name ~ids_to_inner_types 
448         else raise Not_a_proof
449     | C.AMeta (id,n,l) as t ->
450         let sort = Hashtbl.find ids_to_inner_sorts id in
451         if sort = "Prop" then
452           generate_exact seed t id name ~ids_to_inner_types 
453         else raise Not_a_proof
454     | C.ASort (id,s) -> raise Not_a_proof
455     | C.AImplicit _ -> raise NotImplemented
456     | C.AProd (_,_,_,_) -> raise Not_a_proof
457     | C.ACast (id,v,t) -> aux v
458     | C.ALambda (id,n,s,t) -> 
459         let sort = Hashtbl.find ids_to_inner_sorts id in
460         if sort = "Prop" then 
461           let proof = aux t in
462           let proof' = 
463             if proof.K.proof_conclude.K.conclude_method = "Intros+LetTac" then
464                match proof.K.proof_conclude.K.conclude_args with
465                  [K.ArgProof p] -> p
466                | _ -> assert false                  
467             else proof in
468           let proof'' =
469             { proof' with
470               K.proof_name = None;
471               K.proof_context = 
472                 (build_decl_item seed id n s ids_to_inner_sorts)::
473                   proof'.K.proof_context
474             }
475           in
476           generate_intros_let_tac seed id n s true proof'' name ~ids_to_inner_types
477         else raise Not_a_proof 
478     | C.ALetIn (id,n,s,t) ->
479         let sort = Hashtbl.find ids_to_inner_sorts id in
480         if sort = "Prop" then
481           let proof = aux t in
482           let proof' = 
483             if proof.K.proof_conclude.K.conclude_method = "Intros+LetTac" then
484                match proof.K.proof_conclude.K.conclude_args with
485                  [K.ArgProof p] -> p
486                | _ -> assert false                  
487             else proof in
488           let proof'' =
489             { proof' with
490                K.proof_name = None;
491                K.proof_context = 
492                  ((build_def_item seed id n s ids_to_inner_sorts 
493                    ids_to_inner_types):> Cic.annterm K.in_proof_context_element)
494                  ::proof'.K.proof_context;
495             }
496           in
497           generate_intros_let_tac seed id n s false proof'' name ~ids_to_inner_types
498         else raise Not_a_proof 
499     | C.AAppl (id,li) ->
500         (try rewrite 
501            seed name id li ~ids_to_inner_types ~ids_to_inner_sorts
502          with NotApplicable ->
503          try inductive 
504           seed name id li ~ids_to_inner_types ~ids_to_inner_sorts
505          with NotApplicable ->
506           let subproofs, args =
507             build_subproofs_and_args 
508               seed li ~ids_to_inner_types ~ids_to_inner_sorts in
509 (*            
510           let args_to_lift = 
511             List.filter (test_for_lifting ~ids_to_inner_types) li in
512           let subproofs = 
513             match args_to_lift with
514                 [_] -> List.map aux args_to_lift 
515             | _ -> List.map (aux ~name:"H") args_to_lift in
516           let args = build_args seed li subproofs 
517                  ~ids_to_inner_types ~ids_to_inner_sorts in *)
518             { K.proof_name = name;
519               K.proof_id   = gen_id proof_prefix seed;
520               K.proof_context = [];
521               K.proof_apply_context = serialize seed subproofs;
522               K.proof_conclude = 
523                 { K.conclude_id = gen_id conclude_prefix seed;
524                   K.conclude_aref = id;
525                   K.conclude_method = "Apply";
526                   K.conclude_args = args;
527                   K.conclude_conclusion = 
528                      try Some 
529                        (Hashtbl.find ids_to_inner_types id).C2A.annsynthesized
530                      with Not_found -> None
531                  };
532             })
533     | C.AConst (id,uri,exp_named_subst) as t ->
534         let sort = Hashtbl.find ids_to_inner_sorts id in
535         if sort = "Prop" then
536           generate_exact seed t id name ~ids_to_inner_types
537         else raise Not_a_proof
538     | C.AMutInd (id,uri,i,exp_named_subst) -> raise Not_a_proof
539     | C.AMutConstruct (id,uri,i,j,exp_named_subst) as t ->
540         let sort = Hashtbl.find ids_to_inner_sorts id in
541         if sort = "Prop" then 
542           generate_exact seed t id name ~ids_to_inner_types
543         else raise Not_a_proof
544     | C.AMutCase (id,uri,typeno,ty,te,patterns) ->
545         let inductive_types,noparams =
546           (let o, _ = CicEnvironment.get_obj CicUniv.empty_ugraph uri in
547              match o with
548                  Cic.Constant _ -> assert false
549                | Cic.Variable _ -> assert false
550                | Cic.CurrentProof _ -> assert false
551                | Cic.InductiveDefinition (l,_,n) -> l,n 
552           ) in
553         let (_,_,_,constructors) = List.nth inductive_types typeno in
554         let name_and_arities = 
555           let rec count_prods =
556             function 
557                C.Prod (_,_,t) -> 1 + count_prods t
558              | _ -> 0 in
559           List.map 
560             (function (n,t) -> Some n,((count_prods t) - noparams)) constructors in
561         let pp = 
562           let build_proof p (name,arity) =
563             let rec make_context_and_body c p n =
564               if n = 0 then c,(aux p)
565               else 
566                 (match p with
567                    Cic.ALambda(idl,vname,s1,t1) ->
568                      let ce = 
569                        build_decl_item seed idl vname s1 ~ids_to_inner_sorts in
570                      make_context_and_body (ce::c) t1 (n-1)
571                    | _ -> assert false) in
572              let context,body = make_context_and_body [] p arity in
573                K.ArgProof
574                 {body with K.proof_name = name; K.proof_context=context} in
575           List.map2 build_proof patterns name_and_arities in
576         let teid = get_id te in
577         let context,term =
578           (match 
579              build_subproofs_and_args 
580                seed ~ids_to_inner_types ~ids_to_inner_sorts [te]
581            with
582              l,[t] -> l,t
583            | _ -> assert false) in
584         { K.proof_name = name;
585           K.proof_id   = gen_id proof_prefix seed;
586           K.proof_context = []; 
587           K.proof_apply_context = serialize seed context;
588           K.proof_conclude = 
589             { K.conclude_id = gen_id conclude_prefix seed; 
590               K.conclude_aref = id;
591               K.conclude_method = "Case";
592               K.conclude_args = 
593                 (K.Aux (UriManager.string_of_uri uri))::
594                 (K.Aux (string_of_int typeno))::(K.Term ty)::term::pp;
595               K.conclude_conclusion = 
596                 try Some 
597                   (Hashtbl.find ids_to_inner_types id).C2A.annsynthesized
598                 with Not_found -> None  
599              }
600         }
601     | C.AFix (id, no, funs) -> 
602         let proofs = 
603           List.map 
604             (function (_,name,_,_,bo) -> `Proof (aux ~name bo)) funs in
605         let decreasing_args = 
606           List.map (function (_,_,n,_,_) -> n) funs in
607         let jo = 
608           { K.joint_id = gen_id joint_prefix seed;
609             K.joint_kind = `Recursive decreasing_args;
610             K.joint_defs = proofs
611           } 
612         in
613           { K.proof_name = name;
614             K.proof_id  = gen_id proof_prefix seed;
615             K.proof_context = [`Joint jo]; 
616             K.proof_apply_context = [];
617             K.proof_conclude = 
618               { K.conclude_id = gen_id conclude_prefix seed; 
619                 K.conclude_aref = id;
620                 K.conclude_method = "Exact";
621                 K.conclude_args =
622                 [ K.Premise
623                   { K.premise_id = gen_id premise_prefix seed; 
624                     K.premise_xref = jo.K.joint_id;
625                     K.premise_binder = Some "tiralo fuori";
626                     K.premise_n = Some no;
627                   }
628                 ];
629                 K.conclude_conclusion =
630                    try Some 
631                      (Hashtbl.find ids_to_inner_types id).C2A.annsynthesized
632                    with Not_found -> None
633               }
634         } 
635     | C.ACoFix (id,no,funs) -> 
636         let proofs = 
637           List.map 
638             (function (_,name,_,bo) -> `Proof (aux ~name bo)) funs in
639         let jo = 
640           { K.joint_id = gen_id joint_prefix seed;
641             K.joint_kind = `CoRecursive;
642             K.joint_defs = proofs
643           } 
644         in
645           { K.proof_name = name;
646             K.proof_id   = gen_id proof_prefix seed;
647             K.proof_context = [`Joint jo]; 
648             K.proof_apply_context = [];
649             K.proof_conclude = 
650               { K.conclude_id = gen_id conclude_prefix seed; 
651                 K.conclude_aref = id;
652                 K.conclude_method = "Exact";
653                 K.conclude_args =
654                 [ K.Premise
655                   { K.premise_id = gen_id premise_prefix seed; 
656                     K.premise_xref = jo.K.joint_id;
657                     K.premise_binder = Some "tiralo fuori";
658                     K.premise_n = Some no;
659                   }
660                 ];
661                 K.conclude_conclusion =
662                   try Some 
663                     (Hashtbl.find ids_to_inner_types id).C2A.annsynthesized
664                   with Not_found -> None
665               };
666         } 
667      in 
668      let id = get_id t in
669      generate_conversion seed false id t1 ~ids_to_inner_types
670 in aux ?name t
671
672 and inductive seed name id li ~ids_to_inner_types ~ids_to_inner_sorts =
673   let aux ?name = acic2content seed  ~ids_to_inner_types ~ids_to_inner_sorts in
674   let module C2A = Cic2acic in
675   let module K = Content in
676   let module C = Cic in
677   match li with 
678     C.AConst (idc,uri,exp_named_subst)::args ->
679       let uri_str = UriManager.string_of_uri uri in
680       let suffix = Str.regexp_string "_ind.con" in
681       let len = String.length uri_str in 
682       let n = (try (Str.search_backward suffix uri_str len)
683                with Not_found -> -1) in
684       if n<0 then raise NotApplicable
685       else 
686         let method_name =
687           if UriManager.eq uri HelmLibraryObjects.Logic.ex_ind_URI then "Exists"
688           else if UriManager.eq uri HelmLibraryObjects.Logic.and_ind_URI then "AndInd"
689           else if UriManager.eq uri HelmLibraryObjects.Logic.false_ind_URI then "FalseInd"
690           else "ByInduction" in
691         let prefix = String.sub uri_str 0 n in
692         let ind_str = (prefix ^ ".ind") in 
693         let ind_uri = UriManager.uri_of_string ind_str in
694         let inductive_types,noparams =
695           (let o,_ = CicEnvironment.get_obj CicUniv.empty_ugraph ind_uri in
696              match o with
697                  Cic.Constant _ -> assert false
698                | Cic.Variable _ -> assert false
699                | Cic.CurrentProof _ -> assert false
700                | Cic.InductiveDefinition (l,_,n) -> (l,n) 
701           ) in
702         let rec split n l =
703           if n = 0 then ([],l) else
704           let p,a = split (n-1) (List.tl l) in
705           ((List.hd l::p),a) in
706         let params_and_IP,tail_args = split (noparams+1) args in
707         let constructors = 
708             (match inductive_types with
709               [(_,_,_,l)] -> l
710             | _ -> raise NotApplicable) (* don't care for mutual ind *) in
711         let constructors1 = 
712           let rec clean_up n t =
713              if n = 0 then t else
714              (match t with
715                 (label,Cic.Prod (_,_,t)) -> clean_up (n-1) (label,t)
716               | _ -> assert false) in
717           List.map (clean_up noparams) constructors in
718         let no_constructors= List.length constructors in
719         let args_for_cases, other_args = 
720           split no_constructors tail_args in
721         let subproofs,other_method_args =
722           build_subproofs_and_args seed other_args
723              ~ids_to_inner_types ~ids_to_inner_sorts in
724         let method_args=
725           let rec build_method_args =
726             function
727                 [],_-> [] (* extra args are ignored ???? *)
728               | (name,ty)::tlc,arg::tla ->
729                   let idarg = get_id arg in
730                   let sortarg = 
731                     (try (Hashtbl.find ids_to_inner_sorts idarg)
732                      with Not_found -> "Type") in
733                   let hdarg = 
734                     if sortarg = "Prop" then
735                       let (co,bo) = 
736                         let rec bc = 
737                           function 
738                             Cic.Prod (_,s,t),Cic.ALambda(idl,n,s1,t1) ->
739                               let ce = 
740                                 build_decl_item 
741                                   seed idl n s1 ~ids_to_inner_sorts in
742                               if (occur ind_uri s) then
743                                 ( match t1 with
744                                    Cic.ALambda(id2,n2,s2,t2) ->
745                                      let inductive_hyp =
746                                        `Hypothesis
747                                          { K.dec_name = name_of n2;
748                                            K.dec_id =
749                                             gen_id declaration_prefix seed; 
750                                            K.dec_inductive = true;
751                                            K.dec_aref = id2;
752                                            K.dec_type = s2
753                                          } in
754                                      let (context,body) = bc (t,t2) in
755                                      (ce::inductive_hyp::context,body)
756                                  | _ -> assert false)
757                               else 
758                                 ( 
759                                 let (context,body) = bc (t,t1) in
760                                 (ce::context,body))
761                             | _ , t -> ([],aux t) in
762                         bc (ty,arg) in
763                       K.ArgProof
764                        { bo with
765                          K.proof_name = Some name;
766                          K.proof_context = co; 
767                        };
768                     else (K.Term arg) in
769                   hdarg::(build_method_args (tlc,tla))
770               | _ -> assert false in
771           build_method_args (constructors1,args_for_cases) in
772           { K.proof_name = name;
773             K.proof_id   = gen_id proof_prefix seed;
774             K.proof_context = []; 
775             K.proof_apply_context = serialize seed subproofs;
776             K.proof_conclude = 
777               { K.conclude_id = gen_id conclude_prefix seed; 
778                 K.conclude_aref = id;
779                 K.conclude_method = method_name;
780                 K.conclude_args =
781                   K.Aux (string_of_int no_constructors) 
782                   ::K.Term (C.AAppl(id,((C.AConst(idc,uri,exp_named_subst))::params_and_IP)))
783                   ::method_args@other_method_args;
784                 K.conclude_conclusion = 
785                    try Some 
786                      (Hashtbl.find ids_to_inner_types id).C2A.annsynthesized
787                    with Not_found -> None  
788               }
789           } 
790   | _ -> raise NotApplicable
791
792 and rewrite seed name id li ~ids_to_inner_types ~ids_to_inner_sorts =
793   let aux ?name = acic2content seed ~ids_to_inner_types ~ids_to_inner_sorts in
794   let module C2A = Cic2acic in
795   let module K = Content in
796   let module C = Cic in
797   match li with 
798     C.AConst (sid,uri,exp_named_subst)::args ->
799       if UriManager.eq uri HelmLibraryObjects.Logic.eq_ind_URI or
800          UriManager.eq uri HelmLibraryObjects.Logic.eq_ind_r_URI then 
801         let subproofs,arg = 
802           (match 
803              build_subproofs_and_args 
804                seed ~ids_to_inner_types ~ids_to_inner_sorts [List.nth args 3]
805            with 
806              l,[p] -> l,p
807            | _,_ -> assert false) in 
808         let method_args =
809           let rec ma_aux n = function
810               [] -> []
811             | a::tl -> 
812                 let hd = 
813                   if n = 0 then arg
814                   else 
815                     let aid = get_id a in
816                     let asort = (try (Hashtbl.find ids_to_inner_sorts aid)
817                       with Not_found -> "Type") in
818                     if asort = "Prop" then
819                       K.ArgProof (aux a)
820                     else K.Term a in
821                 hd::(ma_aux (n-1) tl) in
822           (ma_aux 3 args) in 
823           { K.proof_name = name;
824             K.proof_id  = gen_id proof_prefix seed;
825             K.proof_context = []; 
826             K.proof_apply_context = serialize seed subproofs;
827             K.proof_conclude = 
828               { K.conclude_id = gen_id conclude_prefix seed; 
829                 K.conclude_aref = id;
830                 K.conclude_method = "Rewrite";
831                 K.conclude_args = 
832                   K.Term (C.AConst (sid,uri,exp_named_subst))::method_args;
833                 K.conclude_conclusion = 
834                    try Some 
835                      (Hashtbl.find ids_to_inner_types id).C2A.annsynthesized
836                    with Not_found -> None
837               }
838           } 
839       else raise NotApplicable
840   | _ -> raise NotApplicable
841 ;; 
842
843 let map_conjectures
844  seed ~ids_to_inner_sorts ~ids_to_inner_types (id,n,context,ty)
845 =
846  let module K = Content in
847  let context' =
848   List.map
849    (function
850        (id,None) -> None
851      | (id,Some (name,Cic.ADecl t)) ->
852          Some
853           (* We should call build_decl_item, but we have not computed *)
854           (* the inner-types ==> we always produce a declaration      *)
855           (`Declaration
856             { K.dec_name = name_of name;
857               K.dec_id = gen_id declaration_prefix seed; 
858               K.dec_inductive = false;
859               K.dec_aref = get_id t;
860               K.dec_type = t
861             })
862      | (id,Some (name,Cic.ADef t)) ->
863          Some
864           (* We should call build_def_item, but we have not computed *)
865           (* the inner-types ==> we always produce a declaration     *)
866           (`Definition
867              { K.def_name = name_of name;
868                K.def_id = gen_id definition_prefix seed; 
869                K.def_aref = get_id t;
870                K.def_term = t
871              })
872    ) context
873  in
874   (id,n,context',ty)
875 ;;
876
877 (* map_sequent is similar to map_conjectures, but the for the hid
878 of the hypothesis, which are preserved instead of generating
879 fresh ones. We shall have to adopt a uniform policy, soon or later *)
880
881 let map_sequent ((id,n,context,ty):Cic.annconjecture) =
882  let module K = Content in
883  let context' =
884   List.map
885    (function
886        (id,None) -> None
887      | (id,Some (name,Cic.ADecl t)) ->
888          Some
889           (* We should call build_decl_item, but we have not computed *)
890           (* the inner-types ==> we always produce a declaration      *)
891           (`Declaration
892             { K.dec_name = name_of name;
893               K.dec_id = id; 
894               K.dec_inductive = false;
895               K.dec_aref = get_id t;
896               K.dec_type = t
897             })
898      | (id,Some (name,Cic.ADef t)) ->
899          Some
900           (* We should call build_def_item, but we have not computed *)
901           (* the inner-types ==> we always produce a declaration     *)
902           (`Definition
903              { K.def_name = name_of name;
904                K.def_id = id; 
905                K.def_aref = get_id t;
906                K.def_term = t
907              })
908    ) context
909  in
910   (id,n,context',ty)
911 ;;
912
913 let rec annobj2content ~ids_to_inner_sorts ~ids_to_inner_types = 
914   let module C = Cic in
915   let module K = Content in
916   let module C2A = Cic2acic in
917   let seed = ref 0 in
918   function
919       C.ACurrentProof (_,_,n,conjectures,bo,ty,params) ->
920         (gen_id object_prefix seed, params,
921           Some
922            (List.map
923              (map_conjectures seed ~ids_to_inner_sorts ~ids_to_inner_types)
924              conjectures),
925           `Def (K.Const,ty,
926             build_def_item seed (get_id bo) (C.Name n) bo 
927              ~ids_to_inner_sorts ~ids_to_inner_types))
928     | C.AConstant (_,_,n,Some bo,ty,params) ->
929          (gen_id object_prefix seed, params, None,
930            `Def (K.Const,ty,
931              build_def_item seed (get_id bo) (C.Name n) bo 
932                ~ids_to_inner_sorts ~ids_to_inner_types))
933     | C.AConstant (id,_,n,None,ty,params) ->
934          (gen_id object_prefix seed, params, None,
935            `Decl (K.Const,
936              build_decl_item seed id (C.Name n) ty 
937                ~ids_to_inner_sorts))
938     | C.AVariable (_,n,Some bo,ty,params) ->
939          (gen_id object_prefix seed, params, None,
940            `Def (K.Var,ty,
941              build_def_item seed (get_id bo) (C.Name n) bo
942                ~ids_to_inner_sorts ~ids_to_inner_types))
943     | C.AVariable (id,n,None,ty,params) ->
944          (gen_id object_prefix seed, params, None,
945            `Decl (K.Var,
946              build_decl_item seed id (C.Name n) ty
947               ~ids_to_inner_sorts))
948     | C.AInductiveDefinition (id,l,params,nparams) ->
949          (gen_id object_prefix seed, params, None,
950             `Joint
951               { K.joint_id = gen_id joint_prefix seed;
952                 K.joint_kind = `Inductive nparams;
953                 K.joint_defs = List.map (build_inductive seed) l
954               }) 
955
956 and
957     build_inductive seed = 
958      let module K = Content in
959       fun (_,n,b,ty,l) ->
960         `Inductive
961           { K.inductive_id = gen_id inductive_prefix seed;
962             K.inductive_kind = b;
963             K.inductive_type = ty;
964             K.inductive_constructors = build_constructors seed l
965            }
966
967 and 
968     build_constructors seed l =
969      let module K = Content in
970       List.map 
971        (fun (n,t) ->
972            { K.dec_name = Some n;
973              K.dec_id = gen_id declaration_prefix seed;
974              K.dec_inductive = false;
975              K.dec_aref = "";
976              K.dec_type = t
977            }) l
978 ;;
979    
980 (* 
981 and 'term cinductiveType = 
982  id * string * bool * 'term *                (* typename, inductive, arity *)
983    'term cconstructor list                   (*  constructors        *)
984
985 and 'term cconstructor =
986  string * 'term    
987 *)
988
989