--- /dev/null
+(* Copyright (C) 2005, HELM Team.
+ *
+ * This file is part of HELM, an Hypertextual, Electronic
+ * Library of Mathematics, developed at the Computer Science
+ * Department, University of Bologna, Italy.
+ *
+ * HELM is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * HELM is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HELM; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ *
+ * For details, see the HELM World-Wide-Web page,
+ * http://cs.unibo.it/helm/.
+ *)
+
+(* let _profiler = <:profiler<_profiler>>;; *)
+
+(* $Id$ *)
+
+open Utils;;
+open Printf;;
+
+let debug_print s = ();;(*prerr_endline (Lazy.force s);;*)
+
+let check_disjoint_invariant subst metasenv msg =
+ if (List.exists
+ (fun (i,_,_) -> (Subst.is_in_subst i subst)) metasenv)
+ then
+ begin
+ prerr_endline ("not disjoint: " ^ msg);
+ assert false
+ end
+;;
+
+let rec check_irl start = function
+ | [] -> true
+ | None::tl -> check_irl (start+1) tl
+ | (Some (Cic.Rel x))::tl ->
+ if x = start then check_irl (start+1) tl else false
+ | _ -> false
+;;
+
+let rec is_simple_term = function
+ | Cic.Appl ((Cic.Meta _)::_) -> false
+ | Cic.Appl l -> List.for_all is_simple_term l
+ | Cic.Meta (i, l) -> let l = [] in check_irl 1 l
+ | Cic.Rel _ -> true
+ | Cic.Const _ -> true
+ | Cic.MutInd (_, _, []) -> true
+ | Cic.MutConstruct (_, _, _, []) -> true
+ | _ -> false
+;;
+
+let locked menv i =
+ List.exists (fun (j,_,_) -> i = j) menv
+;;
+
+let unification_simple locked_menv metasenv context t1 t2 ugraph =
+ let module C = Cic in
+ let module M = CicMetaSubst in
+ let module U = CicUnification in
+ let lookup = Subst.lookup_subst in
+ let rec occurs_check subst what where =
+ match where with
+ | Cic.Meta(i,_) when i = what -> true
+ | C.Appl l -> List.exists (occurs_check subst what) l
+ | C.Meta _ ->
+ let t = lookup where subst in
+ if t <> where then occurs_check subst what t else false
+ | _ -> false
+ in
+ let rec unif subst menv s t =
+ let s = match s with C.Meta _ -> lookup s subst | _ -> s
+ and t = match t with C.Meta _ -> lookup t subst | _ -> t
+
+ in
+ match s, t with
+ | s, t when s = t -> subst, menv
+ (* sometimes the same meta has different local contexts; this
+ could create "cyclic" substitutions *)
+ | C.Meta (i, _), C.Meta (j, _) when i=j -> subst, menv
+ | C.Meta (i, _), C.Meta (j, _)
+ when (locked locked_menv i) &&(locked locked_menv j) ->
+ raise
+ (U.UnificationFailure (lazy "Inference.unification.unif"))
+ | C.Meta (i, _), C.Meta (j, _) when (locked locked_menv i) ->
+ unif subst menv t s
+ | C.Meta (i, _), C.Meta (j, _) when (i > j) && not (locked locked_menv j) ->
+ unif subst menv t s
+ | C.Meta (i,_), t when occurs_check subst i t ->
+ raise
+ (U.UnificationFailure (lazy "Inference.unification.unif"))
+ | C.Meta (i, l), t when (locked locked_menv i) ->
+ raise
+ (U.UnificationFailure (lazy "Inference.unification.unif"))
+ | C.Meta (i, l), t -> (
+ try
+ let _, _, ty = CicUtil.lookup_meta i menv in
+ let subst = Subst.buildsubst i context t ty subst in
+ subst, menv
+ with CicUtil.Meta_not_found m ->
+ let names = names_of_context context in
+ (*debug_print
+ (lazy*) prerr_endline
+ (Printf.sprintf "Meta_not_found %d!: %s %s\n%s\n\n%s" m
+ (CicPp.pp t1 names) (CicPp.pp t2 names)
+ (print_metasenv menv) (print_metasenv metasenv));
+ assert false
+ )
+ | _, C.Meta _ -> unif subst menv t s
+ | C.Appl (hds::_), C.Appl (hdt::_) when hds <> hdt ->
+ raise (U.UnificationFailure (lazy "Inference.unification.unif"))
+ | C.Appl (hds::tls), C.Appl (hdt::tlt) -> (
+ try
+ List.fold_left2
+ (fun (subst', menv) s t -> unif subst' menv s t)
+ (subst, menv) tls tlt
+ with Invalid_argument _ ->
+ raise (U.UnificationFailure (lazy "Inference.unification.unif"))
+ )
+ | _, _ ->
+ raise (U.UnificationFailure (lazy "Inference.unification.unif"))
+ in
+ let subst, menv = unif Subst.empty_subst metasenv t1 t2 in
+ let menv = Subst.filter subst menv in
+ subst, menv, ugraph
+;;
+
+let profiler = HExtlib.profile "P/Inference.unif_simple[flatten]"
+let profiler2 = HExtlib.profile "P/Inference.unif_simple[flatten_fast]"
+let profiler3 = HExtlib.profile "P/Inference.unif_simple[resolve_meta]"
+let profiler4 = HExtlib.profile "P/Inference.unif_simple[filter]"
+
+let unification_aux b metasenv1 metasenv2 context t1 t2 ugraph =
+ let metasenv =
+ HExtlib.list_uniq (List.sort Pervasives.compare (metasenv1 @ metasenv2))
+ (* metasenv1 @ metasenv2 *)
+ in
+ let subst, menv, ug =
+ if not (is_simple_term t1) || not (is_simple_term t2) then (
+ debug_print
+ (lazy
+ (Printf.sprintf "NOT SIMPLE TERMS: %s %s"
+ (CicPp.ppterm t1) (CicPp.ppterm t2)));
+ raise (CicUnification.UnificationFailure (lazy "Inference.unification.unif"))
+ ) else
+ if b then
+ (* full unification *)
+ unification_simple [] metasenv context t1 t2 ugraph
+ else
+ (* matching: metasenv1 is locked *)
+ unification_simple metasenv1 metasenv context t1 t2 ugraph
+ in
+ if Utils.debug_res then
+ ignore(check_disjoint_invariant subst menv "unif");
+ (* let flatten subst =
+ List.map
+ (fun (i, (context, term, ty)) ->
+ let context = apply_subst_context subst context in
+ let term = apply_subst subst term in
+ let ty = apply_subst subst ty in
+ (i, (context, term, ty))) subst
+ in
+ let flatten subst = profiler.HExtlib.profile flatten subst in
+ let subst = flatten subst in *)
+ subst, menv, ug
+;;
+
+exception MatchingFailure;;
+
+(** matching takes in input the _disjoint_ metasenv of t1 and t2;
+it perform unification in the union metasenv, then check that
+the first metasenv has not changed *)
+let matching metasenv1 metasenv2 context t1 t2 ugraph =
+ try
+ unification_aux false metasenv1 metasenv2 context t1 t2 ugraph
+ with
+ CicUnification.UnificationFailure _ ->
+ raise MatchingFailure
+;;
+
+let unification m1 m2 c t1 t2 ug =
+ try
+ unification_aux true m1 m2 c t1 t2 ug
+ with exn ->
+ raise exn
+;;
+
+let get_stats () = "" (*<:show<Inference.>>*) ;;