src/HOL/Boogie/Tools/boogie_split.ML
author haftmann
Mon, 16 Nov 2009 10:16:40 +0100
changeset 33708 b45d3b8cc74e
parent 33662 7be6ee4ee67f
child 33710 ffc5176a9105
permissions -rw-r--r--
proper purge
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
33419
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
     1
(*  Title:      HOL/Boogie/Tools/boogie_split.ML
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
     2
    Author:     Sascha Boehme, TU Muenchen
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
     3
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
     4
Method to split Boogie-generate verification conditions and pass the splinters
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
     5
to user-supplied automated sub-tactics.
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
     6
*)
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
     7
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
     8
signature BOOGIE_SPLIT =
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
     9
sig
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    10
  val add_sub_tactic: string * (Proof.context -> int -> tactic) -> theory ->
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    11
    theory
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    12
  val sub_tactic_names: theory -> string list
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    13
  val setup: theory -> theory
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    14
end
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    15
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    16
structure Boogie_Split: BOOGIE_SPLIT =
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    17
struct
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    18
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    19
(* sub-tactics store *)
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    20
33522
737589bb9bb8 adapted Theory_Data;
wenzelm
parents: 33424
diff changeset
    21
structure Sub_Tactics = Theory_Data
33419
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    22
(
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    23
  type T = (Proof.context -> int -> tactic) Symtab.table
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    24
  val empty = Symtab.empty
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    25
  val extend = I
33522
737589bb9bb8 adapted Theory_Data;
wenzelm
parents: 33424
diff changeset
    26
  fun merge data = Symtab.merge (K true) data
33419
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    27
)
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    28
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    29
fun add_sub_tactic tac = Sub_Tactics.map (Symtab.update_new tac)
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    30
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    31
val sub_tactic_names = Symtab.keys o Sub_Tactics.get
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    32
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    33
fun lookup_sub_tactic ctxt name =
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    34
  (case Symtab.lookup (Sub_Tactics.get (ProofContext.theory_of ctxt)) name of
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    35
    SOME tac => SOME (name, tac)
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    36
  | NONE => (warning ("Unknown sub-tactic: " ^ quote name); NONE))
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    37
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    38
fun as_meta_eq eq = eq RS @{thm eq_reflection}
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    39
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    40
fun full_implies_conv cv ct =
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    41
  (case try Thm.dest_implies ct of
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    42
    NONE => cv ct
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    43
  | SOME (cp, cc) => Drule.imp_cong_rule (cv cp) (full_implies_conv cv cc))
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    44
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    45
fun sub_tactics_tac ctxt (verbose, sub_tac_names) case_name =
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    46
  let
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    47
    fun trace msg = if verbose then tracing msg else ()
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    48
    fun trying name = trace ("Trying tactic " ^ quote name ^ " on case " ^
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    49
      quote case_name ^ " ...")
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    50
    fun solved () = trace ("Case solved: " ^ quote case_name)
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    51
    fun failed () = trace ("Case remains unsolved: " ^ quote case_name)
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    52
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    53
    infix IF_UNSOLVED
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    54
    fun (tac1 IF_UNSOLVED tac2) i st = st |> (tac1 i THEN (fn st' =>
33424
a3b002e2cd55 proper and unique case names for the split_vc method,
boehmes
parents: 33419
diff changeset
    55
      let val j = i + Thm.nprems_of st' - Thm.nprems_of st
a3b002e2cd55 proper and unique case names for the split_vc method,
boehmes
parents: 33419
diff changeset
    56
      in
a3b002e2cd55 proper and unique case names for the split_vc method,
boehmes
parents: 33419
diff changeset
    57
        if i > j then (solved (); Tactical.all_tac st')
a3b002e2cd55 proper and unique case names for the split_vc method,
boehmes
parents: 33419
diff changeset
    58
        else Seq.INTERVAL tac2 i j st'
a3b002e2cd55 proper and unique case names for the split_vc method,
boehmes
parents: 33419
diff changeset
    59
      end))
33419
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    60
    
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    61
    fun TRY_ALL [] _ st = (failed (); Tactical.no_tac st)
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    62
      | TRY_ALL ((name, tac) :: tacs) i st = (trying name;
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    63
          (TRY o tac ctxt IF_UNSOLVED TRY_ALL tacs) i st)
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    64
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    65
    val unfold_labels = Conv.try_conv (Conv.arg_conv
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    66
      (More_Conv.rewrs_conv (map as_meta_eq @{thms labels})))
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    67
  in
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    68
    CONVERSION (full_implies_conv unfold_labels)
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    69
    THEN' TRY_ALL (map_filter (lookup_sub_tactic ctxt) sub_tac_names)
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    70
  end
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    71
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
    72
33424
a3b002e2cd55 proper and unique case names for the split_vc method,
boehmes
parents: 33419
diff changeset
    73
(* case names *)
a3b002e2cd55 proper and unique case names for the split_vc method,
boehmes
parents: 33419
diff changeset
    74
a3b002e2cd55 proper and unique case names for the split_vc method,
boehmes
parents: 33419
diff changeset
    75
fun case_name_of t =
a3b002e2cd55 proper and unique case names for the split_vc method,
boehmes
parents: 33419
diff changeset
    76
  (case HOLogic.dest_Trueprop (Logic.strip_imp_concl t) of
a3b002e2cd55 proper and unique case names for the split_vc method,
boehmes
parents: 33419
diff changeset
    77
    @{term assert_at} $ Free (n, _) $ _ => n
a3b002e2cd55 proper and unique case names for the split_vc method,
boehmes
parents: 33419
diff changeset
    78
  | _ => raise TERM ("case_name_of", [t]))
a3b002e2cd55 proper and unique case names for the split_vc method,
boehmes
parents: 33419
diff changeset
    79
a3b002e2cd55 proper and unique case names for the split_vc method,
boehmes
parents: 33419
diff changeset
    80
local
a3b002e2cd55 proper and unique case names for the split_vc method,
boehmes
parents: 33419
diff changeset
    81
  fun make_case_name (i, t) =
a3b002e2cd55 proper and unique case names for the split_vc method,
boehmes
parents: 33419
diff changeset
    82
    the_default ("B_" ^ string_of_int (i + 1)) (try case_name_of t)
a3b002e2cd55 proper and unique case names for the split_vc method,
boehmes
parents: 33419
diff changeset
    83
a3b002e2cd55 proper and unique case names for the split_vc method,
boehmes
parents: 33419
diff changeset
    84
  val assert_intro = Thm.symmetric (as_meta_eq @{thm assert_at_def})
a3b002e2cd55 proper and unique case names for the split_vc method,
boehmes
parents: 33419
diff changeset
    85
  val l = Thm.dest_arg1 (Thm.rhs_of assert_intro)
a3b002e2cd55 proper and unique case names for the split_vc method,
boehmes
parents: 33419
diff changeset
    86
  fun intro new =
a3b002e2cd55 proper and unique case names for the split_vc method,
boehmes
parents: 33419
diff changeset
    87
    Conv.rewr_conv (Thm.instantiate ([], [(l, new)]) assert_intro)
a3b002e2cd55 proper and unique case names for the split_vc method,
boehmes
parents: 33419
diff changeset
    88
a3b002e2cd55 proper and unique case names for the split_vc method,
boehmes
parents: 33419
diff changeset
    89
  val assert_eq = @{lemma "assert_at x t == assert_at y t"
a3b002e2cd55 proper and unique case names for the split_vc method,
boehmes
parents: 33419
diff changeset
    90
    by (simp add: assert_at_def)}
a3b002e2cd55 proper and unique case names for the split_vc method,
boehmes
parents: 33419
diff changeset
    91
  val (x, y) = pairself Thm.dest_arg1 (Thm.dest_binop (Thm.cprop_of assert_eq))
a3b002e2cd55 proper and unique case names for the split_vc method,
boehmes
parents: 33419
diff changeset
    92
  fun rename old new =
a3b002e2cd55 proper and unique case names for the split_vc method,
boehmes
parents: 33419
diff changeset
    93
    Conv.rewr_conv (Thm.instantiate ([], [(x, old), (y, new)]) assert_eq)
a3b002e2cd55 proper and unique case names for the split_vc method,
boehmes
parents: 33419
diff changeset
    94
a3b002e2cd55 proper and unique case names for the split_vc method,
boehmes
parents: 33419
diff changeset
    95
  fun at_concl cv = Conv.concl_conv ~1 (Conv.arg_conv cv)
a3b002e2cd55 proper and unique case names for the split_vc method,
boehmes
parents: 33419
diff changeset
    96
  fun make_label thy name = Thm.cterm_of thy (Free (name, @{typ bool}))
a3b002e2cd55 proper and unique case names for the split_vc method,
boehmes
parents: 33419
diff changeset
    97
a3b002e2cd55 proper and unique case names for the split_vc method,
boehmes
parents: 33419
diff changeset
    98
  fun rename_case thy new ct =
a3b002e2cd55 proper and unique case names for the split_vc method,
boehmes
parents: 33419
diff changeset
    99
    (case try case_name_of (Thm.term_of ct) of
a3b002e2cd55 proper and unique case names for the split_vc method,
boehmes
parents: 33419
diff changeset
   100
      NONE => at_concl (intro (make_label thy new))
a3b002e2cd55 proper and unique case names for the split_vc method,
boehmes
parents: 33419
diff changeset
   101
    | SOME old => if new = old then Conv.all_conv
a3b002e2cd55 proper and unique case names for the split_vc method,
boehmes
parents: 33419
diff changeset
   102
        else at_concl (rename (make_label thy old) (make_label thy new))) ct
a3b002e2cd55 proper and unique case names for the split_vc method,
boehmes
parents: 33419
diff changeset
   103
in
a3b002e2cd55 proper and unique case names for the split_vc method,
boehmes
parents: 33419
diff changeset
   104
fun unique_case_names thy st =
a3b002e2cd55 proper and unique case names for the split_vc method,
boehmes
parents: 33419
diff changeset
   105
  let
a3b002e2cd55 proper and unique case names for the split_vc method,
boehmes
parents: 33419
diff changeset
   106
    val names = map_index make_case_name (Thm.prems_of st)
a3b002e2cd55 proper and unique case names for the split_vc method,
boehmes
parents: 33419
diff changeset
   107
      |> ` (duplicates (op =)) |-> Name.variant_list
a3b002e2cd55 proper and unique case names for the split_vc method,
boehmes
parents: 33419
diff changeset
   108
  in ALLGOALS (fn i => CONVERSION (rename_case thy (nth names (i-1))) i) st end
a3b002e2cd55 proper and unique case names for the split_vc method,
boehmes
parents: 33419
diff changeset
   109
end
a3b002e2cd55 proper and unique case names for the split_vc method,
boehmes
parents: 33419
diff changeset
   110
a3b002e2cd55 proper and unique case names for the split_vc method,
boehmes
parents: 33419
diff changeset
   111
33419
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
   112
(* splitting method *)
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
   113
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
   114
local
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
   115
  val split_rules = [@{thm impI}, @{thm conjI}, @{thm TrueI}]
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
   116
33662
7be6ee4ee67f parallel solving of Boogie splinters
boehmes
parents: 33522
diff changeset
   117
  fun ALL_GOALS false tac = ALLGOALS tac
7be6ee4ee67f parallel solving of Boogie splinters
boehmes
parents: 33522
diff changeset
   118
    | ALL_GOALS true tac = PARALLEL_GOALS (HEADGOAL tac)
7be6ee4ee67f parallel solving of Boogie splinters
boehmes
parents: 33522
diff changeset
   119
7be6ee4ee67f parallel solving of Boogie splinters
boehmes
parents: 33522
diff changeset
   120
  fun prep_tac ctxt ((parallel, verbose), subs) facts =
33424
a3b002e2cd55 proper and unique case names for the split_vc method,
boehmes
parents: 33419
diff changeset
   121
    HEADGOAL (Method.insert_tac facts)
a3b002e2cd55 proper and unique case names for the split_vc method,
boehmes
parents: 33419
diff changeset
   122
    THEN HEADGOAL (REPEAT_ALL_NEW (Tactic.resolve_tac split_rules))
a3b002e2cd55 proper and unique case names for the split_vc method,
boehmes
parents: 33419
diff changeset
   123
    THEN unique_case_names (ProofContext.theory_of ctxt)
33662
7be6ee4ee67f parallel solving of Boogie splinters
boehmes
parents: 33522
diff changeset
   124
    THEN ALL_GOALS parallel (SUBGOAL (fn (t, i) =>
7be6ee4ee67f parallel solving of Boogie splinters
boehmes
parents: 33522
diff changeset
   125
      TRY (sub_tactics_tac ctxt (verbose, subs) (case_name_of t) i)))
33419
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
   126
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
   127
  val drop_assert_at = Conv.concl_conv ~1 (Conv.try_conv (Conv.arg_conv
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
   128
    (Conv.rewr_conv (as_meta_eq @{thm assert_at_def}))))
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
   129
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
   130
  fun split_vc args ctxt = METHOD_CASES (fn facts =>
33424
a3b002e2cd55 proper and unique case names for the split_vc method,
boehmes
parents: 33419
diff changeset
   131
    prep_tac ctxt args facts #>
33419
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
   132
    Seq.maps (fn st =>
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
   133
      st
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
   134
      |> ALLGOALS (CONVERSION drop_assert_at)
33424
a3b002e2cd55 proper and unique case names for the split_vc method,
boehmes
parents: 33419
diff changeset
   135
      |> Seq.map (pair (map (rpair [] o case_name_of) (Thm.prems_of st)))) #>
33419
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
   136
    Seq.maps (fn (names, st) =>
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
   137
      CASES
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
   138
        (Rule_Cases.make_common false
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
   139
          (ProofContext.theory_of ctxt, Thm.prop_of st) names)
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
   140
        Tactical.all_tac st))
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
   141
33662
7be6ee4ee67f parallel solving of Boogie splinters
boehmes
parents: 33522
diff changeset
   142
  val options =
7be6ee4ee67f parallel solving of Boogie splinters
boehmes
parents: 33522
diff changeset
   143
    Args.parens (Args.$$$ "verbose") >> K (false, true) ||
7be6ee4ee67f parallel solving of Boogie splinters
boehmes
parents: 33522
diff changeset
   144
    Args.parens (Args.$$$ "fast_verbose") >> K (true, true)
33419
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
   145
  val sub_tactics = Args.$$$ "try" -- Args.colon |-- Scan.repeat1 Args.name
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
   146
in
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
   147
val setup_split_vc = Method.setup @{binding split_vc}
33662
7be6ee4ee67f parallel solving of Boogie splinters
boehmes
parents: 33522
diff changeset
   148
  (Scan.lift (Scan.optional options (true, false) --
7be6ee4ee67f parallel solving of Boogie splinters
boehmes
parents: 33522
diff changeset
   149
    Scan.optional sub_tactics []) >> split_vc)
33419
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
   150
  ("Splits a Boogie-generated verification conditions into smaller problems" ^
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
   151
   " and tries to solve the splinters with the supplied sub-tactics.")
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
   152
end
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
   153
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
   154
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
   155
(* predefined sub-tactics *)
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
   156
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
   157
fun fast_sub_tac ctxt = Classical.fast_tac (Classical.claset_of ctxt)
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
   158
fun simp_sub_tac ctxt =
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
   159
  Simplifier.asm_full_simp_tac (Simplifier.simpset_of ctxt)
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
   160
fun smt_sub_tac ctxt = SMT_Solver.smt_tac ctxt (Split_VC_SMT_Rules.get ctxt)
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
   161
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
   162
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
   163
(* setup *)
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
   164
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
   165
val setup =
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
   166
  setup_split_vc #>
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
   167
  add_sub_tactic ("fast", fast_sub_tac) #>
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
   168
  add_sub_tactic ("simp", simp_sub_tac) #>
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
   169
  add_sub_tactic ("smt", smt_sub_tac)  
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
   170
8ae45e87b992 added HOL-Boogie
boehmes
parents:
diff changeset
   171
end