src/HOL/Tools/SMT/smt_builtin.ML
author blanchet
Mon, 30 Sep 2013 16:28:54 +0200
changeset 55136 ba9254f3111b
parent 55135 b352d3d4a58a
child 55137 9cfff7f61d0d
permissions -rw-r--r--
added possibility to reset builtins (for experimentation)
boehmes@40523
     1
(*  Title:      HOL/Tools/SMT/smt_builtin.ML
boehmes@40523
     2
    Author:     Sascha Boehme, TU Muenchen
boehmes@40523
     3
boehmes@41307
     4
Tables of types and terms directly supported by SMT solvers.
boehmes@40523
     5
*)
boehmes@40523
     6
boehmes@40523
     7
signature SMT_BUILTIN =
boehmes@40523
     8
sig
blanchet@55136
     9
  (*for experiments*)
blanchet@55136
    10
  val clear_builtins: Proof.context -> Proof.context
blanchet@55136
    11
boehmes@41307
    12
  (*built-in types*)
boehmes@41372
    13
  val add_builtin_typ: SMT_Utils.class ->
boehmes@41320
    14
    typ * (typ -> string option) * (typ -> int -> string option) ->
boehmes@41320
    15
    Context.generic -> Context.generic
boehmes@41320
    16
  val add_builtin_typ_ext: typ * (typ -> bool) -> Context.generic ->
boehmes@41320
    17
    Context.generic
boehmes@41529
    18
  val dest_builtin_typ: Proof.context -> typ -> string option
boehmes@41307
    19
  val is_builtin_typ_ext: Proof.context -> typ -> bool
boehmes@41307
    20
boehmes@41307
    21
  (*built-in numbers*)
boehmes@41529
    22
  val dest_builtin_num: Proof.context -> term -> (string * typ) option
boehmes@41307
    23
  val is_builtin_num: Proof.context -> term -> bool
boehmes@41307
    24
  val is_builtin_num_ext: Proof.context -> term -> bool
boehmes@41307
    25
boehmes@41307
    26
  (*built-in functions*)
boehmes@41307
    27
  type 'a bfun = Proof.context -> typ -> term list -> 'a
boehmes@41529
    28
  type bfunr = string * int * term list * (term list -> term)
boehmes@41372
    29
  val add_builtin_fun: SMT_Utils.class ->
boehmes@41529
    30
    (string * typ) * bfunr option bfun -> Context.generic -> Context.generic
boehmes@41372
    31
  val add_builtin_fun': SMT_Utils.class -> term * string -> Context.generic ->
boehmes@41320
    32
    Context.generic
boehmes@41600
    33
  val add_builtin_fun_ext: (string * typ) * term list bfun ->
boehmes@41600
    34
    Context.generic -> Context.generic
boehmes@41320
    35
  val add_builtin_fun_ext': string * typ -> Context.generic -> Context.generic
boehmes@41320
    36
  val add_builtin_fun_ext'': string -> Context.generic -> Context.generic
boehmes@41529
    37
  val dest_builtin_fun: Proof.context -> string * typ -> term list ->
boehmes@41529
    38
    bfunr option
boehmes@41529
    39
  val dest_builtin_eq: Proof.context -> term -> term -> bfunr option
boehmes@41529
    40
  val dest_builtin_pred: Proof.context -> string * typ -> term list ->
boehmes@41529
    41
    bfunr option
boehmes@41529
    42
  val dest_builtin_conn: Proof.context -> string * typ -> term list ->
boehmes@41529
    43
    bfunr option
boehmes@41529
    44
  val dest_builtin: Proof.context -> string * typ -> term list -> bfunr option
boehmes@41600
    45
  val dest_builtin_ext: Proof.context -> string * typ -> term list ->
boehmes@41600
    46
    term list option
boehmes@41307
    47
  val is_builtin_fun: Proof.context -> string * typ -> term list -> bool
boehmes@41374
    48
  val is_builtin_fun_ext: Proof.context -> string * typ -> term list -> bool
