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