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
|