aboutsummaryrefslogtreecommitdiff
path: root/pretyping
diff options
context:
space:
mode:
authorPierre-Marie Pédrot2015-02-26 17:23:58 +0100
committerPierre-Marie Pédrot2015-02-26 17:23:58 +0100
commit93db616a6cbebf37f2f4f983963a87a4f66972e7 (patch)
tree94577e8d2128fd35c449acb017a637e81a701ed5 /pretyping
parent31c8c317affc8fb0ae818336c70ba210208249cc (diff)
parentbc7d29e4c0f53d5c8e654157c4137c7e82910a7a (diff)
Merge branch 'v8.5'
Diffstat (limited to 'pretyping')
-rw-r--r--pretyping/evarsolve.ml70
-rw-r--r--pretyping/evarutil.ml13
-rw-r--r--pretyping/evarutil.mli10
-rw-r--r--pretyping/evd.ml33
-rw-r--r--pretyping/evd.mli9
5 files changed, 71 insertions, 64 deletions
diff --git a/pretyping/evarsolve.ml b/pretyping/evarsolve.ml
index b01f29a40a..f355d9a725 100644
--- a/pretyping/evarsolve.ml
+++ b/pretyping/evarsolve.ml
@@ -121,11 +121,11 @@ let is_success = function Success _ -> true | UnifFailure _ -> false
let test_success conv_algo env evd c c' rhs =
is_success (conv_algo env evd c c' rhs)
-let add_conv_oriented_pb (pbty,env,t1,t2) evd =
+let add_conv_oriented_pb ?(tail=true) (pbty,env,t1,t2) evd =
match pbty with
- | Some true -> add_conv_pb (Reduction.CUMUL,env,t1,t2) evd
- | Some false -> add_conv_pb (Reduction.CUMUL,env,t2,t1) evd
- | None -> add_conv_pb (Reduction.CONV,env,t1,t2) evd
+ | Some true -> add_conv_pb ~tail (Reduction.CUMUL,env,t1,t2) evd
+ | Some false -> add_conv_pb ~tail (Reduction.CUMUL,env,t2,t1) evd
+ | None -> add_conv_pb ~tail (Reduction.CONV,env,t1,t2) evd
(*------------------------------------*
* Restricting existing evars *
@@ -178,7 +178,9 @@ let restrict_instance evd evk filter argsv =
Filter.filter_array (Filter.compose (evar_filter evi) filter) argsv
let noccur_evar env evd evk c =
- let rec occur_rec k c = match kind_of_term c with
+ let cache = ref Int.Set.empty (* cache for let-ins *) in
+ let rec occur_rec k c =
+ match kind_of_term c with
| Evar (evk',args' as ev') ->
(match safe_evar_value evd ev' with
| Some c -> occur_rec k c
@@ -186,9 +188,10 @@ let noccur_evar env evd evk c =
if Evar.equal evk evk' then raise Occur
else Array.iter (occur_rec k) args')
| Rel i when i > k ->
+ if not (Int.Set.mem (i-k) !cache) then
(match pi2 (Environ.lookup_rel (i-k) env) with
| None -> ()
- | Some b -> occur_rec k (lift i b))
+ | Some b -> cache := Int.Set.add (i-k) !cache; occur_rec k (lift i b))
| Proj (p,c) -> occur_rec k (Retyping.expand_projection env evd p c [])
| _ -> iter_constr_with_binders succ occur_rec k c
in
@@ -315,6 +318,7 @@ let expand_vars_in_term env = expand_vars_in_term_using (make_alias_map env)
let free_vars_and_rels_up_alias_expansion aliases c =
let acc1 = ref Int.Set.empty and acc2 = ref Id.Set.empty in
+ let acc3 = ref Int.Set.empty and acc4 = ref Id.Set.empty in
let cache_rel = ref Int.Set.empty and cache_var = ref Id.Set.empty in
let is_in_cache depth = function
| Rel n -> Int.Set.mem (n-depth) !cache_rel
@@ -329,8 +333,13 @@ let free_vars_and_rels_up_alias_expansion aliases c =
| Rel _ | Var _ as ck ->
if is_in_cache depth ck then () else begin
put_in_cache depth ck;
- let c = expansion_of_var aliases c in
+ let c' = expansion_of_var aliases c in
+ (if c != c' then (* expansion, hence a let-in *)
match kind_of_term c with
+ | Var id -> acc4 := Id.Set.add id !acc4
+ | Rel n -> if n >= depth+1 then acc3 := Int.Set.add (n-depth) !acc3
+ | _ -> ());
+ match kind_of_term c' with
| Var id -> acc2 := Id.Set.add id !acc2
| Rel n -> if n >= depth+1 then acc1 := Int.Set.add (n-depth) !acc1
| _ -> frec (aliases,depth) c end
@@ -342,7 +351,7 @@ let free_vars_and_rels_up_alias_expansion aliases c =
frec (aliases,depth) c
in
frec (aliases,0) c;
- (!acc1,!acc2)
+ (!acc1,!acc2,!acc3,!acc4)
(********************************)
(* Managing pattern-unification *)
@@ -378,7 +387,7 @@ let get_actual_deps aliases l t =
l
else
(* Probably strong restrictions coming from t being evar-closed *)
- let (fv_rels,fv_ids) = free_vars_and_rels_up_alias_expansion aliases t in
+ let (fv_rels,fv_ids,_,_) = free_vars_and_rels_up_alias_expansion aliases t in
List.filter (fun c ->
match kind_of_term c with
| Var id -> Id.Set.mem id fv_ids
@@ -1017,29 +1026,42 @@ exception CannotProject of evar_map * existential
of subterms to eventually discard so as to be allowed to keep ti.
*)
-let rec is_constrainable_in top force k (ev,(fv_rels,fv_ids) as g) t =
- let f,args = decompose_app_vect t in
+let rec is_constrainable_in top evd k (ev,(fv_rels,fv_ids) as g) t =
+ let f,args2 = decompose_app_vect t in
+ let f,args1 = decompose_app_vect (whd_evar evd f) in
+ let args = Array.append args1 args2 in
match kind_of_term f with
| Construct ((ind,_),u) ->
let n = Inductiveops.inductive_nparams ind in
if n > Array.length args then true (* We don't try to be more clever *)
else
let params = fst (Array.chop n args) in
- Array.for_all (is_constrainable_in false force k g) params
- | Ind _ -> Array.for_all (is_constrainable_in false force k g) args
- | Prod (_,t1,t2) -> is_constrainable_in false force k g t1 && is_constrainable_in false force k g t2
- | Evar (ev',_) -> top || not (force || Evar.equal ev' ev) (*If ev' needed, one may also try to restrict it*)
+ Array.for_all (is_constrainable_in false evd k g) params
+ | Ind _ -> Array.for_all (is_constrainable_in false evd k g) args
+ | Prod (na,t1,t2) -> is_constrainable_in false evd k g t1 && is_constrainable_in false evd k g t2
+ | Evar (ev',_) -> top || not (Evar.equal ev' ev) (*If ev' needed, one may also try to restrict it*)
| Var id -> Id.Set.mem id fv_ids
| Rel n -> n <= k || Int.Set.mem n fv_rels
| Sort _ -> true
| _ -> (* We don't try to be more clever *) true
-let has_constrainable_free_vars evd aliases force k ev (fv_rels,fv_ids as fvs) t =
- let t = expansion_of_var aliases t in
- match kind_of_term t with
- | Var id -> Id.Set.mem id fv_ids
- | Rel n -> n <= k || Int.Set.mem n fv_rels
- | _ -> is_constrainable_in true force k (ev,fvs) t
+let has_constrainable_free_vars env evd aliases force k ev (fv_rels,fv_ids,let_rels,let_ids) t =
+ let t' = expansion_of_var aliases t in
+ if t' != t then
+ (* t is a local definition, we keep it only if appears in the list *)
+ (* of let-in variables effectively occurring on the right-hand side, *)
+ (* which is the only reason to keep it when inverting arguments *)
+ match kind_of_term t with
+ | Var id -> Id.Set.mem id let_ids
+ | Rel n -> Int.Set.mem n let_rels
+ | _ -> assert false
+ else
+ (* t is an instance for a proper variable; we filter it along *)
+ (* the free variables allowed to occur *)
+ match kind_of_term t with
+ | Var id -> Id.Set.mem id fv_ids
+ | Rel n -> n <= k || Int.Set.mem n fv_rels
+ | _ -> (not force || noccur_evar env evd ev t) && is_constrainable_in true evd k (ev,(fv_rels,fv_ids)) t
exception EvarSolvedOnTheFly of evar_map * constr
@@ -1049,7 +1071,7 @@ let project_evar_on_evar force g env evd aliases k2 pbty (evk1,argsv1 as ev1) (e
(* Apply filtering on ev1 so that fvs(ev1) are in fvs(ev2). *)
let fvs2 = free_vars_and_rels_up_alias_expansion aliases (mkEvar ev2) in
let filter1 = restrict_upon_filter evd evk1
- (has_constrainable_free_vars evd aliases force k2 evk2 fvs2)
+ (has_constrainable_free_vars env evd aliases force k2 evk2 fvs2)
argsv1 in
let candidates1 =
try restrict_candidates g env evd filter1 ev1 ev2
@@ -1111,13 +1133,13 @@ let solve_evar_evar_aux force f g env evd pbty (evk1,args1 as ev1) (evk2,args2 a
with CannotProject (evd,ev2) ->
try solve_evar_evar_l2r force f g env evd aliases pbty ev1 ev2
with CannotProject (evd,ev1) ->
- add_conv_oriented_pb (pbty,env,mkEvar ev1,mkEvar ev2) evd
+ add_conv_oriented_pb ~tail:true (pbty,env,mkEvar ev1,mkEvar ev2) evd
else
try solve_evar_evar_l2r force f g env evd aliases pbty ev1 ev2
with CannotProject (evd,ev1) ->
try solve_evar_evar_l2r force f g env evd aliases (opp_problem pbty) ev2 ev1
with CannotProject (evd,ev2) ->
- add_conv_oriented_pb (pbty,env,mkEvar ev1,mkEvar ev2) evd
+ add_conv_oriented_pb ~tail:true (pbty,env,mkEvar ev1,mkEvar ev2) evd
let solve_evar_evar ?(force=false) f g env evd pbty (evk1,args1 as ev1) (evk2,args2 as ev2) =
let pbty = if force then None else pbty in
diff --git a/pretyping/evarutil.ml b/pretyping/evarutil.ml
index d286b98e83..201a16ebeb 100644
--- a/pretyping/evarutil.ml
+++ b/pretyping/evarutil.ml
@@ -212,9 +212,11 @@ let whd_head_evar sigma c =
(* Creating new metas *)
(**********************)
+let meta_counter_summary_name = "meta counter"
+
(* Generator of metavariables *)
let new_meta =
- let meta_ctr = Summary.ref 0 ~name:"meta counter" in
+ let meta_ctr = Summary.ref 0 ~name:meta_counter_summary_name in
fun () -> incr meta_ctr; !meta_ctr
let mk_new_meta () = mkMeta(new_meta())
@@ -241,9 +243,11 @@ let make_pure_subst evi args =
(* Creating new evars *)
(**********************)
+let evar_counter_summary_name = "evar counter"
+
(* Generator of existential names *)
let new_untyped_evar =
- let evar_ctr = Summary.ref 0 ~name:"evar counter" in
+ let evar_ctr = Summary.ref 0 ~name:evar_counter_summary_name in
fun () -> incr evar_ctr; Evar.unsafe_of_int !evar_ctr
(*------------------------------------*
@@ -838,3 +842,8 @@ let subterm_source evk (loc,k) =
| Evar_kinds.SubEvar (evk) -> evk
| _ -> evk in
(loc,Evar_kinds.SubEvar evk)
+
+
+(** Term exploration up to isntantiation. *)
+let kind_of_term_upto sigma t =
+ Constr.kind (Reductionops.whd_evar sigma t)
diff --git a/pretyping/evarutil.mli b/pretyping/evarutil.mli
index f89266a60a..49036798e6 100644
--- a/pretyping/evarutil.mli
+++ b/pretyping/evarutil.mli
@@ -199,6 +199,13 @@ val nf_evar_map_universes : evar_map -> evar_map * (constr -> constr)
exception Uninstantiated_evar of existential_key
val flush_and_check_evars : evar_map -> constr -> constr
+(** {6 Term manipulation up to instantiation} *)
+
+(** Like {!Constr.kind} except that [kind_of_term sigma t] exposes [t]
+ as an evar [e] only if [e] is uninstantiated in [sigma]. Otherwise the
+ value of [e] in [sigma] is (recursively) used. *)
+val kind_of_term_upto : evar_map -> constr -> (constr,types) kind_of_term
+
(** {6 debug pretty-printer:} *)
val pr_tycon : env -> type_constraint -> Pp.std_ppcmds
@@ -236,3 +243,6 @@ val evd_comb2 : (evar_map -> 'b -> 'c -> evar_map * 'a) -> evar_map ref -> 'b ->
val subterm_source : existential_key -> Evar_kinds.t Loc.located ->
Evar_kinds.t Loc.located
+
+val meta_counter_summary_name : string
+val evar_counter_summary_name : string
diff --git a/pretyping/evd.ml b/pretyping/evd.ml
index 9313e22320..454c51195b 100644
--- a/pretyping/evd.ml
+++ b/pretyping/evd.ml
@@ -568,14 +568,6 @@ type evar_map = {
(*** Lifting primitive from Evar.Map. ***)
-(* HH: The progress tactical now uses this function. *)
-let progress_evar_map d1 d2 =
- let is_new k v =
- assert (v.evar_body == Evar_empty);
- EvMap.mem k d2.defn_evars
- in
- not (d1 == d2) && EvMap.exists is_new d1.undf_evars
-
let add_name_newly_undefined naming evk evi (evtoid,idtoev) =
let id = match naming with
| Misctypes.IntroAnonymous ->
@@ -779,7 +771,9 @@ let merge_universe_context evd uctx' =
let set_universe_context evd uctx' =
{ evd with universes = uctx' }
-let add_conv_pb pb d = {d with conv_pbs = pb::d.conv_pbs}
+let add_conv_pb ?(tail=false) pb d =
+ if tail then {d with conv_pbs = d.conv_pbs @ [pb]}
+ else {d with conv_pbs = pb::d.conv_pbs}
let evar_source evk d = (find d evk).evar_source
@@ -1301,27 +1295,6 @@ let e_eq_constr_univs evdref t u =
let eq_constr_univs_test evd t u =
snd (eq_constr_univs evd t u)
-let eq_named_context_val d ctx1 ctx2 =
- ctx1 == ctx2 ||
- let c1 = named_context_of_val ctx1 and c2 = named_context_of_val ctx2 in
- let eq_named_declaration (i1, c1, t1) (i2, c2, t2) =
- Id.equal i1 i2 && Option.equal (eq_constr_univs_test d) c1 c2
- && (eq_constr_univs_test d) t1 t2
- in List.equal eq_named_declaration c1 c2
-
-let eq_evar_body d b1 b2 = match b1, b2 with
-| Evar_empty, Evar_empty -> true
-| Evar_defined t1, Evar_defined t2 -> eq_constr_univs_test d t1 t2
-| _ -> false
-
-let eq_evar_info d ei1 ei2 =
- ei1 == ei2 ||
- eq_constr_univs_test d ei1.evar_concl ei2.evar_concl &&
- eq_named_context_val d (ei1.evar_hyps) (ei2.evar_hyps) &&
- eq_evar_body d ei1.evar_body ei2.evar_body
- (** ppedrot: [eq_constr] may be a bit too permissive here *)
-
-
(**********************************************************)
(* Accessing metas *)
diff --git a/pretyping/evd.mli b/pretyping/evd.mli
index cf6ba07c60..0765b951fd 100644
--- a/pretyping/evd.mli
+++ b/pretyping/evd.mli
@@ -126,10 +126,6 @@ type evar_map
(** Type of unification state. Essentially a bunch of state-passing data needed
to handle incremental term construction. *)
-val progress_evar_map : evar_map -> evar_map -> bool
-(** Assuming that the second map extends the first one, this says if
- some existing evar has been refined *)
-
val empty : evar_map
(** The empty evar map. *)
@@ -204,9 +200,6 @@ val add_constraints : evar_map -> Univ.constraints -> evar_map
val undefined_map : evar_map -> evar_info Evar.Map.t
(** Access the undefined evar mapping directly. *)
-val eq_evar_info : evar_map -> evar_info -> evar_info -> bool
-(** Compare the evar_info's up to the universe constraints of the evar map. *)
-
val drop_all_defined : evar_map -> evar_map
(** {6 Instantiating partial terms} *)
@@ -397,7 +390,7 @@ type clbinding =
(** Unification constraints *)
type conv_pb = Reduction.conv_pb
type evar_constraint = conv_pb * env * constr * constr
-val add_conv_pb : evar_constraint -> evar_map -> evar_map
+val add_conv_pb : ?tail:bool -> evar_constraint -> evar_map -> evar_map
val extract_changed_conv_pbs : evar_map ->
(Evar.Set.t -> evar_constraint -> bool) ->