(* $Id$ *)
open Utils;;
+open Printf;;
let metas_of_proof_time = ref 0.;;
let metas_of_term_time = ref 0.;;
+(*
+type substitution = Cic.substitution
+let apply_subst = CicMetaSubst.apply_subst
+let apply_subst_metasenv = CicMetaSubst.apply_subst_metasenv
+let ppsubst = CicMetaSubst.ppsubst
+let buildsubst n context t ty = (n,(context,t,ty))
+let flatten_subst 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
+let rec lookup_subst meta subst =
+ match meta with
+ | Cic.Meta (i, _) -> (
+ try let _, (_, t, _) = List.find (fun (m, _) -> m = i) subst
+ in lookup_subst t subst
+ with Not_found -> meta
+ )
+ | _ -> meta
+;;
+*)
+
+(* naif version of apply subst; the local context of metas is ignored;
+we assume the substituted term must be lifted according to the nesting
+depth of the meta. Alternatively, ee could used implicit instead of
+metas *)
+
+
+type substitution = (int * Cic.term) list
+
+let apply_subst subst term =
+ let rec aux k t =
+ match t with
+ Cic.Rel _ -> t
+ | Cic.Var (uri,exp_named_subst) ->
+ let exp_named_subst' =
+ List.map (fun (uri, t) -> (uri, aux k t)) exp_named_subst
+ in
+ Cic.Var (uri, exp_named_subst')
+ | Cic.Meta (i, l) ->
+ (try
+ aux k (CicSubstitution.lift k (List.assoc i subst))
+ with Not_found -> t)
+ | Cic.Sort _
+ | Cic.Implicit _ -> t
+ | Cic.Cast (te,ty) -> Cic.Cast (aux k te, aux k ty)
+ | Cic.Prod (n,s,t) -> Cic.Prod (n, aux k s, aux (k+1) t)
+ | Cic.Lambda (n,s,t) -> Cic.Lambda (n, aux k s, aux (k+1) t)
+ | Cic.LetIn (n,s,t) -> Cic.LetIn (n, aux k s, aux (k+1) t)
+ | Cic.Appl [] -> assert false
+ | Cic.Appl l -> Cic.Appl (List.map (aux k) l)
+ | Cic.Const (uri,exp_named_subst) ->
+ let exp_named_subst' =
+ List.map (fun (uri, t) -> (uri, aux k t)) exp_named_subst
+ in
+ if exp_named_subst' != exp_named_subst then
+ Cic.Const (uri, exp_named_subst')
+ else
+ t (* TODO: provare a mantenere il piu' possibile sharing *)
+ | Cic.MutInd (uri,typeno,exp_named_subst) ->
+ let exp_named_subst' =
+ List.map (fun (uri, t) -> (uri, aux k t)) exp_named_subst
+ in
+ Cic.MutInd (uri,typeno,exp_named_subst')
+ | Cic.MutConstruct (uri,typeno,consno,exp_named_subst) ->
+ let exp_named_subst' =
+ List.map (fun (uri, t) -> (uri, aux k t)) exp_named_subst
+ in
+ Cic.MutConstruct (uri,typeno,consno,exp_named_subst')
+ | Cic.MutCase (sp,i,outty,t,pl) ->
+ let pl' = List.map (aux k) pl in
+ Cic.MutCase (sp, i, aux k outty, aux k t, pl')
+ | Cic.Fix (i, fl) ->
+ let len = List.length fl in
+ let fl' =
+ List.map
+ (fun (name, i, ty, bo) -> (name, i, aux k ty, aux (k+len) bo)) fl
+ in
+ Cic.Fix (i, fl')
+ | Cic.CoFix (i, fl) ->
+ let len = List.length fl in
+ let fl' =
+ List.map (fun (name, ty, bo) -> (name, aux k ty, aux (k+len) bo)) fl
+ in
+ Cic.CoFix (i, fl')
+in
+ aux 0 term
+;;
+
+(* naif version of apply_subst_metasenv: we do not apply the
+substitution to the context *)
+
+let apply_subst_metasenv subst metasenv =
+ List.map
+ (fun (n, context, ty) ->
+ (n, context, apply_subst subst ty))
+ (List.filter
+ (fun (i, _, _) -> not (List.mem_assoc i subst))
+ metasenv)
+
+let ppsubst subst =
+ String.concat "\n"
+ (List.map
+ (fun (idx, t) ->
+ sprintf "%d:= %s" idx (CicPp.ppterm t))
+ subst)
+;;
+
+let buildsubst n context t ty = (n,t) ;;
+
+let flatten_subst subst =
+ List.map (fun (i,t) -> i, apply_subst subst t ) subst
+;;
+
+let rec lookup_subst meta subst =
+ match meta with
+ | Cic.Meta (i, _) ->
+ (try
+ lookup_subst (List.assoc i subst) subst
+ with
+ Not_found -> meta)
+ | _ -> meta
+;;
type equality =
int * (* weight *)
and proof =
| NoProof (* term is the goal missing a proof *)
- | BasicProof of Cic.term
+ | BasicProof of substitution * Cic.term
| ProofBlock of
- Cic.substitution * UriManager.uri *
+ substitution * UriManager.uri *
(Cic.name * Cic.term) * Cic.term * (Utils.pos * equality) * proof
| ProofGoalBlock of proof * proof
| ProofSymBlock of Cic.term list * proof
let rec string_of_proof = function
| NoProof -> "NoProof "
- | BasicProof t -> "BasicProof " ^ (CicPp.ppterm t)
+ | BasicProof (s, t) -> "BasicProof " ^
+ (CicPp.ppterm (apply_subst s t))
| SubProof (t, i, p) ->
Printf.sprintf "SubProof(%s, %s, %s)"
(CicPp.ppterm t) (string_of_int i) (string_of_proof p)
| ProofSymBlock _ -> "ProofSymBlock"
| ProofBlock (subst, _, _, _ ,_,_) ->
- "ProofBlock" ^ (CicMetaSubst.ppsubst subst)
+ "ProofBlock" ^ (ppsubst subst)
| ProofGoalBlock (p1, p2) ->
Printf.sprintf "ProofGoalBlock(%s, %s)"
(string_of_proof p1) (string_of_proof p2)
| NoProof ->
Printf.fprintf stderr "WARNING: no proof!\n";
noproof
- | BasicProof term -> term
+ | BasicProof (s,term) -> apply_subst s term
| ProofGoalBlock (proofbit, proof) ->
print_endline "found ProofGoalBlock, going up...";
do_build_goal_proof proofbit proof
let what, other =
if pos = Utils.Left then what, other else other, what
in
- CicMetaSubst.apply_subst subst
+ apply_subst subst
(Cic.Appl [Cic.Const (eq_URI, []); ty;
what; t'; eqproof; other; proof'])
| SubProof (term, meta_index, proof) ->
SubProof (term, meta_index, replace_proof newproof p)
| p -> p
in
- do_build_proof proof
+ do_build_proof proof
;;
-
let rec metas_of_term = function
| Cic.Meta (i, c) -> [i]
| Cic.Var (_, ens)
metas_of_term (build_proof_term p)
;;
+
exception NotMetaConvertible;;
let meta_convertibility_aux table t1 t2 =
| _ -> false
;;
-
-let rec lookup_subst meta subst =
- match meta with
- | Cic.Meta (i, _) -> (
- try let _, (_, t, _) = List.find (fun (m, _) -> m = i) subst
- in lookup_subst t subst
- with Not_found -> meta
- )
- | _ -> meta
-;;
-
let locked menv i =
List.exists (fun (j,_,_) -> i = j) menv
;;
let unification_simple locked_menv metasenv context t1 t2 ugraph =
+ let debug_print x = prerr_endline (Lazy.force x) in
let module C = Cic in
let module M = CicMetaSubst in
let module U = CicUnification in
try
let _, _, ty = CicUtil.lookup_meta i menv in
assert (not (List.mem_assoc i subst));
- let subst = (i, (context, t, ty))::subst in
+ let subst = (buildsubst i context t ty)::subst in
let menv = menv in (* List.filter (fun (m, _, _) -> i <> m) menv in *)
subst, menv
with CicUtil.Meta_not_found m ->
let names = names_of_context context in
- debug_print
- (lazy
+ (*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)));
+ (print_metasenv menv) (print_metasenv metasenv));
assert false
)
| _, C.Meta _ -> unif subst menv t s
in
if Utils.debug_res then
ignore(check_disjoint_invariant subst menv "unif");
- let flatten subst =
+ (* let flatten subst =
List.map
(fun (i, (context, term, ty)) ->
- let context = CicMetaSubst.apply_subst_context subst context in
- let term = CicMetaSubst.apply_subst subst term in
- let ty = CicMetaSubst.apply_subst subst ty in
+ 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_fast subst =
- let resolve_meta (i, (context, term, ty)) subst =
- let term = CicMetaSubst.apply_subst subst term in
- let ty = CicMetaSubst.apply_subst subst ty in
- (i, (context, term, ty))
- in
- let resolve_meta t s = profiler3.HExtlib.profile (resolve_meta t) s in
- let filter j (i,_) = i <> j in
- let filter a b = profiler4.HExtlib.profile (filter a) b in
- List.fold_left
- (fun subst (j,(c,t,ty)) as s ->
- let s = resolve_meta s subst in
- s::(List.filter (filter j) subst))
- subst subst
- in
- (*let flatten subst = profiler.HExtlib.profile flatten subst in*)
- let flatten_fast subst = profiler2.HExtlib.profile flatten_fast subst in
- (*let subst = flatten subst in*)
-(* let subst = flatten_fast subst in*)
+ let flatten subst = profiler.HExtlib.profile flatten subst in
+ let subst = flatten subst in *)
subst, menv, ug
;;
let unification = unification_aux true
;;
-
-
-(*
-let unification metasenv1 metasenv2 context t1 t2 ugraph =
- let (subst, metasenv, ugraph) =
- CicUnification.fo_unif (metasenv1@metasenv2) context t1 t2 ugraph in
- if Utils.debug_res then
- ignore(check_disjoint_invariant subst metasenv "fo_unif");
- (subst, metasenv, ugraph)
-
-;;
-*)
-
-
-(*
-let matching_simple metasenv context t1 t2 ugraph =
- let module C = Cic in
- let module M = CicMetaSubst in
- let module U = CicUnification in
- let lookup meta subst =
- match meta with
- | C.Meta (i, _) -> (
- try let _, (_, t, _) = List.find (fun (m, _) -> m = i) subst in t
- with Not_found -> meta
- )
- | _ -> assert false
- in
- let rec do_match subst menv s t =
- match s, t with
- | s, t when s = t -> subst, menv
- | s, C.Meta (i, l) ->
- let filter_menv i menv =
- List.filter (fun (m, _, _) -> i <> m) menv
- in
- let subst, menv =
- let value = lookup t subst in
- match value with
- | value when value = t ->
- let _, _, ty = CicUtil.lookup_meta i menv in
- (i, (context, s, ty))::subst, filter_menv i menv
- | value when value <> s ->
- raise MatchingFailure
- | value -> do_match subst menv s value
- in
- subst, menv
- | C.Appl ls, C.Appl lt -> (
- try
- List.fold_left2
- (fun (subst, menv) s t -> do_match subst menv s t)
- (subst, menv) ls lt
- with Invalid_argument _ ->
- raise MatchingFailure
- )
- | _, _ ->
- raise MatchingFailure
- in
- let subst, menv = do_match [] metasenv t1 t2 in
- subst, menv, ugraph
-;;
-*)
-
-(*
-let matching metasenv context t1 t2 ugraph =
- try
- let subst, metasenv, ugraph =
- try
- unification metasenv context t1 t2 ugraph
- with CicUtil.Meta_not_found _ as exn ->
- Printf.eprintf "t1 == %s\nt2 = %s\nmetasenv == %s\n%!"
- (CicPp.ppterm t1) (CicPp.ppterm t2)
- (CicMetaSubst.ppmetasenv [] metasenv);
- raise exn
- in
- if Utils.debug_res then
- ignore(check_disjoint_invariant subst metasenv "qua-2");
- let t' = CicMetaSubst.apply_subst subst t1 in
- if not (meta_convertibility t1 t') then
- raise MatchingFailure
- else
- if Utils.debug_res then
- ignore(check_disjoint_invariant subst metasenv "qua-1");
- let metas = metas_of_term t1 in
- let subst =
- List.map
- (fun (i, (context, term, ty)) ->
- let context = CicMetaSubst.apply_subst_context subst context in
- let term = CicMetaSubst.apply_subst subst term in
- let ty = CicMetaSubst.apply_subst subst ty in
- (i, (context, term, ty))) subst in
- if Utils.debug_res then
- ignore(check_disjoint_invariant subst metasenv "qua0");
-
- let subst, metasenv =
- List.fold_left
- (fun
- (subst,metasenv) s ->
- match s with
- | (i, (c, Cic.Meta (j, lc), ty)) when List.mem i metas ->
- let metasenv' =
- List.filter (fun (x, _, _) -> x<>j) metasenv
- in
- ((j, (c, Cic.Meta (i, lc), ty))::subst,
- (i,c,ty)::metasenv')
- |_ -> s::subst,metasenv) ([],metasenv) subst
- in
- if Utils.debug_res then
- ignore(check_disjoint_invariant subst metasenv "qua1");
-(*
- let fix_subst = function
- | (i, (c, Cic.Meta (j, lc), ty)) when List.mem i metas ->
- (j, (c, Cic.Meta (i, lc), ty))
- | s -> s
- in
- let subst = List.map fix_subst subst in *)
- if CicMetaSubst.apply_subst subst t1 = t1 then
- subst, metasenv, ugraph
- else
- (prerr_endline "mah"; raise MatchingFailure)
- with
- | CicUnification.UnificationFailure _
- | CicUnification.Uncertain _ ->
- raise 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 matching2 metasenv1 metasenv2 context t1 t2 ugraph =
- let subst, metasenv, ugraph =
- try
- unification metasenv1 metasenv2 context t1 t2 ugraph
- with
- CicUtil.Meta_not_found _ as exn ->
- Printf.eprintf "t1 == %s\nt2 = %s\nmetasenv == %s\n%!"
- (CicPp.ppterm t1) (CicPp.ppterm t2)
- (CicMetaSubst.ppmetasenv [] (metasenv1@metasenv2));
- raise exn
- | CicUnification.UnificationFailure _
- | CicUnification.Uncertain _ ->
- raise MatchingFailure
- in
- if Utils.debug_res then
- ignore(check_disjoint_invariant subst metasenv "qua-2");
- (* let us unfold subst *)
- if metasenv = metasenv1 then
- let subst =
- List.map
- (fun (i, (context, term, ty)) ->
- let context = CicMetaSubst.apply_subst_context subst context in
- let term = CicMetaSubst.apply_subst subst term in
- let ty = CicMetaSubst.apply_subst subst ty in
- (i, (context, term, ty))) subst in
- subst, metasenv, ugraph (* everything is fine *)
- else
- (* let us unfold subst *)
- (*
- let subst =
- List.map
- (fun (i, (context, term, ty)) ->
- let context = CicMetaSubst.apply_subst_context subst context in
- let term = CicMetaSubst.apply_subst subst term in
- let ty = CicMetaSubst.apply_subst subst ty in
- (i, (context, term, ty))) subst in
- *)
- (* let us revert Meta-Meta in subst privileging metasenv1 *)
- let subst, metasenv =
- List.fold_left
- (fun
- (subst,metasenv) s ->
- match s with
- | (i, (c, Cic.Meta (j, lc), ty))
- when (List.exists (fun (x, _, _) -> x=i) metasenv1) &&
- not (List.exists (fun (x, _) -> x=j) subst) ->
- let metasenv' =
- List.filter (fun (x, _, _) -> x<>j) metasenv
- in
- ((j, (c, Cic.Meta (i, lc), ty))::subst,
- (i,c,ty)::metasenv')
- |_ -> s::subst,metasenv) ([],metasenv) subst
- in
- (* finally, let us chek again that metasenv = metasenv1 *)
- if metasenv = metasenv1 then
- subst, metasenv, ugraph
- else raise MatchingFailure
-;;
-
-(* debug
-let matching metasenv1 metasenv2 context t1 t2 ugraph =
- let rc1 =
- try Some (matching1 metasenv1 metasenv2 context t1 t2 ugraph)
- with MatchingFailure -> None
- in
- let rc2 =
- try
- Some (matching2 metasenv1 metasenv2 context t1 t2 ugraph)
- with MatchingFailure -> None
- in
- match rc1,rc2 with
- | Some (s,m,g) , None ->
- prerr_endline (CicPp.ppterm t1);
- prerr_endline (CicPp.ppterm t2);
- prerr_endline "SOLO NOI";
- prerr_endline (CicMetaSubst.ppsubst s);
- s,m,g
- | None , Some _ ->
- prerr_endline (CicPp.ppterm t1);
- prerr_endline (CicPp.ppterm t2);
- prerr_endline "SOLO LUI";
- assert false
- | None, None -> raise MatchingFailure
- | Some (s,m,g), Some (s',m',g') ->
- let s = List.sort (fun (i,_) (j,_) -> i - j) s in
- let s' = List.sort (fun (i,_) (j,_) -> i - j) s' in
- if s <> s' then
- begin
- prerr_endline (CicMetaSubst.ppsubst s);
- prerr_endline (CicMetaSubst.ppsubst s');
- prerr_endline (CicPp.ppterm t1);
- prerr_endline (CicPp.ppterm t2);
- end;
- s,m,g
-*)
let matching = matching1;;
let check_eq context msg eq =
let o = !Utils.compare_terms t1 t2 in
let stat = (ty,t1,t2,o) in
let w = compute_equality_weight stat in
- let proof = BasicProof p in
+ let proof = BasicProof ([],p) in
let e = (w, proof, stat, newmetas) in
Some e, (newmeta+1)
| _ -> None, newmeta
let o = !Utils.compare_terms t1 t2 in
let stat = (ty,t1,t2,o) in
let w = compute_equality_weight stat in
- let e = (w, BasicProof (C.Rel index), stat, []) in
+ let e = (w, BasicProof ([],(C.Rel index)), stat, []) in
Some e, (newmeta+1)
| _ -> None, newmeta
in (
| C.LetIn (_, s, t) | C.Cast (s, t) ->
(has_vars s) || (has_vars t)
| _ -> false
- in
+ in
let rec aux newmeta = function
| [] -> [], newmeta
| (uri, term, termty)::tl ->
let o = !Utils.compare_terms t1 t2 in
let stat = (ty,t1,t2,o) in
let w = compute_equality_weight stat in
- let proof = BasicProof p in
+ let proof = BasicProof ([],p) in
let e = (w, proof, stat, newmetas) in
Some e, (newmeta+1)
| _ -> None, newmeta
let o = !Utils.compare_terms t1 t2 in
let stat = (ty,t1,t2,o) in
let w = compute_equality_weight stat in
- let e = (w, BasicProof term, stat, []) in
+ let e = (w, BasicProof ([],term), stat, []) in
Some e, (newmeta+1)
| _ -> None, newmeta
in
res
;;
-
+(*
let fix_metas_old newmeta (w, p, (ty, left, right, o), menv, args) =
let table = Hashtbl.create (List.length args) in
(Hashtbl.copy table)
in
let rec fix_proof = function
- | NoProof -> NoProof
+ | NoProof -> NoProof
| BasicProof term -> BasicProof (repl term)
| ProofBlock (subst, eq_URI, namety, bo, (pos, eq), p) ->
let subst' =
let neweq = (w, fix_proof p, (ty, left, right, o), menv', newargs) in
(newmeta +1, neweq)
;;
-
+*)
let relocate newmeta menv =
let subst, metasenv, newmeta =
List.fold_right
- (fun (i, context, ty) (subst, menv, maxmeta) ->
- let irl=CicMkImplicit.identity_relocation_list_for_metavariable context in
- let newsubst = (i, (context, (Cic.Meta (maxmeta, irl)), ty)) in
+ (fun (i, context, ty) (subst, menv, maxmeta) ->
+ let irl = [] (*
+ CicMkImplicit.identity_relocation_list_for_metavariable context *)
+ in
+ let newsubst = buildsubst i context (Cic.Meta(maxmeta,irl)) ty in
let newmeta = maxmeta, context, ty in
newsubst::subst, newmeta::menv, maxmeta+1)
menv ([], [], newmeta+1)
in
- let metasenv = CicMetaSubst.apply_subst_metasenv subst metasenv in
- let subst =
- List.map
- (fun (i, (context, term, ty)) ->
- let context = CicMetaSubst.apply_subst_context subst context in
- let term = CicMetaSubst.apply_subst subst term in
- let ty = CicMetaSubst.apply_subst subst ty in
- (i, (context, term, ty))) subst in
+ let metasenv = apply_subst_metasenv subst metasenv in
+ let subst = flatten_subst subst in
subst, metasenv, newmeta
fix_metas_old newmeta (w, p, (ty, left, right, o), menv, args) in
prerr_endline (string_of_equality eq); *)
let subst, metasenv, newmeta = relocate newmeta menv in
- let ty = CicMetaSubst.apply_subst subst ty in
- let left = CicMetaSubst.apply_subst subst left in
- let right = CicMetaSubst.apply_subst subst right in
- let rec fix_proof = function
+(*
+ if newmeta > 2839 then
+ begin
+ prerr_endline (CicPp.ppterm left ^ " = " ^ CicPp.ppterm right);
+ prerr_endline (CicMetaSubst.ppsubst subst);
+ prerr_endline (CicMetaSubst.ppmetasenv [] metasenv);
+ assert false;
+ end;
+*)
+ let ty = apply_subst subst ty in
+ let left = apply_subst subst left in
+ let right = apply_subst subst right in
+ let fix_proof = function
| NoProof -> NoProof
- | BasicProof term -> BasicProof (CicMetaSubst.apply_subst subst term)
+ | BasicProof (subst',term) -> BasicProof (subst@subst',term)
| ProofBlock (subst', eq_URI, namety, bo, (pos, eq), p) ->
(*
let newsubst =
List.map
(fun (i, (context, term, ty)) ->
- let context = CicMetaSubst.apply_subst_context subst context in
- let term = CicMetaSubst.apply_subst subst term in
- let ty = CicMetaSubst.apply_subst subst ty in
+ 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 *)
ProofBlock (subst@subst', eq_URI, namety, bo, (pos, eq), p)
| p -> assert false
let o = !Utils.compare_terms t1 t2 in
let stat = (ty,t1,t2,o) in
let w = compute_equality_weight stat in
- let e = (w, BasicProof proof, stat, []) in
+ let e = (w, BasicProof ([],proof), stat, []) in
e
| _ ->
raise TermIsNotAnEquality