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