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
151 try NCicTypeChecker.typeof ~subst ~metasenv context t
152 with NCicTypeChecker.TypeCheckerFailure msg ->
153 prerr_endline (NCicPp.ppterm ~metasenv ~subst ~context t);
154 prerr_endline (Lazy.force msg);
157 let name, ctx, ty = NCicUtils.lookup_meta n metasenv in
158 let lty = NCicSubstitution.subst_meta lc ty in
159 pp (lazy("On the types: " ^
160 NCicPp.ppterm ~metasenv ~subst ~context lty ^ " === "
161 ^ NCicPp.ppterm ~metasenv ~subst ~context ty_t));
162 let metasenv, subst = unify test_eq_only metasenv subst context lty ty_t in
163 let (metasenv, subst), t =
164 try NCicMetaSubst.delift metasenv subst context n lc t
165 with NCicMetaSubst.Uncertain msg -> raise (Uncertain msg)
166 | NCicMetaSubst.MetaSubstFailure msg -> raise (UnificationFailure msg)
168 (* Unifying the types may have already instantiated n. *)
170 let _, _,oldt,_ = NCicUtils.lookup_subst n subst in
171 let oldt = NCicSubstitution.subst_meta lc oldt in
172 (* conjecture: always fail --> occur check *)
173 unify test_eq_only metasenv subst context oldt t
174 with NCicUtils.Subst_not_found _ ->
175 (* by cumulativity when unify(?,Type_i)
176 * we could ? := Type_j with j <= i... *)
177 let subst = (n, (name, ctx, t, ty)) :: subst in
178 pp (lazy ("?"^string_of_int n^" := "^NCicPp.ppterm
179 ~metasenv ~subst ~context:ctx (NCicSubstitution.subst_meta lc t)));
181 List.filter (fun (m,_) -> not (n = m)) metasenv
184 (* (*D*) in outside(); rc with exn -> outside (); raise exn *)
186 and unify test_eq_only metasenv subst context t1 t2 =
187 (* (*D*) inside 'U'; try let rc = *)
188 let fo_unif test_eq_only metasenv subst t1 t2 =
189 (* (*D*) inside 'F'; try let rc = *)
191 pp (lazy(" " ^ NCicPp.ppterm ~metasenv ~subst ~context t1 ^ " === " ^
192 NCicPp.ppterm ~metasenv ~subst ~context t2));
198 | (C.Sort (C.Type a), C.Sort (C.Type b)) when not test_eq_only ->
199 if NCicEnvironment.universe_leq a b then metasenv, subst
200 else raise (fail_exc metasenv subst context t1 t2)
201 | (C.Sort (C.Type a), C.Sort (C.Type b)) ->
202 if NCicEnvironment.universe_eq a b then metasenv, subst
203 else raise (fail_exc metasenv subst context t1 t2)
204 | (C.Sort C.Prop,C.Sort (C.Type _)) ->
205 if (not test_eq_only) then metasenv, subst
206 else raise (fail_exc metasenv subst context t1 t2)
208 | (C.Lambda (name1,s1,t1), C.Lambda(_,s2,t2))
209 | (C.Prod (name1,s1,t1), C.Prod(_,s2,t2)) ->
210 let metasenv, subst = unify true metasenv subst context s1 s2 in
211 unify test_eq_only metasenv subst ((name1, C.Decl s1)::context) t1 t2
212 | (C.LetIn (name1,ty1,s1,t1), C.LetIn(_,ty2,s2,t2)) ->
213 let metasenv,subst=unify test_eq_only metasenv subst context ty1 ty2 in
214 let metasenv,subst=unify test_eq_only metasenv subst context s1 s2 in
215 let context = (name1, C.Def (s1,ty1))::context in
216 unify test_eq_only metasenv subst context t1 t2
218 | (C.Meta (n1,(s1,l1 as lc1)),C.Meta (n2,(s2,l2 as lc2))) when n1 = n2 ->
220 let l1 = NCicUtils.expand_local_context l1 in
221 let l2 = NCicUtils.expand_local_context l2 in
222 let metasenv, subst, to_restrict, _ =
224 (fun t1 t2 (metasenv, subst, to_restrict, i) ->
226 let metasenv, subst =
227 unify test_eq_only metasenv subst context
228 (NCicSubstitution.lift s1 t1) (NCicSubstitution.lift s2 t2)
230 metasenv, subst, to_restrict, i-1
231 with UnificationFailure _ | Uncertain _ ->
232 metasenv, subst, i::to_restrict, i-1)
233 l1 l2 (metasenv, subst, [], List.length l1)
235 let metasenv, subst, _ =
236 NCicMetaSubst.restrict metasenv subst n1 to_restrict
240 | Invalid_argument _ -> assert false
241 | NCicMetaSubst.MetaSubstFailure msg ->
243 let _,_,term,_ = NCicUtils.lookup_subst n1 subst in
244 let term1 = NCicSubstitution.subst_meta lc1 term in
245 let term2 = NCicSubstitution.subst_meta lc2 term in
246 unify test_eq_only metasenv subst context term1 term2
247 with NCicUtils.Subst_not_found _-> raise (UnificationFailure msg))
249 | C.Meta (n,lc), t ->
251 let _,_,term,_ = NCicUtils.lookup_subst n subst in
252 let term = NCicSubstitution.subst_meta lc term in
253 unify test_eq_only metasenv subst context term t
254 with NCicUtils.Subst_not_found _->
255 instantiate test_eq_only metasenv subst context n lc t false)
257 | t, C.Meta (n,lc) ->
259 let _,_,term,_ = NCicUtils.lookup_subst n subst in
260 let term = NCicSubstitution.subst_meta lc term in
261 unify test_eq_only metasenv subst context t term
262 with NCicUtils.Subst_not_found _->
263 instantiate test_eq_only metasenv subst context n lc t true)
265 | NCic.Appl (NCic.Meta (i,l)::args), _ when List.mem_assoc i subst ->
266 let _,_,term,_ = NCicUtils.lookup_subst i subst in
267 let term = NCicSubstitution.subst_meta l term in
268 unify test_eq_only metasenv subst context (mk_appl term args) t2
270 | _, NCic.Appl (NCic.Meta (i,l)::args) when List.mem_assoc i subst ->
271 let _,_,term,_ = NCicUtils.lookup_subst i subst in
272 let term = NCicSubstitution.subst_meta l term in
273 unify test_eq_only metasenv subst context t1 (mk_appl term args)
275 | NCic.Appl (NCic.Meta (i,_)::_ as l1),
276 NCic.Appl (NCic.Meta (j,_)::_ as l2) when i=j ->
279 (fun (metasenv, subst) t1 t2 ->
280 unify test_eq_only metasenv subst context t1 t2)
281 (metasenv,subst) l1 l2
282 with Invalid_argument _ ->
283 raise (fail_exc metasenv subst context t1 t2))
285 | NCic.Appl (NCic.Meta (i,l)::args), _ when not (flexible args) ->
286 (* we verify that none of the args is a Meta,
287 since beta expanding w.r.t a metavariable makes no sense *)
288 let metasenv, subst, beta_expanded =
291 metasenv subst context t2 args
293 unify test_eq_only metasenv subst context
294 (C.Meta (i,l)) beta_expanded
296 | _, NCic.Appl (NCic.Meta (i,l)::args) when not(flexible args) ->
297 let metasenv, subst, beta_expanded =
300 metasenv subst context t1 args
302 unify test_eq_only metasenv subst context
303 beta_expanded (C.Meta (i,l))
305 (* processing this case here we avoid a useless small delta step *)
306 | (C.Appl ((C.Const r1) as _hd1::tl1), C.Appl (C.Const r2::tl2))
308 let relevance = NCicEnvironment.get_relevance r1 in
309 let relevance = match r1 with
310 | Ref.Ref (_,Ref.Con (_,_,lno)) ->
311 let _,relevance = HExtlib.split_nth lno relevance in
312 HExtlib.mk_list false lno @ relevance
315 let metasenv, subst, _ =
318 (fun (metasenv, subst, relevance) t1 t2 ->
320 match relevance with b::tl -> b,tl | _ -> true, [] in
321 let metasenv, subst =
322 try unify test_eq_only metasenv subst context t1 t2
323 with UnificationFailure _ | Uncertain _ when not b ->
326 metasenv, subst, relevance)
327 (metasenv, subst, relevance) tl1 tl2
328 with Invalid_argument _ ->
329 raise (uncert_exc metasenv subst context t1 t2)
333 | (C.Match (Ref.Ref (_,Ref.Ind (_,tyno,_)) as ref1,outtype1,term1,pl1),
334 C.Match (ref2,outtype2,term2,pl2)) ->
335 let _,_,itl,_,_ = NCicEnvironment.get_checked_indtys ref1 in
336 let _,_,ty,_ = List.nth itl tyno in
337 let rec remove_prods ~subst context ty =
338 let ty = NCicReduction.whd ~subst context ty in
341 | C.Prod (name,so,ta) ->
342 remove_prods ~subst ((name,(C.Decl so))::context) ta
346 match remove_prods ~subst [] ty with
347 | C.Sort C.Prop -> true
350 let rec remove_prods ~subst context ty =
351 let ty = NCicReduction.whd ~subst context ty in
354 | C.Prod (name,so,ta) ->
355 remove_prods ~subst ((name,(C.Decl so))::context) ta
358 if not (Ref.eq ref1 ref2) then
359 raise (uncert_exc metasenv subst context t1 t2)
361 let metasenv, subst =
362 unify test_eq_only metasenv subst context outtype1 outtype2 in
363 let metasenv, subst =
364 try unify test_eq_only metasenv subst context term1 term2
365 with UnificationFailure _ | Uncertain _ when is_prop ->
370 (fun (metasenv,subst) ->
371 unify test_eq_only metasenv subst context)
372 (metasenv, subst) pl1 pl2
373 with Invalid_argument _ ->
374 raise (uncert_exc metasenv subst context t1 t2))
375 | (C.Implicit _, _) | (_, C.Implicit _) -> assert false
376 | _ -> raise (uncert_exc metasenv subst context t1 t2)
377 (* (*D*) in outside(); rc with exn -> outside (); raise exn *)
379 let height_of = function
380 | NCic.Const (Ref.Ref (_,Ref.Def h))
381 | NCic.Const (Ref.Ref (_,Ref.Fix (_,_,h)))
382 | NCic.Appl(NCic.Const(Ref.Ref(_,Ref.Def h))::_)
383 | NCic.Appl(NCic.Const(Ref.Ref(_,Ref.Fix (_,_,h)))::_) -> h
386 let put_in_whd m1 m2 =
387 NCicReduction.reduce_machine ~delta:max_int ~subst context m1,
388 NCicReduction.reduce_machine ~delta:max_int ~subst context m2,
389 false (* not in normal form *)
391 let small_delta_step (_,_,t1,_ as m1) (_,_,t2,_ as m2) =
392 let h1 = height_of t1 in
393 let h2 = height_of t2 in
395 if flexible [t1] then max 0 (h2 - 1) else
396 if flexible [t2] then max 0 (h1 - 1) else
397 if h1 = h2 then max 0 (h1 -1) else min h1 h2
399 pp (lazy("DELTA STEP TO: " ^ string_of_int delta));
400 let m1' = NCicReduction.reduce_machine ~delta ~subst context m1 in
401 let m2' = NCicReduction.reduce_machine ~delta ~subst context m2 in
402 if (m1' == m1 && m2' == m2 && delta > 0) then
403 (* if we have as heads a Fix of height n>m>0 and another term of height
404 * m, we set delta = m. The Fix may or may not reduce, depending on its
405 * rec argument. if no reduction was performed we decrease delta to m-1
406 * to reduce the other term *)
407 let delta = delta - 1 in
408 pp (lazy("DELTA STEP TO: " ^ string_of_int delta));
409 let m1' = NCicReduction.reduce_machine ~delta ~subst context m1 in
410 let m2' = NCicReduction.reduce_machine ~delta ~subst context m2 in
411 m1', m2', (m1 == m1' && m2 == m2') (* || delta = 0 *)
412 else m1', m2', (m1 == m1' && m2 == m2') (* delta = 0 *)
414 let rec unif_machines metasenv subst =
416 | ((k1,e1,t1,s1 as m1),(k2,e2,t2,s2 as m2),are_normal) ->
417 (* (*D*) inside 'M'; try let rc = *)
419 pp (lazy((if are_normal then "*" else " ") ^ " " ^
420 NCicPp.ppterm ~metasenv ~subst ~context (NCicReduction.unwind m1) ^
422 NCicPp.ppterm ~metasenv ~subst ~context (NCicReduction.unwind m2)));
424 let relevance = [] (* TO BE UNDERSTOOD
426 | C.Const r -> NCicEnvironment.get_relevance r
428 let unif_from_stack t1 t2 b metasenv subst =
430 let t1 = NCicReduction.from_stack t1 in
431 let t2 = NCicReduction.from_stack t2 in
432 unif_machines metasenv subst (put_in_whd t1 t2)
433 with UnificationFailure _ | Uncertain _ when not b ->
436 let rec check_stack l1 l2 r (metasenv, subst) =
438 | x1::tl1, x2::tl2, r::tr ->
439 check_stack tl1 tl2 tr
440 (unif_from_stack x1 x2 r metasenv subst)
441 | x1::tl1, x2::tl2, [] ->
442 check_stack tl1 tl2 []
443 (unif_from_stack x1 x2 true metasenv subst)
445 fo_unif test_eq_only metasenv subst
446 (NCicReduction.unwind (k1,e1,t1,List.rev l1))
447 (NCicReduction.unwind (k2,e2,t2,List.rev l2))
449 try check_stack (List.rev s1) (List.rev s2) relevance (metasenv,subst)
450 with UnificationFailure _ | Uncertain _ when not are_normal ->
451 let m1,m2,normal as small = small_delta_step m1 m2 in
452 if not normal then unif_machines metasenv subst small
453 else raise (UnificationFailure (lazy "TEST x"))
454 (* (*D*) in outside(); rc with exn -> outside (); raise exn *)
456 try fo_unif test_eq_only metasenv subst t1 t2
457 with UnificationFailure msg | Uncertain msg as exn ->
459 unif_machines metasenv subst
460 (put_in_whd (0,[],t1,[]) (0,[],t2,[]))
462 | UnificationFailure _ -> raise (UnificationFailure msg)
463 | Uncertain _ -> raise exn
464 (* (*D*) in outside(); rc with exn -> outside (); raise exn *)
477 exception UnificationFailure of string Lazy.t;;
478 exception Uncertain of string Lazy.t;;
479 exception AssertFailure of string Lazy.t;;
481 let verbose = false;;
482 let debug_print = fun _ -> ()
484 let profiler_toa = HExtlib.profile "fo_unif_subst.type_of_aux'"
485 let profiler_beta_expand = HExtlib.profile "fo_unif_subst.beta_expand"
486 let profiler_deref = HExtlib.profile "fo_unif_subst.deref'"
487 let profiler_are_convertible = HExtlib.profile "fo_unif_subst.are_convertible"
489 let profile = HExtlib.profile "U/CicTypeChecker.type_of_aux'"
491 let type_of_aux' metasenv subst context term ugraph =
494 profile.HExtlib.profile
495 (CicTypeChecker.type_of_aux' ~subst metasenv context term) ugraph
497 CicTypeChecker.TypeCheckerFailure msg ->
501 "Kernel Type checking error:
502 %s\n%s\ncontext=\n%s\nmetasenv=\n%s\nsubstitution=\n%s\nException:\n%s.\nToo bad."
503 (CicMetaSubst.ppterm ~metasenv subst term)
504 (CicMetaSubst.ppterm ~metasenv [] term)
505 (CicMetaSubst.ppcontext ~metasenv subst context)
506 (CicMetaSubst.ppmetasenv subst metasenv)
507 (CicMetaSubst.ppsubst ~metasenv subst) (Lazy.force msg)) in
508 raise (AssertFailure msg)
509 | CicTypeChecker.AssertFailure msg ->
512 "Kernel Type checking assertion failure:
513 %s\n%s\ncontext=\n%s\nmetasenv=\n%s\nsubstitution=\n%s\nException:\n%s.\nToo bad."
514 (CicMetaSubst.ppterm ~metasenv subst term)
515 (CicMetaSubst.ppterm ~metasenv [] term)
516 (CicMetaSubst.ppcontext ~metasenv subst context)
517 (CicMetaSubst.ppmetasenv subst metasenv)
518 (CicMetaSubst.ppsubst ~metasenv subst) (Lazy.force msg)) in
519 raise (AssertFailure msg)
520 in profiler_toa.HExtlib.profile foo ()
523 let exists_a_meta l =
527 | Cic.Appl (Cic.Meta _::_) -> true
530 let rec deref subst t =
531 let snd (_,a,_) = a in
536 (CicSubstitution.subst_meta
537 l (snd (CicUtil.lookup_subst n subst)))
539 CicUtil.Subst_not_found _ -> t)
540 | Cic.Appl(Cic.Meta(n,l)::args) ->
541 (match deref subst (Cic.Meta(n,l)) with
542 | Cic.Lambda _ as t ->
543 deref subst (CicReduction.head_beta_reduce (Cic.Appl(t::args)))
544 | r -> Cic.Appl(r::args))
545 | Cic.Appl(((Cic.Lambda _) as t)::args) ->
546 deref subst (CicReduction.head_beta_reduce (Cic.Appl(t::args)))
551 let foo () = deref subst t
552 in profiler_deref.HExtlib.profile foo ()
554 exception WrongShape;;
555 let eta_reduce after_beta_expansion after_beta_expansion_body
556 before_beta_expansion
559 match before_beta_expansion,after_beta_expansion_body with
560 Cic.Appl l, Cic.Appl l' ->
561 let rec all_but_last check_last =
565 | [_] -> if check_last then raise WrongShape else []
566 | he::tl -> he::(all_but_last check_last tl)
568 let all_but_last check_last l =
569 match all_but_last check_last l with
574 let t = CicSubstitution.subst (Cic.Rel (-1)) (all_but_last true l') in
575 let all_but_last = all_but_last false l in
576 (* here we should test alpha-equivalence; however we know by
577 construction that here alpha_equivalence is equivalent to = *)
578 if t = all_but_last then
582 | _,_ -> after_beta_expansion
584 WrongShape -> after_beta_expansion
586 let rec beta_expand num test_equality_only metasenv subst context t arg ugraph =
587 let module S = CicSubstitution in
588 let module C = Cic in
590 let rec aux metasenv subst n context t' ugraph =
593 let subst,metasenv,ugraph1 =
594 fo_unif_subst test_equality_only subst context metasenv
595 (CicSubstitution.lift n arg) t' ugraph
598 subst,metasenv,C.Rel (1 + n),ugraph1
601 | UnificationFailure _ ->
603 | C.Rel m -> subst,metasenv,
604 (if m <= n then C.Rel m else C.Rel (m+1)),ugraph
605 | C.Var (uri,exp_named_subst) ->
606 let subst,metasenv,exp_named_subst',ugraph1 =
607 aux_exp_named_subst metasenv subst n context exp_named_subst ugraph
609 subst,metasenv,C.Var (uri,exp_named_subst'),ugraph1
611 (* andrea: in general, beta_expand can create badly typed
612 terms. This happens quite seldom in practice, UNLESS we
613 iterate on the local context. For this reason, we renounce
614 to iterate and just lift *)
618 Some t -> Some (CicSubstitution.lift 1 t)
620 subst, metasenv, C.Meta (i,l), ugraph
622 | C.Implicit _ as t -> subst,metasenv,t,ugraph
624 let subst,metasenv,te',ugraph1 =
625 aux metasenv subst n context te ugraph in
626 let subst,metasenv,ty',ugraph2 =
627 aux metasenv subst n context ty ugraph1 in
628 (* TASSI: sure this is in serial? *)
629 subst,metasenv,(C.Cast (te', ty')),ugraph2
631 let subst,metasenv,s',ugraph1 =
632 aux metasenv subst n context s ugraph in
633 let subst,metasenv,t',ugraph2 =
634 aux metasenv subst (n+1) ((Some (nn, C.Decl s))::context) t
637 (* TASSI: sure this is in serial? *)
638 subst,metasenv,(C.Prod (nn, s', t')),ugraph2
639 | C.Lambda (nn,s,t) ->
640 let subst,metasenv,s',ugraph1 =
641 aux metasenv subst n context s ugraph in
642 let subst,metasenv,t',ugraph2 =
643 aux metasenv subst (n+1) ((Some (nn, C.Decl s))::context) t ugraph1
645 (* TASSI: sure this is in serial? *)
646 subst,metasenv,(C.Lambda (nn, s', t')),ugraph2
647 | C.LetIn (nn,s,ty,t) ->
648 let subst,metasenv,s',ugraph1 =
649 aux metasenv subst n context s ugraph in
650 let subst,metasenv,ty',ugraph1 =
651 aux metasenv subst n context ty ugraph in
652 let subst,metasenv,t',ugraph2 =
653 aux metasenv subst (n+1) ((Some (nn, C.Def (s,ty)))::context) t
656 (* TASSI: sure this is in serial? *)
657 subst,metasenv,(C.LetIn (nn, s', ty', t')),ugraph2
659 let subst,metasenv,revl',ugraph1 =
661 (fun (subst,metasenv,appl,ugraph) t ->
662 let subst,metasenv,t',ugraph1 =
663 aux metasenv subst n context t ugraph in
664 subst,metasenv,(t'::appl),ugraph1
665 ) (subst,metasenv,[],ugraph) l
667 subst,metasenv,(C.Appl (List.rev revl')),ugraph1
668 | C.Const (uri,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.Const (uri,exp_named_subst')),ugraph1
673 | C.MutInd (uri,i,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.MutInd (uri,i,exp_named_subst')),ugraph1
678 | C.MutConstruct (uri,i,j,exp_named_subst) ->
679 let subst,metasenv,exp_named_subst',ugraph1 =
680 aux_exp_named_subst metasenv subst n context exp_named_subst ugraph
682 subst,metasenv,(C.MutConstruct (uri,i,j,exp_named_subst')),ugraph1
683 | C.MutCase (sp,i,outt,t,pl) ->
684 let subst,metasenv,outt',ugraph1 =
685 aux metasenv subst n context outt ugraph in
686 let subst,metasenv,t',ugraph2 =
687 aux metasenv subst n context t ugraph1 in
688 let subst,metasenv,revpl',ugraph3 =
690 (fun (subst,metasenv,pl,ugraph) t ->
691 let subst,metasenv,t',ugraph1 =
692 aux metasenv subst n context t ugraph in
693 subst,metasenv,(t'::pl),ugraph1
694 ) (subst,metasenv,[],ugraph2) pl
696 subst,metasenv,(C.MutCase (sp,i,outt', t', List.rev revpl')),ugraph3
697 (* TASSI: not sure this is serial *)
699 (*CSC: not implemented
700 let tylen = List.length fl in
703 (fun (name,i,ty,bo) -> (name, i, aux n ty, aux (n+tylen) bo))
706 C.Fix (i, substitutedfl)
708 subst,metasenv,(CicSubstitution.lift 1 t' ),ugraph
710 (*CSC: not implemented
711 let tylen = List.length fl in
714 (fun (name,ty,bo) -> (name, aux n ty, aux (n+tylen) bo))
717 C.CoFix (i, substitutedfl)
720 subst,metasenv,(CicSubstitution.lift 1 t'), ugraph
722 and aux_exp_named_subst metasenv subst n context ens ugraph =
724 (fun (uri,t) (subst,metasenv,l,ugraph) ->
725 let subst,metasenv,t',ugraph1 = aux metasenv subst n context t ugraph in
726 subst,metasenv,((uri,t')::l),ugraph1) ens (subst,metasenv,[],ugraph)
728 let argty,ugraph1 = type_of_aux' metasenv subst context arg ugraph in
730 FreshNamesGenerator.mk_fresh_name ~subst
731 metasenv context (Cic.Name ("Hbeta" ^ string_of_int num)) ~typ:argty
733 let subst,metasenv,t',ugraph2 = aux metasenv subst 0 context t ugraph1 in
734 let t'' = eta_reduce (C.Lambda (fresh_name,argty,t')) t' t in
735 subst, metasenv, t'', ugraph2
736 in profiler_beta_expand.HExtlib.profile foo ()
739 and beta_expand_many test_equality_only metasenv subst context t args ugraph =
740 let _,subst,metasenv,hd,ugraph =
742 (fun arg (num,subst,metasenv,t,ugraph) ->
743 let subst,metasenv,t,ugraph1 =
744 beta_expand num test_equality_only
745 metasenv subst context t arg ugraph
747 num+1,subst,metasenv,t,ugraph1
748 ) args (1,subst,metasenv,t,ugraph)
750 subst,metasenv,hd,ugraph
752 and warn_if_not_unique xxx to1 to2 carr car1 car2 =
755 | (m2,_,c2,c2')::_ ->
756 let m1,c1,c1' = carr,to1,to2 in
758 function Some (_,t) -> CicPp.ppterm t
762 ("There are two minimal joins of "^ CoercDb.string_of_carr car1^" and "^
763 CoercDb.string_of_carr car2^": " ^
764 CoercDb.string_of_carr m1^" via "^unopt c1^" + "^
765 unopt c1'^" and "^ CoercDb.string_of_carr m2^" via "^
766 unopt c2^" + "^unopt c2')
768 (* NUOVA UNIFICAZIONE *)
769 (* A substitution is a (int * Cic.term) list that associates a
770 metavariable i with its body.
771 A metaenv is a (int * Cic.term) list that associate a metavariable
773 fo_unif_new takes a metasenv, a context, two terms t1 and t2 and gives back
774 a new substitution which is _NOT_ unwinded. It must be unwinded before
777 and fo_unif_subst test_equality_only subst context metasenv t1 t2 ugraph =
778 let module C = Cic in
779 let module R = CicReduction in
780 let module S = CicSubstitution in
781 let t1 = deref subst t1 in
782 let t2 = deref subst t2 in
783 let (&&&) a b = (a && b) || ((not a) && (not b)) in
784 (* let bef = Sys.time () in *)
786 if not (CicUtil.is_meta_closed (CicMetaSubst.apply_subst subst t1) &&& CicUtil.is_meta_closed (CicMetaSubst.apply_subst subst t2)) then
790 R.are_convertible ~subst ~metasenv context t1 t2 ugraph
791 in profiler_are_convertible.HExtlib.profile foo ()
793 (* let aft = Sys.time () in
794 if (aft -. bef > 2.0) then prerr_endline ("LEEEENTO: " ^
795 CicMetaSubst.ppterm_in_context subst ~metasenv t1 context ^ " <===> " ^
796 CicMetaSubst.ppterm_in_context subst ~metasenv t2 context); *)
798 subst, metasenv, ugraph
801 | (C.Meta (n,ln), C.Meta (m,lm)) when n=m ->
802 let _,subst,metasenv,ugraph1 =
805 (fun (j,subst,metasenv,ugraph) t1 t2 ->
808 | _,None -> j+1,subst,metasenv,ugraph
809 | Some t1', Some t2' ->
810 (* First possibility: restriction *)
811 (* Second possibility: unification *)
812 (* Third possibility: convertibility *)
815 ~subst ~metasenv context t1' t2' ugraph
818 j+1,subst,metasenv, ugraph1
821 let subst,metasenv,ugraph2 =
824 subst context metasenv t1' t2' ugraph
826 j+1,subst,metasenv,ugraph2
829 | UnificationFailure _ ->
830 debug_print (lazy ("restringo Meta n." ^ (string_of_int n) ^ "on variable n." ^ (string_of_int j)));
831 let metasenv, subst =
832 CicMetaSubst.restrict
833 subst [(n,j)] metasenv in
834 j+1,subst,metasenv,ugraph1)
835 ) (1,subst,metasenv,ugraph) ln lm
839 (UnificationFailure (lazy "1"))
842 "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."
843 (CicMetaSubst.ppterm ~metasenv subst t1)
844 (CicMetaSubst.ppterm ~metasenv subst t2))) *)
845 | Invalid_argument _ ->
847 (UnificationFailure (lazy "2")))
850 "Error trying to unify %s with %s: the lengths of the two local contexts do not match."
851 (CicMetaSubst.ppterm ~metasenv subst t1)
852 (CicMetaSubst.ppterm ~metasenv subst t2)))) *)
853 in subst,metasenv,ugraph1
854 | (C.Meta (n,_), C.Meta (m,_)) when n>m ->
855 fo_unif_subst test_equality_only subst context metasenv t2 t1 ugraph
857 | (t, C.Meta (n,l)) ->
860 C.Meta (n,_), C.Meta (m,_) when n < m -> false
861 | _, C.Meta _ -> false
864 let lower = fun x y -> if swap then y else x in
865 let upper = fun x y -> if swap then x else y in
866 let fo_unif_subst_ordered
867 test_equality_only subst context metasenv m1 m2 ugraph =
868 fo_unif_subst test_equality_only subst context metasenv
869 (lower m1 m2) (upper m1 m2) ugraph
872 let subst,metasenv,ugraph1 =
873 let (_,_,meta_type) = CicUtil.lookup_meta n metasenv in
876 type_of_aux' metasenv subst context t ugraph
880 subst context metasenv tyt (S.subst_meta l meta_type) ugraph1
882 UnificationFailure _ as e -> raise e
883 | Uncertain msg -> raise (UnificationFailure msg)
885 debug_print (lazy "siamo allo huge hack");
886 (* TODO huge hack!!!!
887 * we keep on unifying/refining in the hope that
888 * the problem will be eventually solved.
889 * In the meantime we're breaking a big invariant:
890 * the terms that we are unifying are no longer well
891 * typed in the current context (in the worst case
892 * we could even diverge) *)
893 (subst, metasenv,ugraph)) in
894 let t',metasenv,subst =
896 CicMetaSubst.delift n subst context metasenv l t
898 (CicMetaSubst.MetaSubstFailure msg)->
899 raise (UnificationFailure msg)
900 | (CicMetaSubst.Uncertain msg) -> raise (Uncertain msg)
904 C.Sort (C.Type u) when not test_equality_only ->
905 let u' = CicUniv.fresh () in
906 let s = C.Sort (C.Type u') in
909 CicUniv.add_ge (upper u u') (lower u u') ugraph1
913 CicUniv.UniverseInconsistency msg ->
914 raise (UnificationFailure msg))
917 (* Unifying the types may have already instantiated n. Let's check *)
919 let (_, oldt,_) = CicUtil.lookup_subst n subst in
920 let lifted_oldt = S.subst_meta l oldt in
921 fo_unif_subst_ordered
922 test_equality_only subst context metasenv t lifted_oldt ugraph2
924 CicUtil.Subst_not_found _ ->
925 let (_, context, ty) = CicUtil.lookup_meta n metasenv in
926 let subst = (n, (context, t'',ty)) :: subst in
928 List.filter (fun (m,_,_) -> not (n = m)) metasenv in
929 subst, metasenv, ugraph2
931 | (C.Var (uri1,exp_named_subst1),C.Var (uri2,exp_named_subst2))
932 | (C.Const (uri1,exp_named_subst1),C.Const (uri2,exp_named_subst2)) ->
933 if UriManager.eq uri1 uri2 then
934 fo_unif_subst_exp_named_subst test_equality_only subst context metasenv
935 exp_named_subst1 exp_named_subst2 ugraph
937 raise (UnificationFailure (lazy
939 "Can't unify %s with %s due to different constants"
940 (CicMetaSubst.ppterm ~metasenv subst t1)
941 (CicMetaSubst.ppterm ~metasenv subst t2))))
942 | C.MutInd (uri1,i1,exp_named_subst1),C.MutInd (uri2,i2,exp_named_subst2) ->
943 if UriManager.eq uri1 uri2 && i1 = i2 then
944 fo_unif_subst_exp_named_subst
946 subst context metasenv exp_named_subst1 exp_named_subst2 ugraph
948 raise (UnificationFailure
951 "Can't unify %s with %s due to different inductive principles"
952 (CicMetaSubst.ppterm ~metasenv subst t1)
953 (CicMetaSubst.ppterm ~metasenv subst t2))))
954 | C.MutConstruct (uri1,i1,j1,exp_named_subst1),
955 C.MutConstruct (uri2,i2,j2,exp_named_subst2) ->
956 if UriManager.eq uri1 uri2 && i1 = i2 && j1 = j2 then
957 fo_unif_subst_exp_named_subst
959 subst context metasenv exp_named_subst1 exp_named_subst2 ugraph
961 raise (UnificationFailure
964 "Can't unify %s with %s due to different inductive constructors"
965 (CicMetaSubst.ppterm ~metasenv subst t1)
966 (CicMetaSubst.ppterm ~metasenv subst t2))))
967 | (C.Implicit _, _) | (_, C.Implicit _) -> assert false
968 | (C.Cast (te,ty), t2) -> fo_unif_subst test_equality_only
969 subst context metasenv te t2 ugraph
970 | (t1, C.Cast (te,ty)) -> fo_unif_subst test_equality_only
971 subst context metasenv t1 te ugraph
972 | (C.Lambda (n1,s1,t1), C.Lambda (_,s2,t2)) ->
973 let subst',metasenv',ugraph1 =
974 fo_unif_subst test_equality_only subst context metasenv s1 s2 ugraph
976 fo_unif_subst test_equality_only
977 subst' ((Some (n1,(C.Decl s1)))::context) metasenv' t1 t2 ugraph1
978 | (C.LetIn (_,s1,ty1,t1), t2)
979 | (t2, C.LetIn (_,s1,ty1,t1)) ->
981 test_equality_only subst context metasenv t2 (S.subst s1 t1) ugraph
982 | (C.Appl l1, C.Appl l2) ->
983 (* andrea: this case should be probably rewritten in the
986 | C.Meta (i,_)::args1, C.Meta (j,_)::args2 when i = j ->
989 (fun (subst,metasenv,ugraph) t1 t2 ->
991 test_equality_only subst context metasenv t1 t2 ugraph)
992 (subst,metasenv,ugraph) l1 l2
993 with (Invalid_argument msg) ->
994 raise (UnificationFailure (lazy msg)))
995 | C.Meta (i,l)::args, _ when not(exists_a_meta args) ->
996 (* we verify that none of the args is a Meta,
997 since beta expanding with respoect to a metavariable
1001 let (_,t,_) = CicUtil.lookup_subst i subst in
1002 let lifted = S.subst_meta l t in
1003 let reduced = CicReduction.head_beta_reduce (Cic.Appl (lifted::args)) in
1006 subst context metasenv reduced t2 ugraph
1007 with CicUtil.Subst_not_found _ -> *)
1008 let subst,metasenv,beta_expanded,ugraph1 =
1010 test_equality_only metasenv subst context t2 args ugraph
1012 fo_unif_subst test_equality_only subst context metasenv
1013 (C.Meta (i,l)) beta_expanded ugraph1
1014 | _, C.Meta (i,l)::args when not(exists_a_meta args) ->
1016 let (_,t,_) = CicUtil.lookup_subst i subst in
1017 let lifted = S.subst_meta l t in
1018 let reduced = CicReduction.head_beta_reduce (Cic.Appl (lifted::args)) in
1021 subst context metasenv t1 reduced ugraph
1022 with CicUtil.Subst_not_found _ -> *)
1023 let subst,metasenv,beta_expanded,ugraph1 =
1026 metasenv subst context t1 args ugraph
1028 fo_unif_subst test_equality_only subst context metasenv
1029 (C.Meta (i,l)) beta_expanded ugraph1
1031 let lr1 = List.rev l1 in
1032 let lr2 = List.rev l2 in
1034 fo_unif_l test_equality_only subst metasenv (l1,l2) ugraph =
1037 | _,[] -> assert false
1040 test_equality_only subst context metasenv h1 h2 ugraph
1043 fo_unif_subst test_equality_only subst context metasenv
1044 h (C.Appl (List.rev l)) ugraph
1045 | ((h1::l1),(h2::l2)) ->
1046 let subst', metasenv',ugraph1 =
1049 subst context metasenv h1 h2 ugraph
1052 test_equality_only subst' metasenv' (l1,l2) ugraph1
1056 test_equality_only subst metasenv (lr1, lr2) ugraph
1058 | UnificationFailure s
1059 | Uncertain s as exn ->
1062 | (((Cic.Const (uri1, ens1)) as cc1) :: tl1),
1063 (((Cic.Const (uri2, ens2)) as cc2) :: tl2) when
1064 CoercDb.is_a_coercion cc1 <> None &&
1065 CoercDb.is_a_coercion cc2 <> None &&
1066 not (UriManager.eq uri1 uri2) ->
1068 prerr_endline ("<<<< " ^ CicMetaSubst.ppterm_in_context ~metasenv subst (C.Appl l1) context ^ " <==> " ^ CicMetaSubst.ppterm_in_context ~metasenv subst (C.Appl l2) context);
1070 let inner_coerced t =
1071 let t = CicMetaSubst.apply_subst subst t in
1075 (match CoercGraph.coerced_arg l with
1077 | Some (t,_) -> aux (List.hd l) t t)
1080 aux (Cic.Implicit None) (Cic.Implicit None) t
1082 let c1,last_tl1 = inner_coerced (Cic.Appl l1) in
1083 let c2,last_tl2 = inner_coerced (Cic.Appl l2) in
1086 CoercDb.is_a_coercion c1, CoercDb.is_a_coercion c2
1088 | Some (s1,_,_,_,_), Some (s2,_,_,_,_) -> s1, s2
1091 let head1_c, head2_c =
1093 CoercDb.is_a_coercion cc1, CoercDb.is_a_coercion cc2
1095 | Some (_,t1,_,_,_), Some (_,t2,_,_,_) -> t1, t2
1098 let unfold uri ens args =
1100 CicEnvironment.get_obj CicUniv.oblivion_ugraph uri
1104 | Cic.Constant (_,Some bo,_,_,_) ->
1105 CicReduction.head_beta_reduce ~delta:false
1106 (Cic.Appl (bo::args))
1109 let conclude subst metasenv ugraph last_tl1' last_tl2' =
1110 let subst',metasenv,ugraph =
1113 ("OK " ^ CicMetaSubst.ppterm_in_context ~metasenv subst last_tl1' context ^
1114 " <==> " ^ CicMetaSubst.ppterm_in_context ~metasenv subst last_tl2' context);
1116 fo_unif_subst test_equality_only subst context
1117 metasenv last_tl1' last_tl2' ugraph
1119 if subst = subst' then raise exn
1122 let subst,metasenv,ugrph as res =
1124 fo_unif_subst test_equality_only subst' context
1125 metasenv (C.Appl l1) (C.Appl l2) ugraph
1129 (">>>> "^CicMetaSubst.ppterm_in_context ~metasenv subst (C.Appl l1) context ^
1130 " <==> "^CicMetaSubst.ppterm_in_context ~metasenv subst (C.Appl l2) context);
1134 if CoercDb.eq_carr car1 car2 then
1135 match last_tl1,last_tl2 with
1136 | C.Meta (i1,_),C.Meta(i2,_) when i1 = i2 -> raise exn
1139 let subst,metasenv,ugraph =
1140 fo_unif_subst test_equality_only subst context
1141 metasenv last_tl1 last_tl2 ugraph
1143 fo_unif_subst test_equality_only subst context
1144 metasenv (Cic.Appl l1) (Cic.Appl l2) ugraph
1145 | _ when CoercDb.eq_carr head1_c head2_c ->
1146 (* composite VS composition + metas avoiding
1147 * coercions not only in coerced position *)
1148 if c1 <> cc1 && c2 <> cc2 then
1149 conclude subst metasenv ugraph
1154 unfold uri1 ens1 tl1, Cic.Appl (cc2::tl2)
1156 Cic.Appl (cc1::tl1), unfold uri2 ens2 tl2
1158 fo_unif_subst test_equality_only subst context
1159 metasenv l1 l2 ugraph
1163 match last_tl1 with Cic.Meta _ -> true | _ -> false in
1165 match last_tl2 with Cic.Meta _ -> true | _ -> false in
1166 if not (grow1 || grow2) then
1167 (* no flexible terminals -> no pullback, but
1168 * we still unify them, in some cases it helps *)
1169 conclude subst metasenv ugraph last_tl1 last_tl2
1173 metasenv subst context (grow1,car1) (grow2,car2)
1177 | (carr,metasenv,to1,to2)::xxx ->
1178 warn_if_not_unique xxx to1 to2 carr car1 car2;
1179 let last_tl1',(subst,metasenv,ugraph) =
1180 match grow1,to1 with
1181 | true,Some (last,coerced) ->
1183 fo_unif_subst test_equality_only subst context
1184 metasenv coerced last_tl1 ugraph
1185 | _ -> last_tl1,(subst,metasenv,ugraph)
1187 let last_tl2',(subst,metasenv,ugraph) =
1188 match grow2,to2 with
1189 | true,Some (last,coerced) ->
1191 fo_unif_subst test_equality_only subst context
1192 metasenv coerced last_tl2 ugraph
1193 | _ -> last_tl2,(subst,metasenv,ugraph)
1195 conclude subst metasenv ugraph last_tl1' last_tl2')
1197 (* {{{ CSC: This is necessary because of the "elim H" tactic
1198 where the type of H is only reducible to an
1199 inductive type. This could be extended from inductive
1200 types to any rigid term. However, the code is
1201 duplicated in two places: inside applications and
1202 outside them. Probably it would be better to
1203 work with lambda-bar terms instead. *)
1204 | (Cic.MutInd _::_, Cic.MutInd _::_) -> raise exn
1205 | (_, Cic.MutInd _::_) ->
1206 let t1' = R.whd ~subst context t1 in
1208 C.Appl (C.MutInd _::_) ->
1209 fo_unif_subst test_equality_only
1210 subst context metasenv t1' t2 ugraph
1211 | _ -> raise (UnificationFailure (lazy "88")))
1212 | (Cic.MutInd _::_,_) ->
1213 let t2' = R.whd ~subst context t2 in
1215 C.Appl (C.MutInd _::_) ->
1216 fo_unif_subst test_equality_only
1217 subst context metasenv t1 t2' ugraph
1220 (lazy ("not a mutind :"^
1221 CicMetaSubst.ppterm ~metasenv subst t2 ))))
1224 | (C.MutCase (_,_,outt1,t1',pl1), C.MutCase (_,_,outt2,t2',pl2))->
1225 let subst', metasenv',ugraph1 =
1226 fo_unif_subst test_equality_only subst context metasenv outt1 outt2
1228 let subst'',metasenv'',ugraph2 =
1229 fo_unif_subst test_equality_only subst' context metasenv' t1' t2'
1233 (fun (subst,metasenv,ugraph) t1 t2 ->
1235 test_equality_only subst context metasenv t1 t2 ugraph
1236 ) (subst'',metasenv'',ugraph2) pl1 pl2
1238 Invalid_argument _ ->
1239 raise (UnificationFailure (lazy "6.1")))
1241 "Error trying to unify %s with %s: the number of branches is not the same."
1242 (CicMetaSubst.ppterm ~metasenv subst t1)
1243 (CicMetaSubst.ppterm ~metasenv subst t2)))) *)
1244 | (C.Rel _, _) | (_, C.Rel _) ->
1246 subst, metasenv,ugraph
1248 raise (UnificationFailure (lazy
1250 "Can't unify %s with %s because they are not convertible"
1251 (CicMetaSubst.ppterm ~metasenv subst t1)
1252 (CicMetaSubst.ppterm ~metasenv subst t2))))
1253 | (C.Appl (C.Meta(i,l)::args),t2) when not(exists_a_meta args) ->
1254 let subst,metasenv,beta_expanded,ugraph1 =
1256 test_equality_only metasenv subst context t2 args ugraph
1258 fo_unif_subst test_equality_only subst context metasenv
1259 (C.Meta (i,l)) beta_expanded ugraph1
1260 | (t1,C.Appl (C.Meta(i,l)::args)) when not(exists_a_meta args) ->
1261 let subst,metasenv,beta_expanded,ugraph1 =
1263 test_equality_only metasenv subst context t1 args ugraph
1265 fo_unif_subst test_equality_only subst context metasenv
1266 beta_expanded (C.Meta (i,l)) ugraph1
1267 (* Works iff there are no arguments applied to it; similar to the
1269 | (_, C.MutInd _) ->
1270 let t1' = R.whd ~subst context t1 in
1273 fo_unif_subst test_equality_only
1274 subst context metasenv t1' t2 ugraph
1275 | _ -> raise (UnificationFailure (lazy "8")))
1277 | (C.Prod (n1,s1,t1), C.Prod (_,s2,t2)) ->
1278 let subst',metasenv',ugraph1 =
1279 fo_unif_subst true subst context metasenv s1 s2 ugraph
1281 fo_unif_subst test_equality_only
1282 subst' ((Some (n1,(C.Decl s1)))::context) metasenv' t1 t2 ugraph1
1284 (match CicReduction.whd ~subst context t2 with
1286 fo_unif_subst test_equality_only subst context metasenv t1 t2 ugraph
1287 | _ -> raise (UnificationFailure (lazy (CicMetaSubst.ppterm ~metasenv subst t2^"Not a product"))))
1289 (match CicReduction.whd ~subst context t1 with
1291 fo_unif_subst test_equality_only subst context metasenv t1 t2 ugraph
1292 | _ -> raise (UnificationFailure (lazy (CicMetaSubst.ppterm ~metasenv subst t1^"Not a product"))))
1294 (* delta-beta reduction should almost never be a problem for
1296 1. long computations require iota reduction
1297 2. it is extremely rare that a close term t1 (that could be unified
1298 to t2) beta-delta reduces to t1' while t2 does not beta-delta
1299 reduces in the same way. This happens only if one meta of t2
1300 occurs in head position during beta reduction. In this unluky
1301 case too much reduction will be performed on t1 and unification
1302 will surely fail. *)
1303 let t1' = CicReduction.head_beta_reduce ~delta:true t1 in
1304 let t2' = CicReduction.head_beta_reduce ~delta:true t2 in
1305 if t1 = t1' && t2 = t2' then
1306 raise (UnificationFailure
1309 "Can't unify %s with %s because they are not convertible"
1310 (CicMetaSubst.ppterm ~metasenv subst t1)
1311 (CicMetaSubst.ppterm ~metasenv subst t2))))
1314 fo_unif_subst test_equality_only subst context metasenv t1' t2' ugraph
1316 UnificationFailure _
1318 raise (UnificationFailure
1321 "Can't unify %s with %s because they are not convertible"
1322 (CicMetaSubst.ppterm ~metasenv subst t1)
1323 (CicMetaSubst.ppterm ~metasenv subst t2))))
1325 and fo_unif_subst_exp_named_subst test_equality_only subst context metasenv
1326 exp_named_subst1 exp_named_subst2 ugraph
1330 (fun (subst,metasenv,ugraph) (uri1,t1) (uri2,t2) ->
1331 assert (uri1=uri2) ;
1332 fo_unif_subst test_equality_only subst context metasenv t1 t2 ugraph
1333 ) (subst,metasenv,ugraph) exp_named_subst1 exp_named_subst2
1335 Invalid_argument _ ->
1340 UriManager.string_of_uri uri ^ " := " ^ (CicMetaSubst.ppterm ~metasenv subst t)
1343 raise (UnificationFailure (lazy (sprintf
1344 "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))))
1346 (* A substitution is a (int * Cic.term) list that associates a *)
1347 (* metavariable i with its body. *)
1348 (* metasenv is of type Cic.metasenv *)
1349 (* fo_unif takes a metasenv, a context, two terms t1 and t2 and gives back *)
1350 (* a new substitution which is already unwinded and ready to be applied and *)
1351 (* a new metasenv in which some hypothesis in the contexts of the *)
1352 (* metavariables may have been restricted. *)
1353 let fo_unif metasenv context t1 t2 ugraph =
1354 fo_unif_subst false [] context metasenv t1 t2 ugraph ;;
1356 let enrich_msg msg subst context metasenv t1 t2 ugraph =
1359 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"
1360 (CicMetaSubst.ppterm ~metasenv subst t1)
1362 let ty_t1,_ = type_of_aux' metasenv subst context t1 ugraph in
1365 | UnificationFailure s
1367 | AssertFailure s -> sprintf "MALFORMED(t1): \n<BEGIN>%s\n<END>" (Lazy.force s))
1368 (CicMetaSubst.ppterm ~metasenv subst t2)
1370 let ty_t2,_ = type_of_aux' metasenv subst context t2 ugraph in
1373 | UnificationFailure s
1375 | AssertFailure s -> sprintf "MALFORMED(t2): \n<BEGIN>%s\n<END>" (Lazy.force s))
1376 (CicMetaSubst.ppcontext ~metasenv subst context)
1377 (CicMetaSubst.ppmetasenv subst metasenv)
1378 (CicMetaSubst.ppsubst ~metasenv subst) (Lazy.force msg)
1380 sprintf "Unification error unifying %s of type %s with %s of type %s in context\n%s\nand metasenv\n%s\nbecause %s"
1381 (CicMetaSubst.ppterm_in_context ~metasenv subst t1 context)
1383 let ty_t1,_ = type_of_aux' metasenv subst context t1 ugraph in
1384 CicMetaSubst.ppterm_in_context ~metasenv subst ty_t1 context
1386 | UnificationFailure s
1388 | AssertFailure s -> sprintf "MALFORMED(t1): \n<BEGIN>%s\n<END>" (Lazy.force s))
1389 (CicMetaSubst.ppterm_in_context ~metasenv subst t2 context)
1391 let ty_t2,_ = type_of_aux' metasenv subst context t2 ugraph in
1392 CicMetaSubst.ppterm_in_context ~metasenv subst ty_t2 context
1394 | UnificationFailure s
1396 | AssertFailure s -> sprintf "MALFORMED(t2): \n<BEGIN>%s\n<END>" (Lazy.force s))
1397 (CicMetaSubst.ppcontext ~metasenv subst context)
1398 (CicMetaSubst.ppmetasenv subst metasenv)
1402 let fo_unif_subst subst context metasenv t1 t2 ugraph =
1404 fo_unif_subst false subst context metasenv t1 t2 ugraph
1406 | AssertFailure msg ->
1407 raise (AssertFailure (enrich_msg msg subst context metasenv t1 t2 ugraph))
1408 | UnificationFailure msg ->
1409 raise (UnificationFailure (enrich_msg msg subst context metasenv t1 t2 ugraph))