]> matita.cs.unibo.it Git - helm.git/blob - components/cic_unification/cicRefine.ml
when a coercion is passed through a case on right-params-free term m,
[helm.git] / components / cic_unification / cicRefine.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 (* $Id$ *)
27
28 open Printf
29
30 exception RefineFailure of string Lazy.t;;
31 exception Uncertain of string Lazy.t;;
32 exception AssertFailure of string Lazy.t;;
33
34 let insert_coercions = ref true
35 let pack_coercions = ref true
36
37 let debug = false;;
38
39 let debug_print = 
40   if debug then (fun x -> prerr_endline (Lazy.force x)) else (fun _ -> ());;
41
42 let profiler_eat_prods2 = HExtlib.profile "CicRefine.fo_unif_eat_prods2"
43
44 let fo_unif_subst_eat_prods2 subst context metasenv t1 t2 ugraph =
45   try
46 let foo () =
47     CicUnification.fo_unif_subst subst context metasenv t1 t2 ugraph
48 in profiler_eat_prods2.HExtlib.profile foo ()
49   with
50       (CicUnification.UnificationFailure msg) -> raise (RefineFailure msg)
51     | (CicUnification.Uncertain msg) -> raise (Uncertain msg)
52 ;;
53
54 let profiler_eat_prods = HExtlib.profile "CicRefine.fo_unif_eat_prods"
55
56 let fo_unif_subst_eat_prods subst context metasenv t1 t2 ugraph =
57   try
58 let foo () =
59     CicUnification.fo_unif_subst subst context metasenv t1 t2 ugraph
60 in profiler_eat_prods.HExtlib.profile foo ()
61   with
62       (CicUnification.UnificationFailure msg) -> raise (RefineFailure msg)
63     | (CicUnification.Uncertain msg) -> raise (Uncertain msg)
64 ;;
65
66 let profiler = HExtlib.profile "CicRefine.fo_unif"
67
68 let fo_unif_subst subst context metasenv t1 t2 ugraph =
69   try
70 let foo () =
71     CicUnification.fo_unif_subst subst context metasenv t1 t2 ugraph
72 in profiler.HExtlib.profile foo ()
73   with
74       (CicUnification.UnificationFailure msg) -> raise (RefineFailure msg)
75     | (CicUnification.Uncertain msg) -> raise (Uncertain msg)
76 ;;
77
78 let enrich localization_tbl t ?(f = fun msg -> msg) exn =
79  let exn' =
80   match exn with
81      RefineFailure msg -> RefineFailure (f msg)
82    | Uncertain msg -> Uncertain (f msg)
83    | AssertFailure msg -> prerr_endline (Lazy.force msg); AssertFailure (f msg)
84    | Sys.Break -> raise exn
85    | _ -> prerr_endline (Printexc.to_string exn); assert false 
86  in
87  let loc =
88   try
89    Cic.CicHash.find localization_tbl t
90   with Not_found ->
91    prerr_endline ("!!! NOT LOCALIZED: " ^ CicPp.ppterm t);
92    raise exn'
93  in
94   raise (HExtlib.Localized (loc,exn'))
95
96 let relocalize localization_tbl oldt newt =
97  try
98   let infos = Cic.CicHash.find localization_tbl oldt in
99    Cic.CicHash.remove localization_tbl oldt;
100    Cic.CicHash.add localization_tbl newt infos;
101  with
102   Not_found -> ()
103 ;;
104                        
105 let rec split l n =
106  match (l,n) with
107     (l,0) -> ([], l)
108   | (he::tl, n) -> let (l1,l2) = split tl (n-1) in (he::l1,l2)
109   | (_,_) -> raise (AssertFailure (lazy "split: list too short"))
110 ;;
111
112 let exp_impl metasenv subst context =
113  function
114   | Some `Type ->
115       let (metasenv', idx) = 
116         CicMkImplicit.mk_implicit_type metasenv subst context in
117       let irl = 
118         CicMkImplicit.identity_relocation_list_for_metavariable context in
119       metasenv', Cic.Meta (idx, irl)
120   | Some `Closed ->
121       let (metasenv', idx) = CicMkImplicit.mk_implicit metasenv subst [] in
122       metasenv', Cic.Meta (idx, [])
123   | None ->
124       let (metasenv', idx) = CicMkImplicit.mk_implicit metasenv subst context in
125       let irl = 
126         CicMkImplicit.identity_relocation_list_for_metavariable context in
127       metasenv', Cic.Meta (idx, irl)
128   | _ -> assert false
129 ;;
130
131 let is_a_double_coercion t =
132   let last_of l = 
133     let rec aux acc = function
134       | x::[] -> acc,x
135       | x::tl -> aux (acc@[x]) tl
136       | [] -> assert false
137     in
138     aux [] l
139   in
140   let imp = Cic.Implicit None in
141   let dummyres = false,imp, imp,imp,imp in
142   match t with
143   | Cic.Appl (c1::tl) when CoercDb.is_a_coercion' c1 ->
144       (match last_of tl with
145       | sib1,Cic.Appl (c2::tl2) when CoercDb.is_a_coercion' c2 ->
146           let sib2,head = last_of tl2 in
147           true, c1, c2, head,Cic.Appl (c1::sib1@[Cic.Appl
148             (c2::sib2@[imp])]) 
149       | _ -> dummyres)
150   | _ -> dummyres
151
152 let more_args_than_expected
153   localization_tbl metasenv subst he context hetype' tlbody_and_type exn
154 =
155   let msg = 
156     lazy ("The term " ^
157       CicMetaSubst.ppterm_in_context ~metasenv subst he context ^ 
158       " (that has type "^CicMetaSubst.ppterm_in_context ~metasenv subst hetype' context ^
159       ") is here applied to " ^ string_of_int (List.length tlbody_and_type) ^
160       " arguments that are more than expected")
161   in
162   enrich localization_tbl he ~f:(fun _-> msg) exn
163 ;; 
164
165 let mk_prod_of_metas metasenv context' subst args = 
166   let rec mk_prod metasenv context' = function
167     | [] ->
168         let (metasenv, idx) = 
169           CicMkImplicit.mk_implicit_type metasenv subst context'
170         in
171         let irl =
172           CicMkImplicit.identity_relocation_list_for_metavariable context'
173         in
174           metasenv,Cic.Meta (idx, irl)
175     | (_,argty)::tl ->
176         let (metasenv, idx) = 
177           CicMkImplicit.mk_implicit_type metasenv subst context' 
178         in
179         let irl =
180           CicMkImplicit.identity_relocation_list_for_metavariable context'
181         in
182         let meta = Cic.Meta (idx,irl) in
183         let name =
184           (* The name must be fresh for context.                 *)
185           (* Nevertheless, argty is well-typed only in context.  *)
186           (* Thus I generate a name (name_hint) in context and   *)
187           (* then I generate a name --- using the hint name_hint *)
188           (* --- that is fresh in context'.                      *)
189           let name_hint = 
190             (* Cic.Name "pippo" *)
191             FreshNamesGenerator.mk_fresh_name ~subst metasenv 
192               (* (CicMetaSubst.apply_subst_metasenv subst metasenv) *)
193               (CicMetaSubst.apply_subst_context subst context')
194               Cic.Anonymous
195               ~typ:(CicMetaSubst.apply_subst subst argty) 
196           in
197             (* [] and (Cic.Sort Cic.prop) are dummy: they will not be used *)
198             FreshNamesGenerator.mk_fresh_name ~subst
199               [] context' name_hint ~typ:(Cic.Sort Cic.Prop)
200         in
201         let metasenv,target =
202           mk_prod metasenv ((Some (name, Cic.Decl meta))::context') tl
203         in
204           metasenv,Cic.Prod (name,meta,target)
205   in
206   mk_prod metasenv context' args
207 ;;
208   
209 let rec type_of_constant uri ugraph =
210  let module C = Cic in
211  let module R = CicReduction in
212  let module U = UriManager in
213   let _ = CicTypeChecker.typecheck uri in
214   let obj,u =
215    try
216     CicEnvironment.get_cooked_obj ugraph uri
217    with Not_found -> assert false
218   in
219    match obj with
220       C.Constant (_,_,ty,_,_) -> ty,u
221     | C.CurrentProof (_,_,_,ty,_,_) -> ty,u
222     | _ ->
223        raise
224         (RefineFailure 
225           (lazy ("Unknown constant definition " ^  U.string_of_uri uri)))
226
227 and type_of_variable uri ugraph =
228   let module C = Cic in
229   let module R = CicReduction in
230   let module U = UriManager in
231   let _ = CicTypeChecker.typecheck uri in
232   let obj,u =
233    try
234     CicEnvironment.get_cooked_obj ugraph uri
235     with Not_found -> assert false
236   in
237    match obj with
238       C.Variable (_,_,ty,_,_) -> ty,u
239     | _ ->
240         raise
241          (RefineFailure
242           (lazy ("Unknown variable definition " ^ UriManager.string_of_uri uri)))
243
244 and type_of_mutual_inductive_defs uri i ugraph =
245   let module C = Cic in
246   let module R = CicReduction in
247   let module U = UriManager in
248   let _ = CicTypeChecker.typecheck uri in
249   let obj,u =
250    try
251     CicEnvironment.get_cooked_obj ugraph uri
252    with Not_found -> assert false
253   in
254    match obj with
255       C.InductiveDefinition (dl,_,_,_) ->
256         let (_,_,arity,_) = List.nth dl i in
257          arity,u
258     | _ ->
259        raise
260         (RefineFailure
261          (lazy ("Unknown mutual inductive definition " ^ U.string_of_uri uri)))
262
263 and type_of_mutual_inductive_constr uri i j ugraph =
264   let module C = Cic in
265   let module R = CicReduction in
266   let module U = UriManager in
267   let _ = CicTypeChecker.typecheck uri in
268    let obj,u =
269     try
270      CicEnvironment.get_cooked_obj ugraph uri
271     with Not_found -> assert false
272    in
273     match obj with
274         C.InductiveDefinition (dl,_,_,_) ->
275           let (_,_,_,cl) = List.nth dl i in
276           let (_,ty) = List.nth cl (j-1) in
277             ty,u
278       | _ -> 
279           raise
280                   (RefineFailure
281               (lazy 
282                 ("Unkown mutual inductive definition " ^ U.string_of_uri uri)))
283
284
285 (* type_of_aux' is just another name (with a different scope) for type_of_aux *)
286
287 (* the check_branch function checks if a branch of a case is refinable. 
288    It returns a pair (outype_instance,args), a subst and a metasenv.
289    outype_instance is the expected result of applying the case outtype 
290    to args. 
291    The problem is that outype is in general unknown, and we should
292    try to synthesize it from the above information, that is in general
293    a second order unification problem. *)
294  
295 and check_branch n context metasenv subst left_args_no actualtype term expectedtype ugraph =
296   let module C = Cic in
297     (* let module R = CicMetaSubst in *)
298   let module R = CicReduction in
299     match R.whd ~subst context expectedtype with
300         C.MutInd (_,_,_) ->
301           (n,context,actualtype, [term]), subst, metasenv, ugraph
302       | C.Appl (C.MutInd (_,_,_)::tl) ->
303           let (_,arguments) = split tl left_args_no in
304             (n,context,actualtype, arguments@[term]), subst, metasenv, ugraph 
305       | C.Prod (name,so,de) ->
306           (* we expect that the actual type of the branch has the due 
307              number of Prod *)
308           (match R.whd ~subst context actualtype with
309                C.Prod (name',so',de') ->
310                  let subst, metasenv, ugraph1 = 
311                    fo_unif_subst subst context metasenv so so' ugraph in
312                  let term' =
313                    (match CicSubstitution.lift 1 term with
314                         C.Appl l -> C.Appl (l@[C.Rel 1])
315                       | t -> C.Appl [t ; C.Rel 1]) in
316                    (* we should also check that the name variable is anonymous in
317                       the actual type de' ?? *)
318                    check_branch (n+1) 
319                      ((Some (name,(C.Decl so)))::context) 
320                        metasenv subst left_args_no de' term' de ugraph1
321              | _ -> raise (AssertFailure (lazy "Wrong number of arguments")))
322       | _ -> raise (AssertFailure (lazy "Prod or MutInd expected"))
323
324 and type_of_aux' ?(localization_tbl = Cic.CicHash.create 1) metasenv context t
325      ugraph
326 =
327   let rec type_of_aux subst metasenv context t ugraph =
328     let module C = Cic in
329     let module S = CicSubstitution in
330     let module U = UriManager in
331 (*
332     let try_coercion t subst context ugraph coercion_tgt (metasenv,last,coerced) =
333      let subst,metasenv,ugraph =
334       fo_unif_subst subst context metasenv last t ugraph
335      in
336       try
337         let newt, tty, subst, metasenv, ugraph = 
338          avoid_double_coercion context subst metasenv ugraph coerced
339           coercion_tgt
340         in
341           Some (newt, tty, subst, metasenv, ugraph)
342       with 
343       | RefineFailure _ | Uncertain _ -> None
344     in
345 *)
346      let (t',_,_,_,_) as res =
347       match t with
348           (*    function *)
349           C.Rel n ->
350             (try
351                match List.nth context (n - 1) with
352                    Some (_,C.Decl ty) -> 
353                      t,S.lift n ty,subst,metasenv, ugraph
354                  | Some (_,C.Def (_,Some ty)) -> 
355                      t,S.lift n ty,subst,metasenv, ugraph
356                  | Some (_,C.Def (bo,None)) ->
357                      let ty,ugraph =
358                       (* if it is in the context it must be already well-typed*)
359                       CicTypeChecker.type_of_aux' ~subst metasenv context
360                        (S.lift n bo) ugraph 
361                      in
362                       t,ty,subst,metasenv,ugraph
363                  | None ->
364                     enrich localization_tbl t
365                      (RefineFailure (lazy "Rel to hidden hypothesis"))
366              with
367               Failure _ ->
368                enrich localization_tbl t
369                 (RefineFailure (lazy "Not a closed term")))
370         | C.Var (uri,exp_named_subst) ->
371             let exp_named_subst',subst',metasenv',ugraph1 =
372               check_exp_named_subst 
373                 subst metasenv context exp_named_subst ugraph 
374             in
375             let ty_uri,ugraph1 = type_of_variable uri ugraph in
376             let ty =
377               CicSubstitution.subst_vars exp_named_subst' ty_uri
378             in
379               C.Var (uri,exp_named_subst'),ty,subst',metasenv',ugraph1
380         | C.Meta (n,l) -> 
381             (try
382                let (canonical_context, term,ty) = 
383                  CicUtil.lookup_subst n subst 
384                in
385                let l',subst',metasenv',ugraph1 =
386                  check_metasenv_consistency n subst metasenv context
387                    canonical_context l ugraph 
388                in
389                  (* trust or check ??? *)
390                  C.Meta (n,l'),CicSubstitution.subst_meta l' ty, 
391                    subst', metasenv', ugraph1
392                    (* type_of_aux subst metasenv 
393                       context (CicSubstitution.subst_meta l term) *)
394              with CicUtil.Subst_not_found _ ->
395                let (_,canonical_context,ty) = CicUtil.lookup_meta n metasenv in
396                let l',subst',metasenv', ugraph1 =
397                  check_metasenv_consistency n subst metasenv context
398                    canonical_context l ugraph
399                in
400                  C.Meta (n,l'),CicSubstitution.subst_meta l' ty, 
401                    subst', metasenv',ugraph1)
402         | C.Sort (C.Type tno) -> 
403             let tno' = CicUniv.fresh() in 
404              (try
405                let ugraph1 = CicUniv.add_gt tno' tno ugraph in
406                  t,(C.Sort (C.Type tno')),subst,metasenv,ugraph1
407               with
408                CicUniv.UniverseInconsistency msg -> raise (RefineFailure msg))
409         | C.Sort _ -> 
410             t,C.Sort (C.Type (CicUniv.fresh())),subst,metasenv,ugraph
411         | C.Implicit infos ->
412            let metasenv',t' = exp_impl metasenv subst context infos in
413             type_of_aux subst metasenv' context t' ugraph
414         | C.Cast (te,ty) ->
415             let ty',_,subst',metasenv',ugraph1 =
416               type_of_aux subst metasenv context ty ugraph 
417             in
418             let te',inferredty,subst'',metasenv'',ugraph2 =
419               type_of_aux subst' metasenv' context te ugraph1
420             in
421             let (te', ty'), subst''',metasenv''',ugraph3 =
422               coerce_to_something true localization_tbl te' inferredty ty'
423                 subst'' metasenv'' context ugraph2
424             in
425              C.Cast (te',ty'),ty',subst''',metasenv''',ugraph3
426         | C.Prod (name,s,t) ->
427             let s',sort1,subst',metasenv',ugraph1 = 
428               type_of_aux subst metasenv context s ugraph 
429             in
430             let s',sort1,subst', metasenv',ugraph1 = 
431               coerce_to_sort localization_tbl 
432               s' sort1 subst' context metasenv' ugraph1
433             in
434             let context_for_t = ((Some (name,(C.Decl s')))::context) in
435             let t',sort2,subst'',metasenv'',ugraph2 =
436               type_of_aux subst' metasenv' 
437                 context_for_t t ugraph1
438             in
439             let t',sort2,subst'',metasenv'',ugraph2 = 
440               coerce_to_sort localization_tbl 
441               t' sort2 subst'' context_for_t metasenv'' ugraph2
442             in
443               let sop,subst''',metasenv''',ugraph3 =
444                 sort_of_prod localization_tbl subst'' metasenv'' 
445                   context (name,s') t' (sort1,sort2) ugraph2
446               in
447                 C.Prod (name,s',t'),sop,subst''',metasenv''',ugraph3
448         | C.Lambda (n,s,t) ->
449             let s',sort1,subst',metasenv',ugraph1 = 
450               type_of_aux subst metasenv context s ugraph 
451             in
452             let s',sort1,subst',metasenv',ugraph1 =
453               coerce_to_sort localization_tbl 
454               s' sort1 subst' context metasenv' ugraph1
455             in
456             let context_for_t = ((Some (n,(C.Decl s')))::context) in 
457             let t',type2,subst'',metasenv'',ugraph2 =
458               type_of_aux subst' metasenv' context_for_t t ugraph1
459             in
460               C.Lambda (n,s',t'),C.Prod (n,s',type2),
461                 subst'',metasenv'',ugraph2
462         | C.LetIn (n,s,t) ->
463             (* only to check if s is well-typed *)
464             let s',ty,subst',metasenv',ugraph1 = 
465               type_of_aux subst metasenv context s ugraph
466             in
467            let context_for_t = ((Some (n,(C.Def (s',Some ty))))::context) in
468            
469             let t',inferredty,subst'',metasenv'',ugraph2 =
470               type_of_aux subst' metasenv' 
471                 context_for_t t ugraph1
472             in
473               (* One-step LetIn reduction. 
474                * Even faster than the previous solution.
475                * Moreover the inferred type is closer to the expected one. 
476                *)
477               C.LetIn (n,s',t'),
478                CicSubstitution.subst ~avoid_beta_redexes:true s' inferredty,
479                subst'',metasenv'',ugraph2
480         | C.Appl (he::((_::_) as tl)) ->
481             let he',hetype,subst',metasenv',ugraph1 = 
482               type_of_aux subst metasenv context he ugraph 
483             in
484             let tlbody_and_type,subst'',metasenv'',ugraph2 =
485                typeof_list subst' metasenv' context ugraph1 tl
486             in
487             let coerced_he,coerced_args,applty,subst''',metasenv''',ugraph3 =
488               eat_prods true subst'' metasenv'' context 
489                 he' hetype tlbody_and_type ugraph2
490             in
491             let newappl = (C.Appl (coerced_he::coerced_args)) in
492             avoid_double_coercion 
493               context subst''' metasenv''' ugraph3 newappl applty
494         | C.Appl _ -> assert false
495         | C.Const (uri,exp_named_subst) ->
496             let exp_named_subst',subst',metasenv',ugraph1 =
497               check_exp_named_subst subst metasenv context 
498                 exp_named_subst ugraph in
499             let ty_uri,ugraph2 = type_of_constant uri ugraph1 in
500             let cty =
501               CicSubstitution.subst_vars exp_named_subst' ty_uri
502             in
503               C.Const (uri,exp_named_subst'),cty,subst',metasenv',ugraph2
504         | C.MutInd (uri,i,exp_named_subst) ->
505             let exp_named_subst',subst',metasenv',ugraph1 =
506               check_exp_named_subst subst metasenv context 
507                 exp_named_subst ugraph 
508             in
509             let ty_uri,ugraph2 = type_of_mutual_inductive_defs uri i ugraph1 in
510             let cty =
511               CicSubstitution.subst_vars exp_named_subst' ty_uri in
512               C.MutInd (uri,i,exp_named_subst'),cty,subst',metasenv',ugraph2
513         | C.MutConstruct (uri,i,j,exp_named_subst) ->
514             let exp_named_subst',subst',metasenv',ugraph1 =
515               check_exp_named_subst subst metasenv context 
516                 exp_named_subst ugraph 
517             in
518             let ty_uri,ugraph2 = 
519               type_of_mutual_inductive_constr uri i j ugraph1 
520             in
521             let cty =
522               CicSubstitution.subst_vars exp_named_subst' ty_uri 
523             in
524               C.MutConstruct (uri,i,j,exp_named_subst'),cty,subst',
525                 metasenv',ugraph2
526         | C.MutCase (uri, i, outtype, term, pl) ->
527             (* first, get the inductive type (and noparams) 
528              * in the environment  *)
529             let (_,b,arity,constructors), expl_params, no_left_params,ugraph =
530               let _ = CicTypeChecker.typecheck uri in
531               let obj,u = CicEnvironment.get_cooked_obj ugraph uri in
532               match obj with
533                   C.InductiveDefinition (l,expl_params,parsno,_) -> 
534                     List.nth l i , expl_params, parsno, u
535                 | _ ->
536                     enrich localization_tbl t
537                      (RefineFailure
538                        (lazy ("Unkown mutual inductive definition " ^ 
539                          U.string_of_uri uri)))
540            in
541            let rec count_prod t =
542              match CicReduction.whd ~subst context t with
543                  C.Prod (_, _, t) -> 1 + (count_prod t)
544                | _ -> 0 
545            in 
546            let no_args = count_prod arity in
547              (* now, create a "generic" MutInd *)
548            let metasenv,left_args = 
549              CicMkImplicit.n_fresh_metas metasenv subst context no_left_params
550            in
551            let metasenv,right_args = 
552              let no_right_params = no_args - no_left_params in
553                if no_right_params < 0 then assert false
554                else CicMkImplicit.n_fresh_metas 
555                       metasenv subst context no_right_params 
556            in
557            let metasenv,exp_named_subst = 
558              CicMkImplicit.fresh_subst metasenv subst context expl_params in
559            let expected_type = 
560              if no_args = 0 then 
561                C.MutInd (uri,i,exp_named_subst)
562              else
563                C.Appl 
564                  (C.MutInd (uri,i,exp_named_subst)::(left_args @ right_args))
565            in
566              (* check consistency with the actual type of term *)
567            let term',actual_type,subst,metasenv,ugraph1 = 
568              type_of_aux subst metasenv context term ugraph in
569            let expected_type',_, subst, metasenv,ugraph2 =
570              type_of_aux subst metasenv context expected_type ugraph1
571            in
572            let actual_type = CicReduction.whd ~subst context actual_type in
573            let subst,metasenv,ugraph3 =
574             try
575              fo_unif_subst subst context metasenv 
576                expected_type' actual_type ugraph2
577             with
578              exn ->
579               enrich localization_tbl term' exn
580                ~f:(function _ ->
581                  lazy ("(10)The term " ^
582                   CicMetaSubst.ppterm_in_context ~metasenv subst term'
583                    context ^ " has type " ^
584                   CicMetaSubst.ppterm_in_context ~metasenv subst actual_type
585                    context ^ " but is here used with type " ^
586                   CicMetaSubst.ppterm_in_context ~metasenv subst expected_type' context))
587            in
588            let rec instantiate_prod t =
589             function
590                [] -> t
591              | he::tl ->
592                 match CicReduction.whd ~subst context t with
593                    C.Prod (_,_,t') ->
594                     instantiate_prod (CicSubstitution.subst he t') tl
595                  | _ -> assert false
596            in
597            let arity_instantiated_with_left_args =
598             instantiate_prod arity left_args in
599              (* TODO: check if the sort elimination 
600               * is allowed: [(I q1 ... qr)|B] *)
601            let (pl',_,outtypeinstances,subst,metasenv,ugraph4) =
602              List.fold_right
603                (fun p (pl,j,outtypeinstances,subst,metasenv,ugraph) ->
604                   let constructor =
605                     if left_args = [] then
606                       (C.MutConstruct (uri,i,j,exp_named_subst))
607                     else
608                       (C.Appl 
609                         (C.MutConstruct (uri,i,j,exp_named_subst)::left_args))
610                   in
611                   let p',actual_type,subst,metasenv,ugraph1 = 
612                     type_of_aux subst metasenv context p ugraph 
613                   in
614                   let constructor',expected_type, subst, metasenv,ugraph2 = 
615                     type_of_aux subst metasenv context constructor ugraph1 
616                   in
617                   let outtypeinstance,subst,metasenv,ugraph3 =
618                    try
619                     check_branch 0 context metasenv subst
620                      no_left_params actual_type constructor' expected_type
621                      ugraph2 
622                    with
623                     exn ->
624                      enrich localization_tbl constructor'
625                       ~f:(fun _ ->
626                         lazy ("(11)The term " ^
627                          CicMetaSubst.ppterm_in_context metasenv subst p'
628                           context ^ " has type " ^
629                          CicMetaSubst.ppterm_in_context metasenv subst actual_type
630                           context ^ " but is here used with type " ^
631                          CicMetaSubst.ppterm_in_context metasenv subst expected_type
632                           context)) exn
633                   in
634                     (p'::pl,j-1,
635                      outtypeinstances@[outtypeinstance],subst,metasenv,ugraph3))
636                pl ([],List.length pl,[],subst,metasenv,ugraph3)
637            in
638            
639              (* we are left to check that the outype matches his instances.
640                 The easy case is when the outype is specified, that amount
641                 to a trivial check. Otherwise, we should guess a type from
642                 its instances 
643              *)
644              
645            let outtype,outtypety, subst, metasenv,ugraph4 =
646              type_of_aux subst metasenv context outtype ugraph4 in
647            (match outtype with
648            | C.Meta (n,l) ->
649                (let candidate,ugraph5,metasenv,subst = 
650                  let exp_name_subst, metasenv = 
651                     let o,_ = 
652                       CicEnvironment.get_cooked_obj CicUniv.empty_ugraph uri 
653                     in
654                     let uris = CicUtil.params_of_obj o in
655                     List.fold_right (
656                       fun uri (acc,metasenv) -> 
657                         let metasenv',new_meta = 
658                            CicMkImplicit.mk_implicit metasenv subst context
659                         in
660                         let irl =
661                           CicMkImplicit.identity_relocation_list_for_metavariable 
662                             context
663                         in
664                         (uri, Cic.Meta(new_meta,irl))::acc, metasenv'
665                     ) uris ([],metasenv)
666                  in
667                  let ty =
668                   match left_args,right_args with
669                      [],[] -> Cic.MutInd(uri, i, exp_name_subst)
670                    | _,_ ->
671                       let rec mk_right_args =
672                        function
673                           0 -> []
674                         | n -> (Cic.Rel n)::(mk_right_args (n - 1))
675                       in
676                       let right_args_no = List.length right_args in
677                       let lifted_left_args =
678                        List.map (CicSubstitution.lift right_args_no) left_args
679                       in
680                        Cic.Appl (Cic.MutInd(uri,i,exp_name_subst)::
681                         (lifted_left_args @ mk_right_args right_args_no))
682                  in
683                  let fresh_name = 
684                    FreshNamesGenerator.mk_fresh_name ~subst metasenv 
685                      context Cic.Anonymous ~typ:ty
686                  in
687                  match outtypeinstances with
688                  | [] -> 
689                      let extended_context = 
690                       let rec add_right_args =
691                        function
692                           Cic.Prod (name,ty,t) ->
693                            Some (name,Cic.Decl ty)::(add_right_args t)
694                         | _ -> []
695                       in
696                        (Some (fresh_name,Cic.Decl ty))::
697                        (List.rev
698                         (add_right_args arity_instantiated_with_left_args))@
699                        context
700                      in
701                      let metasenv,new_meta = 
702                        CicMkImplicit.mk_implicit metasenv subst extended_context
703                      in
704                        let irl =
705                        CicMkImplicit.identity_relocation_list_for_metavariable 
706                          extended_context
707                      in
708                      let rec add_lambdas b =
709                       function
710                          Cic.Prod (name,ty,t) ->
711                           Cic.Lambda (name,ty,(add_lambdas b t))
712                        | _ -> Cic.Lambda (fresh_name, ty, b)
713                      in
714                      let candidate = 
715                       add_lambdas (Cic.Meta (new_meta,irl))
716                        arity_instantiated_with_left_args
717                      in
718                      (Some candidate),ugraph4,metasenv,subst
719                  | (constructor_args_no,_,instance,_)::tl -> 
720                      try
721                        let instance',subst,metasenv = 
722                          CicMetaSubst.delift_rels subst metasenv
723                           constructor_args_no instance
724                        in
725                        let candidate,ugraph,metasenv,subst =
726                          List.fold_left (
727                            fun (candidate_oty,ugraph,metasenv,subst) 
728                              (constructor_args_no,_,instance,_) ->
729                                match candidate_oty with
730                                | None -> None,ugraph,metasenv,subst
731                                | Some ty ->
732                                  try 
733                                    let instance',subst,metasenv = 
734                                      CicMetaSubst.delift_rels subst metasenv
735                                       constructor_args_no instance
736                                    in
737                                    let subst,metasenv,ugraph =
738                                     fo_unif_subst subst context metasenv 
739                                       instance' ty ugraph
740                                    in
741                                     candidate_oty,ugraph,metasenv,subst
742                                  with
743                                     CicMetaSubst.DeliftingARelWouldCaptureAFreeVariable
744                                   | RefineFailure _ | Uncertain _ ->
745                                      None,ugraph,metasenv,subst
746                          ) (Some instance',ugraph4,metasenv,subst) tl
747                        in
748                        match candidate with
749                        | None -> None, ugraph,metasenv,subst
750                        | Some t -> 
751                           let rec add_lambdas n b =
752                            function
753                               Cic.Prod (name,ty,t) ->
754                                Cic.Lambda (name,ty,(add_lambdas (n + 1) b t))
755                             | _ ->
756                               Cic.Lambda (fresh_name, ty,
757                                CicSubstitution.lift (n + 1) t)
758                           in
759                            Some
760                             (add_lambdas 0 t arity_instantiated_with_left_args),
761                            ugraph,metasenv,subst
762                      with CicMetaSubst.DeliftingARelWouldCaptureAFreeVariable ->
763                        None,ugraph4,metasenv,subst
764                in
765                match candidate with
766                | None -> raise (Uncertain (lazy "can't solve an higher order unification problem"))
767                | Some candidate ->
768                    let subst,metasenv,ugraph = 
769                     try
770                      fo_unif_subst subst context metasenv 
771                        candidate outtype ugraph5
772                     with
773                      exn -> assert false(* unification against a metavariable *)
774                    in
775                      C.MutCase (uri, i, outtype, term', pl'),
776                       CicReduction.head_beta_reduce
777                        (CicMetaSubst.apply_subst subst
778                         (Cic.Appl (outtype::right_args@[term']))),
779                      subst,metasenv,ugraph)
780            | _ ->    (* easy case *)
781              let tlbody_and_type,subst,metasenv,ugraph4 =
782                typeof_list subst metasenv context ugraph4 (right_args @ [term'])
783              in
784              let _,_,_,subst,metasenv,ugraph4 =
785                eat_prods false subst metasenv context 
786                  outtype outtypety tlbody_and_type ugraph4
787              in
788              let _,_, subst, metasenv,ugraph5 =
789                type_of_aux subst metasenv context
790                  (C.Appl ((outtype :: right_args) @ [term'])) ugraph4
791              in
792              let (subst,metasenv,ugraph6) = 
793                List.fold_left2
794                  (fun (subst,metasenv,ugraph) 
795                    p (constructor_args_no,context,instance,args)
796                   ->
797                     let instance' = 
798                       let appl =
799                         let outtype' =
800                           CicSubstitution.lift constructor_args_no outtype
801                         in
802                           C.Appl (outtype'::args)
803                       in
804                         CicReduction.whd ~subst context appl
805                     in
806                      try
807                       fo_unif_subst subst context metasenv instance instance'
808                        ugraph
809                      with
810                       exn ->
811                        enrich localization_tbl p exn
812                         ~f:(function _ ->
813                           lazy ("(12)The term " ^
814                            CicMetaSubst.ppterm_in_context ~metasenv subst p
815                             context ^ " has type " ^
816                            CicMetaSubst.ppterm_in_context ~metasenv subst instance'
817                             context ^ " but is here used with type " ^
818                            CicMetaSubst.ppterm_in_context ~metasenv subst instance
819                             context)))
820                  (subst,metasenv,ugraph5) pl' outtypeinstances 
821              in
822                C.MutCase (uri, i, outtype, term', pl'),
823                  CicReduction.head_beta_reduce
824                   (CicMetaSubst.apply_subst subst
825                    (C.Appl(outtype::right_args@[term]))),
826                  subst,metasenv,ugraph6)
827         | C.Fix (i,fl) ->
828             let fl_ty',subst,metasenv,types,ugraph1,len =
829               List.fold_left
830                 (fun (fl,subst,metasenv,types,ugraph,len) (n,_,ty,_) ->
831                    let ty',_,subst',metasenv',ugraph1 = 
832                       type_of_aux subst metasenv context ty ugraph 
833                    in
834                      fl @ [ty'],subst',metasenv', 
835                        Some (C.Name n,(C.Decl (CicSubstitution.lift len ty')))
836                         :: types, ugraph, len+1
837                 ) ([],subst,metasenv,[],ugraph,0) fl
838             in
839             let context' = types@context in
840             let fl_bo',subst,metasenv,ugraph2 =
841               List.fold_left
842                 (fun (fl,subst,metasenv,ugraph) ((name,x,_,bo),ty) ->
843                    let bo',ty_of_bo,subst,metasenv,ugraph1 =
844                      type_of_aux subst metasenv context' bo ugraph in
845                    let expected_ty = CicSubstitution.lift len ty in
846                    let subst',metasenv',ugraph' =
847                     try
848                      fo_unif_subst subst context' metasenv
849                        ty_of_bo expected_ty ugraph1
850                     with
851                      exn ->
852                       enrich localization_tbl bo exn
853                        ~f:(function _ ->
854                          lazy ("(13)The term " ^
855                           CicMetaSubst.ppterm_in_context ~metasenv subst bo
856                            context' ^ " has type " ^
857                           CicMetaSubst.ppterm_in_context ~metasenv subst ty_of_bo
858                            context' ^ " but is here used with type " ^
859                           CicMetaSubst.ppterm_in_context ~metasenv subst expected_ty
860                            context))
861                    in 
862                      fl @ [bo'] , subst',metasenv',ugraph'
863                 ) ([],subst,metasenv,ugraph1) (List.combine fl fl_ty') 
864             in
865             let ty = List.nth fl_ty' i in
866             (* now we have the new ty in fl_ty', the new bo in fl_bo',
867              * and we want the new fl with bo' and ty' injected in the right
868              * place.
869              *) 
870             let rec map3 f l1 l2 l3 =
871               match l1,l2,l3 with
872               | [],[],[] -> []
873               | h1::tl1,h2::tl2,h3::tl3 -> (f h1 h2 h3) :: (map3 f tl1 tl2 tl3)
874               | _ -> assert false 
875             in
876             let fl'' = map3 (fun ty' bo' (name,x,ty,bo) -> (name,x,ty',bo') ) 
877               fl_ty' fl_bo' fl 
878             in
879               C.Fix (i,fl''),ty,subst,metasenv,ugraph2
880         | C.CoFix (i,fl) ->
881             let fl_ty',subst,metasenv,types,ugraph1,len =
882               List.fold_left
883                 (fun (fl,subst,metasenv,types,ugraph,len) (n,ty,_) ->
884                    let ty',_,subst',metasenv',ugraph1 = 
885                      type_of_aux subst metasenv context ty ugraph 
886                    in
887                      fl @ [ty'],subst',metasenv', 
888                       Some (C.Name n,(C.Decl (CicSubstitution.lift len ty'))) ::
889                         types, ugraph1, len+1
890                 ) ([],subst,metasenv,[],ugraph,0) fl
891             in
892             let context' = types@context in
893             let fl_bo',subst,metasenv,ugraph2 =
894               List.fold_left
895                 (fun (fl,subst,metasenv,ugraph) ((name,_,bo),ty) ->
896                    let bo',ty_of_bo,subst,metasenv,ugraph1 =
897                      type_of_aux subst metasenv context' bo ugraph in
898                    let expected_ty = CicSubstitution.lift len ty in
899                    let subst',metasenv',ugraph' = 
900                     try
901                      fo_unif_subst subst context' metasenv
902                        ty_of_bo expected_ty ugraph1
903                     with
904                      exn ->
905                       enrich localization_tbl bo exn
906                        ~f:(function _ ->
907                          lazy ("(14)The term " ^
908                           CicMetaSubst.ppterm_in_context ~metasenv subst bo
909                            context' ^ " has type " ^
910                           CicMetaSubst.ppterm_in_context ~metasenv subst ty_of_bo
911                            context' ^ " but is here used with type " ^
912                           CicMetaSubst.ppterm_in_context ~metasenv subst expected_ty
913                            context))
914                    in
915                      fl @ [bo'],subst',metasenv',ugraph'
916                 ) ([],subst,metasenv,ugraph1) (List.combine fl fl_ty')
917             in
918             let ty = List.nth fl_ty' i in
919             (* now we have the new ty in fl_ty', the new bo in fl_bo',
920              * and we want the new fl with bo' and ty' injected in the right
921              * place.
922              *) 
923             let rec map3 f l1 l2 l3 =
924               match l1,l2,l3 with
925               | [],[],[] -> []
926               | h1::tl1,h2::tl2,h3::tl3 -> (f h1 h2 h3) :: (map3 f tl1 tl2 tl3)
927               | _ -> assert false
928             in
929             let fl'' = map3 (fun ty' bo' (name,ty,bo) -> (name,ty',bo') ) 
930               fl_ty' fl_bo' fl 
931             in
932               C.CoFix (i,fl''),ty,subst,metasenv,ugraph2
933      in
934       relocalize localization_tbl t t';
935       res
936
937   (* check_metasenv_consistency checks that the "canonical" context of a
938      metavariable is consitent - up to relocation via the relocation list l -
939      with the actual context *)
940   and check_metasenv_consistency
941     metano subst metasenv context canonical_context l ugraph
942     =
943     let module C = Cic in
944     let module R = CicReduction in
945     let module S = CicSubstitution in
946     let lifted_canonical_context = 
947       let rec aux i =
948         function
949             [] -> []
950           | (Some (n,C.Decl t))::tl ->
951               (Some (n,C.Decl (S.subst_meta l (S.lift i t))))::(aux (i+1) tl)
952           | (Some (n,C.Def (t,None)))::tl ->
953               (Some (n,C.Def ((S.subst_meta l (S.lift i t)),None)))::(aux (i+1) tl)
954           | None::tl -> None::(aux (i+1) tl)
955           | (Some (n,C.Def (t,Some ty)))::tl ->
956               (Some (n,
957                      C.Def ((S.subst_meta l (S.lift i t)),
958                             Some (S.subst_meta l (S.lift i ty))))) :: (aux (i+1) tl)
959       in
960         aux 1 canonical_context 
961     in
962       try
963         List.fold_left2 
964           (fun (l,subst,metasenv,ugraph) t ct -> 
965              match (t,ct) with
966                  _,None ->
967                    l @ [None],subst,metasenv,ugraph
968                | Some t,Some (_,C.Def (ct,_)) ->
969                    let subst',metasenv',ugraph' = 
970                    (try
971 prerr_endline ("poco geniale: nel caso di IRL basterebbe sapere che questo e' il Rel corrispondente. Si puo' ottimizzare il caso t = rel.");
972                       fo_unif_subst subst context metasenv t ct ugraph
973                     with e -> raise (RefineFailure (lazy (sprintf "The local context is not consistent with the canonical context, since %s cannot be unified with %s. Reason: %s" (CicMetaSubst.ppterm ~metasenv subst t) (CicMetaSubst.ppterm ~metasenv subst ct) (match e with AssertFailure msg -> Lazy.force msg | _ -> (Printexc.to_string e))))))
974                    in
975                      l @ [Some t],subst',metasenv',ugraph'
976                | Some t,Some (_,C.Decl ct) ->
977                    let t',inferredty,subst',metasenv',ugraph1 =
978                      type_of_aux subst metasenv context t ugraph
979                    in
980                    let subst'',metasenv'',ugraph2 = 
981                      (try
982                         fo_unif_subst
983                           subst' context metasenv' inferredty ct ugraph1
984                       with e -> raise (RefineFailure (lazy (sprintf "The local context is not consistent with the canonical context, since the type %s of %s cannot be unified with the expected type %s. Reason: %s" (CicMetaSubst.ppterm metasenv' subst' inferredty) (CicMetaSubst.ppterm metasenv' subst' t) (CicMetaSubst.ppterm metasenv' subst' ct) (match e with AssertFailure msg -> Lazy.force msg | RefineFailure msg -> Lazy.force msg | _ -> (Printexc.to_string e))))))
985                    in
986                      l @ [Some t'], subst'',metasenv'',ugraph2
987                | None, Some _  ->
988                    raise (RefineFailure (lazy (sprintf "Not well typed metavariable instance %s: the local context does not instantiate an hypothesis even if the hypothesis is not restricted in the canonical context %s" (CicMetaSubst.ppterm ~metasenv subst (Cic.Meta (metano, l))) (CicMetaSubst.ppcontext ~metasenv subst canonical_context))))) ([],subst,metasenv,ugraph) l lifted_canonical_context 
989       with
990           Invalid_argument _ ->
991             raise
992             (RefineFailure
993                (lazy (sprintf
994                   "Not well typed metavariable instance %s: the length of the local context does not match the length of the canonical context %s"
995                   (CicMetaSubst.ppterm ~metasenv subst (Cic.Meta (metano, l)))
996                   (CicMetaSubst.ppcontext ~metasenv subst canonical_context))))
997
998   and check_exp_named_subst metasubst metasenv context tl ugraph =
999     let rec check_exp_named_subst_aux metasubst metasenv substs tl ugraph  =
1000       match tl with
1001           [] -> [],metasubst,metasenv,ugraph
1002         | (uri,t)::tl ->
1003             let ty_uri,ugraph1 =  type_of_variable uri ugraph in
1004             let typeofvar =
1005               CicSubstitution.subst_vars substs ty_uri in
1006               (* CSC: why was this code here? it is wrong
1007                  (match CicEnvironment.get_cooked_obj ~trust:false uri with
1008                  Cic.Variable (_,Some bo,_,_) ->
1009                  raise
1010                  (RefineFailure (lazy
1011                  "A variable with a body can not be explicit substituted"))
1012                  | Cic.Variable (_,None,_,_) -> ()
1013                  | _ ->
1014                  raise
1015                  (RefineFailure (lazy
1016                  ("Unkown variable definition " ^ UriManager.string_of_uri uri)))
1017                  ) ;
1018               *)
1019             let t',typeoft,metasubst',metasenv',ugraph2 =
1020               type_of_aux metasubst metasenv context t ugraph1 in
1021             let subst = uri,t' in
1022             let metasubst'',metasenv'',ugraph3 =
1023               try
1024                 fo_unif_subst 
1025                   metasubst' context metasenv' typeoft typeofvar ugraph2
1026               with _ ->
1027                 raise (RefineFailure (lazy
1028                          ("Wrong Explicit Named Substitution: " ^ 
1029                            CicMetaSubst.ppterm metasenv' metasubst' typeoft ^
1030                           " not unifiable with " ^ 
1031                           CicMetaSubst.ppterm metasenv' metasubst' typeofvar)))
1032             in
1033             (* FIXME: no mere tail recursive! *)
1034             let exp_name_subst, metasubst''', metasenv''', ugraph4 = 
1035               check_exp_named_subst_aux 
1036                 metasubst'' metasenv'' (substs@[subst]) tl ugraph3
1037             in
1038               ((uri,t')::exp_name_subst), metasubst''', metasenv''', ugraph4
1039     in
1040       check_exp_named_subst_aux metasubst metasenv [] tl ugraph
1041
1042
1043   and sort_of_prod localization_tbl subst metasenv context (name,s) t (t1, t2)
1044    ugraph
1045   =
1046     let module C = Cic in
1047     let context_for_t2 = (Some (name,C.Decl s))::context in
1048     let t1'' = CicReduction.whd ~subst context t1 in
1049     let t2'' = CicReduction.whd ~subst context_for_t2 t2 in
1050       match (t1'', t2'') with
1051           (C.Sort s1, C.Sort s2)
1052             when (s2 = C.Prop or s2 = C.Set or s2 = C.CProp) -> 
1053               (* different than Coq manual!!! *)
1054               C.Sort s2,subst,metasenv,ugraph
1055         | (C.Sort (C.Type t1), C.Sort (C.Type t2)) -> 
1056             let t' = CicUniv.fresh() in 
1057              (try
1058               let ugraph1 = CicUniv.add_ge t' t1 ugraph in
1059               let ugraph2 = CicUniv.add_ge t' t2 ugraph1 in
1060                 C.Sort (C.Type t'),subst,metasenv,ugraph2
1061               with
1062                CicUniv.UniverseInconsistency msg -> raise (RefineFailure msg))
1063         | (C.Sort _,C.Sort (C.Type t1)) -> 
1064             C.Sort (C.Type t1),subst,metasenv,ugraph
1065         | (C.Meta _, C.Sort _) -> t2'',subst,metasenv,ugraph
1066         | (C.Sort _,C.Meta _) | (C.Meta _,C.Meta _) ->
1067             (* TODO how can we force the meta to become a sort? If we don't we
1068              * break the invariant that refine produce only well typed terms *)
1069             (* TODO if we check the non meta term and if it is a sort then we
1070              * are likely to know the exact value of the result e.g. if the rhs
1071              * is a Sort (Prop | Set | CProp) then the result is the rhs *)
1072             let (metasenv,idx) =
1073               CicMkImplicit.mk_implicit_sort metasenv subst in
1074             let (subst, metasenv,ugraph1) =
1075              try
1076               fo_unif_subst subst context_for_t2 metasenv 
1077                 (C.Meta (idx,[])) t2'' ugraph
1078              with _ -> assert false (* unification against a metavariable *)
1079             in
1080               t2'',subst,metasenv,ugraph1
1081         | (C.Sort _,_)
1082         | (C.Meta _,_) -> 
1083             enrich localization_tbl s
1084              (RefineFailure 
1085                (lazy 
1086                  (sprintf
1087                    "%s is supposed to be a type, but its type is %s"
1088                (CicMetaSubst.ppterm_in_context ~metasenv subst t context)
1089                (CicMetaSubst.ppterm_in_context ~metasenv subst t2 context))))
1090         | _,_ -> 
1091             enrich localization_tbl t
1092              (RefineFailure 
1093                (lazy 
1094                  (sprintf
1095                    "%s is supposed to be a type, but its type is %s"
1096                (CicMetaSubst.ppterm_in_context ~metasenv subst s context)
1097                (CicMetaSubst.ppterm_in_context ~metasenv subst t1 context))))
1098
1099   and avoid_double_coercion context subst metasenv ugraph t ty = 
1100    if not !pack_coercions then
1101     t,ty,subst,metasenv,ugraph
1102    else
1103     let b, c1, c2, head, c1_c2_implicit = is_a_double_coercion t in
1104     if b then
1105       let source_carr = CoercGraph.source_of c2 in
1106       let tgt_carr = CicMetaSubst.apply_subst subst ty in
1107       (match CoercGraph.look_for_coercion metasenv subst context source_carr tgt_carr 
1108       with
1109       | CoercGraph.SomeCoercion candidates -> 
1110          let selected =
1111            HExtlib.list_findopt
1112              (function (metasenv,last,c) ->
1113                match c with 
1114                | c when not (CoercGraph.is_composite c) -> 
1115                    debug_print (lazy ("\nNot a composite.."^CicPp.ppterm c));
1116                    None
1117                | c ->
1118                let subst,metasenv,ugraph =
1119                 fo_unif_subst subst context metasenv last head ugraph in
1120                debug_print (lazy ("\nprovo" ^ CicPp.ppterm c));
1121                (try
1122                  debug_print 
1123                    (lazy 
1124                      ("packing: " ^ 
1125                        CicPp.ppterm t ^ " ==> " ^ CicPp.ppterm c));
1126                  let newt,_,subst,metasenv,ugraph = 
1127                    type_of_aux subst metasenv context c ugraph in
1128                  debug_print (lazy "tipa...");
1129                  let subst, metasenv, ugraph =
1130                    (* COME MAI C'ERA UN IF su !pack_coercions ??? *)
1131                     fo_unif_subst subst context metasenv newt t ugraph
1132                  in
1133                  debug_print (lazy "unifica...");
1134                  Some (newt, ty, subst, metasenv, ugraph)
1135                with 
1136                | RefineFailure s | Uncertain s when not !pack_coercions-> 
1137                    debug_print s; debug_print (lazy "stop\n");None
1138                | RefineFailure s | Uncertain s -> 
1139                    debug_print s;debug_print (lazy "goon\n");
1140                    try 
1141                      let old_pack_coercions = !pack_coercions in
1142                      pack_coercions := false; (* to avoid diverging *)
1143                      let refined_c1_c2_implicit,ty,subst,metasenv,ugraph =
1144                        type_of_aux subst metasenv context c1_c2_implicit ugraph 
1145                      in
1146                      pack_coercions := old_pack_coercions;
1147                      let b, _, _, _, _ = 
1148                        is_a_double_coercion refined_c1_c2_implicit 
1149                      in 
1150                      if b then 
1151                        None 
1152                      else
1153                        let head' = 
1154                          match refined_c1_c2_implicit with
1155                          | Cic.Appl l -> HExtlib.list_last l
1156                          | _ -> assert false   
1157                        in
1158                        let subst, metasenv, ugraph =
1159                         try fo_unif_subst subst context metasenv 
1160                           head head' ugraph
1161                         with RefineFailure s| Uncertain s-> 
1162                           debug_print s;assert false 
1163                        in
1164                        let subst, metasenv, ugraph =
1165                          fo_unif_subst subst context metasenv 
1166                           refined_c1_c2_implicit t ugraph
1167                        in
1168                        Some (refined_c1_c2_implicit,ty,subst,metasenv,ugraph)
1169                    with 
1170                    | RefineFailure s | Uncertain s -> 
1171                        pack_coercions := true;debug_print s;None
1172                    | exn -> pack_coercions := true; raise exn))
1173              candidates
1174          in
1175          (match selected with
1176          | Some x -> x
1177          | None -> 
1178               debug_print
1179                 (lazy ("#### Coercion not packed: " ^ CicPp.ppterm t));
1180               t, ty, subst, metasenv, ugraph)
1181       | _ -> t, ty, subst, metasenv, ugraph)
1182     else
1183       t, ty, subst, metasenv, ugraph  
1184
1185   and typeof_list subst metasenv context ugraph l =
1186     let tlbody_and_type,subst,metasenv,ugraph =
1187       List.fold_right
1188         (fun x (res,subst,metasenv,ugraph) ->
1189            let x',ty,subst',metasenv',ugraph1 =
1190              type_of_aux subst metasenv context x ugraph
1191            in
1192             (x', ty)::res,subst',metasenv',ugraph1
1193         ) l ([],subst,metasenv,ugraph)
1194     in
1195       tlbody_and_type,subst,metasenv,ugraph
1196
1197   and eat_prods 
1198     allow_coercions subst metasenv context he hetype args_bo_and_ty ugraph 
1199   =
1200     (* aux function to add coercions to funclass *)
1201     let rec fix_arity metasenv context subst he hetype args_bo_and_ty ugraph =
1202       (* {{{ body *)
1203       let pristinemenv = metasenv in
1204       let metasenv,hetype' = 
1205         mk_prod_of_metas metasenv context subst args_bo_and_ty 
1206       in
1207       try
1208         let subst,metasenv,ugraph = 
1209           fo_unif_subst_eat_prods 
1210             subst context metasenv hetype hetype' ugraph
1211         in
1212         subst,metasenv,ugraph,hetype',he,args_bo_and_ty
1213       with RefineFailure s | Uncertain s as exn 
1214       when allow_coercions && !insert_coercions ->
1215         (* {{{ we search a coercion of the head (saturated) to funclass *)
1216         let metasenv = pristinemenv in
1217         debug_print (lazy 
1218           ("Fixing arity of: "^CicMetaSubst.ppterm ~metasenv subst hetype ^
1219            " since unif failed with: " ^ CicMetaSubst.ppterm ~metasenv subst hetype' 
1220            (* ^ " cause: " ^ Lazy.force s *)));
1221         let how_many_args_are_needed = 
1222           let rec aux n = function
1223             | Cic.Prod(_,_,t) -> aux (n+1) t
1224             | _ -> n
1225           in
1226           aux 0 (CicMetaSubst.apply_subst subst hetype)
1227         in
1228         let args, remainder = 
1229           HExtlib.split_nth how_many_args_are_needed args_bo_and_ty
1230         in
1231         let args = List.map fst args in
1232         let x = 
1233           if args <> [] then 
1234             match he with
1235             | Cic.Appl l -> Cic.Appl (l@args)
1236             | _ -> Cic.Appl (he::args) 
1237           else
1238             he
1239         in
1240         let x,xty,subst,metasenv,ugraph =
1241          (*CSC: here unsharing is necessary to avoid an unwanted
1242            relocalization. However, this also shows a great source of
1243            inefficiency: "x" is refined twice (once now and once in the
1244            subsequent eat_prods_and_args). Morevoer, how is divergence avoided?
1245          *)
1246          type_of_aux subst metasenv context (Unshare.unshare x) ugraph
1247         in
1248         let carr_src = 
1249           CoercDb.coerc_carr_of_term (CicMetaSubst.apply_subst subst xty) 
1250         in
1251         let carr_tgt = CoercDb.Fun 0 in
1252         match CoercGraph.look_for_coercion' metasenv subst context carr_src carr_tgt with
1253         | CoercGraph.NoCoercion 
1254         | CoercGraph.NotMetaClosed 
1255         | CoercGraph.NotHandled _ -> raise exn
1256         | CoercGraph.SomeCoercionToTgt candidates
1257         | CoercGraph.SomeCoercion candidates ->
1258             match  
1259             HExtlib.list_findopt 
1260               (fun (metasenv,last,coerc) -> 
1261                 let subst,metasenv,ugraph =
1262                  fo_unif_subst subst context metasenv last x ugraph in
1263                 debug_print (lazy ("Tentative " ^ CicMetaSubst.ppterm ~metasenv subst coerc));
1264                 try
1265                   (* we want this to be available in the error handler fo the
1266                    * following (so it has its own try. *)
1267                   let t,tty,subst,metasenv,ugraph =
1268                     type_of_aux subst metasenv context coerc ugraph
1269                   in 
1270                   try
1271                     let metasenv, hetype' = 
1272                       mk_prod_of_metas metasenv context subst remainder 
1273                     in
1274                     debug_print (lazy 
1275                       ("  unif: " ^ CicMetaSubst.ppterm ~metasenv subst tty ^ " = " ^ 
1276                        CicMetaSubst.ppterm ~metasenv subst hetype'));
1277                     let subst,metasenv,ugraph = 
1278                       fo_unif_subst_eat_prods 
1279                         subst context metasenv tty hetype' ugraph
1280                     in
1281                     debug_print (lazy " success!");
1282                     Some (subst,metasenv,ugraph,tty,t,remainder) 
1283                   with 
1284                   | Uncertain _ | RefineFailure _ ->
1285                       try 
1286                         let subst,metasenv,ugraph,hetype',he,args_bo_and_ty =
1287                           fix_arity
1288                             metasenv context subst t tty remainder ugraph
1289                         in
1290                         Some (subst,metasenv,ugraph,hetype',he,args_bo_and_ty)
1291                       with Uncertain _ | RefineFailure _ -> None
1292                 with
1293                    Uncertain _
1294                  | RefineFailure _
1295                  | HExtlib.Localized (_,Uncertain _)
1296                  | HExtlib.Localized (_,RefineFailure _) -> None 
1297                  | exn -> assert false) (* ritornare None, e' un localized *)
1298               candidates
1299            with
1300            | Some(subst,metasenv,ugraph,hetype',he,args_bo_and_ty)->
1301                subst,metasenv,ugraph,hetype',he,args_bo_and_ty
1302            | None -> 
1303                more_args_than_expected localization_tbl metasenv
1304                  subst he context hetype args_bo_and_ty exn
1305       (* }}} end coercion to funclass stuff *)           
1306       (* }}} end fix_arity *)           
1307     in
1308     (* aux function to process the type of the head and the args in parallel *)
1309     let rec eat_prods_and_args 
1310       pristinemenv metasenv subst context pristinehe he hetype ugraph newargs 
1311     =
1312       (* {{{ body *)
1313       function
1314         | [] -> newargs,subst,metasenv,he,hetype,ugraph
1315         | (hete, hety)::tl ->
1316             match (CicReduction.whd ~subst context hetype) with 
1317             | Cic.Prod (n,s,t) ->
1318                 let arg,subst,metasenv,ugraph =
1319                   coerce_to_something allow_coercions localization_tbl 
1320                     hete hety s subst metasenv context ugraph in
1321                 eat_prods_and_args 
1322                   pristinemenv metasenv subst context pristinehe he
1323                   (CicSubstitution.subst (fst arg) t) 
1324                   ugraph (newargs@[arg]) tl
1325             | _ -> 
1326                 try
1327                   let subst,metasenv,ugraph1,hetype',he,args_bo_and_ty =
1328                     fix_arity 
1329                       pristinemenv context subst he hetype 
1330                        (newargs@[hete,hety]@tl) ugraph
1331                   in
1332                   eat_prods_and_args metasenv
1333                     metasenv subst context pristinehe he hetype' 
1334                     ugraph [] args_bo_and_ty
1335                 with RefineFailure _ | Uncertain _ as exn ->
1336                   (* unable to fix arity *)
1337                    more_args_than_expected localization_tbl metasenv
1338                      subst he context hetype args_bo_and_ty exn
1339       (* }}} *)
1340     in
1341     (* first we check if we are in the simple case of a meta closed term *)
1342     let subst,metasenv,ugraph1,hetype',he,args_bo_and_ty =
1343      if CicUtil.is_meta_closed (CicMetaSubst.apply_subst subst hetype) then
1344       (* this optimization is to postpone fix_arity (the most common case)*)
1345       subst,metasenv,ugraph,hetype,he,args_bo_and_ty
1346      else
1347        (* this (says CSC) is also useful to infer dependent types *)
1348        try
1349         fix_arity metasenv context subst he hetype args_bo_and_ty ugraph
1350        with RefineFailure _ | Uncertain _ as exn ->
1351          (* unable to fix arity *)
1352           more_args_than_expected localization_tbl metasenv
1353             subst he context hetype args_bo_and_ty exn
1354     in
1355     let coerced_args,subst,metasenv,he,t,ugraph =
1356       eat_prods_and_args 
1357         metasenv metasenv subst context he he hetype' ugraph1 [] args_bo_and_ty
1358     in
1359     he,(List.map fst coerced_args),t,subst,metasenv,ugraph
1360
1361   and coerce_to_something 
1362     allow_coercions localization_tbl t infty expty subst metasenv context ugraph
1363   =
1364     let module CS = CicSubstitution in
1365     let module CR = CicReduction in
1366     let cs_subst = CS.subst ~avoid_beta_redexes:true in
1367     let coerce_atom_to_something t infty expty subst metasenv context ugraph =
1368       let coer = 
1369         CoercGraph.look_for_coercion metasenv subst context infty expty
1370       in
1371       match coer with
1372       | CoercGraph.NotMetaClosed -> raise (Uncertain (lazy
1373           "coerce_atom_to_something fails since not meta closed"))
1374       | CoercGraph.NoCoercion 
1375       | CoercGraph.SomeCoercionToTgt _
1376       | CoercGraph.NotHandled _ -> raise (RefineFailure (lazy
1377           "coerce_atom_to_something fails since no coercions found"))
1378       | CoercGraph.SomeCoercion candidates -> 
1379           let uncertain = ref false in
1380           let selected = 
1381 (*             HExtlib.list_findopt *)
1382             let posibilities =
1383               HExtlib.filter_map
1384               (fun (metasenv,last,c) -> 
1385                try
1386                 let subst,metasenv,ugraph =
1387                  fo_unif_subst subst context metasenv last t ugraph in
1388                 let newt,newhety,subst,metasenv,ugraph = 
1389                  type_of_aux subst metasenv context c ugraph in
1390                 let newt, newty, subst, metasenv, ugraph = 
1391                  avoid_double_coercion context subst metasenv ugraph newt expty 
1392                 in
1393                 let subst,metasenv,ugraph = 
1394                   fo_unif_subst subst context metasenv newhety expty ugraph in
1395                  Some ((newt,newty), subst, metasenv, ugraph)
1396                with 
1397                | Uncertain _ -> uncertain := true; None
1398                | RefineFailure _ -> None)
1399               candidates
1400             in
1401             match 
1402               List.fast_sort 
1403                 (fun (_,_,m1,_) (_,_,m2,_) -> List.length m1 - List.length m2) 
1404                 posibilities 
1405             with
1406             | [] -> None
1407             | x::_ -> Some x
1408           in
1409           match selected with
1410           | Some x -> x
1411           | None when !uncertain -> raise (Uncertain (lazy "coerce_atom fails"))
1412           | None -> raise (RefineFailure (lazy "coerce_atom fails"))
1413     in
1414     let rec coerce_to_something_aux 
1415       t infty expty subst metasenv context ugraph 
1416     =
1417       try            
1418         let subst, metasenv, ugraph =
1419           fo_unif_subst subst context metasenv infty expty ugraph
1420         in
1421         (t, expty), subst, metasenv, ugraph
1422       with Uncertain _ | RefineFailure _ as exn ->
1423         if not allow_coercions || not !insert_coercions then
1424           enrich localization_tbl t exn
1425         else
1426           let whd = CicReduction.whd ~delta:false in
1427           let clean t s c = whd c (CicMetaSubst.apply_subst s t) in
1428           let infty = clean infty subst context in
1429           let expty = clean expty subst context in
1430           let t = clean t subst context in
1431           match infty, expty, t with
1432           | Cic.Prod (nameprod,src,ty), Cic.Prod (_,src2,ty2), Cic.Fix (n,fl) ->
1433               debug_print (lazy "FIX");
1434              (match fl with
1435                  [name,i,_(* infty *),bo] ->
1436                    let context_bo =
1437                     Some (Cic.Name name,Cic.Decl expty)::context in
1438                    let (rel1, _), subst, metasenv, ugraph =
1439                     coerce_to_something_aux (Cic.Rel 1) 
1440                       (CS.lift 1 expty) (CS.lift 1 infty) subst
1441                      metasenv context_bo ugraph in
1442                    let bo = cs_subst rel1 (CS.lift_from 2 1 bo) in
1443                    let (bo,_), subst, metasenv, ugraph =
1444                     coerce_to_something_aux bo (CS.lift 1 infty) (CS.lift 1
1445                     expty) subst
1446                      metasenv context_bo ugraph
1447                    in
1448                     (Cic.Fix (n,[name,i,expty,bo]),expty),subst,metasenv,ugraph
1449                | _ -> assert false (* not implemented yet *))
1450           | _,_, Cic.MutCase (uri,tyno,outty,m,pl) ->
1451               debug_print (lazy "CASE");
1452               (* {{{ helper functions *)
1453               let get_cl_and_left_p uri tyno outty ugraph =
1454                 match CicEnvironment.get_obj ugraph uri with
1455                 | Cic.InductiveDefinition (tl, _, leftno, _),ugraph ->
1456                     let count_pis t =
1457                       let rec aux ctx t = 
1458                         match CicReduction.whd ~delta:false ctx t with
1459                         | Cic.Prod (name,src,tgt) ->
1460                             let ctx = Some (name, Cic.Decl src) :: ctx in
1461                             1 + aux ctx tgt
1462                         | _ -> 0
1463                       in
1464                         aux [] t
1465                     in
1466                     let rec skip_lambda_delifting t n =
1467                       match t,n with
1468                       | _,0 -> t
1469                       | Cic.Lambda (_,_,t),n -> 
1470                           skip_lambda_delifting
1471                             (CS.subst (Cic.Implicit None) t) (n - 1)
1472                       | _ -> assert false
1473                     in
1474                     let get_l_r_p n = function
1475                       | Cic.Lambda (_,Cic.MutInd _,_) -> [],[]
1476                       | Cic.Lambda (_,Cic.Appl (Cic.MutInd _ :: args),_) ->
1477                           HExtlib.split_nth n args
1478                       | _ -> assert false
1479                     in
1480                     let _, _, ty, cl = List.nth tl tyno in
1481                     let pis = count_pis ty in
1482                     let rno = pis - leftno in
1483                     let t = skip_lambda_delifting outty rno in
1484                     let left_p, _ = get_l_r_p leftno t in
1485                     let instantiale_with_left cl =
1486                       List.map 
1487                         (fun ty -> 
1488                           List.fold_left 
1489                             (fun t p -> match t with
1490                               | Cic.Prod (_,_,t) ->
1491                                   cs_subst p t
1492                               | _-> assert false)
1493                             ty left_p) 
1494                         cl 
1495                     in
1496                     let cl = instantiale_with_left (List.map snd cl) in
1497                     cl, left_p, leftno, rno, ugraph
1498                 | _ -> raise exn
1499               in
1500               let rec keep_lambdas_and_put_expty ctx t bo right_p matched n =
1501                 match t,n with
1502                 | _,0 ->
1503                   let rec mkr n = function 
1504                     | [] -> [] | _::tl -> Cic.Rel n :: mkr (n+1) tl
1505                   in
1506                   let bo =
1507                   CicReplace.replace_lifting
1508                     ~equality:(fun _ -> CicUtil.alpha_equivalence)
1509                     ~context:ctx
1510                     ~what:(matched::right_p)
1511                     ~with_what:(Cic.Rel 1::List.rev (mkr 2 right_p))
1512                     ~where:bo
1513                   in
1514                   bo
1515                 | Cic.Lambda (name, src, tgt),_ ->
1516                     Cic.Lambda (name, src,
1517                       keep_lambdas_and_put_expty 
1518                        (Some (name, Cic.Decl src)::ctx) tgt (CS.lift 1 bo)
1519                        (List.map (CS.lift 1) right_p) (CS.lift 1 matched) (n-1))
1520                 | _ -> assert false
1521               in
1522               let eq_uri, eq, eq_refl = 
1523                 match LibraryObjects.eq_URI () with 
1524                 | None -> HLog.warn "no default equality"; raise exn
1525                 | Some u -> u, Cic.MutInd(u,0,[]), Cic.MutConstruct (u,0,1,[])
1526               in
1527               let add_params 
1528                 metasenv subst context uri tyno cty outty mty m leftno i 
1529               =
1530                 let rec aux context outty par k mty m = function
1531                   | Cic.Prod (name, src, tgt) ->
1532                       let t,k = 
1533                         aux 
1534                           (Some (name, Cic.Decl src) :: context)
1535                           (CS.lift 1 outty) (Cic.Rel k::par) (k+1) 
1536                           (CS.lift 1 mty) (CS.lift 1 m) tgt
1537                       in
1538                       Cic.Prod (name, src, t), k
1539                   | Cic.MutInd _ ->
1540                       let k = 
1541                         let k = Cic.MutConstruct (uri,tyno,i,[]) in
1542                         if par <> [] then Cic.Appl (k::par) else k
1543                       in
1544                       Cic.Prod (Cic.Name "p", 
1545                        Cic.Appl [eq; mty; m; k],
1546                        (CS.lift 1
1547                         (CR.head_beta_reduce ~delta:false 
1548                          (Cic.Appl [outty;k])))),k
1549                   | Cic.Appl (Cic.MutInd _::pl) ->
1550                       let left_p,right_p = HExtlib.split_nth leftno pl in
1551                       let has_rights = right_p <> [] in
1552                       let k = 
1553                         let k = Cic.MutConstruct (uri,tyno,i,[]) in
1554                         Cic.Appl (k::left_p@par)
1555                       in
1556                       let right_p = 
1557                         try match 
1558                           CicTypeChecker.type_of_aux' ~subst metasenv context k
1559                             CicUniv.oblivion_ugraph 
1560                         with
1561                         | Cic.Appl (Cic.MutInd _::args),_ ->
1562                             snd (HExtlib.split_nth leftno args)
1563                         | _ -> assert false
1564                         with CicTypeChecker.TypeCheckerFailure _ -> assert false
1565                       in
1566                       if has_rights then
1567                         CR.head_beta_reduce ~delta:false 
1568                           (Cic.Appl (outty ::right_p @ [k])),k
1569                       else
1570                         Cic.Prod (Cic.Name "p", 
1571                          Cic.Appl [eq; mty; m; k],
1572                          (CS.lift 1
1573                           (CR.head_beta_reduce ~delta:false 
1574                            (Cic.Appl (outty ::right_p @ [k]))))),k
1575                   | _ -> assert false
1576                 in
1577                   aux context outty [] 1 mty m cty
1578               in
1579               let add_lambda_for_refl_m pbo rno mty m k cty =
1580                 (* k lives in the right context *)
1581                 if rno <> 0 then pbo else
1582                 let rec aux mty m = function 
1583                   | Cic.Lambda (name,src,bo), Cic.Prod (_,_,ty) ->
1584                      Cic.Lambda (name,src,
1585                       (aux (CS.lift 1 mty) (CS.lift 1 m) (bo,ty)))
1586                   | t,_ -> 
1587                       Cic.Lambda (Cic.Name "p",
1588                         Cic.Appl [eq; mty; m; k],CS.lift 1 t)
1589                 in
1590                 aux mty m (pbo,cty)
1591               in
1592               let add_pi_for_refl_m new_outty mty m rno =
1593                 if rno <> 0 then new_outty else
1594                   let rec aux m mty = function
1595                     | Cic.Lambda (name, src, tgt) ->
1596                         Cic.Lambda (name, src, 
1597                           aux (CS.lift 1 m) (CS.lift 1 mty) tgt)
1598                     | t ->
1599                         Cic.Prod 
1600                           (Cic.Anonymous, Cic.Appl [eq;mty;m;Cic.Rel 1],
1601                           CS.lift 1 t)
1602                   in
1603                     aux m mty new_outty
1604               in (* }}} end helper functions *)
1605               (* constructors types with left params already instantiated *)
1606               let outty = CicMetaSubst.apply_subst subst outty in
1607               let cl, left_p, leftno,rno,ugraph = 
1608                 get_cl_and_left_p uri tyno outty ugraph 
1609               in
1610               let right_p, mty = 
1611                 try
1612                   match 
1613                     CicTypeChecker.type_of_aux' ~subst metasenv context m
1614                       CicUniv.oblivion_ugraph 
1615                   with
1616                   | Cic.MutInd _ as mty,_ -> [], mty
1617                   | Cic.Appl (Cic.MutInd _::args) as mty,_ ->
1618                       snd (HExtlib.split_nth leftno args), mty
1619                   | _ -> assert false
1620                 with CicTypeChecker.TypeCheckerFailure _ -> assert false
1621               in
1622               let new_outty =
1623                 keep_lambdas_and_put_expty context outty expty right_p m (rno+1)
1624               in
1625               debug_print 
1626                 (lazy ("CASE: new_outty: " ^ CicMetaSubst.ppterm_in_context 
1627                  ~metasenv subst new_outty context));
1628               let _,pl,subst,metasenv,ugraph = 
1629                 List.fold_right2
1630                   (fun cty pbo (i, acc, s, menv, ugraph) -> 
1631                     (* Pi k_par, (Pi H:m=(K_i left_par k_par)), 
1632                      *   (new_)outty right_par (K_i left_par k_par) *)
1633                      let infty_pbo, _ = 
1634                        add_params menv s context uri tyno 
1635                          cty outty mty m leftno i in
1636                      debug_print 
1637                        (lazy ("CASE: infty_pbo: "^CicMetaSubst.ppterm_in_context
1638                        ~metasenv subst infty_pbo context));
1639                      let expty_pbo, k = (* k is (K_i left_par k_par) *)
1640                        add_params menv s context uri tyno 
1641                          cty new_outty mty m leftno i in
1642                      debug_print 
1643                        (lazy ("CASE: expty_pbo: "^CicMetaSubst.ppterm_in_context
1644                        ~metasenv subst expty_pbo context));
1645                      let pbo = add_lambda_for_refl_m pbo rno mty m k cty in
1646                      debug_print 
1647                        (lazy ("CASE: pbo: " ^ CicMetaSubst.ppterm_in_context 
1648                        ~metasenv subst pbo context));
1649                      let (pbo, _), subst, metasenv, ugraph =
1650                        coerce_to_something_aux pbo infty_pbo expty_pbo 
1651                          s menv context ugraph
1652                      in
1653                      debug_print 
1654                        (lazy ("CASE: pbo: " ^ CicMetaSubst.ppterm_in_context 
1655                        ~metasenv subst pbo context));
1656                      (i-1, pbo::acc, subst, metasenv, ugraph))
1657                   cl pl (List.length pl, [], subst, metasenv, ugraph)
1658               in
1659               let new_outty = add_pi_for_refl_m new_outty mty m rno in
1660               debug_print 
1661                 (lazy ("CASE: new_outty: " ^ CicMetaSubst.ppterm_in_context 
1662                  ~metasenv subst new_outty context));
1663               let t = 
1664                 if rno = 0 then
1665                   let refl_m=Cic.Appl[eq_refl;mty;m]in
1666                   Cic.Appl [Cic.MutCase(uri,tyno,new_outty,m,pl);refl_m] 
1667                 else 
1668                   Cic.MutCase(uri,tyno,new_outty,m,pl)
1669               in
1670               (t, expty), subst, metasenv, ugraph
1671           | Cic.Prod (nameprod, src, ty),Cic.Prod (_, src2, ty2), _ -> 
1672               debug_print (lazy "LAM");
1673               let name_con = 
1674                 FreshNamesGenerator.mk_fresh_name 
1675                   ~subst metasenv context ~typ:src2 Cic.Anonymous
1676               in
1677               let context_src2 = (Some (name_con, Cic.Decl src2) :: context) in
1678               (* contravariant part: the argument of f:src->ty *)
1679               let (rel1, _), subst, metasenv, ugraph = 
1680                 coerce_to_something_aux
1681                  (Cic.Rel 1) (CS.lift 1 src2) 
1682                  (CS.lift 1 src) subst metasenv context_src2 ugraph
1683               in
1684               (* covariant part: the result of f(c x); x:src2; (c x):src *)
1685               let name_t, bo = 
1686                 match t with
1687                 | Cic.Lambda (n,_,bo) -> n, cs_subst rel1 (CS.lift_from 2 1 bo)
1688                 | _ -> name_con, Cic.Appl[CS.lift 1 t;rel1]
1689               in
1690               (* we fix the possible dependency problem in the source ty *)
1691               let ty = cs_subst rel1 (CS.lift_from 2 1 ty) in
1692               let (bo, _), subst, metasenv, ugraph = 
1693                 coerce_to_something_aux
1694                   bo ty ty2 subst metasenv context_src2 ugraph
1695               in
1696               let coerced = Cic.Lambda (name_t,src2, bo) in
1697               debug_print (lazy ("coerced: "^ CicMetaSubst.ppterm_in_context 
1698                 ~metasenv subst coerced context));
1699               (coerced, expty), subst, metasenv, ugraph
1700           | _ -> 
1701               debug_print (lazy "ATOM");
1702             coerce_atom_to_something t infty expty subst metasenv context ugraph
1703     in
1704     try
1705       coerce_to_something_aux t infty expty subst metasenv context ugraph
1706     with Uncertain _ | RefineFailure _ as exn ->
1707       let f _ =
1708         lazy ("The term " ^
1709           CicMetaSubst.ppterm_in_context metasenv subst t context ^ 
1710           " has type " ^ CicMetaSubst.ppterm_in_context metasenv subst
1711           infty context ^ " but is here used with type " ^ 
1712           CicMetaSubst.ppterm_in_context metasenv subst expty context)
1713       in
1714         enrich localization_tbl ~f t exn
1715
1716   and coerce_to_sort localization_tbl t infty subst context metasenv uragph =
1717     match CicReduction.whd ~subst:subst context infty with
1718     | Cic.Meta _ | Cic.Sort _ -> 
1719         t,infty, subst, metasenv, ugraph
1720     | src ->
1721        let tgt = Cic.Sort (Cic.Type (CicUniv.fresh())) in
1722        try
1723          let (t, ty_t), subst, metasenv, ugraph =
1724            coerce_to_something true
1725              localization_tbl t src tgt subst metasenv context ugraph
1726          in
1727          t, ty_t, subst, metasenv, ugraph
1728        with HExtlib.Localized (_, exn) -> 
1729          let f _ = 
1730            lazy ("(7)The term " ^ 
1731             CicMetaSubst.ppterm_in_context ~metasenv subst t context 
1732             ^ " is not a type since it has type " ^ 
1733             CicMetaSubst.ppterm_in_context ~metasenv subst src context
1734             ^ " that is not a sort")
1735          in
1736            enrich localization_tbl ~f t exn
1737   in
1738   
1739   (* eat prods ends here! *)
1740   
1741   let t',ty,subst',metasenv',ugraph1 =
1742    type_of_aux [] metasenv context t ugraph
1743   in
1744   let substituted_t = CicMetaSubst.apply_subst subst' t' in
1745   let substituted_ty = CicMetaSubst.apply_subst subst' ty in
1746     (* Andrea: ho rimesso qui l'applicazione della subst al
1747        metasenv dopo che ho droppato l'invariante che il metsaenv
1748        e' sempre istanziato *)
1749   let substituted_metasenv = 
1750     CicMetaSubst.apply_subst_metasenv subst' metasenv' in
1751     (* metasenv' *)
1752     (*  substituted_t,substituted_ty,substituted_metasenv *)
1753     (* ANDREA: spostare tutta questa robaccia da un altra parte *)
1754   let cleaned_t =
1755     FreshNamesGenerator.clean_dummy_dependent_types substituted_t in
1756   let cleaned_ty =
1757     FreshNamesGenerator.clean_dummy_dependent_types substituted_ty in
1758   let cleaned_metasenv =
1759     List.map
1760       (function (n,context,ty) ->
1761          let ty' = FreshNamesGenerator.clean_dummy_dependent_types ty in
1762          let context' =
1763            List.map
1764              (function
1765                   None -> None
1766                 | Some (n, Cic.Decl t) ->
1767                     Some (n,
1768                           Cic.Decl (FreshNamesGenerator.clean_dummy_dependent_types t))
1769                 | Some (n, Cic.Def (bo,ty)) ->
1770                     let bo' = FreshNamesGenerator.clean_dummy_dependent_types bo in
1771                     let ty' =
1772                       match ty with
1773                           None -> None
1774                         | Some ty ->
1775                             Some (FreshNamesGenerator.clean_dummy_dependent_types ty)
1776                     in
1777                       Some (n, Cic.Def (bo',ty'))
1778              ) context
1779          in
1780            (n,context',ty')
1781       ) substituted_metasenv
1782   in
1783     (cleaned_t,cleaned_ty,cleaned_metasenv,ugraph1) 
1784 ;;
1785
1786 let undebrujin uri typesno tys t =
1787   snd
1788    (List.fold_right
1789      (fun (name,_,_,_) (i,t) ->
1790        (* here the explicit_named_substituion is assumed to be *)
1791        (* of length 0 *)
1792        let t' = Cic.MutInd (uri,i,[])  in
1793        let t = CicSubstitution.subst t' t in
1794         i - 1,t
1795      ) tys (typesno - 1,t)) 
1796
1797 let map_first_n n start f g l = 
1798   let rec aux acc k l =
1799     if k < n then
1800       match l with
1801       | [] -> raise (Invalid_argument "map_first_n")
1802       | hd :: tl -> f hd k (aux acc (k+1) tl)
1803     else
1804       g acc l
1805   in
1806   aux start 0 l
1807    
1808 (*CSC: this is a very rough approximation; to be finished *)
1809 let are_all_occurrences_positive metasenv ugraph uri tys leftno =
1810   let subst,metasenv,ugraph,tys = 
1811     List.fold_right
1812       (fun (name,ind,arity,cl) (subst,metasenv,ugraph,acc) ->
1813         let subst,metasenv,ugraph,cl = 
1814           List.fold_right
1815             (fun (name,ty) (subst,metasenv,ugraph,acc) ->
1816                let rec aux ctx k subst = function
1817                  | Cic.Appl((Cic.MutInd (uri',_,_)as hd)::tl) when uri = uri'->
1818                      let subst,metasenv,ugraph,tl = 
1819                        map_first_n leftno 
1820                          (subst,metasenv,ugraph,[]) 
1821                          (fun t n (subst,metasenv,ugraph,acc) ->
1822                            let subst,metasenv,ugraph = 
1823                              fo_unif_subst 
1824                                subst ctx metasenv t (Cic.Rel (k-n)) ugraph 
1825                            in
1826                            subst,metasenv,ugraph,(t::acc)) 
1827                          (fun (s,m,g,acc) tl -> assert(acc=[]);(s,m,g,tl)) 
1828                          tl
1829                      in
1830                      subst,metasenv,ugraph,(Cic.Appl (hd::tl))
1831                  | Cic.MutInd(uri',_,_) as t when uri = uri'->
1832                      subst,metasenv,ugraph,t 
1833                  | Cic.Prod (name,s,t) -> 
1834                      let ctx = (Some (name,Cic.Decl s))::ctx in 
1835                      let subst,metasenv,ugraph,t = aux ctx (k+1) subst t in
1836                      subst,metasenv,ugraph,Cic.Prod (name,s,t)
1837                  | _ -> 
1838                      raise 
1839                       (RefineFailure 
1840                         (lazy "not well formed constructor type"))
1841                in
1842                let subst,metasenv,ugraph,ty = aux [] 0 subst ty in  
1843                subst,metasenv,ugraph,(name,ty) :: acc)
1844           cl (subst,metasenv,ugraph,[])
1845         in 
1846         subst,metasenv,ugraph,(name,ind,arity,cl)::acc)
1847       tys ([],metasenv,ugraph,[])
1848   in
1849   let substituted_tys = 
1850     List.map 
1851       (fun (name,ind,arity,cl) -> 
1852         let cl = 
1853           List.map (fun (name, ty) -> name,CicMetaSubst.apply_subst subst ty) cl
1854         in
1855         name,ind,CicMetaSubst.apply_subst subst arity,cl)
1856       tys 
1857   in
1858   metasenv,ugraph,substituted_tys
1859     
1860 let typecheck metasenv uri obj ~localization_tbl =
1861  let ugraph = CicUniv.empty_ugraph in
1862  match obj with
1863     Cic.Constant (name,Some bo,ty,args,attrs) ->
1864      let bo',boty,metasenv,ugraph =
1865       type_of_aux' ~localization_tbl metasenv [] bo ugraph in
1866      let ty',_,metasenv,ugraph =
1867       type_of_aux' ~localization_tbl metasenv [] ty ugraph in
1868      let subst,metasenv,ugraph = fo_unif_subst [] [] metasenv boty ty' ugraph in
1869      let bo' = CicMetaSubst.apply_subst subst bo' in
1870      let ty' = CicMetaSubst.apply_subst subst ty' in
1871      let metasenv = CicMetaSubst.apply_subst_metasenv subst metasenv in
1872       Cic.Constant (name,Some bo',ty',args,attrs),metasenv,ugraph
1873   | Cic.Constant (name,None,ty,args,attrs) ->
1874      let ty',_,metasenv,ugraph =
1875       type_of_aux' ~localization_tbl metasenv [] ty ugraph
1876      in
1877       Cic.Constant (name,None,ty',args,attrs),metasenv,ugraph
1878   | Cic.CurrentProof (name,metasenv',bo,ty,args,attrs) ->
1879      assert (metasenv' = metasenv);
1880      (* Here we do not check the metasenv for correctness *)
1881      let bo',boty,metasenv,ugraph =
1882       type_of_aux' ~localization_tbl metasenv [] bo ugraph in
1883      let ty',sort,metasenv,ugraph =
1884       type_of_aux' ~localization_tbl metasenv [] ty ugraph in
1885      begin
1886       match sort with
1887          Cic.Sort _
1888        (* instead of raising Uncertain, let's hope that the meta will become
1889           a sort *)
1890        | Cic.Meta _ -> ()
1891        | _ -> raise (RefineFailure (lazy "The term provided is not a type"))
1892      end;
1893      let subst,metasenv,ugraph = fo_unif_subst [] [] metasenv boty ty' ugraph in
1894      let bo' = CicMetaSubst.apply_subst subst bo' in
1895      let ty' = CicMetaSubst.apply_subst subst ty' in
1896      let metasenv = CicMetaSubst.apply_subst_metasenv subst metasenv in
1897       Cic.CurrentProof (name,metasenv,bo',ty',args,attrs),metasenv,ugraph
1898   | Cic.Variable _ -> assert false (* not implemented *)
1899   | Cic.InductiveDefinition (tys,args,paramsno,attrs) ->
1900      (*CSC: this code is greately simplified and many many checks are missing *)
1901      (*CSC: e.g. the constructors are not required to build their own types,  *)
1902      (*CSC: the arities are not required to have as type a sort, etc.         *)
1903      let uri = match uri with Some uri -> uri | None -> assert false in
1904      let typesno = List.length tys in
1905      (* first phase: we fix only the types *)
1906      let metasenv,ugraph,tys =
1907       List.fold_right
1908        (fun (name,b,ty,cl) (metasenv,ugraph,res) ->
1909          let ty',_,metasenv,ugraph =
1910           type_of_aux' ~localization_tbl metasenv [] ty ugraph
1911          in
1912           metasenv,ugraph,(name,b,ty',cl)::res
1913        ) tys (metasenv,ugraph,[]) in
1914      let con_context =
1915       List.rev_map (fun (name,_,ty,_)-> Some (Cic.Name name,Cic.Decl ty)) tys in
1916      (* second phase: we fix only the constructors *)
1917      let saved_menv = metasenv in
1918      let metasenv,ugraph,tys =
1919       List.fold_right
1920        (fun (name,b,ty,cl) (metasenv,ugraph,res) ->
1921          let metasenv,ugraph,cl' =
1922           List.fold_right
1923            (fun (name,ty) (metasenv,ugraph,res) ->
1924              let ty =
1925               CicTypeChecker.debrujin_constructor
1926                ~cb:(relocalize localization_tbl) uri typesno ty in
1927              let ty',_,metasenv,ugraph =
1928               type_of_aux' ~localization_tbl metasenv con_context ty ugraph in
1929              let ty' = undebrujin uri typesno tys ty' in
1930               metasenv@saved_menv,ugraph,(name,ty')::res
1931            ) cl (metasenv,ugraph,[])
1932          in
1933           metasenv,ugraph,(name,b,ty,cl')::res
1934        ) tys (metasenv,ugraph,[]) in
1935      (* third phase: we check the positivity condition *)
1936      let metasenv,ugraph,tys = 
1937        are_all_occurrences_positive metasenv ugraph uri tys paramsno 
1938      in
1939      Cic.InductiveDefinition (tys,args,paramsno,attrs),metasenv,ugraph
1940 ;;
1941
1942 (* sara' piu' veloce che raffinare da zero? mah.... *)
1943 let pack_coercion metasenv ctx t =
1944  let module C = Cic in
1945  let rec merge_coercions ctx =
1946    let aux = (fun (u,t) -> u,merge_coercions ctx t) in
1947    function
1948    | C.Rel _ | C.Sort _ | C.Implicit _ as t -> t
1949    | C.Meta (n,subst) ->
1950       let subst' =
1951        List.map
1952         (function None -> None | Some t -> Some (merge_coercions ctx t)) subst
1953       in
1954        C.Meta (n,subst')
1955    | C.Cast (te,ty) -> C.Cast (merge_coercions ctx te, merge_coercions ctx ty)
1956    | C.Prod (name,so,dest) -> 
1957        let ctx' = (Some (name,C.Decl so))::ctx in
1958        C.Prod (name, merge_coercions ctx so, merge_coercions ctx' dest) 
1959    | C.Lambda (name,so,dest) -> 
1960        let ctx' = (Some (name,C.Decl so))::ctx in
1961        C.Lambda (name, merge_coercions ctx so, merge_coercions ctx' dest)
1962    | C.LetIn (name,so,dest) -> 
1963        let _,ty,metasenv,ugraph =
1964         pack_coercions := false;
1965         type_of_aux' metasenv ctx so CicUniv.oblivion_ugraph in
1966         pack_coercions := true;
1967        let ctx' = Some (name,(C.Def (so,Some ty)))::ctx in
1968        C.LetIn (name, merge_coercions ctx so, merge_coercions ctx' dest)
1969    | C.Appl l -> 
1970       let l = List.map (merge_coercions ctx) l in
1971       let t = C.Appl l in
1972        let b,_,_,_,_ = is_a_double_coercion t in
1973        if b then
1974          let ugraph = CicUniv.oblivion_ugraph in
1975          let old_insert_coercions = !insert_coercions in
1976          insert_coercions := false;
1977          let newt, _, menv, _ = 
1978            try 
1979              type_of_aux' metasenv ctx t ugraph 
1980            with RefineFailure _ | Uncertain _ -> 
1981              t, t, [], ugraph 
1982          in
1983          insert_coercions := old_insert_coercions;
1984          if metasenv <> [] || menv = [] then 
1985            newt 
1986          else 
1987            (prerr_endline "PUO' SUCCEDERE!!!!!";t)
1988        else
1989          t
1990    | C.Var (uri,exp_named_subst) -> 
1991        let exp_named_subst = List.map aux exp_named_subst in
1992        C.Var (uri, exp_named_subst)
1993    | C.Const (uri,exp_named_subst) ->
1994        let exp_named_subst = List.map aux exp_named_subst in
1995        C.Const (uri, exp_named_subst)
1996    | C.MutInd (uri,tyno,exp_named_subst) ->
1997        let exp_named_subst = List.map aux exp_named_subst in
1998        C.MutInd (uri,tyno,exp_named_subst)
1999    | C.MutConstruct (uri,tyno,consno,exp_named_subst) ->
2000        let exp_named_subst = List.map aux exp_named_subst in
2001        C.MutConstruct (uri,tyno,consno,exp_named_subst)  
2002    | C.MutCase (uri,tyno,out,te,pl) ->
2003        let pl = List.map (merge_coercions ctx) pl in
2004        C.MutCase (uri,tyno,merge_coercions ctx out, merge_coercions ctx te, pl)
2005    | C.Fix (fno, fl) ->
2006        let ctx' =
2007          List.fold_left
2008            (fun l (n,_,ty,_) -> (Some (C.Name n,C.Decl ty))::l) 
2009            ctx fl
2010        in 
2011        let fl = 
2012          List.map 
2013            (fun (name,idx,ty,bo) -> 
2014              (name,idx,merge_coercions ctx ty,merge_coercions ctx' bo)) 
2015          fl
2016        in
2017        C.Fix (fno, fl)
2018    | C.CoFix (fno, fl) ->
2019        let ctx' =
2020          List.fold_left
2021            (fun l (n,ty,_) -> (Some (C.Name n,C.Decl ty))::l) 
2022            ctx fl
2023        in 
2024        let fl = 
2025          List.map 
2026            (fun (name,ty,bo) -> 
2027              (name, merge_coercions ctx ty, merge_coercions ctx' bo)) 
2028          fl 
2029        in
2030        C.CoFix (fno, fl)
2031  in
2032   merge_coercions ctx t
2033 ;;
2034
2035 let pack_coercion_metasenv conjectures =
2036   let module C = Cic in
2037   List.map 
2038     (fun (i, ctx, ty) -> 
2039        let ctx = 
2040          List.fold_right 
2041            (fun item ctx ->
2042               let item' =
2043                 match item with
2044                     Some (name, C.Decl t) -> 
2045                       Some (name, C.Decl (pack_coercion conjectures ctx t))
2046                   | Some (name, C.Def (t,None)) -> 
2047                       Some (name,C.Def (pack_coercion conjectures ctx t,None))
2048                   | Some (name, C.Def (t,Some ty)) -> 
2049                       Some (name, C.Def (pack_coercion conjectures ctx t, 
2050                                          Some (pack_coercion conjectures ctx ty)))
2051                   | None -> None
2052               in
2053                 item'::ctx
2054            ) ctx []
2055        in
2056          ((i,ctx,pack_coercion conjectures ctx ty))
2057     ) conjectures
2058 ;;
2059
2060 let pack_coercion_obj obj =
2061   let module C = Cic in
2062   match obj with
2063   | C.Constant (id, body, ty, params, attrs) -> 
2064       let body = 
2065         match body with 
2066         | None -> None 
2067         | Some body -> Some (pack_coercion [] [] body) 
2068       in
2069       let ty = pack_coercion [] [] ty in
2070         C.Constant (id, body, ty, params, attrs)
2071   | C.Variable (name, body, ty, params, attrs) ->
2072       let body = 
2073         match body with 
2074         | None -> None 
2075         | Some body -> Some (pack_coercion [] [] body) 
2076       in
2077       let ty = pack_coercion [] [] ty in
2078         C.Variable (name, body, ty, params, attrs)
2079   | C.CurrentProof (name, conjectures, body, ty, params, attrs) ->
2080       let conjectures = pack_coercion_metasenv conjectures in
2081       let body = pack_coercion conjectures [] body in
2082       let ty = pack_coercion conjectures [] ty in
2083       C.CurrentProof (name, conjectures, body, ty, params, attrs)
2084   | C.InductiveDefinition (indtys, params, leftno, attrs) ->
2085       let indtys = 
2086         List.map 
2087           (fun (name, ind, arity, cl) -> 
2088             let arity = pack_coercion [] [] arity in
2089             let cl = 
2090               List.map (fun (name, ty) -> (name,pack_coercion [] [] ty)) cl 
2091             in
2092             (name, ind, arity, cl))
2093           indtys
2094       in
2095         C.InductiveDefinition (indtys, params, leftno, attrs)
2096 ;;
2097
2098
2099 (* DEBUGGING ONLY 
2100 let type_of_aux' metasenv context term =
2101  try
2102   let (t,ty,m) = 
2103       type_of_aux' metasenv context term in
2104     debug_print (lazy
2105      ("@@@ REFINE SUCCESSFUL: " ^ CicPp.ppterm t ^ " : " ^ CicPp.ppterm ty));
2106    debug_print (lazy
2107     ("@@@ REFINE SUCCESSFUL (metasenv):\n" ^ CicMetaSubst.ppmetasenv ~sep:";" m []));
2108    (t,ty,m)
2109  with
2110  | RefineFailure msg as e ->
2111      debug_print (lazy ("@@@ REFINE FAILED: " ^ msg));
2112      raise e
2113  | Uncertain msg as e ->
2114      debug_print (lazy ("@@@ REFINE UNCERTAIN: " ^ msg));
2115      raise e
2116 ;; *)
2117
2118 let profiler2 = HExtlib.profile "CicRefine"
2119
2120 let type_of_aux' ?localization_tbl metasenv context term ugraph =
2121  profiler2.HExtlib.profile
2122   (type_of_aux' ?localization_tbl metasenv context term) ugraph
2123
2124 let typecheck ~localization_tbl metasenv uri obj =
2125  profiler2.HExtlib.profile (typecheck ~localization_tbl metasenv uri) obj
2126
2127 let _ = DoubleTypeInference.pack_coercion := pack_coercion;;
2128 (* vim:set foldmethod=marker: *)