src/HOL/Tools/Sledgehammer/sledgehammer_annotate.ML
author smolkas
Wed, 28 Nov 2012 12:22:05 +0100
changeset 50258 1c708d7728c7
child 50259 9c64a52ae499
permissions -rw-r--r--
put annotate in own structure
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
50258
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
     1
signature SLEDGEHAMMER_ANNOTATE =
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
     2
sig
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
     3
  val annotate_types : Proof.context -> term -> term
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
     4
end
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
     5
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
     6
structure Sledgehammer_Annotate : SLEDGEHAMMER_ANNOTATE =
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
     7
struct
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
     8
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
     9
(* Util *)
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    10
fun post_traverse_term_type' f _ (t as Const (_, T)) s = f t T s
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    11
  | post_traverse_term_type' f _ (t as Free (_, T)) s = f t T s
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    12
  | post_traverse_term_type' f _ (t as Var (_, T)) s = f t T s
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    13
  | post_traverse_term_type' f env (t as Bound i) s = f t (nth env i) s
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    14
  | post_traverse_term_type' f env (Abs (x, T1, b)) s =
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    15
    let
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    16
      val ((b', s'), T2) = post_traverse_term_type' f (T1 :: env) b s
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    17
    in f (Abs (x, T1, b')) (T1 --> T2) s' end
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    18
  | post_traverse_term_type' f env (u $ v) s =
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    19
    let
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    20
      val ((u', s'), Type (_, [_, T])) = post_traverse_term_type' f env u s
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    21
      val ((v', s''), _) = post_traverse_term_type' f env v s'
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    22
    in f (u' $ v') T s'' end
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    23
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    24
fun post_traverse_term_type f s t =
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    25
  post_traverse_term_type' (fn t => fn T => fn s => (f t T s, T)) [] t s |> fst
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    26
fun post_fold_term_type f s t =
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    27
  post_traverse_term_type (fn t => fn T => fn s => (t, f t T s)) s t |> snd
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    28
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    29
(* Data structures, orders *)
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    30
val cost_ord = prod_ord int_ord (prod_ord int_ord int_ord)
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    31
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    32
structure Var_Set_Tab = Table(
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    33
  type key = indexname list
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    34
  val ord = list_ord Term_Ord.fast_indexname_ord)
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    35
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    36
(* (1) Generalize types *)
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    37
fun generalize_types ctxt t =
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    38
  t |> map_types (fn _ => dummyT)
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    39
    |> Syntax.check_term
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    40
         (Proof_Context.set_mode Proof_Context.mode_pattern ctxt)
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    41
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    42
(* (2) Typing-spot table *)
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    43
local
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    44
fun key_of_atype (TVar (z, _)) =
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    45
    Ord_List.insert Term_Ord.fast_indexname_ord z
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    46
  | key_of_atype _ = I
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    47
fun key_of_type T = fold_atyps key_of_atype T []
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    48
fun update_tab t T (tab, pos) =
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    49
  (case key_of_type T of
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    50
     [] => tab
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    51
   | key =>
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    52
     let val cost = (size_of_typ T, (size_of_term t, pos)) in
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    53
       case Var_Set_Tab.lookup tab key of
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    54
         NONE => Var_Set_Tab.update_new (key, cost) tab
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    55
       | SOME old_cost =>
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    56
         (case cost_ord (cost, old_cost) of
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    57
            LESS => Var_Set_Tab.update (key, cost) tab
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    58
          | _ => tab)
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    59
     end,
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    60
   pos + 1)
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    61
in
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    62
val typing_spot_table =
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    63
  post_fold_term_type update_tab (Var_Set_Tab.empty, 0) #> fst
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    64
end
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    65
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    66
(* (3) Reverse-greedy *)
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    67
fun reverse_greedy typing_spot_tab =
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    68
  let
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    69
    fun update_count z =
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    70
      fold (fn tvar => fn tab =>
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    71
        let val c = Vartab.lookup tab tvar |> the_default 0 in
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    72
          Vartab.update (tvar, c + z) tab
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    73
        end)
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    74
    fun superfluous tcount =
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    75
      forall (fn tvar => the (Vartab.lookup tcount tvar) > 1)
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    76
    fun drop_superfluous (tvars, (_, (_, spot))) (spots, tcount) =
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    77
      if superfluous tcount tvars then (spots, update_count ~1 tvars tcount)
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    78
      else (spot :: spots, tcount)
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    79
    val (typing_spots, tvar_count_tab) =
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    80
      Var_Set_Tab.fold
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    81
        (fn kv as (k, _) => apfst (cons kv) #> apsnd (update_count 1 k))
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    82
        typing_spot_tab ([], Vartab.empty)
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    83
      |>> sort_distinct (rev_order o cost_ord o pairself snd)
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    84
  in fold drop_superfluous typing_spots ([], tvar_count_tab) |> fst end
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    85
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    86
(* (4) Introduce annotations *)
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    87
fun introduce_annotations ctxt spots t t' =
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    88
  let
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    89
    val thy = Proof_Context.theory_of ctxt
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    90
    val get_types = post_fold_term_type (K cons) []
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    91
    fun match_types tp =
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    92
      fold (Sign.typ_match thy) (op ~~ (pairself get_types tp)) Vartab.empty
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    93
    fun unica' b x [] = if b then [x] else []
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    94
      | unica' b x (y :: ys) =
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    95
        if x = y then unica' false x ys
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    96
        else unica' true y ys |> b ? cons x
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    97
    fun unica ord xs =
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    98
      case sort ord xs of x :: ys => unica' true x ys | [] => []
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
    99
    val add_all_tfree_namesT = fold_atyps (fn TFree (x, _) => cons x | _ => I)
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   100
    fun erase_unica_tfrees env =
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   101
      let
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   102
        val unica =
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   103
          Vartab.fold (add_all_tfree_namesT o snd o snd) env []
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   104
          |> filter_out (Variable.is_declared ctxt)
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   105
          |> unica fast_string_ord
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   106
        val erase_unica = map_atyps
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   107
          (fn T as TFree (s, _) =>
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   108
              if Ord_List.member fast_string_ord unica s then dummyT else T
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   109
            | T => T)
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   110
      in Vartab.map (K (apsnd erase_unica)) env end
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   111
    val env = match_types (t', t) |> erase_unica_tfrees
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   112
    fun get_annot env (TFree _) = (false, (env, dummyT))
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   113
      | get_annot env (T as TVar (v, S)) =
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   114
        let val T' = Envir.subst_type env T in
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   115
          if T' = dummyT then (false, (env, dummyT))
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   116
          else (true, (Vartab.update (v, (S, dummyT)) env, T'))
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   117
        end
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   118
      | get_annot env (Type (S, Ts)) =
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   119
        (case fold_rev (fn T => fn (b, (env, Ts)) =>
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   120
                  let
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   121
                    val (b', (env', T)) = get_annot env T
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   122
                  in (b orelse b', (env', T :: Ts)) end)
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   123
                Ts (false, (env, [])) of
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   124
           (true, (env', Ts)) => (true, (env', Type (S, Ts)))
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   125
         | (false, (env', _)) => (false, (env', dummyT)))
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   126
    fun post1 _ T (env, cp, ps as p :: ps', annots) =
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   127
        if p <> cp then
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   128
          (env, cp + 1, ps, annots)
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   129
        else
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   130
          let val (_, (env', T')) = get_annot env T in
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   131
            (env', cp + 1, ps', (p, T') :: annots)
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   132
          end
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   133
      | post1 _ _ accum = accum
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   134
    val (_, _, _, annots) = post_fold_term_type post1 (env, 0, spots, []) t'
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   135
    fun post2 t _ (cp, annots as (p, T) :: annots') =
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   136
        if p <> cp then (t, (cp + 1, annots))
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   137
        else (Type.constraint T t, (cp + 1, annots'))
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   138
      | post2 t _ x = (t, x)
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   139
  in post_traverse_term_type post2 (0, rev annots) t |> fst end
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   140
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   141
(* (5) Annotate *)
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   142
fun annotate_types ctxt t =
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   143
  let
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   144
    val t' = generalize_types ctxt t
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   145
    val typing_spots =
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   146
      t' |> typing_spot_table
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   147
         |> reverse_greedy
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   148
         |> sort int_ord
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   149
  in introduce_annotations ctxt typing_spots t t' end
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   150
1c708d7728c7 put annotate in own structure
smolkas
parents:
diff changeset
   151
end