(************************************************************************) (* v * The Coq Proof Assistant / The Coq Development Team *) (* str (if d then "rewrite -> " else "rewrite <- ") ++ Printer.prterm c ++ str " of type " ++ Printer.prterm typ ++ str " then use tactic " ++ Pptactic.pr_glob_tactic t) hints) with Not_found -> errorlabstrm "AutoRewrite" (str ("Rewriting base "^(bas)^" does not exist")) type raw_rew_rule = constr * bool * raw_tactic_expr (* Applies all the rules of one base *) let one_base tac_main bas = let lrul = try Stringmap.find bas !rewtab with Not_found -> errorlabstrm "AutoRewrite" (str ("Rewriting base "^(bas)^" does not exist")) in let lrul = List.map (fun (c,_,b,t) -> (c,b,Tacinterp.eval_tactic t)) lrul in tclREPEAT_MAIN (tclPROGRESS (List.fold_left (fun tac (csr,dir,tc) -> tclTHEN tac (tclREPEAT_MAIN (tclTHENSFIRSTn (general_rewrite dir csr) [|tac_main|] tc))) tclIDTAC lrul)) (* The AutoRewrite tactic *) let autorewrite tac_main lbas = tclREPEAT_MAIN (tclPROGRESS (List.fold_left (fun tac bas -> tclTHEN tac (one_base tac_main bas)) tclIDTAC lbas)) (* Functions necessary to the library object declaration *) let cache_hintrewrite (_,(rbase,lrl)) = let l = try let oldl = Stringmap.find rbase !rewtab in let lrl = List.map (fun (c,dummy,b,t) -> (* here we substitute the dummy value with the right one *) c,Typing.type_of (Global.env ()) Evd.empty c,b,t) lrl in (List.filter (fun (_,typ,_,_) -> not (List.exists (fun (_,typ',_,_) -> Term.eq_constr typ typ') oldl) ) lrl) @ oldl with | Not_found -> lrl in rewtab:=Stringmap.add rbase l !rewtab let export_hintrewrite x = Some x let subst_hintrewrite (_,subst,(rbase,list as node)) = let subst_first (cst,typ,b,t as pair) = let cst' = subst_mps subst cst in let typ' = (* here we do not have the environment and Global.env () is not the one where cst' lives in. Thus we can just put a dummy value and override it in cache_hintrewrite *) typ (* dummy value, it will be recomputed by cache_hintrewrite *) in let t' = Tacinterp.subst_tactic subst t in if cst == cst' && t == t' then pair else (cst',typ',b,t) in let list' = list_smartmap subst_first list in if list' == list then node else (rbase,list') let classify_hintrewrite (_,x) = Libobject.Substitute x (* Declaration of the Hint Rewrite library object *) let (in_hintrewrite,out_hintrewrite)= Libobject.declare_object {(Libobject.default_object "HINT_REWRITE") with Libobject.open_function = (fun i o -> if i=1 then cache_hintrewrite o); Libobject.cache_function = cache_hintrewrite; Libobject.subst_function = subst_hintrewrite; Libobject.classify_function = classify_hintrewrite; Libobject.export_function = export_hintrewrite } (* To add rewriting rules to a base *) let add_rew_rules base lrul = let lrul = List.rev_map (fun (c,b,t) -> (c,mkProp (* dummy value *), b,Tacinterp.glob_tactic t) ) lrul in Lib.add_anonymous_leaf (in_hintrewrite (base,lrul))