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.
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_______________________________________________________________ *)
14 exception UnificationFailure of string Lazy.t;;
15 exception Uncertain of string Lazy.t;;
16 exception AssertFailure of string Lazy.t;;
18 let (===) x y = Pervasives.compare x y = 0 ;;
20 let uncert_exc metasenv subst context t1 t2 =
22 "Can't unify " ^ NCicPp.ppterm ~metasenv ~subst ~context t1 ^
23 " with " ^ NCicPp.ppterm ~metasenv ~subst ~context t2))
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))
34 | NCic.Appl l -> NCic.Appl (l@tl)
35 | _ -> NCic.Appl (hd :: tl)
42 | NCic.Appl (NCic.Meta _::_) -> true
46 exception WrongShape;;
49 let delift_if_not_occur body orig =
51 NCicSubstitution.psubst ~avoid_beta_redexes:true
52 (fun () -> raise WrongShape) [()] body
53 with WrongShape -> orig
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 ->
61 let args, _ = HExtlib.split_nth (List.length l - 1) l in
64 delift_if_not_occur body orig
69 module Ref = NReference;;
72 let inside c = indent := !indent ^ String.make 1 c;;
73 let outside () = indent := String.sub !indent 0 (String.length !indent -1);;
77 prerr_endline (Printf.sprintf "%-20s" !indent ^ " " ^ Lazy.force s)
83 let rec beta_expand num test_eq_only swap metasenv subst context t arg =
84 let rec aux (n,context,test_eq_only as k) (metasenv, subst as acc) t' =
88 unify test_eq_only metasenv subst context t' (NCicSubstitution.lift n arg)
90 unify test_eq_only metasenv subst context (NCicSubstitution.lift n arg) t'
92 (metasenv, subst), NCic.Rel (1 + n)
93 with Uncertain _ | UnificationFailure _ ->
95 | NCic.Rel m as orig ->
96 (metasenv, subst), if m <= n then orig else NCic.Rel (m+1)
97 (* andrea: in general, beta_expand can create badly typed
98 terms. This happens quite seldom in practice, UNLESS we
99 iterate on the local context. For this reason, we renounce
100 to iterate and just lift *)
101 | NCic.Meta (i,(shift,lc)) ->
102 (metasenv,subst), NCic.Meta (i,(shift+1,lc))
103 | NCic.Prod (name, src, tgt) as orig ->
104 let (metasenv, subst), src1 = aux (n,context,true) acc src in
105 let k = n+1, (name, NCic.Decl src) :: context, test_eq_only in
106 let ms, tgt1 = aux k (metasenv, subst) tgt in
107 if src == src1 && tgt == tgt1 then ms, orig else
108 ms, NCic.Prod (name, src1, tgt1)
110 NCicUntrusted.map_term_fold_a
111 (fun e (n,ctx,teq) -> n+1,e::ctx,teq) k aux acc t
114 let argty = NCicTypeChecker.typeof ~metasenv ~subst context arg in
115 let fresh_name = "Hbeta" ^ string_of_int num in
116 let (metasenv,subst), t1 =
117 aux (0, context, test_eq_only) (metasenv, subst) t in
118 let t2 = eta_reduce (NCic.Lambda (fresh_name,argty,t1)) in
120 ignore(NCicTypeChecker.typeof ~metasenv ~subst context t2);
122 with NCicTypeChecker.TypeCheckerFailure _ ->
123 metasenv, subst, NCic.Lambda ("_", argty, NCicSubstitution.lift 1 arg)
125 and beta_expand_many test_equality_only swap metasenv subst context t args =
126 (* (*D*) inside 'B'; try let rc = *)
127 pp (lazy (String.concat ", "
128 (List.map (NCicPp.ppterm ~metasenv ~subst ~context)
129 args) ^ " ∈ " ^ NCicPp.ppterm ~metasenv ~subst ~context t));
130 let _, subst, metasenv, hd =
132 (fun arg (num,subst,metasenv,t) ->
133 let metasenv, subst, t =
134 beta_expand num test_equality_only swap metasenv subst context t arg
136 num+1,subst,metasenv,t)
137 args (1,subst,metasenv,t)
139 pp (lazy ("Head syntesized by b-exp: " ^
140 NCicPp.ppterm ~metasenv ~subst ~context hd));
142 (* (*D*) in outside (); rc with exn -> outside (); raise exn *)
144 and instantiate test_eq_only metasenv subst context n lc t swap =
145 (* (*D*) inside 'I'; try let rc = *)
146 let unify test_eq_only m s c t1 t2 =
147 if swap then unify test_eq_only m s c t2 t1
148 else unify test_eq_only m s c t1 t2
150 let name, ctx, ty = NCicUtils.lookup_meta n metasenv in
151 let metasenv, subst =
153 | NCic.Implicit (`Typeof _) -> metasenv, subst
155 let lty = NCicSubstitution.subst_meta lc ty in
157 try NCicTypeChecker.typeof ~subst ~metasenv context t
158 with NCicTypeChecker.TypeCheckerFailure msg ->
159 prerr_endline (NCicPp.ppterm ~metasenv ~subst ~context t);
160 prerr_endline (Lazy.force msg);
163 pp (lazy("On the types: " ^
164 NCicPp.ppterm ~metasenv ~subst ~context lty ^ " === "
165 ^ NCicPp.ppterm ~metasenv ~subst ~context ty_t));
166 unify test_eq_only metasenv subst context lty ty_t
168 let (metasenv, subst), t =
169 try NCicMetaSubst.delift metasenv subst context n lc t
170 with NCicMetaSubst.Uncertain msg -> raise (Uncertain msg)
171 | NCicMetaSubst.MetaSubstFailure msg -> raise (UnificationFailure msg)
173 (* Unifying the types may have already instantiated n. *)
175 let _, _,oldt,_ = NCicUtils.lookup_subst n subst in
176 let oldt = NCicSubstitution.subst_meta lc oldt in
177 let t = NCicSubstitution.subst_meta lc t in
178 (* conjecture: always fail --> occur check *)
179 unify test_eq_only metasenv subst context oldt t
180 with NCicUtils.Subst_not_found _ ->
181 (* by cumulativity when unify(?,Type_i)
182 * we could ? := Type_j with j <= i... *)
183 let subst = (n, (name, ctx, t, ty)) :: subst in
184 pp (lazy ("?"^string_of_int n^" := "^NCicPp.ppterm
185 ~metasenv ~subst ~context (NCicSubstitution.subst_meta lc t)));
187 List.filter (fun (m,_) -> not (n = m)) metasenv
190 (* (*D*) in outside(); rc with exn -> outside (); raise exn *)
192 and unify test_eq_only metasenv subst context t1 t2 =
193 (* (*D*) inside 'U'; try let rc = *)
194 let fo_unif test_eq_only metasenv subst t1 t2 =
195 (* (*D*) inside 'F'; try let rc = *)
197 pp (lazy(" " ^ NCicPp.ppterm ~metasenv ~subst ~context t1 ^ " === " ^
198 NCicPp.ppterm ~metasenv ~subst ~context t2));
204 | (C.Sort (C.Type a), C.Sort (C.Type b)) when not test_eq_only ->
205 if NCicEnvironment.universe_leq a b then metasenv, subst
206 else raise (fail_exc metasenv subst context t1 t2)
207 | (C.Sort (C.Type a), C.Sort (C.Type b)) ->
208 if NCicEnvironment.universe_eq a b then metasenv, subst
209 else raise (fail_exc metasenv subst context t1 t2)
210 | (C.Sort C.Prop,C.Sort (C.Type _)) ->
211 if (not test_eq_only) then metasenv, subst
212 else raise (fail_exc metasenv subst context t1 t2)
214 | (C.Lambda (name1,s1,t1), C.Lambda(_,s2,t2))
215 | (C.Prod (name1,s1,t1), C.Prod(_,s2,t2)) ->
216 let metasenv, subst = unify true metasenv subst context s1 s2 in
217 unify test_eq_only metasenv subst ((name1, C.Decl s1)::context) t1 t2
218 | (C.LetIn (name1,ty1,s1,t1), C.LetIn(_,ty2,s2,t2)) ->
219 let metasenv,subst=unify test_eq_only metasenv subst context ty1 ty2 in
220 let metasenv,subst=unify test_eq_only metasenv subst context s1 s2 in
221 let context = (name1, C.Def (s1,ty1))::context in
222 unify test_eq_only metasenv subst context t1 t2
224 | (C.Meta (n1,(s1,l1 as lc1)),C.Meta (n2,(s2,l2 as lc2))) when n1 = n2 ->
226 let l1 = NCicUtils.expand_local_context l1 in
227 let l2 = NCicUtils.expand_local_context l2 in
228 let metasenv, subst, to_restrict, _ =
230 (fun t1 t2 (metasenv, subst, to_restrict, i) ->
232 let metasenv, subst =
233 unify test_eq_only metasenv subst context
234 (NCicSubstitution.lift s1 t1) (NCicSubstitution.lift s2 t2)
236 metasenv, subst, to_restrict, i-1
237 with UnificationFailure _ | Uncertain _ ->
238 metasenv, subst, i::to_restrict, i-1)
239 l1 l2 (metasenv, subst, [], List.length l1)
241 let metasenv, subst, _ =
242 NCicMetaSubst.restrict metasenv subst n1 to_restrict
246 | Invalid_argument _ -> assert false
247 | NCicMetaSubst.MetaSubstFailure msg ->
249 let _,_,term,_ = NCicUtils.lookup_subst n1 subst in
250 let term1 = NCicSubstitution.subst_meta lc1 term in
251 let term2 = NCicSubstitution.subst_meta lc2 term in
252 unify test_eq_only metasenv subst context term1 term2
253 with NCicUtils.Subst_not_found _-> raise (UnificationFailure msg))
255 | C.Meta (n,lc), t ->
257 let _,_,term,_ = NCicUtils.lookup_subst n subst in
258 let term = NCicSubstitution.subst_meta lc term in
259 unify test_eq_only metasenv subst context term t
260 with NCicUtils.Subst_not_found _->
261 instantiate test_eq_only metasenv subst context n lc t false)
263 | t, C.Meta (n,lc) ->
265 let _,_,term,_ = NCicUtils.lookup_subst n subst in
266 let term = NCicSubstitution.subst_meta lc term in
267 unify test_eq_only metasenv subst context t term
268 with NCicUtils.Subst_not_found _->
269 instantiate test_eq_only metasenv subst context n lc t true)
271 | NCic.Appl (NCic.Meta (i,l)::args), _ when List.mem_assoc i subst ->
272 let _,_,term,_ = NCicUtils.lookup_subst i subst in
273 let term = NCicSubstitution.subst_meta l term in
274 unify test_eq_only metasenv subst context (mk_appl term args) t2
276 | _, NCic.Appl (NCic.Meta (i,l)::args) when List.mem_assoc i subst ->
277 let _,_,term,_ = NCicUtils.lookup_subst i subst in
278 let term = NCicSubstitution.subst_meta l term in
279 unify test_eq_only metasenv subst context t1 (mk_appl term args)
281 | NCic.Appl (NCic.Meta (i,_)::_ as l1),
282 NCic.Appl (NCic.Meta (j,_)::_ as l2) when i=j ->
285 (fun (metasenv, subst) t1 t2 ->
286 unify test_eq_only metasenv subst context t1 t2)
287 (metasenv,subst) l1 l2
288 with Invalid_argument _ ->
289 raise (fail_exc metasenv subst context t1 t2))
291 | NCic.Appl (NCic.Meta (i,l)::args), _ when not (flexible args) ->
292 (* we verify that none of the args is a Meta,
293 since beta expanding w.r.t a metavariable makes no sense *)
294 let metasenv, subst, beta_expanded =
297 metasenv subst context t2 args
299 unify test_eq_only metasenv subst context
300 (C.Meta (i,l)) beta_expanded
302 | _, NCic.Appl (NCic.Meta (i,l)::args) when not(flexible args) ->
303 let metasenv, subst, beta_expanded =
306 metasenv subst context t1 args
308 unify test_eq_only metasenv subst context
309 beta_expanded (C.Meta (i,l))
311 (* processing this case here we avoid a useless small delta step *)
312 | (C.Appl ((C.Const r1) as _hd1::tl1), C.Appl (C.Const r2::tl2))
314 let relevance = NCicEnvironment.get_relevance r1 in
315 let relevance = match r1 with
316 | Ref.Ref (_,Ref.Con (_,_,lno)) ->
317 let _,relevance = HExtlib.split_nth lno relevance in
318 HExtlib.mk_list false lno @ relevance
321 let metasenv, subst, _ =
324 (fun (metasenv, subst, relevance) t1 t2 ->
326 match relevance with b::tl -> b,tl | _ -> true, [] in
327 let metasenv, subst =
328 try unify test_eq_only metasenv subst context t1 t2
329 with UnificationFailure _ | Uncertain _ when not b ->
332 metasenv, subst, relevance)
333 (metasenv, subst, relevance) tl1 tl2
334 with Invalid_argument _ ->
335 raise (uncert_exc metasenv subst context t1 t2)
339 | (C.Match (Ref.Ref (_,Ref.Ind (_,tyno,_)) as ref1,outtype1,term1,pl1),
340 C.Match (ref2,outtype2,term2,pl2)) ->
341 let _,_,itl,_,_ = NCicEnvironment.get_checked_indtys ref1 in
342 let _,_,ty,_ = List.nth itl tyno in
343 let rec remove_prods ~subst context ty =
344 let ty = NCicReduction.whd ~subst context ty in
347 | C.Prod (name,so,ta) ->
348 remove_prods ~subst ((name,(C.Decl so))::context) ta
352 match remove_prods ~subst [] ty with
353 | C.Sort C.Prop -> true
356 let rec remove_prods ~subst context ty =
357 let ty = NCicReduction.whd ~subst context ty in
360 | C.Prod (name,so,ta) ->
361 remove_prods ~subst ((name,(C.Decl so))::context) ta
364 if not (Ref.eq ref1 ref2) then
365 raise (uncert_exc metasenv subst context t1 t2)
367 let metasenv, subst =
368 unify test_eq_only metasenv subst context outtype1 outtype2 in
369 let metasenv, subst =
370 try unify test_eq_only metasenv subst context term1 term2
371 with UnificationFailure _ | Uncertain _ when is_prop ->
376 (fun (metasenv,subst) ->
377 unify test_eq_only metasenv subst context)
378 (metasenv, subst) pl1 pl2
379 with Invalid_argument _ ->
380 raise (uncert_exc metasenv subst context t1 t2))
381 | (C.Implicit _, _) | (_, C.Implicit _) -> assert false
382 | _ -> raise (uncert_exc metasenv subst context t1 t2)
383 (* (*D*) in outside(); rc with exn -> outside (); raise exn *)
385 let height_of = function
386 | NCic.Const (Ref.Ref (_,Ref.Def h))
387 | NCic.Const (Ref.Ref (_,Ref.Fix (_,_,h)))
388 | NCic.Appl(NCic.Const(Ref.Ref(_,Ref.Def h))::_)
389 | NCic.Appl(NCic.Const(Ref.Ref(_,Ref.Fix (_,_,h)))::_) -> h
392 let put_in_whd m1 m2 =
393 NCicReduction.reduce_machine ~delta:max_int ~subst context m1,
394 NCicReduction.reduce_machine ~delta:max_int ~subst context m2
397 ((_,_,t1,_ as m1, norm1) as x1) ((_,_,t2,_ as m2, norm2) as x2)
399 assert (not (norm1 && norm2));
401 x1,NCicReduction.reduce_machine ~delta:(height_of t2 -1) ~subst context m2
403 NCicReduction.reduce_machine ~delta:(height_of t1 -1) ~subst context m1,x2
405 let h1 = height_of t1 in
406 let h2 = height_of t2 in
407 let delta = if h1 = h2 then max 0 (h1 -1) else min h1 h2 in
408 NCicReduction.reduce_machine ~delta ~subst context m1,
409 NCicReduction.reduce_machine ~delta ~subst context m2
411 let rec unif_machines metasenv subst =
413 | ((k1,e1,t1,s1),norm1 as m1),((k2,e2,t2,s2),norm2 as m2) ->
414 (* (*D*) inside 'M'; try let rc = *)
416 pp (lazy((if are_normal then "*" else " ") ^ " " ^
417 NCicPp.ppterm ~metasenv ~subst ~context (NCicReduction.unwind m1) ^
419 NCicPp.ppterm ~metasenv ~subst ~context (NCicReduction.unwind m2)));
421 let relevance = [] (* TO BE UNDERSTOOD
423 | C.Const r -> NCicEnvironment.get_relevance r
425 let unif_from_stack t1 t2 b metasenv subst =
427 let t1 = NCicReduction.from_stack t1 in
428 let t2 = NCicReduction.from_stack t2 in
429 unif_machines metasenv subst (put_in_whd t1 t2)
430 with UnificationFailure _ | Uncertain _ when not b ->
433 let rec check_stack l1 l2 r (metasenv, subst) =
435 | x1::tl1, x2::tl2, r::tr ->
436 check_stack tl1 tl2 tr
437 (unif_from_stack x1 x2 r metasenv subst)
438 | x1::tl1, x2::tl2, [] ->
439 check_stack tl1 tl2 []
440 (unif_from_stack x1 x2 true metasenv subst)
442 fo_unif test_eq_only metasenv subst
443 (NCicReduction.unwind (k1,e1,t1,List.rev l1))
444 (NCicReduction.unwind (k2,e2,t2,List.rev l2))
446 try check_stack (List.rev s1) (List.rev s2) relevance (metasenv,subst)
447 with UnificationFailure _ | Uncertain _ when not (norm1 && norm2) ->
448 unif_machines metasenv subst (small_delta_step m1 m2)
449 (* (*D*) in outside(); rc with exn -> outside (); raise exn *)
451 try fo_unif test_eq_only metasenv subst t1 t2
452 with UnificationFailure msg | Uncertain msg as exn ->
454 unif_machines metasenv subst
455 (put_in_whd (0,[],t1,[]) (0,[],t2,[]))
457 | UnificationFailure _ -> raise (UnificationFailure msg)
458 | Uncertain _ -> raise exn
459 (* (*D*) in outside(); rc with exn -> outside (); raise exn *)
472 exception UnificationFailure of string Lazy.t;;
473 exception Uncertain of string Lazy.t;;
474 exception AssertFailure of string Lazy.t;;
476 let verbose = false;;
477 let debug_print = fun _ -> ()
479 let profiler_toa = HExtlib.profile "fo_unif_subst.type_of_aux'"
480 let profiler_beta_expand = HExtlib.profile "fo_unif_subst.beta_expand"
481 let profiler_deref = HExtlib.profile "fo_unif_subst.deref'"
482 let profiler_are_convertible = HExtlib.profile "fo_unif_subst.are_convertible"
484 let profile = HExtlib.profile "U/CicTypeChecker.type_of_aux'"
486 let type_of_aux' metasenv subst context term ugraph =
489 profile.HExtlib.profile
490 (CicTypeChecker.type_of_aux' ~subst metasenv context term) ugraph
492 CicTypeChecker.TypeCheckerFailure msg ->
496 "Kernel Type checking error:
497 %s\n%s\ncontext=\n%s\nmetasenv=\n%s\nsubstitution=\n%s\nException:\n%s.\nToo bad."
498 (CicMetaSubst.ppterm ~metasenv subst term)
499 (CicMetaSubst.ppterm ~metasenv [] term)
500 (CicMetaSubst.ppcontext ~metasenv subst context)
501 (CicMetaSubst.ppmetasenv subst metasenv)
502 (CicMetaSubst.ppsubst ~metasenv subst) (Lazy.force msg)) in
503 raise (AssertFailure msg)
504 | CicTypeChecker.AssertFailure msg ->
507 "Kernel Type checking assertion failure:
508 %s\n%s\ncontext=\n%s\nmetasenv=\n%s\nsubstitution=\n%s\nException:\n%s.\nToo bad."
509 (CicMetaSubst.ppterm ~metasenv subst term)
510 (CicMetaSubst.ppterm ~metasenv [] term)
511 (CicMetaSubst.ppcontext ~metasenv subst context)
512 (CicMetaSubst.ppmetasenv subst metasenv)
513 (CicMetaSubst.ppsubst ~metasenv subst) (Lazy.force msg)) in
514 raise (AssertFailure msg)
515 in profiler_toa.HExtlib.profile foo ()
518 let exists_a_meta l =
522 | Cic.Appl (Cic.Meta _::_) -> true
525 let rec deref subst t =
526 let snd (_,a,_) = a in
531 (CicSubstitution.subst_meta
532 l (snd (CicUtil.lookup_subst n subst)))
534 CicUtil.Subst_not_found _ -> t)
535 | Cic.Appl(Cic.Meta(n,l)::args) ->
536 (match deref subst (Cic.Meta(n,l)) with
537 | Cic.Lambda _ as t ->
538 deref subst (CicReduction.head_beta_reduce (Cic.Appl(t::args)))
539 | r -> Cic.Appl(r::args))
540 | Cic.Appl(((Cic.Lambda _) as t)::args) ->
541 deref subst (CicReduction.head_beta_reduce (Cic.Appl(t::args)))
546 let foo () = deref subst t
547 in profiler_deref.HExtlib.profile foo ()
549 exception WrongShape;;
550 let eta_reduce after_beta_expansion after_beta_expansion_body
551 before_beta_expansion
554 match before_beta_expansion,after_beta_expansion_body with
555 Cic.Appl l, Cic.Appl l' ->
556 let rec all_but_last check_last =
560 | [_] -> if check_last then raise WrongShape else []
561 | he::tl -> he::(all_but_last check_last tl)
563 let all_but_last check_last l =
564 match all_but_last check_last l with
569 let t = CicSubstitution.subst (Cic.Rel (-1)) (all_but_last true l') in
570 let all_but_last = all_but_last false l in
571 (* here we should test alpha-equivalence; however we know by
572 construction that here alpha_equivalence is equivalent to = *)
573 if t = all_but_last then
577 | _,_ -> after_beta_expansion
579 WrongShape -> after_beta_expansion
581 let rec beta_expand num test_equality_only metasenv subst context t arg ugraph =
582 let module S = CicSubstitution in
583 let module C = Cic in
585 let rec aux metasenv subst n context t' ugraph =
588 let subst,metasenv,ugraph1 =
589 fo_unif_subst test_equality_only subst context metasenv
590 (CicSubstitution.lift n arg) t' ugraph
593 subst,metasenv,C.Rel (1 + n),ugraph1
596 | UnificationFailure _ ->
598 | C.Rel m -> subst,metasenv,
599 (if m <= n then C.Rel m else C.Rel (m+1)),ugraph
600 | C.Var (uri,exp_named_subst) ->
601 let subst,metasenv,exp_named_subst',ugraph1 =
602 aux_exp_named_subst metasenv subst n context exp_named_subst ugraph
604 subst,metasenv,C.Var (uri,exp_named_subst'),ugraph1
606 (* andrea: in general, beta_expand can create badly typed
607 terms. This happens quite seldom in practice, UNLESS we
608 iterate on the local context. For this reason, we renounce
609 to iterate and just lift *)
613 Some t -> Some (CicSubstitution.lift 1 t)
615 subst, metasenv, C.Meta (i,l), ugraph
617 | C.Implicit _ as t -> subst,metasenv,t,ugraph
619 let subst,metasenv,te',ugraph1 =
620 aux metasenv subst n context te ugraph in
621 let subst,metasenv,ty',ugraph2 =
622 aux metasenv subst n context ty ugraph1 in
623 (* TASSI: sure this is in serial? *)
624 subst,metasenv,(C.Cast (te', ty')),ugraph2
626 let subst,metasenv,s',ugraph1 =
627 aux metasenv subst n context s ugraph in
628 let subst,metasenv,t',ugraph2 =
629 aux metasenv subst (n+1) ((Some (nn, C.Decl s))::context) t
632 (* TASSI: sure this is in serial? *)
633 subst,metasenv,(C.Prod (nn, s', t')),ugraph2
634 | C.Lambda (nn,s,t) ->
635 let subst,metasenv,s',ugraph1 =
636 aux metasenv subst n context s ugraph in
637 let subst,metasenv,t',ugraph2 =
638 aux metasenv subst (n+1) ((Some (nn, C.Decl s))::context) t ugraph1
640 (* TASSI: sure this is in serial? *)
641 subst,metasenv,(C.Lambda (nn, s', t')),ugraph2
642 | C.LetIn (nn,s,ty,t) ->
643 let subst,metasenv,s',ugraph1 =
644 aux metasenv subst n context s ugraph in
645 let subst,metasenv,ty',ugraph1 =
646 aux metasenv subst n context ty ugraph in
647 let subst,metasenv,t',ugraph2 =
648 aux metasenv subst (n+1) ((Some (nn, C.Def (s,ty)))::context) t
651 (* TASSI: sure this is in serial? *)
652 subst,metasenv,(C.LetIn (nn, s', ty', t')),ugraph2
654 let subst,metasenv,revl',ugraph1 =
656 (fun (subst,metasenv,appl,ugraph) t ->
657 let subst,metasenv,t',ugraph1 =
658 aux metasenv subst n context t ugraph in
659 subst,metasenv,(t'::appl),ugraph1
660 ) (subst,metasenv,[],ugraph) l
662 subst,metasenv,(C.Appl (List.rev revl')),ugraph1
663 | C.Const (uri,exp_named_subst) ->
664 let subst,metasenv,exp_named_subst',ugraph1 =
665 aux_exp_named_subst metasenv subst n context exp_named_subst ugraph
667 subst,metasenv,(C.Const (uri,exp_named_subst')),ugraph1
668 | C.MutInd (uri,i,exp_named_subst) ->
669 let subst,metasenv,exp_named_subst',ugraph1 =
670 aux_exp_named_subst metasenv subst n context exp_named_subst ugraph
672 subst,metasenv,(C.MutInd (uri,i,exp_named_subst')),ugraph1
673 | C.MutConstruct (uri,i,j,exp_named_subst) ->
674 let subst,metasenv,exp_named_subst',ugraph1 =
675 aux_exp_named_subst metasenv subst n context exp_named_subst ugraph
677 subst,metasenv,(C.MutConstruct (uri,i,j,exp_named_subst')),ugraph1
678 | C.MutCase (sp,i,outt,t,pl) ->
679 let subst,metasenv,outt',ugraph1 =
680 aux metasenv subst n context outt ugraph in
681 let subst,metasenv,t',ugraph2 =
682 aux metasenv subst n context t ugraph1 in
683 let subst,metasenv,revpl',ugraph3 =
685 (fun (subst,metasenv,pl,ugraph) t ->
686 let subst,metasenv,t',ugraph1 =
687 aux metasenv subst n context t ugraph in
688 subst,metasenv,(t'::pl),ugraph1
689 ) (subst,metasenv,[],ugraph2) pl
691 subst,metasenv,(C.MutCase (sp,i,outt', t', List.rev revpl')),ugraph3
692 (* TASSI: not sure this is serial *)
694 (*CSC: not implemented
695 let tylen = List.length fl in
698 (fun (name,i,ty,bo) -> (name, i, aux n ty, aux (n+tylen) bo))
701 C.Fix (i, substitutedfl)
703 subst,metasenv,(CicSubstitution.lift 1 t' ),ugraph
705 (*CSC: not implemented
706 let tylen = List.length fl in
709 (fun (name,ty,bo) -> (name, aux n ty, aux (n+tylen) bo))
712 C.CoFix (i, substitutedfl)
715 subst,metasenv,(CicSubstitution.lift 1 t'), ugraph
717 and aux_exp_named_subst metasenv subst n context ens ugraph =
719 (fun (uri,t) (subst,metasenv,l,ugraph) ->
720 let subst,metasenv,t',ugraph1 = aux metasenv subst n context t ugraph in
721 subst,metasenv,((uri,t')::l),ugraph1) ens (subst,metasenv,[],ugraph)
723 let argty,ugraph1 = type_of_aux' metasenv subst context arg ugraph in
725 FreshNamesGenerator.mk_fresh_name ~subst
726 metasenv context (Cic.Name ("Hbeta" ^ string_of_int num)) ~typ:argty
728 let subst,metasenv,t',ugraph2 = aux metasenv subst 0 context t ugraph1 in
729 let t'' = eta_reduce (C.Lambda (fresh_name,argty,t')) t' t in
730 subst, metasenv, t'', ugraph2
731 in profiler_beta_expand.HExtlib.profile foo ()
734 and beta_expand_many test_equality_only metasenv subst context t args ugraph =
735 let _,subst,metasenv,hd,ugraph =
737 (fun arg (num,subst,metasenv,t,ugraph) ->
738 let subst,metasenv,t,ugraph1 =
739 beta_expand num test_equality_only
740 metasenv subst context t arg ugraph
742 num+1,subst,metasenv,t,ugraph1
743 ) args (1,subst,metasenv,t,ugraph)
745 subst,metasenv,hd,ugraph
747 and warn_if_not_unique xxx to1 to2 carr car1 car2 =
750 | (m2,_,c2,c2')::_ ->
751 let m1,c1,c1' = carr,to1,to2 in
753 function Some (_,t) -> CicPp.ppterm t
757 ("There are two minimal joins of "^ CoercDb.string_of_carr car1^" and "^
758 CoercDb.string_of_carr car2^": " ^
759 CoercDb.string_of_carr m1^" via "^unopt c1^" + "^
760 unopt c1'^" and "^ CoercDb.string_of_carr m2^" via "^
761 unopt c2^" + "^unopt c2')
763 (* NUOVA UNIFICAZIONE *)
764 (* A substitution is a (int * Cic.term) list that associates a
765 metavariable i with its body.
766 A metaenv is a (int * Cic.term) list that associate a metavariable
768 fo_unif_new takes a metasenv, a context, two terms t1 and t2 and gives back
769 a new substitution which is _NOT_ unwinded. It must be unwinded before
772 and fo_unif_subst test_equality_only subst context metasenv t1 t2 ugraph =
773 let module C = Cic in
774 let module R = CicReduction in
775 let module S = CicSubstitution in
776 let t1 = deref subst t1 in
777 let t2 = deref subst t2 in
778 let (&&&) a b = (a && b) || ((not a) && (not b)) in
779 (* let bef = Sys.time () in *)
781 if not (CicUtil.is_meta_closed (CicMetaSubst.apply_subst subst t1) &&& CicUtil.is_meta_closed (CicMetaSubst.apply_subst subst t2)) then
785 R.are_convertible ~subst ~metasenv context t1 t2 ugraph
786 in profiler_are_convertible.HExtlib.profile foo ()
788 (* let aft = Sys.time () in
789 if (aft -. bef > 2.0) then prerr_endline ("LEEEENTO: " ^
790 CicMetaSubst.ppterm_in_context subst ~metasenv t1 context ^ " <===> " ^
791 CicMetaSubst.ppterm_in_context subst ~metasenv t2 context); *)
793 subst, metasenv, ugraph
796 | (C.Meta (n,ln), C.Meta (m,lm)) when n=m ->
797 let _,subst,metasenv,ugraph1 =
800 (fun (j,subst,metasenv,ugraph) t1 t2 ->
803 | _,None -> j+1,subst,metasenv,ugraph
804 | Some t1', Some t2' ->
805 (* First possibility: restriction *)
806 (* Second possibility: unification *)
807 (* Third possibility: convertibility *)
810 ~subst ~metasenv context t1' t2' ugraph
813 j+1,subst,metasenv, ugraph1
816 let subst,metasenv,ugraph2 =
819 subst context metasenv t1' t2' ugraph
821 j+1,subst,metasenv,ugraph2
824 | UnificationFailure _ ->
825 debug_print (lazy ("restringo Meta n." ^ (string_of_int n) ^ "on variable n." ^ (string_of_int j)));
826 let metasenv, subst =
827 CicMetaSubst.restrict
828 subst [(n,j)] metasenv in
829 j+1,subst,metasenv,ugraph1)
830 ) (1,subst,metasenv,ugraph) ln lm
834 (UnificationFailure (lazy "1"))
837 "Error trying to unify %s with %s: the algorithm tried to check whether the two substitutions are convertible; if they are not, it tried to unify the two substitutions. No restriction was attempted."
838 (CicMetaSubst.ppterm ~metasenv subst t1)
839 (CicMetaSubst.ppterm ~metasenv subst t2))) *)
840 | Invalid_argument _ ->
842 (UnificationFailure (lazy "2")))
845 "Error trying to unify %s with %s: the lengths of the two local contexts do not match."
846 (CicMetaSubst.ppterm ~metasenv subst t1)
847 (CicMetaSubst.ppterm ~metasenv subst t2)))) *)
848 in subst,metasenv,ugraph1
849 | (C.Meta (n,_), C.Meta (m,_)) when n>m ->
850 fo_unif_subst test_equality_only subst context metasenv t2 t1 ugraph
852 | (t, C.Meta (n,l)) ->
855 C.Meta (n,_), C.Meta (m,_) when n < m -> false
856 | _, C.Meta _ -> false
859 let lower = fun x y -> if swap then y else x in
860 let upper = fun x y -> if swap then x else y in
861 let fo_unif_subst_ordered
862 test_equality_only subst context metasenv m1 m2 ugraph =
863 fo_unif_subst test_equality_only subst context metasenv
864 (lower m1 m2) (upper m1 m2) ugraph
867 let subst,metasenv,ugraph1 =
868 let (_,_,meta_type) = CicUtil.lookup_meta n metasenv in
871 type_of_aux' metasenv subst context t ugraph
875 subst context metasenv tyt (S.subst_meta l meta_type) ugraph1
877 UnificationFailure _ as e -> raise e
878 | Uncertain msg -> raise (UnificationFailure msg)
880 debug_print (lazy "siamo allo huge hack");
881 (* TODO huge hack!!!!
882 * we keep on unifying/refining in the hope that
883 * the problem will be eventually solved.
884 * In the meantime we're breaking a big invariant:
885 * the terms that we are unifying are no longer well
886 * typed in the current context (in the worst case
887 * we could even diverge) *)
888 (subst, metasenv,ugraph)) in
889 let t',metasenv,subst =
891 CicMetaSubst.delift n subst context metasenv l t
893 (CicMetaSubst.MetaSubstFailure msg)->
894 raise (UnificationFailure msg)
895 | (CicMetaSubst.Uncertain msg) -> raise (Uncertain msg)
899 C.Sort (C.Type u) when not test_equality_only ->
900 let u' = CicUniv.fresh () in
901 let s = C.Sort (C.Type u') in
904 CicUniv.add_ge (upper u u') (lower u u') ugraph1
908 CicUniv.UniverseInconsistency msg ->
909 raise (UnificationFailure msg))
912 (* Unifying the types may have already instantiated n. Let's check *)
914 let (_, oldt,_) = CicUtil.lookup_subst n subst in
915 let lifted_oldt = S.subst_meta l oldt in
916 fo_unif_subst_ordered
917 test_equality_only subst context metasenv t lifted_oldt ugraph2
919 CicUtil.Subst_not_found _ ->
920 let (_, context, ty) = CicUtil.lookup_meta n metasenv in
921 let subst = (n, (context, t'',ty)) :: subst in
923 List.filter (fun (m,_,_) -> not (n = m)) metasenv in
924 subst, metasenv, ugraph2
926 | (C.Var (uri1,exp_named_subst1),C.Var (uri2,exp_named_subst2))
927 | (C.Const (uri1,exp_named_subst1),C.Const (uri2,exp_named_subst2)) ->
928 if UriManager.eq uri1 uri2 then
929 fo_unif_subst_exp_named_subst test_equality_only subst context metasenv
930 exp_named_subst1 exp_named_subst2 ugraph
932 raise (UnificationFailure (lazy
934 "Can't unify %s with %s due to different constants"
935 (CicMetaSubst.ppterm ~metasenv subst t1)
936 (CicMetaSubst.ppterm ~metasenv subst t2))))
937 | C.MutInd (uri1,i1,exp_named_subst1),C.MutInd (uri2,i2,exp_named_subst2) ->
938 if UriManager.eq uri1 uri2 && i1 = i2 then
939 fo_unif_subst_exp_named_subst
941 subst context metasenv exp_named_subst1 exp_named_subst2 ugraph
943 raise (UnificationFailure
946 "Can't unify %s with %s due to different inductive principles"
947 (CicMetaSubst.ppterm ~metasenv subst t1)
948 (CicMetaSubst.ppterm ~metasenv subst t2))))
949 | C.MutConstruct (uri1,i1,j1,exp_named_subst1),
950 C.MutConstruct (uri2,i2,j2,exp_named_subst2) ->
951 if UriManager.eq uri1 uri2 && i1 = i2 && j1 = j2 then
952 fo_unif_subst_exp_named_subst
954 subst context metasenv exp_named_subst1 exp_named_subst2 ugraph
956 raise (UnificationFailure
959 "Can't unify %s with %s due to different inductive constructors"
960 (CicMetaSubst.ppterm ~metasenv subst t1)
961 (CicMetaSubst.ppterm ~metasenv subst t2))))
962 | (C.Implicit _, _) | (_, C.Implicit _) -> assert false
963 | (C.Cast (te,ty), t2) -> fo_unif_subst test_equality_only
964 subst context metasenv te t2 ugraph
965 | (t1, C.Cast (te,ty)) -> fo_unif_subst test_equality_only
966 subst context metasenv t1 te ugraph
967 | (C.Lambda (n1,s1,t1), C.Lambda (_,s2,t2)) ->
968 let subst',metasenv',ugraph1 =
969 fo_unif_subst test_equality_only subst context metasenv s1 s2 ugraph
971 fo_unif_subst test_equality_only
972 subst' ((Some (n1,(C.Decl s1)))::context) metasenv' t1 t2 ugraph1
973 | (C.LetIn (_,s1,ty1,t1), t2)
974 | (t2, C.LetIn (_,s1,ty1,t1)) ->
976 test_equality_only subst context metasenv t2 (S.subst s1 t1) ugraph
977 | (C.Appl l1, C.Appl l2) ->
978 (* andrea: this case should be probably rewritten in the
981 | C.Meta (i,_)::args1, C.Meta (j,_)::args2 when i = j ->
984 (fun (subst,metasenv,ugraph) t1 t2 ->
986 test_equality_only subst context metasenv t1 t2 ugraph)
987 (subst,metasenv,ugraph) l1 l2
988 with (Invalid_argument msg) ->
989 raise (UnificationFailure (lazy msg)))
990 | C.Meta (i,l)::args, _ when not(exists_a_meta args) ->
991 (* we verify that none of the args is a Meta,
992 since beta expanding with respoect to a metavariable
996 let (_,t,_) = CicUtil.lookup_subst i subst in
997 let lifted = S.subst_meta l t in
998 let reduced = CicReduction.head_beta_reduce (Cic.Appl (lifted::args)) in
1001 subst context metasenv reduced t2 ugraph
1002 with CicUtil.Subst_not_found _ -> *)
1003 let subst,metasenv,beta_expanded,ugraph1 =
1005 test_equality_only metasenv subst context t2 args ugraph
1007 fo_unif_subst test_equality_only subst context metasenv
1008 (C.Meta (i,l)) beta_expanded ugraph1
1009 | _, C.Meta (i,l)::args when not(exists_a_meta args) ->
1011 let (_,t,_) = CicUtil.lookup_subst i subst in
1012 let lifted = S.subst_meta l t in
1013 let reduced = CicReduction.head_beta_reduce (Cic.Appl (lifted::args)) in
1016 subst context metasenv t1 reduced ugraph
1017 with CicUtil.Subst_not_found _ -> *)
1018 let subst,metasenv,beta_expanded,ugraph1 =
1021 metasenv subst context t1 args ugraph
1023 fo_unif_subst test_equality_only subst context metasenv
1024 (C.Meta (i,l)) beta_expanded ugraph1
1026 let lr1 = List.rev l1 in
1027 let lr2 = List.rev l2 in
1029 fo_unif_l test_equality_only subst metasenv (l1,l2) ugraph =
1032 | _,[] -> assert false
1035 test_equality_only subst context metasenv h1 h2 ugraph
1038 fo_unif_subst test_equality_only subst context metasenv
1039 h (C.Appl (List.rev l)) ugraph
1040 | ((h1::l1),(h2::l2)) ->
1041 let subst', metasenv',ugraph1 =
1044 subst context metasenv h1 h2 ugraph
1047 test_equality_only subst' metasenv' (l1,l2) ugraph1
1051 test_equality_only subst metasenv (lr1, lr2) ugraph
1053 | UnificationFailure s
1054 | Uncertain s as exn ->
1057 | (((Cic.Const (uri1, ens1)) as cc1) :: tl1),
1058 (((Cic.Const (uri2, ens2)) as cc2) :: tl2) when
1059 CoercDb.is_a_coercion cc1 <> None &&
1060 CoercDb.is_a_coercion cc2 <> None &&
1061 not (UriManager.eq uri1 uri2) ->
1063 prerr_endline ("<<<< " ^ CicMetaSubst.ppterm_in_context ~metasenv subst (C.Appl l1) context ^ " <==> " ^ CicMetaSubst.ppterm_in_context ~metasenv subst (C.Appl l2) context);
1065 let inner_coerced t =
1066 let t = CicMetaSubst.apply_subst subst t in
1070 (match CoercGraph.coerced_arg l with
1072 | Some (t,_) -> aux (List.hd l) t t)
1075 aux (Cic.Implicit None) (Cic.Implicit None) t
1077 let c1,last_tl1 = inner_coerced (Cic.Appl l1) in
1078 let c2,last_tl2 = inner_coerced (Cic.Appl l2) in
1081 CoercDb.is_a_coercion c1, CoercDb.is_a_coercion c2
1083 | Some (s1,_,_,_,_), Some (s2,_,_,_,_) -> s1, s2
1086 let head1_c, head2_c =
1088 CoercDb.is_a_coercion cc1, CoercDb.is_a_coercion cc2
1090 | Some (_,t1,_,_,_), Some (_,t2,_,_,_) -> t1, t2
1093 let unfold uri ens args =
1095 CicEnvironment.get_obj CicUniv.oblivion_ugraph uri
1099 | Cic.Constant (_,Some bo,_,_,_) ->
1100 CicReduction.head_beta_reduce ~delta:false
1101 (Cic.Appl (bo::args))
1104 let conclude subst metasenv ugraph last_tl1' last_tl2' =
1105 let subst',metasenv,ugraph =
1108 ("OK " ^ CicMetaSubst.ppterm_in_context ~metasenv subst last_tl1' context ^
1109 " <==> " ^ CicMetaSubst.ppterm_in_context ~metasenv subst last_tl2' context);
1111 fo_unif_subst test_equality_only subst context
1112 metasenv last_tl1' last_tl2' ugraph
1114 if subst = subst' then raise exn
1117 let subst,metasenv,ugrph as res =
1119 fo_unif_subst test_equality_only subst' context
1120 metasenv (C.Appl l1) (C.Appl l2) ugraph
1124 (">>>> "^CicMetaSubst.ppterm_in_context ~metasenv subst (C.Appl l1) context ^
1125 " <==> "^CicMetaSubst.ppterm_in_context ~metasenv subst (C.Appl l2) context);
1129 if CoercDb.eq_carr car1 car2 then
1130 match last_tl1,last_tl2 with
1131 | C.Meta (i1,_),C.Meta(i2,_) when i1 = i2 -> raise exn
1134 let subst,metasenv,ugraph =
1135 fo_unif_subst test_equality_only subst context
1136 metasenv last_tl1 last_tl2 ugraph
1138 fo_unif_subst test_equality_only subst context
1139 metasenv (Cic.Appl l1) (Cic.Appl l2) ugraph
1140 | _ when CoercDb.eq_carr head1_c head2_c ->
1141 (* composite VS composition + metas avoiding
1142 * coercions not only in coerced position *)
1143 if c1 <> cc1 && c2 <> cc2 then
1144 conclude subst metasenv ugraph
1149 unfold uri1 ens1 tl1, Cic.Appl (cc2::tl2)
1151 Cic.Appl (cc1::tl1), unfold uri2 ens2 tl2
1153 fo_unif_subst test_equality_only subst context
1154 metasenv l1 l2 ugraph
1158 match last_tl1 with Cic.Meta _ -> true | _ -> false in
1160 match last_tl2 with Cic.Meta _ -> true | _ -> false in
1161 if not (grow1 || grow2) then
1162 (* no flexible terminals -> no pullback, but
1163 * we still unify them, in some cases it helps *)
1164 conclude subst metasenv ugraph last_tl1 last_tl2
1168 metasenv subst context (grow1,car1) (grow2,car2)
1172 | (carr,metasenv,to1,to2)::xxx ->
1173 warn_if_not_unique xxx to1 to2 carr car1 car2;
1174 let last_tl1',(subst,metasenv,ugraph) =
1175 match grow1,to1 with
1176 | true,Some (last,coerced) ->
1178 fo_unif_subst test_equality_only subst context
1179 metasenv coerced last_tl1 ugraph
1180 | _ -> last_tl1,(subst,metasenv,ugraph)
1182 let last_tl2',(subst,metasenv,ugraph) =
1183 match grow2,to2 with
1184 | true,Some (last,coerced) ->
1186 fo_unif_subst test_equality_only subst context
1187 metasenv coerced last_tl2 ugraph
1188 | _ -> last_tl2,(subst,metasenv,ugraph)
1190 conclude subst metasenv ugraph last_tl1' last_tl2')
1192 (* {{{ CSC: This is necessary because of the "elim H" tactic
1193 where the type of H is only reducible to an
1194 inductive type. This could be extended from inductive
1195 types to any rigid term. However, the code is
1196 duplicated in two places: inside applications and
1197 outside them. Probably it would be better to
1198 work with lambda-bar terms instead. *)
1199 | (Cic.MutInd _::_, Cic.MutInd _::_) -> raise exn
1200 | (_, Cic.MutInd _::_) ->
1201 let t1' = R.whd ~subst context t1 in
1203 C.Appl (C.MutInd _::_) ->
1204 fo_unif_subst test_equality_only
1205 subst context metasenv t1' t2 ugraph
1206 | _ -> raise (UnificationFailure (lazy "88")))
1207 | (Cic.MutInd _::_,_) ->
1208 let t2' = R.whd ~subst context t2 in
1210 C.Appl (C.MutInd _::_) ->
1211 fo_unif_subst test_equality_only
1212 subst context metasenv t1 t2' ugraph
1215 (lazy ("not a mutind :"^
1216 CicMetaSubst.ppterm ~metasenv subst t2 ))))
1219 | (C.MutCase (_,_,outt1,t1',pl1), C.MutCase (_,_,outt2,t2',pl2))->
1220 let subst', metasenv',ugraph1 =
1221 fo_unif_subst test_equality_only subst context metasenv outt1 outt2
1223 let subst'',metasenv'',ugraph2 =
1224 fo_unif_subst test_equality_only subst' context metasenv' t1' t2'
1228 (fun (subst,metasenv,ugraph) t1 t2 ->
1230 test_equality_only subst context metasenv t1 t2 ugraph
1231 ) (subst'',metasenv'',ugraph2) pl1 pl2
1233 Invalid_argument _ ->
1234 raise (UnificationFailure (lazy "6.1")))
1236 "Error trying to unify %s with %s: the number of branches is not the same."
1237 (CicMetaSubst.ppterm ~metasenv subst t1)
1238 (CicMetaSubst.ppterm ~metasenv subst t2)))) *)
1239 | (C.Rel _, _) | (_, C.Rel _) ->
1241 subst, metasenv,ugraph
1243 raise (UnificationFailure (lazy
1245 "Can't unify %s with %s because they are not convertible"
1246 (CicMetaSubst.ppterm ~metasenv subst t1)
1247 (CicMetaSubst.ppterm ~metasenv subst t2))))
1248 | (C.Appl (C.Meta(i,l)::args),t2) when not(exists_a_meta args) ->
1249 let subst,metasenv,beta_expanded,ugraph1 =
1251 test_equality_only metasenv subst context t2 args ugraph
1253 fo_unif_subst test_equality_only subst context metasenv
1254 (C.Meta (i,l)) beta_expanded ugraph1
1255 | (t1,C.Appl (C.Meta(i,l)::args)) when not(exists_a_meta args) ->
1256 let subst,metasenv,beta_expanded,ugraph1 =
1258 test_equality_only metasenv subst context t1 args ugraph
1260 fo_unif_subst test_equality_only subst context metasenv
1261 beta_expanded (C.Meta (i,l)) ugraph1
1262 (* Works iff there are no arguments applied to it; similar to the
1264 | (_, C.MutInd _) ->
1265 let t1' = R.whd ~subst context t1 in
1268 fo_unif_subst test_equality_only
1269 subst context metasenv t1' t2 ugraph
1270 | _ -> raise (UnificationFailure (lazy "8")))
1272 | (C.Prod (n1,s1,t1), C.Prod (_,s2,t2)) ->
1273 let subst',metasenv',ugraph1 =
1274 fo_unif_subst true subst context metasenv s1 s2 ugraph
1276 fo_unif_subst test_equality_only
1277 subst' ((Some (n1,(C.Decl s1)))::context) metasenv' t1 t2 ugraph1
1279 (match CicReduction.whd ~subst context t2 with
1281 fo_unif_subst test_equality_only subst context metasenv t1 t2 ugraph
1282 | _ -> raise (UnificationFailure (lazy (CicMetaSubst.ppterm ~metasenv subst t2^"Not a product"))))
1284 (match CicReduction.whd ~subst context t1 with
1286 fo_unif_subst test_equality_only subst context metasenv t1 t2 ugraph
1287 | _ -> raise (UnificationFailure (lazy (CicMetaSubst.ppterm ~metasenv subst t1^"Not a product"))))
1289 (* delta-beta reduction should almost never be a problem for
1291 1. long computations require iota reduction
1292 2. it is extremely rare that a close term t1 (that could be unified
1293 to t2) beta-delta reduces to t1' while t2 does not beta-delta
1294 reduces in the same way. This happens only if one meta of t2
1295 occurs in head position during beta reduction. In this unluky
1296 case too much reduction will be performed on t1 and unification
1297 will surely fail. *)
1298 let t1' = CicReduction.head_beta_reduce ~delta:true t1 in
1299 let t2' = CicReduction.head_beta_reduce ~delta:true t2 in
1300 if t1 = t1' && t2 = t2' then
1301 raise (UnificationFailure
1304 "Can't unify %s with %s because they are not convertible"
1305 (CicMetaSubst.ppterm ~metasenv subst t1)
1306 (CicMetaSubst.ppterm ~metasenv subst t2))))
1309 fo_unif_subst test_equality_only subst context metasenv t1' t2' ugraph
1311 UnificationFailure _
1313 raise (UnificationFailure
1316 "Can't unify %s with %s because they are not convertible"
1317 (CicMetaSubst.ppterm ~metasenv subst t1)
1318 (CicMetaSubst.ppterm ~metasenv subst t2))))
1320 and fo_unif_subst_exp_named_subst test_equality_only subst context metasenv
1321 exp_named_subst1 exp_named_subst2 ugraph
1325 (fun (subst,metasenv,ugraph) (uri1,t1) (uri2,t2) ->
1326 assert (uri1=uri2) ;
1327 fo_unif_subst test_equality_only subst context metasenv t1 t2 ugraph
1328 ) (subst,metasenv,ugraph) exp_named_subst1 exp_named_subst2
1330 Invalid_argument _ ->
1335 UriManager.string_of_uri uri ^ " := " ^ (CicMetaSubst.ppterm ~metasenv subst t)
1338 raise (UnificationFailure (lazy (sprintf
1339 "Error trying to unify the two explicit named substitutions (local contexts) %s and %s: their lengths is different." (print_ens exp_named_subst1) (print_ens exp_named_subst2))))
1341 (* A substitution is a (int * Cic.term) list that associates a *)
1342 (* metavariable i with its body. *)
1343 (* metasenv is of type Cic.metasenv *)
1344 (* fo_unif takes a metasenv, a context, two terms t1 and t2 and gives back *)
1345 (* a new substitution which is already unwinded and ready to be applied and *)
1346 (* a new metasenv in which some hypothesis in the contexts of the *)
1347 (* metavariables may have been restricted. *)
1348 let fo_unif metasenv context t1 t2 ugraph =
1349 fo_unif_subst false [] context metasenv t1 t2 ugraph ;;
1351 let enrich_msg msg subst context metasenv t1 t2 ugraph =
1354 sprintf "[Verbose] Unification error unifying %s of type %s with %s of type %s in context\n%s\nand metasenv\n%s\nand substitution\n%s\nbecause %s"
1355 (CicMetaSubst.ppterm ~metasenv subst t1)
1357 let ty_t1,_ = type_of_aux' metasenv subst context t1 ugraph in
1360 | UnificationFailure s
1362 | AssertFailure s -> sprintf "MALFORMED(t1): \n<BEGIN>%s\n<END>" (Lazy.force s))
1363 (CicMetaSubst.ppterm ~metasenv subst t2)
1365 let ty_t2,_ = type_of_aux' metasenv subst context t2 ugraph in
1368 | UnificationFailure s
1370 | AssertFailure s -> sprintf "MALFORMED(t2): \n<BEGIN>%s\n<END>" (Lazy.force s))
1371 (CicMetaSubst.ppcontext ~metasenv subst context)
1372 (CicMetaSubst.ppmetasenv subst metasenv)
1373 (CicMetaSubst.ppsubst ~metasenv subst) (Lazy.force msg)
1375 sprintf "Unification error unifying %s of type %s with %s of type %s in context\n%s\nand metasenv\n%s\nbecause %s"
1376 (CicMetaSubst.ppterm_in_context ~metasenv subst t1 context)
1378 let ty_t1,_ = type_of_aux' metasenv subst context t1 ugraph in
1379 CicMetaSubst.ppterm_in_context ~metasenv subst ty_t1 context
1381 | UnificationFailure s
1383 | AssertFailure s -> sprintf "MALFORMED(t1): \n<BEGIN>%s\n<END>" (Lazy.force s))
1384 (CicMetaSubst.ppterm_in_context ~metasenv subst t2 context)
1386 let ty_t2,_ = type_of_aux' metasenv subst context t2 ugraph in
1387 CicMetaSubst.ppterm_in_context ~metasenv subst ty_t2 context
1389 | UnificationFailure s
1391 | AssertFailure s -> sprintf "MALFORMED(t2): \n<BEGIN>%s\n<END>" (Lazy.force s))
1392 (CicMetaSubst.ppcontext ~metasenv subst context)
1393 (CicMetaSubst.ppmetasenv subst metasenv)
1397 let fo_unif_subst subst context metasenv t1 t2 ugraph =
1399 fo_unif_subst false subst context metasenv t1 t2 ugraph
1401 | AssertFailure msg ->
1402 raise (AssertFailure (enrich_msg msg subst context metasenv t1 t2 ugraph))
1403 | UnificationFailure msg ->
1404 raise (UnificationFailure (enrich_msg msg subst context metasenv t1 t2 ugraph))