summaryrefslogtreecommitdiff
path: root/tactics/hints.ml
diff options
context:
space:
mode:
Diffstat (limited to 'tactics/hints.ml')
-rw-r--r--tactics/hints.ml227
1 files changed, 137 insertions, 90 deletions
diff --git a/tactics/hints.ml b/tactics/hints.ml
index 5621c365..55d62e15 100644
--- a/tactics/hints.ml
+++ b/tactics/hints.ml
@@ -68,7 +68,7 @@ let decompose_app_bound t =
(* The Type of Constructions Autotactic Hints *)
(************************************************************************)
-type 'a auto_tactic =
+type 'a auto_tactic_ast =
| Res_pf of 'a (* Hint Apply *)
| ERes_pf of 'a (* Hint EApply *)
| Give_exact of 'a
@@ -92,18 +92,23 @@ type hint_term =
| IsGlobRef of global_reference
| IsConstr of constr * Univ.universe_context_set
+type 'a auto_tactic = 'a auto_tactic_ast
+
type 'a gen_auto_tactic = {
pri : int; (* A number lower is higher priority *)
poly : polymorphic; (** Is the hint polymorpic and hence should be refreshed at each application *)
pat : constr_pattern option; (* A pattern for the concl of the Goal *)
name : hints_path_atom; (* A potential name to refer to the hint *)
- code : 'a auto_tactic (* the tactic to apply when the concl matches pat *)
+ code : 'a (* the tactic to apply when the concl matches pat *)
}
-type pri_auto_tactic = (constr * clausenv) gen_auto_tactic
+type pri_auto_tactic = (constr * clausenv) auto_tactic gen_auto_tactic
type hint_entry = global_reference option *
- (constr * types * Univ.universe_context_set) gen_auto_tactic
+ (constr * types * Univ.universe_context_set) auto_tactic_ast gen_auto_tactic
+
+let run_auto_tactic tac k = k tac
+let repr_auto_tactic tac = tac
let eq_hints_path_atom p1 p2 = match p1, p2 with
| PathHints gr1, PathHints gr2 -> List.equal eq_gr gr1 gr2
@@ -156,10 +161,19 @@ module Bounded_net = Btermdn.Make(struct
let compare = pri_order_int
end)
-type search_entry = stored_data list * stored_data list * Bounded_net.t * bool array list
-
+type search_entry = {
+ sentry_nopat : stored_data list;
+ sentry_pat : stored_data list;
+ sentry_bnet : Bounded_net.t;
+ sentry_mode : bool array list;
+}
-let empty_se = ([],[],Bounded_net.create (),[])
+let empty_se = {
+ sentry_nopat = [];
+ sentry_pat = [];
+ sentry_bnet = Bounded_net.empty;
+ sentry_mode = [];
+}
let eq_pri_auto_tactic (_, x) (_, y) =
if Int.equal x.pri y.pri && Option.equal constr_pattern_eq x.pat y.pat then
@@ -177,27 +191,29 @@ let eq_pri_auto_tactic (_, x) (_, y) =
else
false
-let add_tac pat t st (l,l',dn,m) =
+let add_tac pat t st se =
match pat with
| None ->
- if not (List.exists (eq_pri_auto_tactic t) l) then (List.insert pri_order t l, l', dn, m)
- else (l, l', dn, m)
+ if List.exists (eq_pri_auto_tactic t) se.sentry_nopat then se
+ else { se with sentry_nopat = List.insert pri_order t se.sentry_nopat }
| Some pat ->
- if not (List.exists (eq_pri_auto_tactic t) l')
- then (l, List.insert pri_order t l', Bounded_net.add st dn (pat,t), m) else (l, l', dn, m)
+ if List.exists (eq_pri_auto_tactic t) se.sentry_pat then se
+ else { se with
+ sentry_pat = List.insert pri_order t se.sentry_pat;
+ sentry_bnet = Bounded_net.add st se.sentry_bnet (pat, t); }
-let rebuild_dn st ((l,l',dn,m) : search_entry) =
+let rebuild_dn st se =
let dn' =
List.fold_left
(fun dn (id, t) -> Bounded_net.add (Some st) dn (Option.get t.pat, (id, t)))
- (Bounded_net.create ()) l'
+ Bounded_net.empty se.sentry_pat
in
- (l, l', dn', m)
+ { se with sentry_bnet = dn' }
-let lookup_tacs concl st (l,l',dn) =
- let l' = Bounded_net.lookup st dn concl in
+let lookup_tacs concl st se =
+ let l' = Bounded_net.lookup st se.sentry_bnet concl in
let sl' = List.stable_sort pri_order_int l' in
- List.merge pri_order_int l sl'
+ List.merge pri_order_int se.sentry_nopat sl'
module Constr_map = Map.Make(RefOrdered)
@@ -378,7 +394,7 @@ module Hint_db = struct
hintdb_state : Names.transparent_state;
hintdb_cut : hints_path;
hintdb_unfolds : Id.Set.t * Cset.t;
- mutable hintdb_max_id : int;
+ hintdb_max_id : int;
use_dn : bool;
hintdb_map : search_entry Constr_map.t;
(* A list of unindexed entries starting with an unfoldable constant
@@ -386,8 +402,9 @@ module Hint_db = struct
hintdb_nopat : (global_reference option * stored_data) list
}
- let next_hint_id t =
- let h = t.hintdb_max_id in t.hintdb_max_id <- succ t.hintdb_max_id; h
+ let next_hint_id db =
+ let h = db.hintdb_max_id in
+ { db with hintdb_max_id = succ db.hintdb_max_id }, h
let empty st use_dn = { hintdb_state = st;
hintdb_cut = PathEmpty;
@@ -411,34 +428,38 @@ module Hint_db = struct
if List.is_empty modes then true
else List.exists (matches_mode args) modes
+ let merge_entry db nopat pat =
+ let h = Sort.merge pri_order (List.map snd db.hintdb_nopat @ nopat) pat in
+ List.map realize_tac h
+
let map_none db =
- List.map realize_tac (Sort.merge pri_order (List.map snd db.hintdb_nopat) [])
-
+ merge_entry db [] []
+
let map_all k db =
- let (l,l',_,_) = find k db in
- List.map realize_tac (Sort.merge pri_order (List.map snd db.hintdb_nopat @ l) l')
+ let se = find k db in
+ merge_entry db se.sentry_nopat se.sentry_pat
(** Precondition: concl has no existentials *)
let map_auto (k,args) concl db =
- let (l,l',dn,m) = find k db in
+ let se = find k db in
let st = if db.use_dn then (Some db.hintdb_state) else None in
- let l' = lookup_tacs concl st (l,l',dn) in
- List.map realize_tac (Sort.merge pri_order (List.map snd db.hintdb_nopat) l')
+ let pat = lookup_tacs concl st se in
+ merge_entry db [] pat
let map_existential (k,args) concl db =
- let (l,l',_,m) = find k db in
- if matches_modes args m then
- List.map realize_tac (Sort.merge pri_order (List.map snd db.hintdb_nopat @ l) l')
- else List.map realize_tac (List.map snd db.hintdb_nopat)
+ let se = find k db in
+ if matches_modes args se.sentry_mode then
+ merge_entry db se.sentry_nopat se.sentry_pat
+ else merge_entry db [] []
(* [c] contains an existential *)
let map_eauto (k,args) concl db =
- let (l,l',dn,m) = find k db in
- if matches_modes args m then
- let st = if db.use_dn then Some db.hintdb_state else None in
- let l' = lookup_tacs concl st (l,l',dn) in
- List.map realize_tac (Sort.merge pri_order (List.map snd db.hintdb_nopat) l')
- else List.map realize_tac (List.map snd db.hintdb_nopat)
+ let se = find k db in
+ if matches_modes args se.sentry_mode then
+ let st = if db.use_dn then Some db.hintdb_state else None in
+ let pat = lookup_tacs concl st se in
+ merge_entry db [] pat
+ else merge_entry db [] []
let is_exact = function
| Give_exact _ -> true
@@ -490,16 +511,19 @@ module Hint_db = struct
state, { db with hintdb_unfolds = unfs }, true
| _ -> db.hintdb_state, db, false
in
- let db = if db.use_dn && rebuild then rebuild_db st' db else db
- in addkv k (next_hint_id db) v db
+ let db = if db.use_dn && rebuild then rebuild_db st' db else db in
+ let db, id = next_hint_id db in
+ addkv k id v db
let add_list l db = List.fold_left (fun db k -> add_one k db) db l
let remove_sdl p sdl = List.smartfilter p sdl
- let remove_he st p (sl1, sl2, dn, m as he) =
- let sl1' = remove_sdl p sl1 and sl2' = remove_sdl p sl2 in
- if sl1' == sl1 && sl2' == sl2 then he
- else rebuild_dn st (sl1', sl2', dn, m)
+
+ let remove_he st p se =
+ let sl1' = remove_sdl p se.sentry_nopat in
+ let sl2' = remove_sdl p se.sentry_pat in
+ if sl1' == se.sentry_nopat && sl2' == se.sentry_pat then se
+ else rebuild_dn st { se with sentry_nopat = sl1'; sentry_pat = sl2' }
let remove_list grs db =
let filter (_, h) =
@@ -510,13 +534,16 @@ module Hint_db = struct
let remove_one gr db = remove_list [gr] db
+ let get_entry se = List.map realize_tac (se.sentry_nopat @ se.sentry_pat)
+
let iter f db =
+ let iter_se k se = f (Some k) se.sentry_mode (get_entry se) in
f None [] (List.map (fun x -> realize_tac (snd x)) db.hintdb_nopat);
- Constr_map.iter (fun k (l,l',_,m) -> f (Some k) m (List.map realize_tac (l@l'))) db.hintdb_map
+ Constr_map.iter iter_se db.hintdb_map
let fold f db accu =
let accu = f None [] (List.map (fun x -> snd (snd x)) db.hintdb_nopat) accu in
- Constr_map.fold (fun k (l,l',_,m) -> f (Some k) m (List.map snd (l@l'))) db.hintdb_map accu
+ Constr_map.fold (fun k se -> f (Some k) se.sentry_mode (get_entry se)) db.hintdb_map accu
let transparent_state db = db.hintdb_state
@@ -528,8 +555,9 @@ module Hint_db = struct
{ db with hintdb_cut = normalize_path (PathOr (db.hintdb_cut, path)) }
let add_mode gr m db =
- let (l,l',dn,ms) = find gr db in
- { db with hintdb_map = Constr_map.add gr (l,l',dn,m :: ms) db.hintdb_map }
+ let se = find gr db in
+ let se = { se with sentry_mode = m :: se.sentry_mode } in
+ { db with hintdb_map = Constr_map.add gr se db.hintdb_map }
let cut db = db.hintdb_cut
@@ -609,7 +637,7 @@ let make_exact_entry env sigma pri poly ?(name=PathAny) (c, cty, ctx) =
match kind_of_term cty with
| Prod _ -> failwith "make_exact_entry"
| _ ->
- let pat = snd (Patternops.pattern_of_constr env sigma cty) in
+ let pat = pi3 (Patternops.pattern_of_constr env sigma cty) in
let hd =
try head_pattern_bound pat
with BoundPattern -> failwith "make_exact_entry"
@@ -628,7 +656,7 @@ let make_apply_entry env sigma (eapply,hnf,verbose) pri poly ?(name=PathAny) (c,
let sigma' = Evd.merge_context_set univ_flexible sigma ctx in
let ce = mk_clenv_from_env env sigma' None (c,cty) in
let c' = clenv_type (* ~reduce:false *) ce in
- let pat = snd (Patternops.pattern_of_constr env ce.evd c') in
+ let pat = pi3 (Patternops.pattern_of_constr env ce.evd c') in
let hd =
try head_pattern_bound pat
with BoundPattern -> failwith "make_apply_entry" in
@@ -726,7 +754,7 @@ let make_trivial env sigma poly ?(name=PathAny) r =
let ce = mk_clenv_from_env env sigma None (c,t) in
(Some hd, { pri=1;
poly = poly;
- pat = Some (snd (Patternops.pattern_of_constr env ce.evd (clenv_type ce)));
+ pat = Some (pi3 (Patternops.pattern_of_constr env ce.evd (clenv_type ce)));
name = name;
code=Res_pf_THEN_trivial_fail(c,t,ctx) })
@@ -782,10 +810,15 @@ let add_mode dbname l m =
let db' = Hint_db.add_mode l m db in
searchtable_add (dbname, db')
-type hint_obj = bool * string * hint_action (* locality, name, action *)
+type hint_obj = {
+ hint_local : bool;
+ hint_name : string;
+ hint_action : hint_action;
+}
-let cache_autohint (_,(local,name,hints)) =
- match hints with
+let cache_autohint (_, h) =
+ let name = h.hint_name in
+ match h.hint_action with
| CreateDB (b, st) -> searchtable_add (name, Hint_db.empty st b)
| AddTransparency (grs, b) -> add_transparency name grs b
| AddHints hints -> add_hint name hints
@@ -793,7 +826,7 @@ let cache_autohint (_,(local,name,hints)) =
| AddCut path -> add_cut name path
| AddMode (l, m) -> add_mode name l m
-let subst_autohint (subst,(local,name,hintlist as obj)) =
+let subst_autohint (subst, obj) =
let subst_key gr =
let (lab'', elab') = subst_global subst gr in
let gr' =
@@ -835,29 +868,30 @@ let subst_autohint (subst,(local,name,hintlist as obj)) =
in
if k' == k && data' == data then hint else (k',data')
in
- match hintlist with
- | CreateDB _ -> obj
+ let action = match obj.hint_action with
+ | CreateDB _ -> obj.hint_action
| AddTransparency (grs, b) ->
- let grs' = List.smartmap (subst_evaluable_reference subst) grs in
- if grs==grs' then obj else (local, name, AddTransparency (grs', b))
+ let grs' = List.smartmap (subst_evaluable_reference subst) grs in
+ if grs == grs' then obj.hint_action else AddTransparency (grs', b)
| AddHints hintlist ->
- let hintlist' = List.smartmap subst_hint hintlist in
- if hintlist' == hintlist then obj else
- (local,name,AddHints hintlist')
+ let hintlist' = List.smartmap subst_hint hintlist in
+ if hintlist' == hintlist then obj.hint_action else AddHints hintlist'
| RemoveHints grs ->
- let grs' = List.smartmap (subst_global_reference subst) grs in
- if grs==grs' then obj else (local, name, RemoveHints grs')
+ let grs' = List.smartmap (subst_global_reference subst) grs in
+ if grs == grs' then obj.hint_action else RemoveHints grs'
| AddCut path ->
let path' = subst_hints_path subst path in
- if path' == path then obj else (local, name, AddCut path')
+ if path' == path then obj.hint_action else AddCut path'
| AddMode (l,m) ->
let l' = subst_global_reference subst l in
- (local, name, AddMode (l', m))
+ if l' == l then obj.hint_action else AddMode (l', m)
+ in
+ if action == obj.hint_action then obj else { obj with hint_action = action }
-let classify_autohint ((local,name,hintlist) as obj) =
- match hintlist with
+let classify_autohint obj =
+ match obj.hint_action with
| AddHints [] -> Dispose
- | _ -> if local then Dispose else Substitute obj
+ | _ -> if obj.hint_local then Dispose else Substitute obj
let inAutoHint : hint_obj -> obj =
declare_object {(default_object "AUTOHINT") with
@@ -866,14 +900,22 @@ let inAutoHint : hint_obj -> obj =
subst_function = subst_autohint;
classify_function = classify_autohint; }
+let make_hint ?(local = false) name action = {
+ hint_local = local;
+ hint_name = name;
+ hint_action = action;
+}
+
let create_hint_db l n st b =
- Lib.add_anonymous_leaf (inAutoHint (l,n,CreateDB (b, st)))
+ let hint = make_hint ~local:l n (CreateDB (b, st)) in
+ Lib.add_anonymous_leaf (inAutoHint hint)
let remove_hints local dbnames grs =
let dbnames = if List.is_empty dbnames then ["core"] else dbnames in
List.iter
(fun dbname ->
- Lib.add_anonymous_leaf (inAutoHint(local, dbname, RemoveHints grs)))
+ let hint = make_hint ~local dbname (RemoveHints grs) in
+ Lib.add_anonymous_leaf (inAutoHint hint))
dbnames
(**************************************************************************)
@@ -882,37 +924,42 @@ let remove_hints local dbnames grs =
let add_resolves env sigma clist local dbnames =
List.iter
(fun dbname ->
- Lib.add_anonymous_leaf
- (inAutoHint
- (local,dbname, AddHints
- (List.flatten (List.map (fun (pri, poly, hnf, path, gr) ->
- make_resolves env sigma (true,hnf,Flags.is_verbose())
- pri poly ~name:path gr) clist)))))
+ let r =
+ List.flatten (List.map (fun (pri, poly, hnf, path, gr) ->
+ make_resolves env sigma (true,hnf,Flags.is_verbose())
+ pri poly ~name:path gr) clist)
+ in
+ let hint = make_hint ~local dbname (AddHints r) in
+ Lib.add_anonymous_leaf (inAutoHint hint))
dbnames
let add_unfolds l local dbnames =
List.iter
- (fun dbname -> Lib.add_anonymous_leaf
- (inAutoHint (local,dbname, AddHints (List.map make_unfold l))))
+ (fun dbname ->
+ let hint = make_hint ~local dbname (AddHints (List.map make_unfold l)) in
+ Lib.add_anonymous_leaf (inAutoHint hint))
dbnames
let add_cuts l local dbnames =
List.iter
- (fun dbname -> Lib.add_anonymous_leaf
- (inAutoHint (local,dbname, AddCut l)))
+ (fun dbname ->
+ let hint = make_hint ~local dbname (AddCut l) in
+ Lib.add_anonymous_leaf (inAutoHint hint))
dbnames
let add_mode l m local dbnames =
List.iter
- (fun dbname -> Lib.add_anonymous_leaf
- (let m' = make_mode l m in
- (inAutoHint (local,dbname, AddMode (l,m')))))
+ (fun dbname ->
+ let m' = make_mode l m in
+ let hint = make_hint ~local dbname (AddMode (l, m')) in
+ Lib.add_anonymous_leaf (inAutoHint hint))
dbnames
let add_transparency l b local dbnames =
List.iter
- (fun dbname -> Lib.add_anonymous_leaf
- (inAutoHint (local,dbname, AddTransparency (l, b))))
+ (fun dbname ->
+ let hint = make_hint ~local dbname (AddTransparency (l, b)) in
+ Lib.add_anonymous_leaf (inAutoHint hint))
dbnames
let add_extern pri pat tacast local dbname =
@@ -920,7 +967,7 @@ let add_extern pri pat tacast local dbname =
| None -> None
| Some (_, pat) -> Some pat
in
- let hint = local, dbname, AddHints [make_extern pri pat tacast] in
+ let hint = make_hint ~local dbname (AddHints [make_extern pri pat tacast]) in
Lib.add_anonymous_leaf (inAutoHint hint)
let add_externs pri pat tacast local dbnames =
@@ -929,9 +976,9 @@ let add_externs pri pat tacast local dbnames =
let add_trivials env sigma l local dbnames =
List.iter
(fun dbname ->
- Lib.add_anonymous_leaf (
- inAutoHint(local,dbname,
- AddHints (List.map (fun (name, poly, c) -> make_trivial env sigma poly ~name c) l))))
+ let l = List.map (fun (name, poly, c) -> make_trivial env sigma poly ~name c) l in
+ let hint = make_hint ~local dbname (AddHints l) in
+ Lib.add_anonymous_leaf (inAutoHint hint))
dbnames
let (forward_intern_tac, extern_intern_tac) = Hook.make ()