boehmes@40523
    49
end
boehmes@40523
    50
boehmes@40523
    51
structure SMT_Builtin: SMT_BUILTIN =
boehmes@40523
    52
struct
boehmes@40523
    53
boehmes@40523
    54
boehmes@41307
    55
(* built-in tables *)
boehmes@40523
    56
boehmes@41307
    57
datatype ('a, 'b) kind = Ext of 'a | Int of 'b
boehmes@40523
    58
boehmes@41576
    59
type ('a, 'b) ttab = ((typ * ('a, 'b) kind) Ord_List.T) SMT_Utils.dict 
boehmes@40523
    60
boehmes@41307
    61
fun typ_ord ((T, _), (U, _)) =
boehmes@41307
    62
  let
boehmes@41307
    63
    fun tord (TVar _, Type _) = GREATER
boehmes@41307
    64
      | tord (Type _, TVar _) = LESS
boehmes@41307
    65
      | tord (Type (n, Ts), Type (m, Us)) =
boehmes@41307
    66
          if n = m then list_ord tord (Ts, Us)
boehmes@41307
    67
          else Term_Ord.typ_ord (T, U)
boehmes@41307
    68
      | tord TU = Term_Ord.typ_ord TU
boehmes@41307
    69
  in tord (T, U) end
boehmes@40523
    70
boehmes@41307
    71
fun insert_ttab cs T f =
boehmes@41576
    72
  SMT_Utils.dict_map_default (cs, [])
boehmes@41307
    73
    (Ord_List.insert typ_ord (perhaps (try Logic.varifyT_global) T, f))
boehmes@40523
    74
boehmes@41307
    75
fun merge_ttab ttabp =
wenzelm@41721
    76
  SMT_Utils.dict_merge (Ord_List.merge typ_ord) ttabp
boehmes@40523
    77
boehmes@41307
    78
fun lookup_ttab ctxt ttab T =
wenzelm@43232
    79
  let fun match (U, _) = Sign.typ_instance (Proof_Context.theory_of ctxt) (T, U)
boehmes@41372
    80
  in
boehmes@41576
    81
    get_first (find_first match)
boehmes@41576
    82
      (SMT_Utils.dict_lookup ttab (SMT_Config.solver_class_of ctxt))
boehmes@41372
    83
  end
boehmes@40523
    84
boehmes@41307
    85
type ('a, 'b) btab = ('a, 'b) ttab Symtab.table
boehmes@40523
    86
boehmes@41307
    87
fun insert_btab cs n T f =
boehmes@41307
    88
  Symtab.map_default (n, []) (insert_ttab cs T f)
boehmes@41307
    89
boehmes@41307
    90
fun merge_btab btabp = Symtab.join (K merge_ttab) btabp
boehmes@41307
    91
boehmes@41307
    92
fun lookup_btab ctxt btab (n, T) =
boehmes@41307
    93
  (case Symtab.lookup btab n of
boehmes@41307
    94
    NONE => NONE
boehmes@41307
    95
  | SOME ttab => lookup_ttab ctxt ttab T)
boehmes@41307
    96
blanchet@55135
    97
type 'a bfun = Proof.context -> typ -> term list -> 'a
blanchet@55135
    98
blanchet@55135
    99
type bfunr = string * int * term list * (term list -> term)
blanchet@55135
   100
blanchet@55135
   101
structure Builtins = Generic_Data
blanchet@55135
   102
(
blanchet@55135
   103
  type T =
blanchet@55135
   104
    (typ -> bool, (typ -> string option) * (typ -> int -> string option)) ttab *
blanchet@55135
   105
    (term list bfun, bfunr option bfun) btab
blanchet@55135
   106
  val empty = ([], Symtab.empty)
blanchet@55135
   107
  val extend = I
blanchet@55135
   108
  fun merge ((t1, b1), (t2, b2)) = (merge_ttab (t1, t2), merge_btab (b1, b2))
blanchet@55135
   109
)
boehmes@41307
   110
