]> matita.cs.unibo.it Git - helm.git/blob - helm/software/components/ng_refiner/nCicUnification.ml
hints attached
[helm.git] / helm / software / components / ng_refiner / nCicUnification.ml
1 (*
2     ||M||  This file is part of HELM, an Hypertextual, Electronic        
3     ||A||  Library of Mathematics, developed at the Computer Science     
4     ||T||  Department, University of Bologna, Italy.                     
5     ||I||                                                                
6     ||T||  HELM is free software; you can redistribute it and/or         
7     ||A||  modify it under the terms of the GNU General Public License   
8     \   /  version 2 or (at your option) any later version.      
9      \ /   This software is distributed as is, NO WARRANTY.     
10       V_______________________________________________________________ *)
11
12 (* $Id$ *)
13
14 exception UnificationFailure of string Lazy.t;;
15 exception Uncertain of string Lazy.t;;
16 exception AssertFailure of string Lazy.t;;
17
18 let (===) x y = Pervasives.compare x y = 0 ;;
19
20 let uncert_exc metasenv subst context t1 t2 = 
21   Uncertain (lazy (
22   "Can't unify " ^ NCicPp.ppterm ~metasenv ~subst ~context t1 ^
23   " with " ^ NCicPp.ppterm ~metasenv ~subst ~context t2))
24 ;;
25
26 let fail_exc metasenv subst context t1 t2 = 
27   UnificationFailure (lazy (
28   "Can't unify " ^ NCicPp.ppterm ~metasenv ~subst ~context t1 ^
29   " with " ^ NCicPp.ppterm ~metasenv ~subst ~context t2));
30 ;;
31
32 let mk_appl hd tl =
33   match hd with
34   | NCic.Appl l -> NCic.Appl (l@tl)
35   | _ -> NCic.Appl (hd :: tl)
36 ;;
37
38 let flexible l = 
39   List.exists 
40     (function 
41        | NCic.Meta _  
42        | NCic.Appl (NCic.Meta _::_) -> true
43        | _ -> false) l
44 ;;
45
46 exception WrongShape;;
47
48 let eta_reduce = 
49   let delift_if_not_occur body orig =
50     try 
51         NCicSubstitution.psubst ~avoid_beta_redexes:true
52           (fun () -> raise WrongShape) [()] body
53     with WrongShape -> orig
54   in
55   function
56   | NCic.Lambda(_, _, NCic.Appl [hd; NCic.Rel 1]) as orig ->
57       delift_if_not_occur hd orig
58   | NCic.Lambda(_, _, NCic.Appl (hd :: l)) as orig
59     when HExtlib.list_last l = NCic.Rel 1 ->
60        let body = 
61          let args, _ = HExtlib.split_nth (List.length l - 1) l in
62          NCic.Appl (hd::args)
63        in
64        delift_if_not_occur body orig
65   | t -> t
66 ;;
67  
68 module C = NCic;;
69 module Ref = NReference;;
70
71 let indent = ref "";;
72 let inside c = indent := !indent ^ String.make 1 c;;
73 let outside () = indent := String.sub !indent 0 (String.length !indent -1);;
74
75 (*
76 let pp s = 
77   prerr_endline (Printf.sprintf "%-20s" !indent ^ " " ^ Lazy.force s)
78 ;;  
79 *)
80
81 let pp _ = ();;
82
83 let fix_sorts swap metasenv subst context meta t =
84   let rec aux () = function
85     | NCic.Sort (NCic.Type u) as orig ->
86         if swap then
87          match NCicEnvironment.sup u with
88          | None -> prerr_endline "no sup for" ;
89             raise (fail_exc metasenv subst context meta t)
90          | Some u1 -> if u = u1 then orig else NCic.Sort (NCic.Type u1)
91         else
92          NCic.Sort (NCic.Type (
93            match NCicEnvironment.sup NCicEnvironment.type0 with 
94            | Some x -> x
95            | _ -> assert false))
96     | NCic.Meta _ as orig -> orig
97     | t -> NCicUtils.map (fun _ _ -> ()) () aux t
98   in
99     aux () t
100 ;;
101
102 let rec beta_expand hdb num test_eq_only swap metasenv subst context t arg =
103   let rec aux (n,context,test_eq_only as k) (metasenv, subst as acc) t' =
104    try
105     let metasenv, subst =
106      if swap then
107       unify hdb test_eq_only metasenv subst context t' (NCicSubstitution.lift n arg)
108      else
109       unify hdb test_eq_only metasenv subst context (NCicSubstitution.lift n arg) t'
110     in
111      (metasenv, subst), NCic.Rel (1 + n)
112    with Uncertain _ | UnificationFailure _ ->
113        match t' with
114        | NCic.Rel m as orig -> 
115            (metasenv, subst), if m <= n then orig else NCic.Rel (m+1)
116        (* andrea: in general, beta_expand can create badly typed
117         terms. This happens quite seldom in practice, UNLESS we
118         iterate on the local context. For this reason, we renounce
119         to iterate and just lift *)
120        | NCic.Meta (i,(shift,lc)) ->
121            (metasenv,subst), NCic.Meta (i,(shift+1,lc))
122        | NCic.Prod (name, src, tgt) as orig ->
123            let (metasenv, subst), src1 = aux (n,context,true) acc src in 
124            let k = n+1, (name, NCic.Decl src) :: context, test_eq_only in
125            let ms, tgt1 = aux k (metasenv, subst) tgt in 
126            if src == src1 && tgt == tgt1 then ms, orig else
127            ms, NCic.Prod (name, src1, tgt1)
128        | t -> 
129            NCicUntrusted.map_term_fold_a 
130              (fun e (n,ctx,teq) -> n+1,e::ctx,teq) k aux acc t
131
132   in
133   let argty = NCicTypeChecker.typeof ~metasenv ~subst context arg in
134   let fresh_name = "Hbeta" ^ string_of_int num in
135   let (metasenv,subst), t1 = 
136     aux (0, context, test_eq_only) (metasenv, subst) t in
137   let t2 = eta_reduce (NCic.Lambda (fresh_name,argty,t1)) in
138   try 
139     ignore(NCicTypeChecker.typeof ~metasenv ~subst context t2);
140     metasenv, subst, t2
141   with NCicTypeChecker.TypeCheckerFailure _ -> 
142     metasenv, subst, NCic.Lambda ("_", argty, NCicSubstitution.lift 1 arg)
143
144 and beta_expand_many hdb test_equality_only swap metasenv subst context t args =
145 (* (*D*)  inside 'B'; try let rc = *)
146   pp (lazy (String.concat ", "
147      (List.map (NCicPp.ppterm ~metasenv ~subst ~context)
148      args) ^ " ∈ " ^ NCicPp.ppterm ~metasenv ~subst ~context t));
149   let _, subst, metasenv, hd =
150     List.fold_right
151       (fun arg (num,subst,metasenv,t) ->
152          let metasenv, subst, t =
153            beta_expand hdb num test_equality_only swap metasenv subst context t arg
154          in
155            num+1,subst,metasenv,t)
156       args (1,subst,metasenv,t) 
157   in
158   pp (lazy ("Head syntesized by b-exp: " ^ 
159     NCicPp.ppterm ~metasenv ~subst ~context hd));
160     metasenv, subst, hd
161 (* (*D*)  in outside (); rc with exn -> outside (); raise exn *)
162
163 and instantiate hdb test_eq_only metasenv subst context n lc t swap =
164  (*D*)  inside 'I'; try let rc =  
165          pp (lazy(string_of_int n ^ " :=?= "^
166            NCicPp.ppterm ~metasenv ~subst ~context t));
167   let unify test_eq_only m s c t1 t2 = 
168     if swap then unify hdb test_eq_only m s c t2 t1 
169     else unify hdb test_eq_only m s c t1 t2
170   in
171   let name, ctx, ty = NCicUtils.lookup_meta n metasenv in
172   let metasenv, subst, t = 
173     match ty with 
174     | NCic.Implicit (`Typeof _) -> 
175        metasenv,subst, t
176          (* fix_sorts swap metasenv subst context (NCic.Meta(n,lc)) t *)
177     | _ ->
178        pp (lazy (
179          "typeof: " ^ NCicPp.ppterm ~metasenv ~subst ~context t ^ "\nctx:\n"^
180           NCicPp.ppcontext ~metasenv ~subst context ^ "\nmenv:\n"^
181           NCicPp.ppmetasenv ~subst metasenv));
182        let t, ty_t = 
183          try t, NCicTypeChecker.typeof ~subst ~metasenv context t 
184          with 
185          | NCicTypeChecker.AssertFailure msg -> 
186            (pp (lazy "fine typeof (fallimento)");
187            let ft=fix_sorts swap metasenv subst context (NCic.Meta (n,lc)) t in
188            if ft == t then 
189              (prerr_endline ( ("ILLTYPED: " ^ 
190                 NCicPp.ppterm ~metasenv ~subst ~context t
191             ^ "\nBECAUSE:" ^ Lazy.force msg ^ "\nCONTEXT:\n" ^
192             NCicPp.ppcontext ~metasenv ~subst context ^ "\nMENV:\n" ^
193             NCicPp.ppmetasenv ~subst metasenv
194             ));
195                      assert false)
196            else
197             try 
198               pp (lazy ("typeof: " ^ 
199                 NCicPp.ppterm ~metasenv ~subst ~context ft));
200               ft, NCicTypeChecker.typeof ~subst ~metasenv context ft 
201             with NCicTypeChecker.AssertFailure _ -> 
202               assert false)
203          | NCicTypeChecker.TypeCheckerFailure msg ->
204               prerr_endline (Lazy.force msg);
205               pp msg; assert false
206        in
207        let lty = NCicSubstitution.subst_meta lc ty in
208        pp (lazy ("On the types: " ^
209         NCicPp.ppterm ~metasenv ~subst ~context:ctx ty ^ " ~~~ " ^
210         NCicPp.ppterm ~metasenv ~subst ~context lty ^ " === "
211          ^ NCicPp.ppterm ~metasenv ~subst ~context ty_t)); 
212        let metasenv,subst= unify test_eq_only metasenv subst context lty ty_t in
213        metasenv, subst, t
214   in
215          pp (lazy(string_of_int n ^ " := 111 = "^
216            NCicPp.ppterm ~metasenv ~subst ~context t));
217   let (metasenv, subst), t = 
218     try NCicMetaSubst.delift metasenv subst context n lc t
219     with NCicMetaSubst.Uncertain msg -> 
220          pp (lazy ("delift fails: " ^ Lazy.force msg));
221          raise (Uncertain msg)
222     | NCicMetaSubst.MetaSubstFailure msg -> 
223          pp (lazy ("delift fails: " ^ Lazy.force msg));
224          raise (UnificationFailure msg)
225   in
226          pp (lazy(string_of_int n ^ " := 222 = "^
227            NCicPp.ppterm ~metasenv ~subst ~context:ctx t
228          ^ "\n" ^ NCicPp.ppmetasenv ~subst metasenv));
229   (* Unifying the types may have already instantiated n. *)
230   try
231     let _, _,oldt,_ = NCicUtils.lookup_subst n subst in
232     let oldt = NCicSubstitution.subst_meta lc oldt in
233     let t = NCicSubstitution.subst_meta lc t in
234     (* conjecture: always fail --> occur check *)
235     unify test_eq_only metasenv subst context oldt t
236   with NCicUtils.Subst_not_found _ -> 
237     (* by cumulativity when unify(?,Type_i) 
238      * we could ? := Type_j with j <= i... *)
239     let subst = (n, (name, ctx, t, ty)) :: subst in
240     pp (lazy ("?"^string_of_int n^" := "^NCicPp.ppterm
241       ~metasenv ~subst ~context (NCicSubstitution.subst_meta lc t)));
242     let metasenv = 
243       List.filter (fun (m,_) -> not (n = m)) metasenv 
244     in
245     metasenv, subst
246  (*D*)  in outside(); rc with exn -> outside (); raise exn 
247
248 and unify hdb test_eq_only metasenv subst context t1 t2 =
249  (*D*) inside 'U'; try let rc =
250    let fo_unif test_eq_only metasenv subst t1 t2 =
251     (*D*) inside 'F'; try let rc =  
252      pp (lazy("  " ^ NCicPp.ppterm ~metasenv ~subst ~context t1 ^ " === " ^ 
253          NCicPp.ppterm ~metasenv ~subst ~context t2));
254      if t1 === t2 then
255        metasenv, subst
256      else
257        match (t1,t2) with
258        | (C.Sort (C.Type a), C.Sort (C.Type b)) when not test_eq_only -> 
259            if NCicEnvironment.universe_leq a b then metasenv, subst
260            else raise (fail_exc metasenv subst context t1 t2)
261        | (C.Sort (C.Type a), C.Sort (C.Type b)) -> 
262            if NCicEnvironment.universe_eq a b then metasenv, subst
263            else raise (fail_exc metasenv subst context t1 t2)
264        | (C.Sort C.Prop,C.Sort (C.Type _)) -> 
265            if (not test_eq_only) then metasenv, subst
266            else raise (fail_exc metasenv subst context t1 t2)
267
268        | (C.Lambda (name1,s1,t1), C.Lambda(_,s2,t2)) 
269        | (C.Prod (name1,s1,t1), C.Prod(_,s2,t2)) ->
270            let metasenv, subst = unify hdb true metasenv subst context s1 s2 in
271            unify hdb test_eq_only metasenv subst ((name1, C.Decl s1)::context) t1 t2
272        | (C.LetIn (name1,ty1,s1,t1), C.LetIn(_,ty2,s2,t2)) ->
273            let metasenv,subst=unify hdb test_eq_only metasenv subst context ty1 ty2 in
274            let metasenv,subst=unify hdb test_eq_only metasenv subst context s1 s2 in
275            let context = (name1, C.Def (s1,ty1))::context in
276            unify hdb test_eq_only metasenv subst context t1 t2
277
278        | (C.Meta (n1,(s1,l1 as lc1)),C.Meta (n2,(s2,l2 as lc2))) when n1 = n2 ->
279           (try 
280            let l1 = NCicUtils.expand_local_context l1 in
281            let l2 = NCicUtils.expand_local_context l2 in
282            let metasenv, subst, to_restrict, _ =
283             List.fold_right2 
284              (fun t1 t2 (metasenv, subst, to_restrict, i) -> 
285                 try 
286                   let metasenv, subst = 
287                    unify hdb test_eq_only metasenv subst context 
288                     (NCicSubstitution.lift s1 t1) (NCicSubstitution.lift s2 t2)
289                   in
290                   metasenv, subst, to_restrict, i-1  
291                 with UnificationFailure _ | Uncertain _ ->
292                   metasenv, subst, i::to_restrict, i-1)
293              l1 l2 (metasenv, subst, [], List.length l1)
294            in
295            if to_restrict <> [] then
296              let metasenv, subst, _ = 
297                NCicMetaSubst.restrict metasenv subst n1 to_restrict
298              in
299                metasenv, subst
300            else metasenv, subst
301           with 
302            | Invalid_argument _ -> assert false
303            | NCicMetaSubst.MetaSubstFailure msg ->
304               try 
305                 let _,_,term,_ = NCicUtils.lookup_subst n1 subst in
306                 let term1 = NCicSubstitution.subst_meta lc1 term in
307                 let term2 = NCicSubstitution.subst_meta lc2 term in
308                   unify hdb test_eq_only metasenv subst context term1 term2
309               with NCicUtils.Subst_not_found _-> raise (UnificationFailure msg))
310
311        | C.Meta (n,lc), t -> 
312            (try 
313              let _,_,term,_ = NCicUtils.lookup_subst n subst in
314              let term = NCicSubstitution.subst_meta lc term in
315                unify hdb test_eq_only metasenv subst context term t
316            with NCicUtils.Subst_not_found _-> 
317              instantiate hdb test_eq_only metasenv subst context n lc t false)
318
319        | t, C.Meta (n,lc) -> 
320            (try 
321              let _,_,term,_ = NCicUtils.lookup_subst n subst in
322              let term = NCicSubstitution.subst_meta lc term in
323                unify hdb test_eq_only metasenv subst context t term
324            with NCicUtils.Subst_not_found _-> 
325              instantiate hdb test_eq_only metasenv subst context n lc t true)
326
327        | NCic.Appl (NCic.Meta (i,l)::args), _ when List.mem_assoc i subst ->
328             let _,_,term,_ = NCicUtils.lookup_subst i subst in
329             let term = NCicSubstitution.subst_meta l term in
330               unify hdb test_eq_only metasenv subst context (mk_appl term args) t2
331
332        | _, NCic.Appl (NCic.Meta (i,l)::args) when List.mem_assoc i subst ->
333             let _,_,term,_ = NCicUtils.lookup_subst i subst in
334             let term = NCicSubstitution.subst_meta l term in
335               unify hdb test_eq_only metasenv subst context t1 (mk_appl term args)
336
337        |  NCic.Appl (NCic.Meta (i,_)::_ as l1),
338           NCic.Appl (NCic.Meta (j,_)::_ as l2) when i=j ->
339             (try
340               List.fold_left2 
341                 (fun (metasenv, subst) t1 t2 ->
342                   unify hdb test_eq_only metasenv subst context t1 t2)
343                 (metasenv,subst) l1 l2
344             with Invalid_argument _ -> 
345               raise (fail_exc metasenv subst context t1 t2))
346
347        | NCic.Appl (NCic.Meta (i,l)::args), _ when not (flexible args) ->
348            (* we verify that none of the args is a Meta, 
349               since beta expanding w.r.t a metavariable makes no sense  *)
350               let metasenv, subst, beta_expanded =
351                 beta_expand_many hdb 
352                   test_eq_only false 
353                   metasenv subst context t2 args
354               in
355                 unify hdb test_eq_only metasenv subst context 
356                   (C.Meta (i,l)) beta_expanded 
357
358        | _, NCic.Appl (NCic.Meta (i,l)::args) when not(flexible args) ->
359               let metasenv, subst, beta_expanded =
360                 beta_expand_many hdb 
361                   test_eq_only true 
362                   metasenv subst context t1 args
363               in
364                 unify hdb test_eq_only metasenv subst context 
365                   beta_expanded (C.Meta (i,l))
366
367        (* processing this case here we avoid a useless small delta step *)
368        | (C.Appl ((C.Const r1) as _hd1::tl1), C.Appl (C.Const r2::tl2)) 
369          when Ref.eq r1 r2 ->
370            let relevance = NCicEnvironment.get_relevance r1 in
371            let relevance = match r1 with
372              | Ref.Ref (_,Ref.Con (_,_,lno)) ->
373                  let _,relevance = HExtlib.split_nth lno relevance in
374                    HExtlib.mk_list false lno @ relevance
375              | _ -> relevance
376            in
377            let metasenv, subst, _ = 
378              try
379                List.fold_left2 
380                  (fun (metasenv, subst, relevance) t1 t2 ->
381                     let b, relevance = 
382                       match relevance with b::tl -> b,tl | _ -> true, [] in
383                     let metasenv, subst = 
384                       try unify hdb test_eq_only metasenv subst context t1 t2
385                       with UnificationFailure _ | Uncertain _ when not b ->
386                         metasenv, subst
387                     in
388                       metasenv, subst, relevance)
389                  (metasenv, subst, relevance) tl1 tl2
390              with Invalid_argument _ -> 
391                raise (uncert_exc metasenv subst context t1 t2)
392            in 
393              metasenv, subst
394
395        | (C.Match (Ref.Ref (_,Ref.Ind (_,tyno,_)) as ref1,outtype1,term1,pl1),
396           C.Match (ref2,outtype2,term2,pl2)) ->
397            let _,_,itl,_,_ = NCicEnvironment.get_checked_indtys ref1 in
398            let _,_,ty,_ = List.nth itl tyno in
399            let rec remove_prods ~subst context ty = 
400              let ty = NCicReduction.whd ~subst context ty in
401              match ty with
402              | C.Sort _ -> ty
403              | C.Prod (name,so,ta) -> 
404                    remove_prods ~subst ((name,(C.Decl so))::context) ta
405              | _ -> assert false
406            in
407            let is_prop = 
408              match remove_prods ~subst [] ty with
409              | C.Sort C.Prop -> true
410              | _ -> false 
411            in
412            if not (Ref.eq ref1 ref2) then 
413              raise (uncert_exc metasenv subst context t1 t2) 
414            else
415              let metasenv, subst = 
416               unify hdb test_eq_only metasenv subst context outtype1 outtype2 in
417              let metasenv, subst = 
418                try unify hdb test_eq_only metasenv subst context term1 term2 
419                with UnificationFailure _ | Uncertain _ when is_prop -> 
420                  metasenv, subst
421              in
422              (try
423               List.fold_left2 
424                (fun (metasenv,subst) -> 
425                   unify hdb test_eq_only metasenv subst context)
426                (metasenv, subst) pl1 pl2
427              with Invalid_argument _ -> 
428                raise (uncert_exc metasenv subst context t1 t2))
429        | (C.Implicit _, _) | (_, C.Implicit _) -> assert false
430        | _ when NCicUntrusted.metas_of_term subst context t1 = [] && 
431                 NCicUntrusted.metas_of_term subst context t2 = [] -> 
432                   raise (fail_exc metasenv subst context t1 t2)
433        | _ -> raise (uncert_exc metasenv subst context t1 t2)
434      (*D*)  in outside(); rc with exn -> outside (); raise exn 
435     in
436     let try_hints metasenv subst t1 t2 (* exc*) =
437       let candidates = 
438         NCicUnifHint.look_for_hint hdb metasenv subst context t1 t2
439       in
440       let rec cand_iter = function
441         | [] -> None (* raise exc *)
442         | (metasenv,c1,c2)::tl -> 
443             try 
444               let metasenv,subst = fo_unif test_eq_only metasenv subst t1 c1 in
445               let metasenv,subst = fo_unif test_eq_only metasenv subst c2 t2 in
446               Some (metasenv, subst)
447             with
448               UnificationFailure _ | Uncertain _ -> cand_iter tl
449       in
450         cand_iter candidates
451     in
452     let height_of = function
453      | NCic.Const (Ref.Ref (_,Ref.Def h)) 
454      | NCic.Const (Ref.Ref (_,Ref.Fix (_,_,h))) 
455      | NCic.Appl(NCic.Const(Ref.Ref(_,Ref.Def h))::_) 
456      | NCic.Appl(NCic.Const(Ref.Ref(_,Ref.Fix (_,_,h)))::_) -> h
457      | _ -> 0
458     in
459     let put_in_whd m1 m2 =
460       NCicReduction.reduce_machine ~delta:max_int ~subst context m1,
461       NCicReduction.reduce_machine ~delta:max_int ~subst context m2
462     in
463     let small_delta_step ~subst  
464       ((_,_,t1,_ as m1, norm1) as x1) ((_,_,t2,_ as m2, norm2) as x2)
465     =
466      assert (not (norm1 && norm2));
467      if norm1 then
468       x1,NCicReduction.reduce_machine ~delta:(height_of t2 -1) ~subst context m2
469      else if norm2 then
470       NCicReduction.reduce_machine ~delta:(height_of t1 -1) ~subst context m1,x2
471      else 
472       let h1 = height_of t1 in 
473       let h2 = height_of t2 in
474       let delta = if h1 = h2 then max 0 (h1 -1) else min h1 h2 in
475       NCicReduction.reduce_machine ~delta ~subst context m1,
476       NCicReduction.reduce_machine ~delta ~subst context m2
477     in
478     let rec unif_machines metasenv subst = 
479       function
480       | ((k1,e1,t1,s1),norm1 as m1),((k2,e2,t2,s2),norm2 as m2) ->
481      (*D*) inside 'M'; try let rc = 
482          pp (lazy("UM: " ^
483            NCicPp.ppterm ~metasenv ~subst ~context 
484              (NCicReduction.unwind (k1,e1,t1,s1)) ^
485            " === " ^ 
486            NCicPp.ppterm ~metasenv ~subst ~context 
487              (NCicReduction.unwind (k2,e2,t2,s2))));
488 pp (lazy (string_of_bool norm1 ^ " ?? " ^ string_of_bool norm2));
489           let relevance = [] (* TO BE UNDERSTOOD 
490             match t1 with
491             | C.Const r -> NCicEnvironment.get_relevance r
492             | _ -> [] *) in
493           let unif_from_stack t1 t2 b metasenv subst =
494               try
495                 let t1 = NCicReduction.from_stack t1 in
496                 let t2 = NCicReduction.from_stack t2 in
497                 unif_machines metasenv subst (put_in_whd t1 t2)
498               with UnificationFailure _ | Uncertain _ when not b ->
499                 metasenv, subst
500           in
501           let rec check_stack l1 l2 r todo =
502             match l1,l2,r with
503             | x1::tl1, x2::tl2, r::tr-> check_stack tl1 tl2 tr ((x1,x2,r)::todo)
504             | x1::tl1, x2::tl2, []-> check_stack tl1 tl2 [] ((x1,x2,true)::todo)
505             | l1, l2, _ -> 
506                NCicReduction.unwind (k1,e1,t1,List.rev l1),
507                 NCicReduction.unwind (k2,e2,t2,List.rev l2),
508                 todo
509           in
510         let hh1,hh2,todo=check_stack (List.rev s1) (List.rev s2) relevance [] in
511         try
512          let metasenv,subst = fo_unif test_eq_only metasenv subst hh1 hh2 in
513          List.fold_left
514           (fun (metasenv,subst) (x1,x2,r) ->
515             unif_from_stack x1 x2 r metasenv subst
516           ) (metasenv,subst) todo
517         with UnificationFailure _ | Uncertain _ when not (norm1 && norm2) ->
518             unif_machines metasenv subst (small_delta_step ~subst m1 m2)
519       (*D*)  in outside(); rc with exn -> outside (); raise exn 
520      in
521      try fo_unif test_eq_only metasenv subst t1 t2
522      with UnificationFailure msg | Uncertain msg as exn -> 
523        match try_hints metasenv subst t1 t2 with
524        | Some x -> x
525        | None -> 
526           try 
527             unif_machines metasenv subst 
528              (put_in_whd (0,[],t1,[]) (0,[],t2,[]))
529           with 
530           | UnificationFailure _ -> raise (UnificationFailure msg)
531           | Uncertain _ -> raise exn
532  (*D*)  in outside(); rc with exn -> outside (); raise exn 
533 ;;
534
535 let unify hdb = 
536   indent := "";      
537   unify hdb false;;
538
539