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;;
71 let rec beta_expand num test_eq_only swap metasenv subst context t arg =
72 let rec aux (n,context,test_eq_only as k) (metasenv, subst as acc) t' =
76 unify test_eq_only metasenv subst context t' (NCicSubstitution.lift n arg)
78 unify test_eq_only metasenv subst context (NCicSubstitution.lift n arg) t'
80 (metasenv, subst), NCic.Rel (1 + n)
81 with Uncertain _ | UnificationFailure _ ->
83 | NCic.Rel m as orig ->
84 (metasenv, subst), if m <= n then orig else NCic.Rel (m+1)
85 (* andrea: in general, beta_expand can create badly typed
86 terms. This happens quite seldom in practice, UNLESS we
87 iterate on the local context. For this reason, we renounce
88 to iterate and just lift *)
89 | NCic.Meta (i,(shift,lc)) ->
90 (metasenv,subst), NCic.Meta (i,(shift+1,lc))
91 | NCic.Prod (name, src, tgt) as orig ->
92 let (metasenv, subst), src1 = aux (n,context,true) acc src in
93 let k = n+1, (name, NCic.Decl src) :: context, test_eq_only in
94 let ms, tgt1 = aux k (metasenv, subst) tgt in
95 if src == src1 && tgt == tgt1 then ms, orig else
96 ms, NCic.Prod (name, src1, tgt1)
98 NCicUntrusted.map_term_fold_a
99 (fun e (n,ctx,teq) -> n+1,e::ctx,teq) k aux acc t
102 let argty = NCicTypeChecker.typeof ~metasenv ~subst context arg in
103 let fresh_name = "Hbeta" ^ string_of_int num in
104 let (metasenv,subst), t1 =
105 aux (0, context, test_eq_only) (metasenv, subst) t in
106 let t2 = eta_reduce (NCic.Lambda (fresh_name,argty,t1)) in
108 ignore(NCicTypeChecker.typeof ~metasenv ~subst context t2);
110 with NCicTypeChecker.TypeCheckerFailure _ ->
111 metasenv, subst, NCic.Lambda ("_", argty, NCicSubstitution.lift 1 arg)
113 and beta_expand_many test_equality_only swap metasenv subst context t args =
114 let _, subst, metasenv, hd =
116 (fun arg (num,subst,metasenv,t) ->
117 let metasenv, subst, t =
118 beta_expand num test_equality_only swap metasenv subst context t arg
120 num+1,subst,metasenv,t)
121 args (1,subst,metasenv,t)
125 and instantiate test_eq_only metasenv subst context n lc t swap =
126 let unify test_eq_only m s c t1 t2 =
127 if swap then unify test_eq_only m s c t2 t1
128 else unify test_eq_only m s c t1 t2
131 try NCicTypeChecker.typeof ~subst ~metasenv context t
132 with NCicTypeChecker.TypeCheckerFailure _ -> assert false
134 let name, ctx, ty = NCicUtils.lookup_meta n metasenv in
135 let ty = NCicSubstitution.subst_meta lc ty in
136 let metasenv, subst = unify test_eq_only metasenv subst context ty ty_t in
137 let (metasenv, subst), t =
138 NCicMetaSubst.delift metasenv subst context n lc t
140 (* Unifying the types may have already instantiated n. *)
142 let _, _,oldt,_ = NCicUtils.lookup_subst n subst in
143 let oldt = NCicSubstitution.subst_meta lc oldt in
144 (* conjecture: always fail --> occur check *)
145 unify test_eq_only metasenv subst context oldt t
146 with NCicUtils.Subst_not_found _ ->
147 (* by cumulativity when unify(?,Type_i)
148 * we could ? := Type_j with j <= i... *)
149 let subst = (n, (name, ctx, t, ty)) :: subst in
151 List.filter (fun (m,_) -> not (n = m)) metasenv
155 and unify test_eq_only metasenv subst context t1 t2 =
156 let fo_unif test_eq_only metasenv subst t1 t2 =
161 | (C.Sort (C.Type a), C.Sort (C.Type b)) when not test_eq_only ->
162 if NCicEnvironment.universe_leq a b then metasenv, subst
163 else raise (fail_exc metasenv subst context t1 t2)
164 | (C.Sort (C.Type a), C.Sort (C.Type b)) ->
165 if NCicEnvironment.universe_eq a b then metasenv, subst
166 else raise (fail_exc metasenv subst context t1 t2)
167 | (C.Sort C.Prop,C.Sort (C.Type _)) ->
168 if (not test_eq_only) then metasenv, subst
169 else raise (fail_exc metasenv subst context t1 t2)
171 | (C.Lambda (name1,s1,t1), C.Lambda(_,s2,t2))
172 | (C.Prod (name1,s1,t1), C.Prod(_,s2,t2)) ->
173 let metasenv, subst = unify true metasenv subst context s1 s2 in
174 unify test_eq_only metasenv subst ((name1, C.Decl s1)::context) t1 t2
175 | (C.LetIn (name1,ty1,s1,t1), C.LetIn(_,ty2,s2,t2)) ->
176 let metasenv,subst=unify test_eq_only metasenv subst context ty1 ty2 in
177 let metasenv,subst=unify test_eq_only metasenv subst context s1 s2 in
178 let context = (name1, C.Def (s1,ty1))::context in
179 unify test_eq_only metasenv subst context t1 t2
181 | (C.Meta (n1,(s1,l1 as lc1)),C.Meta (n2,(s2,l2 as lc2))) when n1 = n2 ->
183 let l1 = NCicUtils.expand_local_context l1 in
184 let l2 = NCicUtils.expand_local_context l2 in
185 let metasenv, subst, to_restrict, _ =
187 (fun t1 t2 (metasenv, subst, to_restrict, i) ->
189 let metasenv, subst =
190 unify test_eq_only metasenv subst context
191 (NCicSubstitution.lift s1 t1) (NCicSubstitution.lift s2 t2)
193 metasenv, subst, to_restrict, i-1
194 with UnificationFailure _ | Uncertain _ ->
195 metasenv, subst, i::to_restrict, i-1)
196 l1 l2 (metasenv, subst, [], List.length l1)
198 let metasenv, subst, _ =
199 NCicMetaSubst.restrict metasenv subst n1 to_restrict
203 | Invalid_argument _ -> assert false
204 | NCicMetaSubst.MetaSubstFailure msg ->
206 let _,_,term,_ = NCicUtils.lookup_subst n1 subst in
207 let term1 = NCicSubstitution.subst_meta lc1 term in
208 let term2 = NCicSubstitution.subst_meta lc2 term in
209 unify test_eq_only metasenv subst context term1 term2
210 with NCicUtils.Subst_not_found _-> raise (UnificationFailure msg))
212 | C.Meta (n,lc), t ->
214 let _,_,term,_ = NCicUtils.lookup_subst n subst in
215 let term = NCicSubstitution.subst_meta lc term in
216 unify test_eq_only metasenv subst context term t
217 with NCicUtils.Subst_not_found _->
218 instantiate test_eq_only metasenv subst context n lc t false)
220 | t, C.Meta (n,lc) ->
222 let _,_,term,_ = NCicUtils.lookup_subst n subst in
223 let term = NCicSubstitution.subst_meta lc term in
224 unify test_eq_only metasenv subst context t term
225 with NCicUtils.Subst_not_found _->
226 instantiate test_eq_only metasenv subst context n lc t true)
228 | NCic.Appl (NCic.Meta (i,l)::args), _ when List.mem_assoc i subst ->
229 let _,_,term,_ = NCicUtils.lookup_subst i subst in
230 let term = NCicSubstitution.subst_meta l term in
231 unify test_eq_only metasenv subst context (mk_appl term args) t2
233 | _, NCic.Appl (NCic.Meta (i,l)::args) when List.mem_assoc i subst ->
234 let _,_,term,_ = NCicUtils.lookup_subst i subst in
235 let term = NCicSubstitution.subst_meta l term in
236 unify test_eq_only metasenv subst context t1 (mk_appl term args)
238 | NCic.Appl (NCic.Meta (i,_)::_ as l1),
239 NCic.Appl (NCic.Meta (j,_)::_ as l2) when i=j ->
242 (fun (metasenv, subst) t1 t2 ->
243 unify test_eq_only metasenv subst context t1 t2)
244 (metasenv,subst) l1 l2
245 with Invalid_argument _ ->
246 raise (fail_exc metasenv subst context t1 t2))
248 | NCic.Appl (NCic.Meta (i,l)::args), _ when not (flexible args) ->
249 (* we verify that none of the args is a Meta,
250 since beta expanding w.r.t a metavariable makes no sense *)
251 let metasenv, subst, beta_expanded =
254 metasenv subst context t2 args
256 unify test_eq_only metasenv subst context
257 (C.Meta (i,l)) beta_expanded
259 | _, NCic.Appl (NCic.Meta (i,l)::args) when not(flexible args) ->
260 let metasenv, subst, beta_expanded =
263 metasenv subst context t1 args
265 unify test_eq_only metasenv subst context
266 beta_expanded (C.Meta (i,l))
268 (* processing this case here we avoid a useless small delta step *)
269 | (C.Appl ((C.Const r1) as _hd1::tl1), C.Appl (C.Const r2::tl2))
271 let relevance = NCicEnvironment.get_relevance r1 in
272 let relevance = match r1 with
273 | Ref.Ref (_,Ref.Con (_,_,lno)) ->
274 let _,relevance = HExtlib.split_nth lno relevance in
275 HExtlib.mk_list false lno @ relevance
278 let metasenv, subst, _ =
281 (fun (metasenv, subst, relevance) t1 t2 ->
283 match relevance with b::tl -> b,tl | _ -> true, [] in
284 let metasenv, subst =
285 try unify test_eq_only metasenv subst context t1 t2
286 with UnificationFailure _ | Uncertain _ when not b ->
289 metasenv, subst, relevance)
290 (metasenv, subst, relevance) tl1 tl2
291 with Invalid_argument _ ->
292 raise (uncert_exc metasenv subst context t1 t2)
296 | (C.Match (Ref.Ref (_,Ref.Ind (_,tyno,_)) as ref1,outtype1,term1,pl1),
297 C.Match (ref2,outtype2,term2,pl2)) ->
298 let _,_,itl,_,_ = NCicEnvironment.get_checked_indtys ref1 in
299 let _,_,ty,_ = List.nth itl tyno in
300 let rec remove_prods ~subst context ty =
301 let ty = NCicReduction.whd ~subst context ty in
304 | C.Prod (name,so,ta) ->
305 remove_prods ~subst ((name,(C.Decl so))::context) ta
309 match remove_prods ~subst [] ty with
310 | C.Sort C.Prop -> true
313 let rec remove_prods ~subst context ty =
314 let ty = NCicReduction.whd ~subst context ty in
317 | C.Prod (name,so,ta) ->
318 remove_prods ~subst ((name,(C.Decl so))::context) ta
321 if not (Ref.eq ref1 ref2) then
322 raise (uncert_exc metasenv subst context t1 t2)
324 let metasenv, subst =
325 unify test_eq_only metasenv subst context outtype1 outtype2 in
326 let metasenv, subst =
327 try unify test_eq_only metasenv subst context term1 term2
328 with UnificationFailure _ | Uncertain _ when is_prop ->
333 (fun (metasenv,subst) ->
334 unify test_eq_only metasenv subst context)
335 (metasenv, subst) pl1 pl2
336 with Invalid_argument _ ->
337 raise (uncert_exc metasenv subst context t1 t2))
338 | (C.Implicit _, _) | (_, C.Implicit _) -> assert false
339 | _ -> raise (uncert_exc metasenv subst context t1 t2)
341 let height_of is_whd = function
342 | NCic.Const (Ref.Ref (_,Ref.Def h))
343 | NCic.Const (Ref.Ref (_,Ref.Fix (_,_,h)))
344 | NCic.Appl(NCic.Const(Ref.Ref(_,Ref.Def h))::_)
345 | NCic.Appl(NCic.Const(Ref.Ref(_,Ref.Fix (_,_,h)))::_) -> h, false
346 | NCic.Meta _ | NCic.Appl (NCic.Meta _ :: _) -> max_int, true
347 | _ when is_whd -> 0, false
348 | _ -> 0, false (* !!! with max_int we diverge, with 0 we may do too much
351 let small_delta_step is_whd (_,_,t1,_ as m1) (_,_,t2,_ as m2) =
352 let h1, flex1 = height_of is_whd t1 in
353 let h2, flex2 = height_of is_whd t2 in
354 let delta = if h1 = h2 then max 0 (h1 -1) else min h1 h2 in
355 NCicReduction.reduce_machine ~delta ~subst context m1,
356 NCicReduction.reduce_machine ~delta ~subst context m2,
357 if is_whd && flex1 && flex2 then 0 else delta
359 let rec unif_machines metasenv subst = function
360 | ((k1,e1,t1,s1 as m1),(k2,e2,t2,s2 as m2),delta) ->
362 let relevance = [] (* TO BE UNDERSTOOD
364 | C.Const r -> NCicEnvironment.get_relevance r
366 let unif_from_stack t1 t2 b metasenv subst =
368 let t1 = NCicReduction.from_stack t1 in
369 let t2 = NCicReduction.from_stack t2 in
370 unif_machines metasenv subst (small_delta_step true t1 t2)
371 with UnificationFailure _ | Uncertain _ when not b ->
374 let rec check_stack l1 l2 r (metasenv, subst) =
376 | x1::tl1, x2::tl2, r::tr ->
377 check_stack tl1 tl2 tr
378 (unif_from_stack x1 x2 r metasenv subst)
379 | x1::tl1, x2::tl2, [] ->
380 check_stack tl1 tl2 []
381 (unif_from_stack x1 x2 true metasenv subst)
383 fo_unif test_eq_only metasenv subst
384 (NCicReduction.unwind (k1,e1,t1,List.rev l1))
385 (NCicReduction.unwind (k2,e2,t2,List.rev l2))
387 check_stack (List.rev s1) (List.rev s2) relevance (metasenv,subst)
388 with UnificationFailure _ | Uncertain _ when delta > 0 ->
389 let delta = delta - 1 in
390 let red = NCicReduction.reduce_machine ~delta ~subst context in
391 unif_machines metasenv subst (red m1,red m2,delta)
393 try fo_unif test_eq_only metasenv subst t1 t2
394 with UnificationFailure msg | Uncertain msg as exn ->
396 unif_machines metasenv subst
397 (small_delta_step false (0,[],t1,[]) (0,[],t2,[]))
399 | UnificationFailure _ -> raise (UnificationFailure msg)
400 | Uncertain _ -> raise exn
403 let unify = unify false;;
411 exception UnificationFailure of string Lazy.t;;
412 exception Uncertain of string Lazy.t;;
413 exception AssertFailure of string Lazy.t;;
415 let verbose = false;;
416 let debug_print = fun _ -> ()
418 let profiler_toa = HExtlib.profile "fo_unif_subst.type_of_aux'"
419 let profiler_beta_expand = HExtlib.profile "fo_unif_subst.beta_expand"
420 let profiler_deref = HExtlib.profile "fo_unif_subst.deref'"
421 let profiler_are_convertible = HExtlib.profile "fo_unif_subst.are_convertible"
423 let profile = HExtlib.profile "U/CicTypeChecker.type_of_aux'"
425 let type_of_aux' metasenv subst context term ugraph =
428 profile.HExtlib.profile
429 (CicTypeChecker.type_of_aux' ~subst metasenv context term) ugraph
431 CicTypeChecker.TypeCheckerFailure msg ->
435 "Kernel Type checking error:
436 %s\n%s\ncontext=\n%s\nmetasenv=\n%s\nsubstitution=\n%s\nException:\n%s.\nToo bad."
437 (CicMetaSubst.ppterm ~metasenv subst term)
438 (CicMetaSubst.ppterm ~metasenv [] term)
439 (CicMetaSubst.ppcontext ~metasenv subst context)
440 (CicMetaSubst.ppmetasenv subst metasenv)
441 (CicMetaSubst.ppsubst ~metasenv subst) (Lazy.force msg)) in
442 raise (AssertFailure msg)
443 | CicTypeChecker.AssertFailure msg ->
446 "Kernel Type checking assertion failure:
447 %s\n%s\ncontext=\n%s\nmetasenv=\n%s\nsubstitution=\n%s\nException:\n%s.\nToo bad."
448 (CicMetaSubst.ppterm ~metasenv subst term)
449 (CicMetaSubst.ppterm ~metasenv [] term)
450 (CicMetaSubst.ppcontext ~metasenv subst context)
451 (CicMetaSubst.ppmetasenv subst metasenv)
452 (CicMetaSubst.ppsubst ~metasenv subst) (Lazy.force msg)) in
453 raise (AssertFailure msg)
454 in profiler_toa.HExtlib.profile foo ()
457 let exists_a_meta l =
461 | Cic.Appl (Cic.Meta _::_) -> true
464 let rec deref subst t =
465 let snd (_,a,_) = a in
470 (CicSubstitution.subst_meta
471 l (snd (CicUtil.lookup_subst n subst)))
473 CicUtil.Subst_not_found _ -> t)
474 | Cic.Appl(Cic.Meta(n,l)::args) ->
475 (match deref subst (Cic.Meta(n,l)) with
476 | Cic.Lambda _ as t ->
477 deref subst (CicReduction.head_beta_reduce (Cic.Appl(t::args)))
478 | r -> Cic.Appl(r::args))
479 | Cic.Appl(((Cic.Lambda _) as t)::args) ->
480 deref subst (CicReduction.head_beta_reduce (Cic.Appl(t::args)))
485 let foo () = deref subst t
486 in profiler_deref.HExtlib.profile foo ()
488 exception WrongShape;;
489 let eta_reduce after_beta_expansion after_beta_expansion_body
490 before_beta_expansion
493 match before_beta_expansion,after_beta_expansion_body with
494 Cic.Appl l, Cic.Appl l' ->
495 let rec all_but_last check_last =
499 | [_] -> if check_last then raise WrongShape else []
500 | he::tl -> he::(all_but_last check_last tl)
502 let all_but_last check_last l =
503 match all_but_last check_last l with
508 let t = CicSubstitution.subst (Cic.Rel (-1)) (all_but_last true l') in
509 let all_but_last = all_but_last false l in
510 (* here we should test alpha-equivalence; however we know by
511 construction that here alpha_equivalence is equivalent to = *)
512 if t = all_but_last then
516 | _,_ -> after_beta_expansion
518 WrongShape -> after_beta_expansion
520 let rec beta_expand num test_equality_only metasenv subst context t arg ugraph =
521 let module S = CicSubstitution in
522 let module C = Cic in
524 let rec aux metasenv subst n context t' ugraph =
527 let subst,metasenv,ugraph1 =
528 fo_unif_subst test_equality_only subst context metasenv
529 (CicSubstitution.lift n arg) t' ugraph
532 subst,metasenv,C.Rel (1 + n),ugraph1
535 | UnificationFailure _ ->
537 | C.Rel m -> subst,metasenv,
538 (if m <= n then C.Rel m else C.Rel (m+1)),ugraph
539 | C.Var (uri,exp_named_subst) ->
540 let subst,metasenv,exp_named_subst',ugraph1 =
541 aux_exp_named_subst metasenv subst n context exp_named_subst ugraph
543 subst,metasenv,C.Var (uri,exp_named_subst'),ugraph1
545 (* andrea: in general, beta_expand can create badly typed
546 terms. This happens quite seldom in practice, UNLESS we
547 iterate on the local context. For this reason, we renounce
548 to iterate and just lift *)
552 Some t -> Some (CicSubstitution.lift 1 t)
554 subst, metasenv, C.Meta (i,l), ugraph
556 | C.Implicit _ as t -> subst,metasenv,t,ugraph
558 let subst,metasenv,te',ugraph1 =
559 aux metasenv subst n context te ugraph in
560 let subst,metasenv,ty',ugraph2 =
561 aux metasenv subst n context ty ugraph1 in
562 (* TASSI: sure this is in serial? *)
563 subst,metasenv,(C.Cast (te', ty')),ugraph2
565 let subst,metasenv,s',ugraph1 =
566 aux metasenv subst n context s ugraph in
567 let subst,metasenv,t',ugraph2 =
568 aux metasenv subst (n+1) ((Some (nn, C.Decl s))::context) t
571 (* TASSI: sure this is in serial? *)
572 subst,metasenv,(C.Prod (nn, s', t')),ugraph2
573 | C.Lambda (nn,s,t) ->
574 let subst,metasenv,s',ugraph1 =
575 aux metasenv subst n context s ugraph in
576 let subst,metasenv,t',ugraph2 =
577 aux metasenv subst (n+1) ((Some (nn, C.Decl s))::context) t ugraph1
579 (* TASSI: sure this is in serial? *)
580 subst,metasenv,(C.Lambda (nn, s', t')),ugraph2
581 | C.LetIn (nn,s,ty,t) ->
582 let subst,metasenv,s',ugraph1 =
583 aux metasenv subst n context s ugraph in
584 let subst,metasenv,ty',ugraph1 =
585 aux metasenv subst n context ty ugraph in
586 let subst,metasenv,t',ugraph2 =
587 aux metasenv subst (n+1) ((Some (nn, C.Def (s,ty)))::context) t
590 (* TASSI: sure this is in serial? *)
591 subst,metasenv,(C.LetIn (nn, s', ty', t')),ugraph2
593 let subst,metasenv,revl',ugraph1 =
595 (fun (subst,metasenv,appl,ugraph) t ->
596 let subst,metasenv,t',ugraph1 =
597 aux metasenv subst n context t ugraph in
598 subst,metasenv,(t'::appl),ugraph1
599 ) (subst,metasenv,[],ugraph) l
601 subst,metasenv,(C.Appl (List.rev revl')),ugraph1
602 | C.Const (uri,exp_named_subst) ->
603 let subst,metasenv,exp_named_subst',ugraph1 =
604 aux_exp_named_subst metasenv subst n context exp_named_subst ugraph
606 subst,metasenv,(C.Const (uri,exp_named_subst')),ugraph1
607 | C.MutInd (uri,i,exp_named_subst) ->
608 let subst,metasenv,exp_named_subst',ugraph1 =
609 aux_exp_named_subst metasenv subst n context exp_named_subst ugraph
611 subst,metasenv,(C.MutInd (uri,i,exp_named_subst')),ugraph1
612 | C.MutConstruct (uri,i,j,exp_named_subst) ->
613 let subst,metasenv,exp_named_subst',ugraph1 =
614 aux_exp_named_subst metasenv subst n context exp_named_subst ugraph
616 subst,metasenv,(C.MutConstruct (uri,i,j,exp_named_subst')),ugraph1
617 | C.MutCase (sp,i,outt,t,pl) ->
618 let subst,metasenv,outt',ugraph1 =
619 aux metasenv subst n context outt ugraph in
620 let subst,metasenv,t',ugraph2 =
621 aux metasenv subst n context t ugraph1 in
622 let subst,metasenv,revpl',ugraph3 =
624 (fun (subst,metasenv,pl,ugraph) t ->
625 let subst,metasenv,t',ugraph1 =
626 aux metasenv subst n context t ugraph in
627 subst,metasenv,(t'::pl),ugraph1
628 ) (subst,metasenv,[],ugraph2) pl
630 subst,metasenv,(C.MutCase (sp,i,outt', t', List.rev revpl')),ugraph3
631 (* TASSI: not sure this is serial *)
633 (*CSC: not implemented
634 let tylen = List.length fl in
637 (fun (name,i,ty,bo) -> (name, i, aux n ty, aux (n+tylen) bo))
640 C.Fix (i, substitutedfl)
642 subst,metasenv,(CicSubstitution.lift 1 t' ),ugraph
644 (*CSC: not implemented
645 let tylen = List.length fl in
648 (fun (name,ty,bo) -> (name, aux n ty, aux (n+tylen) bo))
651 C.CoFix (i, substitutedfl)
654 subst,metasenv,(CicSubstitution.lift 1 t'), ugraph
656 and aux_exp_named_subst metasenv subst n context ens ugraph =
658 (fun (uri,t) (subst,metasenv,l,ugraph) ->
659 let subst,metasenv,t',ugraph1 = aux metasenv subst n context t ugraph in
660 subst,metasenv,((uri,t')::l),ugraph1) ens (subst,metasenv,[],ugraph)
662 let argty,ugraph1 = type_of_aux' metasenv subst context arg ugraph in
664 FreshNamesGenerator.mk_fresh_name ~subst
665 metasenv context (Cic.Name ("Hbeta" ^ string_of_int num)) ~typ:argty
667 let subst,metasenv,t',ugraph2 = aux metasenv subst 0 context t ugraph1 in
668 let t'' = eta_reduce (C.Lambda (fresh_name,argty,t')) t' t in
669 subst, metasenv, t'', ugraph2
670 in profiler_beta_expand.HExtlib.profile foo ()
673 and beta_expand_many test_equality_only metasenv subst context t args ugraph =
674 let _,subst,metasenv,hd,ugraph =
676 (fun arg (num,subst,metasenv,t,ugraph) ->
677 let subst,metasenv,t,ugraph1 =
678 beta_expand num test_equality_only
679 metasenv subst context t arg ugraph
681 num+1,subst,metasenv,t,ugraph1
682 ) args (1,subst,metasenv,t,ugraph)
684 subst,metasenv,hd,ugraph
686 and warn_if_not_unique xxx to1 to2 carr car1 car2 =
689 | (m2,_,c2,c2')::_ ->
690 let m1,c1,c1' = carr,to1,to2 in
692 function Some (_,t) -> CicPp.ppterm t
696 ("There are two minimal joins of "^ CoercDb.string_of_carr car1^" and "^
697 CoercDb.string_of_carr car2^": " ^
698 CoercDb.string_of_carr m1^" via "^unopt c1^" + "^
699 unopt c1'^" and "^ CoercDb.string_of_carr m2^" via "^
700 unopt c2^" + "^unopt c2')
702 (* NUOVA UNIFICAZIONE *)
703 (* A substitution is a (int * Cic.term) list that associates a
704 metavariable i with its body.
705 A metaenv is a (int * Cic.term) list that associate a metavariable
707 fo_unif_new takes a metasenv, a context, two terms t1 and t2 and gives back
708 a new substitution which is _NOT_ unwinded. It must be unwinded before
711 and fo_unif_subst test_equality_only subst context metasenv t1 t2 ugraph =
712 let module C = Cic in
713 let module R = CicReduction in
714 let module S = CicSubstitution in
715 let t1 = deref subst t1 in
716 let t2 = deref subst t2 in
717 let (&&&) a b = (a && b) || ((not a) && (not b)) in
718 (* let bef = Sys.time () in *)
720 if not (CicUtil.is_meta_closed (CicMetaSubst.apply_subst subst t1) &&& CicUtil.is_meta_closed (CicMetaSubst.apply_subst subst t2)) then
724 R.are_convertible ~subst ~metasenv context t1 t2 ugraph
725 in profiler_are_convertible.HExtlib.profile foo ()
727 (* let aft = Sys.time () in
728 if (aft -. bef > 2.0) then prerr_endline ("LEEEENTO: " ^
729 CicMetaSubst.ppterm_in_context subst ~metasenv t1 context ^ " <===> " ^
730 CicMetaSubst.ppterm_in_context subst ~metasenv t2 context); *)
732 subst, metasenv, ugraph
735 | (C.Meta (n,ln), C.Meta (m,lm)) when n=m ->
736 let _,subst,metasenv,ugraph1 =
739 (fun (j,subst,metasenv,ugraph) t1 t2 ->
742 | _,None -> j+1,subst,metasenv,ugraph
743 | Some t1', Some t2' ->
744 (* First possibility: restriction *)
745 (* Second possibility: unification *)
746 (* Third possibility: convertibility *)
749 ~subst ~metasenv context t1' t2' ugraph
752 j+1,subst,metasenv, ugraph1
755 let subst,metasenv,ugraph2 =
758 subst context metasenv t1' t2' ugraph
760 j+1,subst,metasenv,ugraph2
763 | UnificationFailure _ ->
764 debug_print (lazy ("restringo Meta n." ^ (string_of_int n) ^ "on variable n." ^ (string_of_int j)));
765 let metasenv, subst =
766 CicMetaSubst.restrict
767 subst [(n,j)] metasenv in
768 j+1,subst,metasenv,ugraph1)
769 ) (1,subst,metasenv,ugraph) ln lm
773 (UnificationFailure (lazy "1"))
776 "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."
777 (CicMetaSubst.ppterm ~metasenv subst t1)
778 (CicMetaSubst.ppterm ~metasenv subst t2))) *)
779 | Invalid_argument _ ->
781 (UnificationFailure (lazy "2")))
784 "Error trying to unify %s with %s: the lengths of the two local contexts do not match."
785 (CicMetaSubst.ppterm ~metasenv subst t1)
786 (CicMetaSubst.ppterm ~metasenv subst t2)))) *)
787 in subst,metasenv,ugraph1
788 | (C.Meta (n,_), C.Meta (m,_)) when n>m ->
789 fo_unif_subst test_equality_only subst context metasenv t2 t1 ugraph
791 | (t, C.Meta (n,l)) ->
794 C.Meta (n,_), C.Meta (m,_) when n < m -> false
795 | _, C.Meta _ -> false
798 let lower = fun x y -> if swap then y else x in
799 let upper = fun x y -> if swap then x else y in
800 let fo_unif_subst_ordered
801 test_equality_only subst context metasenv m1 m2 ugraph =
802 fo_unif_subst test_equality_only subst context metasenv
803 (lower m1 m2) (upper m1 m2) ugraph
806 let subst,metasenv,ugraph1 =
807 let (_,_,meta_type) = CicUtil.lookup_meta n metasenv in
810 type_of_aux' metasenv subst context t ugraph
814 subst context metasenv tyt (S.subst_meta l meta_type) ugraph1
816 UnificationFailure _ as e -> raise e
817 | Uncertain msg -> raise (UnificationFailure msg)
819 debug_print (lazy "siamo allo huge hack");
820 (* TODO huge hack!!!!
821 * we keep on unifying/refining in the hope that
822 * the problem will be eventually solved.
823 * In the meantime we're breaking a big invariant:
824 * the terms that we are unifying are no longer well
825 * typed in the current context (in the worst case
826 * we could even diverge) *)
827 (subst, metasenv,ugraph)) in
828 let t',metasenv,subst =
830 CicMetaSubst.delift n subst context metasenv l t
832 (CicMetaSubst.MetaSubstFailure msg)->
833 raise (UnificationFailure msg)
834 | (CicMetaSubst.Uncertain msg) -> raise (Uncertain msg)
838 C.Sort (C.Type u) when not test_equality_only ->
839 let u' = CicUniv.fresh () in
840 let s = C.Sort (C.Type u') in
843 CicUniv.add_ge (upper u u') (lower u u') ugraph1
847 CicUniv.UniverseInconsistency msg ->
848 raise (UnificationFailure msg))
851 (* Unifying the types may have already instantiated n. Let's check *)
853 let (_, oldt,_) = CicUtil.lookup_subst n subst in
854 let lifted_oldt = S.subst_meta l oldt in
855 fo_unif_subst_ordered
856 test_equality_only subst context metasenv t lifted_oldt ugraph2
858 CicUtil.Subst_not_found _ ->
859 let (_, context, ty) = CicUtil.lookup_meta n metasenv in
860 let subst = (n, (context, t'',ty)) :: subst in
862 List.filter (fun (m,_,_) -> not (n = m)) metasenv in
863 subst, metasenv, ugraph2
865 | (C.Var (uri1,exp_named_subst1),C.Var (uri2,exp_named_subst2))
866 | (C.Const (uri1,exp_named_subst1),C.Const (uri2,exp_named_subst2)) ->
867 if UriManager.eq uri1 uri2 then
868 fo_unif_subst_exp_named_subst test_equality_only subst context metasenv
869 exp_named_subst1 exp_named_subst2 ugraph
871 raise (UnificationFailure (lazy
873 "Can't unify %s with %s due to different constants"
874 (CicMetaSubst.ppterm ~metasenv subst t1)
875 (CicMetaSubst.ppterm ~metasenv subst t2))))
876 | C.MutInd (uri1,i1,exp_named_subst1),C.MutInd (uri2,i2,exp_named_subst2) ->
877 if UriManager.eq uri1 uri2 && i1 = i2 then
878 fo_unif_subst_exp_named_subst
880 subst context metasenv exp_named_subst1 exp_named_subst2 ugraph
882 raise (UnificationFailure
885 "Can't unify %s with %s due to different inductive principles"
886 (CicMetaSubst.ppterm ~metasenv subst t1)
887 (CicMetaSubst.ppterm ~metasenv subst t2))))
888 | C.MutConstruct (uri1,i1,j1,exp_named_subst1),
889 C.MutConstruct (uri2,i2,j2,exp_named_subst2) ->
890 if UriManager.eq uri1 uri2 && i1 = i2 && j1 = j2 then
891 fo_unif_subst_exp_named_subst
893 subst context metasenv exp_named_subst1 exp_named_subst2 ugraph
895 raise (UnificationFailure
898 "Can't unify %s with %s due to different inductive constructors"
899 (CicMetaSubst.ppterm ~metasenv subst t1)
900 (CicMetaSubst.ppterm ~metasenv subst t2))))
901 | (C.Implicit _, _) | (_, C.Implicit _) -> assert false
902 | (C.Cast (te,ty), t2) -> fo_unif_subst test_equality_only
903 subst context metasenv te t2 ugraph
904 | (t1, C.Cast (te,ty)) -> fo_unif_subst test_equality_only
905 subst context metasenv t1 te ugraph
906 | (C.Lambda (n1,s1,t1), C.Lambda (_,s2,t2)) ->
907 let subst',metasenv',ugraph1 =
908 fo_unif_subst test_equality_only subst context metasenv s1 s2 ugraph
910 fo_unif_subst test_equality_only
911 subst' ((Some (n1,(C.Decl s1)))::context) metasenv' t1 t2 ugraph1
912 | (C.LetIn (_,s1,ty1,t1), t2)
913 | (t2, C.LetIn (_,s1,ty1,t1)) ->
915 test_equality_only subst context metasenv t2 (S.subst s1 t1) ugraph
916 | (C.Appl l1, C.Appl l2) ->
917 (* andrea: this case should be probably rewritten in the
920 | C.Meta (i,_)::args1, C.Meta (j,_)::args2 when i = j ->
923 (fun (subst,metasenv,ugraph) t1 t2 ->
925 test_equality_only subst context metasenv t1 t2 ugraph)
926 (subst,metasenv,ugraph) l1 l2
927 with (Invalid_argument msg) ->
928 raise (UnificationFailure (lazy msg)))
929 | C.Meta (i,l)::args, _ when not(exists_a_meta args) ->
930 (* we verify that none of the args is a Meta,
931 since beta expanding with respoect to a metavariable
935 let (_,t,_) = CicUtil.lookup_subst i subst in
936 let lifted = S.subst_meta l t in
937 let reduced = CicReduction.head_beta_reduce (Cic.Appl (lifted::args)) in
940 subst context metasenv reduced t2 ugraph
941 with CicUtil.Subst_not_found _ -> *)
942 let subst,metasenv,beta_expanded,ugraph1 =
944 test_equality_only metasenv subst context t2 args ugraph
946 fo_unif_subst test_equality_only subst context metasenv
947 (C.Meta (i,l)) beta_expanded ugraph1
948 | _, C.Meta (i,l)::args when not(exists_a_meta args) ->
950 let (_,t,_) = CicUtil.lookup_subst i subst in
951 let lifted = S.subst_meta l t in
952 let reduced = CicReduction.head_beta_reduce (Cic.Appl (lifted::args)) in
955 subst context metasenv t1 reduced ugraph
956 with CicUtil.Subst_not_found _ -> *)
957 let subst,metasenv,beta_expanded,ugraph1 =
960 metasenv subst context t1 args ugraph
962 fo_unif_subst test_equality_only subst context metasenv
963 (C.Meta (i,l)) beta_expanded ugraph1
965 let lr1 = List.rev l1 in
966 let lr2 = List.rev l2 in
968 fo_unif_l test_equality_only subst metasenv (l1,l2) ugraph =
971 | _,[] -> assert false
974 test_equality_only subst context metasenv h1 h2 ugraph
977 fo_unif_subst test_equality_only subst context metasenv
978 h (C.Appl (List.rev l)) ugraph
979 | ((h1::l1),(h2::l2)) ->
980 let subst', metasenv',ugraph1 =
983 subst context metasenv h1 h2 ugraph
986 test_equality_only subst' metasenv' (l1,l2) ugraph1
990 test_equality_only subst metasenv (lr1, lr2) ugraph
992 | UnificationFailure s
993 | Uncertain s as exn ->
996 | (((Cic.Const (uri1, ens1)) as cc1) :: tl1),
997 (((Cic.Const (uri2, ens2)) as cc2) :: tl2) when
998 CoercDb.is_a_coercion cc1 <> None &&
999 CoercDb.is_a_coercion cc2 <> None &&
1000 not (UriManager.eq uri1 uri2) ->
1002 prerr_endline ("<<<< " ^ CicMetaSubst.ppterm_in_context ~metasenv subst (C.Appl l1) context ^ " <==> " ^ CicMetaSubst.ppterm_in_context ~metasenv subst (C.Appl l2) context);
1004 let inner_coerced t =
1005 let t = CicMetaSubst.apply_subst subst t in
1009 (match CoercGraph.coerced_arg l with
1011 | Some (t,_) -> aux (List.hd l) t t)
1014 aux (Cic.Implicit None) (Cic.Implicit None) t
1016 let c1,last_tl1 = inner_coerced (Cic.Appl l1) in
1017 let c2,last_tl2 = inner_coerced (Cic.Appl l2) in
1020 CoercDb.is_a_coercion c1, CoercDb.is_a_coercion c2
1022 | Some (s1,_,_,_,_), Some (s2,_,_,_,_) -> s1, s2
1025 let head1_c, head2_c =
1027 CoercDb.is_a_coercion cc1, CoercDb.is_a_coercion cc2
1029 | Some (_,t1,_,_,_), Some (_,t2,_,_,_) -> t1, t2
1032 let unfold uri ens args =
1034 CicEnvironment.get_obj CicUniv.oblivion_ugraph uri
1038 | Cic.Constant (_,Some bo,_,_,_) ->
1039 CicReduction.head_beta_reduce ~delta:false
1040 (Cic.Appl (bo::args))
1043 let conclude subst metasenv ugraph last_tl1' last_tl2' =
1044 let subst',metasenv,ugraph =
1047 ("OK " ^ CicMetaSubst.ppterm_in_context ~metasenv subst last_tl1' context ^
1048 " <==> " ^ CicMetaSubst.ppterm_in_context ~metasenv subst last_tl2' context);
1050 fo_unif_subst test_equality_only subst context
1051 metasenv last_tl1' last_tl2' ugraph
1053 if subst = subst' then raise exn
1056 let subst,metasenv,ugrph as res =
1058 fo_unif_subst test_equality_only subst' context
1059 metasenv (C.Appl l1) (C.Appl l2) ugraph
1063 (">>>> "^CicMetaSubst.ppterm_in_context ~metasenv subst (C.Appl l1) context ^
1064 " <==> "^CicMetaSubst.ppterm_in_context ~metasenv subst (C.Appl l2) context);
1068 if CoercDb.eq_carr car1 car2 then
1069 match last_tl1,last_tl2 with
1070 | C.Meta (i1,_),C.Meta(i2,_) when i1 = i2 -> raise exn
1073 let subst,metasenv,ugraph =
1074 fo_unif_subst test_equality_only subst context
1075 metasenv last_tl1 last_tl2 ugraph
1077 fo_unif_subst test_equality_only subst context
1078 metasenv (Cic.Appl l1) (Cic.Appl l2) ugraph
1079 | _ when CoercDb.eq_carr head1_c head2_c ->
1080 (* composite VS composition + metas avoiding
1081 * coercions not only in coerced position *)
1082 if c1 <> cc1 && c2 <> cc2 then
1083 conclude subst metasenv ugraph
1088 unfold uri1 ens1 tl1, Cic.Appl (cc2::tl2)
1090 Cic.Appl (cc1::tl1), unfold uri2 ens2 tl2
1092 fo_unif_subst test_equality_only subst context
1093 metasenv l1 l2 ugraph
1097 match last_tl1 with Cic.Meta _ -> true | _ -> false in
1099 match last_tl2 with Cic.Meta _ -> true | _ -> false in
1100 if not (grow1 || grow2) then
1101 (* no flexible terminals -> no pullback, but
1102 * we still unify them, in some cases it helps *)
1103 conclude subst metasenv ugraph last_tl1 last_tl2
1107 metasenv subst context (grow1,car1) (grow2,car2)
1111 | (carr,metasenv,to1,to2)::xxx ->
1112 warn_if_not_unique xxx to1 to2 carr car1 car2;
1113 let last_tl1',(subst,metasenv,ugraph) =
1114 match grow1,to1 with
1115 | true,Some (last,coerced) ->
1117 fo_unif_subst test_equality_only subst context
1118 metasenv coerced last_tl1 ugraph
1119 | _ -> last_tl1,(subst,metasenv,ugraph)
1121 let last_tl2',(subst,metasenv,ugraph) =
1122 match grow2,to2 with
1123 | true,Some (last,coerced) ->
1125 fo_unif_subst test_equality_only subst context
1126 metasenv coerced last_tl2 ugraph
1127 | _ -> last_tl2,(subst,metasenv,ugraph)
1129 conclude subst metasenv ugraph last_tl1' last_tl2')
1131 (* {{{ CSC: This is necessary because of the "elim H" tactic
1132 where the type of H is only reducible to an
1133 inductive type. This could be extended from inductive
1134 types to any rigid term. However, the code is
1135 duplicated in two places: inside applications and
1136 outside them. Probably it would be better to
1137 work with lambda-bar terms instead. *)
1138 | (Cic.MutInd _::_, Cic.MutInd _::_) -> raise exn
1139 | (_, Cic.MutInd _::_) ->
1140 let t1' = R.whd ~subst context t1 in
1142 C.Appl (C.MutInd _::_) ->
1143 fo_unif_subst test_equality_only
1144 subst context metasenv t1' t2 ugraph
1145 | _ -> raise (UnificationFailure (lazy "88")))
1146 | (Cic.MutInd _::_,_) ->
1147 let t2' = R.whd ~subst context t2 in
1149 C.Appl (C.MutInd _::_) ->
1150 fo_unif_subst test_equality_only
1151 subst context metasenv t1 t2' ugraph
1154 (lazy ("not a mutind :"^
1155 CicMetaSubst.ppterm ~metasenv subst t2 ))))
1158 | (C.MutCase (_,_,outt1,t1',pl1), C.MutCase (_,_,outt2,t2',pl2))->
1159 let subst', metasenv',ugraph1 =
1160 fo_unif_subst test_equality_only subst context metasenv outt1 outt2
1162 let subst'',metasenv'',ugraph2 =
1163 fo_unif_subst test_equality_only subst' context metasenv' t1' t2'
1167 (fun (subst,metasenv,ugraph) t1 t2 ->
1169 test_equality_only subst context metasenv t1 t2 ugraph
1170 ) (subst'',metasenv'',ugraph2) pl1 pl2
1172 Invalid_argument _ ->
1173 raise (UnificationFailure (lazy "6.1")))
1175 "Error trying to unify %s with %s: the number of branches is not the same."
1176 (CicMetaSubst.ppterm ~metasenv subst t1)
1177 (CicMetaSubst.ppterm ~metasenv subst t2)))) *)
1178 | (C.Rel _, _) | (_, C.Rel _) ->
1180 subst, metasenv,ugraph
1182 raise (UnificationFailure (lazy
1184 "Can't unify %s with %s because they are not convertible"
1185 (CicMetaSubst.ppterm ~metasenv subst t1)
1186 (CicMetaSubst.ppterm ~metasenv subst t2))))
1187 | (C.Appl (C.Meta(i,l)::args),t2) when not(exists_a_meta args) ->
1188 let subst,metasenv,beta_expanded,ugraph1 =
1190 test_equality_only metasenv subst context t2 args ugraph
1192 fo_unif_subst test_equality_only subst context metasenv
1193 (C.Meta (i,l)) beta_expanded ugraph1
1194 | (t1,C.Appl (C.Meta(i,l)::args)) when not(exists_a_meta args) ->
1195 let subst,metasenv,beta_expanded,ugraph1 =
1197 test_equality_only metasenv subst context t1 args ugraph
1199 fo_unif_subst test_equality_only subst context metasenv
1200 beta_expanded (C.Meta (i,l)) ugraph1
1201 (* Works iff there are no arguments applied to it; similar to the
1203 | (_, C.MutInd _) ->
1204 let t1' = R.whd ~subst context t1 in
1207 fo_unif_subst test_equality_only
1208 subst context metasenv t1' t2 ugraph
1209 | _ -> raise (UnificationFailure (lazy "8")))
1211 | (C.Prod (n1,s1,t1), C.Prod (_,s2,t2)) ->
1212 let subst',metasenv',ugraph1 =
1213 fo_unif_subst true subst context metasenv s1 s2 ugraph
1215 fo_unif_subst test_equality_only
1216 subst' ((Some (n1,(C.Decl s1)))::context) metasenv' t1 t2 ugraph1
1218 (match CicReduction.whd ~subst context t2 with
1220 fo_unif_subst test_equality_only subst context metasenv t1 t2 ugraph
1221 | _ -> raise (UnificationFailure (lazy (CicMetaSubst.ppterm ~metasenv subst t2^"Not a product"))))
1223 (match CicReduction.whd ~subst context t1 with
1225 fo_unif_subst test_equality_only subst context metasenv t1 t2 ugraph
1226 | _ -> raise (UnificationFailure (lazy (CicMetaSubst.ppterm ~metasenv subst t1^"Not a product"))))
1228 (* delta-beta reduction should almost never be a problem for
1230 1. long computations require iota reduction
1231 2. it is extremely rare that a close term t1 (that could be unified
1232 to t2) beta-delta reduces to t1' while t2 does not beta-delta
1233 reduces in the same way. This happens only if one meta of t2
1234 occurs in head position during beta reduction. In this unluky
1235 case too much reduction will be performed on t1 and unification
1236 will surely fail. *)
1237 let t1' = CicReduction.head_beta_reduce ~delta:true t1 in
1238 let t2' = CicReduction.head_beta_reduce ~delta:true t2 in
1239 if t1 = t1' && t2 = t2' then
1240 raise (UnificationFailure
1243 "Can't unify %s with %s because they are not convertible"
1244 (CicMetaSubst.ppterm ~metasenv subst t1)
1245 (CicMetaSubst.ppterm ~metasenv subst t2))))
1248 fo_unif_subst test_equality_only subst context metasenv t1' t2' ugraph
1250 UnificationFailure _
1252 raise (UnificationFailure
1255 "Can't unify %s with %s because they are not convertible"
1256 (CicMetaSubst.ppterm ~metasenv subst t1)
1257 (CicMetaSubst.ppterm ~metasenv subst t2))))
1259 and fo_unif_subst_exp_named_subst test_equality_only subst context metasenv
1260 exp_named_subst1 exp_named_subst2 ugraph
1264 (fun (subst,metasenv,ugraph) (uri1,t1) (uri2,t2) ->
1265 assert (uri1=uri2) ;
1266 fo_unif_subst test_equality_only subst context metasenv t1 t2 ugraph
1267 ) (subst,metasenv,ugraph) exp_named_subst1 exp_named_subst2
1269 Invalid_argument _ ->
1274 UriManager.string_of_uri uri ^ " := " ^ (CicMetaSubst.ppterm ~metasenv subst t)
1277 raise (UnificationFailure (lazy (sprintf
1278 "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))))
1280 (* A substitution is a (int * Cic.term) list that associates a *)
1281 (* metavariable i with its body. *)
1282 (* metasenv is of type Cic.metasenv *)
1283 (* fo_unif takes a metasenv, a context, two terms t1 and t2 and gives back *)
1284 (* a new substitution which is already unwinded and ready to be applied and *)
1285 (* a new metasenv in which some hypothesis in the contexts of the *)
1286 (* metavariables may have been restricted. *)
1287 let fo_unif metasenv context t1 t2 ugraph =
1288 fo_unif_subst false [] context metasenv t1 t2 ugraph ;;
1290 let enrich_msg msg subst context metasenv t1 t2 ugraph =
1293 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"
1294 (CicMetaSubst.ppterm ~metasenv subst t1)
1296 let ty_t1,_ = type_of_aux' metasenv subst context t1 ugraph in
1299 | UnificationFailure s
1301 | AssertFailure s -> sprintf "MALFORMED(t1): \n<BEGIN>%s\n<END>" (Lazy.force s))
1302 (CicMetaSubst.ppterm ~metasenv subst t2)
1304 let ty_t2,_ = type_of_aux' metasenv subst context t2 ugraph in
1307 | UnificationFailure s
1309 | AssertFailure s -> sprintf "MALFORMED(t2): \n<BEGIN>%s\n<END>" (Lazy.force s))
1310 (CicMetaSubst.ppcontext ~metasenv subst context)
1311 (CicMetaSubst.ppmetasenv subst metasenv)
1312 (CicMetaSubst.ppsubst ~metasenv subst) (Lazy.force msg)
1314 sprintf "Unification error unifying %s of type %s with %s of type %s in context\n%s\nand metasenv\n%s\nbecause %s"
1315 (CicMetaSubst.ppterm_in_context ~metasenv subst t1 context)
1317 let ty_t1,_ = type_of_aux' metasenv subst context t1 ugraph in
1318 CicMetaSubst.ppterm_in_context ~metasenv subst ty_t1 context
1320 | UnificationFailure s
1322 | AssertFailure s -> sprintf "MALFORMED(t1): \n<BEGIN>%s\n<END>" (Lazy.force s))
1323 (CicMetaSubst.ppterm_in_context ~metasenv subst t2 context)
1325 let ty_t2,_ = type_of_aux' metasenv subst context t2 ugraph in
1326 CicMetaSubst.ppterm_in_context ~metasenv subst ty_t2 context
1328 | UnificationFailure s
1330 | AssertFailure s -> sprintf "MALFORMED(t2): \n<BEGIN>%s\n<END>" (Lazy.force s))
1331 (CicMetaSubst.ppcontext ~metasenv subst context)
1332 (CicMetaSubst.ppmetasenv subst metasenv)
1336 let fo_unif_subst subst context metasenv t1 t2 ugraph =
1338 fo_unif_subst false subst context metasenv t1 t2 ugraph
1340 | AssertFailure msg ->
1341 raise (AssertFailure (enrich_msg msg subst context metasenv t1 t2 ugraph))
1342 | UnificationFailure msg ->
1343 raise (UnificationFailure (enrich_msg msg subst context metasenv t1 t2 ugraph))