diff --git a/src/plugins/qed/logic.ml b/src/plugins/qed/logic.ml index a451922eb1f2411ea7fb1f72e7a2e906f9f8a4c0..91338a35f39b1ae9c23f051afebb2150d72373f5 100644 --- a/src/plugins/qed/logic.ml +++ b/src/plugins/qed/logic.ml @@ -368,14 +368,23 @@ sig val e_subst_var : var -> term -> term -> term - (** {3 Locally Nameless Representation} *) + (** {3 Locally Nameless Representation} - val lc_closed : term -> bool (** All bound variables are under their binder *) + These functions can be {i unsafe} because they might expose terms + that contains non-bound b-vars. Never use such terms to build + substitutions (sigma). + *) val lc_vars : term -> Bvars.t + val lc_closed : term -> bool + (** All bound variables are under their binder *) - val lc_term : term -> lc_term val lc_repr : lc_term -> term + (** Calling this function is {i unsafe} unless the term is lc_closed *) + + val lc_iter : (term -> unit) -> term -> unit + (** Similar to [f_iter] but exposes non-closed sub-terms of `Bind` + as regular [term] values instead of [lc_term] ones. *) (** {3 Iteration Scheme} *) @@ -392,8 +401,6 @@ sig Raises Invalid_argument in case of a bind-term without pool. The optional pool must contain all free variables of the term. *) - val lc_iter : (term -> unit) -> term -> unit - (** {3 Partial Typing} *) (** Try to extract a type of term. diff --git a/src/plugins/qed/term.ml b/src/plugins/qed/term.ml index 1c3ca9819c35e78e420af817cd891e54c527bb2c..ff663736385c38996242a8f7a39857d35bc6ba1e 100644 --- a/src/plugins/qed/term.ml +++ b/src/plugins/qed/term.ml @@ -1970,7 +1970,6 @@ struct let lc_closed_at n e = Bvars.closed_at n e.bind let lc_vars e = e.bind let lc_repr e = e - let lc_term e = e (* Warning: must only be used for alpha-conversion @@ -2080,6 +2079,13 @@ struct filter = [] ; } + let validate fn e = + if false && not (lc_closed e) then + begin + Format.eprintf "Invalid %s: %a@." fn pretty e ; + raise (Invalid_argument (fn ^ ": non lc-closed binding")) + end + let cache sigma = ref begin match sigma.shared with MAP( m , _ ) -> m | _ -> Tmap.empty @@ -2087,11 +2093,15 @@ struct let fresh sigma t = fresh sigma.pool t + let call f e = + let v = f e in + validate "Qed.Subst.add_fun" v ; v + let rec compute e = function | EMPTY -> raise Not_found - | FUN(f,EMPTY) -> f e + | FUN(f,EMPTY) -> call f e | MAP(m,EMPTY) -> Tmap.find e m - | FUN(f,s) -> (try f e with Not_found -> compute e s) + | FUN(f,s) -> (try call f e with Not_found -> compute e s) | MAP(m,s) -> (try Tmap.find e m with Not_found -> compute e s) let get sigma a = compute a sigma.shared @@ -2100,13 +2110,22 @@ struct List.for_all (fun f -> f a) sigma.filter let add sigma a b = + validate "Qed.Subst.add (domain)" a ; + validate "Qed.Subst.add (codomain)" b ; sigma.shared <- match sigma.shared with | MAP(m,s) -> MAP (Tmap.add a b m,s) | (FUN _ | EMPTY) as s -> MAP (Tmap.add a b Tmap.empty,s) let add_map sigma m = if not (Tmap.is_empty m) then - sigma.shared <- MAP(m,sigma.shared) + begin + Tmap.iter + (fun a b -> + validate "Qed.Subst.add_map (domain)" a ; + validate "Qed.Subst.add_map (codomain)" b ; + ) m ; + sigma.shared <- MAP(m,sigma.shared) + end let add_fun sigma f = sigma.shared <- FUN(f,sigma.shared) @@ -2184,9 +2203,12 @@ struct c_apply f' vs let e_subst sigma e = + Subst.validate "Qed.e_subst (target)" e ; subst sigma Intmap.empty e let e_subst_var x v e = + Subst.validate "Qed.e_subst_var (value)" v ; + Subst.validate "Qed.e_subst_var (target)" e ; let filter e = Vars.mem x e.vars in if not (filter e) then e else if Bvars.is_empty v.bind && Bvars.is_empty e.bind then @@ -2302,8 +2324,8 @@ struct match q with Forall | Exists -> Vars.mem x e.vars | Lambda -> true in if do_bind then match let_intro_case q x e with - | None -> c_bind q (tau_of_var x) (lc_close x e) | Some v -> e_subst_var x v e (* case [let x = v ; e] *) + | _ -> c_bind q (tau_of_var x) (lc_close x e) else e let e_close qs a = List.fold_left (fun b (q,x) -> e_bind q x b) a qs diff --git a/src/plugins/wp/Lang.ml b/src/plugins/wp/Lang.ml index 4996cc10890733f2cf17ff7c8c47057dade44838..1f2ecea227a8d5771411009634b05f861e16ddf6 100644 --- a/src/plugins/wp/Lang.ml +++ b/src/plugins/wp/Lang.ml @@ -757,7 +757,7 @@ struct let p_forall = e_forall let p_exists = e_exists let p_subst = e_subst - let p_apply = e_subst_var + let p_subst_var = e_subst_var let p_and p q = e_and [p;q] let p_or p q = e_or [p;q] diff --git a/src/plugins/wp/Lang.mli b/src/plugins/wp/Lang.mli index d02b68cdb98e5ad7a59352b3c7e30d1680f45490..ee4a6dade82b253a7bfbfb82cf5bd26927b89d52 100644 --- a/src/plugins/wp/Lang.mli +++ b/src/plugins/wp/Lang.mli @@ -365,7 +365,7 @@ sig val e_subst : sigma -> term -> term val p_subst : sigma -> pred -> pred - val p_apply : var -> term -> pred -> pred + val p_subst_var : var -> term -> pred -> pred val e_vars : term -> var list (** Sorted *) val p_vars : pred -> var list (** Sorted *) diff --git a/src/plugins/wp/TacInstance.ml b/src/plugins/wp/TacInstance.ml index 9e5f2c1311c7d68202a9699cdc34bfad81bdb717..1b95285882dde1a81db416d4eb23ac4b1537fa58 100644 --- a/src/plugins/wp/TacInstance.ml +++ b/src/plugins/wp/TacInstance.ml @@ -79,12 +79,13 @@ let rec bind_exists bindings property = Lang.F.p_bind L.Exists x property else let value = Tactical.selected v in - Lang.F.p_apply x value property + Lang.F.p_subst_var x value property in bind_exists bindings closed let rec range x a b w = if a <= b then - ( Printf.sprintf "%s-%d" (fst w) a , F.p_apply x (F.e_int a) (snd w) ) + ( Printf.sprintf "%s-%d" (fst w) a , + Lang.F.p_subst_var x (F.e_int a) (snd w) ) :: range x (succ a) b w else [] @@ -104,7 +105,7 @@ let rec bind_forall ranges bindings property = bind_forall ranges bindings (Lang.F.p_bind L.Forall x property) | _ -> let value = Tactical.selected v in - bind_forall ranges bindings (Lang.F.p_apply x value property) + bind_forall ranges bindings (Lang.F.p_subst_var x value property) end | [] -> bind_ranges [ "Instance" , property ] ranges