]> matita.cs.unibo.it Git - helm.git/blob - helm/software/components/ng_kernel/nCicTypeChecker.ml
debujin implemented with the map recursor
[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 type_of_branch ~subst context argsno need_dummy outtype term constype =
521  let module C = Cic in
522  let module R = CicReduction in
523   match R.whd ~subst context constype with
524      C.MutInd (_,_,_) ->
525       if need_dummy then
526        outtype
527       else
528        C.Appl [outtype ; term]
529    | C.Appl (C.MutInd (_,_,_)::tl) ->
530       let (_,arguments) = split tl argsno
531       in
532        if need_dummy && arguments = [] then
533         outtype
534        else
535         C.Appl (outtype::arguments@(if need_dummy then [] else [term]))
536    | C.Prod (name,so,de) ->
537       let term' =
538        match CicSubstitution.lift 1 term with
539           C.Appl l -> C.Appl (l@[C.Rel 1])
540         | t -> C.Appl [t ; C.Rel 1]
541       in
542        C.Prod (name,so,type_of_branch ~subst
543         ((Some (name,(C.Decl so)))::context) argsno need_dummy
544         (CicSubstitution.lift 1 outtype) term' de)
545    | _ -> raise (AssertFailure (lazy "20"))
546
547  and returns_a_coinductive ~subst context ty =
548   let module C = Cic in
549    match CicReduction.whd ~subst context ty with
550       C.MutInd (uri,i,_) ->
551        (*CSC: definire una funzioncina per questo codice sempre replicato *)
552         let obj,_ =
553           try
554             CicEnvironment.get_cooked_obj ~trust:false CicUniv.empty_ugraph uri
555           with Not_found -> assert false
556         in
557         (match obj with
558            C.InductiveDefinition (itl,_,_,_) ->
559             let (_,is_inductive,_,_) = List.nth itl i in
560              if is_inductive then None else (Some uri)
561          | _ ->
562             raise (TypeCheckerFailure
563               (lazy ("Unknown mutual inductive definition:" ^
564               UriManager.string_of_uri uri)))
565         )
566     | C.Appl ((C.MutInd (uri,i,_))::_) ->
567        (let o,_ = CicEnvironment.get_obj CicUniv.empty_ugraph uri in
568          match o with
569            C.InductiveDefinition (itl,_,_,_) ->
570             let (_,is_inductive,_,_) = List.nth itl i in
571              if is_inductive then None else (Some uri)
572          | _ ->
573             raise (TypeCheckerFailure
574               (lazy ("Unknown mutual inductive definition:" ^
575               UriManager.string_of_uri uri)))
576         )
577     | C.Prod (n,so,de) ->
578        returns_a_coinductive ~subst ((Some (n,C.Decl so))::context) de
579     | _ -> None
580
581  in
582   type_of_aux ~logger context t ugraph
583
584 ;;
585
586 (** wrappers which instantiate fresh loggers *)
587
588 (* check_allowed_sort_elimination uri i s1 s2
589    This function is used outside the kernel to determine in advance whether
590    a MutCase will be allowed or not.
591    [uri,i] is the type of the term to match
592    [s1] is the sort of the term to eliminate (i.e. the head of the arity
593         of the inductive type [uri,i])
594    [s2] is the sort of the goal (i.e. the head of the type of the outtype
595         of the MutCase) *)
596 let check_allowed_sort_elimination uri i s1 s2 =
597  fst (check_allowed_sort_elimination ~subst:[] ~metasenv:[]
598   ~logger:(new CicLogger.logger) [] uri i true
599   (Cic.Implicit None) (* never used *) (Cic.Sort s1) (Cic.Sort s2)
600   CicUniv.empty_ugraph)
601 ;;
602
603 Deannotate.type_of_aux' := fun context t -> fst (type_of_aux' [] context t CicUniv.oblivion_ugraph);;
604
605 *)
606
607 module C = NCic 
608 module R = NCicReduction
609 module Ref = NReference
610 module S = NCicSubstitution 
611 module U = NCicUtils
612 module E = NCicEnvironment
613
614 let rec split_prods ~subst context n te =
615   match (n, R.whd ~subst context te) with
616    | (0, _) -> context,te
617    | (n, C.Prod (name,so,ta)) when n > 0 ->
618        split_prods ~subst ((name,(C.Decl so))::context) (n - 1) ta
619    | (_, _) -> raise (AssertFailure (lazy "split_prods"))
620 ;;
621
622 let debruijn ?(cb=fun _ _ -> ()) uri number_of_types = 
623  let rec aux k t =
624   let res =
625    match t with
626     | C.Meta (i,(s,C.Ctx l)) ->
627        let l1 = NCicUtils.sharing_map (aux (k-s)) l in
628        if l1 == l then t else C.Meta (i,(s,C.Ctx l1))
629     | C.Meta _ -> t
630     | C.Const (Ref.Ref (_,uri1,(Ref.Fix (no,_) | Ref.CoFix no))) 
631     | C.Const (Ref.Ref (_,uri1,Ref.Ind no)) when NUri.eq uri uri1 ->
632        C.Rel (k + number_of_types - no)
633     | t -> NCicUtils.map (fun _ k -> k+1) k aux t
634   in
635    cb t res; res
636  in
637   aux 0
638 ;;
639
640
641 let sort_of_prod ~subst context (name,s) (t1, t2) =
642    let t1 = R.whd ~subst context t1 in
643    let t2 = R.whd ~subst ((name,C.Decl s)::context) t2 in
644    match t1, t2 with
645    | C.Sort s1, C.Sort C.Prop -> t2
646    | C.Sort (C.Type u1), C.Sort (C.Type u2) -> C.Sort (C.Type (max u1 u2)) 
647    | C.Sort _,C.Sort (C.Type _) -> t2
648    | C.Sort (C.Type _) , C.Sort C.CProp -> t1
649    | C.Sort _, C.Sort C.CProp -> t2
650    | C.Meta _, C.Sort _
651    | C.Meta _, C.Meta _
652    | C.Sort _, C.Meta _ when U.is_closed t2 -> t2
653    | _ -> 
654       raise (TypeCheckerFailure (lazy (Printf.sprintf
655         "Prod: expected two sorts, found = %s, %s" 
656          (NCicPp.ppterm t1) (NCicPp.ppterm t2))))
657 ;;
658
659 let eat_prods ~subst ~metasenv context ty_he args_with_ty = 
660   let rec aux ty_he = function 
661   | [] -> ty_he
662   | (arg, ty_arg)::tl ->
663       (match R.whd ~subst context ty_he with 
664       | C.Prod (n,s,t) ->
665           if R.are_convertible ~subst ~metasenv context ty_arg s then
666             aux (S.subst ~avoid_beta_redexes:true arg t) tl
667           else
668             raise 
669               (TypeCheckerFailure 
670                 (lazy (Printf.sprintf
671                   ("Appl: wrong parameter-type, expected %s, found %s")
672                   (NCicPp.ppterm ty_arg) (NCicPp.ppterm s))))
673        | _ ->
674           raise 
675             (TypeCheckerFailure
676               (lazy "Appl: this is not a function, it cannot be applied")))
677   in
678     aux ty_he args_with_ty
679 ;;
680
681 let fix_lefts_in_constrs ~subst uri paramsno tyl i =
682   let len = List.length tyl in
683   let _,_,arity,cl = List.nth tyl i in
684   let tys = List.map (fun (_,n,ty,_) -> n,C.Decl ty) tyl in
685   let cl' =
686    List.map
687     (fun (_,id,ty) ->
688       let debruijnedty = debruijn uri len ty in
689       id, snd (split_prods ~subst tys paramsno ty),
690        snd (split_prods ~subst tys paramsno debruijnedty))
691     cl 
692   in
693   let lefts = fst (split_prods ~subst [] paramsno arity) in
694   tys@lefts, len, cl'
695 ;;
696
697 exception DoesOccur;;
698
699 let does_not_occur ~subst context n nn t = 
700   let rec aux (context,n,nn as k) _ = function
701     | C.Rel m when m > n && m <= nn -> raise DoesOccur
702     | C.Rel m ->
703         (try (match List.nth context (m-1) with
704           | _,C.Def (bo,_) -> aux k () (S.lift m bo)
705           | _ -> ())
706          with Failure _ -> assert false)
707     | C.Meta (_,(_,(C.Irl 0 | C.Ctx []))) -> (* closed meta *) ()
708     | C.Meta (mno,(s,l)) ->
709          (try
710            let _,_,term,_ = U.lookup_subst mno subst in
711            aux (context,n+s,nn+s) () (S.subst_meta (0,l) term)
712           with CicUtil.Subst_not_found _ -> match l with
713           | C.Irl len -> if not (n >= s+len || s > nn) then raise DoesOccur
714           | C.Ctx lc -> List.iter (aux (context,n+s,nn+s) ()) lc)
715     | t -> U.fold (fun e (ctx,n,nn) -> (e::ctx,n+1,nn+1)) k aux () t
716   in
717    try aux (context,n,nn) () t; true
718    with DoesOccur -> false
719 ;;
720
721 exception NotGuarded;;
722
723 let rec typeof ~subst ~metasenv context term =
724   let rec typeof_aux context = function
725     | C.Rel n ->
726        (try
727          match List.nth context (n - 1) with
728          | (_,C.Decl ty) -> S.lift n ty
729          | (_,C.Def (_,ty)) -> S.lift n ty
730         with Failure _ -> raise (TypeCheckerFailure (lazy "unbound variable")))
731     | C.Sort (C.Type i) -> C.Sort (C.Type (i+1))
732     | C.Sort s -> C.Sort (C.Type 0)
733     | C.Implicit _ -> raise (AssertFailure (lazy "Implicit found"))
734     | C.Meta (n,l) as t -> 
735        let canonical_context,ty =
736         try
737          let _,c,_,ty = U.lookup_subst n subst in c,ty
738         with U.Subst_not_found _ -> try
739          let _,_,c,ty = U.lookup_meta n metasenv in c,ty
740         with U.Meta_not_found _ ->
741          raise (AssertFailure (lazy (Printf.sprintf
742           "%s not found" (NCicPp.ppterm t))))
743        in
744         check_metasenv_consistency t context canonical_context l;
745         S.subst_meta l ty
746     | C.Const ref -> type_of_constant ref
747     | C.Prod (name,s,t) ->
748        let sort1 = typeof_aux context s in
749        let sort2 = typeof_aux ((name,(C.Decl s))::context) t in
750        sort_of_prod ~subst context (name,s) (sort1,sort2)
751     | C.Lambda (n,s,t) ->
752        let sort = typeof_aux context s in
753        (match R.whd ~subst context sort with
754        | C.Meta _ | C.Sort _ -> ()
755        | _ ->
756          raise
757            (TypeCheckerFailure (lazy (Printf.sprintf
758              ("Not well-typed lambda-abstraction: " ^^
759              "the source %s should be a type; instead it is a term " ^^ 
760              "of type %s") (NCicPp.ppterm s) (NCicPp.ppterm sort)))));
761        let ty = typeof_aux ((n,(C.Decl s))::context) t in
762          C.Prod (n,s,ty)
763     | C.LetIn (n,ty,t,bo) ->
764        let ty_t = typeof_aux context t in
765        if not (R.are_convertible ~subst ~metasenv context ty ty_t) then
766          raise 
767           (TypeCheckerFailure 
768             (lazy (Printf.sprintf
769               "The type of %s is %s but it is expected to be %s" 
770                 (NCicPp.ppterm t) (NCicPp.ppterm ty_t) (NCicPp.ppterm ty))))
771        else
772          let ty_bo = typeof_aux  ((n,C.Def (t,ty))::context) bo in
773          S.subst ~avoid_beta_redexes:true t ty_bo
774     | C.Appl (he::(_::_ as args)) ->
775        let ty_he = typeof_aux context he in
776        let args_with_ty = List.map (fun t -> t, typeof_aux context t) args in
777        eat_prods ~subst ~metasenv context ty_he args_with_ty
778    | C.Appl _ -> raise (AssertFailure (lazy "Appl of length < 2"))
779    | C.Match (Ref.Ref (dummy_depth,uri,Ref.Ind tyno) as r,outtype,term,pl) ->
780       let outsort = typeof_aux context outtype in
781       let leftno = E.get_indty_leftno r in
782       let parameters, arguments =
783         let ty = R.whd ~subst context (typeof_aux context term) in
784         let r',tl =
785          match ty with
786             C.Const (Ref.Ref (_,_,Ref.Ind _) as r') -> r',[]
787           | C.Appl (C.Const (Ref.Ref (_,_,Ref.Ind _) as r') :: tl) -> r',tl
788           | _ ->
789              raise 
790                (TypeCheckerFailure (lazy (Printf.sprintf
791                  "Case analysis: analysed term %s is not an inductive one"
792                  (NCicPp.ppterm term)))) in
793         if not (Ref.eq r r') then
794          raise
795           (TypeCheckerFailure (lazy (Printf.sprintf
796             ("Case analysys: analysed term type is %s, but is expected " ^^
797              "to be (an application of) %s")
798             (NCicPp.ppterm ty) (NCicPp.ppterm (C.Const r')))))
799         else
800          try HExtlib.split_nth leftno tl
801          with
802           Failure _ ->
803            raise (TypeCheckerFailure (lazy (Printf.sprintf
804             "%s is partially applied" (NCicPp.ppterm ty)))) in
805       (* let's control if the sort elimination is allowed: [(I q1 ... qr)|B] *)
806       let sort_of_ind_type =
807         if parameters = [] then C.Const r
808         else C.Appl ((C.Const r)::parameters) in
809       let type_of_sort_of_ind_ty = typeof_aux context sort_of_ind_type in
810       if not (check_allowed_sort_elimination ~subst ~metasenv r context
811           sort_of_ind_type type_of_sort_of_ind_ty outsort)
812       then raise (TypeCheckerFailure (lazy ("Sort elimination not allowed")));
813       (* let's check if the type of branches are right *)
814       let leftno,constructorsno =
815         let inductive,leftno,itl,_,i = E.get_checked_indtys r in
816         let _,name,ty,cl = List.nth itl i in
817         let cl_len = List.length cl in
818         leftno, cl_len
819       in
820       if List.length pl <> constructorsno then
821        raise (TypeCheckerFailure (lazy ("Wrong number of cases in a match")));
822       let j,branches_ok =
823         List.fold_left
824           (fun (j,b) p ->
825             if b then
826               let cons = 
827                 let cons = Ref.Ref (dummy_depth, uri, Ref.Con (tyno, j)) in
828                 if parameters = [] then C.Const cons
829                 else C.Appl (C.Const cons::parameters)
830               in
831               let ty_p = typeof_aux context p in
832               let ty_cons = typeof_aux context cons in
833               let ty_branch = 
834                 type_of_branch ~subst context leftno outtype cons ty_cons in
835               j+1, R.are_convertible ~subst ~metasenv context ty_p ty_branch 
836             else
837               j,false
838           ) (1,true) pl
839          in
840           if not branches_ok then
841            raise
842             (TypeCheckerFailure 
843               (lazy (Printf.sprintf "Branch for constructor %s has wrong type"
844               (NCicPp.ppterm (C.Const 
845                 (Ref.Ref (dummy_depth, uri, Ref.Con (tyno, j)))))))); 
846           let res = outtype::arguments@[term] in
847           R.head_beta_reduce (C.Appl res)
848     | C.Match _ -> assert false
849
850   and type_of_branch ~subst context leftno outty cons tycons = assert false
851
852   (* check_metasenv_consistency checks that the "canonical" context of a
853      metavariable is consitent - up to relocation via the relocation list l -
854      with the actual context *)
855   and check_metasenv_consistency term context canonical_context l =
856    match l with
857     | shift, NCic.Irl n ->
858        let context = snd (HExtlib.split_nth shift context) in
859         let rec compare = function
860          | 0,_,[] -> ()
861          | 0,_,_::_
862          | _,_,[] ->
863             raise (AssertFailure (lazy (Printf.sprintf
864              "Local and canonical context %s have different lengths"
865              (NCicPp.ppterm term))))
866          | m,[],_::_ ->
867             raise (TypeCheckerFailure (lazy (Printf.sprintf
868              "Unbound variable -%d in %s" m (NCicPp.ppterm term))))
869          | m,t::tl,ct::ctl ->
870             (match t,ct with
871                 (_,C.Decl t1), (_,C.Decl t2)
872               | (_,C.Def (t1,_)), (_,C.Def (t2,_))
873               | (_,C.Def (_,t1)), (_,C.Decl t2) ->
874                  if not (R.are_convertible ~subst ~metasenv tl t1 t2) then
875                   raise 
876                       (TypeCheckerFailure 
877                         (lazy (Printf.sprintf 
878                       ("Not well typed metavariable local context for %s: " ^^ 
879                        "%s expected, which is not convertible with %s")
880                       (NCicPp.ppterm term) (NCicPp.ppterm t2) (NCicPp.ppterm t1)
881                       )))
882               | _,_ ->
883                raise 
884                    (TypeCheckerFailure 
885                      (lazy (Printf.sprintf 
886                     ("Not well typed metavariable local context for %s: " ^^ 
887                      "a definition expected, but a declaration found")
888                     (NCicPp.ppterm term)))));
889             compare (m - 1,tl,ctl)
890         in
891          compare (n,context,canonical_context)
892     | shift, lc_kind ->
893        (* we avoid useless lifting by shortening the context*)
894        let l,context = (0,lc_kind), snd (HExtlib.split_nth shift context) in
895        let lifted_canonical_context = 
896          let rec lift_metas i = function
897            | [] -> []
898            | (n,C.Decl t)::tl ->
899                (n,C.Decl (S.subst_meta l (S.lift i t)))::(lift_metas (i+1) tl)
900            | (n,C.Def (t,ty))::tl ->
901                (n,C.Def ((S.subst_meta l (S.lift i t)),
902                           S.subst_meta l (S.lift i ty)))::(lift_metas (i+1) tl)
903          in
904           lift_metas 1 canonical_context in
905        let l = U.expand_local_context lc_kind in
906        try
907         List.iter2 
908         (fun t ct -> 
909           match (t,ct) with
910           | t, (_,C.Def (ct,_)) ->
911              (*CSC: the following optimization is to avoid a possibly expensive
912                     reduction that can be easily avoided and that is quite
913                     frequent. However, this is better handled using levels to
914                     control reduction *)
915              let optimized_t =
916               match t with
917               | C.Rel n ->
918                   (try
919                     match List.nth context (n - 1) with
920                     | (_,C.Def (te,_)) -> S.lift n te
921                     | _ -> t
922                     with Failure _ -> t)
923               | _ -> t
924              in
925              if not (R.are_convertible ~subst ~metasenv context optimized_t ct)
926              then
927                raise 
928                  (TypeCheckerFailure 
929                    (lazy (Printf.sprintf 
930                      ("Not well typed metavariable local context: " ^^ 
931                       "expected a term convertible with %s, found %s")
932                      (NCicPp.ppterm ct) (NCicPp.ppterm t))))
933           | t, (_,C.Decl ct) ->
934               let type_t = typeof_aux context t in
935               if not (R.are_convertible ~subst ~metasenv context type_t ct) then
936                 raise (TypeCheckerFailure 
937                   (lazy (Printf.sprintf 
938                    ("Not well typed metavariable local context: "^^
939                     "expected a term of type %s, found %s of type %s") 
940                     (NCicPp.ppterm ct) (NCicPp.ppterm t) (NCicPp.ppterm type_t))))
941         ) l lifted_canonical_context 
942        with
943         Invalid_argument _ ->
944           raise (AssertFailure (lazy (Printf.sprintf
945            "Local and canonical context %s have different lengths"
946            (NCicPp.ppterm term))))
947
948   and is_non_informative context paramsno c =
949    let rec aux context c =
950      match R.whd context c with
951       | C.Prod (n,so,de) ->
952          let s = typeof_aux context so in
953          s = C.Sort C.Prop && aux ((n,(C.Decl so))::context) de
954       | _ -> true in
955    let context',dx = split_prods ~subst:[] context paramsno c in
956     aux context' dx
957
958   and check_allowed_sort_elimination ~subst ~metasenv r =
959    let mkapp he arg =
960      match he with
961      | C.Appl l -> C.Appl (l @ [arg])
962      | t -> C.Appl [t;arg] in
963    let rec aux context ind arity1 arity2 =
964     let arity1 = R.whd ~subst context arity1 in
965     let arity2 = R.whd ~subst context arity2 in
966       match arity1,arity2 with
967        | C.Prod (name,so1,de1), C.Prod (_,so2,de2) ->
968           R.are_convertible ~subst ~metasenv context so1 so2 &&
969            aux ((name, C.Decl so1)::context)
970             (mkapp (S.lift 1 ind) (C.Rel 1)) de1 de2
971        | C.Sort _, C.Prod (name,so,ta) ->
972         (R.are_convertible ~subst ~metasenv context so ind &&
973           match arity1,ta with
974           | (C.Sort (C.CProp | C.Type _), C.Sort _)
975           | (C.Sort C.Prop, C.Sort C.Prop) -> true
976           | (C.Sort C.Prop, C.Sort (C.CProp | C.Type _)) ->
977               let inductive,leftno,itl,_,i = E.get_checked_indtys r in
978               let itl_len = List.length itl in
979               let _,name,ty,cl = List.nth itl i in
980               let cl_len = List.length cl in
981                (* is it a singleton or empty non recursive and non informative
982                   definition? *)
983                cl_len = 0 ||
984                 (itl_len = 1 && cl_len = 1 &&
985                  is_non_informative [name,C.Decl ty] leftno
986                   (let _,_,x = List.nth cl 0 in x))
987           | _,_ -> false)
988        | _,_ -> false
989    in
990     aux 
991
992  in 
993    typeof_aux context term
994
995 and check_mutual_inductive_defs _ = assert false
996
997 and eat_lambdas ~subst context n te =
998   match (n, R.whd ~subst context te) with
999   | (0, _) -> (te, context)
1000   | (n, C.Lambda (name,so,ta)) when n > 0 ->
1001       eat_lambdas ~subst ((name,(C.Decl so))::context) (n - 1) ta
1002    | (n, te) ->
1003       raise (AssertFailure 
1004         (lazy (Printf.sprintf "9 (%d, %s)" n (NCicPp.ppterm te))))
1005
1006 and guarded_by_destructors ~subst context recfuns t = 
1007  let recursor f k t = NCicUtils.fold shift_k k (fun k () -> f k) () t in
1008  let rec aux (context, recfuns, x, safes as k) = function
1009   | C.Rel m when List.mem_assoc m recfuns -> raise NotGuarded 
1010   | C.Rel m ->
1011      (match List.nth context (m-1) with 
1012      | _,C.Decl _ -> ()
1013      | _,C.Def (bo,_) -> aux (context, recfuns, x, safes) (S.lift m bo))
1014   | C.Meta _ -> ()
1015   | C.Appl ((C.Rel m)::tl) when List.mem_assoc m recfuns ->
1016      let rec_no = List.assoc m recfuns in
1017      if not (List.length tl > rec_no) then raise NotGuarded
1018      else
1019        let rec_arg = List.nth tl rec_no in
1020        aux k rec_arg;
1021        List.iter (aux k) tl
1022   | C.Match (Ref.Ref (_,uri,_) as ref,outtype,term,pl) as t ->
1023      (match R.whd ~subst context term with
1024      | C.Rel m | C.Appl (C.Rel m :: _ ) as t when List.mem m safes || m = x ->
1025         let isinductive, paramsno, tl, _, i = E.get_checked_indtys ref in
1026         if not isinductive then recursor aux k t
1027         else
1028          let c_ctx,len,cl = fix_lefts_in_constrs ~subst uri paramsno tl i in
1029          let args = match t with C.Appl (_::tl) -> tl | _ -> [] in
1030          aux k outtype; 
1031          List.iter (aux k) args; 
1032          List.iter2
1033            (fun p (_,_,bruijnedc) ->
1034              let rl = recursive_args ~subst c_ctx 0 len bruijnedc in
1035              let p, k = get_new_safes ~subst k p rl in
1036              aux k p) 
1037            pl cl
1038      | _ -> recursor aux k t)
1039   | t -> recursor aux k t
1040  in
1041   try aux (context, recfuns, 1, []) t;true
1042   with NotGuarded -> false
1043
1044 (*
1045  | C.Fix (_, fl) ->
1046     let len = List.length fl in
1047      let n_plus_len = n + len
1048      and nn_plus_len = nn + len
1049      and x_plus_len = x + len
1050      and tys,_ =
1051       List.fold_left
1052         (fun (types,len) (n,_,ty,_) ->
1053            (Some (C.Name n,(C.Decl (CicSubstitution.lift len ty)))::types,
1054             len+1)
1055         ) ([],0) fl
1056      and safes' = List.map (fun x -> x + len) safes in
1057       List.fold_right
1058        (fun (_,_,ty,bo) i ->
1059          i && guarded_by_destructors ~subst context n nn kl x_plus_len safes' ty &&
1060           guarded_by_destructors ~subst (tys@context) n_plus_len nn_plus_len kl
1061            x_plus_len safes' bo
1062        ) fl true
1063  | C.CoFix (_, fl) ->
1064     let len = List.length fl in
1065      let n_plus_len = n + len
1066      and nn_plus_len = nn + len
1067      and x_plus_len = x + len
1068      and tys,_ =
1069       List.fold_left
1070         (fun (types,len) (n,ty,_) ->
1071            (Some (C.Name n,(C.Decl (CicSubstitution.lift len ty)))::types,
1072             len+1)
1073         ) ([],0) fl
1074      and safes' = List.map (fun x -> x + len) safes in
1075       List.fold_right
1076        (fun (_,ty,bo) i ->
1077          i &&
1078           guarded_by_destructors ~subst context n nn kl x_plus_len safes' ty &&
1079           guarded_by_destructors ~subst (tys@context) n_plus_len nn_plus_len kl
1080            x_plus_len safes' bo
1081        ) fl true
1082 *)
1083
1084 and guarded_by_constructors ~subst _ _ _ _ _ _ _ = assert false
1085
1086 and recursive_args ~subst context n nn te =
1087   match R.whd context te with
1088   | C.Rel _ -> []
1089   | C.Prod (name,so,de) ->
1090      (not (does_not_occur ~subst context n nn so)) ::
1091       (recursive_args ~subst ((name,(C.Decl so))::context) (n+1) (nn + 1) de)
1092   | _ -> raise (AssertFailure (lazy ("recursive_args")))
1093
1094 and get_new_safes ~subst (context, recfuns, x, safes as k) p rl =
1095   match R.whd ~subst context p, rl with
1096   | C.Lambda (name,so,ta), b::tl ->
1097       let safes = (if b then [0] else []) @ safes in
1098       get_new_safes ~subst 
1099         (shift_k (name,(C.Decl so)) (context, recfuns, x, safes)) ta tl
1100   | C.Meta _ as e, _ | e, [] -> e, k
1101   | _ -> raise (AssertFailure (lazy "Ill formed pattern"))
1102
1103 and split_prods ~subst context n te =
1104   match n, R.whd ~subst context te with
1105   | 0, _ -> context,te
1106   | n, C.Prod (name,so,ta) when n > 0 ->
1107        split_prods ~subst ((name,(C.Decl so))::context) (n - 1) ta
1108   | _ -> raise (AssertFailure (lazy "split_prods"))
1109
1110 (*CSC: Tutto quello che segue e' l'intuzione di luca ;-) *) 
1111 and check_is_really_smaller_arg ~subst context n nn kl x safes te =
1112 assert false        (*
1113  (*CSC: forse la whd si puo' fare solo quando serve veramente. *)
1114  (*CSC: cfr guarded_by_destructors                             *)
1115  let module C = Cic in
1116  let module U = UriManager in
1117  match CicReduction.whd ~subst context te with
1118      C.Rel m when List.mem m safes -> true
1119    | C.Rel _ -> false
1120    | C.Var _
1121    | C.Meta _
1122    | C.Sort _
1123    | C.Implicit _
1124    | C.Cast _
1125 (*   | C.Cast (te,ty) ->
1126       check_is_really_smaller_arg ~subst n nn kl x safes te &&
1127        check_is_really_smaller_arg ~subst n nn kl x safes ty*)
1128 (*   | C.Prod (_,so,ta) ->
1129       check_is_really_smaller_arg ~subst n nn kl x safes so &&
1130        check_is_really_smaller_arg ~subst (n+1) (nn+1) kl (x+1)
1131         (List.map (fun x -> x + 1) safes) ta*)
1132    | C.Prod _ -> raise (AssertFailure (lazy "10"))
1133    | C.Lambda (name,so,ta) ->
1134       check_is_really_smaller_arg ~subst context n nn kl x safes so &&
1135        check_is_really_smaller_arg ~subst ((Some (name,(C.Decl so)))::context)
1136         (n+1) (nn+1) kl (x+1) (List.map (fun x -> x + 1) safes) ta
1137    | C.LetIn (name,so,ty,ta) ->
1138       check_is_really_smaller_arg ~subst context n nn kl x safes so &&
1139        check_is_really_smaller_arg ~subst context n nn kl x safes ty &&
1140         check_is_really_smaller_arg ~subst ((Some (name,(C.Def (so,ty))))::context)
1141         (n+1) (nn+1) kl (x+1) (List.map (fun x -> x + 1) safes) ta
1142    | C.Appl (he::_) ->
1143       (*CSC: sulla coda ci vogliono dei controlli? secondo noi no, ma *)
1144       (*CSC: solo perche' non abbiamo trovato controesempi            *)
1145       check_is_really_smaller_arg ~subst context n nn kl x safes he
1146    | C.Appl [] -> raise (AssertFailure (lazy "11"))
1147    | C.Const _
1148    | C.MutInd _ -> raise (AssertFailure (lazy "12"))
1149    | C.MutConstruct _ -> false
1150    | C.MutCase (uri,i,outtype,term,pl) ->
1151       (match term with
1152           C.Rel m when List.mem m safes || m = x ->
1153            let (lefts_and_tys,len,isinductive,paramsno,cl) =
1154             let o,_ = CicEnvironment.get_obj CicUniv.empty_ugraph uri in
1155             match o with
1156                C.InductiveDefinition (tl,_,paramsno,_) ->
1157                 let tys =
1158                  List.map
1159                   (fun (n,_,ty,_) -> Some (Cic.Name n,(Cic.Decl ty))) tl
1160                 in
1161                  let (_,isinductive,_,cl) = List.nth tl i in
1162                   let cl' =
1163                    List.map
1164                     (fun (id,ty) ->
1165                       (id, snd (split_prods ~subst tys paramsno ty))) cl in
1166                   let lefts =
1167                    match tl with
1168                       [] -> assert false
1169                     | (_,_,ty,_)::_ ->
1170                        fst (split_prods ~subst [] paramsno ty)
1171                   in
1172                    (tys@lefts,List.length tl,isinductive,paramsno,cl')
1173              | _ ->
1174                 raise (TypeCheckerFailure
1175                   (lazy ("Unknown mutual inductive definition:" ^
1176                   UriManager.string_of_uri uri)))
1177            in
1178             if not isinductive then
1179               List.fold_right
1180                (fun p i ->
1181                  i && check_is_really_smaller_arg ~subst context n nn kl x safes p)
1182                pl true
1183             else
1184              let pl_and_cl =
1185               try
1186                List.combine pl cl
1187               with
1188                Invalid_argument _ ->
1189                 raise (TypeCheckerFailure (lazy "not enough patterns"))
1190              in
1191               (*CSC: supponiamo come prima che nessun controllo sia necessario*)
1192               (*CSC: sugli argomenti di una applicazione                      *)
1193               List.fold_right
1194                (fun (p,(_,c)) i ->
1195                  let rl' =
1196                   let debruijnedte = debruijn uri len c in
1197                    recursive_args lefts_and_tys 0 len debruijnedte
1198                  in
1199                   let (e,safes',n',nn',x',context') =
1200                    get_new_safes ~subst context p c rl' safes n nn x
1201                   in
1202                    i &&
1203                    check_is_really_smaller_arg ~subst context' n' nn' kl x' safes' e
1204                ) pl_and_cl true
1205         | C.Appl ((C.Rel m)::tl) when List.mem m safes || m = x ->
1206            let (lefts_and_tys,len,isinductive,paramsno,cl) =
1207             let o,_ = CicEnvironment.get_obj CicUniv.empty_ugraph uri in
1208             match o with
1209                C.InductiveDefinition (tl,_,paramsno,_) ->
1210                 let (_,isinductive,_,cl) = List.nth tl i in
1211                  let tys =
1212                   List.map (fun (n,_,ty,_) ->
1213                    Some(Cic.Name n,(Cic.Decl ty))) tl
1214                  in
1215                   let cl' =
1216                    List.map
1217                     (fun (id,ty) ->
1218                       (id, snd (split_prods ~subst tys paramsno ty))) cl in
1219                   let lefts =
1220                    match tl with
1221                       [] -> assert false
1222                     | (_,_,ty,_)::_ ->
1223                        fst (split_prods ~subst [] paramsno ty)
1224                   in
1225                    (tys@lefts,List.length tl,isinductive,paramsno,cl')
1226              | _ ->
1227                 raise (TypeCheckerFailure
1228                   (lazy ("Unknown mutual inductive definition:" ^
1229                   UriManager.string_of_uri uri)))
1230            in
1231             if not isinductive then
1232               List.fold_right
1233                (fun p i ->
1234                  i && check_is_really_smaller_arg ~subst context n nn kl x safes p)
1235                pl true
1236             else
1237              let pl_and_cl =
1238               try
1239                List.combine pl cl
1240               with
1241                Invalid_argument _ ->
1242                 raise (TypeCheckerFailure (lazy "not enough patterns"))
1243              in
1244               (*CSC: supponiamo come prima che nessun controllo sia necessario*)
1245               (*CSC: sugli argomenti di una applicazione                      *)
1246               List.fold_right
1247                (fun (p,(_,c)) i ->
1248                  let rl' =
1249                   let debruijnedte = debruijn uri len c in
1250                    recursive_args lefts_and_tys 0 len debruijnedte
1251                  in
1252                   let (e,safes',n',nn',x',context') =
1253                    get_new_safes ~subst context p c rl' safes n nn x
1254                   in
1255                    i &&
1256                    check_is_really_smaller_arg ~subst context' n' nn' kl x' safes' e
1257                ) pl_and_cl true
1258         | _ ->
1259           List.fold_right
1260            (fun p i ->
1261              i && check_is_really_smaller_arg ~subst context n nn kl x safes p
1262            ) pl true
1263       )
1264    | C.Fix (_, fl) ->
1265       let len = List.length fl in
1266        let n_plus_len = n + len
1267        and nn_plus_len = nn + len
1268        and x_plus_len = x + len
1269        and tys,_ =
1270         List.fold_left
1271           (fun (types,len) (n,_,ty,_) ->
1272              (Some (C.Name n,(C.Decl (CicSubstitution.lift len ty)))::types,
1273               len+1)
1274           ) ([],0) fl
1275        and safes' = List.map (fun x -> x + len) safes in
1276         List.fold_right
1277          (fun (_,_,ty,bo) i ->
1278            i &&
1279             check_is_really_smaller_arg ~subst (tys@context) n_plus_len nn_plus_len kl
1280              x_plus_len safes' bo
1281          ) fl true
1282    | C.CoFix (_, fl) ->
1283       let len = List.length fl in
1284        let n_plus_len = n + len
1285        and nn_plus_len = nn + len
1286        and x_plus_len = x + len
1287        and tys,_ =
1288         List.fold_left
1289           (fun (types,len) (n,ty,_) ->
1290              (Some (C.Name n,(C.Decl (CicSubstitution.lift len ty)))::types,
1291               len+1)
1292           ) ([],0) fl
1293        and safes' = List.map (fun x -> x + len) safes in
1294         List.fold_right
1295          (fun (_,ty,bo) i ->
1296            i &&
1297             check_is_really_smaller_arg ~subst (tys@context) n_plus_len nn_plus_len kl
1298              x_plus_len safes' bo
1299          ) fl true
1300          *)
1301
1302 and returns_a_coinductive ~subst _ _ = assert false
1303
1304 and type_of_constant ref = assert false (* USARE typecheck_obj0 *)
1305 (* ALIAS typecheck *)
1306 (*
1307   let cobj,ugraph1 =
1308    match CicEnvironment.is_type_checked ~trust:true ugraph uri with
1309        CicEnvironment.CheckedObj (cobj,ugraph') -> cobj,ugraph'
1310      | CicEnvironment.UncheckedObj uobj ->
1311          logger#log (`Start_type_checking uri) ;
1312          let ugraph1_dust =
1313           typecheck_obj0 ~logger uri CicUniv.empty_ugraph uobj in
1314            try 
1315              CicEnvironment.set_type_checking_info uri ;
1316              logger#log (`Type_checking_completed uri) ;
1317              (match CicEnvironment.is_type_checked ~trust:false ugraph uri with
1318                   CicEnvironment.CheckedObj (cobj,ugraph') -> (cobj,ugraph')
1319                 | CicEnvironment.UncheckedObj _ -> raise CicEnvironmentError
1320              )
1321            with
1322             (*
1323               this is raised if set_type_checking_info is called on an object
1324               that has no associated universe file. If we are in univ_maker 
1325               phase this is OK since univ_maker will properly commit the 
1326               object.
1327             *)
1328                Invalid_argument s ->
1329                  (*debug_print (lazy s);*)
1330                  uobj,ugraph1_dust
1331   in
1332 CASO COSTRUTTORE
1333     match cobj with
1334         C.InductiveDefinition (dl,_,_,_) ->
1335           let (_,_,arity,_) = List.nth dl i in
1336             arity,ugraph1
1337       | _ ->
1338           raise (TypeCheckerFailure
1339            (lazy ("Unknown mutual inductive definition:" ^ U.string_of_uri uri)))
1340 CASO TIPO INDUTTIVO
1341     match cobj with
1342         C.InductiveDefinition (dl,_,_,_) ->
1343           let (_,_,_,cl) = List.nth dl i in
1344           let (_,ty) = List.nth cl (j-1) in
1345             ty,ugraph1
1346       | _ ->
1347           raise (TypeCheckerFailure
1348            (lazy ("Unknown mutual inductive definition:" ^ UriManager.string_of_uri uri)))
1349 CASO COSTANTE
1350 CASO FIX/COFIX
1351 *)
1352
1353 and typecheck_obj0 (uri,height,metasenv,subst,kind) =
1354  (* CSC: here we should typecheck the metasenv and the subst *)
1355  assert (metasenv = [] && subst = []);
1356  match kind with
1357    | C.Constant (_,_,Some te,ty,_) ->
1358       let _ = typeof ~subst ~metasenv [] ty in
1359       let ty_te = typeof ~subst ~metasenv [] te in
1360       if not (R.are_convertible ~subst ~metasenv [] ty_te ty) then
1361        raise (TypeCheckerFailure (lazy (Printf.sprintf
1362         "the type of the body is not the one expected:\n%s\nvs\n%s"
1363         (NCicPp.ppterm ty_te) (NCicPp.ppterm ty))))
1364    | C.Constant (_,_,None,ty,_) -> ignore (typeof ~subst ~metasenv [] ty)
1365    | C.Inductive _ as obj -> check_mutual_inductive_defs uri obj
1366    | C.Fixpoint (inductive,fl,_) ->
1367       let types,kl,len =
1368         List.fold_left
1369          (fun (types,kl,len) (_,name,k,ty,_) ->
1370            let _ = typeof ~subst ~metasenv [] ty in
1371             ((name,(C.Decl (S.lift len ty)))::types, k::kl,len+1)
1372          ) ([],[],0) fl
1373       in
1374         List.iter (fun (_,name,x,ty,bo) ->
1375          let ty_bo = typeof ~subst ~metasenv types bo in
1376          if not (R.are_convertible ~subst ~metasenv types ty_bo (S.lift len ty))
1377          then raise (TypeCheckerFailure (lazy ("(Co)Fix: ill-typed bodies")))
1378          else
1379           if inductive then begin
1380             let m, context = eat_lambdas ~subst types (x + 1) bo in
1381             (* guarded by destructors conditions D{f,k,x,M} *)
1382             let rec enum_from k = 
1383               function [] -> [] | v::tl -> (k,v)::enum_from (k+1) tl 
1384             in
1385             if not (guarded_by_destructors 
1386                       ~subst context (enum_from (x+1) kl) m) then
1387               raise(TypeCheckerFailure(lazy("Fix: not guarded by destructors")))
1388           end else
1389            match returns_a_coinductive ~subst [] ty with
1390             | None ->
1391                 raise (TypeCheckerFailure
1392                   (lazy "CoFix: does not return a coinductive type"))
1393             | Some uri ->
1394                 (* guarded by constructors conditions C{f,M} *)
1395                 if not (guarded_by_constructors ~subst
1396                     types 0 len false bo [] uri)
1397                 then
1398                   raise (TypeCheckerFailure
1399                    (lazy "CoFix: not guarded by constructors"))
1400           ) fl
1401
1402 let typecheck_obj (*uri*) obj = assert false (*
1403  let ugraph = typecheck_obj0 ~logger uri CicUniv.empty_ugraph obj in
1404  let ugraph, univlist, obj = CicUnivUtils.clean_and_fill uri obj ugraph in
1405   CicEnvironment.add_type_checked_obj uri (obj,ugraph,univlist)
1406 *)
1407 ;;