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