]> matita.cs.unibo.it Git - helm.git/blob - helm/ocaml/cic_proof_checking/cicTypeChecker.ml
use stateful logger so that the ProofChecker daemon is able to properly
[helm.git] / helm / ocaml / cic_proof_checking / cicTypeChecker.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 (* TODO factorize functions to frequent errors (e.g. "Unknwon mutual inductive
27  * ...") *)
28
29 open Printf
30
31 exception AssertFailure of string;;
32 exception TypeCheckerFailure of string;;
33
34 let fdebug = ref 0;;
35 let debug t context =
36  let rec debug_aux t i =
37   let module C = Cic in
38   let module U = UriManager in
39    CicPp.ppobj (C.Variable ("DEBUG", None, t, [])) ^ "\n" ^ i
40  in
41   if !fdebug = 0 then
42    raise (TypeCheckerFailure (List.fold_right debug_aux (t::context) ""))
43 ;;
44
45 let debug_print = prerr_endline ;;
46
47 let rec split l n =
48  match (l,n) with
49     (l,0) -> ([], l)
50   | (he::tl, n) -> let (l1,l2) = split tl (n-1) in (he::l1,l2)
51   | (_,_) ->
52       raise (TypeCheckerFailure "Parameters number < left parameters number")
53 ;;
54
55 let debrujin_constructor uri number_of_types =
56  let rec aux k =
57   let module C = Cic in
58    function
59       C.Rel n as t when n <= k -> t
60     | C.Rel _ ->
61         raise (TypeCheckerFailure "unbound variable found in constructor type")
62     | C.Var (uri,exp_named_subst) ->
63        let exp_named_subst' = 
64         List.map (function (uri,t) -> (uri,aux k t)) exp_named_subst
65        in
66         C.Var (uri,exp_named_subst')
67     | C.Meta _ -> assert false
68     | C.Sort _
69     | C.Implicit _ as t -> t
70     | C.Cast (te,ty) -> C.Cast (aux k te, aux k ty)
71     | C.Prod (n,s,t) -> C.Prod (n, aux k s, aux (k+1) t)
72     | C.Lambda (n,s,t) -> C.Lambda (n, aux k s, aux (k+1) t)
73     | C.LetIn (n,s,t) -> C.LetIn (n, aux k s, aux (k+1) t)
74     | C.Appl l -> C.Appl (List.map (aux k) l)
75     | C.Const (uri,exp_named_subst) ->
76        let exp_named_subst' = 
77         List.map (function (uri,t) -> (uri,aux k t)) exp_named_subst
78        in
79         C.Const (uri,exp_named_subst')
80     | C.MutInd (uri',tyno,exp_named_subst) when UriManager.eq uri uri' ->
81        if exp_named_subst != [] then
82         raise (TypeCheckerFailure
83           ("non-empty explicit named substitution is applied to "^
84            "a mutual inductive type which is being defined")) ;
85        C.Rel (k + number_of_types - tyno) ;
86     | C.MutInd (uri',tyno,exp_named_subst) ->
87        let exp_named_subst' = 
88         List.map (function (uri,t) -> (uri,aux k t)) exp_named_subst
89        in
90         C.MutInd (uri',tyno,exp_named_subst')
91     | C.MutConstruct (uri,tyno,consno,exp_named_subst) ->
92        let exp_named_subst' = 
93         List.map (function (uri,t) -> (uri,aux k t)) exp_named_subst
94        in
95         C.MutConstruct (uri,tyno,consno,exp_named_subst')
96     | C.MutCase (sp,i,outty,t,pl) ->
97        C.MutCase (sp, i, aux k outty, aux k t,
98         List.map (aux k) pl)
99     | C.Fix (i, fl) ->
100        let len = List.length fl in
101        let liftedfl =
102         List.map
103          (fun (name, i, ty, bo) -> (name, i, aux k ty, aux (k+len) bo))
104           fl
105        in
106         C.Fix (i, liftedfl)
107     | C.CoFix (i, fl) ->
108        let len = List.length fl in
109        let liftedfl =
110         List.map
111          (fun (name, ty, bo) -> (name, aux k ty, aux (k+len) bo))
112           fl
113        in
114         C.CoFix (i, liftedfl)
115  in
116   aux 0
117 ;;
118
119 exception CicEnvironmentError;;
120
121 let rec type_of_constant ~logger uri =
122  let module C = Cic in
123  let module R = CicReduction in
124  let module U = UriManager in
125   let cobj =
126    match CicEnvironment.is_type_checked ~trust:true uri with
127       CicEnvironment.CheckedObj cobj -> cobj
128     | CicEnvironment.UncheckedObj uobj ->
129        logger#log (`Start_type_checking uri) ;
130        CicUniv.directly_to_env_begin ();
131        (* let's typecheck the uncooked obj *)
132        (match uobj with
133            C.Constant (_,Some te,ty,_) ->
134              let _ = type_of ~logger ty in
135               let type_of_te = type_of ~logger te in
136               if not (R.are_convertible [] type_of_te ty) then
137                raise (TypeCheckerFailure (sprintf
138                 "the constant %s is not well typed because the type %s of the body is not convertible to the declared type %s"
139                 (U.string_of_uri uri) (CicPp.ppterm type_of_te)
140                 (CicPp.ppterm ty)))
141          | C.Constant (_,None,ty,_) ->
142            (* only to check that ty is well-typed *)
143            let _ = type_of ty in ()
144          | C.CurrentProof (_,conjs,te,ty,_) ->
145              let _ =
146               List.fold_left
147                (fun metasenv ((_,context,ty) as conj) ->
148                  ignore (type_of_aux' ~logger metasenv context ty) ;
149                  metasenv @ [conj]
150                ) [] conjs
151              in
152               let _ = type_of_aux' ~logger conjs [] ty in
153                let type_of_te = type_of_aux' ~logger conjs [] te in
154                if not (R.are_convertible [] type_of_te ty) then
155                  raise (TypeCheckerFailure (sprintf
156                   "the current proof %s is not well typed because the type %s of the body is not convertible to the declared type %s"
157                   (U.string_of_uri uri) (CicPp.ppterm type_of_te)
158                   (CicPp.ppterm ty)))
159          | _ ->
160            raise (TypeCheckerFailure
161             ("Unknown constant:" ^ U.string_of_uri uri))
162        );
163        CicEnvironment.set_type_checking_info uri ;
164        CicUniv.directly_to_env_end ();
165        logger#log (`Type_checking_completed uri) ;
166        match CicEnvironment.is_type_checked ~trust:false uri with
167           CicEnvironment.CheckedObj cobj -> cobj
168         | CicEnvironment.UncheckedObj _ -> raise CicEnvironmentError
169   in
170    match cobj with
171       C.Constant (_,_,ty,_) -> ty
172     | C.CurrentProof (_,_,_,ty,_) -> ty
173     | _ ->
174         raise (TypeCheckerFailure ("Unknown constant:" ^ U.string_of_uri uri))
175
176 and type_of_variable ~logger uri =
177  let module C = Cic in
178  let module R = CicReduction in
179  let module U = UriManager in
180   (* 0 because a variable is never cooked => no partial cooking at one level *)
181   match CicEnvironment.is_type_checked ~trust:true uri with
182      CicEnvironment.CheckedObj (C.Variable (_,_,ty,_)) -> ty
183    | CicEnvironment.UncheckedObj (C.Variable (_,bo,ty,_)) ->
184       logger#log (`Start_type_checking uri) ;
185       CicUniv.directly_to_env_begin ();
186       (* only to check that ty is well-typed *)
187       let _ = type_of ty in
188        (match bo with
189            None -> ()
190          | Some bo ->
191             if not (R.are_convertible [] (type_of ~logger bo) ty) then
192               raise (TypeCheckerFailure
193                 ("Unknown variable:" ^ U.string_of_uri uri))
194        ) ;
195        CicEnvironment.set_type_checking_info uri ;
196        CicUniv.directly_to_env_end ();
197        logger#log (`Type_checking_completed uri) ;
198        ty
199    |  _ ->
200        raise (TypeCheckerFailure ("Unknown variable:" ^ U.string_of_uri uri))
201
202 and does_not_occur context n nn te =
203  let module C = Cic in
204    (*CSC: whd sembra essere superflua perche' un caso in cui l'occorrenza *)
205    (*CSC: venga mangiata durante la whd sembra presentare problemi di *)
206    (*CSC: universi                                                    *)
207    match CicReduction.whd context te with
208       C.Rel m when m > n && m <= nn -> false
209     | C.Rel _
210     | C.Meta _  (* CSC: Are we sure? No recursion?*)
211     | C.Sort _
212     | C.Implicit _ -> true
213     | C.Cast (te,ty) ->
214        does_not_occur context n nn te && does_not_occur context n nn ty
215     | C.Prod (name,so,dest) ->
216        does_not_occur context n nn so &&
217         does_not_occur((Some (name,(C.Decl so)))::context) (n + 1) (nn + 1)
218          dest
219     | C.Lambda (name,so,dest) ->
220        does_not_occur context n nn so &&
221         does_not_occur((Some (name,(C.Decl so)))::context) (n + 1) (nn + 1)
222          dest
223     | C.LetIn (name,so,dest) ->
224        does_not_occur context n nn so &&
225         does_not_occur ((Some (name,(C.Def (so,None))))::context)
226          (n + 1) (nn + 1) dest
227     | C.Appl l ->
228        List.fold_right (fun x i -> i && does_not_occur context n nn x) l true
229     | C.Var (_,exp_named_subst)
230     | C.Const (_,exp_named_subst)
231     | C.MutInd (_,_,exp_named_subst)
232     | C.MutConstruct (_,_,_,exp_named_subst) ->
233        List.fold_right (fun (_,x) i -> i && does_not_occur context n nn x)
234         exp_named_subst true
235     | C.MutCase (_,_,out,te,pl) ->
236        does_not_occur context n nn out && does_not_occur context n nn te &&
237         List.fold_right (fun x i -> i && does_not_occur context n nn x) pl true
238     | C.Fix (_,fl) ->
239        let len = List.length fl in
240         let n_plus_len = n + len in
241         let nn_plus_len = nn + len in
242         let tys =
243          List.map (fun (n,_,ty,_) -> Some (C.Name n,(Cic.Decl ty))) fl
244         in
245          List.fold_right
246           (fun (_,_,ty,bo) i ->
247             i && does_not_occur context n nn ty &&
248             does_not_occur (tys @ context) n_plus_len nn_plus_len bo
249           ) fl true
250     | C.CoFix (_,fl) ->
251        let len = List.length fl in
252         let n_plus_len = n + len in
253         let nn_plus_len = nn + len in
254         let tys =
255          List.map (fun (n,ty,_) -> Some (C.Name n,(Cic.Decl ty))) fl
256         in
257          List.fold_right
258           (fun (_,ty,bo) i ->
259             i && does_not_occur context n nn ty &&
260             does_not_occur (tys @ context) n_plus_len nn_plus_len bo
261           ) fl true
262
263 (*CSC l'indice x dei tipi induttivi e' t.c. n < x <= nn *)
264 (*CSC questa funzione e' simile alla are_all_occurrences_positive, ma fa *)
265 (*CSC dei controlli leggermente diversi. Viene invocata solamente dalla  *)
266 (*CSC strictly_positive                                                  *)
267 (*CSC definizione (giusta???) tratta dalla mail di Hugo ;-)              *)
268 and weakly_positive context n nn uri te =
269  let module C = Cic in
270 (*CSC: Che schifo! Bisogna capire meglio e trovare una soluzione ragionevole!*)
271   let dummy_mutind =
272    C.MutInd (HelmLibraryObjects.Datatypes.nat_URI,0,[])
273   in
274   (*CSC mettere in cicSubstitution *)
275   let rec subst_inductive_type_with_dummy_mutind =
276    function
277       C.MutInd (uri',0,_) when UriManager.eq uri' uri ->
278        dummy_mutind
279     | C.Appl ((C.MutInd (uri',0,_))::tl) when UriManager.eq uri' uri ->
280        dummy_mutind
281     | C.Cast (te,ty) -> subst_inductive_type_with_dummy_mutind te
282     | C.Prod (name,so,ta) ->
283        C.Prod (name, subst_inductive_type_with_dummy_mutind so,
284         subst_inductive_type_with_dummy_mutind ta)
285     | C.Lambda (name,so,ta) ->
286        C.Lambda (name, subst_inductive_type_with_dummy_mutind so,
287         subst_inductive_type_with_dummy_mutind ta)
288     | C.Appl tl ->
289        C.Appl (List.map subst_inductive_type_with_dummy_mutind tl)
290     | C.MutCase (uri,i,outtype,term,pl) ->
291        C.MutCase (uri,i,
292         subst_inductive_type_with_dummy_mutind outtype,
293         subst_inductive_type_with_dummy_mutind term,
294         List.map subst_inductive_type_with_dummy_mutind pl)
295     | C.Fix (i,fl) ->
296        C.Fix (i,List.map (fun (name,i,ty,bo) -> (name,i,
297         subst_inductive_type_with_dummy_mutind ty,
298         subst_inductive_type_with_dummy_mutind bo)) fl)
299     | C.CoFix (i,fl) ->
300        C.CoFix (i,List.map (fun (name,ty,bo) -> (name,
301         subst_inductive_type_with_dummy_mutind ty,
302         subst_inductive_type_with_dummy_mutind bo)) fl)
303     | C.Const (uri,exp_named_subst) ->
304        let exp_named_subst' =
305         List.map
306          (function (uri,t) -> (uri,subst_inductive_type_with_dummy_mutind t))
307          exp_named_subst
308        in
309         C.Const (uri,exp_named_subst')
310     | C.MutInd (uri,typeno,exp_named_subst) ->
311        let exp_named_subst' =
312         List.map
313          (function (uri,t) -> (uri,subst_inductive_type_with_dummy_mutind t))
314          exp_named_subst
315        in
316         C.MutInd (uri,typeno,exp_named_subst')
317     | C.MutConstruct (uri,typeno,consno,exp_named_subst) ->
318        let exp_named_subst' =
319         List.map
320          (function (uri,t) -> (uri,subst_inductive_type_with_dummy_mutind t))
321          exp_named_subst
322        in
323         C.MutConstruct (uri,typeno,consno,exp_named_subst')
324     | t -> t
325   in
326   match CicReduction.whd context te with
327      C.Appl ((C.MutInd (uri',0,_))::tl) when UriManager.eq uri' uri -> true
328    | C.MutInd (uri',0,_) when UriManager.eq uri' uri -> true
329    | C.Prod (C.Anonymous,source,dest) ->
330       strictly_positive context n nn
331        (subst_inductive_type_with_dummy_mutind source) &&
332        weakly_positive ((Some (C.Anonymous,(C.Decl source)))::context)
333         (n + 1) (nn + 1) uri dest
334    | C.Prod (name,source,dest) when
335       does_not_occur ((Some (name,(C.Decl source)))::context) 0 n dest ->
336        (* dummy abstraction, so we behave as in the anonimous case *)
337        strictly_positive context n nn
338         (subst_inductive_type_with_dummy_mutind source) &&
339         weakly_positive ((Some (name,(C.Decl source)))::context)
340          (n + 1) (nn + 1) uri dest
341    | C.Prod (name,source,dest) ->
342       does_not_occur context n nn
343        (subst_inductive_type_with_dummy_mutind source)&&
344        weakly_positive ((Some (name,(C.Decl source)))::context)
345         (n + 1) (nn + 1) uri dest
346    | _ ->
347      raise (TypeCheckerFailure "Malformed inductive constructor type")
348
349 (* instantiate_parameters ps (x1:T1)...(xn:Tn)C                             *)
350 (* returns ((x_|ps|:T_|ps|)...(xn:Tn)C){ps_1 / x1 ; ... ; ps_|ps| / x_|ps|} *)
351 and instantiate_parameters params c =
352  let module C = Cic in
353   match (c,params) with
354      (c,[]) -> c
355    | (C.Prod (_,_,ta), he::tl) ->
356        instantiate_parameters tl
357         (CicSubstitution.subst he ta)
358    | (C.Cast (te,_), _) -> instantiate_parameters params te
359    | (t,l) -> raise (AssertFailure "1")
360
361 and strictly_positive context n nn te =
362  let module C = Cic in
363  let module U = UriManager in
364   match CicReduction.whd context te with
365      C.Rel _ -> true
366    | C.Cast (te,ty) ->
367       (*CSC: bisogna controllare ty????*)
368       strictly_positive context n nn te
369    | C.Prod (name,so,ta) ->
370       does_not_occur context n nn so &&
371        strictly_positive ((Some (name,(C.Decl so)))::context) (n+1) (nn+1) ta
372    | C.Appl ((C.Rel m)::tl) when m > n && m <= nn ->
373       List.fold_right (fun x i -> i && does_not_occur context n nn x) tl true
374    | C.Appl ((C.MutInd (uri,i,exp_named_subst))::tl) -> 
375       let (ok,paramsno,ity,cl,name) =
376        match CicEnvironment.get_obj uri with
377            C.InductiveDefinition (tl,_,paramsno) ->
378             let (name,_,ity,cl) = List.nth tl i in
379              (List.length tl = 1, paramsno, ity, cl, name)
380          | _ ->
381            raise (TypeCheckerFailure
382             ("Unknown inductive type:" ^ U.string_of_uri uri))
383       in
384        let (params,arguments) = split tl paramsno in
385        let lifted_params = List.map (CicSubstitution.lift 1) params in
386        let cl' =
387         List.map
388          (fun (_,te) ->
389            instantiate_parameters lifted_params
390             (CicSubstitution.subst_vars exp_named_subst te)
391          ) cl
392        in
393         ok &&
394          List.fold_right
395           (fun x i -> i && does_not_occur context n nn x)
396           arguments true &&
397          (*CSC: MEGAPATCH3 (sara' quella giusta?)*)
398          List.fold_right
399           (fun x i ->
400             i &&
401              weakly_positive
402               ((Some (C.Name name,(Cic.Decl ity)))::context) (n+1) (nn+1) uri
403               x
404           ) cl' true
405    | t -> does_not_occur context n nn t
406
407 (*CSC l'indice x dei tipi induttivi e' t.c. n < x <= nn *)
408 and are_all_occurrences_positive context uri indparamsno i n nn te =
409  let module C = Cic in
410   match CicReduction.whd context te with
411      C.Appl ((C.Rel m)::tl) when m = i ->
412       (*CSC: riscrivere fermandosi a 0 *)
413       (* let's check if the inductive type is applied at least to *)
414       (* indparamsno parameters                                   *)
415       let last =
416        List.fold_left
417         (fun k x ->
418           if k = 0 then 0
419           else
420            match CicReduction.whd context x with
421               C.Rel m when m = n - (indparamsno - k) -> k - 1
422             | _ ->
423               raise (TypeCheckerFailure
424                 ("Non-positive occurence in mutual inductive definition(s) " ^
425                 UriManager.string_of_uri uri))
426         ) indparamsno tl
427       in
428        if last = 0 then
429         List.fold_right (fun x i -> i && does_not_occur context n nn x) tl true
430        else
431         raise (TypeCheckerFailure
432           ("Non-positive occurence in mutual inductive definition(s) " ^
433           UriManager.string_of_uri uri))
434    | C.Rel m when m = i ->
435       if indparamsno = 0 then
436        true
437       else
438         raise (TypeCheckerFailure
439           ("Non-positive occurence in mutual inductive definition(s) " ^
440           UriManager.string_of_uri uri))
441    | C.Prod (C.Anonymous,source,dest) ->
442       strictly_positive context n nn source &&
443        are_all_occurrences_positive
444         ((Some (C.Anonymous,(C.Decl source)))::context) uri indparamsno
445         (i+1) (n + 1) (nn + 1) dest
446    | C.Prod (name,source,dest) when
447       does_not_occur ((Some (name,(C.Decl source)))::context) 0 n dest ->
448       (* dummy abstraction, so we behave as in the anonimous case *)
449       strictly_positive context n nn source &&
450        are_all_occurrences_positive
451         ((Some (name,(C.Decl source)))::context) uri indparamsno
452         (i+1) (n + 1) (nn + 1) dest
453    | C.Prod (name,source,dest) ->
454       does_not_occur context n nn source &&
455        are_all_occurrences_positive ((Some (name,(C.Decl source)))::context)
456         uri indparamsno (i+1) (n + 1) (nn + 1) dest
457    | _ ->
458      raise
459       (TypeCheckerFailure ("Malformed inductive constructor type " ^
460         (UriManager.string_of_uri uri)))
461
462 (* Main function to checks the correctness of a mutual *)
463 (* inductive block definition. This is the function    *)
464 (* exported to the proof-engine.                       *)
465 and typecheck_mutual_inductive_defs ~logger uri (itl,_,indparamsno) =
466  let module U = UriManager in
467   (* let's check if the arity of the inductive types are well *)
468   (* formed                                                   *)
469   List.iter (fun (_,_,x,_) -> let _ = type_of ~logger x in ()) itl ;
470
471   (* let's check if the types of the inductive constructors  *)
472   (* are well formed.                                        *)
473   (* In order not to use type_of_aux we put the types of the *)
474   (* mutual inductive types at the head of the types of the  *)
475   (* constructors using Prods                                *)
476   let len = List.length itl in
477    let tys =
478     List.map (fun (n,_,ty,_) -> Some (Cic.Name n,(Cic.Decl ty))) itl in
479    let _ =
480     List.fold_right
481      (fun (_,_,_,cl) i ->
482        List.iter
483         (fun (name,te) -> 
484           let debrujinedte = debrujin_constructor uri len te in
485           let augmented_term =
486            List.fold_right
487             (fun (name,_,ty,_) i -> Cic.Prod (Cic.Name name, ty, i))
488             itl debrujinedte
489           in
490            let _ = type_of augmented_term in
491             (* let's check also the positivity conditions *)
492             if
493              not
494               (are_all_occurrences_positive tys uri indparamsno i 0 len
495                 debrujinedte)
496             then
497              raise
498               (TypeCheckerFailure ("Non positive occurence in " ^
499                 U.string_of_uri uri))
500         ) cl ;
501        (i + 1)
502     ) itl 1
503    in
504     ()
505
506 (* Main function to checks the correctness of a mutual *)
507 (* inductive block definition.                         *)
508 and check_mutual_inductive_defs uri =
509  function
510     Cic.InductiveDefinition (itl, params, indparamsno) ->
511      typecheck_mutual_inductive_defs uri (itl,params,indparamsno)
512   | _ ->
513      raise (TypeCheckerFailure ("Unknown mutual inductive definition:" ^
514       UriManager.string_of_uri uri))
515
516 and type_of_mutual_inductive_defs ~logger uri i =
517  let module C = Cic in
518  let module R = CicReduction in
519  let module U = UriManager in
520   let cobj =
521    match CicEnvironment.is_type_checked ~trust:true uri with
522       CicEnvironment.CheckedObj cobj -> cobj
523     | CicEnvironment.UncheckedObj uobj ->
524        logger#log (`Start_type_checking uri) ;
525        CicUniv.directly_to_env_begin ();
526        check_mutual_inductive_defs ~logger uri uobj ;
527        CicEnvironment.set_type_checking_info uri ;
528        CicUniv.directly_to_env_end ();
529        logger#log (`Type_checking_completed uri) ;
530        (match CicEnvironment.is_type_checked ~trust:false uri with
531           CicEnvironment.CheckedObj cobj -> cobj
532         | CicEnvironment.UncheckedObj _ -> raise CicEnvironmentError
533        )
534   in
535    match cobj with
536       C.InductiveDefinition (dl,_,_) ->
537        let (_,_,arity,_) = List.nth dl i in
538         arity
539     | _ ->
540         raise (TypeCheckerFailure ("Unknown mutual inductive definition:" ^
541           U.string_of_uri uri))
542
543 and type_of_mutual_inductive_constr ~logger uri i j =
544  let module C = Cic in
545  let module R = CicReduction in
546  let module U = UriManager in
547   let cobj =
548    match CicEnvironment.is_type_checked ~trust:true uri with
549       CicEnvironment.CheckedObj cobj -> cobj
550     | CicEnvironment.UncheckedObj uobj ->
551        logger#log (`Start_type_checking uri) ;
552        (*CicUniv.directly_to_env_begin ();*)
553        check_mutual_inductive_defs ~logger uri uobj ;
554        CicEnvironment.set_type_checking_info uri ;
555        (*CicUniv.directly_to_env_end ();*)
556        logger#log (`Type_checking_completed uri) ;
557        (match CicEnvironment.is_type_checked ~trust:false uri with
558           CicEnvironment.CheckedObj cobj -> cobj
559         | CicEnvironment.UncheckedObj _ -> raise CicEnvironmentError
560        )
561   in
562    match cobj with
563       C.InductiveDefinition (dl,_,_) ->
564        let (_,_,_,cl) = List.nth dl i in
565         let (_,ty) = List.nth cl (j-1) in
566          ty
567     | _ ->
568        raise (TypeCheckerFailure ("Unknown mutual inductive definition:" ^
569         UriManager.string_of_uri uri))
570
571 and recursive_args context n nn te =
572  let module C = Cic in
573   match CicReduction.whd context te with
574      C.Rel _ -> []
575    | C.Var _
576    | C.Meta _
577    | C.Sort _
578    | C.Implicit _
579    | C.Cast _ (*CSC ??? *) ->
580       raise (AssertFailure "3") (* due to type-checking *)
581    | C.Prod (name,so,de) ->
582       (not (does_not_occur context n nn so)) ::
583        (recursive_args ((Some (name,(C.Decl so)))::context) (n+1) (nn + 1) de)
584    | C.Lambda _
585    | C.LetIn _ ->
586       raise (AssertFailure "4") (* due to type-checking *)
587    | C.Appl _ -> []
588    | C.Const _ -> raise (AssertFailure "5")
589    | C.MutInd _
590    | C.MutConstruct _
591    | C.MutCase _
592    | C.Fix _
593    | C.CoFix _ -> raise (AssertFailure "6") (* due to type-checking *)
594
595 and get_new_safes ?(subst = []) context p c rl safes n nn x =
596  let module C = Cic in
597  let module U = UriManager in
598  let module R = CicReduction in
599   match (R.whd ~subst context c, R.whd ~subst context p, rl) with
600      (C.Prod (_,so,ta1), C.Lambda (name,_,ta2), b::tl) ->
601        (* we are sure that the two sources are convertible because we *)
602        (* have just checked this. So let's go along ...               *)
603        let safes' =
604         List.map (fun x -> x + 1) safes
605        in
606         let safes'' =
607          if b then 1::safes' else safes'
608         in
609          get_new_safes ~subst ((Some (name,(C.Decl so)))::context)
610           ta2 ta1 tl safes'' (n+1) (nn+1) (x+1)
611    | (C.Prod _, (C.MutConstruct _ as e), _)
612    | (C.Prod _, (C.Rel _ as e), _)
613    | (C.MutInd _, e, [])
614    | (C.Appl _, e, []) -> (e,safes,n,nn,x,context)
615    | (c,p,l) ->
616       (* CSC: If the next exception is raised, it just means that   *)
617       (* CSC: the proof-assistant allows to use very strange things *)
618       (* CSC: as a branch of a case whose type is a Prod. In        *)
619       (* CSC: particular, this means that a new (C.Prod, x,_) case  *)
620       (* CSC: must be considered in this match. (e.g. x = MutCase)  *)
621       raise
622        (AssertFailure
623          (Printf.sprintf "Get New Safes: c=%s ; p=%s"
624            (CicPp.ppterm c) (CicPp.ppterm p)))
625
626 and split_prods ?(subst = []) context n te =
627  let module C = Cic in
628  let module R = CicReduction in
629   match (n, R.whd context te) with
630      (0, _) -> context,te
631    | (n, C.Prod (name,so,ta)) when n > 0 ->
632        split_prods ~subst ((Some (name,(C.Decl so)))::context) (n - 1) ta
633    | (_, _) -> raise (AssertFailure "8")
634
635 and eat_lambdas ?(subst = []) context n te =
636  let module C = Cic in
637  let module R = CicReduction in
638   match (n, R.whd ~subst context te) with
639      (0, _) -> (te, 0, context)
640    | (n, C.Lambda (name,so,ta)) when n > 0 ->
641       let (te, k, context') =
642        eat_lambdas ~subst ((Some (name,(C.Decl so)))::context) (n - 1) ta
643       in
644        (te, k + 1, context')
645    | (n, te) ->
646        raise (AssertFailure (sprintf "9 (%d, %s)" n (CicPp.ppterm te)))
647
648 (*CSC: Tutto quello che segue e' l'intuzione di luca ;-) *) 
649 and check_is_really_smaller_arg ?(subst = []) context n nn kl x safes te =
650  (*CSC: forse la whd si puo' fare solo quando serve veramente. *)
651  (*CSC: cfr guarded_by_destructors                             *)
652  let module C = Cic in
653  let module U = UriManager in
654  match CicReduction.whd context te with
655      C.Rel m when List.mem m safes -> true
656    | C.Rel _ -> false
657    | C.Var _
658    | C.Meta _
659    | C.Sort _
660    | C.Implicit _
661    | C.Cast _
662 (*   | C.Cast (te,ty) ->
663       check_is_really_smaller_arg ~subst n nn kl x safes te &&
664        check_is_really_smaller_arg ~subst n nn kl x safes ty*)
665 (*   | C.Prod (_,so,ta) ->
666       check_is_really_smaller_arg ~subst n nn kl x safes so &&
667        check_is_really_smaller_arg ~subst (n+1) (nn+1) kl (x+1)
668         (List.map (fun x -> x + 1) safes) ta*)
669    | C.Prod _ -> raise (AssertFailure "10")
670    | C.Lambda (name,so,ta) ->
671       check_is_really_smaller_arg ~subst context n nn kl x safes so &&
672        check_is_really_smaller_arg ~subst ((Some (name,(C.Decl so)))::context)
673         (n+1) (nn+1) kl (x+1) (List.map (fun x -> x + 1) safes) ta
674    | C.LetIn (name,so,ta) ->
675       check_is_really_smaller_arg ~subst context n nn kl x safes so &&
676        check_is_really_smaller_arg ~subst ((Some (name,(C.Def (so,None))))::context)
677         (n+1) (nn+1) kl (x+1) (List.map (fun x -> x + 1) safes) ta
678    | C.Appl (he::_) ->
679       (*CSC: sulla coda ci vogliono dei controlli? secondo noi no, ma *)
680       (*CSC: solo perche' non abbiamo trovato controesempi            *)
681       check_is_really_smaller_arg ~subst context n nn kl x safes he
682    | C.Appl [] -> raise (AssertFailure "11")
683    | C.Const _
684    | C.MutInd _ -> raise (AssertFailure "12")
685    | C.MutConstruct _ -> false
686    | C.MutCase (uri,i,outtype,term,pl) ->
687       (match term with
688           C.Rel m when List.mem m safes || m = x ->
689            let (tys,len,isinductive,paramsno,cl) =
690             match CicEnvironment.get_obj uri with
691                C.InductiveDefinition (tl,_,paramsno) ->
692                 let tys =
693                  List.map
694                   (fun (n,_,ty,_) -> Some (Cic.Name n,(Cic.Decl ty))) tl
695                 in
696                  let (_,isinductive,_,cl) = List.nth tl i in
697                   let cl' =
698                    List.map
699                     (fun (id,ty) ->
700                       (id, snd (split_prods ~subst tys paramsno ty))) cl
701                   in
702                    (tys,List.length tl,isinductive,paramsno,cl')
703              | _ ->
704                 raise (TypeCheckerFailure
705                   ("Unknown mutual inductive definition:" ^
706                   UriManager.string_of_uri uri))
707            in
708             if not isinductive then
709               List.fold_right
710                (fun p i ->
711                  i && check_is_really_smaller_arg ~subst context n nn kl x safes p)
712                pl true
713             else
714               List.fold_right
715                (fun (p,(_,c)) i ->
716                  let rl' =
717                   let debrujinedte = debrujin_constructor uri len c in
718                    recursive_args tys 0 len debrujinedte
719                  in
720                   let (e,safes',n',nn',x',context') =
721                    get_new_safes ~subst context p c rl' safes n nn x
722                   in
723                    i &&
724                    check_is_really_smaller_arg ~subst context' n' nn' kl x' safes' e
725                ) (List.combine pl cl) true
726         | C.Appl ((C.Rel m)::tl) when List.mem m safes || m = x ->
727            let (tys,len,isinductive,paramsno,cl) =
728             match CicEnvironment.get_obj uri with
729                C.InductiveDefinition (tl,_,paramsno) ->
730                 let (_,isinductive,_,cl) = List.nth tl i in
731                  let tys =
732                   List.map (fun (n,_,ty,_) ->
733                    Some(Cic.Name n,(Cic.Decl ty))) tl
734                  in
735                   let cl' =
736                    List.map
737                     (fun (id,ty) ->
738                       (id, snd (split_prods ~subst tys paramsno ty))) cl
739                   in
740                    (tys,List.length tl,isinductive,paramsno,cl')
741              | _ ->
742                 raise (TypeCheckerFailure
743                   ("Unknown mutual inductive definition:" ^
744                   UriManager.string_of_uri uri))
745            in
746             if not isinductive then
747               List.fold_right
748                (fun p i ->
749                  i && check_is_really_smaller_arg ~subst context n nn kl x safes p)
750                pl true
751             else
752               (*CSC: supponiamo come prima che nessun controllo sia necessario*)
753               (*CSC: sugli argomenti di una applicazione                      *)
754               List.fold_right
755                (fun (p,(_,c)) i ->
756                  let rl' =
757                   let debrujinedte = debrujin_constructor uri len c in
758                    recursive_args tys 0 len debrujinedte
759                  in
760                   let (e, safes',n',nn',x',context') =
761                    get_new_safes context p c rl' safes n nn x
762                   in
763                    i &&
764                    check_is_really_smaller_arg ~subst context' n' nn' kl x' safes' e
765                ) (List.combine pl cl) true
766         | _ ->
767           List.fold_right
768            (fun p i ->
769              i && check_is_really_smaller_arg ~subst context n nn kl x safes p
770            ) pl true
771       )
772    | C.Fix (_, fl) ->
773       let len = List.length fl in
774        let n_plus_len = n + len
775        and nn_plus_len = nn + len
776        and x_plus_len = x + len
777        and tys = List.map (fun (n,_,ty,_) -> Some (C.Name n,(C.Decl ty))) fl
778        and safes' = List.map (fun x -> x + len) safes in
779         List.fold_right
780          (fun (_,_,ty,bo) i ->
781            i &&
782             check_is_really_smaller_arg ~subst (tys@context) n_plus_len nn_plus_len kl
783              x_plus_len safes' bo
784          ) fl true
785    | C.CoFix (_, fl) ->
786       let len = List.length fl in
787        let n_plus_len = n + len
788        and nn_plus_len = nn + len
789        and x_plus_len = x + len
790        and tys = List.map (fun (n,ty,_) -> Some (C.Name n,(C.Decl ty))) fl
791        and safes' = List.map (fun x -> x + len) safes in
792         List.fold_right
793          (fun (_,ty,bo) i ->
794            i &&
795             check_is_really_smaller_arg ~subst (tys@context) n_plus_len nn_plus_len kl
796              x_plus_len safes' bo
797          ) fl true
798
799 and guarded_by_destructors ?(subst = []) context n nn kl x safes =
800  let module C = Cic in
801  let module U = UriManager in
802   function
803      C.Rel m when m > n && m <= nn -> false
804    | C.Rel m ->
805       (match List.nth context (n-1) with
806           Some (_,C.Decl _) -> true
807         | Some (_,C.Def (bo,_)) ->
808            guarded_by_destructors context m nn kl x safes
809             (CicSubstitution.lift m bo)
810         | None -> raise (TypeCheckerFailure "Reference to deleted hypothesis")
811       )
812    | C.Meta _
813    | C.Sort _
814    | C.Implicit _ -> true
815    | C.Cast (te,ty) ->
816       guarded_by_destructors context n nn kl x safes te &&
817        guarded_by_destructors context n nn kl x safes ty
818    | C.Prod (name,so,ta) ->
819       guarded_by_destructors context n nn kl x safes so &&
820        guarded_by_destructors ((Some (name,(C.Decl so)))::context)
821         (n+1) (nn+1) kl (x+1) (List.map (fun x -> x + 1) safes) ta
822    | C.Lambda (name,so,ta) ->
823       guarded_by_destructors context n nn kl x safes so &&
824        guarded_by_destructors ((Some (name,(C.Decl so)))::context)
825         (n+1) (nn+1) kl (x+1) (List.map (fun x -> x + 1) safes) ta
826    | C.LetIn (name,so,ta) ->
827       guarded_by_destructors context n nn kl x safes so &&
828        guarded_by_destructors ((Some (name,(C.Def (so,None))))::context)
829         (n+1) (nn+1) kl (x+1) (List.map (fun x -> x + 1) safes) ta
830    | C.Appl ((C.Rel m)::tl) when m > n && m <= nn ->
831       let k = List.nth kl (m - n - 1) in
832        if not (List.length tl > k) then false
833        else
834         List.fold_right
835          (fun param i ->
836            i && guarded_by_destructors context n nn kl x safes param
837          ) tl true &&
838          check_is_really_smaller_arg ~subst context n nn kl x safes (List.nth tl k)
839    | C.Appl tl ->
840       List.fold_right
841        (fun t i -> i && guarded_by_destructors context n nn kl x safes t)
842        tl true
843    | C.Var (_,exp_named_subst)
844    | C.Const (_,exp_named_subst)
845    | C.MutInd (_,_,exp_named_subst)
846    | C.MutConstruct (_,_,_,exp_named_subst) ->
847       List.fold_right
848        (fun (_,t) i -> i && guarded_by_destructors context n nn kl x safes t)
849        exp_named_subst true
850    | C.MutCase (uri,i,outtype,term,pl) ->
851       (match term with
852           C.Rel m when List.mem m safes || m = x ->
853            let (tys,len,isinductive,paramsno,cl) =
854             match CicEnvironment.get_obj uri with
855                C.InductiveDefinition (tl,_,paramsno) ->
856                 let len = List.length tl in
857                  let (_,isinductive,_,cl) = List.nth tl i in
858                   let tys =
859                    List.map (fun (n,_,ty,_) ->
860                     Some(Cic.Name n,(Cic.Decl ty))) tl
861                   in
862                    let cl' =
863                     List.map
864                      (fun (id,ty) ->
865                       let debrujinedty = debrujin_constructor uri len ty in
866                        (id, snd (split_prods ~subst tys paramsno ty),
867                         snd (split_prods ~subst tys paramsno debrujinedty)
868                        )) cl
869                    in
870                     (tys,len,isinductive,paramsno,cl')
871              | _ ->
872                 raise (TypeCheckerFailure
873                   ("Unknown mutual inductive definition:" ^
874                   UriManager.string_of_uri uri))
875            in
876             if not isinductive then
877              guarded_by_destructors context n nn kl x safes outtype &&
878               guarded_by_destructors context n nn kl x safes term &&
879               (*CSC: manca ??? il controllo sul tipo di term? *)
880               List.fold_right
881                (fun p i ->
882                  i && guarded_by_destructors context n nn kl x safes p)
883                pl true
884             else
885              guarded_by_destructors context n nn kl x safes outtype &&
886               (*CSC: manca ??? il controllo sul tipo di term? *)
887               List.fold_right
888                (fun (p,(_,c,brujinedc)) i ->
889                  let rl' = recursive_args tys 0 len brujinedc in
890                   let (e,safes',n',nn',x',context') =
891                    get_new_safes context p c rl' safes n nn x
892                   in
893                    i &&
894                    guarded_by_destructors context' n' nn' kl x' safes' e
895                ) (List.combine pl cl) true
896         | C.Appl ((C.Rel m)::tl) when List.mem m safes || m = x ->
897            let (tys,len,isinductive,paramsno,cl) =
898             match CicEnvironment.get_obj uri with
899                C.InductiveDefinition (tl,_,paramsno) ->
900                 let (_,isinductive,_,cl) = List.nth tl i in
901                  let tys =
902                   List.map
903                    (fun (n,_,ty,_) -> Some(Cic.Name n,(Cic.Decl ty))) tl
904                  in
905                   let cl' =
906                    List.map
907                     (fun (id,ty) ->
908                       (id, snd (split_prods ~subst tys paramsno ty))) cl
909                   in
910                    (tys,List.length tl,isinductive,paramsno,cl')
911              | _ ->
912                 raise (TypeCheckerFailure
913                   ("Unknown mutual inductive definition:" ^
914                   UriManager.string_of_uri uri))
915            in
916             if not isinductive then
917              guarded_by_destructors context n nn kl x safes outtype &&
918               guarded_by_destructors context n nn kl x safes term &&
919               (*CSC: manca ??? il controllo sul tipo di term? *)
920               List.fold_right
921                (fun p i ->
922                  i && guarded_by_destructors context n nn kl x safes p)
923                pl true
924             else
925              guarded_by_destructors context n nn kl x safes outtype &&
926               (*CSC: manca ??? il controllo sul tipo di term? *)
927               List.fold_right
928                (fun t i ->
929                  i && guarded_by_destructors context n nn kl x safes t)
930                tl true &&
931               List.fold_right
932                (fun (p,(_,c)) i ->
933                  let rl' =
934                   let debrujinedte = debrujin_constructor uri len c in
935                    recursive_args tys 0 len debrujinedte
936                  in
937                   let (e, safes',n',nn',x',context') =
938                    get_new_safes context p c rl' safes n nn x
939                   in
940                    i &&
941                    guarded_by_destructors context' n' nn' kl x' safes' e
942                ) (List.combine pl cl) true
943         | _ ->
944           guarded_by_destructors context n nn kl x safes outtype &&
945            guarded_by_destructors context n nn kl x safes term &&
946            (*CSC: manca ??? il controllo sul tipo di term? *)
947            List.fold_right
948             (fun p i -> i && guarded_by_destructors context n nn kl x safes p)
949             pl true
950       )
951    | C.Fix (_, fl) ->
952       let len = List.length fl in
953        let n_plus_len = n + len
954        and nn_plus_len = nn + len
955        and x_plus_len = x + len
956        and tys = List.map (fun (n,_,ty,_) -> Some (C.Name n,(C.Decl ty))) fl
957        and safes' = List.map (fun x -> x + len) safes in
958         List.fold_right
959          (fun (_,_,ty,bo) i ->
960            i && guarded_by_destructors context n nn kl x_plus_len safes' ty &&
961             guarded_by_destructors (tys@context) n_plus_len nn_plus_len kl
962              x_plus_len safes' bo
963          ) fl true
964    | C.CoFix (_, fl) ->
965       let len = List.length fl in
966        let n_plus_len = n + len
967        and nn_plus_len = nn + len
968        and x_plus_len = x + len
969        and tys = List.map (fun (n,ty,_) -> Some (C.Name n,(C.Decl ty))) fl
970        and safes' = List.map (fun x -> x + len) safes in
971         List.fold_right
972          (fun (_,ty,bo) i ->
973            i &&
974             guarded_by_destructors context n nn kl x_plus_len safes' ty &&
975             guarded_by_destructors (tys@context) n_plus_len nn_plus_len kl
976              x_plus_len safes' bo
977          ) fl true
978
979 (* the boolean h means already protected *)
980 (* args is the list of arguments the type of the constructor that may be *)
981 (* found in head position must be applied to.                            *)
982 (*CSC: coInductiveTypeURI non cambia mai di ricorsione in ricorsione *)
983 and guarded_by_constructors context n nn h te args coInductiveTypeURI =
984  let module C = Cic in
985   (*CSC: There is a lot of code replication between the cases X and    *)
986   (*CSC: (C.Appl X tl). Maybe it will be better to define a function   *)
987   (*CSC: that maps X into (C.Appl X []) when X is not already a C.Appl *)
988   match CicReduction.whd context te with
989      C.Rel m when m > n && m <= nn -> h
990    | C.Rel _ -> true
991    | C.Meta _
992    | C.Sort _
993    | C.Implicit _
994    | C.Cast _
995    | C.Prod _
996    | C.LetIn _ ->
997       (* the term has just been type-checked *)
998       raise (AssertFailure "17")
999    | C.Lambda (name,so,de) ->
1000       does_not_occur context n nn so &&
1001        guarded_by_constructors ((Some (name,(C.Decl so)))::context)
1002         (n + 1) (nn + 1) h de args coInductiveTypeURI
1003    | C.Appl ((C.Rel m)::tl) when m > n && m <= nn ->
1004       h &&
1005        List.fold_right (fun x i -> i && does_not_occur context n nn x) tl true
1006    | C.Appl ((C.MutConstruct (uri,i,j,exp_named_subst))::tl) ->
1007       let consty =
1008        match CicEnvironment.get_cooked_obj ~trust:false uri with
1009           C.InductiveDefinition (itl,_,_) ->
1010            let (_,_,_,cl) = List.nth itl i in
1011             let (_,cons) = List.nth cl (j - 1) in
1012              CicSubstitution.subst_vars exp_named_subst cons
1013         | _ ->
1014             raise (TypeCheckerFailure ("Unknown mutual inductive definition:" ^
1015               UriManager.string_of_uri uri))
1016       in
1017        let rec analyse_branch context ty te =
1018         match CicReduction.whd context ty with
1019            C.Meta _ -> raise (AssertFailure "34")
1020          | C.Rel _
1021          | C.Var _
1022          | C.Sort _ ->
1023             does_not_occur context n nn te
1024          | C.Implicit _
1025          | C.Cast _ ->
1026             raise (AssertFailure "24")(* due to type-checking *)
1027          | C.Prod (name,so,de) ->
1028             analyse_branch ((Some (name,(C.Decl so)))::context) de te
1029          | C.Lambda _
1030          | C.LetIn _ ->
1031             raise (AssertFailure "25")(* due to type-checking *)
1032          | C.Appl ((C.MutInd (uri,_,_))::_) as ty
1033             when uri == coInductiveTypeURI -> 
1034              guarded_by_constructors context n nn true te [] coInductiveTypeURI
1035          | C.Appl ((C.MutInd (uri,_,_))::_) as ty -> 
1036             guarded_by_constructors context n nn true te tl coInductiveTypeURI
1037          | C.Appl _ ->
1038             does_not_occur context n nn te
1039          | C.Const _ -> raise (AssertFailure "26")
1040          | C.MutInd (uri,_,_) when uri == coInductiveTypeURI ->
1041             guarded_by_constructors context n nn true te [] coInductiveTypeURI
1042          | C.MutInd _ ->
1043             does_not_occur context n nn te
1044          | C.MutConstruct _ -> raise (AssertFailure "27")
1045          (*CSC: we do not consider backbones with a MutCase, Fix, Cofix *)
1046          (*CSC: in head position.                                       *)
1047          | C.MutCase _
1048          | C.Fix _
1049          | C.CoFix _ ->
1050             raise (AssertFailure "28")(* due to type-checking *)
1051        in
1052        let rec analyse_instantiated_type context ty l =
1053         match CicReduction.whd context ty with
1054            C.Rel _
1055          | C.Var _
1056          | C.Meta _
1057          | C.Sort _
1058          | C.Implicit _
1059          | C.Cast _ -> raise (AssertFailure "29")(* due to type-checking *)
1060          | C.Prod (name,so,de) ->
1061             begin
1062              match l with
1063                 [] -> true
1064               | he::tl ->
1065                  analyse_branch context so he &&
1066                   analyse_instantiated_type
1067                    ((Some (name,(C.Decl so)))::context) de tl
1068             end
1069          | C.Lambda _
1070          | C.LetIn _ ->
1071             raise (AssertFailure "30")(* due to type-checking *)
1072          | C.Appl _ -> 
1073             List.fold_left
1074              (fun i x -> i && does_not_occur context n nn x) true l
1075          | C.Const _ -> raise (AssertFailure "31")
1076          | C.MutInd _ ->
1077             List.fold_left
1078              (fun i x -> i && does_not_occur context n nn x) true l
1079          | C.MutConstruct _ -> raise (AssertFailure "32")
1080          (*CSC: we do not consider backbones with a MutCase, Fix, Cofix *)
1081          (*CSC: in head position.                                       *)
1082          | C.MutCase _
1083          | C.Fix _
1084          | C.CoFix _ ->
1085             raise (AssertFailure "33")(* due to type-checking *)
1086        in
1087         let rec instantiate_type args consty =
1088          function
1089             [] -> true
1090           | tlhe::tltl as l ->
1091              let consty' = CicReduction.whd context consty in
1092               match args with 
1093                  he::tl ->
1094                   begin
1095                    match consty' with
1096                       C.Prod (_,_,de) ->
1097                        let instantiated_de = CicSubstitution.subst he de in
1098                         (*CSC: siamo sicuri che non sia troppo forte? *)
1099                         does_not_occur context n nn tlhe &
1100                          instantiate_type tl instantiated_de tltl
1101                     | _ ->
1102                       (*CSC:We do not consider backbones with a MutCase, a    *)
1103                       (*CSC:FixPoint, a CoFixPoint and so on in head position.*)
1104                       raise (AssertFailure "23")
1105                   end
1106                | [] -> analyse_instantiated_type context consty' l
1107                   (* These are all the other cases *)
1108        in
1109         instantiate_type args consty tl
1110    | C.Appl ((C.CoFix (_,fl))::tl) ->
1111       List.fold_left (fun i x -> i && does_not_occur context n nn x) true tl &&
1112        let len = List.length fl in
1113         let n_plus_len = n + len
1114         and nn_plus_len = nn + len
1115         (*CSC: Is a Decl of the ty ok or should I use Def of a Fix? *)
1116         and tys = List.map (fun (n,ty,_) -> Some (C.Name n,(C.Decl ty))) fl in
1117          List.fold_right
1118           (fun (_,ty,bo) i ->
1119             i && does_not_occur context n nn ty &&
1120              guarded_by_constructors (tys@context) n_plus_len nn_plus_len h bo
1121               args coInductiveTypeURI
1122           ) fl true
1123    | C.Appl ((C.MutCase (_,_,out,te,pl))::tl) ->
1124        List.fold_left (fun i x -> i && does_not_occur context n nn x) true tl &&
1125         does_not_occur context n nn out &&
1126          does_not_occur context n nn te &&
1127           List.fold_right
1128            (fun x i ->
1129              i &&
1130              guarded_by_constructors context n nn h x args coInductiveTypeURI
1131            ) pl true
1132    | C.Appl l ->
1133       List.fold_right (fun x i -> i && does_not_occur context n nn x) l true
1134    | C.Var (_,exp_named_subst)
1135    | C.Const (_,exp_named_subst) ->
1136       List.fold_right
1137        (fun (_,x) i -> i && does_not_occur context n nn x) exp_named_subst true
1138    | C.MutInd _ -> assert false
1139    | C.MutConstruct (_,_,_,exp_named_subst) ->
1140       List.fold_right
1141        (fun (_,x) i -> i && does_not_occur context n nn x) exp_named_subst true
1142    | C.MutCase (_,_,out,te,pl) ->
1143        does_not_occur context n nn out &&
1144         does_not_occur context n nn te &&
1145          List.fold_right
1146           (fun x i ->
1147             i &&
1148              guarded_by_constructors context n nn h x args coInductiveTypeURI
1149           ) pl true
1150    | C.Fix (_,fl) ->
1151       let len = List.length fl in
1152        let n_plus_len = n + len
1153        and nn_plus_len = nn + len
1154        (*CSC: Is a Decl of the ty ok or should I use Def of a Fix? *)
1155        and tys = List.map (fun (n,_,ty,_)-> Some (C.Name n,(C.Decl ty))) fl in
1156         List.fold_right
1157          (fun (_,_,ty,bo) i ->
1158            i && does_not_occur context n nn ty &&
1159             does_not_occur (tys@context) n_plus_len nn_plus_len bo
1160          ) fl true
1161    | C.CoFix (_,fl) ->
1162       let len = List.length fl in
1163        let n_plus_len = n + len
1164        and nn_plus_len = nn + len
1165        (*CSC: Is a Decl of the ty ok or should I use Def of a Fix? *)
1166        and tys = List.map (fun (n,ty,_) -> Some (C.Name n,(C.Decl ty))) fl in
1167         List.fold_right
1168          (fun (_,ty,bo) i ->
1169            i && does_not_occur context n nn ty &&
1170             guarded_by_constructors (tys@context) n_plus_len nn_plus_len h bo
1171              args coInductiveTypeURI
1172          ) fl true
1173
1174 and check_allowed_sort_elimination ~logger context uri i need_dummy ind arity1 arity2 =
1175  let module C = Cic in
1176  let module U = UriManager in
1177   match (CicReduction.whd context arity1, CicReduction.whd context arity2) with
1178      (C.Prod (_,so1,de1), C.Prod (_,so2,de2))
1179       when CicReduction.are_convertible context so1 so2 ->
1180        check_allowed_sort_elimination ~logger context uri i need_dummy
1181         (C.Appl [CicSubstitution.lift 1 ind ; C.Rel 1]) de1 de2
1182    | (C.Sort C.Prop, C.Sort C.Prop) when need_dummy -> true
1183    | (C.Sort C.Prop, C.Sort C.Set)
1184    | (C.Sort C.Prop, C.Sort C.CProp)
1185    | (C.Sort C.Prop, C.Sort (C.Type _) ) when need_dummy ->
1186    (* TASSI: da verificare *)
1187 (*CSC: WRONG. MISSING CONDITIONS ON THE ARGUMENTS OF THE CONSTRUTOR *)
1188        (match CicEnvironment.get_obj uri with
1189            C.InductiveDefinition (itl,_,_) ->
1190             let (_,_,_,cl) = List.nth itl i in
1191              (* is a singleton definition or the empty proposition? *)
1192              List.length cl = 1 || List.length cl = 0
1193          | _ ->
1194             raise (TypeCheckerFailure ("Unknown mutual inductive definition:" ^
1195               UriManager.string_of_uri uri))
1196        )
1197    | (C.Sort C.Set, C.Sort C.Prop) when need_dummy -> true
1198    | (C.Sort C.CProp, C.Sort C.Prop) when need_dummy -> true
1199    | (C.Sort C.Set, C.Sort C.Set) when need_dummy -> true
1200    | (C.Sort C.Set, C.Sort C.CProp) when need_dummy -> true
1201    | (C.Sort C.CProp, C.Sort C.Set) when need_dummy -> true
1202    | (C.Sort C.CProp, C.Sort C.CProp) when need_dummy -> true
1203    | ((C.Sort C.Set, C.Sort (C.Type _)) | (C.Sort C.CProp, C.Sort (C.Type _)))
1204       (* TASSI: da verificare *)
1205       when need_dummy ->
1206        (match CicEnvironment.get_obj uri with
1207            C.InductiveDefinition (itl,_,paramsno) ->
1208             let tys =
1209              List.map (fun (n,_,ty,_) -> Some (Cic.Name n,(Cic.Decl ty))) itl
1210             in
1211              let (_,_,_,cl) = List.nth itl i in
1212               List.fold_right
1213                (fun (_,x) i -> i && is_small ~logger tys paramsno x) cl true
1214          | _ ->
1215             raise (TypeCheckerFailure ("Unknown mutual inductive definition:" ^
1216               UriManager.string_of_uri uri))
1217        )
1218    | (C.Sort (C.Type _), C.Sort _) when need_dummy -> true
1219      (* TASSI: da verificare *)
1220    | (C.Sort C.Prop, C.Prod (name,so,ta)) when not need_dummy ->
1221        let res = CicReduction.are_convertible context so ind
1222        in
1223         res &&
1224         (match CicReduction.whd ((Some (name,(C.Decl so)))::context) ta with
1225             C.Sort C.Prop -> true
1226           | (C.Sort C.Set | C.Sort C.CProp) ->
1227              (match CicEnvironment.get_obj uri with
1228                  C.InductiveDefinition (itl,_,_) ->
1229                   let (_,_,_,cl) = List.nth itl i in
1230                    (* is a singleton definition? *)
1231                    List.length cl = 1
1232                | _ ->
1233                   raise (TypeCheckerFailure
1234                     ("Unknown mutual inductive definition:" ^
1235                     UriManager.string_of_uri uri))
1236              )
1237           | _ -> false
1238         )
1239    | ((C.Sort C.Set, C.Prod (name,so,ta)) | (C.Sort C.CProp, C.Prod (name,so,ta)))
1240       when not need_dummy ->
1241        let res = CicReduction.are_convertible context so ind
1242        in
1243         res &&
1244         (match CicReduction.whd ((Some (name,(C.Decl so)))::context) ta with
1245             C.Sort C.Prop
1246           | C.Sort C.Set  -> true
1247           | C.Sort C.CProp -> true
1248           | C.Sort (C.Type _) ->
1249             (* TASSI: da verificare *)
1250              (match CicEnvironment.get_obj uri with
1251                  C.InductiveDefinition (itl,_,paramsno) ->
1252                   let (_,_,_,cl) = List.nth itl i in
1253                    let tys =
1254                     List.map
1255                      (fun (n,_,ty,_) -> Some (Cic.Name n,(Cic.Decl ty))) itl
1256                    in
1257                     List.fold_right
1258                      (fun (_,x) i -> i && is_small ~logger tys paramsno x) cl true
1259                | _ ->
1260                   raise (TypeCheckerFailure
1261                     ("Unknown mutual inductive definition:" ^
1262                     UriManager.string_of_uri uri))
1263              )
1264           | _ -> raise (AssertFailure "19")
1265         )
1266    | (C.Sort (C.Type _), C.Prod (_,so,_)) when not need_dummy ->
1267      (* TASSI: da verificare *)
1268        CicReduction.are_convertible context so ind
1269    | (_,_) -> false
1270   
1271 and type_of_branch context argsno need_dummy outtype term constype =
1272  let module C = Cic in
1273  let module R = CicReduction in
1274   match R.whd context constype with
1275      C.MutInd (_,_,_) ->
1276       if need_dummy then
1277        outtype
1278       else
1279        C.Appl [outtype ; term]
1280    | C.Appl (C.MutInd (_,_,_)::tl) ->
1281       let (_,arguments) = split tl argsno
1282       in
1283        if need_dummy && arguments = [] then
1284         outtype
1285        else
1286         C.Appl (outtype::arguments@(if need_dummy then [] else [term]))
1287    | C.Prod (name,so,de) ->
1288       let term' =
1289        match CicSubstitution.lift 1 term with
1290           C.Appl l -> C.Appl (l@[C.Rel 1])
1291         | t -> C.Appl [t ; C.Rel 1]
1292       in
1293        C.Prod (C.Anonymous,so,type_of_branch
1294         ((Some (name,(C.Decl so)))::context) argsno need_dummy
1295         (CicSubstitution.lift 1 outtype) term' de)
1296   | _ -> raise (AssertFailure "20")
1297
1298 (* check_metasenv_consistency checks that the "canonical" context of a
1299 metavariable is consitent - up to relocation via the relocation list l -
1300 with the actual context *)
1301
1302 and check_metasenv_consistency ~logger ?(subst=[]) metasenv context
1303   canonical_context l
1304 =
1305   let module C = Cic in
1306   let module R = CicReduction in
1307   let module S = CicSubstitution in
1308     let lifted_canonical_context = 
1309     let rec aux i =
1310      function
1311         [] -> []
1312       | (Some (n,C.Decl t))::tl ->
1313          (Some (n,C.Decl (S.lift_meta l (S.lift i t))))::(aux (i+1) tl)
1314       | (Some (n,C.Def (t,None)))::tl ->
1315          (Some (n,C.Def ((S.lift_meta l (S.lift i t)),None)))::(aux (i+1) tl)
1316       | None::tl -> None::(aux (i+1) tl)
1317       | (Some (n,C.Def (t,Some ty)))::tl ->
1318          (Some (n,C.Def ((S.lift_meta l (S.lift i t)),Some (S.lift_meta l (S.lift i ty)))))::(aux (i+1) tl)
1319     in
1320      aux 1 canonical_context 
1321    in
1322     List.iter2 
1323      (fun t ct -> 
1324         match (t,ct) with
1325          | _,None -> ()
1326          | Some t,Some (_,C.Def (ct,_)) ->
1327             if not (R.are_convertible ~subst ~metasenv context t ct) then
1328               raise (TypeCheckerFailure (sprintf
1329                 "Not well typed metavariable local context: expected a term convertible with %s, found %s"
1330                 (CicPp.ppterm ct) (CicPp.ppterm t)))
1331          | Some t,Some (_,C.Decl ct) ->
1332              let type_t = type_of_aux' ~logger ~subst metasenv context t in
1333              if not (R.are_convertible ~subst ~metasenv context type_t ct) then
1334                (* debug *)
1335               raise (TypeCheckerFailure (sprintf
1336                 "Not well typed metavariable local context: expected a term of type %s, found %s of type %s"
1337                 (CicPp.ppterm ct) (CicPp.ppterm t) (CicPp.ppterm type_t)))
1338          | None, _  ->
1339              raise (TypeCheckerFailure
1340               "Not well typed metavariable local context: an hypothesis, that is not hidden, is not instantiated")
1341      ) l lifted_canonical_context 
1342
1343 (* type_of_aux' is just another name (with a different scope) for type_of_aux *)
1344 and type_of_aux' ~logger ?(subst = []) metasenv context t =
1345  let rec type_of_aux ~logger context =
1346   let module C = Cic in
1347   let module R = CicReduction in
1348   let module S = CicSubstitution in
1349   let module U = UriManager in
1350    function
1351       C.Rel n ->
1352        (try
1353          match List.nth context (n - 1) with
1354             Some (_,C.Decl t) -> S.lift n t
1355           | Some (_,C.Def (_,Some ty)) -> S.lift n ty
1356           | Some (_,C.Def (bo,None)) ->
1357              debug_print "##### CASO DA INVESTIGARE E CAPIRE" ;
1358              type_of_aux ~logger context (S.lift n bo)
1359           | None -> raise (TypeCheckerFailure "Reference to deleted hypothesis")
1360         with
1361         _ ->
1362           raise (TypeCheckerFailure "unbound variable")
1363        )
1364     | C.Var (uri,exp_named_subst) ->
1365       incr fdebug ;
1366       check_exp_named_subst ~logger ~subst context exp_named_subst ;
1367       let ty =
1368        CicSubstitution.subst_vars exp_named_subst (type_of_variable ~logger uri)
1369       in
1370        decr fdebug ;
1371        ty
1372     | C.Meta (n,l) -> 
1373        (try
1374           let (canonical_context,term,ty) = CicUtil.lookup_subst n subst in
1375           check_metasenv_consistency  ~logger
1376             ~subst metasenv context canonical_context l;
1377           (* assuming subst is well typed !!!!! *)
1378           CicSubstitution.lift_meta l ty
1379           (* type_of_aux context (CicSubstitution.lift_meta l term) *)
1380         with CicUtil.Subst_not_found _ ->
1381           let (_,canonical_context,ty) = CicUtil.lookup_meta n metasenv in
1382           check_metasenv_consistency ~logger
1383              ~subst metasenv context canonical_context l;
1384           CicSubstitution.lift_meta l ty)
1385       (* TASSI: CONSTRAINTS *)
1386     | C.Sort (C.Type t) -> 
1387        let t' = CicUniv.fresh() in
1388         if not (CicUniv.add_gt t' t ) then
1389           assert false (* t' is fresh! an error in CicUniv *)
1390         else
1391           C.Sort (C.Type t')
1392       (* TASSI: CONSTRAINTS *)
1393     | C.Sort s -> C.Sort (C.Type (CicUniv.fresh ()))
1394     | C.Implicit _ -> raise (AssertFailure "21")
1395     | C.Cast (te,ty) as t ->
1396        let _ = type_of_aux ~logger context ty in
1397         if R.are_convertible ~subst ~metasenv context (type_of_aux ~logger context te) ty then
1398           ty
1399         else
1400           raise (TypeCheckerFailure
1401             (sprintf "Invalid cast %s" (CicPp.ppterm t)))
1402     | C.Prod (name,s,t) ->
1403        let sort1 = type_of_aux ~logger context s
1404        and sort2 = type_of_aux ~logger ((Some (name,(C.Decl s)))::context) t in
1405        let res = sort_of_prod ~subst context (name,s) (sort1,sort2) in
1406       res
1407    | C.Lambda (n,s,t) ->
1408        let sort1 = type_of_aux ~logger context s in
1409        (match R.whd ~subst context sort1 with
1410            C.Meta _
1411          | C.Sort _ -> ()
1412          | _ ->
1413            raise
1414             (TypeCheckerFailure (sprintf
1415               "Not well-typed lambda-abstraction: the source %s should be a
1416                type; instead it is a term of type %s" (CicPp.ppterm s)
1417                 (CicPp.ppterm sort1)))
1418        ) ;
1419        let type2 = type_of_aux ~logger ((Some (n,(C.Decl s)))::context) t in
1420         C.Prod (n,s,type2)
1421    | C.LetIn (n,s,t) ->
1422       (* only to check if s is well-typed *)
1423       let ty = type_of_aux ~logger context s in
1424        (* The type of a LetIn is a LetIn. Extremely slow since the computed
1425           LetIn is later reduced and maybe also re-checked.
1426        (C.LetIn (n,s, type_of_aux ((Some (n,(C.Def s)))::context) t))
1427        *)
1428        (* The type of the LetIn is reduced. Much faster than the previous
1429           solution. Moreover the inferred type is probably very different
1430           from the expected one.
1431        (CicReduction.whd context
1432         (C.LetIn (n,s, type_of_aux ((Some (n,(C.Def s)))::context) t)))
1433        *)
1434        (* One-step LetIn reduction. Even faster than the previous solution.
1435           Moreover the inferred type is closer to the expected one. *)
1436        (CicSubstitution.subst s
1437         (type_of_aux ~logger ((Some (n,(C.Def (s,Some ty))))::context) t))
1438    | C.Appl (he::tl) when List.length tl > 0 ->
1439       let hetype = type_of_aux ~logger context he in
1440       let tlbody_and_type = List.map (fun x -> (x, type_of_aux ~logger context x)) tl in
1441        eat_prods ~subst context hetype tlbody_and_type
1442    | C.Appl _ -> raise (AssertFailure "Appl: no arguments")
1443    | C.Const (uri,exp_named_subst) ->
1444       incr fdebug ;
1445       check_exp_named_subst ~logger ~subst context exp_named_subst ;
1446       let cty =
1447        CicSubstitution.subst_vars exp_named_subst (type_of_constant ~logger uri)
1448       in
1449        decr fdebug ;
1450        cty
1451    | C.MutInd (uri,i,exp_named_subst) ->
1452       incr fdebug ;
1453       check_exp_named_subst ~logger ~subst context exp_named_subst ;
1454       let cty =
1455        CicSubstitution.subst_vars exp_named_subst
1456         (type_of_mutual_inductive_defs ~logger uri i)
1457       in
1458        decr fdebug ;
1459        cty
1460    | C.MutConstruct (uri,i,j,exp_named_subst) ->
1461       check_exp_named_subst ~logger ~subst context exp_named_subst ;
1462       let cty =
1463        CicSubstitution.subst_vars exp_named_subst
1464         (type_of_mutual_inductive_constr ~logger uri i j)
1465       in
1466        cty
1467    | C.MutCase (uri,i,outtype,term,pl) ->
1468       let outsort = type_of_aux ~logger context outtype in
1469       let (need_dummy, k) =
1470       let rec guess_args context t =
1471         let outtype = CicReduction.whd ~subst context t in
1472           match outtype with
1473               C.Sort _ -> (true, 0)
1474             | C.Prod (name, s, t) ->
1475                 let (b, n) = 
1476                   guess_args ((Some (name,(C.Decl s)))::context) t in
1477                   if n = 0 then
1478                   (* last prod before sort *)
1479                     match CicReduction.whd ~subst context s with
1480 (*CSC: for _ see comment below about the missing named_exp_subst ?????????? *)
1481                         C.MutInd (uri',i',_) when U.eq uri' uri && i' = i ->
1482                           (false, 1)
1483 (*CSC: for _ see comment below about the missing named_exp_subst ?????????? *)
1484                       | C.Appl ((C.MutInd (uri',i',_)) :: _)
1485                           when U.eq uri' uri && i' = i -> (false, 1)
1486                       | _ -> (true, 1)
1487                   else
1488                     (b, n + 1)
1489             | _ ->
1490                 raise 
1491                   (TypeCheckerFailure 
1492                      (sprintf
1493                         "Malformed case analasys' output type %s" 
1494                         (CicPp.ppterm outtype)))
1495       in
1496       let (b, k) = guess_args context outsort in
1497       if not b then (b, k - 1) else (b, k) in
1498       let (parameters, arguments, exp_named_subst) =
1499         match R.whd ~subst context (type_of_aux ~logger context term) with
1500             C.MutInd (uri',i',exp_named_subst) as typ ->
1501               if U.eq uri uri' && i = i' then ([],[],exp_named_subst)
1502               else raise 
1503                 (TypeCheckerFailure 
1504                    (sprintf
1505                       "Case analysys: analysed term type is %s, 
1506                         but is expected to be (an application of) %s#1/%d{_}"
1507                       (CicPp.ppterm typ) (U.string_of_uri uri) i))
1508           | C.Appl ((C.MutInd (uri',i',exp_named_subst) as typ):: tl) as typ' ->
1509               if U.eq uri uri' && i = i' then
1510                 let params,args =
1511                   split tl (List.length tl - k)
1512                 in params,args,exp_named_subst
1513               else raise 
1514                 (TypeCheckerFailure 
1515                    (sprintf
1516                       "Case analysys: analysed term type is %s, 
1517                        but is expected to be (an application of) %s#1/%d{_}"
1518                       (CicPp.ppterm typ') (U.string_of_uri uri) i))
1519           | _ ->
1520               raise 
1521                 (TypeCheckerFailure 
1522                    (sprintf
1523                       "Case analysis: analysed term %s is not an inductive one"
1524                       (CicPp.ppterm term)))
1525       in
1526         (* let's control if the sort elimination is allowed: [(I q1 ... qr)|B] *)
1527       let sort_of_ind_type =
1528         if parameters = [] then
1529           C.MutInd (uri,i,exp_named_subst)
1530         else
1531           C.Appl ((C.MutInd (uri,i,exp_named_subst))::parameters) in
1532       if not 
1533         (check_allowed_sort_elimination ~logger context uri i need_dummy
1534            sort_of_ind_type (type_of_aux ~logger context sort_of_ind_type) outsort)
1535       then
1536         raise
1537           (TypeCheckerFailure ("Case analasys: sort elimination not allowed"));
1538         (* let's check if the type of branches are right *)
1539       let parsno =
1540         match CicEnvironment.get_cooked_obj ~trust:false uri with
1541             C.InductiveDefinition (_,_,parsno) -> parsno
1542           | _ ->
1543               raise (TypeCheckerFailure
1544                 ("Unknown mutual inductive definition:" ^
1545                   UriManager.string_of_uri uri))
1546       in
1547       let (_,branches_ok) =
1548         List.fold_left
1549           (fun (j,b) p ->
1550              let cons =
1551                if parameters = [] then
1552                  (C.MutConstruct (uri,i,j,exp_named_subst))
1553                else
1554                  (C.Appl 
1555                     (C.MutConstruct (uri,i,j,exp_named_subst)::parameters)) in
1556                (j + 1,
1557                   let res = 
1558                     b &&
1559                     R.are_convertible 
1560                       ~subst ~metasenv context (type_of_aux ~logger context p)
1561                       (type_of_branch context parsno need_dummy outtype cons
1562                          (type_of_aux ~logger context cons)) in 
1563                     if not res then 
1564                       debug_print ("#### " ^ CicPp.ppterm (type_of_aux ~logger context p) ^ " <==> " ^ CicPp.ppterm (type_of_branch context parsno need_dummy outtype cons (type_of_aux ~logger context cons))) ; res
1565                )
1566           ) (1,true) pl
1567       in
1568       if not branches_ok then
1569         raise
1570           (TypeCheckerFailure "Case analysys: wrong branch type");
1571       if not need_dummy then
1572         C.Appl ((outtype::arguments)@[term])
1573       else if arguments = [] then
1574         outtype
1575       else
1576         C.Appl (outtype::arguments)
1577    | C.Fix (i,fl) ->
1578        let types_times_kl =
1579        List.rev
1580          (List.map
1581             (fun (n,k,ty,_) ->
1582                let _ = type_of_aux ~logger context ty in
1583                  (Some (C.Name n,(C.Decl ty)),k)) fl)
1584        in
1585        let (types,kl) = List.split types_times_kl in
1586        let len = List.length types in
1587          List.iter
1588            (fun (name,x,ty,bo) ->
1589               if
1590                 (R.are_convertible 
1591                    ~subst ~metasenv (types@context) (type_of_aux ~logger (types@context) bo)
1592                    (CicSubstitution.lift len ty))
1593               then
1594               begin
1595                 let (m, eaten, context') =
1596                   eat_lambdas ~subst (types @ context) (x + 1) bo in
1597                   (*let's control the guarded by destructors conditions D{f,k,x,M}*)
1598                 if
1599                   not (guarded_by_destructors context' 
1600                          eaten (len + eaten) kl 1 [] m)
1601                 then
1602                   raise
1603                     (TypeCheckerFailure ("Fix: not guarded by destructors"))
1604               end
1605               else
1606                 raise (TypeCheckerFailure ("Fix: ill-typed bodies"))
1607            ) fl ;
1608         (*CSC: controlli mancanti solo su D{f,k,x,M} *)
1609          let (_,_,ty,_) = List.nth fl i in
1610          ty
1611    | C.CoFix (i,fl) ->
1612        let types =
1613        List.rev
1614         (List.map
1615           (fun (n,ty,_) -> 
1616             let _ = type_of_aux ~logger context ty in Some (C.Name n,(C.Decl ty))) fl)
1617        in
1618        let len = List.length types in
1619        List.iter
1620          (fun (_,ty,bo) ->
1621             if
1622               (R.are_convertible 
1623                  ~subst ~metasenv (types @ context)
1624                  (type_of_aux ~logger (types @ context) bo) (CicSubstitution.lift len ty))
1625             then
1626               begin
1627               (* let's control that the returned type is coinductive *)
1628               match returns_a_coinductive context ty with
1629                   None ->
1630                     raise
1631                     (TypeCheckerFailure
1632                        ("CoFix: does not return a coinductive type"))
1633                 | Some uri ->
1634                     (*let's control the guarded by constructors conditions C{f,M}*)
1635                     if
1636                       not
1637                         (guarded_by_constructors 
1638                            (types @ context) 0 len false bo [] uri)
1639                     then
1640                       raise
1641                         (TypeCheckerFailure ("CoFix: not guarded by constructors"))
1642               end
1643             else
1644               raise
1645                 (TypeCheckerFailure ("CoFix: ill-typed bodies"))
1646          ) fl ;
1647          let (_,ty,_) = List.nth fl i in
1648          ty
1649
1650  and check_exp_named_subst ~logger ?(subst = []) context =
1651   let rec check_exp_named_subst_aux ~logger esubsts =
1652    function
1653       [] -> ()
1654     | ((uri,t) as item)::tl ->
1655        let typeofvar =
1656          CicSubstitution.subst_vars esubsts (type_of_variable ~logger uri) in
1657        let typeoft = type_of_aux ~logger context t in
1658        if CicReduction.are_convertible 
1659          ~subst ~metasenv context typeoft typeofvar then
1660          check_exp_named_subst_aux ~logger (esubsts@[item]) tl
1661        else
1662          begin
1663            CicReduction.fdebug := 0 ;
1664            ignore (CicReduction.are_convertible ~subst ~metasenv context typeoft typeofvar) ;
1665            fdebug := 0 ;
1666            debug typeoft [typeofvar] ;
1667            raise (TypeCheckerFailure "Wrong Explicit Named Substitution")
1668          end
1669   in
1670    check_exp_named_subst_aux ~logger []
1671
1672  and sort_of_prod ?(subst = []) context (name,s) (t1, t2) =
1673   let module C = Cic in
1674    let t1' = CicReduction.whd ~subst context t1 in
1675    let t2' = CicReduction.whd ~subst ((Some (name,C.Decl s))::context) t2 in
1676    match (t1', t2') with
1677       (C.Sort s1, C.Sort s2)
1678         when (s2 = C.Prop or s2 = C.Set or s2 = C.CProp) -> 
1679          (* different from Coq manual!!! *)
1680          C.Sort s2
1681     | (C.Sort (C.Type t1), C.Sort (C.Type t2)) -> 
1682       (* TASSI: CONSRTAINTS: the same in doubletypeinference, cicrefine *)
1683        let t' = CicUniv.fresh() in
1684        if not (CicUniv.add_ge t' t1) || not (CicUniv.add_ge t' t2) then
1685          assert false ; (* not possible, error in CicUniv *)
1686        C.Sort (C.Type t')
1687     | (C.Sort _,C.Sort (C.Type t1)) -> 
1688         (* TASSI: CONSRTAINTS: the same in doubletypeinference, cicrefine *)
1689         C.Sort (C.Type t1) (* c'e' bisogno di un fresh? *)
1690     | (C.Meta _, C.Sort _) -> t2'
1691     | (C.Meta _, (C.Meta (_,_) as t))
1692     | (C.Sort _, (C.Meta (_,_) as t)) when CicUtil.is_closed t ->
1693         t2'
1694     | (_,_) -> raise (TypeCheckerFailure (sprintf
1695         "Prod: expected two sorts, found = %s, %s" (CicPp.ppterm t1')
1696           (CicPp.ppterm t2')))
1697
1698  and eat_prods ?(subst = []) context hetype =
1699   (*CSC: siamo sicuri che le are_convertible non lavorino con termini non *)
1700   (*CSC: cucinati                                                         *)
1701   function
1702      [] -> hetype
1703    | (hete, hety)::tl ->
1704     (match (CicReduction.whd ~subst context hetype) with
1705         Cic.Prod (n,s,t) ->
1706          if CicReduction.are_convertible ~subst ~metasenv context hety s then
1707           (CicReduction.fdebug := -1 ;
1708            eat_prods ~subst context (CicSubstitution.subst hete t) tl
1709           )
1710          else
1711           begin
1712            CicReduction.fdebug := 0 ;
1713            ignore (CicReduction.are_convertible ~subst ~metasenv context s hety) ;
1714            fdebug := 0 ;
1715            debug s [hety] ;
1716            raise (TypeCheckerFailure (sprintf
1717             "Appl: wrong parameter-type, expected %s, found %s"
1718             (CicPp.ppterm hetype) (CicPp.ppterm s)))
1719           end
1720       | _ ->
1721           raise (TypeCheckerFailure
1722             "Appl: this is not a function, it cannot be applied")
1723     )
1724
1725  and returns_a_coinductive context ty =
1726   let module C = Cic in
1727    match CicReduction.whd context ty with
1728       C.MutInd (uri,i,_) ->
1729        (*CSC: definire una funzioncina per questo codice sempre replicato *)
1730        (match CicEnvironment.get_cooked_obj ~trust:false uri with
1731            C.InductiveDefinition (itl,_,_) ->
1732             let (_,is_inductive,_,_) = List.nth itl i in
1733              if is_inductive then None else (Some uri)
1734          | _ ->
1735             raise (TypeCheckerFailure
1736               ("Unknown mutual inductive definition:" ^
1737               UriManager.string_of_uri uri))
1738         )
1739     | C.Appl ((C.MutInd (uri,i,_))::_) ->
1740        (match CicEnvironment.get_obj uri with
1741            C.InductiveDefinition (itl,_,_) ->
1742             let (_,is_inductive,_,_) = List.nth itl i in
1743              if is_inductive then None else (Some uri)
1744          | _ ->
1745             raise (TypeCheckerFailure
1746               ("Unknown mutual inductive definition:" ^
1747               UriManager.string_of_uri uri))
1748         )
1749     | C.Prod (n,so,de) ->
1750        returns_a_coinductive ((Some (n,C.Decl so))::context) de
1751     | _ -> None
1752
1753  in
1754 (*CSC
1755 debug_print ("INIZIO TYPE_OF_AUX " ^ CicPp.ppterm t) ; flush stderr ;
1756 let res =
1757 *)
1758   type_of_aux ~logger context t
1759 (*
1760 in debug_print "FINE TYPE_OF_AUX" ; flush stderr ; res
1761 *)
1762
1763 (* is a small constructor? *)
1764 (*CSC: ottimizzare calcolando staticamente *)
1765 and is_small ~logger context paramsno c =
1766  let rec is_small_aux ~logger context c =
1767   let module C = Cic in
1768    match CicReduction.whd context c with
1769       C.Prod (n,so,de) ->
1770        (*CSC: [] is an empty metasenv. Is it correct? *)
1771        let s = type_of_aux' ~logger [] context so in
1772         (s = C.Sort C.Prop || s = C.Sort C.Set || s = C.Sort C.CProp) &&
1773         is_small_aux ~logger ((Some (n,(C.Decl so)))::context) de
1774     | _ -> true (*CSC: we trust the type-checker *)
1775  in
1776   let (context',dx) = split_prods context paramsno c in
1777    is_small_aux ~logger context' dx
1778
1779 and type_of ~logger t =
1780 (*CSC
1781 debug_print ("INIZIO TYPE_OF_AUX' " ^ CicPp.ppterm t) ; flush stderr ;
1782 let res =
1783 *)
1784  type_of_aux' ~logger [] [] t
1785 (*CSC
1786 in debug_print "FINE TYPE_OF_AUX'" ; flush stderr ; res
1787 *)
1788 ;;
1789
1790 (* tassi FIXME: not sure where is this called... no history here... *)
1791 let typecheck uri =
1792  let module C = Cic in
1793  let module R = CicReduction in
1794  let module U = UriManager in
1795  let logger = new CicLogger.logger in
1796   (*match CicEnvironment.is_type_checked ~trust:false uri with*)
1797   match CicEnvironment.is_type_checked ~trust:true uri with
1798      CicEnvironment.CheckedObj cobj -> cobj
1799    | CicEnvironment.UncheckedObj uobj ->
1800       (* let's typecheck the uncooked object *)
1801       logger#log (`Start_type_checking uri) ;
1802       CicUniv.directly_to_env_begin ();
1803       (match uobj with
1804           C.Constant (_,Some te,ty,_) ->
1805            let _ = type_of ~logger ty in
1806             if not (R.are_convertible [] (type_of ~logger te ) ty) then
1807               raise (TypeCheckerFailure
1808                 ("Unknown constant:" ^ U.string_of_uri uri))
1809         | C.Constant (_,None,ty,_) ->
1810           (* only to check that ty is well-typed *)
1811           let _ = type_of ~logger ty in ()
1812         | C.CurrentProof (_,conjs,te,ty,_) ->
1813            let _ =
1814             List.fold_left
1815              (fun metasenv ((_,context,ty) as conj) ->
1816                ignore (type_of_aux' ~logger metasenv context ty) ;
1817                metasenv @ [conj]
1818              ) [] conjs
1819            in
1820             let _ = type_of_aux' ~logger conjs [] ty in
1821             let type_of_te = type_of_aux' ~logger conjs [] te in
1822              if not (R.are_convertible [] type_of_te ty)
1823              then
1824                raise (TypeCheckerFailure (sprintf
1825                 "the current proof %s is not well typed because the type %s of the body is not convertible to the declared type %s"
1826                 (U.string_of_uri uri) (CicPp.ppterm type_of_te)
1827                 (CicPp.ppterm ty)))
1828         | C.Variable (_,bo,ty,_) ->
1829            (* only to check that ty is well-typed *)
1830            let _ = type_of ~logger ty in
1831             (match bo with
1832                 None -> ()
1833               | Some bo ->
1834                  if not (R.are_convertible [] (type_of ~logger bo) ty) then
1835                   raise (TypeCheckerFailure
1836                     ("Unknown variable:" ^ U.string_of_uri uri))
1837             )
1838         | C.InductiveDefinition _ ->
1839            check_mutual_inductive_defs ~logger uri uobj
1840       ) ;
1841       CicEnvironment.set_type_checking_info uri ;
1842       CicUniv.directly_to_env_end ();
1843       logger#log (`Type_checking_completed uri);
1844       uobj
1845 ;;
1846
1847 (** wrappers which instantiate fresh loggers *)
1848
1849 let type_of_aux' ?(subst = []) metasenv context t =
1850   let logger = new CicLogger.logger in
1851   type_of_aux' ~logger metasenv context t
1852
1853 let typecheck_mutual_inductive_defs uri (itl, uris, indparamsno) =
1854   let logger = new CicLogger.logger in
1855   typecheck_mutual_inductive_defs ~logger uri (itl, uris, indparamsno)
1856