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