1 (* Copyright (C) 2000, HELM Team.
3 * This file is part of HELM, an Hypertextual, Electronic
4 * Library of Mathematics, developed at the Computer Science
5 * Department, University of Bologna, Italy.
7 * HELM is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * HELM is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with HELM; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
22 * For details, see the HELM World-Wide-Web page,
23 * http://cs.unibo.it/helm/.
30 exception UnificationFailure of string Lazy.t;;
31 exception Uncertain of string Lazy.t;;
32 exception AssertFailure of string Lazy.t;;
35 let debug_print = fun _ -> ()
37 let profiler_toa = HExtlib.profile "fo_unif_subst.type_of_aux'"
38 let profiler_beta_expand = HExtlib.profile "fo_unif_subst.beta_expand"
39 let profiler_deref = HExtlib.profile "fo_unif_subst.deref'"
40 let profiler_are_convertible = HExtlib.profile "fo_unif_subst.are_convertible"
42 let profile = HExtlib.profile "U/CicTypeChecker.type_of_aux'"
44 let type_of_aux' metasenv subst context term ugraph =
47 profile.HExtlib.profile
48 (CicTypeChecker.type_of_aux' ~subst metasenv context term) ugraph
50 CicTypeChecker.TypeCheckerFailure msg ->
54 "Kernel Type checking error:
55 %s\n%s\ncontext=\n%s\nmetasenv=\n%s\nsubstitution=\n%s\nException:\n%s.\nToo bad."
56 (CicMetaSubst.ppterm ~metasenv subst term)
57 (CicMetaSubst.ppterm ~metasenv [] term)
58 (CicMetaSubst.ppcontext ~metasenv subst context)
59 (CicMetaSubst.ppmetasenv subst metasenv)
60 (CicMetaSubst.ppsubst ~metasenv subst) (Lazy.force msg)) in
61 raise (AssertFailure msg)
62 | CicTypeChecker.AssertFailure msg ->
65 "Kernel Type checking assertion failure:
66 %s\n%s\ncontext=\n%s\nmetasenv=\n%s\nsubstitution=\n%s\nException:\n%s.\nToo bad."
67 (CicMetaSubst.ppterm ~metasenv subst term)
68 (CicMetaSubst.ppterm ~metasenv [] term)
69 (CicMetaSubst.ppcontext ~metasenv subst context)
70 (CicMetaSubst.ppmetasenv subst metasenv)
71 (CicMetaSubst.ppsubst ~metasenv subst) (Lazy.force msg)) in
72 raise (AssertFailure msg)
73 in profiler_toa.HExtlib.profile foo ()
80 | Cic.Appl (Cic.Meta _::_) -> true
83 let rec deref subst t =
84 let snd (_,a,_) = a in
89 (CicSubstitution.subst_meta
90 l (snd (CicUtil.lookup_subst n subst)))
92 CicUtil.Subst_not_found _ -> t)
93 | Cic.Appl(Cic.Meta(n,l)::args) ->
94 (match deref subst (Cic.Meta(n,l)) with
95 | Cic.Lambda _ as t ->
96 deref subst (CicReduction.head_beta_reduce (Cic.Appl(t::args)))
97 | r -> Cic.Appl(r::args))
98 | Cic.Appl(((Cic.Lambda _) as t)::args) ->
99 deref subst (CicReduction.head_beta_reduce (Cic.Appl(t::args)))
104 let foo () = deref subst t
105 in profiler_deref.HExtlib.profile foo ()
107 exception WrongShape;;
108 let eta_reduce after_beta_expansion after_beta_expansion_body
109 before_beta_expansion
112 match before_beta_expansion,after_beta_expansion_body with
113 Cic.Appl l, Cic.Appl l' ->
114 let rec all_but_last check_last =
118 | [_] -> if check_last then raise WrongShape else []
119 | he::tl -> he::(all_but_last check_last tl)
121 let all_but_last check_last l =
122 match all_but_last check_last l with
127 let t = CicSubstitution.subst (Cic.Rel (-1)) (all_but_last true l') in
128 let all_but_last = all_but_last false l in
129 (* here we should test alpha-equivalence; however we know by
130 construction that here alpha_equivalence is equivalent to = *)
131 if t = all_but_last then
135 | _,_ -> after_beta_expansion
137 WrongShape -> after_beta_expansion
139 let rec beta_expand test_equality_only metasenv subst context t arg ugraph =
140 let module S = CicSubstitution in
141 let module C = Cic in
143 let rec aux metasenv subst n context t' ugraph =
146 let subst,metasenv,ugraph1 =
147 fo_unif_subst test_equality_only subst context metasenv
148 (CicSubstitution.lift n arg) t' ugraph
151 subst,metasenv,C.Rel (1 + n),ugraph1
154 | UnificationFailure _ ->
156 | C.Rel m -> subst,metasenv,
157 (if m <= n then C.Rel m else C.Rel (m+1)),ugraph
158 | C.Var (uri,exp_named_subst) ->
159 let subst,metasenv,exp_named_subst',ugraph1 =
160 aux_exp_named_subst metasenv subst n context exp_named_subst ugraph
162 subst,metasenv,C.Var (uri,exp_named_subst'),ugraph1
164 (* andrea: in general, beta_expand can create badly typed
165 terms. This happens quite seldom in practice, UNLESS we
166 iterate on the local context. For this reason, we renounce
167 to iterate and just lift *)
171 Some t -> Some (CicSubstitution.lift 1 t)
173 subst, metasenv, C.Meta (i,l), ugraph
175 | C.Implicit _ as t -> subst,metasenv,t,ugraph
177 let subst,metasenv,te',ugraph1 =
178 aux metasenv subst n context te ugraph in
179 let subst,metasenv,ty',ugraph2 =
180 aux metasenv subst n context ty ugraph1 in
181 (* TASSI: sure this is in serial? *)
182 subst,metasenv,(C.Cast (te', ty')),ugraph2
184 let subst,metasenv,s',ugraph1 =
185 aux metasenv subst n context s ugraph in
186 let subst,metasenv,t',ugraph2 =
187 aux metasenv subst (n+1) ((Some (nn, C.Decl s))::context) t
190 (* TASSI: sure this is in serial? *)
191 subst,metasenv,(C.Prod (nn, s', t')),ugraph2
192 | C.Lambda (nn,s,t) ->
193 let subst,metasenv,s',ugraph1 =
194 aux metasenv subst n context s ugraph in
195 let subst,metasenv,t',ugraph2 =
196 aux metasenv subst (n+1) ((Some (nn, C.Decl s))::context) t ugraph1
198 (* TASSI: sure this is in serial? *)
199 subst,metasenv,(C.Lambda (nn, s', t')),ugraph2
200 | C.LetIn (nn,s,t) ->
201 let subst,metasenv,s',ugraph1 =
202 aux metasenv subst n context s ugraph in
203 let subst,metasenv,t',ugraph2 =
204 aux metasenv subst (n+1) ((Some (nn, C.Def (s,None)))::context) t
207 (* TASSI: sure this is in serial? *)
208 subst,metasenv,(C.LetIn (nn, s', t')),ugraph2
210 let subst,metasenv,revl',ugraph1 =
212 (fun (subst,metasenv,appl,ugraph) t ->
213 let subst,metasenv,t',ugraph1 =
214 aux metasenv subst n context t ugraph in
215 subst,metasenv,(t'::appl),ugraph1
216 ) (subst,metasenv,[],ugraph) l
218 subst,metasenv,(C.Appl (List.rev revl')),ugraph1
219 | C.Const (uri,exp_named_subst) ->
220 let subst,metasenv,exp_named_subst',ugraph1 =
221 aux_exp_named_subst metasenv subst n context exp_named_subst ugraph
223 subst,metasenv,(C.Const (uri,exp_named_subst')),ugraph1
224 | C.MutInd (uri,i,exp_named_subst) ->
225 let subst,metasenv,exp_named_subst',ugraph1 =
226 aux_exp_named_subst metasenv subst n context exp_named_subst ugraph
228 subst,metasenv,(C.MutInd (uri,i,exp_named_subst')),ugraph1
229 | C.MutConstruct (uri,i,j,exp_named_subst) ->
230 let subst,metasenv,exp_named_subst',ugraph1 =
231 aux_exp_named_subst metasenv subst n context exp_named_subst ugraph
233 subst,metasenv,(C.MutConstruct (uri,i,j,exp_named_subst')),ugraph1
234 | C.MutCase (sp,i,outt,t,pl) ->
235 let subst,metasenv,outt',ugraph1 =
236 aux metasenv subst n context outt ugraph in
237 let subst,metasenv,t',ugraph2 =
238 aux metasenv subst n context t ugraph1 in
239 let subst,metasenv,revpl',ugraph3 =
241 (fun (subst,metasenv,pl,ugraph) t ->
242 let subst,metasenv,t',ugraph1 =
243 aux metasenv subst n context t ugraph in
244 subst,metasenv,(t'::pl),ugraph1
245 ) (subst,metasenv,[],ugraph2) pl
247 subst,metasenv,(C.MutCase (sp,i,outt', t', List.rev revpl')),ugraph3
248 (* TASSI: not sure this is serial *)
250 (*CSC: not implemented
251 let tylen = List.length fl in
254 (fun (name,i,ty,bo) -> (name, i, aux n ty, aux (n+tylen) bo))
257 C.Fix (i, substitutedfl)
259 subst,metasenv,(CicSubstitution.lift 1 t' ),ugraph
261 (*CSC: not implemented
262 let tylen = List.length fl in
265 (fun (name,ty,bo) -> (name, aux n ty, aux (n+tylen) bo))
268 C.CoFix (i, substitutedfl)
271 subst,metasenv,(CicSubstitution.lift 1 t'), ugraph
273 and aux_exp_named_subst metasenv subst n context ens ugraph =
275 (fun (uri,t) (subst,metasenv,l,ugraph) ->
276 let subst,metasenv,t',ugraph1 = aux metasenv subst n context t ugraph in
277 subst,metasenv,((uri,t')::l),ugraph1) ens (subst,metasenv,[],ugraph)
279 let argty,ugraph1 = type_of_aux' metasenv subst context arg ugraph in
281 FreshNamesGenerator.mk_fresh_name ~subst
282 metasenv context (Cic.Name "Hbeta") ~typ:argty
284 let subst,metasenv,t',ugraph2 = aux metasenv subst 0 context t ugraph1 in
285 let t'' = eta_reduce (C.Lambda (fresh_name,argty,t')) t' t in
286 subst, metasenv, t'', ugraph2
287 in profiler_beta_expand.HExtlib.profile foo ()
290 and beta_expand_many test_equality_only metasenv subst context t args ugraph =
291 let subst,metasenv,hd,ugraph =
293 (fun arg (subst,metasenv,t,ugraph) ->
294 let subst,metasenv,t,ugraph1 =
295 beta_expand test_equality_only
296 metasenv subst context t arg ugraph
298 subst,metasenv,t,ugraph1
299 ) args (subst,metasenv,t,ugraph)
301 subst,metasenv,hd,ugraph
304 (* NUOVA UNIFICAZIONE *)
305 (* A substitution is a (int * Cic.term) list that associates a
306 metavariable i with its body.
307 A metaenv is a (int * Cic.term) list that associate a metavariable
309 fo_unif_new takes a metasenv, a context, two terms t1 and t2 and gives back
310 a new substitution which is _NOT_ unwinded. It must be unwinded before
313 and fo_unif_subst test_equality_only subst context metasenv t1 t2 ugraph =
314 let module C = Cic in
315 let module R = CicReduction in
316 let module S = CicSubstitution in
317 let t1 = deref subst t1 in
318 let t2 = deref subst t2 in
321 R.are_convertible ~subst ~metasenv context t1 t2 ugraph
322 in profiler_are_convertible.HExtlib.profile foo ()
325 subst, metasenv, ugraph
328 | (C.Meta (n,ln), C.Meta (m,lm)) when n=m ->
329 let _,subst,metasenv,ugraph1 =
332 (fun (j,subst,metasenv,ugraph) t1 t2 ->
335 | _,None -> j+1,subst,metasenv,ugraph
336 | Some t1', Some t2' ->
337 (* First possibility: restriction *)
338 (* Second possibility: unification *)
339 (* Third possibility: convertibility *)
342 ~subst ~metasenv context t1' t2' ugraph
345 j+1,subst,metasenv, ugraph1
348 let subst,metasenv,ugraph2 =
351 subst context metasenv t1' t2' ugraph
353 j+1,subst,metasenv,ugraph2
356 | UnificationFailure _ ->
357 debug_print (lazy ("restringo Meta n." ^ (string_of_int n) ^ "on variable n." ^ (string_of_int j)));
358 let metasenv, subst =
359 CicMetaSubst.restrict
360 subst [(n,j)] metasenv in
361 j+1,subst,metasenv,ugraph1)
362 ) (1,subst,metasenv,ugraph) ln lm
366 (UnificationFailure (lazy "1"))
369 "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."
370 (CicMetaSubst.ppterm ~metasenv subst t1)
371 (CicMetaSubst.ppterm ~metasenv subst t2))) *)
372 | Invalid_argument _ ->
374 (UnificationFailure (lazy "2")))
377 "Error trying to unify %s with %s: the lengths of the two local contexts do not match."
378 (CicMetaSubst.ppterm ~metasenv subst t1)
379 (CicMetaSubst.ppterm ~metasenv subst t2)))) *)
380 in subst,metasenv,ugraph1
381 | (C.Meta (n,_), C.Meta (m,_)) when n>m ->
382 fo_unif_subst test_equality_only subst context metasenv t2 t1 ugraph
384 | (t, C.Meta (n,l)) ->
387 C.Meta (n,_), C.Meta (m,_) when n < m -> false
388 | _, C.Meta _ -> false
391 let lower = fun x y -> if swap then y else x in
392 let upper = fun x y -> if swap then x else y in
393 let fo_unif_subst_ordered
394 test_equality_only subst context metasenv m1 m2 ugraph =
395 fo_unif_subst test_equality_only subst context metasenv
396 (lower m1 m2) (upper m1 m2) ugraph
399 let subst,metasenv,ugraph1 =
400 let (_,_,meta_type) = CicUtil.lookup_meta n metasenv in
403 type_of_aux' metasenv subst context t ugraph
407 subst context metasenv tyt (S.subst_meta l meta_type) ugraph1
409 UnificationFailure _ as e -> raise e
410 | Uncertain msg -> raise (UnificationFailure msg)
412 debug_print (lazy "siamo allo huge hack");
413 (* TODO huge hack!!!!
414 * we keep on unifying/refining in the hope that
415 * the problem will be eventually solved.
416 * In the meantime we're breaking a big invariant:
417 * the terms that we are unifying are no longer well
418 * typed in the current context (in the worst case
419 * we could even diverge) *)
420 (subst, metasenv,ugraph)) in
421 let t',metasenv,subst =
423 CicMetaSubst.delift n subst context metasenv l t
425 (CicMetaSubst.MetaSubstFailure msg)->
426 raise (UnificationFailure msg)
427 | (CicMetaSubst.Uncertain msg) -> raise (Uncertain msg)
431 C.Sort (C.Type u) when not test_equality_only ->
432 let u' = CicUniv.fresh () in
433 let s = C.Sort (C.Type u') in
436 CicUniv.add_ge (upper u u') (lower u u') ugraph1
440 CicUniv.UniverseInconsistency msg ->
441 raise (UnificationFailure msg))
444 (* Unifying the types may have already instantiated n. Let's check *)
446 let (_, oldt,_) = CicUtil.lookup_subst n subst in
447 let lifted_oldt = S.subst_meta l oldt in
448 fo_unif_subst_ordered
449 test_equality_only subst context metasenv t lifted_oldt ugraph2
451 CicUtil.Subst_not_found _ ->
452 let (_, context, ty) = CicUtil.lookup_meta n metasenv in
453 let subst = (n, (context, t'',ty)) :: subst in
455 List.filter (fun (m,_,_) -> not (n = m)) metasenv in
456 subst, metasenv, ugraph2
458 | (C.Var (uri1,exp_named_subst1),C.Var (uri2,exp_named_subst2))
459 | (C.Const (uri1,exp_named_subst1),C.Const (uri2,exp_named_subst2)) ->
460 if UriManager.eq uri1 uri2 then
461 fo_unif_subst_exp_named_subst test_equality_only subst context metasenv
462 exp_named_subst1 exp_named_subst2 ugraph
464 raise (UnificationFailure (lazy
466 "Can't unify %s with %s due to different constants"
467 (CicMetaSubst.ppterm ~metasenv subst t1)
468 (CicMetaSubst.ppterm ~metasenv subst t2))))
469 | C.MutInd (uri1,i1,exp_named_subst1),C.MutInd (uri2,i2,exp_named_subst2) ->
470 if UriManager.eq uri1 uri2 && i1 = i2 then
471 fo_unif_subst_exp_named_subst
473 subst context metasenv exp_named_subst1 exp_named_subst2 ugraph
475 raise (UnificationFailure
478 "Can't unify %s with %s due to different inductive principles"
479 (CicMetaSubst.ppterm ~metasenv subst t1)
480 (CicMetaSubst.ppterm ~metasenv subst t2))))
481 | C.MutConstruct (uri1,i1,j1,exp_named_subst1),
482 C.MutConstruct (uri2,i2,j2,exp_named_subst2) ->
483 if UriManager.eq uri1 uri2 && i1 = i2 && j1 = j2 then
484 fo_unif_subst_exp_named_subst
486 subst context metasenv exp_named_subst1 exp_named_subst2 ugraph
488 raise (UnificationFailure
491 "Can't unify %s with %s due to different inductive constructors"
492 (CicMetaSubst.ppterm ~metasenv subst t1)
493 (CicMetaSubst.ppterm ~metasenv subst t2))))
494 | (C.Implicit _, _) | (_, C.Implicit _) -> assert false
495 | (C.Cast (te,ty), t2) -> fo_unif_subst test_equality_only
496 subst context metasenv te t2 ugraph
497 | (t1, C.Cast (te,ty)) -> fo_unif_subst test_equality_only
498 subst context metasenv t1 te ugraph
499 | (C.Prod (n1,s1,t1), C.Prod (_,s2,t2)) ->
500 let subst',metasenv',ugraph1 =
501 fo_unif_subst true subst context metasenv s1 s2 ugraph
503 fo_unif_subst test_equality_only
504 subst' ((Some (n1,(C.Decl s1)))::context) metasenv' t1 t2 ugraph1
505 | (C.Lambda (n1,s1,t1), C.Lambda (_,s2,t2)) ->
506 let subst',metasenv',ugraph1 =
507 fo_unif_subst test_equality_only subst context metasenv s1 s2 ugraph
509 fo_unif_subst test_equality_only
510 subst' ((Some (n1,(C.Decl s1)))::context) metasenv' t1 t2 ugraph1
511 | (C.LetIn (_,s1,t1), t2)
512 | (t2, C.LetIn (_,s1,t1)) ->
514 test_equality_only subst context metasenv t2 (S.subst s1 t1) ugraph
515 | (C.Appl l1, C.Appl l2) ->
516 (* andrea: this case should be probably rewritten in the
519 | C.Meta (i,_)::args1, C.Meta (j,_)::args2 when i = j ->
522 (fun (subst,metasenv,ugraph) t1 t2 ->
524 test_equality_only subst context metasenv t1 t2 ugraph)
525 (subst,metasenv,ugraph) l1 l2
526 with (Invalid_argument msg) ->
527 raise (UnificationFailure (lazy msg)))
528 | C.Meta (i,l)::args, _ when not(exists_a_meta args) ->
529 (* we verify that none of the args is a Meta,
530 since beta expanding with respoect to a metavariable
534 let (_,t,_) = CicUtil.lookup_subst i subst in
535 let lifted = S.subst_meta l t in
536 let reduced = CicReduction.head_beta_reduce (Cic.Appl (lifted::args)) in
539 subst context metasenv reduced t2 ugraph
540 with CicUtil.Subst_not_found _ -> *)
541 let subst,metasenv,beta_expanded,ugraph1 =
543 test_equality_only metasenv subst context t2 args ugraph
545 fo_unif_subst test_equality_only subst context metasenv
546 (C.Meta (i,l)) beta_expanded ugraph1
547 | _, C.Meta (i,l)::args when not(exists_a_meta args) ->
549 let (_,t,_) = CicUtil.lookup_subst i subst in
550 let lifted = S.subst_meta l t in
551 let reduced = CicReduction.head_beta_reduce (Cic.Appl (lifted::args)) in
554 subst context metasenv t1 reduced ugraph
555 with CicUtil.Subst_not_found _ -> *)
556 let subst,metasenv,beta_expanded,ugraph1 =
559 metasenv subst context t1 args ugraph
561 fo_unif_subst test_equality_only subst context metasenv
562 (C.Meta (i,l)) beta_expanded ugraph1
564 let lr1 = List.rev l1 in
565 let lr2 = List.rev l2 in
567 fo_unif_l test_equality_only subst metasenv (l1,l2) ugraph =
570 | _,[] -> assert false
573 test_equality_only subst context metasenv h1 h2 ugraph
576 fo_unif_subst test_equality_only subst context metasenv
577 h (C.Appl (List.rev l)) ugraph
578 | ((h1::l1),(h2::l2)) ->
579 let subst', metasenv',ugraph1 =
582 subst context metasenv h1 h2 ugraph
585 test_equality_only subst' metasenv' (l1,l2) ugraph1
589 test_equality_only subst metasenv (lr1, lr2) ugraph
591 | UnificationFailure s
592 | Uncertain s as exn ->
594 | (((Cic.Const (uri1, ens1)) as c1) :: tl1),
595 (((Cic.Const (uri2, ens2)) as c2) :: tl2) when
596 CoercDb.is_a_coercion' c1 &&
597 CoercDb.is_a_coercion' c2 &&
598 not (UriManager.eq uri1 uri2) ->
600 prerr_endline ("<<<< " ^ CicMetaSubst.ppterm_in_context ~metasenv subst (C.Appl l1) context ^ " <==> " ^ CicMetaSubst.ppterm_in_context ~metasenv subst (C.Appl l2) context);
603 let rec look_for_first_coercion c tl =
605 CicMetaSubst.apply_subst subst (HExtlib.list_last tl)
607 Cic.Appl ((Cic.Const (uri1,ens1) as c')::tl')
608 when CoercDb.is_a_coercion' c' ->
609 look_for_first_coercion c' tl'
610 | last_tl -> c,last_tl
612 let c1,last_tl1 = look_for_first_coercion c1 tl1 in
613 let c2,last_tl2 = look_for_first_coercion c2 tl2 in
615 CoercDb.coerc_carr_of_term (CoercGraph.source_of c1) in
617 CoercDb.coerc_carr_of_term (CoercGraph.source_of c2) in
618 if CoercDb.eq_carr car1 car2 then
619 (match last_tl1,last_tl2 with
620 C.Meta (i1,_),C.Meta(i2,_) when i1=i2 -> raise exn
623 let subst,metasenv,ugraph =
624 fo_unif_subst test_equality_only subst context
625 metasenv last_tl1 last_tl2 ugraph
627 fo_unif_subst test_equality_only subst context
628 metasenv (C.Appl l1) (C.Appl l2) ugraph
632 CoercGraph.meets metasenv subst context car1 car2
636 | (carr,metasenv,to1,to2)::xxx ->
639 | (m2,_,c2,c2')::_ ->
640 let m1,_,c1,c1' = carr,metasenv,to1,to2 in
642 function Some (_,t) -> CicPp.ppterm t
646 ("There are two minimal joins of "^
647 CoercDb.name_of_carr car1^" and "^
648 CoercDb.name_of_carr car2^": " ^
649 CoercDb.name_of_carr m1 ^ " via "^unopt c1^" + "^
650 unopt c1'^" and " ^ CoercDb.name_of_carr m2^" via "^
651 unopt c2^" + "^unopt c2'));
652 let last_tl1',(subst,metasenv,ugraph) =
653 match last_tl1,to1 with
654 | Cic.Meta (i1,l1),Some (last,coerced) ->
656 fo_unif_subst test_equality_only subst context
657 metasenv coerced last_tl1 ugraph
658 | _ -> last_tl1,(subst,metasenv,ugraph)
660 let last_tl2',(subst,metasenv,ugraph) =
661 match last_tl2,to2 with
662 | Cic.Meta (i2,l2),Some (last,coerced) ->
664 fo_unif_subst test_equality_only subst context
665 metasenv coerced last_tl2 ugraph
666 | _ -> last_tl2,(subst,metasenv,ugraph)
669 prerr_endline ("OK " ^ CicMetaSubst.ppterm_in_context ~metasenv subst last_tl1' context ^ " <==> " ^ CicMetaSubst.ppterm_in_context ~metasenv subst last_tl2' context);
671 let subst,metasenv,ugraph =
672 fo_unif_subst test_equality_only subst context
673 metasenv last_tl1' last_tl2' ugraph
675 fo_unif_subst test_equality_only subst context
676 metasenv (C.Appl l1) (C.Appl l2) ugraph)
679 let subst,metasenv,ugraph = res in
680 prerr_endline (">>>> " ^ CicMetaSubst.ppterm_in_context ~metasenv subst (C.Appl l1) context ^ " <==> " ^ CicMetaSubst.ppterm_in_context ~metasenv subst (C.Appl l2) context);
683 (*CSC: This is necessary because of the "elim H" tactic
684 where the type of H is only reducible to an
685 inductive type. This could be extended from inductive
686 types to any rigid term. However, the code is
687 duplicated in two places: inside applications and
688 outside them. Probably it would be better to
689 work with lambda-bar terms instead. *)
690 | (Cic.MutInd _::_, Cic.MutInd _::_) -> raise exn
691 | (_, Cic.MutInd _::_) ->
692 let t1' = R.whd ~subst context t1 in
694 C.Appl (C.MutInd _::_) ->
695 fo_unif_subst test_equality_only
696 subst context metasenv t1' t2 ugraph
697 | _ -> raise (UnificationFailure (lazy "88")))
698 | (Cic.MutInd _::_,_) ->
699 let t2' = R.whd ~subst context t2 in
701 C.Appl (C.MutInd _::_) ->
702 fo_unif_subst test_equality_only
703 subst context metasenv t1 t2' ugraph
706 (lazy ("not a mutind :"^CicMetaSubst.ppterm ~metasenv subst t2 ))))
708 | (C.MutCase (_,_,outt1,t1',pl1), C.MutCase (_,_,outt2,t2',pl2))->
709 let subst', metasenv',ugraph1 =
710 fo_unif_subst test_equality_only subst context metasenv outt1 outt2
712 let subst'',metasenv'',ugraph2 =
713 fo_unif_subst test_equality_only subst' context metasenv' t1' t2'
717 (fun (subst,metasenv,ugraph) t1 t2 ->
719 test_equality_only subst context metasenv t1 t2 ugraph
720 ) (subst'',metasenv'',ugraph2) pl1 pl2
722 Invalid_argument _ ->
723 raise (UnificationFailure (lazy "6.1")))
725 "Error trying to unify %s with %s: the number of branches is not the same."
726 (CicMetaSubst.ppterm ~metasenv subst t1)
727 (CicMetaSubst.ppterm ~metasenv subst t2)))) *)
728 | (C.Rel _, _) | (_, C.Rel _) ->
730 subst, metasenv,ugraph
732 raise (UnificationFailure (lazy
734 "Can't unify %s with %s because they are not convertible"
735 (CicMetaSubst.ppterm ~metasenv subst t1)
736 (CicMetaSubst.ppterm ~metasenv subst t2))))
737 | (C.Appl (C.Meta(i,l)::args),t2) when not(exists_a_meta args) ->
738 let subst,metasenv,beta_expanded,ugraph1 =
740 test_equality_only metasenv subst context t2 args ugraph
742 fo_unif_subst test_equality_only subst context metasenv
743 (C.Meta (i,l)) beta_expanded ugraph1
744 | (t1,C.Appl (C.Meta(i,l)::args)) when not(exists_a_meta args) ->
745 let subst,metasenv,beta_expanded,ugraph1 =
747 test_equality_only metasenv subst context t1 args ugraph
749 fo_unif_subst test_equality_only subst context metasenv
750 beta_expanded (C.Meta (i,l)) ugraph1
751 (* Works iff there are no arguments applied to it; similar to the
754 let t1' = R.whd ~subst context t1 in
757 fo_unif_subst test_equality_only
758 subst context metasenv t1' t2 ugraph
759 | _ -> raise (UnificationFailure (lazy "8")))
761 (* The following idea could be exploited again; right now we have no
762 longer any example requiring it
764 let t2' = R.whd ~subst context t2 in
767 fo_unif_subst test_equality_only
768 subst context metasenv t1 t2' ugraph
769 | _ -> raise (UnificationFailure (lazy "8")))
771 let t1' = R.whd ~subst context t1 in
774 fo_unif_subst test_equality_only
775 subst context metasenv t1' t2 ugraph
776 | _ -> (* raise (UnificationFailure "9")) *)
778 (UnificationFailure (lazy (sprintf
779 "Can't unify %s with %s because they are not convertible"
780 (CicMetaSubst.ppterm ~metasenv subst t1)
781 (CicMetaSubst.ppterm ~metasenv subst t2)))))
784 (* delta-beta reduction should almost never be a problem for
786 1. long computations require iota reduction
787 2. it is extremely rare that a close term t1 (that could be unified
788 to t2) beta-delta reduces to t1' while t2 does not beta-delta
789 reduces in the same way. This happens only if one meta of t2
790 occurs in head position during beta reduction. In this unluky
791 case too much reduction will be performed on t1 and unification
793 let t1' = CicReduction.head_beta_reduce ~delta:true t1 in
794 let t2' = CicReduction.head_beta_reduce ~delta:true t2 in
795 if t1 = t1' && t2 = t2' then
796 raise (UnificationFailure
799 "Can't unify %s with %s because they are not convertible"
800 (CicMetaSubst.ppterm ~metasenv subst t1)
801 (CicMetaSubst.ppterm ~metasenv subst t2))))
804 fo_unif_subst test_equality_only subst context metasenv t1' t2' ugraph
808 raise (UnificationFailure
811 "Can't unify %s with %s because they are not convertible"
812 (CicMetaSubst.ppterm ~metasenv subst t1)
813 (CicMetaSubst.ppterm ~metasenv subst t2))))
815 and fo_unif_subst_exp_named_subst test_equality_only subst context metasenv
816 exp_named_subst1 exp_named_subst2 ugraph
820 (fun (subst,metasenv,ugraph) (uri1,t1) (uri2,t2) ->
822 fo_unif_subst test_equality_only subst context metasenv t1 t2 ugraph
823 ) (subst,metasenv,ugraph) exp_named_subst1 exp_named_subst2
825 Invalid_argument _ ->
830 UriManager.string_of_uri uri ^ " := " ^ (CicMetaSubst.ppterm ~metasenv subst t)
833 raise (UnificationFailure (lazy (sprintf
834 "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))))
836 (* A substitution is a (int * Cic.term) list that associates a *)
837 (* metavariable i with its body. *)
838 (* metasenv is of type Cic.metasenv *)
839 (* fo_unif takes a metasenv, a context, two terms t1 and t2 and gives back *)
840 (* a new substitution which is already unwinded and ready to be applied and *)
841 (* a new metasenv in which some hypothesis in the contexts of the *)
842 (* metavariables may have been restricted. *)
843 let fo_unif metasenv context t1 t2 ugraph =
844 fo_unif_subst false [] context metasenv t1 t2 ugraph ;;
846 let enrich_msg msg subst context metasenv t1 t2 ugraph =
849 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"
850 (CicMetaSubst.ppterm ~metasenv subst t1)
852 let ty_t1,_ = type_of_aux' metasenv subst context t1 ugraph in
855 | UnificationFailure s
857 | AssertFailure s -> sprintf "MALFORMED(t1): \n<BEGIN>%s\n<END>" (Lazy.force s))
858 (CicMetaSubst.ppterm ~metasenv subst t2)
860 let ty_t2,_ = type_of_aux' metasenv subst context t2 ugraph in
863 | UnificationFailure s
865 | AssertFailure s -> sprintf "MALFORMED(t2): \n<BEGIN>%s\n<END>" (Lazy.force s))
866 (CicMetaSubst.ppcontext ~metasenv subst context)
867 (CicMetaSubst.ppmetasenv subst metasenv)
868 (CicMetaSubst.ppsubst ~metasenv subst) (Lazy.force msg)
870 sprintf "Unification error unifying %s of type %s with %s of type %s in context\n%s\nand metasenv\n%s\nbecause %s"
871 (CicMetaSubst.ppterm_in_context ~metasenv subst t1 context)
873 let ty_t1,_ = type_of_aux' metasenv subst context t1 ugraph in
874 CicMetaSubst.ppterm_in_context ~metasenv subst ty_t1 context
876 | UnificationFailure s
878 | AssertFailure s -> sprintf "MALFORMED(t1): \n<BEGIN>%s\n<END>" (Lazy.force s))
879 (CicMetaSubst.ppterm_in_context ~metasenv subst t2 context)
881 let ty_t2,_ = type_of_aux' metasenv subst context t2 ugraph in
882 CicMetaSubst.ppterm_in_context ~metasenv subst ty_t2 context
884 | UnificationFailure s
886 | AssertFailure s -> sprintf "MALFORMED(t2): \n<BEGIN>%s\n<END>" (Lazy.force s))
887 (CicMetaSubst.ppcontext ~metasenv subst context)
888 (CicMetaSubst.ppmetasenv subst metasenv)
892 let fo_unif_subst subst context metasenv t1 t2 ugraph =
894 fo_unif_subst false subst context metasenv t1 t2 ugraph
896 | AssertFailure msg ->
897 raise (AssertFailure (enrich_msg msg subst context metasenv t1 t2 ugraph))
898 | UnificationFailure msg ->
899 raise (UnificationFailure (enrich_msg msg subst context metasenv t1 t2 ugraph))