]> matita.cs.unibo.it Git - helm.git/blob - helm/ocaml/cic_proof_checking/cicTypeChecker.ml
Experimental commit: we can now have definitions in contexts. As a
[helm.git] / helm / ocaml / cic_proof_checking / cicTypeChecker.ml
1 (* Copyright (C) 2000, HELM Team.
2  * 
3  * This file is part of HELM, an Hypertextual, Electronic
4  * Library of Mathematics, developed at the Computer Science
5  * Department, University of Bologna, Italy.
6  * 
7  * HELM is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  * 
12  * HELM is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with HELM; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
20  * MA  02111-1307, USA.
21  * 
22  * For details, see the HELM World-Wide-Web page,
23  * http://cs.unibo.it/helm/.
24  *)
25
26 exception Impossible of int;;
27 exception NotWellTyped of string;;
28 exception WrongUriToConstant of string;;
29 exception WrongUriToVariable of string;;
30 exception WrongUriToMutualInductiveDefinitions of string;;
31 exception ListTooShort;;
32 exception NotPositiveOccurrences of string;;
33 exception NotWellFormedTypeOfInductiveConstructor of string;;
34 exception WrongRequiredArgument of string;;
35
36 let fdebug = ref 0;;
37 let debug t context =
38  let rec debug_aux t i =
39   let module C = Cic in
40   let module U = UriManager in
41    CicPp.ppobj (C.Variable ("DEBUG", None, t)) ^ "\n" ^ i
42  in
43   if !fdebug = 0 then
44    raise (NotWellTyped ("\n" ^ List.fold_right debug_aux (t::context) ""))
45    (*print_endline ("\n" ^ List.fold_right debug_aux (t::context) "") ; flush stdout*)
46 ;;
47
48 let rec split l n =
49  match (l,n) with
50     (l,0) -> ([], l)
51   | (he::tl, n) -> let (l1,l2) = split tl (n-1) in (he::l1,l2)
52   | (_,_) -> raise ListTooShort
53 ;;
54
55 exception CicEnvironmentError;;
56
57 let rec cooked_type_of_constant uri cookingsno =
58  let module C = Cic in
59  let module R = CicReduction in
60  let module U = UriManager in
61   let cobj =
62    match CicEnvironment.is_type_checked uri cookingsno with
63       CicEnvironment.CheckedObj cobj -> cobj
64     | CicEnvironment.UncheckedObj uobj ->
65        Logger.log (`Start_type_checking uri) ;
66        (* let's typecheck the uncooked obj *)
67        (match uobj with
68            C.Definition (_,te,ty,_) ->
69              let _ = type_of ty in
70               if not (R.are_convertible [] (type_of te) ty) then
71                raise (NotWellTyped ("Constant " ^ (U.string_of_uri uri)))
72          | C.Axiom (_,ty,_) ->
73            (* only to check that ty is well-typed *)
74            let _ = type_of ty in ()
75          | C.CurrentProof (_,conjs,te,ty) ->
76              let _ = type_of_aux' conjs [] ty in
77               if not (R.are_convertible [] (type_of_aux' conjs [] te) ty)
78               then
79                raise (NotWellTyped ("CurrentProof" ^ (U.string_of_uri uri)))
80          | _ -> raise (WrongUriToConstant (U.string_of_uri uri))
81        ) ;
82        CicEnvironment.set_type_checking_info uri ;
83        Logger.log (`Type_checking_completed uri) ;
84        match CicEnvironment.is_type_checked uri cookingsno with
85           CicEnvironment.CheckedObj cobj -> cobj
86         | CicEnvironment.UncheckedObj _ -> raise CicEnvironmentError
87   in
88    match cobj with
89       C.Definition (_,_,ty,_) -> ty
90     | C.Axiom (_,ty,_) -> ty
91     | C.CurrentProof (_,_,_,ty) -> ty
92     | _ -> raise (WrongUriToConstant (U.string_of_uri uri))
93
94 and type_of_variable uri =
95  let module C = Cic in
96  let module R = CicReduction in
97  let module U = UriManager in
98   (* 0 because a variable is never cooked => no partial cooking at one level *)
99   match CicEnvironment.is_type_checked uri 0 with
100      CicEnvironment.CheckedObj (C.Variable (_,_,ty)) -> ty
101    | CicEnvironment.UncheckedObj (C.Variable (_,bo,ty)) ->
102       Logger.log (`Start_type_checking uri) ;
103       (* only to check that ty is well-typed *)
104       let _ = type_of ty in
105        (match bo with
106            None -> ()
107          | Some bo ->
108             if not (R.are_convertible [] (type_of bo) ty) then
109              raise (NotWellTyped ("Variable " ^ (U.string_of_uri uri)))
110        ) ;
111        CicEnvironment.set_type_checking_info uri ;
112        Logger.log (`Type_checking_completed uri) ;
113        ty
114    |  _ -> raise (WrongUriToVariable (UriManager.string_of_uri uri))
115
116 and does_not_occur context n nn te =
117  let module C = Cic in
118    (*CSC: whd sembra essere superflua perche' un caso in cui l'occorrenza *)
119    (*CSC: venga mangiata durante la whd sembra presentare problemi di *)
120    (*CSC: universi                                                    *)
121    match CicReduction.whd context te with
122       C.Rel m when m > n && m <= nn -> false
123     | C.Rel _
124     | C.Var _
125     | C.Meta _
126     | C.Sort _
127     | C.Implicit -> true
128     | C.Cast (te,ty) ->
129        does_not_occur context n nn te && does_not_occur context n nn ty
130     | C.Prod (_,so,dest) ->
131        does_not_occur context n nn so &&
132         does_not_occur ((C.Decl so)::context) (n + 1) (nn + 1) dest
133     | C.Lambda (_,so,dest) ->
134        does_not_occur context n nn so &&
135         does_not_occur ((C.Decl so)::context) (n + 1) (nn + 1) dest
136     | C.LetIn (_,so,dest) ->
137        does_not_occur context n nn so &&
138         does_not_occur ((C.Def so)::context) (n + 1) (nn + 1) dest
139     | C.Appl l ->
140        List.fold_right (fun x i -> i && does_not_occur context n nn x) l true
141     | C.Const _
142     | C.Abst _
143     | C.MutInd _
144     | C.MutConstruct _ -> true
145     | C.MutCase (_,_,_,out,te,pl) ->
146        does_not_occur context n nn out && does_not_occur context n nn te &&
147         List.fold_right (fun x i -> i && does_not_occur context n nn x) pl true
148     | C.Fix (_,fl) ->
149        let len = List.length fl in
150         let n_plus_len = n + len in
151         let nn_plus_len = nn + len in
152         let tys = List.map (fun (_,_,ty,_) -> Cic.Decl ty) fl in
153          List.fold_right
154           (fun (_,_,ty,bo) i ->
155             i && does_not_occur context n nn ty &&
156             does_not_occur (tys @ context) n_plus_len nn_plus_len bo
157           ) fl true
158     | C.CoFix (_,fl) ->
159        let len = List.length fl in
160         let n_plus_len = n + len in
161         let nn_plus_len = nn + len in
162         let tys = List.map (fun (_,ty,_) -> Cic.Decl ty) fl in
163          List.fold_right
164           (fun (_,ty,bo) i ->
165             i && does_not_occur context n nn ty &&
166             does_not_occur (tys @ context) n_plus_len nn_plus_len bo
167           ) fl true
168
169 (*CSC l'indice x dei tipi induttivi e' t.c. n < x <= nn *)
170 (*CSC questa funzione e' simile alla are_all_occurrences_positive, ma fa *)
171 (*CSC dei controlli leggermente diversi. Viene invocata solamente dalla  *)
172 (*CSC strictly_positive                                                  *)
173 (*CSC definizione (giusta???) tratta dalla mail di Hugo ;-)              *)
174 and weakly_positive context n nn uri te =
175  let module C = Cic in
176 (*CSC: Che schifo! Bisogna capire meglio e trovare una soluzione ragionevole!*)
177   let dummy_mutind =
178    C.MutInd (UriManager.uri_of_string "cic:/Coq/Init/Datatypes/nat.ind",0,0)
179   in
180   (*CSC mettere in cicSubstitution *)
181   let rec subst_inductive_type_with_dummy_mutind =
182    function
183       C.MutInd (uri',_,0) when UriManager.eq uri' uri ->
184        dummy_mutind
185     | C.Appl ((C.MutInd (uri',_,0))::tl) when UriManager.eq uri' uri ->
186        dummy_mutind
187     | C.Cast (te,ty) -> subst_inductive_type_with_dummy_mutind te
188     | C.Prod (name,so,ta) ->
189        C.Prod (name, subst_inductive_type_with_dummy_mutind so,
190         subst_inductive_type_with_dummy_mutind ta)
191     | C.Lambda (name,so,ta) ->
192        C.Lambda (name, subst_inductive_type_with_dummy_mutind so,
193         subst_inductive_type_with_dummy_mutind ta)
194     | C.Appl tl ->
195        C.Appl (List.map subst_inductive_type_with_dummy_mutind tl)
196     | C.MutCase (uri,cookingsno,i,outtype,term,pl) ->
197        C.MutCase (uri,cookingsno,i,
198         subst_inductive_type_with_dummy_mutind outtype,
199         subst_inductive_type_with_dummy_mutind term,
200         List.map subst_inductive_type_with_dummy_mutind pl)
201     | C.Fix (i,fl) ->
202        C.Fix (i,List.map (fun (name,i,ty,bo) -> (name,i,
203         subst_inductive_type_with_dummy_mutind ty,
204         subst_inductive_type_with_dummy_mutind bo)) fl)
205     | C.CoFix (i,fl) ->
206        C.CoFix (i,List.map (fun (name,ty,bo) -> (name,
207         subst_inductive_type_with_dummy_mutind ty,
208         subst_inductive_type_with_dummy_mutind bo)) fl)
209     | t -> t
210   in
211   match CicReduction.whd context te with
212      C.Appl ((C.MutInd (uri',_,0))::tl) when UriManager.eq uri' uri -> true
213    | C.MutInd (uri',_,0) when UriManager.eq uri' uri -> true
214    | C.Prod (C.Anonimous,source,dest) ->
215       strictly_positive context n nn
216        (subst_inductive_type_with_dummy_mutind source) &&
217        weakly_positive ((C.Decl source)::context) (n + 1) (nn + 1) uri dest
218    | C.Prod (name,source,dest) when
219       does_not_occur ((C.Decl source)::context) 0 n dest ->
220        (* dummy abstraction, so we behave as in the anonimous case *)
221        strictly_positive context n nn
222         (subst_inductive_type_with_dummy_mutind source) &&
223         weakly_positive ((C.Decl source)::context) (n + 1) (nn + 1) uri dest
224    | C.Prod (_,source,dest) ->
225       does_not_occur context n nn
226        (subst_inductive_type_with_dummy_mutind source)&&
227        weakly_positive ((C.Decl source)::context) (n + 1) (nn + 1) uri dest
228    | _ -> raise (NotWellFormedTypeOfInductiveConstructor ("Guess where the error is ;-)"))
229
230 (* instantiate_parameters ps (x1:T1)...(xn:Tn)C                             *)
231 (* returns ((x_|ps|:T_|ps|)...(xn:Tn)C){ps_1 / x1 ; ... ; ps_|ps| / x_|ps|} *)
232 and instantiate_parameters params c =
233  let module C = Cic in
234   match (c,params) with
235      (c,[]) -> c
236    | (C.Prod (_,_,ta), he::tl) ->
237        instantiate_parameters tl
238         (CicSubstitution.subst he ta)
239    | (C.Cast (te,_), _) -> instantiate_parameters params te
240    | (t,l) -> raise (Impossible 1)
241
242 and strictly_positive context n nn te =
243  let module C = Cic in
244  let module U = UriManager in
245   match CicReduction.whd context te with
246      C.Rel _ -> true
247    | C.Cast (te,ty) ->
248       (*CSC: bisogna controllare ty????*)
249       strictly_positive context n nn te
250    | C.Prod (_,so,ta) ->
251       does_not_occur context n nn so &&
252        strictly_positive ((C.Decl so)::context) (n+1) (nn+1) ta
253    | C.Appl ((C.Rel m)::tl) when m > n && m <= nn ->
254       List.fold_right (fun x i -> i && does_not_occur context n nn x) tl true
255    | C.Appl ((C.MutInd (uri,_,i))::tl) -> 
256       let (ok,paramsno,ity,cl) =
257        match CicEnvironment.get_obj uri with
258            C.InductiveDefinition (tl,_,paramsno) ->
259             let (_,_,ity,cl) = List.nth tl i in
260              (List.length tl = 1, paramsno, ity, cl)
261          | _ -> raise(WrongUriToMutualInductiveDefinitions(U.string_of_uri uri))
262       in
263        let (params,arguments) = split tl paramsno in
264        let lifted_params = List.map (CicSubstitution.lift 1) params in
265        let cl' =
266         List.map (fun (_,te,_) -> instantiate_parameters lifted_params te) cl
267        in
268         ok &&
269          List.fold_right
270           (fun x i -> i && does_not_occur context n nn x)
271           arguments true &&
272          (*CSC: MEGAPATCH3 (sara' quella giusta?)*)
273          List.fold_right
274           (fun x i ->
275             i &&
276              weakly_positive ((Cic.Decl ity)::context) (n+1) (nn+1) uri x
277           ) cl' true
278    | t -> does_not_occur context n nn t
279
280 (*CSC l'indice x dei tipi induttivi e' t.c. n < x <= nn *)
281 and are_all_occurrences_positive context uri indparamsno i n nn te =
282  let module C = Cic in
283   match CicReduction.whd context te with
284      C.Appl ((C.Rel m)::tl) when m = i ->
285       (*CSC: riscrivere fermandosi a 0 *)
286       (* let's check if the inductive type is applied at least to *)
287       (* indparamsno parameters                                   *)
288       let last =
289        List.fold_left
290         (fun k x ->
291           if k = 0 then 0
292           else
293            match CicReduction.whd context x with
294               C.Rel m when m = n - (indparamsno - k) -> k - 1
295             | _ -> raise (WrongRequiredArgument (UriManager.string_of_uri uri))
296         ) indparamsno tl
297       in
298        if last = 0 then
299         List.fold_right (fun x i -> i && does_not_occur context n nn x) tl true
300        else
301         raise (WrongRequiredArgument (UriManager.string_of_uri uri))
302    | C.Rel m when m = i ->
303       if indparamsno = 0 then
304        true
305       else
306        raise (WrongRequiredArgument (UriManager.string_of_uri uri))
307    | C.Prod (C.Anonimous,source,dest) ->
308       strictly_positive context n nn source &&
309        are_all_occurrences_positive ((C.Decl source)::context) uri indparamsno
310         (i+1) (n + 1) (nn + 1) dest
311    | C.Prod (name,source,dest) when
312       does_not_occur ((C.Decl source)::context) 0 n dest ->
313       (* dummy abstraction, so we behave as in the anonimous case *)
314       strictly_positive context n nn source &&
315        are_all_occurrences_positive ((C.Decl source)::context) uri indparamsno
316         (i+1) (n + 1) (nn + 1) dest
317    | C.Prod (_,source,dest) ->
318       does_not_occur context n nn source &&
319        are_all_occurrences_positive ((C.Decl source)::context) uri indparamsno
320         (i+1) (n + 1) (nn + 1) dest
321    | _ -> raise (NotWellFormedTypeOfInductiveConstructor (UriManager.string_of_uri uri))
322
323 (*CSC: cambiare il nome, torna unit! *)
324 and cooked_mutual_inductive_defs uri =
325  let module U = UriManager in
326   function
327      Cic.InductiveDefinition (itl, _, indparamsno) ->
328       (* let's check if the arity of the inductive types are well *)
329       (* formed                                                   *)
330       List.iter (fun (_,_,x,_) -> let _ = type_of x in ()) itl ;
331
332       (* let's check if the types of the inductive constructors  *)
333       (* are well formed.                                        *)
334       (* In order not to use type_of_aux we put the types of the *)
335       (* mutual inductive types at the head of the types of the  *)
336       (* constructors using Prods                                *)
337       (*CSC: piccola??? inefficienza                             *)
338       let len = List.length itl in
339 (*CSC: siamo sicuri che non debba fare anche un List.rev? Il bug *)
340 (*CSC: si manifesterebbe solamene con tipi veramente mutualmente *)
341 (*CSC: induttivi...                                              *)
342        let tys = List.map (fun (_,_,ty,_) -> Cic.Decl ty) itl in
343        let _ =
344         List.fold_right
345          (fun (_,_,_,cl) i ->
346            List.iter
347             (fun (name,te,r) -> 
348               let augmented_term =
349                List.fold_right
350                 (fun (name,_,ty,_) i -> Cic.Prod (Cic.Name name, ty, i))
351                 itl te
352               in
353                let _ = type_of augmented_term in
354                 (* let's check also the positivity conditions *)
355                 if
356                  not
357                   (are_all_occurrences_positive tys uri indparamsno i 0 len te)
358                 then
359                  raise (NotPositiveOccurrences (U.string_of_uri uri))
360                 else
361                  match !r with
362                     Some _ -> raise (Impossible 2)
363                   | None -> r := Some (recursive_args tys 0 len te)
364             ) cl ;
365            (i + 1)
366         ) itl 1
367        in
368         ()
369    | _ ->
370      raise (WrongUriToMutualInductiveDefinitions (U.string_of_uri uri))
371
372 and cooked_type_of_mutual_inductive_defs uri cookingsno i =
373  let module C = Cic in
374  let module R = CicReduction in
375  let module U = UriManager in
376   let cobj =
377    match CicEnvironment.is_type_checked uri cookingsno with
378       CicEnvironment.CheckedObj cobj -> cobj
379     | CicEnvironment.UncheckedObj uobj ->
380        Logger.log (`Start_type_checking uri) ;
381        cooked_mutual_inductive_defs uri uobj ;
382        CicEnvironment.set_type_checking_info uri ;
383        Logger.log (`Type_checking_completed uri) ;
384        (match CicEnvironment.is_type_checked uri cookingsno with
385           CicEnvironment.CheckedObj cobj -> cobj
386         | CicEnvironment.UncheckedObj _ -> raise CicEnvironmentError
387        )
388   in
389    match cobj with
390       C.InductiveDefinition (dl,_,_) ->
391        let (_,_,arity,_) = List.nth dl i in
392         arity
393     | _ -> raise (WrongUriToMutualInductiveDefinitions (U.string_of_uri uri))
394
395 and cooked_type_of_mutual_inductive_constr uri cookingsno i j =
396  let module C = Cic in
397  let module R = CicReduction in
398  let module U = UriManager in
399   let cobj =
400    match CicEnvironment.is_type_checked uri cookingsno with
401       CicEnvironment.CheckedObj cobj -> cobj
402     | CicEnvironment.UncheckedObj uobj ->
403        Logger.log (`Start_type_checking uri) ;
404        cooked_mutual_inductive_defs uri uobj ;
405        CicEnvironment.set_type_checking_info uri ;
406        Logger.log (`Type_checking_completed uri) ;
407        (match CicEnvironment.is_type_checked uri cookingsno with
408           CicEnvironment.CheckedObj cobj -> cobj
409         | CicEnvironment.UncheckedObj _ -> raise CicEnvironmentError
410        )
411   in
412    match cobj with
413       C.InductiveDefinition (dl,_,_) ->
414        let (_,_,_,cl) = List.nth dl i in
415         let (_,ty,_) = List.nth cl (j-1) in
416          ty
417     | _ -> raise (WrongUriToMutualInductiveDefinitions (U.string_of_uri uri))
418
419 and recursive_args context n nn te =
420  let module C = Cic in
421   match CicReduction.whd context te with
422      C.Rel _ -> []
423    | C.Var _
424    | C.Meta _
425    | C.Sort _
426    | C.Implicit
427    | C.Cast _ (*CSC ??? *) -> raise (Impossible 3) (* due to type-checking *)
428    | C.Prod (_,so,de) ->
429       (not (does_not_occur context n nn so)) ::
430        (recursive_args ((C.Decl so)::context) (n+1) (nn + 1) de)
431    | C.Lambda _
432    | C.LetIn _ -> raise (Impossible 4) (* due to type-checking *)
433    | C.Appl _ -> []
434    | C.Const _
435    | C.Abst _ -> raise (Impossible 5)
436    | C.MutInd _
437    | C.MutConstruct _
438    | C.MutCase _
439    | C.Fix _
440    | C.CoFix _ -> raise (Impossible 6) (* due to type-checking *)
441
442 and get_new_safes context p c rl safes n nn x =
443  let module C = Cic in
444  let module U = UriManager in
445  let module R = CicReduction in
446   match (R.whd context c, R.whd context p, rl) with
447      (C.Prod (_,so,ta1), C.Lambda (_,_,ta2), b::tl) ->
448        (* we are sure that the two sources are convertible because we *)
449        (* have just checked this. So let's go along ...               *)
450        let safes' =
451         List.map (fun x -> x + 1) safes
452        in
453         let safes'' =
454          if b then 1::safes' else safes'
455         in
456          get_new_safes ((C.Decl so)::context) ta2 ta1 tl safes'' (n+1) (nn+1)
457           (x+1)
458    | (C.Prod _, (C.MutConstruct _ as e), _)
459    | (C.Prod _, (C.Rel _ as e), _)
460    | (C.MutInd _, e, [])
461    | (C.Appl _, e, []) -> (e,safes,n,nn,x,context)
462    | (_,_,_) ->
463       (* CSC: If the next exception is raised, it just means that   *)
464       (* CSC: the proof-assistant allows to use very strange things *)
465       (* CSC: as a branch of a case whose type is a Prod. In        *)
466       (* CSC: particular, this means that a new (C.Prod, x,_) case  *)
467       (* CSC: must be considered in this match. (e.g. x = MutCase)  *)
468       raise (Impossible 7)
469
470 and split_prods context n te =
471  let module C = Cic in
472  let module R = CicReduction in
473   match (n, R.whd context te) with
474      (0, _) -> context,te
475    | (n, C.Prod (_,so,ta)) when n > 0 ->
476        split_prods ((C.Decl so)::context) (n - 1) ta
477    | (_, _) -> raise (Impossible 8)
478
479 and eat_lambdas context n te =
480  let module C = Cic in
481  let module R = CicReduction in
482   match (n, R.whd context te) with
483      (0, _) -> (te, 0, context)
484    | (n, C.Lambda (_,so,ta)) when n > 0 ->
485       let (te, k, context') = eat_lambdas ((C.Decl so)::context) (n - 1) ta in
486        (te, k + 1, context')
487    | (_, _) -> raise (Impossible 9)
488
489 (*CSC: Tutto quello che segue e' l'intuzione di luca ;-) *)
490 and check_is_really_smaller_arg context n nn kl x safes te =
491  (*CSC: forse la whd si puo' fare solo quando serve veramente. *)
492  (*CSC: cfr guarded_by_destructors                             *)
493  let module C = Cic in
494  let module U = UriManager in
495  match CicReduction.whd context te with
496      C.Rel m when List.mem m safes -> true
497    | C.Rel _ -> false
498    | C.Var _
499    | C.Meta _
500    | C.Sort _
501    | C.Implicit 
502    | C.Cast _
503 (*   | C.Cast (te,ty) ->
504       check_is_really_smaller_arg n nn kl x safes te &&
505        check_is_really_smaller_arg n nn kl x safes ty*)
506 (*   | C.Prod (_,so,ta) ->
507       check_is_really_smaller_arg n nn kl x safes so &&
508        check_is_really_smaller_arg (n+1) (nn+1) kl (x+1)
509         (List.map (fun x -> x + 1) safes) ta*)
510    | C.Prod _ -> raise (Impossible 10)
511    | C.Lambda (_,so,ta) ->
512       check_is_really_smaller_arg context n nn kl x safes so &&
513        check_is_really_smaller_arg ((C.Decl so)::context) (n+1) (nn+1) kl (x+1)
514         (List.map (fun x -> x + 1) safes) ta
515    | C.LetIn (_,so,ta) ->
516       check_is_really_smaller_arg context n nn kl x safes so &&
517        check_is_really_smaller_arg ((C.Def so)::context) (n+1) (nn+1) kl (x+1)
518         (List.map (fun x -> x + 1) safes) ta
519    | C.Appl (he::_) ->
520       (*CSC: sulla coda ci vogliono dei controlli? secondo noi no, ma *)
521       (*CSC: solo perche' non abbiamo trovato controesempi            *)
522       check_is_really_smaller_arg context n nn kl x safes he
523    | C.Appl [] -> raise (Impossible 11)
524    | C.Const _
525    | C.Abst _
526    | C.MutInd _ -> raise (Impossible 12)
527    | C.MutConstruct _ -> false
528    | C.MutCase (uri,_,i,outtype,term,pl) ->
529       (match term with
530           C.Rel m when List.mem m safes || m = x ->
531            let (isinductive,paramsno,cl) =
532             match CicEnvironment.get_obj uri with
533                C.InductiveDefinition (tl,_,paramsno) ->
534                 let tys = List.map (fun (_,_,ty,_) -> Cic.Decl ty) tl in
535                  let (_,isinductive,_,cl) = List.nth tl i in
536                   let cl' =
537                    List.map
538                     (fun (id,ty,r) ->
539                       (id, snd (split_prods tys paramsno ty), r)) cl
540                   in
541                    (isinductive,paramsno,cl')
542              | _ ->
543                raise (WrongUriToMutualInductiveDefinitions(U.string_of_uri uri))
544            in
545             if not isinductive then
546               List.fold_right
547                (fun p i ->
548                  i && check_is_really_smaller_arg context n nn kl x safes p)
549                pl true
550             else
551               List.fold_right
552                (fun (p,(_,c,rl)) i ->
553                  let rl' =
554                   match !rl with
555                      Some rl' ->
556                       let (_,rl'') = split rl' paramsno in
557                        rl''
558                    | None -> raise (Impossible 13)
559                  in
560                   let (e,safes',n',nn',x',context') =
561                    get_new_safes context p c rl' safes n nn x
562                   in
563                    i &&
564                    check_is_really_smaller_arg context' n' nn' kl x' safes' e
565                ) (List.combine pl cl) true
566         | C.Appl ((C.Rel m)::tl) when List.mem m safes || m = x ->
567            let (isinductive,paramsno,cl) =
568             match CicEnvironment.get_obj uri with
569                C.InductiveDefinition (tl,_,paramsno) ->
570                 let (_,isinductive,_,cl) = List.nth tl i in
571                  let tys = List.map (fun (_,_,ty,_) -> Cic.Decl ty) tl in
572                   let cl' =
573                    List.map
574                     (fun (id,ty,r) ->
575                       (id, snd (split_prods tys paramsno ty), r)) cl
576                   in
577                   (isinductive,paramsno,cl')
578              | _ ->
579                raise (WrongUriToMutualInductiveDefinitions(U.string_of_uri uri))
580            in
581             if not isinductive then
582               List.fold_right
583                (fun p i ->
584                  i && check_is_really_smaller_arg context n nn kl x safes p)
585                pl true
586             else
587               (*CSC: supponiamo come prima che nessun controllo sia necessario*)
588               (*CSC: sugli argomenti di una applicazione                      *)
589               List.fold_right
590                (fun (p,(_,c,rl)) i ->
591                  let rl' =
592                   match !rl with
593                      Some rl' ->
594                       let (_,rl'') = split rl' paramsno in
595                        rl''
596                    | None -> raise (Impossible 14)
597                  in
598                   let (e, safes',n',nn',x',context') =
599                    get_new_safes context p c rl' safes n nn x
600                   in
601                    i &&
602                    check_is_really_smaller_arg context' n' nn' kl x' safes' e
603                ) (List.combine pl cl) true
604         | _ ->
605           List.fold_right
606            (fun p i ->
607              i && check_is_really_smaller_arg context n nn kl x safes p
608            ) pl true
609       )
610    | C.Fix (_, fl) ->
611       let len = List.length fl in
612        let n_plus_len = n + len
613        and nn_plus_len = nn + len
614        and x_plus_len = x + len
615        (*CSC: Is a Decl of the ty ok or should I use Def of a Fix? *)
616        and tys = List.map (fun (_,_,ty,_) -> C.Decl ty) fl
617        and safes' = List.map (fun x -> x + len) safes in
618         List.fold_right
619          (fun (_,_,ty,bo) i ->
620            i &&
621             check_is_really_smaller_arg (tys@context) n_plus_len nn_plus_len kl
622              x_plus_len safes' bo
623          ) fl true
624    | C.CoFix (_, fl) ->
625       let len = List.length fl in
626        let n_plus_len = n + len
627        and nn_plus_len = nn + len
628        and x_plus_len = x + len
629        (*CSC: Is a Decl of the ty ok or should I use Def of a Fix? *)
630        and tys = List.map (fun (_,ty,_) -> C.Decl ty) fl
631        and safes' = List.map (fun x -> x + len) safes in
632         List.fold_right
633          (fun (_,ty,bo) i ->
634            i &&
635             check_is_really_smaller_arg (tys@context) n_plus_len nn_plus_len kl
636              x_plus_len safes' bo
637          ) fl true
638
639 and guarded_by_destructors context n nn kl x safes =
640  let module C = Cic in
641  let module U = UriManager in
642   function
643      C.Rel m when m > n && m <= nn -> false
644    | C.Rel n ->
645       (match List.nth context (n-1) with
646           C.Decl _ -> true
647         | C.Def bo -> guarded_by_destructors context n nn kl x safes bo
648       )
649    | C.Var _
650    | C.Meta _
651    | C.Sort _
652    | C.Implicit -> true
653    | C.Cast (te,ty) ->
654       guarded_by_destructors context n nn kl x safes te &&
655        guarded_by_destructors context n nn kl x safes ty
656    | C.Prod (_,so,ta) ->
657       guarded_by_destructors context n nn kl x safes so &&
658        guarded_by_destructors ((C.Decl so)::context) (n+1) (nn+1) kl (x+1)
659         (List.map (fun x -> x + 1) safes) ta
660    | C.Lambda (_,so,ta) ->
661       guarded_by_destructors context n nn kl x safes so &&
662        guarded_by_destructors ((C.Decl so)::context) (n+1) (nn+1) kl (x+1)
663         (List.map (fun x -> x + 1) safes) ta
664    | C.LetIn (_,so,ta) ->
665       guarded_by_destructors context n nn kl x safes so &&
666        guarded_by_destructors ((C.Def so)::context) (n+1) (nn+1) kl (x+1)
667         (List.map (fun x -> x + 1) safes) ta
668    | C.Appl ((C.Rel m)::tl) when m > n && m <= nn ->
669       let k = List.nth kl (m - n - 1) in
670        if not (List.length tl > k) then false
671        else
672         List.fold_right
673          (fun param i ->
674            i && guarded_by_destructors context n nn kl x safes param
675          ) tl true &&
676          check_is_really_smaller_arg context n nn kl x safes (List.nth tl k)
677    | C.Appl tl ->
678       List.fold_right
679        (fun t i -> i && guarded_by_destructors context n nn kl x safes t)
680        tl true
681    | C.Const _
682    | C.Abst _
683    | C.MutInd _
684    | C.MutConstruct _ -> true
685    | C.MutCase (uri,_,i,outtype,term,pl) ->
686       (match term with
687           C.Rel m when List.mem m safes || m = x ->
688            let (isinductive,paramsno,cl) =
689             match CicEnvironment.get_obj uri with
690                C.InductiveDefinition (tl,_,paramsno) ->
691                 let (_,isinductive,_,cl) = List.nth tl i in
692                  let tys = List.map (fun (_,_,ty,_) -> Cic.Decl ty) tl in
693                   let cl' =
694                    List.map
695                     (fun (id,ty,r) ->
696                       (id, snd (split_prods tys paramsno ty), r)) cl
697                   in
698                    (isinductive,paramsno,cl')
699              | _ ->
700                raise (WrongUriToMutualInductiveDefinitions(U.string_of_uri uri))
701            in
702             if not isinductive then
703              guarded_by_destructors context n nn kl x safes outtype &&
704               guarded_by_destructors context n nn kl x safes term &&
705               (*CSC: manca ??? il controllo sul tipo di term? *)
706               List.fold_right
707                (fun p i ->
708                  i && guarded_by_destructors context n nn kl x safes p)
709                pl true
710             else
711              guarded_by_destructors context n nn kl x safes outtype &&
712               (*CSC: manca ??? il controllo sul tipo di term? *)
713               List.fold_right
714                (fun (p,(_,c,rl)) i ->
715                  let rl' =
716                   match !rl with
717                      Some rl' ->
718                       let (_,rl'') = split rl' paramsno in
719                        rl''
720                    | None -> raise (Impossible 15)
721                  in
722                   let (e,safes',n',nn',x',context') =
723                    get_new_safes context p c rl' safes n nn x
724                   in
725                    i &&
726                    guarded_by_destructors context' n' nn' kl x' safes' e
727                ) (List.combine pl cl) true
728         | C.Appl ((C.Rel m)::tl) when List.mem m safes || m = x ->
729            let (isinductive,paramsno,cl) =
730             match CicEnvironment.get_obj uri with
731                C.InductiveDefinition (tl,_,paramsno) ->
732                 let (_,isinductive,_,cl) = List.nth tl i in
733                  let tys = List.map (fun (_,_,ty,_) -> Cic.Decl ty) tl in
734                   let cl' =
735                    List.map
736                     (fun (id,ty,r) ->
737                       (id, snd (split_prods tys paramsno ty), r)) cl
738                   in
739                    (isinductive,paramsno,cl')
740              | _ ->
741                raise (WrongUriToMutualInductiveDefinitions(U.string_of_uri uri))
742            in
743             if not isinductive then
744              guarded_by_destructors context n nn kl x safes outtype &&
745               guarded_by_destructors context n nn kl x safes term &&
746               (*CSC: manca ??? il controllo sul tipo di term? *)
747               List.fold_right
748                (fun p i ->
749                  i && guarded_by_destructors context n nn kl x safes p)
750                pl true
751             else
752              guarded_by_destructors context n nn kl x safes outtype &&
753               (*CSC: manca ??? il controllo sul tipo di term? *)
754               List.fold_right
755                (fun t i ->
756                  i && guarded_by_destructors context n nn kl x safes t)
757                tl true &&
758               List.fold_right
759                (fun (p,(_,c,rl)) i ->
760                  let rl' =
761                   match !rl with
762                      Some rl' ->
763                       let (_,rl'') = split rl' paramsno in
764                        rl''
765                    | None -> raise (Impossible 16)
766                  in
767                   let (e, safes',n',nn',x',context') =
768                    get_new_safes context p c rl' safes n nn x
769                   in
770                    i &&
771                    guarded_by_destructors context' n' nn' kl x' safes' e
772                ) (List.combine pl cl) true
773         | _ ->
774           guarded_by_destructors context n nn kl x safes outtype &&
775            guarded_by_destructors context n nn kl x safes term &&
776            (*CSC: manca ??? il controllo sul tipo di term? *)
777            List.fold_right
778             (fun p i -> i && guarded_by_destructors context n nn kl x safes p)
779             pl true
780       )
781    | C.Fix (_, fl) ->
782       let len = List.length fl in
783        let n_plus_len = n + len
784        and nn_plus_len = nn + len
785        and x_plus_len = x + len
786        (*CSC: Is a Decl of the ty ok or should I use Def of a Fix? *)
787        and tys = List.map (fun (_,_,ty,_) -> C.Decl ty) fl
788        and safes' = List.map (fun x -> x + len) safes in
789         List.fold_right
790          (fun (_,_,ty,bo) i ->
791            i && guarded_by_destructors context n nn kl x_plus_len safes' ty &&
792             guarded_by_destructors (tys@context) n_plus_len nn_plus_len kl
793              x_plus_len safes' bo
794          ) fl true
795    | C.CoFix (_, fl) ->
796       let len = List.length fl in
797        let n_plus_len = n + len
798        and nn_plus_len = nn + len
799        and x_plus_len = x + len
800        (*CSC: Is a Decl of the ty ok or should I use Def of a Fix? *)
801        and tys = List.map (fun (_,ty,_) -> C.Decl ty) fl
802        and safes' = List.map (fun x -> x + len) safes in
803         List.fold_right
804          (fun (_,ty,bo) i ->
805            i &&
806             guarded_by_destructors context n nn kl x_plus_len safes' ty &&
807             guarded_by_destructors (tys@context) n_plus_len nn_plus_len kl
808              x_plus_len safes' bo
809          ) fl true
810
811 (* the boolean h means already protected *)
812 (* args is the list of arguments the type of the constructor that may be *)
813 (* found in head position must be applied to.                            *)
814 (*CSC: coInductiveTypeURI non cambia mai di ricorsione in ricorsione *)
815 and guarded_by_constructors context n nn h te args coInductiveTypeURI =
816  let module C = Cic in
817   (*CSC: There is a lot of code replication between the cases X and    *)
818   (*CSC: (C.Appl X tl). Maybe it will be better to define a function   *)
819   (*CSC: that maps X into (C.Appl X []) when X is not already a C.Appl *)
820   match CicReduction.whd context te with
821      C.Rel m when m > n && m <= nn -> h
822    | C.Rel _
823    | C.Var _  -> true
824    | C.Meta _
825    | C.Sort _
826    | C.Implicit
827    | C.Cast _
828    | C.Prod _
829    | C.LetIn _ ->
830       raise (Impossible 17) (* the term has just been type-checked *)
831    | C.Lambda (_,so,de) ->
832       does_not_occur context n nn so &&
833        guarded_by_constructors ((C.Decl so)::context) (n + 1) (nn + 1) h de args
834         coInductiveTypeURI
835    | C.Appl ((C.Rel m)::tl) when m > n && m <= nn ->
836       h &&
837        List.fold_right (fun x i -> i && does_not_occur context n nn x) tl true
838    | C.Appl ((C.MutConstruct (uri,cookingsno,i,j))::tl) ->
839       let consty =
840        match CicEnvironment.get_cooked_obj uri cookingsno with
841           C.InductiveDefinition (itl,_,_) ->
842            let (_,_,_,cl) = List.nth itl i in
843             let (_,cons,_) = List.nth cl (j - 1) in cons
844         | _ ->
845          raise (WrongUriToMutualInductiveDefinitions
846           (UriManager.string_of_uri uri))
847       in
848        let rec analyse_branch context ty te =
849         match CicReduction.whd context ty with
850            C.Meta _ -> raise (Impossible 34)
851          | C.Rel _
852          | C.Var _
853          | C.Sort _ ->
854             does_not_occur context n nn te
855          | C.Implicit
856          | C.Cast _ -> raise (Impossible 24) (* due to type-checking *)
857          | C.Prod (_,so,de) ->
858             analyse_branch ((C.Decl so)::context) de te
859          | C.Lambda _
860          | C.LetIn _ -> raise (Impossible 25) (* due to type-checking *)
861          | C.Appl ((C.MutInd (uri,_,_))::tl) as ty
862             when uri == coInductiveTypeURI -> 
863              guarded_by_constructors context n nn true te [] coInductiveTypeURI
864          | C.Appl ((C.MutInd (uri,_,_))::tl) as ty -> 
865             guarded_by_constructors context n nn true te tl coInductiveTypeURI
866          | C.Appl _ ->
867             does_not_occur context n nn te
868          | C.Const _
869          | C.Abst _ -> raise (Impossible 26)
870          | C.MutInd (uri,_,_) when uri == coInductiveTypeURI ->
871             guarded_by_constructors context n nn true te [] coInductiveTypeURI
872          | C.MutInd _ ->
873             does_not_occur context n nn te
874          | C.MutConstruct _ -> raise (Impossible 27)
875          (*CSC: we do not consider backbones with a MutCase, Fix, Cofix *)
876          (*CSC: in head position.                                       *)
877          | C.MutCase _
878          | C.Fix _
879          | C.CoFix _ -> raise (Impossible 28) (* due to type-checking *)
880        in
881        let rec analyse_instantiated_type context ty l =
882         match CicReduction.whd context ty with
883            C.Rel _
884          | C.Var _
885          | C.Meta _
886          | C.Sort _
887          | C.Implicit
888          | C.Cast _ -> raise (Impossible 29) (* due to type-checking *)
889          | C.Prod (_,so,de) ->
890             begin
891              match l with
892                 [] -> true
893               | he::tl ->
894                  analyse_branch context so he &&
895                   analyse_instantiated_type ((C.Decl so)::context) de tl
896             end
897          | C.Lambda _
898          | C.LetIn _ -> raise (Impossible 30) (* due to type-checking *)
899          | C.Appl _ -> 
900             List.fold_left
901              (fun i x -> i && does_not_occur context n nn x) true l
902          | C.Const _
903          | C.Abst _ -> raise (Impossible 31)
904          | C.MutInd _ ->
905             List.fold_left
906              (fun i x -> i && does_not_occur context n nn x) true l
907          | C.MutConstruct _ -> raise (Impossible 32)
908          (*CSC: we do not consider backbones with a MutCase, Fix, Cofix *)
909          (*CSC: in head position.                                       *)
910          | C.MutCase _
911          | C.Fix _
912          | C.CoFix _ -> raise (Impossible 33) (* due to type-checking *)
913        in
914         let rec instantiate_type args consty =
915          function
916             [] -> true
917           | tlhe::tltl as l ->
918              let consty' = CicReduction.whd context consty in
919               match args with 
920                  he::tl ->
921                   begin
922                    match consty' with
923                       C.Prod (_,_,de) ->
924                        let instantiated_de = CicSubstitution.subst he de in
925                         (*CSC: siamo sicuri che non sia troppo forte? *)
926                         does_not_occur context n nn tlhe &
927                          instantiate_type tl instantiated_de tltl
928                     | _ ->
929                       (*CSC:We do not consider backbones with a MutCase, a    *)
930                       (*CSC:FixPoint, a CoFixPoint and so on in head position.*)
931                       raise (Impossible 23)
932                   end
933                | [] -> analyse_instantiated_type context consty' l
934                   (* These are all the other cases *)
935        in
936         instantiate_type args consty tl
937    | C.Appl ((C.CoFix (_,fl))::tl) ->
938       List.fold_left (fun i x -> i && does_not_occur context n nn x) true tl &&
939        let len = List.length fl in
940         let n_plus_len = n + len
941         and nn_plus_len = nn + len
942         (*CSC: Is a Decl of the ty ok or should I use Def of a Fix? *)
943         and tys = List.map (fun (_,ty,_) -> C.Decl ty) fl in
944          List.fold_right
945           (fun (_,ty,bo) i ->
946             i && does_not_occur context n nn ty &&
947              guarded_by_constructors (tys@context) n_plus_len nn_plus_len h bo
948               args coInductiveTypeURI
949           ) fl true
950    | C.Appl ((C.MutCase (_,_,_,out,te,pl))::tl) ->
951        List.fold_left (fun i x -> i && does_not_occur context n nn x) true tl &&
952         does_not_occur context n nn out &&
953          does_not_occur context n nn te &&
954           List.fold_right
955            (fun x i ->
956              i &&
957              guarded_by_constructors context n nn h x args coInductiveTypeURI
958            ) pl true
959    | C.Appl l ->
960       List.fold_right (fun x i -> i && does_not_occur context n nn x) l true
961    | C.Const _ -> true
962    | C.Abst _
963    | C.MutInd _ -> assert false
964    | C.MutConstruct _ -> true
965    | C.MutCase (_,_,_,out,te,pl) ->
966        does_not_occur context n nn out &&
967         does_not_occur context n nn te &&
968          List.fold_right
969           (fun x i ->
970             i &&
971              guarded_by_constructors context n nn h x args coInductiveTypeURI
972           ) pl true
973    | C.Fix (_,fl) ->
974       let len = List.length fl in
975        let n_plus_len = n + len
976        and nn_plus_len = nn + len
977        (*CSC: Is a Decl of the ty ok or should I use Def of a Fix? *)
978        and tys = List.map (fun (_,_,ty,_) -> C.Decl ty) fl in
979         List.fold_right
980          (fun (_,_,ty,bo) i ->
981            i && does_not_occur context n nn ty &&
982             does_not_occur (tys@context) n_plus_len nn_plus_len bo
983          ) fl true
984    | C.CoFix (_,fl) ->
985       let len = List.length fl in
986        let n_plus_len = n + len
987        and nn_plus_len = nn + len
988        (*CSC: Is a Decl of the ty ok or should I use Def of a Fix? *)
989        and tys = List.map (fun (_,ty,_) -> C.Decl ty) fl in
990         List.fold_right
991          (fun (_,ty,bo) i ->
992            i && does_not_occur context n nn ty &&
993             guarded_by_constructors (tys@context) n_plus_len nn_plus_len h bo
994              args coInductiveTypeURI
995          ) fl true
996
997 and check_allowed_sort_elimination context uri i need_dummy ind arity1 arity2 =
998  let module C = Cic in
999  let module U = UriManager in
1000   match (CicReduction.whd context arity1, CicReduction.whd context arity2) with
1001      (C.Prod (_,so1,de1), C.Prod (_,so2,de2))
1002       when CicReduction.are_convertible context so1 so2 ->
1003        check_allowed_sort_elimination context uri i need_dummy
1004         (C.Appl [CicSubstitution.lift 1 ind ; C.Rel 1]) de1 de2
1005    | (C.Sort C.Prop, C.Sort C.Prop) when need_dummy -> true
1006    | (C.Sort C.Prop, C.Sort C.Set) when need_dummy ->
1007        (match CicEnvironment.get_obj uri with
1008            C.InductiveDefinition (itl,_,_) ->
1009             let (_,_,_,cl) = List.nth itl i in
1010              (* is a singleton definition? *)
1011              List.length cl = 1
1012          | _ ->
1013            raise (WrongUriToMutualInductiveDefinitions (U.string_of_uri uri))
1014        )
1015    | (C.Sort C.Set, C.Sort C.Prop) when need_dummy -> true
1016    | (C.Sort C.Set, C.Sort C.Set) when need_dummy -> true
1017    | (C.Sort C.Set, C.Sort C.Type) when need_dummy ->
1018        (match CicEnvironment.get_obj uri with
1019            C.InductiveDefinition (itl,_,paramsno) ->
1020             let tys = List.map (fun (_,_,ty,_) -> Cic.Decl ty) itl in
1021              let (_,_,_,cl) = List.nth itl i in
1022               List.fold_right
1023                (fun (_,x,_) i -> i && is_small tys paramsno x) cl true
1024          | _ ->
1025            raise (WrongUriToMutualInductiveDefinitions (U.string_of_uri uri))
1026        )
1027    | (C.Sort C.Type, C.Sort _) when need_dummy -> true
1028    | (C.Sort C.Prop, C.Prod (_,so,ta)) when not need_dummy ->
1029        let res = CicReduction.are_convertible context so ind
1030        in
1031         res &&
1032         (match CicReduction.whd ((C.Decl so)::context) ta with
1033             C.Sort C.Prop -> true
1034           | C.Sort C.Set ->
1035              (match CicEnvironment.get_obj uri with
1036                  C.InductiveDefinition (itl,_,_) ->
1037                   let (_,_,_,cl) = List.nth itl i in
1038                    (* is a singleton definition? *)
1039                    List.length cl = 1
1040                | _ ->
1041                  raise (WrongUriToMutualInductiveDefinitions
1042                   (U.string_of_uri uri))
1043              )
1044           | _ -> false
1045         )
1046    | (C.Sort C.Set, C.Prod (_,so,ta)) when not need_dummy ->
1047        let res = CicReduction.are_convertible context so ind
1048        in
1049         res &&
1050         (match CicReduction.whd ((C.Decl so)::context) ta with
1051             C.Sort C.Prop
1052           | C.Sort C.Set  -> true
1053           | C.Sort C.Type ->
1054              (match CicEnvironment.get_obj uri with
1055                  C.InductiveDefinition (itl,_,paramsno) ->
1056                   let (_,_,_,cl) = List.nth itl i in
1057                    let tys = List.map (fun (_,_,ty,_) -> Cic.Decl ty) itl in
1058                     List.fold_right
1059                      (fun (_,x,_) i -> i && is_small tys paramsno x) cl true
1060                | _ ->
1061                  raise (WrongUriToMutualInductiveDefinitions
1062                   (U.string_of_uri uri))
1063              )
1064           | _ -> raise (Impossible 19)
1065         )
1066    | (C.Sort C.Type, C.Prod (_,so,_)) when not need_dummy ->
1067        CicReduction.are_convertible context so ind
1068    | (_,_) -> false
1069   
1070 and type_of_branch context argsno need_dummy outtype term constype =
1071  let module C = Cic in
1072  let module R = CicReduction in
1073   match R.whd context constype with
1074      C.MutInd (_,_,_) ->
1075       if need_dummy then
1076        outtype
1077       else
1078        C.Appl [outtype ; term]
1079    | C.Appl (C.MutInd (_,_,_)::tl) ->
1080       let (_,arguments) = split tl argsno
1081       in
1082        if need_dummy && arguments = [] then
1083         outtype
1084        else
1085         C.Appl (outtype::arguments@(if need_dummy then [] else [term]))
1086    | C.Prod (name,so,de) ->
1087       C.Prod (C.Anonimous,so,type_of_branch ((C.Decl so)::context) argsno
1088        need_dummy (CicSubstitution.lift 1 outtype)
1089        (C.Appl [CicSubstitution.lift 1 term ; C.Rel 1]) de)
1090   | _ -> raise (Impossible 20)
1091        
1092  
1093 (* type_of_aux' is just another name (with a different scope) for type_of_aux *)
1094 and type_of_aux' metasenv context t =
1095  let rec type_of_aux context =
1096   let module C = Cic in
1097   let module R = CicReduction in
1098   let module S = CicSubstitution in
1099   let module U = UriManager in
1100    function
1101       C.Rel n ->
1102        (try
1103          match List.nth context (n - 1) with
1104             C.Decl t -> S.lift n t
1105           | C.Def bo -> type_of_aux context (S.lift n bo)
1106         with
1107          _ -> raise (NotWellTyped "Not a close term")
1108        )
1109     | C.Var uri ->
1110       incr fdebug ;
1111       let ty = type_of_variable uri in
1112        decr fdebug ;
1113        ty
1114     | C.Meta n -> List.assoc n metasenv
1115     | C.Sort s -> C.Sort C.Type (*CSC manca la gestione degli universi!!! *)
1116     | C.Implicit -> raise (Impossible 21)
1117     | C.Cast (te,ty) ->
1118        let _ = type_of_aux context ty in
1119         if R.are_convertible context (type_of_aux context te) ty then ty
1120         else raise (NotWellTyped "Cast")
1121     | C.Prod (_,s,t) ->
1122        let sort1 = type_of_aux context s
1123        and sort2 = type_of_aux ((C.Decl s)::context) t in
1124         sort_of_prod (sort1,sort2)
1125    | C.Lambda (n,s,t) ->
1126        let sort1 = type_of_aux context s
1127        and type2 = type_of_aux ((C.Decl s)::context) t in
1128         let sort2 = type_of_aux ((C.Decl s)::context) type2 in
1129          (* only to check if the product is well-typed *)
1130          let _ = sort_of_prod (sort1,sort2) in
1131           C.Prod (n,s,type2)
1132    | C.LetIn (n,s,t) ->
1133        let t' = CicSubstitution.subst s t in
1134         type_of_aux context t'
1135    | C.Appl (he::tl) when List.length tl > 0 ->
1136       let hetype = type_of_aux context he
1137       and tlbody_and_type = List.map (fun x -> (x, type_of_aux context x)) tl in
1138        eat_prods context hetype tlbody_and_type
1139    | C.Appl _ -> raise (NotWellTyped "Appl: no arguments")
1140    | C.Const (uri,cookingsno) ->
1141       incr fdebug ;
1142       let cty = cooked_type_of_constant uri cookingsno in
1143        decr fdebug ;
1144        cty
1145    | C.Abst _ -> raise (Impossible 22)
1146    | C.MutInd (uri,cookingsno,i) ->
1147       incr fdebug ;
1148       let cty = cooked_type_of_mutual_inductive_defs uri cookingsno i in
1149        decr fdebug ;
1150        cty
1151    | C.MutConstruct (uri,cookingsno,i,j) ->
1152       let cty = cooked_type_of_mutual_inductive_constr uri cookingsno i j
1153       in
1154        cty
1155    | C.MutCase (uri,cookingsno,i,outtype,term,pl) ->
1156       let outsort = type_of_aux context outtype in
1157       let (need_dummy, k) =
1158        let rec guess_args context t =
1159         match CicReduction.whd context t with
1160            C.Sort _ -> (true, 0)
1161          | C.Prod (_, s, t) ->
1162             let (b, n) = guess_args ((C.Decl s)::context) t in
1163              if n = 0 then
1164               (* last prod before sort *)
1165               match CicReduction.whd context s with
1166                  (*CSC vedi nota delirante su cookingsno in cicReduction.ml *)
1167                  C.MutInd (uri',_,i') when U.eq uri' uri && i' = i -> (false, 1)
1168                | C.Appl ((C.MutInd (uri',_,i')) :: _)
1169                   when U.eq uri' uri && i' = i -> (false, 1)
1170                | _ -> (true, 1)
1171              else
1172               (b, n + 1)
1173          | _ -> raise (NotWellTyped "MutCase: outtype ill-formed")
1174        in
1175         (*CSC whd non serve dopo type_of_aux ? *)
1176         let (b, k) = guess_args context outsort in
1177          if not b then (b, k - 1) else (b, k)
1178       in
1179       let (parameters, arguments) =
1180         match R.whd context (type_of_aux context term) with
1181            (*CSC manca il caso dei CAST *)
1182            C.MutInd (uri',_,i') ->
1183             (*CSC vedi nota delirante sui cookingsno in cicReduction.ml*)
1184             if U.eq uri uri' && i = i' then ([],[])
1185             else raise (NotWellTyped ("MutCase: the term is of type " ^
1186              (U.string_of_uri uri') ^ "," ^ string_of_int i' ^
1187              " instead of type " ^ (U.string_of_uri uri') ^ "," ^
1188              string_of_int i))
1189          | C.Appl (C.MutInd (uri',_,i') :: tl) ->
1190             if U.eq uri uri' && i = i' then split tl (List.length tl - k)
1191             else raise (NotWellTyped ("MutCase: the term is of type " ^
1192              (U.string_of_uri uri') ^ "," ^ string_of_int i' ^
1193              " instead of type " ^ (U.string_of_uri uri) ^ "," ^
1194              string_of_int i))
1195          | _ -> raise (NotWellTyped "MutCase: the term is not an inductive one")
1196       in
1197        (* let's control if the sort elimination is allowed: [(I q1 ... qr)|B] *)
1198        let sort_of_ind_type =
1199         if parameters = [] then
1200          C.MutInd (uri,cookingsno,i)
1201         else
1202          C.Appl ((C.MutInd (uri,cookingsno,i))::parameters)
1203        in
1204         if not (check_allowed_sort_elimination context uri i need_dummy
1205          sort_of_ind_type (type_of_aux context sort_of_ind_type) outsort)
1206         then
1207          raise (NotWellTyped "MutCase: not allowed sort elimination") ;
1208
1209         (* let's check if the type of branches are right *)
1210         let (cl,parsno) =
1211          match CicEnvironment.get_cooked_obj uri cookingsno with
1212             C.InductiveDefinition (tl,_,parsno) ->
1213              let (_,_,_,cl) = List.nth tl i in (cl,parsno)
1214           | _ ->
1215             raise (WrongUriToMutualInductiveDefinitions (U.string_of_uri uri))
1216         in
1217          let (_,branches_ok) =
1218           List.fold_left
1219            (fun (j,b) (p,(_,c,_)) ->
1220              let cons =
1221               if parameters = [] then
1222                (C.MutConstruct (uri,cookingsno,i,j))
1223               else
1224                (C.Appl (C.MutConstruct (uri,cookingsno,i,j)::parameters))
1225              in
1226               (j + 1, b &&
1227                R.are_convertible context (type_of_aux context p)
1228                 (type_of_branch context parsno need_dummy outtype cons
1229                   (type_of_aux context cons))
1230               )
1231            ) (1,true) (List.combine pl cl)
1232          in
1233           if not branches_ok then
1234            raise (NotWellTyped "MutCase: wrong type of a branch") ;
1235
1236           if not need_dummy then
1237            C.Appl ((outtype::arguments)@[term])
1238           else if arguments = [] then
1239            outtype
1240           else
1241            C.Appl (outtype::arguments)
1242    | C.Fix (i,fl) ->
1243       let types_times_kl =
1244        List.rev
1245         (List.map
1246           (fun (_,k,ty,_) ->
1247             let _ = type_of_aux context ty in (C.Decl ty,k)) fl)
1248       in
1249       let (types,kl) = List.split types_times_kl in
1250        let len = List.length types in
1251         List.iter
1252          (fun (name,x,ty,bo) ->
1253            if
1254             (R.are_convertible (types@context) (type_of_aux (types@context) bo)
1255              (CicSubstitution.lift len ty))
1256            then
1257             begin
1258              let (m, eaten, context') =
1259               eat_lambdas (types @ context) (x + 1) bo
1260              in
1261               (*let's control the guarded by destructors conditions D{f,k,x,M}*)
1262               if
1263                not
1264                 (guarded_by_destructors context' eaten (len + eaten) kl 1 [] m)
1265               then
1266                raise (NotWellTyped "Fix: not guarded by destructors")
1267             end
1268            else
1269             raise (NotWellTyped "Fix: ill-typed bodies")
1270          ) fl ;
1271       
1272         (*CSC: controlli mancanti solo su D{f,k,x,M} *)
1273         let (_,_,ty,_) = List.nth fl i in
1274         ty
1275    | C.CoFix (i,fl) ->
1276       let types =
1277        List.rev
1278         (List.map
1279           (fun (_,ty,_) -> let _ = type_of_aux context ty in C.Decl ty) fl)
1280       in
1281        let len = List.length types in
1282         List.iter
1283          (fun (_,ty,bo) ->
1284            if
1285             (R.are_convertible (types @ context)
1286              (type_of_aux (types @ context) bo) (CicSubstitution.lift len ty))
1287            then
1288             begin
1289              (* let's control that the returned type is coinductive *)
1290              match returns_a_coinductive ty with
1291                 None ->
1292                  raise(NotWellTyped "CoFix: does not return a coinductive type")
1293               | Some uri ->
1294                  (*let's control the guarded by constructors conditions C{f,M}*)
1295                  if
1296                   not
1297                    (guarded_by_constructors (types @ context) 0 len false bo
1298                      [] uri)
1299                  then
1300                   raise (NotWellTyped "CoFix: not guarded by constructors")
1301             end
1302            else
1303             raise (NotWellTyped "CoFix: ill-typed bodies")
1304          ) fl ;
1305       
1306         let (_,ty,_) = List.nth fl i in
1307          ty
1308
1309  and sort_of_prod (t1, t2) =
1310   let module C = Cic in
1311    let t1' = CicReduction.whd context t1 in
1312    let t2' = CicReduction.whd context t2 in
1313    match (t1', t2') with
1314       (C.Sort s1, C.Sort s2)
1315         when (s2 = C.Prop or s2 = C.Set) -> (* different from Coq manual!!! *)
1316          C.Sort s2
1317     | (C.Sort s1, C.Sort s2) -> C.Sort C.Type (*CSC manca la gestione degli universi!!! *)
1318     | (_,_) ->
1319       raise
1320        (NotWellTyped
1321         ("Prod: sort1= " ^ CicPp.ppterm t1' ^ " ; sort2= " ^ CicPp.ppterm t2'))
1322
1323  and eat_prods context hetype =
1324   (*CSC: siamo sicuri che le are_convertible non lavorino con termini non *)
1325   (*CSC: cucinati                                                         *)
1326   function
1327      [] -> hetype
1328    | (hete, hety)::tl ->
1329     (match (CicReduction.whd context hetype) with
1330         Cic.Prod (n,s,t) ->
1331          if CicReduction.are_convertible context s hety then
1332           (CicReduction.fdebug := -1 ;
1333            eat_prods context (CicSubstitution.subst hete t) tl
1334           )
1335          else
1336           begin
1337            CicReduction.fdebug := 0 ;
1338            ignore (CicReduction.are_convertible context s hety) ;
1339            fdebug := 0 ;
1340            debug s [hety] ;
1341            raise (NotWellTyped "Appl: wrong parameter-type")
1342           end
1343       | _ -> raise (NotWellTyped "Appl: wrong Prod-type")
1344     )
1345
1346  and returns_a_coinductive ty =
1347   let module C = Cic in
1348    match CicReduction.whd context ty with
1349       C.MutInd (uri,cookingsno,i) ->
1350        (*CSC: definire una funzioncina per questo codice sempre replicato *)
1351        (match CicEnvironment.get_cooked_obj uri cookingsno with
1352            C.InductiveDefinition (itl,_,_) ->
1353             let (_,is_inductive,_,cl) = List.nth itl i in
1354              if is_inductive then None else (Some uri)
1355          | _ ->
1356            raise (WrongUriToMutualInductiveDefinitions
1357             (UriManager.string_of_uri uri))
1358         )
1359     | C.Appl ((C.MutInd (uri,_,i))::_) ->
1360        (match CicEnvironment.get_obj uri with
1361            C.InductiveDefinition (itl,_,_) ->
1362             let (_,is_inductive,_,_) = List.nth itl i in
1363              if is_inductive then None else (Some uri)
1364          | _ ->
1365            raise (WrongUriToMutualInductiveDefinitions
1366             (UriManager.string_of_uri uri))
1367         )
1368     | C.Prod (_,_,de) -> returns_a_coinductive de
1369     | _ -> None
1370
1371  in
1372 (*CSC
1373 prerr_endline ("INIZIO TYPE_OF_AUX " ^ CicPp.ppterm t) ; flush stderr ;
1374 let res =
1375 *)
1376   type_of_aux context t
1377 (*
1378 in prerr_endline "FINE TYPE_OF_AUX" ; flush stderr ; res
1379 *)
1380
1381 (* is a small constructor? *)
1382 (*CSC: ottimizzare calcolando staticamente *)
1383 and is_small context paramsno c =
1384  let rec is_small_aux context c =
1385   let module C = Cic in
1386    match CicReduction.whd context c with
1387       C.Prod (_,so,de) ->
1388        (*CSC: [] is an empty metasenv. Is it correct? *)
1389        let s = type_of_aux' [] context so in
1390         (s = C.Sort C.Prop || s = C.Sort C.Set) &&
1391         is_small_aux ((C.Decl so)::context) de
1392     | _ -> true (*CSC: we trust the type-checker *)
1393  in
1394   let (context',dx) = split_prods context paramsno c in
1395    is_small_aux context' dx
1396
1397 and type_of t =
1398 (*CSC
1399 prerr_endline ("INIZIO TYPE_OF_AUX' " ^ CicPp.ppterm t) ; flush stderr ;
1400 let res =
1401 *)
1402  type_of_aux' [] [] t
1403 (*CSC
1404 in prerr_endline "FINE TYPE_OF_AUX'" ; flush stderr ; res
1405 *)
1406 ;;
1407
1408 let typecheck uri =
1409  let module C = Cic in
1410  let module R = CicReduction in
1411  let module U = UriManager in
1412   match CicEnvironment.is_type_checked uri 0 with
1413      CicEnvironment.CheckedObj _ -> ()
1414    | CicEnvironment.UncheckedObj uobj ->
1415       (* let's typecheck the uncooked object *)
1416       Logger.log (`Start_type_checking uri) ;
1417       (match uobj with
1418           C.Definition (_,te,ty,_) ->
1419            let _ = type_of ty in
1420             if not (R.are_convertible [] (type_of te ) ty) then
1421              raise (NotWellTyped ("Constant " ^ (U.string_of_uri uri)))
1422         | C.Axiom (_,ty,_) ->
1423           (* only to check that ty is well-typed *)
1424           let _ = type_of ty in ()
1425         | C.CurrentProof (_,conjs,te,ty) ->
1426             (*CSC [] wrong *)
1427             let _ = type_of_aux' conjs [] ty in
1428              debug (type_of_aux' conjs [] te) [] ;
1429              if not (R.are_convertible [] (type_of_aux' conjs [] te) ty) then
1430               raise (NotWellTyped ("CurrentProof" ^ (U.string_of_uri uri)))
1431         | C.Variable (_,bo,ty) ->
1432            (* only to check that ty is well-typed *)
1433            let _ = type_of ty in
1434             (match bo with
1435                 None -> ()
1436               | Some bo ->
1437                  if not (R.are_convertible [] (type_of bo) ty) then
1438                   raise (NotWellTyped ("Variable" ^ (U.string_of_uri uri)))
1439             )
1440         | C.InductiveDefinition _ ->
1441            cooked_mutual_inductive_defs uri uobj
1442       ) ;
1443       CicEnvironment.set_type_checking_info uri ;
1444       Logger.log (`Type_checking_completed uri)
1445 ;;