diff options
author | 2011-10-18 15:01:00 +0000 | |
---|---|---|
committer | 2011-10-18 15:01:00 +0000 | |
commit | 391bbdcd874bc358bb052fbe94d40304ebcfb5b5 (patch) | |
tree | 2725bd8e4e87e8d6ab57dc3cf7754f4679945e98 | |
parent | 8fb5eeef9efe3873b10c4f14ba06a1883bc38aac (diff) |
Fix bug #2227
git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/coq/trunk@14572 85f007b7-540e-0410-9357-904b9bb8a0f7
-rw-r--r-- | plugins/firstorder/sequent.ml | 4 | ||||
-rw-r--r-- | tactics/auto.ml | 112 | ||||
-rw-r--r-- | tactics/auto.mli | 4 |
3 files changed, 64 insertions, 56 deletions
diff --git a/plugins/firstorder/sequent.ml b/plugins/firstorder/sequent.ml index cf8b86b23..571ec4ef3 100644 --- a/plugins/firstorder/sequent.ml +++ b/plugins/firstorder/sequent.ml @@ -210,7 +210,7 @@ open Auto let extend_with_auto_hints l seq gl= let seqref=ref seq in - let f p_a_t = + let f (_, p_a_t) = match p_a_t.code with Res_pf (c,_) | Give_exact c | Res_pf_THEN_trivial_fail (c,_) -> @@ -220,7 +220,7 @@ let extend_with_auto_hints l seq gl= seqref:=add_formula Hint gr typ !seqref gl with Not_found->()) | _-> () in - let g _ l=List.iter f l in + let g _ l = List.iter f l in let h dbname= let hdb= try diff --git a/tactics/auto.ml b/tactics/auto.ml index 2c0e49b64..0386c5de4 100644 --- a/tactics/auto.ml +++ b/tactics/auto.ml @@ -55,7 +55,7 @@ type auto_tactic = | Extern of glob_tactic_expr (* Hint Extern *) type pri_auto_tactic = { - pri : int; (* A number between 0 and 4, 4 = lower priority *) + pri : int; (* A number lower is higher priority *) pat : constr_pattern option; (* A pattern for the concl of the Goal *) name : global_reference option; (* A potential name to refer to the hint *) code : auto_tactic (* the tactic to apply when the concl matches pat *) @@ -63,7 +63,12 @@ type pri_auto_tactic = { type hint_entry = global_reference option * pri_auto_tactic -let pri_order {pri=pri1} {pri=pri2} = pri1 <= pri2 +let pri_order_int (id1, {pri=pri1}) (id2, {pri=pri2}) = + let d = pri1 - pri2 in + if d == 0 then id2 - id1 + else d + +let pri_order t1 t2 = pri_order_int t1 t2 <= 0 let insert v l = let rec insrec = function @@ -87,7 +92,8 @@ let insert v l = - un discrimination net borné (Btermdn.t) constitué de tous les patterns de la seconde liste de tactiques *) -type stored_data = pri_auto_tactic +type stored_data = int * pri_auto_tactic + (* First component is the index of insertion in the table, to keep most recent first semantics. *) let auto_tactic_ord code1 code2 = match code1, code2 with @@ -101,25 +107,16 @@ let auto_tactic_ord code1 code2 = | Extern t1, Extern t2 -> Pervasives.compare t1 t2 | _ -> Pervasives.compare code1 code2 -let pri_auto_tactic_ord - {pri=pri1; pat=pat1; name=name1; code=code1} - {pri=pri2; pat=pat2; name=name2; code=code2} = - let r = pri1 - pri2 in - if r <> 0 then r else - let r = Pervasives.compare pat1 pat2 in (* there should be an equality on constr_pattern *) - if r <> 0 then r else - auto_tactic_ord code1 code2 - module Bounded_net = Btermdn.Make(struct type t = stored_data - let compare = pri_auto_tactic_ord + let compare = pri_order_int end) type search_entry = stored_data list * stored_data list * Bounded_net.t let empty_se = ([],[],Bounded_net.create ()) -let eq_pri_auto_tactic x y = +let eq_pri_auto_tactic (_, x) (_, y) = if x.pri = y.pri && x.pat = y.pat then match x.code,y.code with | Res_pf(cstr,_),Res_pf(cstr1,_) -> @@ -140,13 +137,14 @@ let add_tac pat t st (l,l',dn) = | None -> if not (List.exists (eq_pri_auto_tactic t) l) then (insert t l, l', dn) else (l, l', dn) | Some pat -> if not (List.exists (eq_pri_auto_tactic t) l') then (l, insert t l', Bounded_net.add st dn (pat,t)) else (l, l', dn) -let rebuild_dn st (l,l',dn) = - (l, l', List.fold_left (fun dn t -> Bounded_net.add (Some st) dn (Option.get t.pat, t)) +let rebuild_dn st ((l,l',dn) : search_entry) = + (l, l', List.fold_left (fun dn (id, t) -> Bounded_net.add (Some st) dn (Option.get t.pat, (id, t))) (Bounded_net.create ()) l') + let lookup_tacs (hdc,c) st (l,l',dn) = let l' = List.map snd (Bounded_net.lookup st dn c) in - let sl' = Sort.list pri_order l' in + let sl' = List.stable_sort pri_order_int l' in Sort.merge pri_order l sl' module Constr_map = Map.Make(RefOrdered) @@ -161,6 +159,7 @@ module Hint_db = struct type t = { hintdb_state : Names.transparent_state; hintdb_unfolds : Idset.t * Cset.t; + mutable hintdb_max_id : int; use_dn : bool; hintdb_map : search_entry Constr_map.t; (* A list of unindexed entries starting with an unfoldable constant @@ -168,8 +167,12 @@ 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 empty st use_dn = { hintdb_state = st; hintdb_unfolds = (Idset.empty, Cset.empty); + hintdb_max_id = 0; use_dn = use_dn; hintdb_map = Constr_map.empty; hintdb_nopat = [] } @@ -179,16 +182,16 @@ module Hint_db = struct with Not_found -> empty_se let map_none db = - Sort.merge pri_order (List.map snd db.hintdb_nopat) [] - + List.map snd (Sort.merge pri_order (List.map snd db.hintdb_nopat) []) + let map_all k db = let (l,l',_) = find k db in - Sort.merge pri_order (List.map snd db.hintdb_nopat @ l) l' + List.map snd (Sort.merge pri_order (List.map snd db.hintdb_nopat @ l) l') let map_auto (k,c) db = let st = if db.use_dn then Some db.hintdb_state else None in let l' = lookup_tacs (k,c) st (find k db) in - Sort.merge pri_order (List.map snd db.hintdb_nopat) l' + List.map snd (Sort.merge pri_order (List.map snd db.hintdb_nopat) l') let is_exact = function | Give_exact _ -> true @@ -198,7 +201,8 @@ module Hint_db = struct | Unfold_nth _ -> true | _ -> false - let addkv gr v db = + let addkv gr id v db = + let idv = id, v in let k = match gr with | Some gr -> if db.use_dn && is_transparent_gr db.hintdb_state gr && is_unfold v.code then None else Some gr @@ -208,19 +212,19 @@ module Hint_db = struct let pat = if not db.use_dn && is_exact v.code then None else v.pat in match k with | None -> - if not (List.exists (fun (_, v') -> v = v') db.hintdb_nopat) then - { db with hintdb_nopat = (gr,v) :: db.hintdb_nopat } + if not (List.exists (fun (_, (_, v')) -> v = v') db.hintdb_nopat) then + { db with hintdb_nopat = (gr,idv) :: db.hintdb_nopat } else db | Some gr -> let oval = find gr db in - { db with hintdb_map = Constr_map.add gr (add_tac pat v dnst oval) db.hintdb_map } + { db with hintdb_map = Constr_map.add gr (add_tac pat idv dnst oval) db.hintdb_map } let rebuild_db st' db = let db' = { db with hintdb_map = Constr_map.map (rebuild_dn st') db.hintdb_map; hintdb_state = st'; hintdb_nopat = [] } in - List.fold_left (fun db (gr,v) -> addkv gr v db) db' db.hintdb_nopat + List.fold_left (fun db (gr,(id,v)) -> addkv gr id v db) db' db.hintdb_nopat let add_one (k,v) db = let st',db,rebuild = @@ -236,7 +240,7 @@ module Hint_db = struct | _ -> db.hintdb_state, db, false in let db = if db.use_dn && rebuild then rebuild_db st' db else db - in addkv k v db + in addkv k (next_hint_id db) v db let add_list l db = List.fold_right add_one l db @@ -247,7 +251,7 @@ module Hint_db = struct else rebuild_dn st (sl1', sl2', dn) let remove_list grs db = - let filter h = match h.name with None -> true | Some gr -> not (List.mem gr grs) in + let filter (_, h) = match h.name with None -> true | Some gr -> not (List.mem gr grs) in let hintmap = Constr_map.map (remove_he db.hintdb_state filter) db.hintdb_map in let hintnopat = list_smartfilter (fun (ge, sd) -> filter sd) db.hintdb_nopat in { db with hintdb_map = hintmap; hintdb_nopat = hintnopat } @@ -365,10 +369,10 @@ let make_apply_entry env sigma (eapply,hnf,verbose) pri ?name (c,cty) = warn (str "the hint: eapply " ++ pr_lconstr c ++ str " will only be used by eauto"); (Some hd, - { pri = (match pri with None -> nb_hyp cty + nmiss | Some p -> p); - pat = Some pat; - name = name; - code = ERes_pf(c,{ce with env=empty_env}) }) + { pri = (match pri with None -> nb_hyp cty + nmiss | Some p -> p); + pat = Some pat; + name = name; + code = ERes_pf(c,{ce with env=empty_env}) }) end | _ -> failwith "make_apply_entry" @@ -421,10 +425,10 @@ let make_trivial env sigma ?name c = let hd = head_of_constr_reference (fst (head_constr t)) in let ce = mk_clenv_from dummy_goal (c,t) in (Some hd, { pri=1; - pat = Some (snd (Pattern.pattern_of_constr sigma (clenv_type ce))); - name = name; - code=Res_pf_THEN_trivial_fail(c,{ce with env=empty_env}) }) - + pat = Some (snd (Pattern.pattern_of_constr sigma (clenv_type ce))); + name = name; + code=Res_pf_THEN_trivial_fail(c,{ce with env=empty_env}) }) + open Vernacexpr (**************************************************************************) @@ -746,8 +750,8 @@ let pr_autotactic = | Extern tac -> (str "(external) " ++ Pptactic.pr_glob_tactic (Global.env()) tac) -let pr_hint v = - (pr_autotactic v.code ++ str"(" ++ int v.pri ++ str")" ++ spc ()) +let pr_hint (id, v) = + (pr_autotactic v.code ++ str"(level " ++ int v.pri ++ str", id " ++ int id ++ str ")" ++ spc ()) let pr_hint_list hintlist = (str " " ++ hov 0 (prlist pr_hint hintlist) ++ fnl ()) @@ -762,7 +766,7 @@ let pr_hint_list_for_head c = let dbs = Hintdbmap.to_list !searchtable in let valid_dbs = map_succeed - (fun (name,db) -> (name,db,Hint_db.map_all c db)) + (fun (name,db) -> (name,db, List.map (fun v -> 0, v) (Hint_db.map_all c db))) dbs in if valid_dbs = [] then @@ -789,6 +793,7 @@ let pr_hint_term cl = else Hint_db.map_auto (hd, applist (hdc,args)) with Bound -> Hint_db.map_none in + let fn db = List.map (fun x -> 0, x) (fn db) in map_succeed (fun (name, db) -> (name, db, fn db)) dbs in if valid_dbs = [] then @@ -857,7 +862,7 @@ let print_searchtable () = (* tactics with a trace mechanism for automatic search *) (**************************************************************************) -let priority l = List.filter (fun (_,hint) -> hint.pri = 0) l +let priority l = List.filter (fun (_, hint) -> hint.pri = 0) l (* tell auto not to reuse already instantiated metas in unification (for compatibility, since otherwise, apply succeeds oftener) *) @@ -986,7 +991,7 @@ let rec trivial_fail_db mod_delta db_list local_db gl = in tclFIRST (assumption::intro_tac:: - (List.map tclCOMPLETE + (List.map (fun tac -> tclCOMPLETE tac) (trivial_resolve mod_delta db_list local_db (pf_concl gl)))) gl and my_find_search_nodelta db_list local_db hdc concl = @@ -1028,20 +1033,23 @@ and my_find_search_delta db_list local_db hdc concl = in List.map (fun x -> (Some flags,x)) l) (local_db::db_list) -and tac_of_hint db_list local_db concl (flags, {pat=p; code=t}) = - match t with - | Res_pf (c,cl) -> unify_resolve_gen flags (c,cl) - | ERes_pf _ -> (fun gl -> error "eres_pf") - | Give_exact c -> exact_check c - | Res_pf_THEN_trivial_fail (c,cl) -> +and tac_of_hint db_list local_db concl (flags, ({pat=p; code=t})) = + let tactic = + match t with + | Res_pf (c,cl) -> unify_resolve_gen flags (c,cl) + | ERes_pf _ -> (fun gl -> error "eres_pf") + | Give_exact c -> exact_check c + | Res_pf_THEN_trivial_fail (c,cl) -> tclTHEN (unify_resolve_gen flags (c,cl)) (trivial_fail_db (flags <> None) db_list local_db) - | Unfold_nth c -> (fun gl -> - if exists_evaluable_reference (pf_env gl) c then - tclPROGRESS (h_reduce (Unfold [all_occurrences_expr,c]) onConcl) gl - else tclFAIL 0 (str"Unbound reference") gl) - | Extern tacast -> conclPattern concl p tacast + | Unfold_nth c -> + (fun gl -> + if exists_evaluable_reference (pf_env gl) c then + tclPROGRESS (h_reduce (Unfold [all_occurrences_expr,c]) onConcl) gl + else tclFAIL 0 (str"Unbound reference") gl) + | Extern tacast -> conclPattern concl p tacast + in tactic and trivial_resolve mod_delta db_list local_db cl = try diff --git a/tactics/auto.mli b/tactics/auto.mli index 32eaeef27..8556b453f 100644 --- a/tactics/auto.mli +++ b/tactics/auto.mli @@ -39,7 +39,7 @@ type pri_auto_tactic = { code : auto_tactic; (** the tactic to apply when the concl matches pat *) } -type stored_data = pri_auto_tactic +type stored_data = int * pri_auto_tactic type search_entry @@ -52,7 +52,7 @@ module Hint_db : type t val empty : transparent_state -> bool -> t val find : global_reference -> t -> search_entry - val map_none : t -> pri_auto_tactic list + val map_none : t ->pri_auto_tactic list val map_all : global_reference -> t -> pri_auto_tactic list val map_auto : global_reference * constr -> t -> pri_auto_tactic list val add_one : hint_entry -> t -> t |