src/HOL/Boogie/Tools/boogie_tactics.ML
author haftmann
Thu, 26 Aug 2010 20:51:17 +0200
changeset 39019 e46e7a9cb622
parent 36938 c52d1c130898
child 39028 848be46708dc
permissions -rw-r--r--
formerly unnamed infix impliciation now named HOL.implies
boehmes@34068
     1
(*  Title:      HOL/Boogie/Tools/boogie_tactics.ML
boehmes@34068
     2
    Author:     Sascha Boehme, TU Muenchen
boehmes@34068
     3
boehmes@34068
     4
Boogie tactics and Boogie methods.
boehmes@34068
     5
*)
boehmes@34068
     6
boehmes@34068
     7
signature BOOGIE_TACTICS =
boehmes@34068
     8
sig
boehmes@34181
     9
  val unfold_labels_tac: Proof.context -> int -> tactic
boehmes@34068
    10
  val boogie_tac: Proof.context -> thm list -> int -> tactic
boehmes@34068
    11
  val boogie_all_tac: Proof.context -> thm list -> tactic
boehmes@35351
    12
  val split: term -> (term list * term) list
boehmes@35351
    13
  val split_tac: int -> tactic
boehmes@35351
    14
  val drop_assert_at_tac: int -> tactic
boehmes@34068
    15
  val setup: theory -> theory
boehmes@34068
    16
end
boehmes@34068
    17
boehmes@34068
    18
structure Boogie_Tactics: BOOGIE_TACTICS =
boehmes@34068
    19
struct
boehmes@34068
    20
boehmes@34068
    21
fun as_meta_eq eq = eq RS @{thm eq_reflection}
boehmes@34068
    22
boehmes@34068
    23
val assert_at_def = as_meta_eq @{thm assert_at_def}
boehmes@34068
    24
val block_at_def = as_meta_eq @{thm block_at_def}
boehmes@34068
    25
val label_eqs = [assert_at_def, block_at_def]
boehmes@34068
    26
boehmes@34068
    27
fun unfold_labels_tac ctxt =
wenzelm@36938
    28
  let val unfold = Conv.rewrs_conv label_eqs
wenzelm@36938
    29
  in CONVERSION (Conv.top_sweep_conv (K unfold) ctxt) end
boehmes@34068
    30
boehmes@34068
    31
fun boogie_tac ctxt rules =
boehmes@34068
    32
  unfold_labels_tac ctxt
boehmes@34068
    33
  THEN' SMT_Solver.smt_tac ctxt (Boogie_Axioms.get ctxt @ rules)
boehmes@34068
    34
boehmes@34068
    35
fun boogie_all_tac ctxt rules =
boehmes@34068
    36
  PARALLEL_GOALS (HEADGOAL (boogie_tac ctxt rules))
boehmes@34068
    37
boehmes@34068
    38
fun boogie_method all =
boehmes@34068
    39
  Scan.optional Attrib.thms [] >> (fn thms => fn ctxt => METHOD (fn facts =>
boehmes@34068
    40
    let val tac = if all then boogie_all_tac else HEADGOAL oo boogie_tac
boehmes@34068
    41
    in tac ctxt (thms @ facts) end))
boehmes@34068
    42
boehmes@34068
    43
val setup_boogie = Method.setup @{binding boogie} (boogie_method false)
boehmes@34068
    44
  ("Applies an SMT solver to the current goal " ^
boehmes@34068
    45
   "using the current set of Boogie background axioms")
boehmes@34068
    46
boehmes@34068
    47
val setup_boogie_all = Method.setup @{binding boogie_all} (boogie_method true)
boehmes@34068
    48
  ("Applies an SMT solver to all goals " ^
boehmes@34068
    49
   "using the current set of Boogie background axioms")
boehmes@34068
    50
boehmes@34068
    51
boehmes@34068
    52
local
boehmes@35351
    53
  fun explode_conj (@{term "op &"} $ t $ u) = explode_conj t @ explode_conj u
boehmes@35351
    54
    | explode_conj t = [t] 
boehmes@34068
    55
haftmann@39019
    56
  fun splt (ts, @{term HOL.implies} $ t $ u) = splt (ts @ explode_conj t, u)
boehmes@35351
    57
    | splt (ts, @{term "op &"} $ t $ u) = splt (ts, t) @ splt (ts, u)
boehmes@35351
    58
    | splt (ts, @{term assert_at} $ _ $ t) = [(ts, t)]
boehmes@35351
    59
    | splt (_, @{term True}) = []
boehmes@35351
    60
    | splt tp = [tp]
boehmes@35351
    61
in
boehmes@35351
    62
fun split t =
boehmes@35351
    63
  splt ([], HOLogic.dest_Trueprop t)
boehmes@35351
    64
  |> map (fn (us, u) => (map HOLogic.mk_Trueprop us, HOLogic.mk_Trueprop u))
boehmes@35351
    65
end
boehmes@34068
    66
boehmes@35351
    67
val split_tac = REPEAT_ALL_NEW (
boehmes@35351
    68
  Tactic.resolve_tac [@{thm impI}, @{thm conjI}, @{thm TrueI}]
boehmes@35351
    69
  ORELSE' Tactic.etac @{thm conjE})
boehmes@35351
    70
boehmes@35351
    71
val drop_assert_at_tac = CONVERSION (Conv.concl_conv ~1 (Conv.try_conv (
boehmes@35351
    72
  Conv.arg_conv (Conv.rewr_conv assert_at_def))))
boehmes@35351
    73
boehmes@35351
    74
local
boehmes@34068
    75
  fun case_name_of t =
boehmes@34068
    76
    (case HOLogic.dest_Trueprop (Logic.strip_imp_concl t) of
boehmes@34068
    77
      @{term assert_at} $ Free (n, _) $ _ => n
boehmes@34068
    78
    | _ => raise TERM ("case_name_of", [t]))
boehmes@34068
    79
boehmes@34068
    80
  fun boogie_cases ctxt = METHOD_CASES (fn facts =>
boehmes@35351
    81
    ALLGOALS (Method.insert_tac facts THEN' split_tac) #>
boehmes@34068
    82
    Seq.maps (fn st =>
boehmes@34068
    83
      st
boehmes@35351
    84
      |> ALLGOALS drop_assert_at_tac
boehmes@34068
    85
      |> Seq.map (pair (map (rpair [] o case_name_of) (Thm.prems_of st)))) #>
boehmes@34068
    86
    Seq.maps (fn (names, st) =>
boehmes@34068
    87
      CASES
berghofe@34916
    88
        (Rule_Cases.make_common
berghofe@34916
    89
          (ProofContext.theory_of ctxt,
berghofe@34916
    90
           Thm.prop_of (Rule_Cases.internalize_params st)) names)
boehmes@34068
    91
        Tactical.all_tac st))
boehmes@34068
    92
in
boehmes@34068
    93
val setup_boogie_cases = Method.setup @{binding boogie_cases}
boehmes@34068
    94
  (Scan.succeed boogie_cases)
boehmes@34068
    95
  "Prepares a set of Boogie assertions for case-based proofs"
boehmes@34068
    96
end
boehmes@34068
    97
boehmes@34068
    98
boehmes@34068
    99
val setup =
boehmes@34068
   100
  setup_boogie #>
boehmes@34068
   101
  setup_boogie_all #>
boehmes@34068
   102
  setup_boogie_cases
boehmes@34068
   103
boehmes@34068
   104
end