wenzelm@5824: (* Title: Pure/Isar/method.ML wenzelm@5824: ID: $Id$ wenzelm@5824: Author: Markus Wenzel, TU Muenchen wenzelm@8807: License: GPL (GNU GENERAL PUBLIC LICENSE) wenzelm@5824: wenzelm@5824: Proof methods. wenzelm@5824: *) wenzelm@5824: wenzelm@5824: signature BASIC_METHOD = wenzelm@5824: sig wenzelm@5824: val print_methods: theory -> unit wenzelm@5824: val Method: bstring -> (Args.src -> Proof.context -> Proof.method) -> string -> unit wenzelm@5824: end; wenzelm@5824: wenzelm@5824: signature METHOD = wenzelm@5824: sig wenzelm@5824: include BASIC_METHOD wenzelm@8153: val print_global_rules: theory -> unit wenzelm@8153: val print_local_rules: Proof.context -> unit wenzelm@8153: val dest_global: theory attribute wenzelm@8153: val elim_global: theory attribute wenzelm@8153: val intro_global: theory attribute wenzelm@9938: val rule_del_global: theory attribute wenzelm@8153: val dest_local: Proof.context attribute wenzelm@8153: val elim_local: Proof.context attribute wenzelm@8153: val intro_local: Proof.context attribute wenzelm@9938: val rule_del_local: Proof.context attribute wenzelm@6091: val METHOD: (thm list -> tactic) -> Proof.method wenzelm@8372: val METHOD_CASES: wenzelm@8372: (thm list -> thm -> (thm * (string * RuleCases.T) list) Seq.seq) -> Proof.method wenzelm@9706: val SIMPLE_METHOD: tactic -> Proof.method wenzelm@9706: val SIMPLE_METHOD': ((int -> tactic) -> tactic) -> (int -> tactic) -> Proof.method wenzelm@5824: val fail: Proof.method wenzelm@5824: val succeed: Proof.method wenzelm@8167: val defer: int option -> Proof.method wenzelm@8167: val prefer: int -> Proof.method wenzelm@7419: val insert_tac: thm list -> int -> tactic wenzelm@7574: val insert: thm list -> Proof.method wenzelm@7555: val insert_facts: Proof.method wenzelm@7601: val unfold: thm list -> Proof.method wenzelm@7419: val fold: thm list -> Proof.method wenzelm@9484: val atomize_tac: thm list -> int -> tactic wenzelm@9485: val atomize_goal: thm list -> int -> thm -> thm wenzelm@7419: val multi_resolve: thm list -> thm -> thm Seq.seq wenzelm@7419: val multi_resolves: thm list -> thm list -> thm Seq.seq wenzelm@8335: val resolveq_tac: thm Seq.seq -> int -> tactic wenzelm@9294: val resolveq_cases_tac: bool -> (thm * string list) Seq.seq wenzelm@8372: -> int -> thm -> (thm * (string * RuleCases.T) list) Seq.seq wenzelm@6091: val rule_tac: thm list -> thm list -> int -> tactic wenzelm@9587: val erule_tac: thm list -> thm list -> int -> tactic wenzelm@6091: val rule: thm list -> Proof.method wenzelm@7130: val erule: thm list -> Proof.method wenzelm@8220: val drule: thm list -> Proof.method wenzelm@8220: val frule: thm list -> Proof.method wenzelm@8195: val this: Proof.method wenzelm@7555: val assumption: Proof.context -> Proof.method wenzelm@8351: val set_tactic: (Proof.context -> thm list -> tactic) -> unit wenzelm@8351: val tactic: string -> Proof.context -> Proof.method wenzelm@5916: exception METHOD_FAIL of (string * Position.T) * exn wenzelm@5824: val method: theory -> Args.src -> Proof.context -> Proof.method wenzelm@9539: val add_method: bstring * (Args.src -> Proof.context -> Proof.method) * string wenzelm@9539: -> theory -> theory wenzelm@5824: val add_methods: (bstring * (Args.src -> Proof.context -> Proof.method) * string) list wenzelm@5824: -> theory -> theory wenzelm@5884: val syntax: (Proof.context * Args.T list -> 'a * (Proof.context * Args.T list)) -> wenzelm@8282: Args.src -> Proof.context -> Proof.context * 'a wenzelm@8351: val simple_args: (Args.T list -> 'a * Args.T list) wenzelm@8351: -> ('a -> Proof.context -> Proof.method) -> Args.src -> Proof.context -> Proof.method wenzelm@7555: val ctxt_args: (Proof.context -> Proof.method) -> Args.src -> Proof.context -> Proof.method wenzelm@5884: val no_args: Proof.method -> Args.src -> Proof.context -> Proof.method wenzelm@7268: type modifier wenzelm@7601: val sectioned_args: (Proof.context * Args.T list -> 'a * (Proof.context * Args.T list)) -> wenzelm@7268: (Args.T list -> modifier * Args.T list) list -> wenzelm@9864: ('a -> Proof.context -> 'b) -> Args.src -> Proof.context -> 'b wenzelm@7601: val bang_sectioned_args: wenzelm@7601: (Args.T list -> modifier * Args.T list) list -> wenzelm@9864: (thm list -> Proof.context -> 'a) -> Args.src -> Proof.context -> 'a wenzelm@9777: val bang_sectioned_args': wenzelm@9777: (Args.T list -> modifier * Args.T list) list -> wenzelm@9777: (Proof.context * Args.T list -> 'a * (Proof.context * Args.T list)) -> wenzelm@9864: ('a -> thm list -> Proof.context -> 'b) -> Args.src -> Proof.context -> 'b wenzelm@7601: val only_sectioned_args: wenzelm@7601: (Args.T list -> modifier * Args.T list) list -> wenzelm@9864: (Proof.context -> 'a) -> Args.src -> Proof.context -> 'a wenzelm@9864: val thms_ctxt_args: (thm list -> Proof.context -> 'a) -> Args.src -> Proof.context -> 'a wenzelm@9864: val thms_args: (thm list -> 'a) -> Args.src -> Proof.context -> 'a wenzelm@9864: val thm_args: (thm -> 'a) -> Args.src -> Proof.context -> 'a wenzelm@5824: datatype text = wenzelm@5824: Basic of (Proof.context -> Proof.method) | wenzelm@5824: Source of Args.src | wenzelm@5824: Then of text list | wenzelm@5824: Orelse of text list | wenzelm@5824: Try of text | wenzelm@5824: Repeat1 of text wenzelm@5824: val refine: text -> Proof.state -> Proof.state Seq.seq wenzelm@8238: val refine_end: text -> Proof.state -> Proof.state Seq.seq wenzelm@5824: val proof: text option -> Proof.state -> Proof.state Seq.seq wenzelm@8966: val local_qed: bool -> text option wenzelm@6981: -> ({kind: string, name: string, thm: thm} -> unit) * (thm -> unit) wenzelm@6736: -> Proof.state -> Proof.state Seq.seq wenzelm@6981: val local_terminal_proof: text * text option wenzelm@6981: -> ({kind: string, name: string, thm: thm} -> unit) * (thm -> unit) wenzelm@6736: -> Proof.state -> Proof.state Seq.seq wenzelm@6981: val local_default_proof: ({kind: string, name: string, thm: thm} -> unit) * (thm -> unit) wenzelm@6736: -> Proof.state -> Proof.state Seq.seq wenzelm@8966: val local_immediate_proof: ({kind: string, name: string, thm: thm} -> unit) * (thm -> unit) wenzelm@8966: -> Proof.state -> Proof.state Seq.seq wenzelm@8966: val local_done_proof: ({kind: string, name: string, thm: thm} -> unit) * (thm -> unit) wenzelm@8966: -> Proof.state -> Proof.state Seq.seq wenzelm@8966: val global_qed: bool -> text option wenzelm@8966: -> Proof.state -> theory * {kind: string, name: string, thm: thm} wenzelm@6934: val global_terminal_proof: text * text option wenzelm@6934: -> Proof.state -> theory * {kind: string, name: string, thm: thm} wenzelm@8966: val global_default_proof: Proof.state -> theory * {kind: string, name: string, thm: thm} wenzelm@6532: val global_immediate_proof: Proof.state -> theory * {kind: string, name: string, thm: thm} wenzelm@8966: val global_done_proof: Proof.state -> theory * {kind: string, name: string, thm: thm} wenzelm@9539: val goal_args: (Args.T list -> 'a * Args.T list) -> ('a -> int -> tactic) wenzelm@9539: -> Args.src -> Proof.context -> Proof.method wenzelm@9539: val goal_args': (Proof.context * Args.T list -> 'a * (Proof.context * Args.T list)) wenzelm@9539: -> ('a -> int -> tactic) -> Args.src -> Proof.context -> Proof.method wenzelm@5824: val setup: (theory -> theory) list wenzelm@5824: end; wenzelm@5824: wenzelm@5824: structure Method: METHOD = wenzelm@5824: struct wenzelm@5824: wenzelm@5824: wenzelm@8153: (** global and local rule data **) wenzelm@8153: wenzelm@10008: local wenzelm@10008: fun prt_rules kind sg ths = wenzelm@10008: Pretty.writeln (Pretty.big_list ("standard " ^ kind ^ " rules:") wenzelm@10008: (map (Display.pretty_thm_sg sg) ths)); wenzelm@10008: in wenzelm@10008: fun print_rules sg (intro, elim) = wenzelm@10008: (prt_rules "introduction" sg intro; prt_rules "elimination" sg elim); wenzelm@10008: end; wenzelm@8153: wenzelm@8153: wenzelm@8153: (* theory data kind 'Isar/rules' *) wenzelm@8153: wenzelm@8153: structure GlobalRulesArgs = wenzelm@8153: struct wenzelm@8153: val name = "Isar/rules"; wenzelm@8153: type T = thm list * thm list; wenzelm@8153: wenzelm@8153: val empty = ([], []); wenzelm@8153: val copy = I; wenzelm@8153: val prep_ext = I; wenzelm@8153: fun merge ((intro1, elim1), (intro2, elim2)) = wenzelm@9418: (Drule.merge_rules (intro1, intro2), Drule.merge_rules (elim1, elim2)); wenzelm@10008: val print = print_rules; wenzelm@8153: end; wenzelm@8153: wenzelm@8153: structure GlobalRules = TheoryDataFun(GlobalRulesArgs); wenzelm@8153: val print_global_rules = GlobalRules.print; wenzelm@8153: wenzelm@8153: wenzelm@8153: (* proof data kind 'Isar/rules' *) wenzelm@8153: wenzelm@8153: structure LocalRulesArgs = wenzelm@8153: struct wenzelm@8153: val name = "Isar/rules"; wenzelm@8153: type T = thm list * thm list; wenzelm@8153: wenzelm@8153: val init = GlobalRules.get; wenzelm@10008: val print = print_rules o ProofContext.sign_of; wenzelm@8153: end; wenzelm@8153: wenzelm@8153: structure LocalRules = ProofDataFun(LocalRulesArgs); wenzelm@8153: val print_local_rules = LocalRules.print; wenzelm@8153: wenzelm@8153: wenzelm@8153: wenzelm@8153: (** attributes **) wenzelm@8153: wenzelm@8153: (* add rules *) wenzelm@8153: wenzelm@8153: local wenzelm@8153: wenzelm@9938: fun add_dest th (intro, elim) = (intro, Drule.add_rules [Tactic.make_elim th] elim); wenzelm@9938: fun add_elim th (intro, elim) = (intro, Drule.add_rules [th] elim); wenzelm@9938: fun add_intro th (intro, elim) = (Drule.add_rules [th] intro, elim); wenzelm@8153: wenzelm@9938: fun del_rule th (intro, elim) = wenzelm@9938: let wenzelm@9938: val th' = Tactic.make_elim th; wenzelm@9938: val del = Drule.del_rules [th'] o Drule.del_rules [th]; wenzelm@9938: in (del intro, del elim) end; wenzelm@8153: wenzelm@9938: fun mk_att f g (x, th) = (f (g th) x, th); wenzelm@8153: wenzelm@8153: in wenzelm@8153: wenzelm@8153: val dest_global = mk_att GlobalRules.map add_dest; wenzelm@8153: val elim_global = mk_att GlobalRules.map add_elim; wenzelm@8153: val intro_global = mk_att GlobalRules.map add_intro; wenzelm@9938: val rule_del_global = mk_att GlobalRules.map del_rule; wenzelm@8153: wenzelm@8153: val dest_local = mk_att LocalRules.map add_dest; wenzelm@8153: val elim_local = mk_att LocalRules.map add_elim; wenzelm@8153: val intro_local = mk_att LocalRules.map add_intro; wenzelm@9938: val rule_del_local = mk_att LocalRules.map del_rule; wenzelm@9938: wenzelm@9952: fun del_args att = Attrib.syntax (Scan.lift (Args.$$$ Args.delN) >> K att); wenzelm@8153: wenzelm@8153: end; wenzelm@8153: wenzelm@8153: wenzelm@8153: (* concrete syntax *) wenzelm@8153: wenzelm@8153: val rule_atts = wenzelm@9900: [("dest", (Attrib.no_args dest_global, Attrib.no_args dest_local), wenzelm@9900: "declaration of destruction rule"), wenzelm@9900: ("elim", (Attrib.no_args elim_global, Attrib.no_args elim_local), wenzelm@9900: "declaration of elimination rule"), wenzelm@9900: ("intro", (Attrib.no_args intro_global, Attrib.no_args intro_local), wenzelm@9900: "declaration of introduction rule"), wenzelm@9938: ("rule", (del_args rule_del_global, del_args rule_del_local), wenzelm@9900: "remove declaration of elim/intro rule")]; wenzelm@8153: wenzelm@8153: wenzelm@8153: wenzelm@5824: (** proof methods **) wenzelm@5824: wenzelm@8372: (* make methods *) wenzelm@5824: wenzelm@6849: val METHOD = Proof.method; wenzelm@8372: val METHOD_CASES = Proof.method_cases; wenzelm@8372: wenzelm@5824: wenzelm@5824: (* primitive *) wenzelm@5824: wenzelm@5824: val fail = METHOD (K no_tac); wenzelm@5824: val succeed = METHOD (K all_tac); wenzelm@5824: wenzelm@5824: wenzelm@8167: (* shuffle *) wenzelm@8167: wenzelm@8240: fun prefer i = METHOD (K (Tactic.defer_tac i THEN PRIMITIVE (Thm.permute_prems 0 ~1))); wenzelm@8167: fun defer opt_i = METHOD (K (Tactic.defer_tac (if_none opt_i 1))); wenzelm@8167: wenzelm@8167: wenzelm@7419: (* insert *) wenzelm@7419: wenzelm@7419: local wenzelm@5824: wenzelm@6981: fun cut_rule_tac raw_rule = wenzelm@6981: let wenzelm@6981: val rule = Drule.forall_intr_vars raw_rule; wenzelm@6981: val revcut_rl = Drule.incr_indexes_wrt [] [] [] [rule] Drule.revcut_rl; wenzelm@7555: in Tactic.rtac (rule COMP revcut_rl) end; wenzelm@6981: wenzelm@7419: in wenzelm@5824: wenzelm@7419: fun insert_tac [] i = all_tac wenzelm@7419: | insert_tac facts i = EVERY (map (fn th => cut_rule_tac th i) facts); wenzelm@6981: wenzelm@7555: val insert_facts = METHOD (ALLGOALS o insert_tac); wenzelm@7664: fun insert thms = METHOD (fn _ => ALLGOALS (insert_tac thms)); wenzelm@7419: wenzelm@7419: end; wenzelm@5824: wenzelm@5824: wenzelm@9706: (* simple methods *) wenzelm@9706: wenzelm@9706: fun SIMPLE_METHOD tac = METHOD (fn facts => ALLGOALS (insert_tac facts) THEN tac); wenzelm@9706: fun SIMPLE_METHOD' quant tac = METHOD (fn facts => quant (insert_tac facts THEN' tac)); wenzelm@9706: wenzelm@9706: wenzelm@7601: (* unfold / fold definitions *) wenzelm@6532: wenzelm@9706: fun unfold thms = SIMPLE_METHOD (CHANGED (rewrite_goals_tac thms)); wenzelm@9706: fun fold thms = SIMPLE_METHOD (CHANGED (fold_goals_tac thms)); wenzelm@9484: wenzelm@9484: wenzelm@9484: (* atomize meta-connectives *) wenzelm@9484: wenzelm@9485: fun atomize_tac rews i thm = wenzelm@9485: if Logic.has_meta_prems (#prop (Thm.rep_thm thm)) i then wenzelm@9485: Tactic.asm_rewrite_goal_tac (true, false, false) (K no_tac) (Thm.mss_of rews) i thm wenzelm@9485: else all_tac thm; wenzelm@9485: wenzelm@9485: fun atomize_goal rews i thm = wenzelm@9485: (case Seq.pull (atomize_tac rews i thm) of wenzelm@9485: None => thm wenzelm@9485: | Some (thm', _) => thm'); wenzelm@6532: wenzelm@6532: wenzelm@7419: (* multi_resolve *) wenzelm@7419: wenzelm@7419: local wenzelm@7419: wenzelm@7419: fun res th i rule = wenzelm@7419: Thm.biresolution false [(false, th)] i rule handle THM _ => Seq.empty; wenzelm@7419: wenzelm@7419: fun multi_res _ [] rule = Seq.single rule wenzelm@7419: | multi_res i (th :: ths) rule = Seq.flat (Seq.map (res th i) (multi_res (i + 1) ths rule)); wenzelm@7419: wenzelm@7419: in wenzelm@7419: wenzelm@7419: val multi_resolve = multi_res 1; wenzelm@8372: fun multi_resolves facts rules = Seq.flat (Seq.map (multi_resolve facts) (Seq.of_list rules)); wenzelm@7419: wenzelm@7419: end; wenzelm@7419: wenzelm@7419: wenzelm@8372: (* general rule *) wenzelm@5824: wenzelm@8335: fun gen_resolveq_tac tac rules i st = wenzelm@8372: Seq.flat (Seq.map (fn rule => tac rule i st) rules); wenzelm@8372: wenzelm@8372: val resolveq_tac = gen_resolveq_tac Tactic.rtac; wenzelm@8335: wenzelm@9631: fun resolveq_cases_tac open_parms = gen_resolveq_tac (fn (rule, cases) => fn i => fn st => wenzelm@9653: Seq.map (rpair (RuleCases.make (not open_parms) rule cases)) (Tactic.rtac rule i st)); wenzelm@8335: wenzelm@8335: wenzelm@8372: (* simple rule *) wenzelm@8372: wenzelm@7419: local wenzelm@5824: wenzelm@7130: fun gen_rule_tac tac rules [] = tac rules wenzelm@8372: | gen_rule_tac tac erules facts = gen_resolveq_tac (tac o single) (multi_resolves facts erules); wenzelm@7130: wenzelm@8671: fun gen_rule tac rules = METHOD (HEADGOAL o tac rules); wenzelm@8153: wenzelm@8153: fun gen_rule' tac arg_rules ctxt = METHOD (fn facts => wenzelm@8153: let val rules = wenzelm@8153: if not (null arg_rules) then arg_rules wenzelm@8153: else if null facts then #1 (LocalRules.get ctxt) wenzelm@8153: else op @ (LocalRules.get ctxt); wenzelm@8671: in HEADGOAL (tac rules facts) end); wenzelm@8153: wenzelm@8220: fun setup raw_tac = wenzelm@8220: let val tac = gen_rule_tac raw_tac wenzelm@8220: in (tac, gen_rule tac, gen_rule' tac) end; wenzelm@8220: wenzelm@7419: in wenzelm@7419: wenzelm@8220: val (rule_tac, rule, some_rule) = setup Tactic.resolve_tac; wenzelm@8220: val (erule_tac, erule, some_erule) = setup Tactic.eresolve_tac; wenzelm@8220: val (drule_tac, drule, some_drule) = setup Tactic.dresolve_tac; wenzelm@8220: val (frule_tac, frule, some_frule) = setup Tactic.forward_tac; wenzelm@5824: wenzelm@7419: end; wenzelm@7419: wenzelm@7419: wenzelm@8195: (* this *) wenzelm@8195: wenzelm@8671: val this = METHOD (EVERY o map (HEADGOAL o Tactic.rtac)); wenzelm@8195: wenzelm@8195: wenzelm@8195: (* assumption *) wenzelm@7555: wenzelm@7555: fun assm_tac ctxt = wenzelm@7555: assume_tac APPEND' resolve_tac (filter Thm.no_prems (ProofContext.prems_of ctxt)); wenzelm@7419: wenzelm@7555: fun assumption_tac ctxt [] = assm_tac ctxt wenzelm@7555: | assumption_tac _ [fact] = resolve_tac [fact] wenzelm@7555: | assumption_tac _ _ = K no_tac; wenzelm@7419: wenzelm@8671: fun assumption ctxt = METHOD (HEADGOAL o assumption_tac ctxt); wenzelm@7419: wenzelm@7419: wenzelm@9539: (* res_inst_tac etc. *) wenzelm@8238: wenzelm@9539: (*Note: insts refer to the implicit (!!) goal context; use at your own risk*) wenzelm@9565: fun gen_res_inst _ tac (quant, ([], thms)) = wenzelm@9565: METHOD (fn facts => (quant (insert_tac facts THEN' tac thms))) wenzelm@9565: | gen_res_inst tac _ (quant, (insts, [thm])) = wenzelm@9565: METHOD (fn facts => (quant (insert_tac facts THEN' tac insts thm))) wenzelm@9565: | gen_res_inst _ _ _ = error "Cannot have instantiations with multiple rules"; wenzelm@8238: wenzelm@9565: val res_inst = gen_res_inst Tactic.res_inst_tac Tactic.resolve_tac; wenzelm@9565: val eres_inst = gen_res_inst Tactic.eres_inst_tac Tactic.eresolve_tac; wenzelm@9565: val dres_inst = gen_res_inst Tactic.dres_inst_tac Tactic.dresolve_tac; wenzelm@9565: val forw_inst = gen_res_inst Tactic.forw_inst_tac Tactic.forward_tac; wenzelm@9565: val cut_inst = gen_res_inst Tactic.cut_inst_tac Tactic.cut_facts_tac; wenzelm@8238: wenzelm@8238: wenzelm@8329: (* simple Prolog interpreter *) wenzelm@8329: wenzelm@8329: fun prolog_tac rules facts = wenzelm@8329: DEPTH_SOLVE_1 (HEADGOAL (Tactic.assume_tac APPEND' Tactic.resolve_tac (facts @ rules))); wenzelm@8329: wenzelm@8329: val prolog = METHOD o prolog_tac; wenzelm@8329: wenzelm@8329: wenzelm@8351: (* ML tactics *) wenzelm@8351: wenzelm@8351: val tactic_ref = ref ((fn _ => raise Match): Proof.context -> thm list -> tactic); wenzelm@8351: fun set_tactic f = tactic_ref := f; wenzelm@8351: wenzelm@8351: fun tactic txt ctxt = METHOD (fn facts => wenzelm@9631: (Context.use_mltext wenzelm@9631: ("let fun tactic (ctxt: PureIsar.Proof.context) (facts: thm list) : tactic = \ wenzelm@9631: \let val thm = PureIsar.ProofContext.get_thm_closure ctxt\n\ wenzelm@9631: \ and thms = PureIsar.ProofContext.get_thms_closure ctxt in\n" wenzelm@9631: ^ txt ^ wenzelm@9631: "\nend in PureIsar.Method.set_tactic tactic end") wenzelm@9631: false None; wenzelm@9631: Context.setmp (Some (ProofContext.theory_of ctxt)) (! tactic_ref ctxt) facts)); wenzelm@8351: wenzelm@8351: wenzelm@5824: wenzelm@5824: (** methods theory data **) wenzelm@5824: wenzelm@5824: (* data kind 'Isar/methods' *) wenzelm@5824: wenzelm@5824: structure MethodsDataArgs = wenzelm@5824: struct wenzelm@5824: val name = "Isar/methods"; wenzelm@5824: type T = wenzelm@5824: {space: NameSpace.T, wenzelm@5824: meths: (((Args.src -> Proof.context -> Proof.method) * string) * stamp) Symtab.table}; wenzelm@5824: wenzelm@5824: val empty = {space = NameSpace.empty, meths = Symtab.empty}; wenzelm@6546: val copy = I; wenzelm@5824: val prep_ext = I; wenzelm@5824: fun merge ({space = space1, meths = meths1}, {space = space2, meths = meths2}) = wenzelm@5824: {space = NameSpace.merge (space1, space2), wenzelm@5824: meths = Symtab.merge eq_snd (meths1, meths2) handle Symtab.DUPS dups => wenzelm@5824: error ("Attempt to merge different versions of methods " ^ commas_quote dups)}; wenzelm@5824: wenzelm@9222: fun print _ {space, meths} = wenzelm@5824: let wenzelm@5824: fun prt_meth (name, ((_, comment), _)) = Pretty.block wenzelm@6849: [Pretty.str (name ^ ":"), Pretty.brk 2, Pretty.str comment]; wenzelm@5824: in wenzelm@8720: [Pretty.big_list "methods:" (map prt_meth (NameSpace.cond_extern_table space meths))] wenzelm@9222: |> Pretty.chunks |> Pretty.writeln wenzelm@5824: end; wenzelm@5824: end; wenzelm@5824: wenzelm@5824: structure MethodsData = TheoryDataFun(MethodsDataArgs); wenzelm@5824: val print_methods = MethodsData.print; wenzelm@7611: wenzelm@5824: wenzelm@5824: (* get methods *) wenzelm@5824: wenzelm@5916: exception METHOD_FAIL of (string * Position.T) * exn; wenzelm@5916: wenzelm@5824: fun method thy = wenzelm@5824: let wenzelm@5824: val {space, meths} = MethodsData.get thy; wenzelm@5824: wenzelm@5884: fun meth src = wenzelm@5884: let wenzelm@5884: val ((raw_name, _), pos) = Args.dest_src src; wenzelm@5884: val name = NameSpace.intern space raw_name; wenzelm@5884: in wenzelm@5824: (case Symtab.lookup (meths, name) of wenzelm@5824: None => error ("Unknown proof method: " ^ quote name ^ Position.str_of pos) wenzelm@5916: | Some ((mth, _), _) => transform_failure (curry METHOD_FAIL (name, pos)) (mth src)) wenzelm@5824: end; wenzelm@5824: in meth end; wenzelm@5824: wenzelm@5824: wenzelm@9194: (* add_method(s) *) wenzelm@5824: wenzelm@5824: fun add_methods raw_meths thy = wenzelm@5824: let wenzelm@5824: val full = Sign.full_name (Theory.sign_of thy); wenzelm@5824: val new_meths = wenzelm@5824: map (fn (name, f, comment) => (full name, ((f, comment), stamp ()))) raw_meths; wenzelm@5824: wenzelm@5824: val {space, meths} = MethodsData.get thy; wenzelm@5824: val space' = NameSpace.extend (space, map fst new_meths); wenzelm@5824: val meths' = Symtab.extend (meths, new_meths) handle Symtab.DUPS dups => wenzelm@5824: error ("Duplicate declaration of method(s) " ^ commas_quote dups); wenzelm@5824: in wenzelm@5824: thy |> MethodsData.put {space = space', meths = meths'} wenzelm@5824: end; wenzelm@5824: wenzelm@9194: val add_method = add_methods o Library.single; wenzelm@9194: wenzelm@5824: (*implicit version*) wenzelm@5824: fun Method name meth cmt = Context.>> (add_methods [(name, meth, cmt)]); wenzelm@5824: wenzelm@5824: wenzelm@5884: wenzelm@5884: (** method syntax **) wenzelm@5824: wenzelm@5884: (* basic *) wenzelm@5884: wenzelm@5884: fun syntax (scan: (Proof.context * Args.T list -> 'a * (Proof.context * Args.T list))) = wenzelm@5884: Args.syntax "method" scan; wenzelm@5824: wenzelm@8351: fun simple_args scan f src ctxt : Proof.method = wenzelm@8351: #2 (syntax (Scan.lift (scan >> (fn x => f x ctxt))) src ctxt); wenzelm@8351: wenzelm@7555: fun ctxt_args (f: Proof.context -> Proof.method) src ctxt = wenzelm@8282: #2 (syntax (Scan.succeed (f ctxt)) src ctxt); wenzelm@7555: wenzelm@7555: fun no_args m = ctxt_args (K m); wenzelm@5884: wenzelm@5884: wenzelm@8351: wenzelm@5884: (* sections *) wenzelm@5824: wenzelm@7268: type modifier = (Proof.context -> Proof.context) * Proof.context attribute; wenzelm@7268: wenzelm@7268: local wenzelm@7268: wenzelm@8381: fun sect ss = Scan.first (map Scan.lift ss); wenzelm@5884: fun thms ss = Scan.unless (sect ss) Attrib.local_thms; wenzelm@5884: fun thmss ss = Scan.repeat (thms ss) >> flat; wenzelm@5884: wenzelm@7268: fun apply (f, att) (ctxt, ths) = Thm.applys_attributes ((f ctxt, ths), [att]); wenzelm@5824: wenzelm@7268: fun section ss = (sect ss -- thmss ss) :-- (fn (m, ths) => Scan.depend (fn ctxt => wenzelm@7268: Scan.succeed (apply m (ctxt, ths)))) >> #2; wenzelm@5884: wenzelm@7601: fun sectioned args ss = args -- Scan.repeat (section ss); wenzelm@5884: wenzelm@7268: in wenzelm@5824: wenzelm@5884: fun sectioned_args args ss f src ctxt = wenzelm@8282: let val (ctxt', (x, _)) = syntax (sectioned args ss) src ctxt wenzelm@5921: in f x ctxt' end; wenzelm@5884: wenzelm@7601: fun bang_sectioned_args ss f = sectioned_args Args.bang_facts ss f; wenzelm@9777: fun bang_sectioned_args' ss scan f = wenzelm@9777: sectioned_args (Args.bang_facts -- scan >> swap) ss (uncurry f); wenzelm@7601: fun only_sectioned_args ss f = sectioned_args (Scan.succeed ()) ss (fn () => f); wenzelm@7268: wenzelm@8093: fun thms_ctxt_args f = sectioned_args (thmss []) [] f; wenzelm@8093: fun thms_args f = thms_ctxt_args (K o f); wenzelm@9706: fun thm_args f = thms_args (fn [thm] => f thm | _ => error "Single theorem expected"); wenzelm@5824: wenzelm@7268: end; wenzelm@7268: wenzelm@5824: wenzelm@9539: (* tactic syntax *) wenzelm@8238: wenzelm@8238: val insts = wenzelm@9539: Scan.optional wenzelm@9565: (Args.enum1 "and" (Scan.lift (Args.name -- (Args.$$$ "=" |-- Args.!!! Args.name))) --| wenzelm@9565: Scan.lift (Args.$$$ "in")) [] -- Attrib.local_thmss; wenzelm@8238: wenzelm@8537: fun inst_args f = f oo (#2 oo syntax (Args.goal_spec HEADGOAL -- insts)); wenzelm@8537: wenzelm@8537: wenzelm@9539: fun goal_args' args tac = #2 oo syntax (Args.goal_spec HEADGOAL -- args >> wenzelm@9706: (fn (quant, s) => SIMPLE_METHOD' quant (tac s))); wenzelm@8537: wenzelm@9539: fun goal_args args tac = goal_args' (Scan.lift args) tac; wenzelm@8238: wenzelm@8238: wenzelm@5824: wenzelm@5824: (** method text **) wenzelm@5824: wenzelm@5824: (* datatype text *) wenzelm@5824: wenzelm@5824: datatype text = wenzelm@5824: Basic of (Proof.context -> Proof.method) | wenzelm@5824: Source of Args.src | wenzelm@5824: Then of text list | wenzelm@5824: Orelse of text list | wenzelm@5824: Try of text | wenzelm@5824: Repeat1 of text; wenzelm@5824: wenzelm@5824: wenzelm@5824: (* refine *) wenzelm@5824: wenzelm@8238: fun gen_refine f text state = wenzelm@5824: let wenzelm@5824: val thy = Proof.theory_of state; wenzelm@5824: wenzelm@8238: fun eval (Basic mth) = f mth wenzelm@8238: | eval (Source src) = f (method thy src) wenzelm@5824: | eval (Then txts) = Seq.EVERY (map eval txts) wenzelm@5824: | eval (Orelse txts) = Seq.FIRST (map eval txts) wenzelm@5824: | eval (Try txt) = Seq.TRY (eval txt) wenzelm@5824: | eval (Repeat1 txt) = Seq.REPEAT1 (eval txt); wenzelm@5824: in eval text state end; wenzelm@5824: wenzelm@8238: val refine = gen_refine Proof.refine; wenzelm@8238: val refine_end = gen_refine Proof.refine_end; wenzelm@6404: wenzelm@5824: wenzelm@6404: (* structured proof steps *) wenzelm@5824: wenzelm@7506: val default_text = Source (Args.src (("default", []), Position.none)); wenzelm@8195: val this_text = Basic (K this); wenzelm@9706: val done_text = Basic (K (SIMPLE_METHOD all_tac)); wenzelm@7555: wenzelm@8966: fun close_text asm = Basic (fn ctxt => METHOD (K wenzelm@8966: (FILTER Thm.no_prems ((if asm then ALLGOALS (assm_tac ctxt) else all_tac) THEN flexflex_tac)))); wenzelm@8966: wenzelm@8966: fun finish_text asm None = close_text asm wenzelm@8966: | finish_text asm (Some txt) = Then [txt, close_text asm]; wenzelm@6872: wenzelm@5824: fun proof opt_text state = wenzelm@5824: state wenzelm@5824: |> Proof.assert_backward wenzelm@6404: |> refine (if_none opt_text default_text) wenzelm@8242: |> Seq.map (Proof.goal_facts (K [])) wenzelm@5824: |> Seq.map Proof.enter_forward; wenzelm@5824: wenzelm@8966: fun local_qed asm opt_text = Proof.local_qed (refine (finish_text asm opt_text)); wenzelm@8966: fun local_terminal_proof (text, opt_text) pr = wenzelm@8966: Seq.THEN (proof (Some text), local_qed true opt_text pr); wenzelm@8966: val local_default_proof = local_terminal_proof (default_text, None); wenzelm@8195: val local_immediate_proof = local_terminal_proof (this_text, None); wenzelm@8966: fun local_done_proof pr = Seq.THEN (proof (Some done_text), local_qed false None pr); wenzelm@5824: wenzelm@6872: wenzelm@8966: fun global_qeds asm opt_text = Proof.global_qed (refine (finish_text asm opt_text)); wenzelm@5824: wenzelm@8966: fun global_qed asm opt_text state = wenzelm@6872: state wenzelm@8966: |> global_qeds asm opt_text wenzelm@6872: |> Proof.check_result "Failed to finish proof" state wenzelm@6872: |> Seq.hd; wenzelm@6872: wenzelm@8966: fun global_term_proof asm (text, opt_text) state = wenzelm@6872: state wenzelm@6872: |> proof (Some text) wenzelm@6872: |> Proof.check_result "Terminal proof method failed" state wenzelm@8966: |> (Seq.flat o Seq.map (global_qeds asm opt_text)) wenzelm@6872: |> Proof.check_result "Failed to finish proof (after successful terminal method)" state wenzelm@6872: |> Seq.hd; wenzelm@6872: wenzelm@8966: val global_terminal_proof = global_term_proof true; wenzelm@6934: val global_default_proof = global_terminal_proof (default_text, None); wenzelm@8966: val global_immediate_proof = global_terminal_proof (this_text, None); wenzelm@8966: val global_done_proof = global_term_proof false (done_text, None); wenzelm@5824: wenzelm@5824: wenzelm@5824: (** theory setup **) wenzelm@5824: wenzelm@9539: (* misc tactic emulations *) wenzelm@9539: wenzelm@9539: val subgoal_meth = goal_args (Scan.repeat1 Args.name) Tactic.subgoals_tac; wenzelm@9539: val thin_meth = goal_args Args.name Tactic.thin_tac; wenzelm@9539: val rename_meth = goal_args (Scan.repeat1 Args.name) Tactic.rename_params_tac; wenzelm@9631: val rotate_meth = goal_args (Scan.optional Args.int 1) Tactic.rotate_tac; wenzelm@9539: wenzelm@9539: wenzelm@5824: (* pure_methods *) wenzelm@5824: wenzelm@5824: val pure_methods = wenzelm@5824: [("fail", no_args fail, "force failure"), wenzelm@5824: ("succeed", no_args succeed, "succeed"), wenzelm@9587: ("-", no_args insert_facts, "do nothing (insert current facts only)"), wenzelm@9539: ("insert", thms_args insert, "insert theorems, ignoring facts (improper)"), wenzelm@7601: ("unfold", thms_args unfold, "unfold definitions"), wenzelm@7601: ("fold", thms_args fold, "fold definitions"), wenzelm@8153: ("default", thms_ctxt_args some_rule, "apply some rule"), wenzelm@8153: ("rule", thms_ctxt_args some_rule, "apply some rule"), wenzelm@9539: ("erule", thms_ctxt_args some_erule, "apply some rule in elimination manner (improper)"), wenzelm@9539: ("drule", thms_ctxt_args some_drule, "apply some rule in destruct manner (improper)"), wenzelm@9539: ("frule", thms_ctxt_args some_frule, "apply some rule in forward manner (improper)"), wenzelm@8195: ("this", no_args this, "apply current facts as rules"), wenzelm@8238: ("assumption", ctxt_args assumption, "proof by assumption, preferring facts"), wenzelm@9539: ("rule_tac", inst_args res_inst, "apply rule (dynamic instantiation!)"), wenzelm@9539: ("erule_tac", inst_args eres_inst, "apply rule in elimination manner (dynamic instantiation!)"), wenzelm@9539: ("drule_tac", inst_args dres_inst, "apply rule in destruct manner (dynamic instantiation!)"), wenzelm@9539: ("frule_tac", inst_args forw_inst, "apply rule in forward manner (dynamic instantiation!)"), wenzelm@9539: ("cut_tac", inst_args cut_inst, "cut rule (dynamic instantiation!)"), wenzelm@9565: ("subgoal_tac", subgoal_meth, "insert subgoal (dynamic instantiation!)"), wenzelm@9565: ("thin_tac", thin_meth, "remove premise (dynamic instantiation!)"), wenzelm@9631: ("rename_tac", rename_meth, "rename parameters of goal (dynamic instantiation!)"), wenzelm@9631: ("rotate_tac", rotate_meth, "rotate assumptions of goal"), wenzelm@8351: ("prolog", thms_args prolog, "simple prolog interpreter"), wenzelm@8351: ("tactic", simple_args Args.name tactic, "ML tactic as proof method")]; wenzelm@5824: wenzelm@5824: wenzelm@5824: (* setup *) wenzelm@5824: wenzelm@8153: val setup = wenzelm@8153: [GlobalRules.init, LocalRules.init, Attrib.add_attributes rule_atts, wenzelm@8153: MethodsData.init, add_methods pure_methods]; wenzelm@5824: wenzelm@5824: wenzelm@5824: end; wenzelm@5824: wenzelm@5824: wenzelm@5824: structure BasicMethod: BASIC_METHOD = Method; wenzelm@5824: open BasicMethod;