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