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