]> matita.cs.unibo.it Git - helm.git/blob - helm/ocaml/cic_unification/cicMetaSubst.ml
New handling of substitution:
[helm.git] / helm / ocaml / cic_unification / cicMetaSubst.ml
1 (* Copyright (C) 2004, 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 open Printf
27
28 let apply_subst_counter = ref 0
29 let apply_subst_context_counter = ref 0
30 let apply_subst_metasenv_counter = ref 0
31 let lift_counter = ref 0
32 let subst_counter = ref 0
33 let whd_counter = ref 0
34 let are_convertible_counter = ref 0
35 let metasenv_length = ref 0
36 let context_length = ref 0
37
38 let reset_counters () =
39  apply_subst_counter := 0;
40  apply_subst_context_counter := 0;
41  apply_subst_metasenv_counter := 0;
42  lift_counter := 0;
43  subst_counter := 0;
44  whd_counter := 0;
45  are_convertible_counter := 0;
46  metasenv_length := 0;
47  context_length := 0
48
49 let print_counters () =
50   prerr_endline (Printf.sprintf
51 "apply_subst: %d
52 apply_subst_context: %d
53 apply_subst_metasenv: %d
54 lift: %d
55 subst: %d
56 whd: %d
57 are_convertible: %d
58 metasenv length: %d (avg = %.2f)
59 context length: %d (avg = %.2f)
60 "
61   !apply_subst_counter !apply_subst_context_counter
62   !apply_subst_metasenv_counter !lift_counter !subst_counter !whd_counter
63   !are_convertible_counter !metasenv_length
64   ((float !metasenv_length) /. (float !apply_subst_metasenv_counter))
65   !context_length
66   ((float !context_length) /. (float !apply_subst_context_counter))
67   )
68
69 exception MetaSubstFailure of string
70 exception Uncertain of string
71 exception AssertFailure of string
72 exception SubstNotFound of int
73
74 let debug_print = prerr_endline
75
76 type substitution = (int * (Cic.context * Cic.term)) list
77
78 let lookup_subst n subst =
79   try
80     List.assoc n subst
81   with Not_found -> raise (SubstNotFound n)
82
83 (*** Functions to apply a substitution ***)
84
85 let apply_subst_gen ~appl_fun subst term =
86  let rec um_aux =
87   let module C = Cic in
88   let module S = CicSubstitution in 
89    function
90       C.Rel _ as t -> t
91     | C.Var (uri,exp_named_subst) ->
92        let exp_named_subst' =
93          List.map (fun (uri, t) -> (uri, um_aux t)) exp_named_subst
94        in
95        C.Var (uri, exp_named_subst')
96     | C.Meta (i, l) -> 
97         (try
98           let (context, t) = lookup_subst i subst in
99           um_aux (S.lift_meta l t)
100         with SubstNotFound _ -> (* unconstrained variable, i.e. free in subst*)
101           let l' =
102             List.map (function None -> None | Some t -> Some (um_aux t)) l
103           in
104            C.Meta (i,l'))
105     | C.Sort _ as t -> t
106     | C.Implicit _ -> assert false
107     | C.Cast (te,ty) -> C.Cast (um_aux te, um_aux ty)
108     | C.Prod (n,s,t) -> C.Prod (n, um_aux s, um_aux t)
109     | C.Lambda (n,s,t) -> C.Lambda (n, um_aux s, um_aux t)
110     | C.LetIn (n,s,t) -> C.LetIn (n, um_aux s, um_aux t)
111     | C.Appl (hd :: tl) -> appl_fun um_aux hd tl
112     | C.Appl _ -> assert false
113     | C.Const (uri,exp_named_subst) ->
114        let exp_named_subst' =
115          List.map (fun (uri, t) -> (uri, um_aux t)) exp_named_subst
116        in
117        C.Const (uri, exp_named_subst')
118     | C.MutInd (uri,typeno,exp_named_subst) ->
119        let exp_named_subst' =
120          List.map (fun (uri, t) -> (uri, um_aux t)) exp_named_subst
121        in
122        C.MutInd (uri,typeno,exp_named_subst')
123     | C.MutConstruct (uri,typeno,consno,exp_named_subst) ->
124        let exp_named_subst' =
125          List.map (fun (uri, t) -> (uri, um_aux t)) exp_named_subst
126        in
127        C.MutConstruct (uri,typeno,consno,exp_named_subst')
128     | C.MutCase (sp,i,outty,t,pl) ->
129        let pl' = List.map um_aux pl in
130        C.MutCase (sp, i, um_aux outty, um_aux t, pl')
131     | C.Fix (i, fl) ->
132        let fl' =
133          List.map (fun (name, i, ty, bo) -> (name, i, um_aux ty, um_aux bo)) fl
134        in
135        C.Fix (i, fl')
136     | C.CoFix (i, fl) ->
137        let fl' =
138          List.map (fun (name, ty, bo) -> (name, um_aux ty, um_aux bo)) fl
139        in
140        C.CoFix (i, fl')
141  in
142  um_aux term
143 ;;
144
145 let apply_subst =
146 (* CSC: old code that never performs beta reduction
147   let appl_fun um_aux he tl =
148     let tl' = List.map um_aux tl in
149       begin
150        match um_aux he with
151           Cic.Appl l -> Cic.Appl (l@tl')
152         | he' -> Cic.Appl (he'::tl')
153       end
154   in
155   apply_subst_gen ~appl_fun
156 *)
157   let appl_fun um_aux he tl =
158     let tl' = List.map um_aux tl in
159     let t' =
160      match um_aux he with
161         Cic.Appl l -> Cic.Appl (l@tl')
162       | he' -> Cic.Appl (he'::tl')
163     in
164      begin
165       match he with
166          Cic.Meta (m,_) ->
167           let rec beta_reduce =
168            function
169               (Cic.Appl (Cic.Lambda (_,_,t)::he'::tl')) ->
170                 let he'' = CicSubstitution.subst he' t in
171                  if tl' = [] then
172                   he''
173                  else
174                   beta_reduce (Cic.Appl(he''::tl'))
175             | t -> t
176           in
177            beta_reduce t'
178        | _ -> t'
179      end
180   in
181   fun s t ->
182     incr apply_subst_counter;
183     apply_subst_gen ~appl_fun s t
184 ;;
185
186 let rec apply_subst_context subst context =
187   incr apply_subst_context_counter;
188   context_length := !context_length + List.length context;
189   List.fold_right
190     (fun item context ->
191       match item with
192       | Some (n, Cic.Decl t) ->
193           let t' = apply_subst subst t in
194           Some (n, Cic.Decl t') :: context
195       | Some (n, Cic.Def (t, ty)) ->
196           let ty' =
197             match ty with
198             | None -> None
199             | Some ty -> Some (apply_subst subst ty)
200           in
201           let t' = apply_subst subst t in
202           Some (n, Cic.Def (t', ty')) :: context
203       | None -> None :: context)
204     context []
205
206 let apply_subst_metasenv subst metasenv =
207   incr apply_subst_metasenv_counter;
208   metasenv_length := !metasenv_length + List.length metasenv;
209   List.map
210     (fun (n, context, ty) ->
211       (n, apply_subst_context subst context, apply_subst subst ty))
212     (List.filter
213       (fun (i, _, _) -> not (List.mem_assoc i subst))
214       metasenv)
215
216 (***** Pretty printing functions ******)
217
218 let ppsubst subst =
219   String.concat "\n"
220     (List.map
221       (fun (idx, (_, term)) ->
222         Printf.sprintf "?%d := %s" idx (CicPp.ppterm term))
223       subst)
224 ;;
225
226 let ppterm subst term = CicPp.ppterm (apply_subst subst term)
227
228 let ppterm_in_context subst term name_context =
229  CicPp.pp (apply_subst subst term) name_context
230
231 let ppcontext' ?(sep = "\n") subst context =
232  let separate s = if s = "" then "" else s ^ sep in
233   List.fold_right 
234    (fun context_entry (i,name_context) ->
235      match context_entry with
236         Some (n,Cic.Decl t) ->
237          sprintf "%s%s : %s" (separate i) (CicPp.ppname n)
238           (ppterm_in_context subst t name_context), (Some n)::name_context
239       | Some (n,Cic.Def (bo,ty)) ->
240          sprintf "%s%s : %s := %s" (separate i) (CicPp.ppname n)
241           (match ty with
242               None -> "_"
243             | Some ty -> ppterm_in_context subst ty name_context)
244           (ppterm_in_context subst bo name_context), (Some n)::name_context
245        | None ->
246           sprintf "%s_ :? _" (separate i), None::name_context
247     ) context ("",[])
248
249 let ppcontext ?sep subst context = fst (ppcontext' ?sep subst context)
250
251 let ppmetasenv ?(sep = "\n") metasenv subst =
252   String.concat sep
253     (List.map
254       (fun (i, c, t) ->
255         let context,name_context = ppcontext' ~sep:"; " subst c in
256          sprintf "%s |- ?%d: %s" context i
257           (ppterm_in_context subst t name_context))
258       (List.filter
259         (fun (i, _, _) -> not (List.mem_assoc i subst))
260         metasenv))
261
262 (* From now on we recreate a kernel abstraction where substitutions are part of
263  * the calculus *)
264
265 let lift subst n term =
266   incr subst_counter;
267   let term = apply_subst subst term in
268   try
269     CicSubstitution.lift n term
270   with e ->
271     raise (MetaSubstFailure ("Lift failure: " ^ Printexc.to_string e))
272
273 let subst subst t1 t2 =
274   incr subst_counter;
275   let t1 = apply_subst subst t1 in
276   let t2 = apply_subst subst t2 in
277   try
278     CicSubstitution.subst t1 t2
279   with e ->
280     raise (MetaSubstFailure ("Subst failure: " ^ Printexc.to_string e))
281
282 let whd subst context term =
283   incr whd_counter;
284   let term = apply_subst subst term in
285   let context = apply_subst_context subst context in
286   try
287     CicReduction.whd context term
288   with e ->
289     raise (MetaSubstFailure ("Weak head reduction failure: " ^
290       Printexc.to_string e))
291
292 let are_convertible subst context t1 t2 =
293   incr are_convertible_counter;
294   let context = apply_subst_context subst context in
295   let t1 = apply_subst subst t1 in
296   let t2 = apply_subst subst t2 in
297   CicReduction.are_convertible context t1 t2
298
299 let tempi_type_of_aux_subst = ref 0.0;;
300 let tempi_subst = ref 0.0;;
301 let tempi_type_of_aux = ref 0.0;;
302
303   (* assumption: metasenv is already instantiated wrt subst *)
304 let type_of_aux' metasenv subst context term =
305   let time1 = Unix.gettimeofday () in
306   let term = apply_subst subst term in
307   let context = apply_subst_context subst context in
308 (*   let metasenv = apply_subst_metasenv subst metasenv in *)
309   let time2 = Unix.gettimeofday () in
310   let res =
311     try
312       CicTypeChecker.type_of_aux' metasenv context term
313     with CicTypeChecker.TypeCheckerFailure msg ->
314       raise (MetaSubstFailure ("Type checker failure: " ^ msg))
315   in
316   let time3 = Unix.gettimeofday () in
317    tempi_type_of_aux_subst := !tempi_type_of_aux_subst +. time3 -. time1 ; 
318    tempi_subst := !tempi_subst +. time2 -. time1 ; 
319    tempi_type_of_aux := !tempi_type_of_aux +. time3 -. time2 ; 
320    res
321
322 (**** DELIFT ****)
323 (* the delift function takes in input a metavariable index, an ordered list of
324  * optional terms [t1,...,tn] and a term t, and substitutes every tk = Some
325  * (rel(nk)) with rel(k).  Typically, the list of optional terms is the explicit
326  * substitution that is applied to a metavariable occurrence and the result of
327  * the delift function is a term the implicit variable can be substituted with
328  * to make the term [t] unifiable with the metavariable occurrence.  In general,
329  * the problem is undecidable if we consider equivalence in place of alpha
330  * convertibility. Our implementation, though, is even weaker than alpha
331  * convertibility, since it replace the term [tk] if and only if [tk] is a Rel
332  * (missing all the other cases). Does this matter in practice?
333  * The metavariable index is the index of the metavariable that must not occur
334  * in the term (for occur check).
335  *)
336
337 exception NotInTheList;;
338
339 let position n =
340   let rec aux k =
341    function 
342        [] -> raise NotInTheList
343      | (Some (Cic.Rel m))::_ when m=n -> k
344      | _::tl -> aux (k+1) tl in
345   aux 1
346 ;;
347
348 exception Occur;;
349
350 let rec force_does_not_occur subst to_be_restricted t =
351  let module C = Cic in
352  let more_to_be_restricted = ref [] in
353  let rec aux k = function
354       C.Rel r when List.mem (r - k) to_be_restricted -> raise Occur
355     | C.Rel _
356     | C.Sort _ as t -> t
357     | C.Implicit _ -> assert false
358     | C.Meta (n, l) ->
359        (* we do not retrieve the term associated to ?n in subst since *)
360        (* in this way we can restrict if something goes wrong         *)
361        let l' =
362          let i = ref 0 in
363          List.map
364            (function t ->
365              incr i ;
366              match t with
367                 None -> None
368               | Some t ->
369                  try
370                    Some (aux k t)
371                  with Occur ->
372                    more_to_be_restricted := (n,!i) :: !more_to_be_restricted;
373                    None)
374            l
375        in
376         C.Meta (n, l')
377     | C.Cast (te,ty) -> C.Cast (aux k te, aux k ty)
378     | C.Prod (name,so,dest) -> C.Prod (name, aux k so, aux (k+1) dest)
379     | C.Lambda (name,so,dest) -> C.Lambda (name, aux k so, aux (k+1) dest)
380     | C.LetIn (name,so,dest) -> C.LetIn (name, aux k so, aux (k+1) dest)
381     | C.Appl l -> C.Appl (List.map (aux k) l)
382     | C.Var (uri,exp_named_subst) ->
383         let exp_named_subst' =
384           List.map (fun (uri,t) -> (uri, aux k t)) exp_named_subst
385         in
386         C.Var (uri, exp_named_subst')
387     | C.Const (uri, exp_named_subst) ->
388         let exp_named_subst' =
389           List.map (fun (uri,t) -> (uri, aux k t)) exp_named_subst
390         in
391         C.Const (uri, exp_named_subst')
392     | C.MutInd (uri,tyno,exp_named_subst) ->
393         let exp_named_subst' =
394           List.map (fun (uri,t) -> (uri, aux k t)) exp_named_subst
395         in
396         C.MutInd (uri, tyno, exp_named_subst')
397     | C.MutConstruct (uri,tyno,consno,exp_named_subst) ->
398         let exp_named_subst' =
399           List.map (fun (uri,t) -> (uri, aux k t)) exp_named_subst
400         in
401         C.MutConstruct (uri, tyno, consno, exp_named_subst')
402     | C.MutCase (uri,tyno,out,te,pl) ->
403         C.MutCase (uri, tyno, aux k out, aux k te, List.map (aux k) pl)
404     | C.Fix (i,fl) ->
405        let len = List.length fl in
406        let k_plus_len = k + len in
407        let fl' =
408          List.map
409           (fun (name,j,ty,bo) -> (name, j, aux k ty, aux k_plus_len bo)) fl
410        in
411        C.Fix (i, fl')
412     | C.CoFix (i,fl) ->
413        let len = List.length fl in
414        let k_plus_len = k + len in
415        let fl' =
416          List.map
417           (fun (name,ty,bo) -> (name, aux k ty, aux k_plus_len bo)) fl
418        in
419        C.CoFix (i, fl')
420  in
421  let res = aux 0 t in
422  (!more_to_be_restricted, res)
423  
424 let rec restrict subst to_be_restricted metasenv =
425   let names_of_context_indexes context indexes =
426     String.concat ", "
427       (List.map
428         (fun i ->
429           try
430            match List.nth context i with
431            | None -> assert false
432            | Some (n, _) -> CicPp.ppname n
433           with
434            Failure _ -> assert false
435         ) indexes)
436   in
437   let force_does_not_occur_in_context to_be_restricted = function
438     | None -> [], None
439     | Some (name, Cic.Decl t) ->
440         let (more_to_be_restricted, t') =
441           force_does_not_occur subst to_be_restricted t
442         in
443         more_to_be_restricted, Some (name, Cic.Decl t')
444     | Some (name, Cic.Def (bo, ty)) ->
445         let (more_to_be_restricted, bo') =
446           force_does_not_occur subst to_be_restricted bo
447         in
448         let more_to_be_restricted, ty' =
449           match ty with
450           | None ->  more_to_be_restricted, None
451           | Some ty ->
452               let more_to_be_restricted', ty' =
453                 force_does_not_occur subst to_be_restricted ty
454               in
455               more_to_be_restricted @ more_to_be_restricted',
456               Some ty'
457         in
458         more_to_be_restricted, Some (name, Cic.Def (bo', ty'))
459   in
460   let rec erase i to_be_restricted n = function
461     | [] -> [], to_be_restricted, []
462     | hd::tl ->
463         let more_to_be_restricted,restricted,tl' =
464          erase (i+1) to_be_restricted n tl
465         in
466         let restrict_me = List.mem i restricted in
467         if restrict_me then
468          more_to_be_restricted, restricted, None:: tl'
469         else
470           (try
471             let more_to_be_restricted', hd' =
472               let delifted_restricted =
473                let rec aux =
474                 function
475                    [] -> []
476                  | j::tl when j > i -> (j - i)::aux tl
477                  | _::tl -> aux tl
478                in
479                 aux restricted
480               in
481                force_does_not_occur_in_context delifted_restricted hd
482             in
483              more_to_be_restricted @ more_to_be_restricted',
484              restricted, hd' :: tl'
485           with Occur ->
486             more_to_be_restricted, (i :: restricted), None :: tl')
487   in
488   let (more_to_be_restricted, metasenv) =  (* restrict metasenv *)
489     List.fold_right
490       (fun (n, context, t) (more, metasenv) ->
491         let to_be_restricted =
492           List.map snd (List.filter (fun (m, _) -> m = n) to_be_restricted)
493         in
494         let (more_to_be_restricted, restricted, context') =
495          (* just an optimization *)
496          if to_be_restricted = [] then
497           [],[],context
498          else
499           erase 1 to_be_restricted n context
500         in
501         try
502           let more_to_be_restricted', t' =
503             force_does_not_occur subst restricted t
504           in
505           let metasenv' = (n, context', t') :: metasenv in
506           (more @ more_to_be_restricted @ more_to_be_restricted',
507           metasenv')
508         with Occur ->
509           raise (MetaSubstFailure (sprintf
510             "Cannot restrict the context of the metavariable ?%d over the hypotheses %s since metavariable's type depends on at least one of them"
511             n (names_of_context_indexes context to_be_restricted))))
512       metasenv ([], [])
513   in
514   let (more_to_be_restricted', subst) = (* restrict subst *)
515     List.fold_right
516       (fun (n, (context, term)) (more, subst) ->
517         let to_be_restricted =
518           List.map snd (List.filter (fun (m, _) -> m = n) to_be_restricted)
519         in
520         (try
521           let (more_to_be_restricted, restricted, context') =
522            (* just an optimization *)
523             if to_be_restricted = [] then
524               [], [], context
525             else
526               erase 1 to_be_restricted n context
527           in
528           let more_to_be_restricted', term' =
529             force_does_not_occur subst restricted term
530           in
531           let subst' = (n, (context', term')) :: subst in
532           let more = more @ more_to_be_restricted @ more_to_be_restricted' in
533           (more, subst')
534         with Occur ->
535           raise (MetaSubstFailure (sprintf
536             "Cannot restrict the context of the metavariable ?%d over the hypotheses %s since ?%d is already instantiated with %s and at least one of the hypotheses occurs in the substituted term"
537             n (names_of_context_indexes context to_be_restricted) n
538             (ppterm subst term)))))
539       subst ([], [])
540   in
541   match more_to_be_restricted @ more_to_be_restricted' with
542   | [] -> (metasenv, subst)
543   | l -> restrict subst l metasenv
544 ;;
545
546 (*CSC: maybe we should rename delift in abstract, as I did in my dissertation *)
547 let delift n subst context metasenv l t =
548  let module S = CicSubstitution in
549   let l =
550    let (_, canonical_context, _) = CicUtil.lookup_meta n metasenv in
551    List.map2 (fun ct lt ->
552      match (ct, lt) with
553      | None, _ -> None
554      | Some _, _ -> lt)
555      canonical_context l
556   in
557   let to_be_restricted = ref [] in
558   let rec deliftaux k =
559    let module C = Cic in
560     function
561        C.Rel m -> 
562          if m <=k then
563           C.Rel m   (*CSC: che succede se c'e' un Def? Dovrebbe averlo gia' *)
564                     (*CSC: deliftato la regola per il LetIn                 *)
565                     (*CSC: FALSO! La regola per il LetIn non lo fa          *)
566          else
567           (try
568             match List.nth context (m-k-1) with
569                Some (_,C.Def (t,_)) ->
570                 (*CSC: Hmmm. This bit of reduction is not in the spirit of    *)
571                 (*CSC: first order unification. Does it help or does it harm? *)
572                 deliftaux k (S.lift m t)
573              | Some (_,C.Decl t) ->
574                 C.Rel ((position (m-k) l) + k)
575              | None -> raise (MetaSubstFailure "RelToHiddenHypothesis")
576            with
577             Failure _ ->
578              raise (MetaSubstFailure "Unbound variable found in deliftaux")
579           )
580      | C.Var (uri,exp_named_subst) ->
581         let exp_named_subst' =
582          List.map (function (uri,t) -> uri,deliftaux k t) exp_named_subst
583         in
584          C.Var (uri,exp_named_subst')
585      | C.Meta (i, l1) as t -> 
586         if i = n then
587           raise (MetaSubstFailure (sprintf
588             "Cannot unify the metavariable ?%d with a term that has as subterm %s in which the same metavariable occurs (occur check)"
589             i (ppterm subst t)))
590         else
591          (* I do not consider the term associated to ?i in subst since *)
592          (* in this way I can restrict if something goes wrong.        *)
593           let rec deliftl j =
594            function
595               [] -> []
596             | None::tl -> None::(deliftl (j+1) tl)
597             | (Some t)::tl ->
598                let l1' = (deliftl (j+1) tl) in
599                 try
600                  Some (deliftaux k t)::l1'
601                 with
602                    NotInTheList
603                  | MetaSubstFailure _ ->
604                     to_be_restricted := (i,j)::!to_be_restricted ; None::l1'
605           in
606            let l' = deliftl 1 l1 in
607             C.Meta(i,l')
608      | C.Sort _ as t -> t
609      | C.Implicit _ as t -> t
610      | C.Cast (te,ty) -> C.Cast (deliftaux k te, deliftaux k ty)
611      | C.Prod (n,s,t) -> C.Prod (n, deliftaux k s, deliftaux (k+1) t)
612      | C.Lambda (n,s,t) -> C.Lambda (n, deliftaux k s, deliftaux (k+1) t)
613      | C.LetIn (n,s,t) -> C.LetIn (n, deliftaux k s, deliftaux (k+1) t)
614      | C.Appl l -> C.Appl (List.map (deliftaux k) l)
615      | C.Const (uri,exp_named_subst) ->
616         let exp_named_subst' =
617          List.map (function (uri,t) -> uri,deliftaux k t) exp_named_subst
618         in
619          C.Const (uri,exp_named_subst')
620      | C.MutInd (uri,typeno,exp_named_subst) ->
621         let exp_named_subst' =
622          List.map (function (uri,t) -> uri,deliftaux k t) exp_named_subst
623         in
624          C.MutInd (uri,typeno,exp_named_subst')
625      | C.MutConstruct (uri,typeno,consno,exp_named_subst) ->
626         let exp_named_subst' =
627          List.map (function (uri,t) -> uri,deliftaux k t) exp_named_subst
628         in
629          C.MutConstruct (uri,typeno,consno,exp_named_subst')
630      | C.MutCase (sp,i,outty,t,pl) ->
631         C.MutCase (sp, i, deliftaux k outty, deliftaux k t,
632          List.map (deliftaux k) pl)
633      | C.Fix (i, fl) ->
634         let len = List.length fl in
635         let liftedfl =
636          List.map
637           (fun (name, i, ty, bo) ->
638            (name, i, deliftaux k ty, deliftaux (k+len) bo))
639            fl
640         in
641          C.Fix (i, liftedfl)
642      | C.CoFix (i, fl) ->
643         let len = List.length fl in
644         let liftedfl =
645          List.map
646           (fun (name, ty, bo) -> (name, deliftaux k ty, deliftaux (k+len) bo))
647            fl
648         in
649          C.CoFix (i, liftedfl)
650   in
651    let res =
652     try
653      deliftaux 0 t
654     with
655      NotInTheList ->
656       (* This is the case where we fail even first order unification. *)
657       (* The reason is that our delift function is weaker than first  *)
658       (* order (in the sense of alpha-conversion). See comment above  *)
659       (* related to the delift function.                              *)
660 debug_print "\n!!!!!!!!!!! First Order UnificationFailure, but maybe it could have been successful even in a first order setting (no conversion, only alpha convertibility)! Please, implement a better delift function !!!!!!!!!!!!!!!!" ;
661       raise (Uncertain (sprintf
662         "Error trying to abstract %s over [%s]: the algorithm only tried to abstract over bound variables"
663         (ppterm subst t)
664         (String.concat "; "
665           (List.map
666             (function Some t -> ppterm subst t | None -> "_")
667             l))))
668    in
669    let (metasenv, subst) = restrict subst !to_be_restricted metasenv in
670     res, metasenv, subst
671 ;;
672
673 (**** END OF DELIFT ****)
674
675
676 (** {2 Format-like pretty printers} *)
677
678 let fpp_gen ppf s =
679   Format.pp_print_string ppf s;
680   Format.pp_print_newline ppf ();
681   Format.pp_print_flush ppf ()
682
683 let fppsubst ppf subst = fpp_gen ppf (ppsubst subst)
684 let fppterm ppf term = fpp_gen ppf (CicPp.ppterm term)
685 let fppmetasenv ppf metasenv = fpp_gen ppf (ppmetasenv metasenv [])
686