blanchet@55136
   111
val clear_builtins = Context.proof_map (Builtins.put ([], Symtab.empty))
blanchet@55136
   112
blanchet@55136
   113
boehmes@41307
   114
(* built-in types *)
boehmes@41307
   115
boehmes@41307
   116
fun add_builtin_typ cs (T, f, g) =
blanchet@55135
   117
  Builtins.map (apfst (insert_ttab cs T (Int (f, g))))
boehmes@41307
   118
boehmes@41307
   119
fun add_builtin_typ_ext (T, f) =
blanchet@55135
   120
  Builtins.map (apfst (insert_ttab SMT_Utils.basicC T (Ext f)))
boehmes@41307
   121
boehmes@41307
   122
fun lookup_builtin_typ ctxt =
blanchet@55135
   123
  lookup_ttab ctxt (fst (Builtins.get (Context.Proof ctxt)))
boehmes@41307
   124
boehmes@41529
   125
fun dest_builtin_typ ctxt T =
boehmes@41307
   126
  (case lookup_builtin_typ ctxt T of
boehmes@41307
   127
    SOME (_, Int (f, _)) => f T
boehmes@41307
   128
  | _ => NONE) 
boehmes@41307
   129
boehmes@41307
   130
fun is_builtin_typ_ext ctxt T =
boehmes@41307
   131
  (case lookup_builtin_typ ctxt T of
boehmes@41307
   132
    SOME (_, Int (f, _)) => is_some (f T)
boehmes@41307
   133
  | SOME (_, Ext f) => f T
boehmes@40523
   134
  | NONE => false)
boehmes@40523
   135
boehmes@40523
   136
boehmes@41307
   137
(* built-in numbers *)
boehmes@41307
   138
boehmes@41529
   139
fun dest_builtin_num ctxt t =
boehmes@41307
   140
  (case try HOLogic.dest_number t of
boehmes@41307
   141
    NONE => NONE
boehmes@41307
   142
  | SOME (T, i) =>
boehmes@41307
   143
      (case lookup_builtin_typ ctxt T of
boehmes@41375
   144
        SOME (_, Int (_, g)) => g T i |> Option.map (rpair T)
boehmes@41307
   145
      | _ => NONE))
boehmes@41307
   146
boehmes@41529
   147
val is_builtin_num = is_some oo dest_builtin_num
boehmes@41307
   148
boehmes@41307
   149
fun is_builtin_num_ext ctxt t =
boehmes@41307
   150
  (case try HOLogic.dest_number t of
boehmes@41307
   151
    NONE => false
boehmes@41307
   152
  | SOME (T, _) => is_builtin_typ_ext ctxt T)
boehmes@41307
   153
boehmes@41307
   154
boehmes@41307
   155
(* built-in functions *)
boehmes@41307
   156
boehmes@41307
   157
fun add_builtin_fun cs ((n, T), f) =
blanchet@55135
   158
  Builtins.map (apsnd (insert_btab cs n T (Int f)))
boehmes@41307
   159
boehmes@41307
   160
fun add_builtin_fun' cs (t, n) =
boehmes@41375
   161
  let
boehmes@41529
   162
    val c as (m, T) = Term.dest_Const t
boehmes@41529
   163
    fun app U ts = Term.list_comb (Const (m, U), ts)
boehmes@41529
   164
    fun bfun _ U ts = SOME (n, length (Term.binder_types T), ts, app U)
boehmes@41529
   165
  in add_builtin_fun cs (c, bfun) end
boehmes@41307
   166
boehmes@41307
   167
fun add_builtin_fun_ext ((n, T), f) =
blanchet@55135
   168
  Builtins.map (apsnd (insert_btab SMT_Utils.basicC n T (Ext f)))
boehmes@41307
   169
boehmes@41600
   170
fun add_builtin_fun_ext' c = add_builtin_fun_ext (c, fn _ => fn _ => I)
boehmes@41307
   171
