In an Isabelle theory file, I can write simple one-line tactics such as the following:
apply (clarsimp simp: split_def split: prod.splits)
I fi
The Method
class appear to provide enough of an interface to extract out a tactic, via a cases_tactic
as follows:
(*
* Generate an ML tactic object of the given Isar string.
*
* For example,
*
* mk_tac "auto simp: field_simps intro!: ext" @{context}
*
* will generate the corresponding "tactic" object.
*)
fun mk_tac str ctxt =
let
val parsed_str = Outer_Syntax.scan Position.start str
|> filter Token.is_proper
|> Args.name
val meth = Method.method (Proof_Context.theory_of ctxt)
(Args.src (parsed_str, Position.start)) ctxt
in
Method.apply (K meth) ctxt [] #> Seq.map snd
end
or alternatively as an anti-quotation:
(*
* Setup an antiquotation of the form:
*
* @{tactic "auto simp: foo intro!: bar"}
*
* which returns an object of type "context -> tactic".
*
* While this doesn't provide any benefits over a direct call to "mk_tac" just
* yet, in the future it may generate code to avoid parsing the tactic at
* run-time.
*)
val tactic_antiquotation_setup =
let
val parse_string =
((Args.context -- Scan.lift Args.name) >> snd)
#>> ML_Syntax.print_string
#>> (fn s => "mk_tac " ^ s)
#>> ML_Syntax.atomic
in
ML_Antiquote.inline @{binding "tactic"} parse_string
end
and setup in a theory file as follows:
setup {*
tactic_antiquotation_setup
*}
which can then be used as follows:
lemma "(a :: nat) * (b + 1) = (a * b) + a"
by (tactic {* @{tactic "metis Suc_eq_plus1 mult_Suc_right nat_add_commute"} @{context} *})
as desired.