wenzelm@12350: (* Title: Pure/Isar/context_rules.ML wenzelm@12350: Author: Stefan Berghofer and Markus Wenzel, TU Muenchen wenzelm@12350: wenzelm@18728: Declarations of intro/elim/dest rules in Pure (see also wenzelm@18728: Provers/classical.ML for a more specialized version of the same idea). wenzelm@12350: *) wenzelm@12350: wenzelm@12350: signature CONTEXT_RULES = wenzelm@12350: sig wenzelm@33370: type netpair = ((int * int) * (bool * thm)) Net.net * ((int * int) * (bool * thm)) Net.net wenzelm@20289: val netpair_bang: Proof.context -> netpair wenzelm@20289: val netpair: Proof.context -> netpair wenzelm@12350: val orderlist: ((int * int) * 'a) list -> 'a list wenzelm@12399: val find_rules_netpair: bool -> thm list -> term -> netpair -> thm list wenzelm@20289: val find_rules: bool -> thm list -> term -> Proof.context -> thm list list wenzelm@21506: val print_rules: Proof.context -> unit wenzelm@12350: val addSWrapper: ((int -> tactic) -> int -> tactic) -> theory -> theory wenzelm@12350: val addWrapper: ((int -> tactic) -> int -> tactic) -> theory -> theory wenzelm@20289: val Swrap: Proof.context -> (int -> tactic) -> int -> tactic wenzelm@20289: val wrap: Proof.context -> (int -> tactic) -> int -> tactic wenzelm@18728: val intro_bang: int option -> attribute wenzelm@18728: val elim_bang: int option -> attribute wenzelm@18728: val dest_bang: int option -> attribute wenzelm@18728: val intro: int option -> attribute wenzelm@18728: val elim: int option -> attribute wenzelm@18728: val dest: int option -> attribute wenzelm@18728: val intro_query: int option -> attribute wenzelm@18728: val elim_query: int option -> attribute wenzelm@18728: val dest_query: int option -> attribute wenzelm@18728: val rule_del: attribute wenzelm@30529: val add: (int option -> attribute) -> (int option -> attribute) -> (int option -> attribute) -> wenzelm@30529: attribute context_parser wenzelm@12350: end; wenzelm@12350: wenzelm@33369: structure Context_Rules: CONTEXT_RULES = wenzelm@12350: struct wenzelm@12350: wenzelm@12350: wenzelm@12350: (** rule declaration contexts **) wenzelm@12350: wenzelm@12350: (* rule kinds *) wenzelm@12350: wenzelm@12350: val intro_bangK = (0, false); wenzelm@12350: val elim_bangK = (0, true); wenzelm@12350: val introK = (1, false); wenzelm@12350: val elimK = (1, true); wenzelm@12350: val intro_queryK = (2, false); wenzelm@12350: val elim_queryK = (2, true); wenzelm@12350: wenzelm@12350: val kind_names = wenzelm@12350: [(intro_bangK, "safe introduction rules (intro!)"), wenzelm@12350: (elim_bangK, "safe elimination rules (elim!)"), wenzelm@12350: (introK, "introduction rules (intro)"), wenzelm@12350: (elimK, "elimination rules (elim)"), wenzelm@12350: (intro_queryK, "extra introduction rules (intro?)"), wenzelm@12350: (elim_queryK, "extra elimination rules (elim?)")]; wenzelm@12350: wenzelm@12350: val rule_kinds = map #1 kind_names; wenzelm@19046: val rule_indexes = distinct (op =) (map #1 rule_kinds); wenzelm@12350: wenzelm@12350: wenzelm@18637: (* context data *) wenzelm@12350: wenzelm@12350: type netpair = ((int * int) * (bool * thm)) Net.net * ((int * int) * (bool * thm)) Net.net; wenzelm@12350: val empty_netpairs: netpair list = replicate (length rule_indexes) (Net.empty, Net.empty); wenzelm@12350: wenzelm@33370: datatype rules = Rules of wenzelm@12350: {next: int, wenzelm@12350: rules: (int * ((int * bool) * thm)) list, wenzelm@12350: netpairs: netpair list, wenzelm@12350: wrappers: (((int -> tactic) -> int -> tactic) * stamp) list * wenzelm@12350: (((int -> tactic) -> int -> tactic) * stamp) list}; wenzelm@12350: wenzelm@12350: fun make_rules next rules netpairs wrappers = wenzelm@12350: Rules {next = next, rules = rules, netpairs = netpairs, wrappers = wrappers}; wenzelm@12350: wenzelm@12350: fun add_rule (i, b) opt_w th (Rules {next, rules, netpairs, wrappers}) = skalberg@15531: let val w = (case opt_w of SOME w => w | NONE => Tactic.subgoals_of_brl (b, th)) in wenzelm@12350: make_rules (next - 1) ((w, ((i, b), th)) :: rules) wenzelm@23227: (nth_map i (Tactic.insert_tagged_brl ((w, next), (b, th))) netpairs) wrappers wenzelm@12350: end; wenzelm@12350: wenzelm@45375: fun del_rule0 th (rs as Rules {next, rules, netpairs, wrappers}) = wenzelm@12350: let wenzelm@22360: fun eq_th (_, (_, th')) = Thm.eq_thm_prop (th, th'); wenzelm@23227: fun del b netpair = Tactic.delete_tagged_brl (b, th) netpair handle Net.DELETE => netpair; wenzelm@12350: in wenzelm@12350: if not (exists eq_th rules) then rs wenzelm@12350: else make_rules next (filter_out eq_th rules) (map (del false o del true) netpairs) wrappers wenzelm@12350: end; wenzelm@12350: wenzelm@45375: fun del_rule th = del_rule0 th o del_rule0 (Tactic.make_elim th); wenzelm@45375: wenzelm@33519: structure Rules = Generic_Data wenzelm@18637: ( wenzelm@33370: type T = rules; wenzelm@12350: val empty = make_rules ~1 [] empty_netpairs ([], []); wenzelm@16424: val extend = I; wenzelm@33519: fun merge wenzelm@33519: (Rules {rules = rules1, wrappers = (ws1, ws1'), ...}, wenzelm@12350: Rules {rules = rules2, wrappers = (ws2, ws2'), ...}) = wenzelm@12350: let wenzelm@18637: val wrappers = wenzelm@18921: (Library.merge (eq_snd (op =)) (ws1, ws2), Library.merge (eq_snd (op =)) (ws1', ws2')); wenzelm@18921: val rules = Library.merge (fn ((_, (k1, th1)), (_, (k2, th2))) => wenzelm@22360: k1 = k2 andalso Thm.eq_thm_prop (th1, th2)) (rules1, rules2); wenzelm@12350: val next = ~ (length rules); wenzelm@19473: val netpairs = fold (fn (n, (w, ((i, b), th))) => wenzelm@23227: nth_map i (Tactic.insert_tagged_brl ((w, n), (b, th)))) wenzelm@19473: (next upto ~1 ~~ rules) empty_netpairs; wenzelm@23227: in make_rules (next - 1) rules netpairs wrappers end; wenzelm@18637: ); wenzelm@12350: wenzelm@22846: fun print_rules ctxt = wenzelm@22846: let wenzelm@22846: val Rules {rules, ...} = Rules.get (Context.Proof ctxt); wenzelm@22846: fun prt_kind (i, b) = wenzelm@22846: Pretty.big_list ((the o AList.lookup (op =) kind_names) (i, b) ^ ":") wenzelm@22846: (map_filter (fn (_, (k, th)) => wenzelm@51580: if k = (i, b) then SOME (Pretty.item [Display.pretty_thm ctxt th]) else NONE) wenzelm@22846: (sort (int_ord o pairself fst) rules)); wenzelm@22846: in Pretty.writeln (Pretty.chunks (map prt_kind rule_kinds)) end; wenzelm@12350: wenzelm@12350: wenzelm@12350: (* access data *) wenzelm@12350: wenzelm@18637: fun netpairs ctxt = let val Rules {netpairs, ...} = Rules.get (Context.Proof ctxt) in netpairs end; wenzelm@12350: val netpair_bang = hd o netpairs; wenzelm@12350: val netpair = hd o tl o netpairs; wenzelm@12350: wenzelm@12350: wenzelm@12399: (* retrieving rules *) wenzelm@12399: wenzelm@12350: fun untaglist [] = [] wenzelm@32784: | untaglist [(_ : int * int, x)] = [x] wenzelm@32784: | untaglist ((k, x) :: (rest as (k', _) :: _)) = wenzelm@12350: if k = k' then untaglist rest wenzelm@12350: else x :: untaglist rest; wenzelm@12350: wenzelm@16424: fun orderlist brls = wenzelm@16512: untaglist (sort (prod_ord int_ord int_ord o pairself fst) brls); wenzelm@16424: wenzelm@16424: fun orderlist_no_weight brls = wenzelm@16512: untaglist (sort (int_ord o pairself (snd o fst)) brls); wenzelm@12399: wenzelm@12399: fun may_unify weighted t net = wenzelm@12399: map snd ((if weighted then orderlist else orderlist_no_weight) (Net.unify_term net t)); wenzelm@12399: wenzelm@12399: fun find_erules _ [] = K [] wenzelm@12805: | find_erules w (fact :: _) = may_unify w (Logic.strip_assums_concl (Thm.prop_of fact)); wenzelm@16424: wenzelm@12399: fun find_irules w goal = may_unify w (Logic.strip_assums_concl goal); wenzelm@12380: wenzelm@12399: fun find_rules_netpair weighted facts goal (inet, enet) = wenzelm@12399: find_erules weighted facts enet @ find_irules weighted goal inet; wenzelm@12380: wenzelm@16424: fun find_rules weighted facts goals = wenzelm@16424: map (find_rules_netpair weighted facts goals) o netpairs; wenzelm@12350: wenzelm@12350: wenzelm@12399: (* wrappers *) wenzelm@12399: wenzelm@18667: fun gen_add_wrapper upd w = wenzelm@32784: Context.theory_map (Rules.map (fn Rules {next, rules, netpairs, wrappers} => wenzelm@18667: make_rules next rules netpairs (upd (fn ws => (w, stamp ()) :: ws) wrappers))); wenzelm@12350: wenzelm@12350: val addSWrapper = gen_add_wrapper Library.apfst; wenzelm@12350: val addWrapper = gen_add_wrapper Library.apsnd; wenzelm@12350: wenzelm@12350: wenzelm@12350: fun gen_wrap which ctxt = wenzelm@18637: let val Rules {wrappers, ...} = Rules.get (Context.Proof ctxt) wenzelm@17351: in fold_rev fst (which wrappers) end; wenzelm@12350: wenzelm@12350: val Swrap = gen_wrap #1; wenzelm@12350: val wrap = gen_wrap #2; wenzelm@12350: wenzelm@12350: wenzelm@12350: wenzelm@12350: (** attributes **) wenzelm@12350: wenzelm@12350: (* add and del rules *) wenzelm@12350: wenzelm@45375: wenzelm@45375: val rule_del = Thm.declaration_attribute (fn th => Rules.map (del_rule th)); wenzelm@12350: wenzelm@18637: fun rule_add k view opt_w = wenzelm@45375: Thm.declaration_attribute (fn th => Rules.map (add_rule k opt_w (view th) o del_rule th)); wenzelm@12350: wenzelm@18637: val intro_bang = rule_add intro_bangK I; wenzelm@18637: val elim_bang = rule_add elim_bangK I; wenzelm@18637: val dest_bang = rule_add elim_bangK Tactic.make_elim; wenzelm@18637: val intro = rule_add introK I; wenzelm@18637: val elim = rule_add elimK I; wenzelm@18637: val dest = rule_add elimK Tactic.make_elim; wenzelm@18637: val intro_query = rule_add intro_queryK I; wenzelm@18637: val elim_query = rule_add elim_queryK I; wenzelm@18637: val dest_query = rule_add elim_queryK Tactic.make_elim; wenzelm@12350: wenzelm@26463: val _ = Context.>> (Context.map_theory wenzelm@39557: (snd o Global_Theory.add_thms [((Binding.empty, Drule.equal_intr_rule), [intro_query NONE])])); wenzelm@18637: wenzelm@12350: wenzelm@18637: (* concrete syntax *) wenzelm@18637: wenzelm@30529: fun add a b c x = wenzelm@27809: (Scan.lift ((Args.bang >> K a || Args.query >> K c || Scan.succeed b) -- wenzelm@36950: Scan.option Parse.nat) >> (fn (f, n) => f n)) x; wenzelm@18637: wenzelm@30529: val _ = Context.>> (Context.map_theory wenzelm@30529: (Attrib.setup (Binding.name "intro") (add intro_bang intro intro_query) wenzelm@30529: "declaration of introduction rule" #> wenzelm@30529: Attrib.setup (Binding.name "elim") (add elim_bang elim elim_query) wenzelm@30529: "declaration of elimination rule" #> wenzelm@30529: Attrib.setup (Binding.name "dest") (add dest_bang dest dest_query) wenzelm@30529: "declaration of destruction rule" #> wenzelm@30529: Attrib.setup (Binding.name "rule") (Scan.lift Args.del >> K rule_del) wenzelm@30529: "remove declaration of intro/elim/dest rule")); wenzelm@12350: wenzelm@12350: end;