]> matita.cs.unibo.it Git - helm.git/blob - helm/software/components/ng_kernel/nCicTypeChecker.ml
type_of_branch ported and optimized to not lift the outty every Prod, keep the
[helm.git] / helm / software / components / ng_kernel / nCicTypeChecker.ml
1 (*
2     ||M||  This file is part of HELM, an Hypertextual, Electronic        
3     ||A||  Library of Mathematics, developed at the Computer Science     
4     ||T||  Department, University of Bologna, Italy.                     
5     ||I||                                                                
6     ||T||  HELM is free software; you can redistribute it and/or         
7     ||A||  modify it under the terms of the GNU General Public License   
8     \   /  version 2 or (at your option) any later version.      
9      \ /   This software is distributed as is, NO WARRANTY.     
10       V_______________________________________________________________ *)
11
12 (* $Id: nCicReduction.ml 8250 2008-03-25 17:56:20Z tassi $ *)
13
14 exception TypeCheckerFailure of string Lazy.t
15 exception AssertFailure of string Lazy.t
16
17 let shift_k e (c,rf,x,safes) =
18   e::c,List.map (fun (k,v) -> k+1,v) rf,x+1,List.map ((+)1) safes
19 ;;
20
21 (* $Id: cicTypeChecker.ml 8213 2008-03-13 18:48:26Z sacerdot $ *)
22
23 (*
24 exception CicEnvironmentError;;
25
26 (*CSC l'indice x dei tipi induttivi e' t.c. n < x <= nn *)
27 (*CSC questa funzione e' simile alla are_all_occurrences_positive, ma fa *)
28 (*CSC dei controlli leggermente diversi. Viene invocata solamente dalla  *)
29 (*CSC strictly_positive                                                  *)
30 (*CSC definizione (giusta???) tratta dalla mail di Hugo ;-)              *)
31 and weakly_positive context n nn uri te =
32  let module C = Cic in
33 (*CSC: Che schifo! Bisogna capire meglio e trovare una soluzione ragionevole!*)
34   let dummy_mutind =
35    C.MutInd (HelmLibraryObjects.Datatypes.nat_URI,0,[])
36   in
37   (*CSC: mettere in cicSubstitution *)
38   let rec subst_inductive_type_with_dummy_mutind =
39    function
40       C.MutInd (uri',0,_) when UriManager.eq uri' uri ->
41        dummy_mutind
42     | C.Appl ((C.MutInd (uri',0,_))::tl) when UriManager.eq uri' uri ->
43        dummy_mutind
44     | C.Cast (te,ty) -> subst_inductive_type_with_dummy_mutind te
45     | C.Prod (name,so,ta) ->
46        C.Prod (name, subst_inductive_type_with_dummy_mutind so,
47         subst_inductive_type_with_dummy_mutind ta)
48     | C.Lambda (name,so,ta) ->
49        C.Lambda (name, subst_inductive_type_with_dummy_mutind so,
50         subst_inductive_type_with_dummy_mutind ta)
51     | C.Appl tl ->
52        C.Appl (List.map subst_inductive_type_with_dummy_mutind tl)
53     | C.MutCase (uri,i,outtype,term,pl) ->
54        C.MutCase (uri,i,
55         subst_inductive_type_with_dummy_mutind outtype,
56         subst_inductive_type_with_dummy_mutind term,
57         List.map subst_inductive_type_with_dummy_mutind pl)
58     | C.Fix (i,fl) ->
59        C.Fix (i,List.map (fun (name,i,ty,bo) -> (name,i,
60         subst_inductive_type_with_dummy_mutind ty,
61         subst_inductive_type_with_dummy_mutind bo)) fl)
62     | C.CoFix (i,fl) ->
63        C.CoFix (i,List.map (fun (name,ty,bo) -> (name,
64         subst_inductive_type_with_dummy_mutind ty,
65         subst_inductive_type_with_dummy_mutind bo)) fl)
66     | C.Const (uri,exp_named_subst) ->
67        let exp_named_subst' =
68         List.map
69          (function (uri,t) -> (uri,subst_inductive_type_with_dummy_mutind t))
70          exp_named_subst
71        in
72         C.Const (uri,exp_named_subst')
73     | C.MutInd (uri,typeno,exp_named_subst) ->
74        let exp_named_subst' =
75         List.map
76          (function (uri,t) -> (uri,subst_inductive_type_with_dummy_mutind t))
77          exp_named_subst
78        in
79         C.MutInd (uri,typeno,exp_named_subst')
80     | C.MutConstruct (uri,typeno,consno,exp_named_subst) ->
81        let exp_named_subst' =
82         List.map
83          (function (uri,t) -> (uri,subst_inductive_type_with_dummy_mutind t))
84          exp_named_subst
85        in
86         C.MutConstruct (uri,typeno,consno,exp_named_subst')
87     | t -> t
88   in
89   match CicReduction.whd context te with
90 (*
91      C.Appl ((C.MutInd (uri',0,_))::tl) when UriManager.eq uri' uri -> true
92 *)
93      C.Appl ((C.MutInd (uri',_,_))::tl) when UriManager.eq uri' uri -> true
94    | C.MutInd (uri',0,_) when UriManager.eq uri' uri -> true
95    | C.Prod (C.Anonymous,source,dest) ->
96       strictly_positive context n nn
97        (subst_inductive_type_with_dummy_mutind source) &&
98        weakly_positive ((Some (C.Anonymous,(C.Decl source)))::context)
99         (n + 1) (nn + 1) uri dest
100    | C.Prod (name,source,dest) when
101       does_not_occur ((Some (name,(C.Decl source)))::context) 0 n dest ->
102        (* dummy abstraction, so we behave as in the anonimous case *)
103        strictly_positive context n nn
104         (subst_inductive_type_with_dummy_mutind source) &&
105          weakly_positive ((Some (name,(C.Decl source)))::context)
106          (n + 1) (nn + 1) uri dest
107    | C.Prod (name,source,dest) ->
108        does_not_occur context n nn
109          (subst_inductive_type_with_dummy_mutind source)&&
110          weakly_positive ((Some (name,(C.Decl source)))::context)
111          (n + 1) (nn + 1) uri dest
112    | _ ->
113      raise (TypeCheckerFailure (lazy "Malformed inductive constructor type"))
114
115 (* instantiate_parameters ps (x1:T1)...(xn:Tn)C                             *)
116 (* returns ((x_|ps|:T_|ps|)...(xn:Tn)C){ps_1 / x1 ; ... ; ps_|ps| / x_|ps|} *)
117 and instantiate_parameters params c =
118  let module C = Cic in
119   match (c,params) with
120      (c,[]) -> c
121    | (C.Prod (_,_,ta), he::tl) ->
122        instantiate_parameters tl
123         (CicSubstitution.subst he ta)
124    | (C.Cast (te,_), _) -> instantiate_parameters params te
125    | (t,l) -> raise (AssertFailure (lazy "1"))
126
127 and strictly_positive context n nn te =
128  let module C = Cic in
129  let module U = UriManager in
130   match CicReduction.whd context te with
131    | t when does_not_occur context n nn t -> true
132    | C.Rel _ -> true
133    | C.Cast (te,ty) ->
134       (*CSC: bisogna controllare ty????*)
135       strictly_positive context n nn te
136    | C.Prod (name,so,ta) ->
137       does_not_occur context n nn so &&
138        strictly_positive ((Some (name,(C.Decl so)))::context) (n+1) (nn+1) ta
139    | C.Appl ((C.Rel m)::tl) when m > n && m <= nn ->
140       List.fold_right (fun x i -> i && does_not_occur context n nn x) tl true
141    | C.Appl ((C.MutInd (uri,i,exp_named_subst))::tl) -> 
142       let (ok,paramsno,ity,cl,name) =
143         let o,_ = CicEnvironment.get_obj CicUniv.empty_ugraph uri in
144           match o with
145               C.InductiveDefinition (tl,_,paramsno,_) ->
146                 let (name,_,ity,cl) = List.nth tl i in
147                 (List.length tl = 1, paramsno, ity, cl, name) 
148                 (* (true, paramsno, ity, cl, name) *)
149             | _ ->
150                 raise 
151                   (TypeCheckerFailure
152                      (lazy ("Unknown inductive type:" ^ U.string_of_uri uri)))
153       in 
154       let (params,arguments) = split tl paramsno in
155       let lifted_params = List.map (CicSubstitution.lift 1) params in
156       let cl' =
157         List.map
158           (fun (_,te) ->
159              instantiate_parameters lifted_params
160                (CicSubstitution.subst_vars exp_named_subst te)
161           ) cl
162       in
163         ok &&
164           List.fold_right
165           (fun x i -> i && does_not_occur context n nn x)
166           arguments true &&
167          (*CSC: MEGAPATCH3 (sara' quella giusta?)*)
168           List.fold_right
169           (fun x i ->
170              i &&
171                weakly_positive
172                ((Some (C.Name name,(Cic.Decl ity)))::context) (n+1) (nn+1) uri
173                x
174           ) cl' true
175    | t -> false
176        
177 (* the inductive type indexes are s.t. n < x <= nn *)
178 and are_all_occurrences_positive context uri indparamsno i n nn te =
179  let module C = Cic in
180   match CicReduction.whd context te with
181      C.Appl ((C.Rel m)::tl) when m = i ->
182       (*CSC: riscrivere fermandosi a 0 *)
183       (* let's check if the inductive type is applied at least to *)
184       (* indparamsno parameters                                   *)
185       let last =
186        List.fold_left
187         (fun k x ->
188           if k = 0 then 0
189           else
190            match CicReduction.whd context x with
191               C.Rel m when m = n - (indparamsno - k) -> k - 1
192             | _ ->
193               raise (TypeCheckerFailure
194                (lazy 
195                ("Non-positive occurence in mutual inductive definition(s) [1]" ^
196                 UriManager.string_of_uri uri)))
197         ) indparamsno tl
198       in
199        if last = 0 then
200         List.fold_right (fun x i -> i && does_not_occur context n nn x) tl true
201        else
202         raise (TypeCheckerFailure
203          (lazy ("Non-positive occurence in mutual inductive definition(s) [2]"^
204           UriManager.string_of_uri uri)))
205    | C.Rel m when m = i ->
206       if indparamsno = 0 then
207        true
208       else
209         raise (TypeCheckerFailure
210          (lazy ("Non-positive occurence in mutual inductive definition(s) [3]"^
211           UriManager.string_of_uri uri)))
212    | C.Prod (C.Anonymous,source,dest) ->
213        let b = strictly_positive context n nn source in
214        b &&
215        are_all_occurrences_positive
216         ((Some (C.Anonymous,(C.Decl source)))::context) uri indparamsno
217         (i+1) (n + 1) (nn + 1) dest
218    | C.Prod (name,source,dest) when
219       does_not_occur ((Some (name,(C.Decl source)))::context) 0 n dest ->
220       (* dummy abstraction, so we behave as in the anonimous case *)
221       strictly_positive context n nn source &&
222        are_all_occurrences_positive
223         ((Some (name,(C.Decl source)))::context) uri indparamsno
224         (i+1) (n + 1) (nn + 1) dest
225    | C.Prod (name,source,dest) ->
226       does_not_occur context n nn source &&
227        are_all_occurrences_positive ((Some (name,(C.Decl source)))::context)
228         uri indparamsno (i+1) (n + 1) (nn + 1) dest
229    | _ ->
230      raise
231       (TypeCheckerFailure (lazy ("Malformed inductive constructor type " ^
232         (UriManager.string_of_uri uri))))
233
234 (* Main function to checks the correctness of a mutual *)
235 (* inductive block definition. This is the function    *)
236 (* exported to the proof-engine.                       *)
237 and typecheck_mutual_inductive_defs ~logger uri (itl,_,indparamsno) ugraph =
238  let module U = UriManager in
239   (* let's check if the arity of the inductive types are well *)
240   (* formed                                                   *)
241   let ugrap1 = List.fold_left 
242    (fun ugraph (_,_,x,_) -> let _,ugraph' = 
243       type_of ~logger x ugraph in ugraph') 
244    ugraph itl in
245
246   (* let's check if the types of the inductive constructors  *)
247   (* are well formed.                                        *)
248   (* In order not to use type_of_aux we put the types of the *)
249   (* mutual inductive types at the head of the types of the  *)
250   (* constructors using Prods                                *)
251   let len = List.length itl in
252   let tys =
253     List.map (fun (n,_,ty,_) -> Some (Cic.Name n,(Cic.Decl ty))) itl in
254   let _,ugraph2 =
255     List.fold_right
256       (fun (_,_,_,cl) (i,ugraph) ->
257         let ugraph'' = 
258           List.fold_left
259             (fun ugraph (name,te) -> 
260               let debruijnedte = debruijn uri len te in
261               let augmented_term =
262                 List.fold_right
263                   (fun (name,_,ty,_) i -> Cic.Prod (Cic.Name name, ty, i))
264                   itl debruijnedte
265               in
266               let _,ugraph' = type_of ~logger augmented_term ugraph in
267               (* let's check also the positivity conditions *)
268               if
269                 not
270                   (are_all_occurrences_positive tys uri indparamsno i 0 len
271                      debruijnedte)
272               then
273                 begin
274                 prerr_endline (UriManager.string_of_uri uri);
275                 prerr_endline (string_of_int (List.length tys));
276                 raise
277                   (TypeCheckerFailure
278                     (lazy ("Non positive occurence in " ^ U.string_of_uri uri)))                end 
279               else
280                 ugraph'
281             ) ugraph cl in
282         (i + 1),ugraph''
283       ) itl (1,ugrap1)
284   in
285   ugraph2
286
287 (* Main function to checks the correctness of a mutual *)
288 (* inductive block definition.                         *)
289 and check_mutual_inductive_defs uri obj ugraph =
290   match obj with
291       Cic.InductiveDefinition (itl, params, indparamsno, _) ->
292         typecheck_mutual_inductive_defs uri (itl,params,indparamsno) ugraph 
293     | _ ->
294         raise (TypeCheckerFailure (
295                 lazy ("Unknown mutual inductive definition:" ^
296                  UriManager.string_of_uri uri)))
297
298 (* the boolean h means already protected *)
299 (* args is the list of arguments the type of the constructor that may be *)
300 (* found in head position must be applied to.                            *)
301 and guarded_by_constructors ~subst context n nn h te args coInductiveTypeURI =
302  let module C = Cic in
303   (*CSC: There is a lot of code replication between the cases X and    *)
304   (*CSC: (C.Appl X tl). Maybe it will be better to define a function   *)
305   (*CSC: that maps X into (C.Appl X []) when X is not already a C.Appl *)
306   match CicReduction.whd ~subst context te with
307      C.Rel m when m > n && m <= nn -> h
308    | C.Rel _ -> true
309    | C.Meta _
310    | C.Sort _
311    | C.Implicit _
312    | C.Cast _
313    | C.Prod _
314    | C.LetIn _ ->
315       (* the term has just been type-checked *)
316       raise (AssertFailure (lazy "17"))
317    | C.Lambda (name,so,de) ->
318       does_not_occur ~subst context n nn so &&
319        guarded_by_constructors ~subst ((Some (name,(C.Decl so)))::context)
320         (n + 1) (nn + 1) h de args coInductiveTypeURI
321    | C.Appl ((C.Rel m)::tl) when m > n && m <= nn ->
322       h &&
323        List.fold_right (fun x i -> i && does_not_occur ~subst context n nn x) tl true
324    | C.Appl ((C.MutConstruct (uri,i,j,exp_named_subst))::tl) ->
325       let consty =
326         let obj,_ = 
327           try 
328             CicEnvironment.get_cooked_obj ~trust:false CicUniv.empty_ugraph uri
329           with Not_found -> assert false
330         in
331        match obj with
332           C.InductiveDefinition (itl,_,_,_) ->
333            let (_,_,_,cl) = List.nth itl i in
334             let (_,cons) = List.nth cl (j - 1) in
335              CicSubstitution.subst_vars exp_named_subst cons
336         | _ ->
337             raise (TypeCheckerFailure
338              (lazy ("Unknown mutual inductive definition:" ^ UriManager.string_of_uri uri)))
339       in
340        let rec analyse_branch context ty te =
341         match CicReduction.whd ~subst context ty with
342            C.Meta _ -> raise (AssertFailure (lazy "34"))
343          | C.Rel _
344          | C.Var _
345          | C.Sort _ ->
346             does_not_occur ~subst context n nn te
347          | C.Implicit _
348          | C.Cast _ ->
349             raise (AssertFailure (lazy "24"))(* due to type-checking *)
350          | C.Prod (name,so,de) ->
351             analyse_branch ((Some (name,(C.Decl so)))::context) de te
352          | C.Lambda _
353          | C.LetIn _ ->
354             raise (AssertFailure (lazy "25"))(* due to type-checking *)
355          | C.Appl ((C.MutInd (uri,_,_))::_) when uri == coInductiveTypeURI -> 
356              guarded_by_constructors ~subst context n nn true te []
357               coInductiveTypeURI
358          | C.Appl ((C.MutInd (uri,_,_))::_) -> 
359             guarded_by_constructors ~subst context n nn true te tl
360              coInductiveTypeURI
361          | C.Appl _ ->
362             does_not_occur ~subst context n nn te
363          | C.Const _ -> raise (AssertFailure (lazy "26"))
364          | C.MutInd (uri,_,_) when uri == coInductiveTypeURI ->
365             guarded_by_constructors ~subst context n nn true te []
366              coInductiveTypeURI
367          | C.MutInd _ ->
368             does_not_occur ~subst context n nn te
369          | C.MutConstruct _ -> raise (AssertFailure (lazy "27"))
370          (*CSC: we do not consider backbones with a MutCase, Fix, Cofix *)
371          (*CSC: in head position.                                       *)
372          | C.MutCase _
373          | C.Fix _
374          | C.CoFix _ ->
375             raise (AssertFailure (lazy "28"))(* due to type-checking *)
376        in
377        let rec analyse_instantiated_type context ty l =
378         match CicReduction.whd ~subst context ty with
379            C.Rel _
380          | C.Var _
381          | C.Meta _
382          | C.Sort _
383          | C.Implicit _
384          | C.Cast _ -> raise (AssertFailure (lazy "29"))(* due to type-checking *)
385          | C.Prod (name,so,de) ->
386             begin
387              match l with
388                 [] -> true
389               | he::tl ->
390                  analyse_branch context so he &&
391                   analyse_instantiated_type
392                    ((Some (name,(C.Decl so)))::context) de tl
393             end
394          | C.Lambda _
395          | C.LetIn _ ->
396             raise (AssertFailure (lazy "30"))(* due to type-checking *)
397          | C.Appl _ -> 
398             List.fold_left
399              (fun i x -> i && does_not_occur ~subst context n nn x) true l
400          | C.Const _ -> raise (AssertFailure (lazy "31"))
401          | C.MutInd _ ->
402             List.fold_left
403              (fun i x -> i && does_not_occur ~subst context n nn x) true l
404          | C.MutConstruct _ -> raise (AssertFailure (lazy "32"))
405          (*CSC: we do not consider backbones with a MutCase, Fix, Cofix *)
406          (*CSC: in head position.                                       *)
407          | C.MutCase _
408          | C.Fix _
409          | C.CoFix _ ->
410             raise (AssertFailure (lazy "33"))(* due to type-checking *)
411        in
412         let rec instantiate_type args consty =
413          function
414             [] -> true
415           | tlhe::tltl as l ->
416              let consty' = CicReduction.whd ~subst context consty in
417               match args with 
418                  he::tl ->
419                   begin
420                    match consty' with
421                       C.Prod (_,_,de) ->
422                        let instantiated_de = CicSubstitution.subst he de in
423                         (*CSC: siamo sicuri che non sia troppo forte? *)
424                         does_not_occur ~subst context n nn tlhe &
425                          instantiate_type tl instantiated_de tltl
426                     | _ ->
427                       (*CSC:We do not consider backbones with a MutCase, a    *)
428                       (*CSC:FixPoint, a CoFixPoint and so on in head position.*)
429                       raise (AssertFailure (lazy "23"))
430                   end
431                | [] -> analyse_instantiated_type context consty' l
432                   (* These are all the other cases *)
433        in
434         instantiate_type args consty tl
435    | C.Appl ((C.CoFix (_,fl))::tl) ->
436       List.fold_left (fun i x -> i && does_not_occur ~subst context n nn x) true tl &&
437        let len = List.length fl in
438         let n_plus_len = n + len
439         and nn_plus_len = nn + len
440         (*CSC: Is a Decl of the ty ok or should I use Def of a Fix? *)
441         and tys,_ =
442           List.fold_left
443             (fun (types,len) (n,ty,_) ->
444                (Some (C.Name n,(C.Decl (CicSubstitution.lift len ty)))::types,
445                 len+1)
446             ) ([],0) fl
447         in
448          List.fold_right
449           (fun (_,ty,bo) i ->
450             i && does_not_occur ~subst context n nn ty &&
451              guarded_by_constructors ~subst (tys@context) n_plus_len nn_plus_len
452               h bo args coInductiveTypeURI
453           ) fl true
454    | C.Appl ((C.MutCase (_,_,out,te,pl))::tl) ->
455        List.fold_left (fun i x -> i && does_not_occur ~subst context n nn x) true tl &&
456         does_not_occur ~subst context n nn out &&
457          does_not_occur ~subst context n nn te &&
458           List.fold_right
459            (fun x i ->
460              i &&
461              guarded_by_constructors ~subst context n nn h x args
462               coInductiveTypeURI
463            ) pl true
464    | C.Appl l ->
465       List.fold_right (fun x i -> i && does_not_occur ~subst context n nn x) l true
466    | C.Var (_,exp_named_subst)
467    | C.Const (_,exp_named_subst) ->
468       List.fold_right
469        (fun (_,x) i -> i && does_not_occur ~subst context n nn x) exp_named_subst true
470    | C.MutInd _ -> assert false
471    | C.MutConstruct (_,_,_,exp_named_subst) ->
472       List.fold_right
473        (fun (_,x) i -> i && does_not_occur ~subst context n nn x) exp_named_subst true
474    | C.MutCase (_,_,out,te,pl) ->
475        does_not_occur ~subst context n nn out &&
476         does_not_occur ~subst context n nn te &&
477          List.fold_right
478           (fun x i ->
479             i &&
480              guarded_by_constructors ~subst context n nn h x args
481               coInductiveTypeURI
482           ) pl true
483    | C.Fix (_,fl) ->
484       let len = List.length fl in
485        let n_plus_len = n + len
486        and nn_plus_len = nn + len
487        (*CSC: Is a Decl of the ty ok or should I use Def of a Fix? *)
488        and tys,_ =
489         List.fold_left
490           (fun (types,len) (n,_,ty,_) ->
491              (Some (C.Name n,(C.Decl (CicSubstitution.lift len ty)))::types,
492               len+1)
493           ) ([],0) fl
494        in
495         List.fold_right
496          (fun (_,_,ty,bo) i ->
497            i && does_not_occur ~subst context n nn ty &&
498             does_not_occur ~subst (tys@context) n_plus_len nn_plus_len bo
499          ) fl true
500    | C.CoFix (_,fl) ->
501       let len = List.length fl in
502        let n_plus_len = n + len
503        and nn_plus_len = nn + len
504        (*CSC: Is a Decl of the ty ok or should I use Def of a Fix? *)
505        and tys,_ =
506         List.fold_left
507           (fun (types,len) (n,ty,_) ->
508              (Some (C.Name n,(C.Decl (CicSubstitution.lift len ty)))::types,
509               len+1)
510           ) ([],0) fl
511        in
512         List.fold_right
513          (fun (_,ty,bo) i ->
514            i && does_not_occur ~subst context n nn ty &&
515             guarded_by_constructors ~subst (tys@context) n_plus_len nn_plus_len
516              h bo
517              args coInductiveTypeURI
518          ) fl true
519
520  and returns_a_coinductive ~subst context ty =
521   let module C = Cic in
522    match CicReduction.whd ~subst context ty with
523       C.MutInd (uri,i,_) ->
524        (*CSC: definire una funzioncina per questo codice sempre replicato *)
525         let obj,_ =
526           try
527             CicEnvironment.get_cooked_obj ~trust:false CicUniv.empty_ugraph uri
528           with Not_found -> assert false
529         in
530         (match obj with
531            C.InductiveDefinition (itl,_,_,_) ->
532             let (_,is_inductive,_,_) = List.nth itl i in
533              if is_inductive then None else (Some uri)
534          | _ ->
535             raise (TypeCheckerFailure
536               (lazy ("Unknown mutual inductive definition:" ^
537               UriManager.string_of_uri uri)))
538         )
539     | C.Appl ((C.MutInd (uri,i,_))::_) ->
540        (let o,_ = CicEnvironment.get_obj CicUniv.empty_ugraph uri in
541          match o with
542            C.InductiveDefinition (itl,_,_,_) ->
543             let (_,is_inductive,_,_) = List.nth itl i in
544              if is_inductive then None else (Some uri)
545          | _ ->
546             raise (TypeCheckerFailure
547               (lazy ("Unknown mutual inductive definition:" ^
548               UriManager.string_of_uri uri)))
549         )
550     | C.Prod (n,so,de) ->
551        returns_a_coinductive ~subst ((Some (n,C.Decl so))::context) de
552     | _ -> None
553
554  in
555   type_of_aux ~logger context t ugraph
556
557 ;;
558
559 (** wrappers which instantiate fresh loggers *)
560
561 (* check_allowed_sort_elimination uri i s1 s2
562    This function is used outside the kernel to determine in advance whether
563    a MutCase will be allowed or not.
564    [uri,i] is the type of the term to match
565    [s1] is the sort of the term to eliminate (i.e. the head of the arity
566         of the inductive type [uri,i])
567    [s2] is the sort of the goal (i.e. the head of the type of the outtype
568         of the MutCase) *)
569 let check_allowed_sort_elimination uri i s1 s2 =
570  fst (check_allowed_sort_elimination ~subst:[] ~metasenv:[]
571   ~logger:(new CicLogger.logger) [] uri i true
572   (Cic.Implicit None) (* never used *) (Cic.Sort s1) (Cic.Sort s2)
573   CicUniv.empty_ugraph)
574 ;;
575
576 Deannotate.type_of_aux' := fun context t -> fst (type_of_aux' [] context t CicUniv.oblivion_ugraph);;
577
578 *)
579
580 module C = NCic 
581 module R = NCicReduction
582 module Ref = NReference
583 module S = NCicSubstitution 
584 module U = NCicUtils
585 module E = NCicEnvironment
586
587 let rec split_prods ~subst context n te =
588   match (n, R.whd ~subst context te) with
589    | (0, _) -> context,te
590    | (n, C.Prod (name,so,ta)) when n > 0 ->
591        split_prods ~subst ((name,(C.Decl so))::context) (n - 1) ta
592    | (_, _) -> raise (AssertFailure (lazy "split_prods"))
593 ;;
594
595 let debruijn ?(cb=fun _ _ -> ()) uri number_of_types = 
596  let rec aux k t =
597   let res =
598    match t with
599     | C.Meta (i,(s,C.Ctx l)) ->
600        let l1 = NCicUtils.sharing_map (aux (k-s)) l in
601        if l1 == l then t else C.Meta (i,(s,C.Ctx l1))
602     | C.Meta _ -> t
603     | C.Const (Ref.Ref (_,uri1,(Ref.Fix (no,_) | Ref.CoFix no))) 
604     | C.Const (Ref.Ref (_,uri1,Ref.Ind no)) when NUri.eq uri uri1 ->
605        C.Rel (k + number_of_types - no)
606     | t -> NCicUtils.map (fun _ k -> k+1) k aux t
607   in
608    cb t res; res
609  in
610   aux 0
611 ;;
612
613 let sort_of_prod ~subst context (name,s) (t1, t2) =
614    let t1 = R.whd ~subst context t1 in
615    let t2 = R.whd ~subst ((name,C.Decl s)::context) t2 in
616    match t1, t2 with
617    | C.Sort s1, C.Sort C.Prop -> t2
618    | C.Sort (C.Type u1), C.Sort (C.Type u2) -> C.Sort (C.Type (max u1 u2)) 
619    | C.Sort _,C.Sort (C.Type _) -> t2
620    | C.Sort (C.Type _) , C.Sort C.CProp -> t1
621    | C.Sort _, C.Sort C.CProp -> t2
622    | C.Meta _, C.Sort _
623    | C.Meta _, C.Meta _
624    | C.Sort _, C.Meta _ when U.is_closed t2 -> t2
625    | _ -> 
626       raise (TypeCheckerFailure (lazy (Printf.sprintf
627         "Prod: expected two sorts, found = %s, %s" 
628          (NCicPp.ppterm t1) (NCicPp.ppterm t2))))
629 ;;
630
631 let eat_prods ~subst ~metasenv context ty_he args_with_ty = 
632   let rec aux ty_he = function 
633   | [] -> ty_he
634   | (arg, ty_arg)::tl ->
635       (match R.whd ~subst context ty_he with 
636       | C.Prod (n,s,t) ->
637           if R.are_convertible ~subst ~metasenv context ty_arg s then
638             aux (S.subst ~avoid_beta_redexes:true arg t) tl
639           else
640             raise 
641               (TypeCheckerFailure 
642                 (lazy (Printf.sprintf
643                   ("Appl: wrong parameter-type, expected %s, found %s")
644                   (NCicPp.ppterm ty_arg) (NCicPp.ppterm s))))
645        | _ ->
646           raise 
647             (TypeCheckerFailure
648               (lazy "Appl: this is not a function, it cannot be applied")))
649   in
650     aux ty_he args_with_ty
651 ;;
652
653 let fix_lefts_in_constrs ~subst uri paramsno tyl i =
654   let len = List.length tyl in
655   let _,_,arity,cl = List.nth tyl i in
656   let tys = List.map (fun (_,n,ty,_) -> n,C.Decl ty) tyl in
657   let cl' =
658    List.map
659     (fun (_,id,ty) ->
660       let debruijnedty = debruijn uri len ty in
661       id, snd (split_prods ~subst tys paramsno ty),
662        snd (split_prods ~subst tys paramsno debruijnedty))
663     cl 
664   in
665   let lefts = fst (split_prods ~subst [] paramsno arity) in
666   tys@lefts, len, cl'
667 ;;
668
669 exception DoesOccur;;
670
671 let does_not_occur ~subst context n nn t = 
672   let rec aux (context,n,nn as k) _ = function
673     | C.Rel m when m > n && m <= nn -> raise DoesOccur
674     | C.Rel m ->
675         (try (match List.nth context (m-1) with
676           | _,C.Def (bo,_) -> aux k () (S.lift m bo)
677           | _ -> ())
678          with Failure _ -> assert false)
679     | C.Meta (_,(_,(C.Irl 0 | C.Ctx []))) -> (* closed meta *) ()
680     | C.Meta (mno,(s,l)) ->
681          (try
682            let _,_,term,_ = U.lookup_subst mno subst in
683            aux (context,n+s,nn+s) () (S.subst_meta (0,l) term)
684           with CicUtil.Subst_not_found _ -> match l with
685           | C.Irl len -> if not (n >= s+len || s > nn) then raise DoesOccur
686           | C.Ctx lc -> List.iter (aux (context,n+s,nn+s) ()) lc)
687     | t -> U.fold (fun e (ctx,n,nn) -> (e::ctx,n+1,nn+1)) k aux () t
688   in
689    try aux (context,n,nn) () t; true
690    with DoesOccur -> false
691 ;;
692
693 exception NotGuarded;;
694
695 let rec typeof ~subst ~metasenv context term =
696   let rec typeof_aux context = function
697     | C.Rel n ->
698        (try
699          match List.nth context (n - 1) with
700          | (_,C.Decl ty) -> S.lift n ty
701          | (_,C.Def (_,ty)) -> S.lift n ty
702         with Failure _ -> raise (TypeCheckerFailure (lazy "unbound variable")))
703     | C.Sort (C.Type i) -> C.Sort (C.Type (i+1))
704     | C.Sort s -> C.Sort (C.Type 0)
705     | C.Implicit _ -> raise (AssertFailure (lazy "Implicit found"))
706     | C.Meta (n,l) as t -> 
707        let canonical_context,ty =
708         try
709          let _,c,_,ty = U.lookup_subst n subst in c,ty
710         with U.Subst_not_found _ -> try
711          let _,_,c,ty = U.lookup_meta n metasenv in c,ty
712         with U.Meta_not_found _ ->
713          raise (AssertFailure (lazy (Printf.sprintf
714           "%s not found" (NCicPp.ppterm t))))
715        in
716         check_metasenv_consistency t context canonical_context l;
717         S.subst_meta l ty
718     | C.Const ref -> type_of_constant ref
719     | C.Prod (name,s,t) ->
720        let sort1 = typeof_aux context s in
721        let sort2 = typeof_aux ((name,(C.Decl s))::context) t in
722        sort_of_prod ~subst context (name,s) (sort1,sort2)
723     | C.Lambda (n,s,t) ->
724        let sort = typeof_aux context s in
725        (match R.whd ~subst context sort with
726        | C.Meta _ | C.Sort _ -> ()
727        | _ ->
728          raise
729            (TypeCheckerFailure (lazy (Printf.sprintf
730              ("Not well-typed lambda-abstraction: " ^^
731              "the source %s should be a type; instead it is a term " ^^ 
732              "of type %s") (NCicPp.ppterm s) (NCicPp.ppterm sort)))));
733        let ty = typeof_aux ((n,(C.Decl s))::context) t in
734          C.Prod (n,s,ty)
735     | C.LetIn (n,ty,t,bo) ->
736        let ty_t = typeof_aux context t in
737        if not (R.are_convertible ~subst ~metasenv context ty ty_t) then
738          raise 
739           (TypeCheckerFailure 
740             (lazy (Printf.sprintf
741               "The type of %s is %s but it is expected to be %s" 
742                 (NCicPp.ppterm t) (NCicPp.ppterm ty_t) (NCicPp.ppterm ty))))
743        else
744          let ty_bo = typeof_aux  ((n,C.Def (t,ty))::context) bo in
745          S.subst ~avoid_beta_redexes:true t ty_bo
746     | C.Appl (he::(_::_ as args)) ->
747        let ty_he = typeof_aux context he in
748        let args_with_ty = List.map (fun t -> t, typeof_aux context t) args in
749        eat_prods ~subst ~metasenv context ty_he args_with_ty
750    | C.Appl _ -> raise (AssertFailure (lazy "Appl of length < 2"))
751    | C.Match (Ref.Ref (dummy_depth,uri,Ref.Ind tyno) as r,outtype,term,pl) ->
752       let outsort = typeof_aux context outtype in
753       let leftno = E.get_indty_leftno r in
754       let parameters, arguments =
755         let ty = R.whd ~subst context (typeof_aux context term) in
756         let r',tl =
757          match ty with
758             C.Const (Ref.Ref (_,_,Ref.Ind _) as r') -> r',[]
759           | C.Appl (C.Const (Ref.Ref (_,_,Ref.Ind _) as r') :: tl) -> r',tl
760           | _ ->
761              raise 
762                (TypeCheckerFailure (lazy (Printf.sprintf
763                  "Case analysis: analysed term %s is not an inductive one"
764                  (NCicPp.ppterm term)))) in
765         if not (Ref.eq r r') then
766          raise
767           (TypeCheckerFailure (lazy (Printf.sprintf
768             ("Case analysys: analysed term type is %s, but is expected " ^^
769              "to be (an application of) %s")
770             (NCicPp.ppterm ty) (NCicPp.ppterm (C.Const r')))))
771         else
772          try HExtlib.split_nth leftno tl
773          with
774           Failure _ ->
775            raise (TypeCheckerFailure (lazy (Printf.sprintf
776             "%s is partially applied" (NCicPp.ppterm ty)))) in
777       (* let's control if the sort elimination is allowed: [(I q1 ... qr)|B] *)
778       let sort_of_ind_type =
779         if parameters = [] then C.Const r
780         else C.Appl ((C.Const r)::parameters) in
781       let type_of_sort_of_ind_ty = typeof_aux context sort_of_ind_type in
782       if not (check_allowed_sort_elimination ~subst ~metasenv r context
783           sort_of_ind_type type_of_sort_of_ind_ty outsort)
784       then raise (TypeCheckerFailure (lazy ("Sort elimination not allowed")));
785       (* let's check if the type of branches are right *)
786       let leftno,constructorsno =
787         let inductive,leftno,itl,_,i = E.get_checked_indtys r in
788         let _,name,ty,cl = List.nth itl i in
789         let cl_len = List.length cl in
790         leftno, cl_len
791       in
792       if List.length pl <> constructorsno then
793        raise (TypeCheckerFailure (lazy ("Wrong number of cases in a match")));
794       let j,branches_ok =
795         List.fold_left
796           (fun (j,b) p ->
797             if b then
798               let cons = 
799                 let cons = Ref.Ref (dummy_depth, uri, Ref.Con (tyno, j)) in
800                 if parameters = [] then C.Const cons
801                 else C.Appl (C.Const cons::parameters)
802               in
803               let ty_p = typeof_aux context p in
804               let ty_cons = typeof_aux context cons in
805               let ty_branch = 
806                 type_of_branch ~subst context leftno outtype cons ty_cons 0 in
807               j+1, R.are_convertible ~subst ~metasenv context ty_p ty_branch 
808             else
809               j,false
810           ) (1,true) pl
811          in
812           if not branches_ok then
813            raise
814             (TypeCheckerFailure 
815               (lazy (Printf.sprintf "Branch for constructor %s has wrong type"
816               (NCicPp.ppterm (C.Const 
817                 (Ref.Ref (dummy_depth, uri, Ref.Con (tyno, j)))))))); 
818           let res = outtype::arguments@[term] in
819           R.head_beta_reduce (C.Appl res)
820     | C.Match _ -> assert false
821
822   and type_of_branch ~subst context leftno outty cons tycons liftno = 
823     match R.whd ~subst context tycons with
824     | C.Const (Ref.Ref (_,_,Ref.Ind _)) -> C.Appl [S.lift liftno outty ; cons]
825     | C.Appl (C.Const (Ref.Ref (_,_,Ref.Ind _))::tl) ->
826         let _,arguments = HExtlib.split_nth leftno tl in
827         C.Appl (S.lift liftno outty::arguments@[cons])
828     | C.Prod (name,so,de) ->
829         let cons =
830          match S.lift 1 cons with
831          | C.Appl l -> C.Appl (l@[C.Rel 1])
832          | t -> C.Appl [t ; C.Rel 1]
833         in
834          C.Prod (name,so,
835            type_of_branch ~subst ((name,(C.Decl so))::context) 
836             leftno outty cons de (liftno+1))
837     | _ -> raise (AssertFailure (lazy "type_of_branch"))
838
839   (* check_metasenv_consistency checks that the "canonical" context of a
840      metavariable is consitent - up to relocation via the relocation list l -
841      with the actual context *)
842   and check_metasenv_consistency term context canonical_context l =
843    match l with
844     | shift, NCic.Irl n ->
845        let context = snd (HExtlib.split_nth shift context) in
846         let rec compare = function
847          | 0,_,[] -> ()
848          | 0,_,_::_
849          | _,_,[] ->
850             raise (AssertFailure (lazy (Printf.sprintf
851              "Local and canonical context %s have different lengths"
852              (NCicPp.ppterm term))))
853          | m,[],_::_ ->
854             raise (TypeCheckerFailure (lazy (Printf.sprintf
855              "Unbound variable -%d in %s" m (NCicPp.ppterm term))))
856          | m,t::tl,ct::ctl ->
857             (match t,ct with
858                 (_,C.Decl t1), (_,C.Decl t2)
859               | (_,C.Def (t1,_)), (_,C.Def (t2,_))
860               | (_,C.Def (_,t1)), (_,C.Decl t2) ->
861                  if not (R.are_convertible ~subst ~metasenv tl t1 t2) then
862                   raise 
863                       (TypeCheckerFailure 
864                         (lazy (Printf.sprintf 
865                       ("Not well typed metavariable local context for %s: " ^^ 
866                        "%s expected, which is not convertible with %s")
867                       (NCicPp.ppterm term) (NCicPp.ppterm t2) (NCicPp.ppterm t1)
868                       )))
869               | _,_ ->
870                raise 
871                    (TypeCheckerFailure 
872                      (lazy (Printf.sprintf 
873                     ("Not well typed metavariable local context for %s: " ^^ 
874                      "a definition expected, but a declaration found")
875                     (NCicPp.ppterm term)))));
876             compare (m - 1,tl,ctl)
877         in
878          compare (n,context,canonical_context)
879     | shift, lc_kind ->
880        (* we avoid useless lifting by shortening the context*)
881        let l,context = (0,lc_kind), snd (HExtlib.split_nth shift context) in
882        let lifted_canonical_context = 
883          let rec lift_metas i = function
884            | [] -> []
885            | (n,C.Decl t)::tl ->
886                (n,C.Decl (S.subst_meta l (S.lift i t)))::(lift_metas (i+1) tl)
887            | (n,C.Def (t,ty))::tl ->
888                (n,C.Def ((S.subst_meta l (S.lift i t)),
889                           S.subst_meta l (S.lift i ty)))::(lift_metas (i+1) tl)
890          in
891           lift_metas 1 canonical_context in
892        let l = U.expand_local_context lc_kind in
893        try
894         List.iter2 
895         (fun t ct -> 
896           match (t,ct) with
897           | t, (_,C.Def (ct,_)) ->
898              (*CSC: the following optimization is to avoid a possibly expensive
899                     reduction that can be easily avoided and that is quite
900                     frequent. However, this is better handled using levels to
901                     control reduction *)
902              let optimized_t =
903               match t with
904               | C.Rel n ->
905                   (try
906                     match List.nth context (n - 1) with
907                     | (_,C.Def (te,_)) -> S.lift n te
908                     | _ -> t
909                     with Failure _ -> t)
910               | _ -> t
911              in
912              if not (R.are_convertible ~subst ~metasenv context optimized_t ct)
913              then
914                raise 
915                  (TypeCheckerFailure 
916                    (lazy (Printf.sprintf 
917                      ("Not well typed metavariable local context: " ^^ 
918                       "expected a term convertible with %s, found %s")
919                      (NCicPp.ppterm ct) (NCicPp.ppterm t))))
920           | t, (_,C.Decl ct) ->
921               let type_t = typeof_aux context t in
922               if not (R.are_convertible ~subst ~metasenv context type_t ct) then
923                 raise (TypeCheckerFailure 
924                   (lazy (Printf.sprintf 
925                    ("Not well typed metavariable local context: "^^
926                     "expected a term of type %s, found %s of type %s") 
927                     (NCicPp.ppterm ct) (NCicPp.ppterm t) (NCicPp.ppterm type_t))))
928         ) l lifted_canonical_context 
929        with
930         Invalid_argument _ ->
931           raise (AssertFailure (lazy (Printf.sprintf
932            "Local and canonical context %s have different lengths"
933            (NCicPp.ppterm term))))
934
935   and is_non_informative context paramsno c =
936    let rec aux context c =
937      match R.whd context c with
938       | C.Prod (n,so,de) ->
939          let s = typeof_aux context so in
940          s = C.Sort C.Prop && aux ((n,(C.Decl so))::context) de
941       | _ -> true in
942    let context',dx = split_prods ~subst:[] context paramsno c in
943     aux context' dx
944
945   and check_allowed_sort_elimination ~subst ~metasenv r =
946    let mkapp he arg =
947      match he with
948      | C.Appl l -> C.Appl (l @ [arg])
949      | t -> C.Appl [t;arg] in
950    let rec aux context ind arity1 arity2 =
951     let arity1 = R.whd ~subst context arity1 in
952     let arity2 = R.whd ~subst context arity2 in
953       match arity1,arity2 with
954        | C.Prod (name,so1,de1), C.Prod (_,so2,de2) ->
955           R.are_convertible ~subst ~metasenv context so1 so2 &&
956            aux ((name, C.Decl so1)::context)
957             (mkapp (S.lift 1 ind) (C.Rel 1)) de1 de2
958        | C.Sort _, C.Prod (name,so,ta) ->
959         (R.are_convertible ~subst ~metasenv context so ind &&
960           match arity1,ta with
961           | (C.Sort (C.CProp | C.Type _), C.Sort _)
962           | (C.Sort C.Prop, C.Sort C.Prop) -> true
963           | (C.Sort C.Prop, C.Sort (C.CProp | C.Type _)) ->
964               let inductive,leftno,itl,_,i = E.get_checked_indtys r in
965               let itl_len = List.length itl in
966               let _,name,ty,cl = List.nth itl i in
967               let cl_len = List.length cl in
968                (* is it a singleton or empty non recursive and non informative
969                   definition? *)
970                cl_len = 0 ||
971                 (itl_len = 1 && cl_len = 1 &&
972                  is_non_informative [name,C.Decl ty] leftno
973                   (let _,_,x = List.nth cl 0 in x))
974           | _,_ -> false)
975        | _,_ -> false
976    in
977     aux 
978
979  in 
980    typeof_aux context term
981
982 and check_mutual_inductive_defs _ = assert false
983
984 and eat_lambdas ~subst context n te =
985   match (n, R.whd ~subst context te) with
986   | (0, _) -> (te, context)
987   | (n, C.Lambda (name,so,ta)) when n > 0 ->
988       eat_lambdas ~subst ((name,(C.Decl so))::context) (n - 1) ta
989    | (n, te) ->
990       raise (AssertFailure 
991         (lazy (Printf.sprintf "9 (%d, %s)" n (NCicPp.ppterm te))))
992
993 and guarded_by_destructors ~subst context recfuns t = 
994  let recursor f k t = NCicUtils.fold shift_k k (fun k () -> f k) () t in
995  let rec aux (context, recfuns, x, safes as k) = function
996   | C.Rel m when List.mem_assoc m recfuns -> raise NotGuarded 
997   | C.Rel m ->
998      (match List.nth context (m-1) with 
999      | _,C.Decl _ -> ()
1000      | _,C.Def (bo,_) -> aux (context, recfuns, x, safes) (S.lift m bo))
1001   | C.Meta _ -> ()
1002   | C.Appl ((C.Rel m)::tl) when List.mem_assoc m recfuns ->
1003      let rec_no = List.assoc m recfuns in
1004      if not (List.length tl > rec_no) then raise NotGuarded
1005      else
1006        let rec_arg = List.nth tl rec_no in
1007        if not (is_really_smaller ~subst k rec_arg) then raise
1008        NotGuarded;
1009        List.iter (aux k) tl
1010   | C.Match (Ref.Ref (_,uri,_) as ref,outtype,term,pl) as t ->
1011      (match R.whd ~subst context term with
1012      | C.Rel m | C.Appl (C.Rel m :: _ ) as t when List.mem m safes || m = x ->
1013         let isinductive, paramsno, tl, _, i = E.get_checked_indtys ref in
1014         if not isinductive then recursor aux k t
1015         else
1016          let c_ctx,len,cl = fix_lefts_in_constrs ~subst uri paramsno tl i in
1017          let args = match t with C.Appl (_::tl) -> tl | _ -> [] in
1018          aux k outtype; 
1019          List.iter (aux k) args; 
1020          List.iter2
1021            (fun p (_,_,bruijnedc) ->
1022              let rl = recursive_args ~subst c_ctx 0 len bruijnedc in
1023              let p, k = get_new_safes ~subst k p rl in
1024              aux k p) 
1025            pl cl
1026      | _ -> recursor aux k t)
1027   | t -> recursor aux k t
1028  in
1029   try aux (context, recfuns, 1, []) t;true
1030   with NotGuarded -> false
1031
1032 (*
1033  | C.Fix (_, fl) ->
1034     let len = List.length fl in
1035      let n_plus_len = n + len
1036      and nn_plus_len = nn + len
1037      and x_plus_len = x + len
1038      and tys,_ =
1039       List.fold_left
1040         (fun (types,len) (n,_,ty,_) ->
1041            (Some (C.Name n,(C.Decl (CicSubstitution.lift len ty)))::types,
1042             len+1)
1043         ) ([],0) fl
1044      and safes' = List.map (fun x -> x + len) safes in
1045       List.fold_right
1046        (fun (_,_,ty,bo) i ->
1047          i && guarded_by_destructors ~subst context n nn kl x_plus_len safes' ty &&
1048           guarded_by_destructors ~subst (tys@context) n_plus_len nn_plus_len kl
1049            x_plus_len safes' bo
1050        ) fl true
1051  | C.CoFix (_, fl) ->
1052     let len = List.length fl in
1053      let n_plus_len = n + len
1054      and nn_plus_len = nn + len
1055      and x_plus_len = x + len
1056      and tys,_ =
1057       List.fold_left
1058         (fun (types,len) (n,ty,_) ->
1059            (Some (C.Name n,(C.Decl (CicSubstitution.lift len ty)))::types,
1060             len+1)
1061         ) ([],0) fl
1062      and safes' = List.map (fun x -> x + len) safes in
1063       List.fold_right
1064        (fun (_,ty,bo) i ->
1065          i &&
1066           guarded_by_destructors ~subst context n nn kl x_plus_len safes' ty &&
1067           guarded_by_destructors ~subst (tys@context) n_plus_len nn_plus_len kl
1068            x_plus_len safes' bo
1069        ) fl true
1070 *)
1071
1072 and guarded_by_constructors ~subst _ _ _ _ _ _ _ = assert false
1073
1074 and recursive_args ~subst context n nn te =
1075   match R.whd context te with
1076   | C.Rel _ -> []
1077   | C.Prod (name,so,de) ->
1078      (not (does_not_occur ~subst context n nn so)) ::
1079       (recursive_args ~subst ((name,(C.Decl so))::context) (n+1) (nn + 1) de)
1080   | _ -> raise (AssertFailure (lazy ("recursive_args")))
1081
1082 and get_new_safes ~subst (context, recfuns, x, safes as k) p rl =
1083   match R.whd ~subst context p, rl with
1084   | C.Lambda (name,so,ta), b::tl ->
1085       let safes = (if b then [0] else []) @ safes in
1086       get_new_safes ~subst 
1087         (shift_k (name,(C.Decl so)) (context, recfuns, x, safes)) ta tl
1088   | C.Meta _ as e, _ | e, [] -> e, k
1089   | _ -> raise (AssertFailure (lazy "Ill formed pattern"))
1090
1091 and split_prods ~subst context n te =
1092   match n, R.whd ~subst context te with
1093   | 0, _ -> context,te
1094   | n, C.Prod (name,so,ta) when n > 0 ->
1095        split_prods ~subst ((name,(C.Decl so))::context) (n - 1) ta
1096   | _ -> raise (AssertFailure (lazy "split_prods"))
1097
1098 and is_really_smaller ~subst (context, recfuns, x, safes as k) te =
1099  match R.whd ~subst context te with
1100  | C.Rel m when List.mem m safes -> true
1101  | C.Rel _ -> false
1102  | C.LetIn _ -> raise (AssertFailure (lazy "letin after whd"))
1103  | C.Sort _ | C.Implicit _ | C.Prod _ | C.Lambda _ 
1104  | C.Const (Ref.Ref (_,_,(Ref.Decl | Ref.Def | Ref.Ind _ | Ref.CoFix _))) ->
1105     raise (AssertFailure (lazy "not a constructor"))
1106  | C.Appl ([]|[_]) -> raise (AssertFailure (lazy "empty/unary appl"))
1107  | C.Appl (he::_) ->
1108     (*CSC: sulla coda ci vogliono dei controlli? secondo noi no, ma *)
1109     (*CSC: solo perche' non abbiamo trovato controesempi            *)
1110     (*TASSI: da capire soprattutto se he รจ un altro fix che non ha ridotto...*)
1111     is_really_smaller ~subst k he
1112  | C.Const (Ref.Ref (_,_,Ref.Con _)) -> false
1113  | C.Const (Ref.Ref (_,_,Ref.Fix _)) -> assert false
1114    (*| C.Fix (_, fl) ->
1115       let len = List.length fl in
1116        let n_plus_len = n + len
1117        and nn_plus_len = nn + len
1118        and x_plus_len = x + len
1119        and tys,_ =
1120         List.fold_left
1121           (fun (types,len) (n,_,ty,_) ->
1122              (Some (C.Name n,(C.Decl (CicSubstitution.lift len ty)))::types,
1123               len+1)
1124           ) ([],0) fl
1125        and safes' = List.map (fun x -> x + len) safes in
1126         List.fold_right
1127          (fun (_,_,ty,bo) i ->
1128            i &&
1129             is_really_smaller ~subst (tys@context) n_plus_len nn_plus_len kl
1130              x_plus_len safes' bo
1131          ) fl true*)
1132  | C.Meta _ -> 
1133      true (* XXX if this check is repeated when the user completes the
1134              definition *)
1135  | C.Match (Ref.Ref (_,uri,_) as ref,outtype,term,pl) ->
1136     (match term with
1137     | C.Rel m | C.Appl (C.Rel m :: _ ) when List.mem m safes || m = x ->
1138         let isinductive, paramsno, tl, _, i = E.get_checked_indtys ref in
1139         if not isinductive then
1140           List.for_all (is_really_smaller ~subst k) pl
1141         else
1142           let c_ctx,len,cl = fix_lefts_in_constrs ~subst uri paramsno tl i in
1143           List.for_all2
1144            (fun p (_,_,debruijnedte) -> 
1145              let rl' = recursive_args ~subst c_ctx 0 len debruijnedte in
1146              let e, k = get_new_safes ~subst k p rl' in
1147              is_really_smaller ~subst k e)
1148            pl cl
1149     | _ -> List.for_all (is_really_smaller ~subst k) pl)
1150
1151 and returns_a_coinductive ~subst _ _ = assert false
1152
1153 and type_of_constant ref = assert false (* USARE typecheck_obj0 *)
1154 (* ALIAS typecheck *)
1155 (*
1156   let cobj,ugraph1 =
1157    match CicEnvironment.is_type_checked ~trust:true ugraph uri with
1158        CicEnvironment.CheckedObj (cobj,ugraph') -> cobj,ugraph'
1159      | CicEnvironment.UncheckedObj uobj ->
1160          logger#log (`Start_type_checking uri) ;
1161          let ugraph1_dust =
1162           typecheck_obj0 ~logger uri CicUniv.empty_ugraph uobj in
1163            try 
1164              CicEnvironment.set_type_checking_info uri ;
1165              logger#log (`Type_checking_completed uri) ;
1166              (match CicEnvironment.is_type_checked ~trust:false ugraph uri with
1167                   CicEnvironment.CheckedObj (cobj,ugraph') -> (cobj,ugraph')
1168                 | CicEnvironment.UncheckedObj _ -> raise CicEnvironmentError
1169              )
1170            with
1171             (*
1172               this is raised if set_type_checking_info is called on an object
1173               that has no associated universe file. If we are in univ_maker 
1174               phase this is OK since univ_maker will properly commit the 
1175               object.
1176             *)
1177                Invalid_argument s ->
1178                  (*debug_print (lazy s);*)
1179                  uobj,ugraph1_dust
1180   in
1181 CASO COSTRUTTORE
1182     match cobj with
1183         C.InductiveDefinition (dl,_,_,_) ->
1184           let (_,_,arity,_) = List.nth dl i in
1185             arity,ugraph1
1186       | _ ->
1187           raise (TypeCheckerFailure
1188            (lazy ("Unknown mutual inductive definition:" ^ U.string_of_uri uri)))
1189 CASO TIPO INDUTTIVO
1190     match cobj with
1191         C.InductiveDefinition (dl,_,_,_) ->
1192           let (_,_,_,cl) = List.nth dl i in
1193           let (_,ty) = List.nth cl (j-1) in
1194             ty,ugraph1
1195       | _ ->
1196           raise (TypeCheckerFailure
1197            (lazy ("Unknown mutual inductive definition:" ^ UriManager.string_of_uri uri)))
1198 CASO COSTANTE
1199 CASO FIX/COFIX
1200 *)
1201
1202 and typecheck_obj0 (uri,height,metasenv,subst,kind) =
1203  (* CSC: here we should typecheck the metasenv and the subst *)
1204  assert (metasenv = [] && subst = []);
1205  match kind with
1206    | C.Constant (_,_,Some te,ty,_) ->
1207       let _ = typeof ~subst ~metasenv [] ty in
1208       let ty_te = typeof ~subst ~metasenv [] te in
1209       if not (R.are_convertible ~subst ~metasenv [] ty_te ty) then
1210        raise (TypeCheckerFailure (lazy (Printf.sprintf
1211         "the type of the body is not the one expected:\n%s\nvs\n%s"
1212         (NCicPp.ppterm ty_te) (NCicPp.ppterm ty))))
1213    | C.Constant (_,_,None,ty,_) -> ignore (typeof ~subst ~metasenv [] ty)
1214    | C.Inductive _ as obj -> check_mutual_inductive_defs uri obj
1215    | C.Fixpoint (inductive,fl,_) ->
1216       let types,kl,len =
1217         List.fold_left
1218          (fun (types,kl,len) (_,name,k,ty,_) ->
1219            let _ = typeof ~subst ~metasenv [] ty in
1220             ((name,(C.Decl (S.lift len ty)))::types, k::kl,len+1)
1221          ) ([],[],0) fl
1222       in
1223         List.iter (fun (_,name,x,ty,bo) ->
1224          let ty_bo = typeof ~subst ~metasenv types bo in
1225          if not (R.are_convertible ~subst ~metasenv types ty_bo (S.lift len ty))
1226          then raise (TypeCheckerFailure (lazy ("(Co)Fix: ill-typed bodies")))
1227          else
1228           if inductive then begin
1229             let m, context = eat_lambdas ~subst types (x + 1) bo in
1230             (* guarded by destructors conditions D{f,k,x,M} *)
1231             let rec enum_from k = 
1232               function [] -> [] | v::tl -> (k,v)::enum_from (k+1) tl 
1233             in
1234             if not (guarded_by_destructors 
1235                       ~subst context (enum_from (x+1) kl) m) then
1236               raise(TypeCheckerFailure(lazy("Fix: not guarded by destructors")))
1237           end else
1238            match returns_a_coinductive ~subst [] ty with
1239             | None ->
1240                 raise (TypeCheckerFailure
1241                   (lazy "CoFix: does not return a coinductive type"))
1242             | Some uri ->
1243                 (* guarded by constructors conditions C{f,M} *)
1244                 if not (guarded_by_constructors ~subst
1245                     types 0 len false bo [] uri)
1246                 then
1247                   raise (TypeCheckerFailure
1248                    (lazy "CoFix: not guarded by constructors"))
1249           ) fl
1250
1251 let typecheck_obj (*uri*) obj = assert false (*
1252  let ugraph = typecheck_obj0 ~logger uri CicUniv.empty_ugraph obj in
1253  let ugraph, univlist, obj = CicUnivUtils.clean_and_fill uri obj ugraph in
1254   CicEnvironment.add_type_checked_obj uri (obj,ugraph,univlist)
1255 *)
1256 ;;