]> matita.cs.unibo.it Git - helm.git/blob - helm/interface/cicTypeChecker.ml
Initial revision
[helm.git] / helm / interface / cicTypeChecker.ml
1 exception NotImplemented;;
2 exception Impossible;;
3 exception NotWellTyped of string;;
4 exception WrongUriToConstant of string;;
5 exception WrongUriToVariable of string;;
6 exception WrongUriToMutualInductiveDefinitions of string;;
7 exception ListTooShort;;
8 exception NotPositiveOccurrences of string;;
9 exception NotWellFormedTypeOfInductiveConstructor of string;;
10 exception WrongRequiredArgument of string;;
11
12 let fdebug = ref 0;;
13 let debug t env =
14  let rec debug_aux t i =
15   let module C = Cic in
16   let module U = UriManager in
17    CicPp.ppobj (C.Variable ("DEBUG", None,
18     C.Prod (C.Name "-15", C.Const (U.uri_of_string "cic:/dummy-15",0),
19     C.Prod (C.Name "-14", C.Const (U.uri_of_string "cic:/dummy-14",0),
20     C.Prod (C.Name "-13", C.Const (U.uri_of_string "cic:/dummy-13",0),
21     C.Prod (C.Name "-12", C.Const (U.uri_of_string "cic:/dummy-12",0),
22     C.Prod (C.Name "-11", C.Const (U.uri_of_string "cic:/dummy-11",0),
23     C.Prod (C.Name "-10", C.Const (U.uri_of_string "cic:/dummy-10",0),
24     C.Prod (C.Name "-9", C.Const (U.uri_of_string "cic:/dummy-9",0),
25     C.Prod (C.Name "-8", C.Const (U.uri_of_string "cic:/dummy-8",0),
26     C.Prod (C.Name "-7", C.Const (U.uri_of_string "cic:/dummy-7",0),
27     C.Prod (C.Name "-6", C.Const (U.uri_of_string "cic:/dummy-6",0),
28      C.Prod (C.Name "-5", C.Const (U.uri_of_string "cic:/dummy-5",0),
29       C.Prod (C.Name "-4", C.Const (U.uri_of_string "cic:/dummy-4",0),
30        C.Prod (C.Name "-3", C.Const (U.uri_of_string "cic:/dummy-3",0),
31         C.Prod (C.Name "-2", C.Const (U.uri_of_string "cic:/dummy-2",0),
32          C.Prod (C.Name "-1", C.Const (U.uri_of_string "cic:/dummy-1",0),
33           t
34          )
35         )
36        )
37       )
38      )
39     )
40     )
41     )
42     )))))))
43     )) ^ "\n" ^ i
44  in
45   if !fdebug = 0 then
46    raise (NotWellTyped ("\n" ^ List.fold_right debug_aux (t::env) ""))
47    (*print_endline ("\n" ^ List.fold_right debug_aux (t::env) "") ; flush stdout*)
48 ;;
49
50 let rec split l n =
51  match (l,n) with
52     (l,0) -> ([], l)
53   | (he::tl, n) -> let (l1,l2) = split tl (n-1) in (he::l1,l2)
54   | (_,_) -> raise ListTooShort
55 ;;
56
57 exception CicCacheError;;
58
59 let rec cooked_type_of_constant uri cookingsno =
60  let module C = Cic in
61  let module R = CicReduction in
62  let module U = UriManager in
63   let cobj =
64    match CicCache.is_type_checked uri cookingsno with
65       CicCache.CheckedObj cobj -> cobj
66     | CicCache.UncheckedObj uobj ->
67        (* let's typecheck the uncooked obj *)
68        (match uobj with
69            C.Definition (_,te,ty,_) ->
70              let _ = type_of ty in
71               if not (R.are_convertible (type_of te) ty) then
72                raise (NotWellTyped ("Constant " ^ (U.string_of_uri uri)))
73          | C.Axiom (_,ty,_) ->
74            (* only to check that ty is well-typed *)
75            let _ = type_of ty in ()
76          | C.CurrentProof (_,_,te,ty) ->
77              let _ = type_of ty in
78               if not (R.are_convertible (type_of te) ty) then
79                raise (NotWellTyped ("CurrentProof" ^ (U.string_of_uri uri)))
80          | _ -> raise (WrongUriToConstant (U.string_of_uri uri))
81        ) ;
82        CicCache.set_type_checking_info uri ;
83        match CicCache.is_type_checked uri cookingsno with
84           CicCache.CheckedObj cobj -> cobj
85         | CicCache.UncheckedObj _ -> raise CicCacheError
86   in
87    match cobj with
88       C.Definition (_,_,ty,_) -> ty
89     | C.Axiom (_,ty,_) -> ty
90     | C.CurrentProof (_,_,_,ty) -> ty
91     | _ -> raise (WrongUriToConstant (U.string_of_uri uri))
92
93 and type_of_variable uri =
94  let module C = Cic in
95  let module R = CicReduction in
96  let module U = UriManager in
97   (* 0 because a variable is never cooked => no partial cooking at one level *)
98   match CicCache.is_type_checked uri 0 with
99      CicCache.CheckedObj (C.Variable (_,_,ty)) -> ty
100    | CicCache.UncheckedObj (C.Variable (_,bo,ty)) ->
101       (* only to check that ty is well-typed *)
102       let _ = type_of ty in
103        (match bo with
104            None -> ()
105          | Some bo ->
106             if not (R.are_convertible (type_of bo) ty) then
107              raise (NotWellTyped ("Variable " ^ (U.string_of_uri uri)))
108        ) ;
109        CicCache.set_type_checking_info uri ;
110        ty
111    |  _ -> raise (WrongUriToVariable (UriManager.string_of_uri uri))
112
113 and does_not_occur n nn te =
114  let module C = Cic in
115    (*CSC: whd sembra essere superflua perche' un caso in cui l'occorrenza *)
116    (*CSC: venga mangiata durante la whd sembra presentare problemi di *)
117    (*CSC: universi                                                    *)
118    match CicReduction.whd te with
119       C.Rel m when m > n && m <= nn -> false
120     | C.Rel _
121     | C.Var _
122     | C.Meta _
123     | C.Sort _
124     | C.Implicit -> true
125     | C.Cast (te,ty) -> does_not_occur n nn te && does_not_occur n nn ty
126     | C.Prod (_,so,dest) ->
127        does_not_occur n nn so && does_not_occur (n + 1) (nn + 1) dest
128     | C.Lambda (_,so,dest) ->
129        does_not_occur n nn so && does_not_occur (n + 1) (nn + 1) dest
130     | C.LetIn (_,so,dest) ->
131        does_not_occur n nn so && does_not_occur (n + 1) (nn + 1) dest
132     | C.Appl l ->
133        List.fold_right (fun x i -> i && does_not_occur n nn x) l true
134     | C.Const _
135     | C.Abst _
136     | C.MutInd _
137     | C.MutConstruct _ -> true
138     | C.MutCase (_,_,_,out,te,pl) ->
139        does_not_occur n nn out && does_not_occur n nn te &&
140         List.fold_right (fun x i -> i && does_not_occur n nn x) pl true
141     | C.Fix (_,fl) ->
142        let len = List.length fl in
143         let n_plus_len = n + len in
144         let nn_plus_len = nn + len in
145          List.fold_right
146           (fun (_,_,ty,bo) i ->
147             i && does_not_occur n_plus_len nn_plus_len ty &&
148             does_not_occur n_plus_len nn_plus_len bo
149           ) fl true
150     | C.CoFix (_,fl) ->
151        let len = List.length fl in
152         let n_plus_len = n + len in
153         let nn_plus_len = nn + len in
154          List.fold_right
155           (fun (_,ty,bo) i ->
156             i && does_not_occur n_plus_len nn_plus_len ty &&
157             does_not_occur n_plus_len nn_plus_len bo
158           ) fl true
159
160 (*CSC l'indice x dei tipi induttivi e' t.c. n < x <= nn *)
161 (*CSC questa funzione e' simile alla are_all_occurrences_positive, ma fa *)
162 (*CSC dei controlli leggermente diversi. Viene invocata solamente dalla  *)
163 (*CSC strictly_positive                                                  *)
164 (*CSC definizione (giusta???) tratta dalla mail di Hugo ;-)              *)
165 and weakly_positive n nn uri te =
166  let module C = Cic in
167   (*CSC mettere in cicSubstitution *)
168   let rec subst_inductive_type_with_dummy_rel =
169    function
170       C.MutInd (uri',_,0) when UriManager.eq uri' uri ->
171        C.Rel 0 (* dummy rel *)
172     | C.Appl ((C.MutInd (uri',_,0))::tl) when UriManager.eq uri' uri ->
173        C.Rel 0 (* dummy rel *)
174     | C.Cast (te,ty) -> subst_inductive_type_with_dummy_rel te
175     | C.Prod (name,so,ta) ->
176        C.Prod (name, subst_inductive_type_with_dummy_rel so,
177         subst_inductive_type_with_dummy_rel ta)
178     | C.Lambda (name,so,ta) ->
179        C.Lambda (name, subst_inductive_type_with_dummy_rel so,
180         subst_inductive_type_with_dummy_rel ta)
181     | C.Appl tl ->
182        C.Appl (List.map subst_inductive_type_with_dummy_rel tl)
183     | C.MutCase (uri,cookingsno,i,outtype,term,pl) ->
184        C.MutCase (uri,cookingsno,i,
185         subst_inductive_type_with_dummy_rel outtype,
186         subst_inductive_type_with_dummy_rel term,
187         List.map subst_inductive_type_with_dummy_rel pl)
188     | C.Fix (i,fl) ->
189        C.Fix (i,List.map (fun (name,i,ty,bo) -> (name,i,
190         subst_inductive_type_with_dummy_rel ty,
191         subst_inductive_type_with_dummy_rel bo)) fl)
192     | C.CoFix (i,fl) ->
193        C.CoFix (i,List.map (fun (name,ty,bo) -> (name,
194         subst_inductive_type_with_dummy_rel ty,
195         subst_inductive_type_with_dummy_rel bo)) fl)
196     | t -> t
197   in
198   match CicReduction.whd te with
199      C.Appl ((C.MutInd (uri',_,0))::tl) when UriManager.eq uri' uri -> true
200    | C.MutInd (uri',_,0) when UriManager.eq uri' uri -> true
201    | C.Prod (C.Anonimous,source,dest) ->
202       strictly_positive n nn (subst_inductive_type_with_dummy_rel source) &&
203        weakly_positive (n + 1) (nn + 1) uri dest
204    | C.Prod (name,source,dest) when does_not_occur 0 n dest ->
205       (* dummy abstraction, so we behave as in the anonimous case *)
206       strictly_positive n nn (subst_inductive_type_with_dummy_rel source) &&
207        weakly_positive (n + 1) (nn + 1) uri dest
208    | C.Prod (_,source,dest) ->
209       does_not_occur n nn (subst_inductive_type_with_dummy_rel source) &&
210        weakly_positive (n + 1) (nn + 1) uri dest
211    | _ -> raise (NotWellFormedTypeOfInductiveConstructor ("Guess where the error is ;-)"))
212
213 (* instantiate_parameters ps (x1:T1)...(xn:Tn)C                             *)
214 (* returns ((x_|ps|:T_|ps|)...(xn:Tn)C){ps_1 / x1 ; ... ; ps_|ps| / x_|ps|} *)
215 and instantiate_parameters params c =
216  let module C = Cic in
217   match (c,params) with
218      (c,[]) -> c
219    | (C.Prod (_,_,ta), he::tl) ->
220        instantiate_parameters tl
221         (CicSubstitution.subst he ta)
222    | (C.Cast (te,_), _) -> instantiate_parameters params te
223    | (t,l) -> raise Impossible
224
225 and strictly_positive n nn te =
226  let module C = Cic in
227  let module U = UriManager in
228   match CicReduction.whd te with
229      C.Rel _ -> true
230    | C.Cast (te,ty) ->
231       (*CSC: bisogna controllare ty????*)
232       strictly_positive n nn te
233    | C.Prod (_,so,ta) ->
234       does_not_occur n nn so &&
235        strictly_positive (n+1) (nn+1) ta
236    | C.Appl ((C.Rel m)::tl) when m > n && m <= nn ->
237       List.fold_right (fun x i -> i && does_not_occur n nn x) tl true
238    | C.Appl ((C.MutInd (uri,_,i))::tl) -> 
239       let (ok,paramsno,cl) =
240        match CicCache.get_obj uri with
241            C.InductiveDefinition (tl,_,paramsno) ->
242             let (_,_,_,cl) = List.nth tl i in
243              (List.length tl = 1, paramsno, cl)
244          | _ -> raise(WrongUriToMutualInductiveDefinitions(U.string_of_uri uri))
245       in
246        let (params,arguments) = split tl paramsno in
247        let lifted_params = List.map (CicSubstitution.lift 1) params in
248        let cl' =
249         List.map (fun (_,te,_) -> instantiate_parameters lifted_params te) cl
250        in
251         ok &&
252          List.fold_right
253           (fun x i -> i && does_not_occur n nn x)
254           arguments true &&
255          (*CSC: MEGAPATCH3 (sara' quella giusta?)*)
256          List.fold_right
257           (fun x i ->
258             i &&
259              weakly_positive (n+1) (nn+1) uri x
260           ) cl' true
261    | C.MutInd (uri,_,i) ->
262       (match CicCache.get_obj uri with
263           C.InductiveDefinition (tl,_,_) ->
264            List.length tl = 1
265         | _ -> raise (WrongUriToMutualInductiveDefinitions(U.string_of_uri uri))
266       )
267    | t -> does_not_occur n nn t
268
269 (*CSC l'indice x dei tipi induttivi e' t.c. n < x <= nn *)
270 and are_all_occurrences_positive uri indparamsno i n nn te =
271  let module C = Cic in
272   match CicReduction.whd te with
273      C.Appl ((C.Rel m)::tl) when m = i ->
274       (*CSC: riscrivere fermandosi a 0 *)
275       (* let's check if the inductive type is applied at least to *)
276       (* indparamsno parameters                                   *)
277       let last =
278        List.fold_left
279         (fun k x ->
280           if k = 0 then 0
281           else
282            match CicReduction.whd x with
283               C.Rel m when m = n - (indparamsno - k) -> k - 1
284             | _ -> raise (WrongRequiredArgument (UriManager.string_of_uri uri))
285         ) indparamsno tl
286       in
287        if last = 0 then
288         List.fold_right (fun x i -> i && does_not_occur n nn x) tl true
289        else
290         raise (WrongRequiredArgument (UriManager.string_of_uri uri))
291    | C.Rel m when m = i ->
292       if indparamsno = 0 then
293        true
294       else
295        raise (WrongRequiredArgument (UriManager.string_of_uri uri))
296    | C.Prod (C.Anonimous,source,dest) ->
297       strictly_positive n nn source &&
298        are_all_occurrences_positive uri indparamsno (i+1) (n + 1) (nn + 1) dest
299    | C.Prod (name,source,dest) when does_not_occur 0 n dest ->
300       (* dummy abstraction, so we behave as in the anonimous case *)
301       strictly_positive n nn source &&
302        are_all_occurrences_positive uri indparamsno (i+1) (n + 1) (nn + 1) dest
303    | C.Prod (_,source,dest) ->
304       does_not_occur n nn source &&
305        are_all_occurrences_positive uri indparamsno (i+1) (n + 1) (nn + 1) dest
306    | _ -> raise (NotWellFormedTypeOfInductiveConstructor (UriManager.string_of_uri uri))
307
308 (*CSC: cambiare il nome, torna unit! *)
309 and cooked_mutual_inductive_defs uri =
310  let module U = UriManager in
311   function
312      Cic.InductiveDefinition (itl, _, indparamsno) ->
313       (* let's check if the arity of the inductive types are well *)
314       (* formed                                                   *)
315       List.iter (fun (_,_,x,_) -> let _ = type_of x in ()) itl ;
316
317       (* let's check if the types of the inductive constructors  *)
318       (* are well formed.                                        *)
319       (* In order not to use type_of_aux we put the types of the *)
320       (* mutual inductive types at the head of the types of the  *)
321       (* constructors using Prods                                *)
322       (*CSC: piccola??? inefficienza                             *)
323       let len = List.length itl in
324        let _ =
325         List.fold_right
326          (fun (_,_,_,cl) i ->
327            List.iter
328             (fun (name,te,r) -> 
329               let augmented_term =
330                List.fold_right
331                 (fun (name,_,ty,_) i -> Cic.Prod (Cic.Name name, ty, i))
332                 itl te
333               in
334                let _ = type_of augmented_term in
335                 (* let's check also the positivity conditions *)
336                 if not (are_all_occurrences_positive uri indparamsno i 0 len te)
337                 then
338                  raise (NotPositiveOccurrences (U.string_of_uri uri))
339                 else
340                  match !r with
341                     Some _ -> raise Impossible
342                   | None -> r := Some (recursive_args 0 len te)
343             ) cl ;
344            (i + 1)
345         ) itl 1
346        in
347         ()
348    | _ ->
349      raise (WrongUriToMutualInductiveDefinitions (U.string_of_uri uri))
350
351 and cooked_type_of_mutual_inductive_defs uri cookingsno i =
352  let module C = Cic in
353  let module R = CicReduction in
354  let module U = UriManager in
355   let cobj =
356    match CicCache.is_type_checked uri cookingsno with
357       CicCache.CheckedObj cobj -> cobj
358     | CicCache.UncheckedObj uobj ->
359        cooked_mutual_inductive_defs uri uobj ;
360        CicCache.set_type_checking_info uri ;
361        (match CicCache.is_type_checked uri cookingsno with
362           CicCache.CheckedObj cobj -> cobj
363         | CicCache.UncheckedObj _ -> raise CicCacheError
364        )
365   in
366    match cobj with
367       C.InductiveDefinition (dl,_,_) ->
368        let (_,_,arity,_) = List.nth dl i in
369         arity
370     | _ -> raise (WrongUriToMutualInductiveDefinitions (U.string_of_uri uri))
371
372 and cooked_type_of_mutual_inductive_constr uri cookingsno i j =
373  let module C = Cic in
374  let module R = CicReduction in
375  let module U = UriManager in
376   let cobj =
377    match CicCache.is_type_checked uri cookingsno with
378       CicCache.CheckedObj cobj -> cobj
379     | CicCache.UncheckedObj uobj ->
380        cooked_mutual_inductive_defs uri uobj ;
381        CicCache.set_type_checking_info uri ;
382        (match CicCache.is_type_checked uri cookingsno with
383           CicCache.CheckedObj cobj -> cobj
384         | CicCache.UncheckedObj _ -> raise CicCacheError
385        )
386   in
387    match cobj with
388       C.InductiveDefinition (dl,_,_) ->
389        let (_,_,_,cl) = List.nth dl i in
390         let (_,ty,_) = List.nth cl (j-1) in
391          ty
392     | _ -> raise (WrongUriToMutualInductiveDefinitions (U.string_of_uri uri))
393
394 and recursive_args n nn te =
395  let module C = Cic in
396   match CicReduction.whd te with
397      C.Rel _ -> []
398    | C.Var _
399    | C.Meta _
400    | C.Sort _
401    | C.Implicit
402    | C.Cast _ (*CSC ??? *) -> raise Impossible (* due to type-checking *)
403    | C.Prod (_,so,de) ->
404       (not (does_not_occur n nn so))::(recursive_args (n+1) (nn + 1) de)
405    | C.Lambda _ -> raise Impossible (* due to type-checking *)
406    | C.LetIn _ -> raise NotImplemented
407    | C.Appl _ -> []
408    | C.Const _
409    | C.Abst _ -> raise Impossible
410    | C.MutInd _
411    | C.MutConstruct _
412    | C.MutCase _
413    | C.Fix _
414    | C.CoFix _ -> raise Impossible (* due to type-checking *)
415
416 and get_new_safes p c rl safes n nn x =
417  let module C = Cic in
418  let module U = UriManager in
419  let module R = CicReduction in
420   match (R.whd c, R.whd p, rl) with
421      (C.Prod (_,_,ta1), C.Lambda (_,_,ta2), b::tl) ->
422        (* we are sure that the two sources are convertible because we *)
423        (* have just checked this. So let's go along ...               *)
424        let safes' =
425         List.map (fun x -> x + 1) safes
426        in
427         let safes'' =
428          if b then 1::safes' else safes'
429         in
430          get_new_safes ta2 ta1 tl safes'' (n+1) (nn+1) (x+1)
431    | (C.MutInd _, e, []) -> (e,safes,n,nn,x)
432    | (C.Appl _, e, []) -> (e,safes,n,nn,x)
433    | (_,_,_) -> raise Impossible
434
435 and eat_prods n te =
436  let module C = Cic in
437  let module R = CicReduction in
438   match (n, R.whd te) with
439      (0, _) -> te
440    | (n, C.Prod (_,_,ta)) when n > 0 -> eat_prods (n - 1) ta
441    | (_, _) -> raise Impossible
442
443 and eat_lambdas n te =
444  let module C = Cic in
445  let module R = CicReduction in
446   match (n, R.whd te) with
447      (0, _) -> (te, 0)
448    | (n, C.Lambda (_,_,ta)) when n > 0 ->
449       let (te, k) = eat_lambdas (n - 1) ta in
450        (te, k + 1)
451    | (_, _) -> raise Impossible
452
453 (*CSC: Tutto quello che segue e' l'intuzione di luca ;-) *)
454 and check_is_really_smaller_arg n nn kl x safes te =
455  (*CSC: forse la whd si puo' fare solo quando serve veramente. *)
456  (*CSC: cfr guarded_by_destructors                             *)
457  let module C = Cic in
458  let module U = UriManager in
459  match CicReduction.whd te with
460      C.Rel m when List.mem m safes -> true
461    | C.Rel _ -> false
462    | C.Var _
463    | C.Meta _
464    | C.Sort _
465    | C.Implicit 
466    | C.Cast _
467 (*   | C.Cast (te,ty) ->
468       check_is_really_smaller_arg n nn kl x safes te &&
469        check_is_really_smaller_arg n nn kl x safes ty*)
470 (*   | C.Prod (_,so,ta) ->
471       check_is_really_smaller_arg n nn kl x safes so &&
472        check_is_really_smaller_arg (n+1) (nn+1) kl (x+1)
473         (List.map (fun x -> x + 1) safes) ta*)
474    | C.Prod _ -> raise Impossible
475    | C.Lambda (_,so,ta) ->
476       check_is_really_smaller_arg n nn kl x safes so &&
477        check_is_really_smaller_arg (n+1) (nn+1) kl (x+1)
478         (List.map (fun x -> x + 1) safes) ta
479    | C.LetIn (_,so,ta) ->
480       check_is_really_smaller_arg n nn kl x safes so &&
481        check_is_really_smaller_arg (n+1) (nn+1) kl (x+1)
482         (List.map (fun x -> x + 1) safes) ta
483    | C.Appl (he::_) ->
484       (*CSC: sulla coda ci vogliono dei controlli? secondo noi no, ma *)
485       (*CSC: solo perche' non abbiamo trovato controesempi            *)
486       check_is_really_smaller_arg n nn kl x safes he
487    | C.Appl [] -> raise Impossible
488    | C.Const _
489    | C.Abst _
490    | C.MutInd _ -> raise Impossible
491    | C.MutConstruct _ -> false
492    | C.MutCase (uri,_,i,outtype,term,pl) ->
493       (match term with
494           C.Rel m when List.mem m safes || m = x ->
495            let (isinductive,paramsno,cl) =
496             match CicCache.get_obj uri with
497                C.InductiveDefinition (tl,_,paramsno) ->
498                 let (_,isinductive,_,cl) = List.nth tl i in
499                  let cl' =
500                   List.map (fun (id,ty,r) -> (id, eat_prods paramsno ty, r)) cl
501                  in
502                   (isinductive,paramsno,cl')
503              | _ ->
504                raise (WrongUriToMutualInductiveDefinitions(U.string_of_uri uri))
505            in
506             if not isinductive then
507               List.fold_right
508                (fun p i -> i && check_is_really_smaller_arg n nn kl x safes p)
509                pl true
510             else
511               List.fold_right
512                (fun (p,(_,c,rl)) i ->
513                  let rl' =
514                   match !rl with
515                      Some rl' ->
516                       let (_,rl'') = split rl' paramsno in
517                        rl''
518                    | None -> raise Impossible
519                  in
520                   let (e,safes',n',nn',x') =
521                    get_new_safes p c rl' safes n nn x
522                   in
523                    i &&
524                    check_is_really_smaller_arg n' nn' kl x' safes' e
525                ) (List.combine pl cl) true
526         | C.Appl ((C.Rel m)::tl) when List.mem m safes || m = x ->
527            let (isinductive,paramsno,cl) =
528             match CicCache.get_obj uri with
529                C.InductiveDefinition (tl,_,paramsno) ->
530                 let (_,isinductive,_,cl) = List.nth tl i in
531                  let cl' =
532                   List.map (fun (id,ty,r) -> (id, eat_prods paramsno ty, r)) cl
533                  in
534                   (isinductive,paramsno,cl')
535              | _ ->
536                raise (WrongUriToMutualInductiveDefinitions(U.string_of_uri uri))
537            in
538             if not isinductive then
539               List.fold_right
540                (fun p i -> i && check_is_really_smaller_arg n nn kl x safes p)
541                pl true
542             else
543               (*CSC: supponiamo come prima che nessun controllo sia necessario*)
544               (*CSC: sugli argomenti di una applicazione                      *)
545               List.fold_right
546                (fun (p,(_,c,rl)) i ->
547                  let rl' =
548                   match !rl with
549                      Some rl' ->
550                       let (_,rl'') = split rl' paramsno in
551                        rl''
552                    | None -> raise Impossible
553                  in
554                   let (e, safes',n',nn',x') =
555                    get_new_safes p c rl' safes n nn x
556                   in
557                    i &&
558                    check_is_really_smaller_arg n' nn' kl x' safes' e
559                ) (List.combine pl cl) true
560         | _ ->
561           List.fold_right
562            (fun p i -> i && check_is_really_smaller_arg n nn kl x safes p)
563            pl true
564       )
565    | C.Fix (_, fl) ->
566       let len = List.length fl in
567        let n_plus_len = n + len
568        and nn_plus_len = nn + len
569        and x_plus_len = x + len
570        and safes' = List.map (fun x -> x + len) safes in
571         List.fold_right
572          (fun (_,_,ty,bo) i ->
573            i &&
574             check_is_really_smaller_arg n_plus_len nn_plus_len kl x_plus_len
575              safes' bo
576          ) fl true
577    | C.CoFix (_, fl) ->
578       let len = List.length fl in
579        let n_plus_len = n + len
580        and nn_plus_len = nn + len
581        and x_plus_len = x + len
582        and safes' = List.map (fun x -> x + len) safes in
583         List.fold_right
584          (fun (_,ty,bo) i ->
585            i &&
586             check_is_really_smaller_arg n_plus_len nn_plus_len kl x_plus_len
587              safes' bo
588          ) fl true
589
590 and guarded_by_destructors n nn kl x safes =
591  let module C = Cic in
592  let module U = UriManager in
593   function
594      C.Rel m when m > n && m <= nn -> false
595    | C.Rel _
596    | C.Var _
597    | C.Meta _
598    | C.Sort _
599    | C.Implicit -> true
600    | C.Cast (te,ty) ->
601       guarded_by_destructors n nn kl x safes te &&
602        guarded_by_destructors n nn kl x safes ty
603    | C.Prod (_,so,ta) ->
604       guarded_by_destructors n nn kl x safes so &&
605        guarded_by_destructors (n+1) (nn+1) kl (x+1)
606         (List.map (fun x -> x + 1) safes) ta
607    | C.Lambda (_,so,ta) ->
608       guarded_by_destructors n nn kl x safes so &&
609        guarded_by_destructors (n+1) (nn+1) kl (x+1)
610         (List.map (fun x -> x + 1) safes) ta
611    | C.LetIn (_,so,ta) ->
612       guarded_by_destructors n nn kl x safes so &&
613        guarded_by_destructors (n+1) (nn+1) kl (x+1)
614         (List.map (fun x -> x + 1) safes) ta
615    | C.Appl ((C.Rel m)::tl) when m > n && m <= nn ->
616       let k = List.nth kl (m - n - 1) in
617        if not (List.length tl > k) then false
618        else
619         List.fold_right
620          (fun param i ->
621            i && guarded_by_destructors n nn kl x safes param
622          ) tl true &&
623          check_is_really_smaller_arg n nn kl x safes (List.nth tl k)
624    | C.Appl tl ->
625       List.fold_right (fun t i -> i && guarded_by_destructors n nn kl x safes t)
626        tl true
627    | C.Const _
628    | C.Abst _
629    | C.MutInd _
630    | C.MutConstruct _ -> true
631    | C.MutCase (uri,_,i,outtype,term,pl) ->
632       (match term with
633           C.Rel m when List.mem m safes || m = x ->
634            let (isinductive,paramsno,cl) =
635             match CicCache.get_obj uri with
636                C.InductiveDefinition (tl,_,paramsno) ->
637                 let (_,isinductive,_,cl) = List.nth tl i in
638                  let cl' =
639                   List.map (fun (id,ty,r) -> (id, eat_prods paramsno ty, r)) cl
640                  in
641                   (isinductive,paramsno,cl')
642              | _ ->
643                raise (WrongUriToMutualInductiveDefinitions(U.string_of_uri uri))
644            in
645             if not isinductive then
646              guarded_by_destructors n nn kl x safes outtype &&
647               guarded_by_destructors n nn kl x safes term &&
648               (*CSC: manca ??? il controllo sul tipo di term? *)
649               List.fold_right
650                (fun p i -> i && guarded_by_destructors n nn kl x safes p)
651                pl true
652             else
653              guarded_by_destructors n nn kl x safes outtype &&
654               (*CSC: manca ??? il controllo sul tipo di term? *)
655               List.fold_right
656                (fun (p,(_,c,rl)) i ->
657                  let rl' =
658                   match !rl with
659                      Some rl' ->
660                       let (_,rl'') = split rl' paramsno in
661                        rl''
662                    | None -> raise Impossible
663                  in
664                   let (e,safes',n',nn',x') =
665                    get_new_safes p c rl' safes n nn x
666                   in
667                    i &&
668                    guarded_by_destructors n' nn' kl x' safes' e
669                ) (List.combine pl cl) true
670         | C.Appl ((C.Rel m)::tl) when List.mem m safes || m = x ->
671            let (isinductive,paramsno,cl) =
672             match CicCache.get_obj uri with
673                C.InductiveDefinition (tl,_,paramsno) ->
674                 let (_,isinductive,_,cl) = List.nth tl i in
675                  let cl' =
676                   List.map (fun (id,ty,r) -> (id, eat_prods paramsno ty, r)) cl
677                  in
678                   (isinductive,paramsno,cl')
679              | _ ->
680                raise (WrongUriToMutualInductiveDefinitions(U.string_of_uri uri))
681            in
682             if not isinductive then
683              guarded_by_destructors n nn kl x safes outtype &&
684               guarded_by_destructors n nn kl x safes term &&
685               (*CSC: manca ??? il controllo sul tipo di term? *)
686               List.fold_right
687                (fun p i -> i && guarded_by_destructors n nn kl x safes p)
688                pl true
689             else
690              guarded_by_destructors n nn kl x safes outtype &&
691               (*CSC: manca ??? il controllo sul tipo di term? *)
692               List.fold_right
693                (fun t i -> i && guarded_by_destructors n nn kl x safes t)
694                tl true &&
695               List.fold_right
696                (fun (p,(_,c,rl)) i ->
697                  let rl' =
698                   match !rl with
699                      Some rl' ->
700                       let (_,rl'') = split rl' paramsno in
701                        rl''
702                    | None -> raise Impossible
703                  in
704                   let (e, safes',n',nn',x') =
705                    get_new_safes p c rl' safes n nn x
706                   in
707                    i &&
708                    guarded_by_destructors n' nn' kl x' safes' e
709                ) (List.combine pl cl) true
710         | _ ->
711           guarded_by_destructors n nn kl x safes outtype &&
712            guarded_by_destructors n nn kl x safes term &&
713            (*CSC: manca ??? il controllo sul tipo di term? *)
714            List.fold_right
715             (fun p i -> i && guarded_by_destructors n nn kl x safes p)
716             pl true
717       )
718    | C.Fix (_, fl) ->
719       let len = List.length fl in
720        let n_plus_len = n + len
721        and nn_plus_len = nn + len
722        and x_plus_len = x + len
723        and safes' = List.map (fun x -> x + len) safes in
724         List.fold_right
725          (fun (_,_,ty,bo) i ->
726            i && guarded_by_destructors n_plus_len nn_plus_len kl x_plus_len
727             safes' ty &&
728             guarded_by_destructors n_plus_len nn_plus_len kl x_plus_len
729              safes' bo
730          ) fl true
731    | C.CoFix (_, fl) ->
732       let len = List.length fl in
733        let n_plus_len = n + len
734        and nn_plus_len = nn + len
735        and x_plus_len = x + len
736        and safes' = List.map (fun x -> x + len) safes in
737         List.fold_right
738          (fun (_,ty,bo) i ->
739            i && guarded_by_destructors n_plus_len nn_plus_len kl x_plus_len
740             safes' ty &&
741             guarded_by_destructors n_plus_len nn_plus_len kl x_plus_len safes'
742              bo
743          ) fl true
744
745 (*CSC h = 0 significa non ancora protetto *)
746 and guarded_by_constructors n nn h =
747  let module C = Cic in
748   function
749      C.Rel m when m > n && m <= nn -> h = 1
750    | C.Rel _
751    | C.Var _ 
752    | C.Meta _
753    | C.Sort _
754    | C.Implicit -> true (*CSC: ma alcuni sono impossibili!!!! vedi Prod *)
755    | C.Cast (te,ty) ->
756       guarded_by_constructors n nn h te &&
757        guarded_by_constructors n nn h ty
758    | C.Prod (_,so,de) ->
759       raise Impossible (* the term has just been type-checked *)
760    | C.Lambda (_,so,de) ->
761       does_not_occur n nn so &&
762        guarded_by_constructors (n + 1) (nn + 1) h de
763    | C.LetIn (_,so,de) ->
764       does_not_occur n nn so &&
765        guarded_by_constructors (n + 1) (nn + 1) h de
766    | C.Appl ((C.Rel m)::tl) when m > n && m <= nn ->
767       h = 1 &&
768        List.fold_right (fun x i -> i && does_not_occur n nn x) tl true
769    | C.Appl ((C.MutConstruct (uri,cookingsno,i,j))::tl) ->
770       let (is_coinductive, rl) =
771        match CicCache.get_cooked_obj uri cookingsno with
772           C.InductiveDefinition (itl,_,_) ->
773            let (_,is_inductive,_,cl) = List.nth itl i in
774             let (_,cons,rrec_args) = List.nth cl (j - 1) in
775              (match !rrec_args with
776                  None -> raise Impossible
777                | Some rec_args -> (not is_inductive, rec_args)
778              )
779         | _ ->
780          raise (WrongUriToMutualInductiveDefinitions
781           (UriManager.string_of_uri uri))
782       in
783        is_coinductive &&
784        List.fold_right
785         (fun (x,r) i ->
786           i &&
787            if r then
788             guarded_by_constructors n nn 1 x
789            else
790             does_not_occur n nn x
791         ) (List.combine tl rl) true
792    | C.Appl l ->
793       List.fold_right (fun x i -> i && does_not_occur n nn x) l true
794    | C.Const _
795    | C.Abst _
796    | C.MutInd _ 
797    | C.MutConstruct _ -> true (*CSC: ma alcuni sono impossibili!!!! vedi Prod *)
798    | C.MutCase (_,_,_,out,te,pl) ->
799       let rec returns_a_coinductive =
800        function
801           (*CSC: per le regole di tipaggio, la chiamata ricorsiva verra' *)
802           (*CSC: effettata solo una volta, per mangiarsi l'astrazione    *)
803           (*CSC: non dummy                                               *)
804           C.Lambda (_,_,de) -> returns_a_coinductive de
805         | C.MutInd (uri,_,i) ->
806            (*CSC: definire una funzioncina per questo codice sempre replicato *)
807            (match CicCache.get_obj uri with
808                C.InductiveDefinition (itl,_,_) ->
809                 let (_,is_inductive,_,_) = List.nth itl i in
810                  not is_inductive
811              | _ ->
812                raise (WrongUriToMutualInductiveDefinitions
813                 (UriManager.string_of_uri uri))
814             )
815         (*CSC: bug nella prossima riga (manca la whd) *)
816         | C.Appl ((C.MutInd (uri,_,i))::_) ->
817            (match CicCache.get_obj uri with
818                C.InductiveDefinition (itl,_,_) ->
819                 let (_,is_inductive,_,_) = List.nth itl i in
820                  not is_inductive
821              | _ ->
822                raise (WrongUriToMutualInductiveDefinitions
823                 (UriManager.string_of_uri uri))
824             )
825         | _ -> false
826       in
827        does_not_occur n nn out &&
828         does_not_occur n nn te &&
829         if returns_a_coinductive out then
830          List.fold_right
831           (fun x i -> i && guarded_by_constructors n nn h x) pl true
832         else
833          List.fold_right (fun x i -> i && does_not_occur n nn x) pl true
834    | C.Fix (_,fl) ->
835       let len = List.length fl in
836        let n_plus_len = n + len
837        and nn_plus_len = nn + len in
838         List.fold_right
839          (fun (_,_,ty,bo) i ->
840            i && does_not_occur n_plus_len nn_plus_len ty &&
841             does_not_occur n_plus_len nn_plus_len bo
842          ) fl true
843    | C.CoFix (_,fl) ->
844       let len = List.length fl in
845        let n_plus_len = n + len
846        and nn_plus_len = nn + len in
847         List.fold_right
848          (fun (_,ty,bo) i ->
849            i && does_not_occur n_plus_len nn_plus_len ty &&
850             does_not_occur n_plus_len nn_plus_len bo
851          ) fl true
852
853 and check_allowed_sort_elimination uri i need_dummy ind arity1 arity2 =
854  let module C = Cic in
855  let module U = UriManager in
856   match (CicReduction.whd arity1, CicReduction.whd arity2) with
857      (C.Prod (_,so1,de1), C.Prod (_,so2,de2))
858       when CicReduction.are_convertible so1 so2 ->
859        check_allowed_sort_elimination uri i need_dummy
860         (C.Appl [CicSubstitution.lift 1 ind ; C.Rel 1]) de1 de2
861    | (C.Sort C.Prop, C.Sort C.Prop) when need_dummy -> true
862    | (C.Sort C.Prop, C.Sort C.Set) when need_dummy ->
863        (match CicCache.get_obj uri with
864            C.InductiveDefinition (itl,_,_) ->
865             let (_,_,_,cl) = List.nth itl i in
866              (* is a singleton definition? *)
867              List.length cl = 1
868          | _ ->
869            raise (WrongUriToMutualInductiveDefinitions (U.string_of_uri uri))
870        )
871    | (C.Sort C.Set, C.Sort C.Prop) when need_dummy -> true
872    | (C.Sort C.Set, C.Sort C.Set) when need_dummy -> true
873    | (C.Sort C.Set, C.Sort C.Type) when need_dummy ->
874        (match CicCache.get_obj uri with
875            C.InductiveDefinition (itl,_,_) ->
876             let (_,_,_,cl) = List.nth itl i in
877              (* is a small inductive type? *)
878              (*CSC: ottimizzare calcolando staticamente *)
879              let rec is_small =
880               function
881                  C.Prod (_,so,de) ->
882                   let s = type_of so in
883                    (s = C.Sort C.Prop || s = C.Sort C.Set) &&
884                    is_small de
885                | _ -> true (*CSC: we trust the type-checker *)
886              in
887               List.fold_right (fun (_,x,_) i -> i && is_small x) cl true
888          | _ ->
889            raise (WrongUriToMutualInductiveDefinitions (U.string_of_uri uri))
890        )
891    | (C.Sort C.Type, C.Sort _) when need_dummy -> true
892    | (C.Sort C.Prop, C.Prod (_,so,ta)) when not need_dummy ->
893        let res = CicReduction.are_convertible so ind
894        in
895         res &&
896         (match CicReduction.whd ta with
897             C.Sort C.Prop -> true
898           | C.Sort C.Set ->
899              (match CicCache.get_obj uri with
900                  C.InductiveDefinition (itl,_,_) ->
901                   let (_,_,_,cl) = List.nth itl i in
902                    (* is a singleton definition? *)
903                    List.length cl = 1
904                | _ ->
905                  raise (WrongUriToMutualInductiveDefinitions
906                   (U.string_of_uri uri))
907              )
908           | _ -> false
909         )
910    | (C.Sort C.Set, C.Prod (_,so,ta)) when not need_dummy ->
911        let res = CicReduction.are_convertible so ind
912        in
913         res &&
914         (match CicReduction.whd ta with
915             C.Sort C.Prop
916           | C.Sort C.Set  -> true
917           | C.Sort C.Type ->
918              (match CicCache.get_obj uri with
919                  C.InductiveDefinition (itl,_,_) ->
920                   let (_,_,_,cl) = List.nth itl i in
921                    (* is a small inductive type? *)
922                    let rec is_small =
923                     function
924                        C.Prod (_,so,de) ->
925                         let s = type_of so in
926                          (s = C.Sort C.Prop || s = C.Sort C.Set) &&
927                          is_small de
928                      | _ -> true (*CSC: we trust the type-checker *)
929                    in
930                     List.fold_right (fun (_,x,_) i -> i && is_small x) cl true
931                | _ ->
932                  raise (WrongUriToMutualInductiveDefinitions
933                   (U.string_of_uri uri))
934              )
935           | _ -> raise Impossible
936         )
937    | (C.Sort C.Type, C.Prod (_,so,_)) when not need_dummy ->
938        CicReduction.are_convertible so ind
939    | (_,_) -> false
940   
941 and type_of_branch argsno need_dummy outtype term constype =
942  let module C = Cic in
943  let module R = CicReduction in
944   match R.whd constype with
945      C.MutInd (_,_,_) ->
946       if need_dummy then
947        outtype
948       else
949        C.Appl [outtype ; term]
950    | C.Appl (C.MutInd (_,_,_)::tl) ->
951       let (_,arguments) = split tl argsno
952       in
953        if need_dummy && arguments = [] then
954         outtype
955        else
956         C.Appl (outtype::arguments@(if need_dummy then [] else [term]))
957    | C.Prod (name,so,de) ->
958       C.Prod (C.Name "pippo",so,type_of_branch argsno need_dummy 
959        (CicSubstitution.lift 1 outtype)
960        (C.Appl [CicSubstitution.lift 1 term ; C.Rel 1]) de)
961   | _ -> raise Impossible
962        
963  
964 and type_of t =
965  let rec type_of_aux env =
966   let module C = Cic in
967   let module R = CicReduction in
968   let module S = CicSubstitution in
969   let module U = UriManager in
970    function
971       C.Rel n -> S.lift n (List.nth env (n - 1))
972     | C.Var uri ->
973       incr fdebug ;
974       let ty = type_of_variable uri in
975        decr fdebug ;
976        ty
977     | C.Meta n -> raise NotImplemented
978     | C.Sort s -> C.Sort C.Type (*CSC manca la gestione degli universi!!! *)
979     | C.Implicit -> raise Impossible
980     | C.Cast (te,ty) ->
981        let _ = type_of ty in
982         if R.are_convertible (type_of_aux env te) ty then ty
983         else raise (NotWellTyped "Cast")
984     | C.Prod (_,s,t) ->
985        let sort1 = type_of_aux env s
986        and sort2 = type_of_aux (s::env) t in
987         sort_of_prod (sort1,sort2)
988    | C.Lambda (n,s,t) ->
989        let sort1 = type_of_aux env s
990        and type2 = type_of_aux (s::env) t in
991         let sort2 = type_of_aux (s::env) type2 in
992          (* only to check if the product is well-typed *)
993          let _ = sort_of_prod (sort1,sort2) in
994           C.Prod (n,s,type2)
995    | C.LetIn (n,s,t) ->
996        let type1 = type_of_aux env s in
997        let type2 = type_of_aux (type1::env) t in
998         type2
999    | C.Appl (he::tl) when List.length tl > 0 ->
1000       let hetype = type_of_aux env he
1001       and tlbody_and_type = List.map (fun x -> (x, type_of_aux env x)) tl in
1002        (try
1003         eat_prods hetype tlbody_and_type
1004        with _ -> debug (C.Appl (he::tl)) env ; C.Implicit)
1005    | C.Appl _ -> raise (NotWellTyped "Appl: no arguments")
1006    | C.Const (uri,cookingsno) ->
1007       incr fdebug ;
1008       let cty = cooked_type_of_constant uri cookingsno in
1009        decr fdebug ;
1010        cty
1011    | C.Abst _ -> raise Impossible
1012    | C.MutInd (uri,cookingsno,i) ->
1013       incr fdebug ;
1014       let cty = cooked_type_of_mutual_inductive_defs uri cookingsno i in
1015        decr fdebug ;
1016        cty
1017    | C.MutConstruct (uri,cookingsno,i,j) ->
1018       let cty = cooked_type_of_mutual_inductive_constr uri cookingsno i j
1019       in
1020        cty
1021    | C.MutCase (uri,cookingsno,i,outtype,term,pl) ->
1022       let outsort = type_of_aux env outtype in
1023       let (need_dummy, k) =
1024        let rec guess_args t =
1025         match decast t with
1026            C.Sort _ -> (true, 0)
1027          | C.Prod (_, s, t) ->
1028             let (b, n) = guess_args t in
1029              if n = 0 then
1030               (* last prod before sort *)
1031               match CicReduction.whd s with
1032                  (*CSC vedi nota delirante su cookingsno in cicReduction.ml *)
1033                  C.MutInd (uri',_,i') when U.eq uri' uri && i' = i -> (false, 1)
1034                | C.Appl ((C.MutInd (uri',_,i')) :: _)
1035                   when U.eq uri' uri && i' = i -> (false, 1)
1036                | _ -> (true, 1)
1037              else
1038               (b, n + 1)
1039          | _ -> raise (NotWellTyped "MutCase: outtype ill-formed")
1040        in
1041         (*CSC whd non serve dopo type_of_aux ? *)
1042         let (b, k) = guess_args outsort in
1043          if not b then (b, k - 1) else (b, k)
1044       in
1045       let (parameters, arguments) =
1046         match R.whd (type_of_aux env term) with
1047            (*CSC manca il caso dei CAST *)
1048            C.MutInd (uri',_,i') ->
1049             (*CSC vedi nota delirante sui cookingsno in cicReduction.ml*)
1050             if U.eq uri uri' && i = i' then ([],[])
1051             else raise (NotWellTyped ("MutCase: the term is of type " ^
1052              (U.string_of_uri uri') ^ "," ^ string_of_int i' ^
1053              " instead of type " ^ (U.string_of_uri uri') ^ "," ^
1054              string_of_int i))
1055          | C.Appl (C.MutInd (uri',_,i') :: tl) ->
1056             if U.eq uri uri' && i = i' then split tl (List.length tl - k)
1057             else raise (NotWellTyped ("MutCase: the term is of type " ^
1058              (U.string_of_uri uri') ^ "," ^ string_of_int i' ^
1059              " instead of type " ^ (U.string_of_uri uri) ^ "," ^
1060              string_of_int i))
1061          | _ -> raise (NotWellTyped "MutCase: the term is not an inductive one")
1062       in
1063        (* let's control if the sort elimination is allowed: [(I q1 ... qr)|B] *)
1064        let sort_of_ind_type =
1065         if parameters = [] then
1066          C.MutInd (uri,cookingsno,i)
1067         else
1068          C.Appl ((C.MutInd (uri,cookingsno,i))::parameters)
1069        in
1070         if not (check_allowed_sort_elimination uri i need_dummy
1071          sort_of_ind_type (type_of_aux env sort_of_ind_type) outsort)
1072         then
1073          raise (NotWellTyped "MutCase: not allowed sort elimination") ;
1074
1075         (* let's check if the type of branches are right *)
1076         let (cl,parsno) =
1077          match CicCache.get_cooked_obj uri cookingsno with
1078             C.InductiveDefinition (tl,_,parsno) ->
1079              let (_,_,_,cl) = List.nth tl i in (cl,parsno)
1080           | _ ->
1081             raise (WrongUriToMutualInductiveDefinitions (U.string_of_uri uri))
1082         in
1083          let (_,branches_ok) =
1084           List.fold_left
1085            (fun (j,b) (p,(_,c,_)) ->
1086              let cons =
1087               if parameters = [] then
1088                (C.MutConstruct (uri,cookingsno,i,j))
1089               else
1090                (C.Appl (C.MutConstruct (uri,cookingsno,i,j)::parameters))
1091              in
1092               (j + 1, b &&
1093                R.are_convertible (type_of_aux env p)
1094                 (type_of_branch parsno need_dummy outtype cons
1095                   (type_of_aux env cons))
1096               )
1097            ) (1,true) (List.combine pl cl)
1098          in
1099           if not branches_ok then
1100            raise (NotWellTyped "MutCase: wrong type of a branch") ;
1101
1102           if not need_dummy then
1103            C.Appl ((outtype::arguments)@[term])
1104           else if arguments = [] then
1105            outtype
1106           else
1107            C.Appl (outtype::arguments)
1108    | C.Fix (i,fl) ->
1109       let types_times_kl =
1110        List.rev
1111         (List.map (fun (_,k,ty,_) -> let _ = type_of_aux env ty in (ty,k)) fl)
1112       in
1113       let (types,kl) = List.split types_times_kl in
1114        let len = List.length types in
1115         List.iter
1116          (fun (name,x,ty,bo) ->
1117            if (R.are_convertible (type_of_aux (types @ env) bo)
1118             (CicSubstitution.lift len ty))
1119            then
1120             begin
1121              let (m, eaten) = eat_lambdas (x + 1) bo in
1122               (*let's control the guarded by destructors conditions D{f,k,x,M}*)
1123               if not (guarded_by_destructors eaten (len + eaten) kl 1 [] m) then
1124                raise (NotWellTyped "Fix: not guarded by destructors")
1125             end
1126            else
1127             raise (NotWellTyped "Fix: ill-typed bodies")
1128          ) fl ;
1129       
1130         (*CSC: controlli mancanti solo su D{f,k,x,M} *)
1131         let (_,_,ty,_) = List.nth fl i in
1132         ty
1133    | C.CoFix (i,fl) ->
1134       let types =
1135        List.rev (List.map (fun (_,ty,_) -> let _ = type_of_aux env ty in ty) fl)
1136       in
1137        let len = List.length types in
1138         List.iter
1139          (fun (_,ty,bo) ->
1140            if (R.are_convertible (type_of_aux (types @ env) bo)
1141             (CicSubstitution.lift len ty))
1142            then
1143             begin
1144              (* let's control the guarded by constructors conditions C{f,M} *)
1145              if not (guarded_by_constructors 0 len 0 bo) then
1146               raise (NotWellTyped "CoFix: not guarded by constructors")
1147             end
1148            else
1149             raise (NotWellTyped "CoFix: ill-typed bodies")
1150          ) fl ;
1151       
1152         let (_,ty,_) = List.nth fl i in
1153          ty
1154
1155  and decast =
1156   let module C = Cic in
1157    function
1158       C.Cast (t,_) -> t
1159     | t -> t
1160
1161  and sort_of_prod (t1, t2) =
1162   let module C = Cic in
1163    match (decast t1, decast t2) with
1164       (C.Sort s1, C.Sort s2)
1165         when (s2 = C.Prop or s2 = C.Set) -> (* different from Coq manual!!! *)
1166          C.Sort s2
1167     | (C.Sort s1, C.Sort s2) -> C.Sort C.Type (*CSC manca la gestione degli universi!!! *)
1168     | (_,_) -> raise (NotWellTyped "Prod")
1169
1170  and eat_prods hetype =
1171   (*CSC: siamo sicuri che le are_convertible non lavorino con termini non *)
1172   (*CSC: cucinati                                                         *)
1173   function
1174      [] -> hetype
1175    | (hete, hety)::tl ->
1176     (match (CicReduction.whd hetype) with
1177         Cic.Prod (n,s,t) ->
1178          if CicReduction.are_convertible s hety then
1179           (CicReduction.fdebug := -1 ;
1180           eat_prods (CicSubstitution.subst hete t) tl
1181           )
1182          else
1183           (
1184           CicReduction.fdebug := 0 ;
1185           let _ = CicReduction.are_convertible s hety in
1186           debug hete [hety ; s] ;
1187           raise (NotWellTyped "Appl: wrong parameter-type")
1188 )
1189       | _ -> raise (NotWellTyped "Appl: wrong Prod-type")
1190     )
1191  in
1192   type_of_aux [] t
1193 ;;
1194
1195 let typecheck uri =
1196  let module C = Cic in
1197  let module R = CicReduction in
1198  let module U = UriManager in
1199   match CicCache.is_type_checked uri 0 with
1200      CicCache.CheckedObj _ -> ()
1201    | CicCache.UncheckedObj uobj ->
1202       (* let's typecheck the uncooked object *)
1203       (match uobj with
1204           C.Definition (_,te,ty,_) ->
1205            let _ = type_of ty in
1206             if not (R.are_convertible (type_of te ) ty) then
1207              raise (NotWellTyped ("Constant " ^ (U.string_of_uri uri)))
1208         | C.Axiom (_,ty,_) ->
1209           (* only to check that ty is well-typed *)
1210           let _ = type_of ty in ()
1211         | C.CurrentProof (_,_,te,ty) ->
1212            (*CSC [] wrong *)
1213            let _ = type_of ty in
1214             debug (type_of te) [] ;
1215             if not (R.are_convertible (type_of te) ty) then
1216              raise (NotWellTyped ("CurrentProof" ^ (U.string_of_uri uri)))
1217         | C.Variable (_,bo,ty) ->
1218            (* only to check that ty is well-typed *)
1219            let _ = type_of ty in
1220             (match bo with
1221                 None -> ()
1222               | Some bo ->
1223                  if not (R.are_convertible (type_of bo) ty) then
1224                   raise (NotWellTyped ("Variable" ^ (U.string_of_uri uri)))
1225             )
1226         | C.InductiveDefinition _ ->
1227            cooked_mutual_inductive_defs uri uobj
1228       ) ;
1229       CicCache.set_type_checking_info uri
1230 ;;