boehmes@41320
   172
fun add_builtin_fun_ext'' n context =
boehmes@41320
   173
  let val thy = Context.theory_of context
boehmes@41320
   174
  in add_builtin_fun_ext' (n, Sign.the_const_type thy n) context end
boehmes@41307
   175
boehmes@41307
   176
fun lookup_builtin_fun ctxt =
blanchet@55135
   177
  lookup_btab ctxt (snd (Builtins.get (Context.Proof ctxt)))
boehmes@41307
   178
boehmes@41529
   179
fun dest_builtin_fun ctxt (c as (_, T)) ts =
boehmes@41307
   180
  (case lookup_builtin_fun ctxt c of
boehmes@41307
   181
    SOME (_, Int f) => f ctxt T ts
boehmes@41307
   182
  | _ => NONE)
boehmes@41307
   183
boehmes@41529
   184
fun dest_builtin_eq ctxt t u =
boehmes@41529
   185
  let
boehmes@41529
   186
    val aT = TFree (Name.aT, @{sort type})
boehmes@41529
   187
    val c = (@{const_name HOL.eq}, aT --> aT --> @{typ bool})
boehmes@41529
   188
    fun mk ts = Term.list_comb (HOLogic.eq_const (Term.fastype_of (hd ts)), ts)
boehmes@41529
   189
  in
boehmes@41529
   190
    dest_builtin_fun ctxt c []
boehmes@41529
   191
    |> Option.map (fn (n, i, _, _) => (n, i, [t, u], mk))
boehmes@41529
   192
  end
boehmes@41529
   193
boehmes@41529
   194
fun special_builtin_fun pred ctxt (c as (_, T)) ts =
boehmes@41529
   195
  if pred (Term.body_type T, Term.binder_types T) then
boehmes@41529
   196
    dest_builtin_fun ctxt c ts
boehmes@41529
   197
  else NONE
boehmes@41529
   198
boehmes@41529
   199
fun dest_builtin_pred ctxt = special_builtin_fun (equal @{typ bool} o fst) ctxt
boehmes@41529
   200
boehmes@41529
   201
fun dest_builtin_conn ctxt =
boehmes@41529
   202
  special_builtin_fun (forall (equal @{typ bool}) o (op ::)) ctxt
boehmes@41529
   203
boehmes@41529
   204
fun dest_builtin ctxt c ts =
blanchet@55136
   205
  let val t = Term.list_comb (Const c, ts)
boehmes@41529
   206
  in
boehmes@41529
   207
    (case dest_builtin_num ctxt t of
boehmes@41529
   208
      SOME (n, _) => SOME (n, 0, [], K t)
boehmes@41529
   209
    | NONE => dest_builtin_fun ctxt c ts)
boehmes@41529
   210
  end
boehmes@41529
   211
boehmes@41600
   212
fun dest_builtin_fun_ext ctxt (c as (_, T)) ts =    
boehmes@41600
   213
  (case lookup_builtin_fun ctxt c of
boehmes@41600
   214
    SOME (_, Int f) => f ctxt T ts |> Option.map (fn (_, _, us, _) => us)
boehmes@41600
   215
  | SOME (_, Ext f) => SOME (f ctxt T ts)
boehmes@41600
   216
  | NONE => NONE)
boehmes@41600
   217
boehmes@41600
   218
fun dest_builtin_ext ctxt c ts =
boehmes@41600
   219
  if is_builtin_num_ext ctxt (Term.list_comb (Const c, ts)) then SOME []
boehmes@41600
   220
  else dest_builtin_fun_ext ctxt c ts
boehmes@41600
   221
boehmes@41529
   222
fun is_builtin_fun ctxt c ts = is_some (dest_builtin_fun ctxt c ts)
boehmes@41307
   223
boehmes@41600
   224
fun is_builtin_fun_ext ctxt c ts = is_some (dest_builtin_fun_ext ctxt c ts)
boehmes@41307
   225
boehmes@40523
   226
end