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