1 (* Copyright (C) 2005, 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/.
26 (* let _profiler = <:profiler<_profiler>>;; *)
33 let debug_print s = ();;(*prerr_endline (Lazy.force s);;*)
35 let check_disjoint_invariant subst metasenv msg =
37 (fun (i,_,_) -> (Subst.is_in_subst i subst)) metasenv)
40 prerr_endline ("not disjoint: " ^ msg);
45 let rec check_irl start = function
47 | None::tl -> check_irl (start+1) tl
48 | (Some (Cic.Rel x))::tl ->
49 if x = start then check_irl (start+1) tl else false
53 let rec is_simple_term = function
54 | Cic.Appl ((Cic.Meta _)::_) -> false
55 | Cic.Appl l -> List.for_all is_simple_term l
56 | Cic.Meta (i, l) -> let l = [] in check_irl 1 l
59 | Cic.MutInd (_, _, []) -> true
60 | Cic.MutConstruct (_, _, _, []) -> true
65 List.exists (fun (j,_,_) -> i = j) menv
68 let unification_simple locked_menv metasenv context t1 t2 ugraph =
70 let module M = CicMetaSubst in
71 let module U = CicUnification in
72 let lookup = Subst.lookup_subst in
73 let rec occurs_check subst what where =
75 | Cic.Meta(i,_) when i = what -> true
76 | C.Appl l -> List.exists (occurs_check subst what) l
78 let t = lookup where subst in
79 if t <> where then occurs_check subst what t else false
82 let rec unif subst menv s t =
83 let s = match s with C.Meta _ -> lookup s subst | _ -> s
84 and t = match t with C.Meta _ -> lookup t subst | _ -> t
88 | s, t when s = t -> subst, menv
89 (* sometimes the same meta has different local contexts; this
90 could create "cyclic" substitutions *)
91 | C.Meta (i, _), C.Meta (j, _) when i=j -> subst, menv
92 | C.Meta (i, _), C.Meta (j, _)
93 when (locked locked_menv i) &&(locked locked_menv j) ->
95 (U.UnificationFailure (lazy "Inference.unification.unif"))
96 | C.Meta (i, _), C.Meta (j, _) when (locked locked_menv i) ->
98 | C.Meta (i, _), C.Meta (j, _) when (i > j) && not (locked locked_menv j) ->
100 | C.Meta (i,_), t when occurs_check subst i t ->
102 (U.UnificationFailure (lazy "Inference.unification.unif"))
103 | C.Meta (i, l), t when (locked locked_menv i) ->
105 (U.UnificationFailure (lazy "Inference.unification.unif"))
106 | C.Meta (i, l), t -> (
108 let _, _, ty = CicUtil.lookup_meta i menv in
109 let subst = Subst.buildsubst i context t ty subst in
111 with CicUtil.Meta_not_found m ->
112 let names = names_of_context context in
114 (lazy*) prerr_endline
115 (Printf.sprintf "Meta_not_found %d!: %s %s\n%s\n\n%s" m
116 (CicPp.pp t1 names) (CicPp.pp t2 names)
117 (print_metasenv menv) (print_metasenv metasenv));
120 | _, C.Meta _ -> unif subst menv t s
121 | C.Appl (hds::_), C.Appl (hdt::_) when hds <> hdt ->
122 raise (U.UnificationFailure (lazy "Inference.unification.unif"))
123 | C.Appl (hds::tls), C.Appl (hdt::tlt) -> (
126 (fun (subst', menv) s t -> unif subst' menv s t)
127 (subst, menv) tls tlt
128 with Invalid_argument _ ->
129 raise (U.UnificationFailure (lazy "Inference.unification.unif"))
132 raise (U.UnificationFailure (lazy "Inference.unification.unif"))
134 let subst, menv = unif Subst.empty_subst metasenv t1 t2 in
135 let menv = Subst.filter subst menv in
139 let profiler = HExtlib.profile "P/Inference.unif_simple[flatten]"
140 let profiler2 = HExtlib.profile "P/Inference.unif_simple[flatten_fast]"
141 let profiler3 = HExtlib.profile "P/Inference.unif_simple[resolve_meta]"
142 let profiler4 = HExtlib.profile "P/Inference.unif_simple[filter]"
144 let check_for_duplicates metas msg =
145 let rec aux = function
148 not (List.exists (fun (i, _, _) -> i = m) tl) && aux tl in
152 prerr_endline ("DUPLICATI ---- " ^ msg);
153 prerr_endline (CicMetaSubst.ppmetasenv [] metas);
159 let check_metasenv msg menv =
162 try ignore(CicTypeChecker.type_of_aux' menv ctx ty
163 CicUniv.empty_ugraph)
165 | CicUtil.Meta_not_found _ ->
166 prerr_endline (msg ^ CicMetaSubst.ppmetasenv [] menv);
172 let unification_aux b metasenv1 metasenv2 context t1 t2 ugraph =
173 let metasenv = metasenv1@metasenv2 in
174 if Utils.debug_metas then
176 ignore(check_for_duplicates metasenv "unification_aux");
177 check_metasenv "unification_aux" metasenv;
179 let subst, menv, ug =
180 if not (is_simple_term t1) || not (is_simple_term t2) then (
183 (Printf.sprintf "NOT SIMPLE TERMS: %s %s"
184 (CicPp.ppterm t1) (CicPp.ppterm t2)));
185 raise (CicUnification.UnificationFailure (lazy "Inference.unification.unif"))
188 (* full unification *)
189 unification_simple [] metasenv context t1 t2 ugraph
191 (* matching: metasenv1 is locked *)
192 unification_simple metasenv1 metasenv context t1 t2 ugraph
194 if Utils.debug_res then
195 ignore(check_disjoint_invariant subst menv "unif");
196 (* let flatten subst =
198 (fun (i, (context, term, ty)) ->
199 let context = apply_subst_context subst context in
200 let term = apply_subst subst term in
201 let ty = apply_subst subst ty in
202 (i, (context, term, ty))) subst
204 let flatten subst = profiler.HExtlib.profile flatten subst in
205 let subst = flatten subst in *)
206 if Utils.debug_metas then
207 ignore(check_for_duplicates menv "unification_aux prima di apply_subst");
208 let menv = Subst.apply_subst_metasenv subst menv in
209 if Utils.debug_metas then
210 (let _ = check_for_duplicates menv "unif_aux after" in
211 check_metasenv "unification_aux after 1" menv);
215 exception MatchingFailure;;
217 (** matching takes in input the _disjoint_ metasenv of t1 and t2;
218 it perform unification in the union metasenv, then check that
219 the first metasenv has not changed *)
220 let matching metasenv1 metasenv2 context t1 t2 ugraph =
222 unification_aux false metasenv1 metasenv2 context t1 t2 ugraph
224 CicUnification.UnificationFailure _ ->
225 raise MatchingFailure
228 let unification m1 m2 c t1 t2 ug =
230 if (m1 = m2 && m1 <> []) then assert false
231 (* (prerr_endline "eccoci 2"; []) *) else m1 in
233 prerr_endline (CicPp.ppterm t1);
234 prerr_endline (CicPp.ppterm t2);
235 prerr_endline "++++++++++"; *)
237 unification_aux true m1 m2 c t1 t2 ug
242 let get_stats () = "" (*<:show<Inference.>>*) ;;