]> matita.cs.unibo.it Git - helm.git/blob - helm/ocaml/cic_transformations/doubleTypeInference.ml
71422ced12d6190d09b2829d2f80d1fcffaef6c5
[helm.git] / helm / ocaml / cic_transformations / doubleTypeInference.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 RelToHiddenHypothesis;;
33
34 type types = {synthesized : Cic.term ; expected : Cic.term option};;
35
36 (* does_not_occur n te                              *)
37 (* returns [true] if [Rel n] does not occur in [te] *)
38 let rec does_not_occur n =
39  let module C = Cic in
40   function
41      C.Rel m when m = n -> false
42    | C.Rel _
43    | C.Meta _
44    | C.Sort _
45    | C.Implicit -> true 
46    | C.Cast (te,ty) ->
47       does_not_occur n te && does_not_occur n ty
48    | C.Prod (name,so,dest) ->
49       does_not_occur n so &&
50        does_not_occur (n + 1) dest
51    | C.Lambda (name,so,dest) ->
52       does_not_occur n so &&
53        does_not_occur (n + 1) dest
54    | C.LetIn (name,so,dest) ->
55       does_not_occur n so &&
56        does_not_occur (n + 1) dest
57    | C.Appl l ->
58       List.fold_right (fun x i -> i && does_not_occur n x) l true
59    | C.Var (_,exp_named_subst)
60    | C.Const (_,exp_named_subst)
61    | C.MutInd (_,_,exp_named_subst)
62    | C.MutConstruct (_,_,_,exp_named_subst) ->
63       List.fold_right (fun (_,x) i -> i && does_not_occur n x)
64        exp_named_subst true
65    | C.MutCase (_,_,out,te,pl) ->
66       does_not_occur n out && does_not_occur n te &&
67        List.fold_right (fun x i -> i && does_not_occur n x) pl true
68    | C.Fix (_,fl) ->
69       let len = List.length fl in
70        let n_plus_len = n + len in
71        let tys =
72         List.map (fun (n,_,ty,_) -> Some (C.Name n,(Cic.Decl ty))) fl
73        in
74         List.fold_right
75          (fun (_,_,ty,bo) i ->
76            i && does_not_occur n ty &&
77            does_not_occur n_plus_len bo
78          ) fl true
79    | C.CoFix (_,fl) ->
80       let len = List.length fl in
81        let n_plus_len = n + len in
82        let tys =
83         List.map (fun (n,ty,_) -> Some (C.Name n,(Cic.Decl ty))) fl
84        in
85         List.fold_right
86          (fun (_,ty,bo) i ->
87            i && does_not_occur n ty &&
88            does_not_occur n_plus_len bo
89          ) fl true
90 ;;
91
92 (*CSC: potrebbe creare applicazioni di applicazioni *)
93 (*CSC: ora non e' piu' head, ma completa!!! *)
94 let rec head_beta_reduce =
95  let module S = CicSubstitution in
96  let module C = Cic in
97   function
98       C.Rel _ as t -> t
99     | C.Var (uri,exp_named_subst) ->
100        let exp_named_subst' =
101         List.map (function (i,t) -> i, head_beta_reduce t) exp_named_subst
102        in
103         C.Var (uri,exp_named_subst)
104     | C.Meta (n,l) ->
105        C.Meta (n,
106         List.map
107          (function None -> None | Some t -> Some (head_beta_reduce t)) l
108        )
109     | C.Sort _ as t -> t
110     | C.Implicit -> assert false
111     | C.Cast (te,ty) ->
112        C.Cast (head_beta_reduce te, head_beta_reduce ty)
113     | C.Prod (n,s,t) ->
114        C.Prod (n, head_beta_reduce s, head_beta_reduce t)
115     | C.Lambda (n,s,t) ->
116        C.Lambda (n, head_beta_reduce s, head_beta_reduce t)
117     | C.LetIn (n,s,t) ->
118        C.LetIn (n, head_beta_reduce s, head_beta_reduce t)
119     | C.Appl ((C.Lambda (name,s,t))::he::tl) ->
120        let he' = S.subst he t in
121         if tl = [] then
122          head_beta_reduce he'
123         else
124          head_beta_reduce (C.Appl (he'::tl))
125     | C.Appl l ->
126        C.Appl (List.map head_beta_reduce l)
127     | C.Const (uri,exp_named_subst) ->
128        let exp_named_subst' =
129         List.map (function (i,t) -> i, head_beta_reduce t) exp_named_subst
130        in
131         C.Const (uri,exp_named_subst')
132     | C.MutInd (uri,i,exp_named_subst) ->
133        let exp_named_subst' =
134         List.map (function (i,t) -> i, head_beta_reduce t) exp_named_subst
135        in
136         C.MutInd (uri,i,exp_named_subst')
137     | C.MutConstruct (uri,i,j,exp_named_subst) ->
138        let exp_named_subst' =
139         List.map (function (i,t) -> i, head_beta_reduce t) exp_named_subst
140        in
141         C.MutConstruct (uri,i,j,exp_named_subst')
142     | C.MutCase (sp,i,outt,t,pl) ->
143        C.MutCase (sp,i,head_beta_reduce outt,head_beta_reduce t,
144         List.map head_beta_reduce pl)
145     | C.Fix (i,fl) ->
146        let fl' =
147         List.map
148          (function (name,i,ty,bo) ->
149            name,i,head_beta_reduce ty,head_beta_reduce bo
150          ) fl
151        in
152         C.Fix (i,fl')
153     | C.CoFix (i,fl) ->
154        let fl' =
155         List.map
156          (function (name,ty,bo) ->
157            name,head_beta_reduce ty,head_beta_reduce bo
158          ) fl
159        in
160         C.CoFix (i,fl')
161 ;;
162
163 (* syntactic_equality up to cookingsno for uris *)
164 (* (which is often syntactically irrilevant),   *)
165 (* distinction between fake dependent products  *)
166 (* and non-dependent products, alfa-conversion  *)
167 (*CSC: must alfa-conversion be considered or not? *)
168 let syntactic_equality t t' =
169  let module C = Cic in
170  let rec syntactic_equality t t' =
171   if t = t' then true
172   else
173    match t, t' with
174       C.Var (uri,exp_named_subst), C.Var (uri',exp_named_subst') ->
175        UriManager.eq uri uri' &&
176         syntactic_equality_exp_named_subst exp_named_subst exp_named_subst'
177     | C.Cast (te,ty), C.Cast (te',ty') ->
178        syntactic_equality te te' &&
179         syntactic_equality ty ty'
180     | C.Prod (_,s,t), C.Prod (_,s',t') ->
181        syntactic_equality s s' &&
182         syntactic_equality t t'
183     | C.Lambda (_,s,t), C.Lambda (_,s',t') ->
184        syntactic_equality s s' &&
185         syntactic_equality t t'
186     | C.LetIn (_,s,t), C.LetIn(_,s',t') ->
187        syntactic_equality s s' &&
188         syntactic_equality t t'
189     | C.Appl l, C.Appl l' ->
190        List.fold_left2 (fun b t1 t2 -> b && syntactic_equality t1 t2) true l l'
191     | C.Const (uri,exp_named_subst), C.Const (uri',exp_named_subst') ->
192        UriManager.eq uri uri' &&
193         syntactic_equality_exp_named_subst exp_named_subst exp_named_subst'
194     | C.MutInd (uri,i,exp_named_subst), C.MutInd (uri',i',exp_named_subst') ->
195        UriManager.eq uri uri' && i = i' &&
196         syntactic_equality_exp_named_subst exp_named_subst exp_named_subst'
197     | C.MutConstruct (uri,i,j,exp_named_subst),
198       C.MutConstruct (uri',i',j',exp_named_subst') ->
199        UriManager.eq uri uri' && i = i' && j = j' &&
200         syntactic_equality_exp_named_subst exp_named_subst exp_named_subst'
201     | C.MutCase (sp,i,outt,t,pl), C.MutCase (sp',i',outt',t',pl') ->
202        UriManager.eq sp sp' && i = i' &&
203         syntactic_equality outt outt' &&
204          syntactic_equality t t' &&
205           List.fold_left2
206            (fun b t1 t2 -> b && syntactic_equality t1 t2) true pl pl'
207     | C.Fix (i,fl), C.Fix (i',fl') ->
208        i = i' &&
209         List.fold_left2
210          (fun b (_,i,ty,bo) (_,i',ty',bo') ->
211            b && i = i' &&
212             syntactic_equality ty ty' &&
213              syntactic_equality bo bo') true fl fl'
214     | C.CoFix (i,fl), C.CoFix (i',fl') ->
215        i = i' &&
216         List.fold_left2
217          (fun b (_,ty,bo) (_,ty',bo') ->
218            b &&
219             syntactic_equality ty ty' &&
220              syntactic_equality bo bo') true fl fl'
221     | _, _ -> false (* we already know that t != t' *)
222  and syntactic_equality_exp_named_subst exp_named_subst1 exp_named_subst2 =
223   List.fold_left2
224    (fun b (_,t1) (_,t2) -> b && syntactic_equality t1 t2) true
225    exp_named_subst1 exp_named_subst2
226  in
227   try
228    syntactic_equality t t'
229   with
230    _ -> false
231 ;;
232
233 let rec split l n =
234  match (l,n) with
235     (l,0) -> ([], l)
236   | (he::tl, n) -> let (l1,l2) = split tl (n-1) in (he::l1,l2)
237   | (_,_) -> raise ListTooShort
238 ;;
239
240 let type_of_constant uri =
241  let module C = Cic in
242  let module R = CicReduction in
243  let module U = UriManager in
244   let cobj =
245    match CicEnvironment.is_type_checked uri with
246       CicEnvironment.CheckedObj cobj -> cobj
247     | CicEnvironment.UncheckedObj uobj ->
248        raise (NotWellTyped "Reference to an unchecked constant")
249   in
250    match cobj with
251       C.Constant (_,_,ty,_) -> ty
252     | C.CurrentProof (_,_,_,ty,_) -> ty
253     | _ -> raise (WrongUriToConstant (U.string_of_uri uri))
254 ;;
255
256 let type_of_variable uri =
257  let module C = Cic in
258  let module R = CicReduction in
259  let module U = UriManager in
260   match CicEnvironment.is_type_checked uri with
261      CicEnvironment.CheckedObj (C.Variable (_,_,ty,_)) -> ty
262    | CicEnvironment.UncheckedObj (C.Variable _) ->
263       raise (NotWellTyped "Reference to an unchecked variable")
264    |  _ -> raise (WrongUriToVariable (UriManager.string_of_uri uri))
265 ;;
266
267 let type_of_mutual_inductive_defs uri i =
268  let module C = Cic in
269  let module R = CicReduction in
270  let module U = UriManager in
271   let cobj =
272    match CicEnvironment.is_type_checked uri with
273       CicEnvironment.CheckedObj cobj -> cobj
274     | CicEnvironment.UncheckedObj uobj ->
275        raise (NotWellTyped "Reference to an unchecked inductive type")
276   in
277    match cobj with
278       C.InductiveDefinition (dl,_,_) ->
279        let (_,_,arity,_) = List.nth dl i in
280         arity
281     | _ -> raise (WrongUriToMutualInductiveDefinitions (U.string_of_uri uri))
282 ;;
283
284 let type_of_mutual_inductive_constr uri i j =
285  let module C = Cic in
286  let module R = CicReduction in
287  let module U = UriManager in
288   let cobj =
289    match CicEnvironment.is_type_checked uri with
290       CicEnvironment.CheckedObj cobj -> cobj
291     | CicEnvironment.UncheckedObj uobj ->
292        raise (NotWellTyped "Reference to an unchecked constructor")
293   in
294    match cobj with
295       C.InductiveDefinition (dl,_,_) ->
296        let (_,_,_,cl) = List.nth dl i in
297         let (_,ty) = List.nth cl (j-1) in
298          ty
299     | _ -> raise (WrongUriToMutualInductiveDefinitions (U.string_of_uri uri))
300 ;;
301
302 module CicHash =
303  Hashtbl.Make
304   (struct
305     type t = Cic.term
306     let equal = (==)
307     let hash = Hashtbl.hash
308    end)
309 ;;
310
311 (* type_of_aux' is just another name (with a different scope) for type_of_aux *)
312 let rec type_of_aux' subterms_to_types metasenv context t expectedty =
313  (* Coscoy's double type-inference algorithm             *)
314  (* It computes the inner-types of every subterm of [t], *)
315  (* even when they are not needed to compute the types   *)
316  (* of other terms.                                      *)
317  let rec type_of_aux context t expectedty =
318   let module C = Cic in
319   let module R = CicReduction in
320   let module S = CicSubstitution in
321   let module U = UriManager in
322    let synthesized =
323     match t with
324        C.Rel n ->
325         (try
326           match List.nth context (n - 1) with
327              Some (_,C.Decl t) -> S.lift n t
328            | Some (_,C.Def bo) -> type_of_aux context (S.lift n bo) expectedty
329            | None -> raise RelToHiddenHypothesis
330          with
331           _ -> raise (NotWellTyped "Not a close term")
332         )
333      | C.Var (uri,exp_named_subst) ->
334         visit_exp_named_subst context uri exp_named_subst ;
335         CicSubstitution.subst_vars exp_named_subst (type_of_variable uri)
336      | C.Meta (n,l) -> 
337         (* Let's visit all the subterms that will not be visited later *)
338         let (_,canonical_context,_) =
339          List.find (function (m,_,_) -> n = m) metasenv
340         in
341          let lifted_canonical_context =
342           let rec aux i =
343            function
344               [] -> []
345             | (Some (n,C.Decl t))::tl ->
346                (Some (n,C.Decl (S.lift_meta l (S.lift i t))))::(aux (i+1) tl)
347             | (Some (n,C.Def t))::tl ->
348                (Some (n,C.Def (S.lift_meta l (S.lift i t))))::(aux (i+1) tl)
349             | None::tl -> None::(aux (i+1) tl)
350           in
351            aux 1 canonical_context
352          in
353           let _ =
354            List.iter2
355             (fun t ct ->
356               match t,ct with
357                  _,None -> ()
358                | Some t,Some (_,C.Def ct) ->
359                   let expected_type =
360                    R.whd context
361                     (CicTypeChecker.type_of_aux' metasenv context ct)
362                   in
363                    (* Maybe I am a bit too paranoid, because   *)
364                    (* if the term is well-typed than t and ct  *)
365                    (* are convertible. Nevertheless, I compute *)
366                    (* the expected type.                       *)
367                    ignore (type_of_aux context t (Some expected_type))
368                | Some t,Some (_,C.Decl ct) ->
369                   ignore (type_of_aux context t (Some ct))
370                | _,_ -> assert false (* the term is not well typed!!! *)
371             ) l lifted_canonical_context
372           in
373            let (_,canonical_context,ty) =
374             List.find (function (m,_,_) -> n = m) metasenv
375            in
376             (* Checks suppressed *)
377             CicSubstitution.lift_meta l ty
378      | C.Sort s -> C.Sort C.Type (*CSC manca la gestione degli universi!!! *)
379      | C.Implicit -> raise (Impossible 21)
380      | C.Cast (te,ty) ->
381         (* Let's visit all the subterms that will not be visited later *)
382         let _ = type_of_aux context te (Some (head_beta_reduce ty)) in
383         let _ = type_of_aux context ty None in
384          (* Checks suppressed *)
385          ty
386      | C.Prod (name,s,t) ->
387         let sort1 = type_of_aux context s None
388         and sort2 = type_of_aux ((Some (name,(C.Decl s)))::context) t None in
389          sort_of_prod context (name,s) (sort1,sort2)
390      | C.Lambda (n,s,t) ->
391         (* Let's visit all the subterms that will not be visited later *)
392         let _ = type_of_aux context s None in
393          let expected_target_type =
394           match expectedty with
395              None -> None
396            | Some expectedty' ->
397               let ty =
398                match R.whd context expectedty' with
399                   C.Prod (_,_,expected_target_type) ->
400                    head_beta_reduce expected_target_type
401                 | _ -> assert false
402               in
403                Some ty
404          in
405           let type2 =
406            type_of_aux ((Some (n,(C.Decl s)))::context) t expected_target_type
407           in
408            (* Checks suppressed *)
409            C.Prod (n,s,type2)
410      | C.LetIn (n,s,t) ->
411 (*CSC: What are the right expected types for the source and *)
412 (*CSC: target of a LetIn? None used.                        *)
413         (* Let's visit all the subterms that will not be visited later *)
414         let _ = type_of_aux context s None in
415          let t_typ =
416           (* Checks suppressed *)
417           type_of_aux ((Some (n,(C.Def s)))::context) t None
418          in
419           if does_not_occur 1 t_typ then
420            (* since [Rel 1] does not occur in typ, substituting any term *)
421            (* in place of [Rel 1] is equivalent to delifting once        *)
422            CicSubstitution.subst C.Implicit t_typ
423           else
424            C.LetIn (n,s,t_typ)
425      | C.Appl (he::tl) when List.length tl > 0 ->
426         let expected_hetype =
427          (* Inefficient, the head is computed twice. But I know *)
428          (* of no other solution.                               *)
429          R.whd context (CicTypeChecker.type_of_aux' metasenv context he)
430         in
431          let hetype = type_of_aux context he (Some expected_hetype) in
432          let tlbody_and_type =
433           let rec aux =
434            function
435               _,[] -> []
436             | C.Prod (n,s,t),he::tl ->
437                (he, type_of_aux context he (Some (head_beta_reduce s)))::
438                 (aux (R.whd context (S.subst he t), tl))
439             | _ -> assert false
440           in
441            aux (expected_hetype, tl)
442          in
443           eat_prods context hetype tlbody_and_type
444      | C.Appl _ -> raise (NotWellTyped "Appl: no arguments")
445      | C.Const (uri,exp_named_subst) ->
446         visit_exp_named_subst context uri exp_named_subst ;
447         CicSubstitution.subst_vars exp_named_subst (type_of_constant uri)
448      | C.MutInd (uri,i,exp_named_subst) ->
449         visit_exp_named_subst context uri exp_named_subst ;
450         CicSubstitution.subst_vars exp_named_subst
451          (type_of_mutual_inductive_defs uri i)
452      | C.MutConstruct (uri,i,j,exp_named_subst) ->
453         visit_exp_named_subst context uri exp_named_subst ;
454         CicSubstitution.subst_vars exp_named_subst
455          (type_of_mutual_inductive_constr uri i j)
456      | C.MutCase (uri,i,outtype,term,pl) ->
457         let outsort = type_of_aux context outtype None in
458         let (need_dummy, k) =
459          let rec guess_args context t =
460           match CicReduction.whd context t with
461              C.Sort _ -> (true, 0)
462            | C.Prod (name, s, t) ->
463               let (b, n) = guess_args ((Some (name,(C.Decl s)))::context) t in
464                if n = 0 then
465                 (* last prod before sort *)
466                 match CicReduction.whd context s with
467                    C.MutInd (uri',i',_) when U.eq uri' uri && i' = i ->
468                     (false, 1)
469                  | C.Appl ((C.MutInd (uri',i',_)) :: _)
470                     when U.eq uri' uri && i' = i -> (false, 1)
471                  | _ -> (true, 1)
472                else
473                 (b, n + 1)
474            | _ -> raise (NotWellTyped "MutCase: outtype ill-formed")
475          in
476           let (b, k) = guess_args context outsort in
477            if not b then (b, k - 1) else (b, k)
478         in
479         let (parameters, arguments,exp_named_subst) =
480          let type_of_term =
481           CicTypeChecker.type_of_aux' metasenv context term
482          in
483           match
484            R.whd context (type_of_aux context term
485             (Some (head_beta_reduce type_of_term)))
486           with
487              (*CSC manca il caso dei CAST *)
488              C.MutInd (uri',i',exp_named_subst) ->
489               (* Checks suppressed *)
490               [],[],exp_named_subst
491            | C.Appl (C.MutInd (uri',i',exp_named_subst) :: tl) ->
492              let params,args =
493               split tl (List.length tl - k)
494              in params,args,exp_named_subst
495            | _ ->
496              raise (NotWellTyped "MutCase: the term is not an inductive one")
497         in
498          (* Checks suppressed *)
499          (* Let's visit all the subterms that will not be visited later *)
500          let (cl,parsno) =
501           match CicEnvironment.get_cooked_obj uri with
502              C.InductiveDefinition (tl,_,parsno) ->
503               let (_,_,_,cl) = List.nth tl i in (cl,parsno)
504            | _ ->
505              raise (WrongUriToMutualInductiveDefinitions (U.string_of_uri uri))
506          in
507           let _ =
508            List.fold_left
509             (fun j (p,(_,c)) ->
510               let cons =
511                if parameters = [] then
512                 (C.MutConstruct (uri,i,j,exp_named_subst))
513                else
514                 (C.Appl (C.MutConstruct (uri,i,j,exp_named_subst)::parameters))
515               in
516                let expectedtype =
517                 type_of_branch context parsno need_dummy outtype cons
518                   (CicTypeChecker.type_of_aux' metasenv context cons)
519                in
520                 ignore (type_of_aux context p
521                  (Some (head_beta_reduce expectedtype))) ;
522                 j+1
523             ) 1 (List.combine pl cl)
524           in
525            if not need_dummy then
526             C.Appl ((outtype::arguments)@[term])
527            else if arguments = [] then
528             outtype
529            else
530             C.Appl (outtype::arguments)
531      | C.Fix (i,fl) ->
532         (* Let's visit all the subterms that will not be visited later *)
533         let context' =
534          List.rev
535           (List.map
536             (fun (n,_,ty,_) ->
537               let _ = type_of_aux context ty None in
538                (Some (C.Name n,(C.Decl ty)))
539             ) fl
540           ) @
541           context
542         in
543          let _ =
544           List.iter
545            (fun (_,_,ty,bo) ->
546              let expectedty =
547               head_beta_reduce (CicSubstitution.lift (List.length fl) ty)
548              in
549               ignore (type_of_aux context' bo (Some expectedty))
550            ) fl
551          in
552           (* Checks suppressed *)
553           let (_,_,ty,_) = List.nth fl i in
554            ty
555      | C.CoFix (i,fl) ->
556         (* Let's visit all the subterms that will not be visited later *)
557         let context' =
558          List.rev
559           (List.map
560             (fun (n,ty,_) ->
561               let _ = type_of_aux context ty None in
562                (Some (C.Name n,(C.Decl ty)))
563             ) fl
564           ) @
565           context
566         in
567          let _ =
568           List.iter
569            (fun (_,ty,bo) ->
570              let expectedty =
571               head_beta_reduce (CicSubstitution.lift (List.length fl) ty)
572              in
573               ignore (type_of_aux context' bo (Some expectedty))
574            ) fl
575          in
576           (* Checks suppressed *)
577           let (_,ty,_) = List.nth fl i in
578            ty
579    in
580     let synthesized' = head_beta_reduce synthesized in
581      let types,res =
582       match expectedty with
583          None ->
584           (* No expected type *)
585           {synthesized = synthesized' ; expected = None}, synthesized
586        | Some ty when syntactic_equality synthesized' ty ->
587           (* The expected type is synthactically equal to *)
588           (* the synthesized type. Let's forget it.       *)
589           {synthesized = synthesized' ; expected = None}, synthesized
590        | Some expectedty' ->
591           {synthesized = synthesized' ; expected = Some expectedty'},
592           expectedty'
593      in
594       CicHash.add subterms_to_types t types ;
595       res
596
597  and visit_exp_named_subst context uri exp_named_subst =
598   let uris_and_types =
599    match CicEnvironment.get_cooked_obj uri with
600       Cic.Constant (_,_,_,params)
601     | Cic.CurrentProof (_,_,_,_,params)
602     | Cic.Variable (_,_,_,params)
603     | Cic.InductiveDefinition (_,params,_) ->
604        List.map
605         (function uri ->
606           match CicEnvironment.get_cooked_obj uri with
607              Cic.Variable (_,None,ty,_) -> uri,ty
608            | _ -> assert false (* the theorem is well-typed *)
609         ) params
610   in
611    let rec check uris_and_types subst =
612     match uris_and_types,subst with
613        _,[] -> []
614      | (uri,ty)::tytl,(uri',t)::substtl when uri = uri' ->
615         ignore (type_of_aux context t (Some ty)) ;
616         let tytl' =
617          List.map
618           (function uri,t' -> uri,(CicSubstitution.subst_vars [uri',t] t')) tytl
619         in
620          check tytl' substtl
621      | _,_ -> assert false (* the theorem is well-typed *)
622    in
623     check uris_and_types exp_named_subst
624
625  and sort_of_prod context (name,s) (t1, t2) =
626   let module C = Cic in
627    let t1' = CicReduction.whd context t1 in
628    let t2' = CicReduction.whd ((Some (name,C.Decl s))::context) t2 in
629    match (t1', t2') with
630       (C.Sort s1, C.Sort s2)
631         when (s2 = C.Prop or s2 = C.Set) -> (* different from Coq manual!!! *)
632          C.Sort s2
633     | (C.Sort s1, C.Sort s2) -> C.Sort C.Type (*CSC manca la gestione degli universi!!! *)
634     | (_,_) ->
635       raise
636        (NotWellTyped
637         ("Prod: sort1= " ^ CicPp.ppterm t1' ^ " ; sort2= " ^ CicPp.ppterm t2'))
638
639  and eat_prods context hetype =
640   (*CSC: siamo sicuri che le are_convertible non lavorino con termini non *)
641   (*CSC: cucinati                                                         *)
642   function
643      [] -> hetype
644    | (hete, hety)::tl ->
645     (match (CicReduction.whd context hetype) with
646         Cic.Prod (n,s,t) ->
647          (* Checks suppressed *)
648          eat_prods context (CicSubstitution.subst hete t) tl
649       | _ -> raise (NotWellTyped "Appl: wrong Prod-type")
650     )
651
652 and type_of_branch context argsno need_dummy outtype term constype =
653  let module C = Cic in
654  let module R = CicReduction in
655   match R.whd context constype with
656      C.MutInd (_,_,_) ->
657       if need_dummy then
658        outtype
659       else
660        C.Appl [outtype ; term]
661    | C.Appl (C.MutInd (_,_,_)::tl) ->
662       let (_,arguments) = split tl argsno
663       in
664        if need_dummy && arguments = [] then
665         outtype
666        else
667         C.Appl (outtype::arguments@(if need_dummy then [] else [term]))
668    | C.Prod (name,so,de) ->
669       let term' =
670        match CicSubstitution.lift 1 term with
671           C.Appl l -> C.Appl (l@[C.Rel 1])
672         | t -> C.Appl [t ; C.Rel 1]
673       in
674        C.Prod (C.Anonymous,so,type_of_branch
675         ((Some (name,(C.Decl so)))::context) argsno need_dummy
676         (CicSubstitution.lift 1 outtype) term' de)
677   | _ -> raise (Impossible 20)
678
679  in
680   type_of_aux context t expectedty
681 ;;
682
683 let double_type_of metasenv context t expectedty =
684  let subterms_to_types = CicHash.create 503 in
685   ignore (type_of_aux' subterms_to_types metasenv context t expectedty) ;
686   subterms_to_types
687 ;;