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