8 *) |
8 *) |
9 |
9 |
10 signature METIS_TACTICS = |
10 signature METIS_TACTICS = |
11 sig |
11 sig |
12 val metisN : string |
12 val metisN : string |
13 val metisFT_N : string |
13 val full_typesN : string |
14 val default_unsound_type_sys : string |
14 val partial_typesN : string |
15 val default_sound_type_sys : string |
15 val no_typesN : string |
|
16 val full_type_sys : string |
|
17 val partial_type_sys : string |
|
18 val no_type_sys : string |
16 val trace : bool Config.T |
19 val trace : bool Config.T |
17 val verbose : bool Config.T |
20 val verbose : bool Config.T |
18 val new_skolemizer : bool Config.T |
21 val new_skolemizer : bool Config.T |
19 val metis_tac : string list -> Proof.context -> thm list -> int -> tactic |
22 val metis_tac : string list -> Proof.context -> thm list -> int -> tactic |
20 val metisFT_tac : Proof.context -> thm list -> int -> tactic |
|
21 val setup : theory -> theory |
23 val setup : theory -> theory |
22 end |
24 end |
23 |
25 |
24 structure Metis_Tactics : METIS_TACTICS = |
26 structure Metis_Tactics : METIS_TACTICS = |
25 struct |
27 struct |
27 open ATP_Translate |
29 open ATP_Translate |
28 open Metis_Translate |
30 open Metis_Translate |
29 open Metis_Reconstruct |
31 open Metis_Reconstruct |
30 |
32 |
31 val metisN = Binding.qualified_name_of @{binding metis} |
33 val metisN = Binding.qualified_name_of @{binding metis} |
32 val metisFT_N = Binding.qualified_name_of @{binding metisFT} |
34 |
33 val full_typesN = "full_types" |
35 val full_typesN = "full_types" |
34 |
36 val partial_typesN = "partial_types" |
35 val default_unsound_type_sys = "poly_args" |
37 val no_typesN = "no_types" |
36 val default_sound_type_sys = "poly_preds_heavy_query" |
38 |
|
39 val full_type_sys = "poly_preds_heavy_query" |
|
40 val partial_type_sys = "poly_args" |
|
41 val no_type_sys = "erased" |
|
42 |
|
43 val type_sys_aliases = |
|
44 [(full_typesN, full_type_sys), |
|
45 (partial_typesN, partial_type_sys), |
|
46 (no_typesN, no_type_sys)] |
37 |
47 |
38 fun method_call_for_type_sys type_sys = |
48 fun method_call_for_type_sys type_sys = |
39 if type_sys = default_sound_type_sys then |
49 metisN ^ " (" ^ |
40 (@{binding metisFT}, "") |
50 (case AList.find (op =) type_sys_aliases type_sys of |
41 else |
51 [alias] => alias |
42 (@{binding metis}, |
52 | _ => type_sys) ^ ")" |
43 if type_sys = default_unsound_type_sys then "" else type_sys) |
|
44 |
53 |
45 val new_skolemizer = |
54 val new_skolemizer = |
46 Attrib.setup_config_bool @{binding metis_new_skolemizer} (K false) |
55 Attrib.setup_config_bool @{binding metis_new_skolemizer} (K false) |
47 |
56 |
48 (* Designed to work also with monomorphic instances of polymorphic theorems. *) |
57 (* Designed to work also with monomorphic instances of polymorphic theorems. *) |
166 case fallback_type_syss of |
175 case fallback_type_syss of |
167 [] => error ("Failed to replay Metis proof in Isabelle." ^ |
176 [] => error ("Failed to replay Metis proof in Isabelle." ^ |
168 (if Config.get ctxt verbose then "\n" ^ loc ^ ": " ^ msg |
177 (if Config.get ctxt verbose then "\n" ^ loc ^ ": " ^ msg |
169 else "")) |
178 else "")) |
170 | type_sys :: _ => |
179 | type_sys :: _ => |
171 let val (binding, arg) = method_call_for_type_sys type_sys in |
180 (verbose_warning ctxt |
172 (verbose_warning ctxt |
181 ("Falling back on " ^ |
173 ("Falling back on " ^ |
182 quote (method_call_for_type_sys type_sys) ^ "..."); |
174 quote (Binding.qualified_name_of binding ^ |
183 FOL_SOLVE fallback_type_syss ctxt cls ths0) |
175 (arg |> arg <> "" ? enclose " (" ")")) ^ "..."); |
|
176 FOL_SOLVE fallback_type_syss ctxt cls ths0) |
|
177 end |
|
178 |
184 |
179 val neg_clausify = |
185 val neg_clausify = |
180 single |
186 single |
181 #> Meson.make_clauses_unsorted |
187 #> Meson.make_clauses_unsorted |
182 #> map Meson_Clausify.introduce_combinators_in_theorem |
188 #> map Meson_Clausify.introduce_combinators_in_theorem |
205 Seq.empty) |
211 Seq.empty) |
206 else |
212 else |
207 Meson.MESON (preskolem_tac ctxt) (maps neg_clausify) tac ctxt i st0 |
213 Meson.MESON (preskolem_tac ctxt) (maps neg_clausify) tac ctxt i st0 |
208 end |
214 end |
209 |
215 |
210 val metis_default_type_syss = [default_unsound_type_sys, default_sound_type_sys] |
216 val metis_default_type_syss = [partial_type_sys, full_type_sys] |
211 val metisFT_type_syss = [default_sound_type_sys] |
217 val metisFT_type_syss = [full_type_sys] |
212 |
218 |
213 fun metis_tac [] = generic_metis_tac metis_default_type_syss |
219 fun metis_tac [] = generic_metis_tac metis_default_type_syss |
214 | metis_tac type_syss = generic_metis_tac type_syss |
220 | metis_tac type_syss = generic_metis_tac type_syss |
215 val metisFT_tac = generic_metis_tac metisFT_type_syss |
|
216 |
221 |
217 (* Whenever "X" has schematic type variables, we treat "using X by metis" as |
222 (* Whenever "X" has schematic type variables, we treat "using X by metis" as |
218 "by (metis X)" to prevent "Subgoal.FOCUS" from freezing the type variables. |
223 "by (metis X)" to prevent "Subgoal.FOCUS" from freezing the type variables. |
219 We don't do it for nonschematic facts "X" because this breaks a few proofs |
224 We don't do it for nonschematic facts "X" because this breaks a few proofs |
220 (in the rare and subtle case where a proof relied on extensionality not being |
225 (in the rare and subtle case where a proof relied on extensionality not being |
222 val has_tvar = |
227 val has_tvar = |
223 exists_type (exists_subtype (fn TVar _ => true | _ => false)) o prop_of |
228 exists_type (exists_subtype (fn TVar _ => true | _ => false)) o prop_of |
224 |
229 |
225 fun method type_syss (type_sys, ths) ctxt facts = |
230 fun method type_syss (type_sys, ths) ctxt facts = |
226 let |
231 let |
|
232 val _ = |
|
233 if type_syss = metisFT_type_syss then |
|
234 legacy_feature "Old 'metisFT' method -- \ |
|
235 \use 'metis (full_types)' instead" |
|
236 else |
|
237 () |
227 val (schem_facts, nonschem_facts) = List.partition has_tvar facts |
238 val (schem_facts, nonschem_facts) = List.partition has_tvar facts |
228 val type_syss = type_sys |> Option.map single |> the_default type_syss |
239 val type_syss = type_sys |> Option.map single |> the_default type_syss |
229 in |
240 in |
230 HEADGOAL (Method.insert_tac nonschem_facts THEN' |
241 HEADGOAL (Method.insert_tac nonschem_facts THEN' |
231 CHANGED_PROP |
242 CHANGED_PROP |
232 o generic_metis_tac type_syss ctxt (schem_facts @ ths)) |
243 o generic_metis_tac type_syss ctxt (schem_facts @ ths)) |
233 end |
244 end |
234 |
245 |
235 fun setup_method (type_syss as type_sys :: _) = |
246 fun setup_method (binding, type_syss as type_sys :: _) = |
236 (if type_syss = metis_default_type_syss then |
247 (if type_syss = metis_default_type_syss then |
237 (Args.parens Parse.short_ident |
248 (Args.parens Parse.short_ident |
238 >> (fn s => if s = full_typesN then default_sound_type_sys else s)) |
249 >> (fn s => AList.lookup (op =) type_sys_aliases s |> the_default s)) |
239 |> Scan.option |> Scan.lift |
250 |> Scan.option |> Scan.lift |
240 else |
251 else |
241 Scan.succeed NONE) |
252 Scan.succeed NONE) |
242 -- Attrib.thms >> (METHOD oo method type_syss) |
253 -- Attrib.thms >> (METHOD oo method type_syss) |
243 |> Method.setup (fst (method_call_for_type_sys type_sys)) |
254 |> Method.setup binding |
244 |
255 |
245 val setup = |
256 val setup = |
246 [(metis_default_type_syss, "Metis for FOL and HOL problems"), |
257 [((@{binding metis}, metis_default_type_syss), |
247 (metisFT_type_syss, |
258 "Metis for FOL and HOL problems"), |
|
259 ((@{binding metisFT}, metisFT_type_syss), |
248 "Metis for FOL/HOL problems with fully-typed translation")] |
260 "Metis for FOL/HOL problems with fully-typed translation")] |
249 |> fold (uncurry setup_method) |
261 |> fold (uncurry setup_method) |
250 |
262 |
251 end; |
263 end; |