bump up Nitpick's axiom/definition unfolding limits, because some real-world problems (e.g. from Boogie) ran into the previous limits;
the limits are there to prevent infinite recursion; they can be set arbitrarily high without much harm
1 (* Title: HOL/Nitpick/Tools/nitpick_hol.ML
2 Author: Jasmin Blanchette, TU Muenchen
5 Auxiliary HOL-related functions used by Nitpick.
8 signature NITPICK_HOL =
10 type styp = Nitpick_Util.styp
11 type const_table = term list Symtab.table
12 type special_fun = (styp * int list * term list) * styp
13 type unrolled = styp * styp
14 type wf_cache = (styp * (bool * bool)) list
16 type extended_context = {
20 boxes: (typ option * bool option) list,
21 wfs: (styp option * bool option) list,
22 user_axioms: bool option,
24 destroy_constrs: bool,
27 star_linear_preds: bool,
30 tac_timeout: Time.time option,
32 case_names: (string * int) list,
33 def_table: const_table,
34 nondef_table: const_table,
35 user_nondefs: term list,
36 simp_table: const_table Unsynchronized.ref,
37 psimp_table: const_table,
38 intro_table: const_table,
39 ground_thm_table: term list Inttab.table,
40 ersatz_table: (string * string) list,
41 skolems: (string * string list) list Unsynchronized.ref,
42 special_funs: special_fun list Unsynchronized.ref,
43 unrolled_preds: unrolled list Unsynchronized.ref,
44 wf_cache: wf_cache Unsynchronized.ref,
45 constr_cache: (typ * styp list) list Unsynchronized.ref}
48 val numeral_prefix : string
49 val skolem_prefix : string
50 val eval_prefix : string
51 val original_name : string -> string
52 val unbox_type : typ -> typ
53 val string_for_type : Proof.context -> typ -> string
54 val prefix_name : string -> string -> string
55 val short_name : string -> string
56 val short_const_name : string -> string
57 val shorten_const_names_in_term : term -> term
58 val type_match : theory -> typ * typ -> bool
59 val const_match : theory -> styp * styp -> bool
60 val term_match : theory -> term * term -> bool
61 val is_TFree : typ -> bool
62 val is_higher_order_type : typ -> bool
63 val is_fun_type : typ -> bool
64 val is_set_type : typ -> bool
65 val is_pair_type : typ -> bool
66 val is_lfp_iterator_type : typ -> bool
67 val is_gfp_iterator_type : typ -> bool
68 val is_fp_iterator_type : typ -> bool
69 val is_boolean_type : typ -> bool
70 val is_integer_type : typ -> bool
71 val is_record_type : typ -> bool
72 val is_number_type : theory -> typ -> bool
73 val const_for_iterator_type : typ -> styp
74 val nth_range_type : int -> typ -> typ
75 val num_factors_in_type : typ -> int
76 val num_binder_types : typ -> int
77 val curried_binder_types : typ -> typ list
78 val mk_flat_tuple : typ -> term list -> term
79 val dest_n_tuple : int -> term -> term list
80 val instantiate_type : theory -> typ -> typ -> typ -> typ
81 val is_codatatype : theory -> typ -> bool
82 val is_pure_typedef : theory -> typ -> bool
83 val is_univ_typedef : theory -> typ -> bool
84 val is_datatype : theory -> typ -> bool
85 val is_record_constr : styp -> bool
86 val is_record_get : theory -> styp -> bool
87 val is_record_update : theory -> styp -> bool
88 val is_abs_fun : theory -> styp -> bool
89 val is_rep_fun : theory -> styp -> bool
90 val is_constr : theory -> styp -> bool
91 val is_stale_constr : theory -> styp -> bool
92 val is_sel : string -> bool
93 val discr_for_constr : styp -> styp
94 val num_sels_for_constr_type : typ -> int
95 val nth_sel_name_for_constr_name : string -> int -> string
96 val nth_sel_for_constr : styp -> int -> styp
97 val boxed_nth_sel_for_constr : extended_context -> styp -> int -> styp
98 val sel_no_from_name : string -> int
99 val eta_expand : typ list -> term -> int -> term
100 val extensionalize : term -> term
101 val distinctness_formula : typ -> term list -> term
102 val register_frac_type : string -> (string * string) list -> theory -> theory
103 val unregister_frac_type : string -> theory -> theory
104 val register_codatatype : typ -> string -> styp list -> theory -> theory
105 val unregister_codatatype : typ -> theory -> theory
106 val datatype_constrs : extended_context -> typ -> styp list
107 val boxed_datatype_constrs : extended_context -> typ -> styp list
108 val num_datatype_constrs : extended_context -> typ -> int
109 val constr_name_for_sel_like : string -> string
110 val boxed_constr_for_sel : extended_context -> styp -> styp
111 val card_of_type : (typ * int) list -> typ -> int
112 val bounded_card_of_type : int -> int -> (typ * int) list -> typ -> int
113 val bounded_precise_card_of_type :
114 extended_context -> int -> int -> (typ * int) list -> typ -> int
115 val is_finite_type : extended_context -> typ -> bool
116 val all_axioms_of : theory -> term list * term list * term list
117 val arity_of_built_in_const : bool -> styp -> int option
118 val is_built_in_const : bool -> styp -> bool
119 val case_const_names : theory -> (string * int) list
120 val const_def_table : Proof.context -> term list -> const_table
121 val const_nondef_table : term list -> const_table
122 val const_simp_table : Proof.context -> const_table
123 val const_psimp_table : Proof.context -> const_table
124 val inductive_intro_table : Proof.context -> const_table -> const_table
125 val ground_theorem_table : theory -> term list Inttab.table
126 val ersatz_table : theory -> (string * string) list
127 val def_of_const : theory -> const_table -> styp -> term option
128 val is_inductive_pred : extended_context -> styp -> bool
129 val is_constr_pattern_lhs : theory -> term -> bool
130 val is_constr_pattern_formula : theory -> term -> bool
131 val merge_type_vars_in_terms : term list -> term list
132 val ground_types_in_type : extended_context -> typ -> typ list
133 val ground_types_in_terms : extended_context -> term list -> typ list
134 val format_type : int list -> int list -> typ -> typ
135 val format_term_type :
136 theory -> const_table -> (term option * int list) list -> term -> typ
137 val user_friendly_const :
138 extended_context -> string * string -> (term option * int list) list
139 -> styp -> term * typ
140 val assign_operator_for_const : styp -> string
141 val preprocess_term :
142 extended_context -> term -> ((term list * term list) * (bool * bool)) * term
145 structure Nitpick_HOL : NITPICK_HOL =
150 type const_table = term list Symtab.table
151 type special_fun = (styp * int list * term list) * styp
152 type unrolled = styp * styp
153 type wf_cache = (styp * (bool * bool)) list
155 type extended_context = {
158 max_bisim_depth: int,
159 boxes: (typ option * bool option) list,
160 wfs: (styp option * bool option) list,
161 user_axioms: bool option,
163 destroy_constrs: bool,
166 star_linear_preds: bool,
169 tac_timeout: Time.time option,
171 case_names: (string * int) list,
172 def_table: const_table,
173 nondef_table: const_table,
174 user_nondefs: term list,
175 simp_table: const_table Unsynchronized.ref,
176 psimp_table: const_table,
177 intro_table: const_table,
178 ground_thm_table: term list Inttab.table,
179 ersatz_table: (string * string) list,
180 skolems: (string * string list) list Unsynchronized.ref,
181 special_funs: special_fun list Unsynchronized.ref,
182 unrolled_preds: unrolled list Unsynchronized.ref,
183 wf_cache: wf_cache Unsynchronized.ref,
184 constr_cache: (typ * styp list) list Unsynchronized.ref}
186 structure Data = Theory_Data(
187 type T = {frac_types: (string * (string * string) list) list,
188 codatatypes: (string * (string * styp list)) list}
189 val empty = {frac_types = [], codatatypes = []}
191 fun merge ({frac_types = fs1, codatatypes = cs1},
192 {frac_types = fs2, codatatypes = cs2}) : T =
193 {frac_types = AList.merge (op =) (K true) (fs1, fs2),
194 codatatypes = AList.merge (op =) (K true) (cs1, cs2)})
196 (* term * term -> term *)
197 fun s_conj (t1, @{const True}) = t1
198 | s_conj (@{const True}, t2) = t2
199 | s_conj (t1, t2) = if @{const False} mem [t1, t2] then @{const False}
200 else HOLogic.mk_conj (t1, t2)
201 fun s_disj (t1, @{const False}) = t1
202 | s_disj (@{const False}, t2) = t2
203 | s_disj (t1, t2) = if @{const True} mem [t1, t2] then @{const True}
204 else HOLogic.mk_disj (t1, t2)
205 (* term -> term -> term *)
207 HOLogic.exists_const (fastype_of v) $ lambda v (incr_boundvars 1 t)
209 (* term -> term -> term list *)
210 fun strip_connective conn_t (t as (t0 $ t1 $ t2)) =
211 if t0 = conn_t then strip_connective t0 t2 @ strip_connective t0 t1 else [t]
212 | strip_connective _ t = [t]
213 (* term -> term list * term *)
214 fun strip_any_connective (t as (t0 $ t1 $ t2)) =
215 if t0 mem [@{const "op &"}, @{const "op |"}] then
216 (strip_connective t0 t, t0)
219 | strip_any_connective t = ([t], @{const Not})
220 (* term -> term list *)
221 val conjuncts = strip_connective @{const "op &"}
222 val disjuncts = strip_connective @{const "op |"}
225 val numeral_prefix = nitpick_prefix ^ "num" ^ name_sep
226 val sel_prefix = nitpick_prefix ^ "sel"
227 val discr_prefix = nitpick_prefix ^ "is" ^ name_sep
228 val set_prefix = nitpick_prefix ^ "set" ^ name_sep
229 val lfp_iterator_prefix = nitpick_prefix ^ "lfpit" ^ name_sep
230 val gfp_iterator_prefix = nitpick_prefix ^ "gfpit" ^ name_sep
231 val nwf_prefix = nitpick_prefix ^ "nwf" ^ name_sep
232 val unrolled_prefix = nitpick_prefix ^ "unroll" ^ name_sep
233 val base_prefix = nitpick_prefix ^ "base" ^ name_sep
234 val step_prefix = nitpick_prefix ^ "step" ^ name_sep
235 val ubfp_prefix = nitpick_prefix ^ "ubfp" ^ name_sep
236 val lbfp_prefix = nitpick_prefix ^ "lbfp" ^ name_sep
237 val skolem_prefix = nitpick_prefix ^ "sk"
238 val special_prefix = nitpick_prefix ^ "sp"
239 val uncurry_prefix = nitpick_prefix ^ "unc"
240 val eval_prefix = nitpick_prefix ^ "eval"
241 val bound_var_prefix = "b"
242 val cong_var_prefix = "c"
243 val iter_var_prefix = "i"
244 val val_var_prefix = nitpick_prefix ^ "v"
245 val arg_var_prefix = "x"
248 fun sel_prefix_for j = sel_prefix ^ string_of_int j ^ name_sep
249 fun special_prefix_for j = special_prefix ^ string_of_int j ^ name_sep
250 (* int -> int -> string *)
251 fun skolem_prefix_for k j =
252 skolem_prefix ^ string_of_int k ^ "@" ^ string_of_int j ^ name_sep
253 fun uncurry_prefix_for k j =
254 uncurry_prefix ^ string_of_int k ^ "@" ^ string_of_int j ^ name_sep
256 (* string -> string * string *)
257 val strip_first_name_sep =
258 Substring.full #> Substring.position name_sep ##> Substring.triml 1
259 #> pairself Substring.string
260 (* string -> string *)
261 fun original_name s =
262 if String.isPrefix nitpick_prefix s then
263 case strip_first_name_sep s of (s1, "") => s1 | (_, s2) => original_name s2
266 val after_name_sep = snd o strip_first_name_sep
268 (* When you add constants to these lists, make sure to handle them in
269 "Nitpick_Nut.nut_from_term", and perhaps in "Nitpick_Mono.consider_term" as
271 val built_in_consts =
272 [(@{const_name all}, 1),
273 (@{const_name "=="}, 2),
274 (@{const_name "==>"}, 2),
275 (@{const_name Pure.conjunction}, 2),
276 (@{const_name Trueprop}, 1),
277 (@{const_name Not}, 1),
278 (@{const_name False}, 0),
279 (@{const_name True}, 0),
280 (@{const_name All}, 1),
281 (@{const_name Ex}, 1),
282 (@{const_name "op ="}, 2),
283 (@{const_name "op &"}, 2),
284 (@{const_name "op |"}, 2),
285 (@{const_name "op -->"}, 2),
286 (@{const_name If}, 3),
287 (@{const_name Let}, 2),
288 (@{const_name Unity}, 0),
289 (@{const_name Pair}, 2),
290 (@{const_name fst}, 1),
291 (@{const_name snd}, 1),
292 (@{const_name Id}, 0),
293 (@{const_name insert}, 2),
294 (@{const_name converse}, 1),
295 (@{const_name trancl}, 1),
296 (@{const_name rel_comp}, 2),
297 (@{const_name image}, 2),
298 (@{const_name Suc}, 0),
299 (@{const_name finite}, 1),
300 (@{const_name nat}, 0),
301 (@{const_name zero_nat_inst.zero_nat}, 0),
302 (@{const_name one_nat_inst.one_nat}, 0),
303 (@{const_name plus_nat_inst.plus_nat}, 0),
304 (@{const_name minus_nat_inst.minus_nat}, 0),
305 (@{const_name times_nat_inst.times_nat}, 0),
306 (@{const_name div_nat_inst.div_nat}, 0),
307 (@{const_name div_nat_inst.mod_nat}, 0),
308 (@{const_name ord_nat_inst.less_nat}, 2),
309 (@{const_name ord_nat_inst.less_eq_nat}, 2),
310 (@{const_name nat_gcd}, 0),
311 (@{const_name nat_lcm}, 0),
312 (@{const_name zero_int_inst.zero_int}, 0),
313 (@{const_name one_int_inst.one_int}, 0),
314 (@{const_name plus_int_inst.plus_int}, 0),
315 (@{const_name minus_int_inst.minus_int}, 0),
316 (@{const_name times_int_inst.times_int}, 0),
317 (@{const_name div_int_inst.div_int}, 0),
318 (@{const_name div_int_inst.mod_int}, 0),
319 (@{const_name uminus_int_inst.uminus_int}, 0),
320 (@{const_name ord_int_inst.less_int}, 2),
321 (@{const_name ord_int_inst.less_eq_int}, 2),
322 (@{const_name Tha}, 1),
323 (@{const_name Frac}, 0),
324 (@{const_name norm_frac}, 0)]
325 val built_in_descr_consts =
326 [(@{const_name The}, 1),
327 (@{const_name Eps}, 1)]
328 val built_in_typed_consts =
329 [((@{const_name of_nat}, nat_T --> int_T), 0)]
330 val built_in_set_consts =
331 [(@{const_name lower_semilattice_fun_inst.inf_fun}, 2),
332 (@{const_name upper_semilattice_fun_inst.sup_fun}, 2),
333 (@{const_name minus_fun_inst.minus_fun}, 2),
334 (@{const_name ord_fun_inst.less_eq_fun}, 2)]
337 fun unbox_type (Type (@{type_name fun_box}, Ts)) =
338 Type ("fun", map unbox_type Ts)
339 | unbox_type (Type (@{type_name pair_box}, Ts)) =
340 Type ("*", map unbox_type Ts)
341 | unbox_type (Type (s, Ts)) = Type (s, map unbox_type Ts)
343 (* Proof.context -> typ -> string *)
344 fun string_for_type ctxt = Syntax.string_of_typ ctxt o unbox_type
346 (* string -> string -> string *)
347 val prefix_name = Long_Name.qualify o Long_Name.base_name
348 (* string -> string *)
349 fun short_name s = List.last (space_explode "." s) handle List.Empty => ""
350 (* string -> term -> term *)
351 val prefix_abs_vars = Term.map_abs_vars o prefix_name
353 val shorten_abs_vars = Term.map_abs_vars short_name
354 (* string -> string *)
355 fun short_const_name s =
356 case space_explode name_sep s of
357 [_] => s |> String.isPrefix nitpick_prefix s ? unprefix nitpick_prefix
358 | ss => map short_name ss |> space_implode "_"
360 val shorten_const_names_in_term =
361 map_aterms (fn Const (s, T) => Const (short_const_name s, T) | t => t)
363 (* theory -> typ * typ -> bool *)
364 fun type_match thy (T1, T2) =
365 (Sign.typ_match thy (T2, T1) Vartab.empty; true)
366 handle Type.TYPE_MATCH => false
367 (* theory -> styp * styp -> bool *)
368 fun const_match thy ((s1, T1), (s2, T2)) =
369 s1 = s2 andalso type_match thy (T1, T2)
370 (* theory -> term * term -> bool *)
371 fun term_match thy (Const x1, Const x2) = const_match thy (x1, x2)
372 | term_match thy (Free (s1, T1), Free (s2, T2)) =
373 const_match thy ((short_name s1, T1), (short_name s2, T2))
374 | term_match thy (t1, t2) = t1 aconv t2
377 fun is_TFree (TFree _) = true
379 fun is_higher_order_type (Type ("fun", _)) = true
380 | is_higher_order_type (Type (_, Ts)) = exists is_higher_order_type Ts
381 | is_higher_order_type _ = false
382 fun is_fun_type (Type ("fun", _)) = true
383 | is_fun_type _ = false
384 fun is_set_type (Type ("fun", [_, @{typ bool}])) = true
385 | is_set_type _ = false
386 fun is_pair_type (Type ("*", _)) = true
387 | is_pair_type _ = false
388 fun is_lfp_iterator_type (Type (s, _)) = String.isPrefix lfp_iterator_prefix s
389 | is_lfp_iterator_type _ = false
390 fun is_gfp_iterator_type (Type (s, _)) = String.isPrefix gfp_iterator_prefix s
391 | is_gfp_iterator_type _ = false
392 val is_fp_iterator_type = is_lfp_iterator_type orf is_gfp_iterator_type
393 val is_boolean_type = equal prop_T orf equal bool_T
394 val is_integer_type =
395 member (op =) [nat_T, int_T, @{typ bisim_iterator}] orf is_fp_iterator_type
396 val is_record_type = not o null o Record.dest_recTs
397 (* theory -> typ -> bool *)
398 fun is_frac_type thy (Type (s, [])) =
399 not (null (these (AList.lookup (op =) (#frac_types (Data.get thy)) s)))
400 | is_frac_type _ _ = false
401 fun is_number_type thy = is_integer_type orf is_frac_type thy
403 (* bool -> styp -> typ *)
404 fun iterator_type_for_const gfp (s, T) =
405 Type ((if gfp then gfp_iterator_prefix else lfp_iterator_prefix) ^ s,
408 fun const_for_iterator_type (Type (s, Ts)) = (after_name_sep s, Ts ---> bool_T)
409 | const_for_iterator_type T =
410 raise TYPE ("Nitpick_HOL.const_for_iterator_type", [T], [])
412 (* int -> typ -> typ * typ *)
413 fun strip_n_binders 0 T = ([], T)
414 | strip_n_binders n (Type ("fun", [T1, T2])) =
415 strip_n_binders (n - 1) T2 |>> cons T1
416 | strip_n_binders n (Type (@{type_name fun_box}, Ts)) =
417 strip_n_binders n (Type ("fun", Ts))
418 | strip_n_binders _ T = raise TYPE ("Nitpick_HOL.strip_n_binders", [T], [])
420 val nth_range_type = snd oo strip_n_binders
423 fun num_factors_in_type (Type ("*", [T1, T2])) =
424 fold (Integer.add o num_factors_in_type) [T1, T2] 0
425 | num_factors_in_type _ = 1
426 fun num_binder_types (Type ("fun", [_, T2])) = 1 + num_binder_types T2
427 | num_binder_types _ = 0
428 (* typ -> typ list *)
429 val curried_binder_types = maps HOLogic.flatten_tupleT o binder_types
430 fun maybe_curried_binder_types T =
431 (if is_pair_type (body_type T) then binder_types else curried_binder_types) T
433 (* typ -> term list -> term *)
434 fun mk_flat_tuple _ [t] = t
435 | mk_flat_tuple (Type ("*", [T1, T2])) (t :: ts) =
436 HOLogic.pair_const T1 T2 $ t $ (mk_flat_tuple T2 ts)
437 | mk_flat_tuple T ts = raise TYPE ("Nitpick_HOL.mk_flat_tuple", [T], ts)
438 (* int -> term -> term list *)
439 fun dest_n_tuple 1 t = [t]
440 | dest_n_tuple n t = HOLogic.dest_prod t ||> dest_n_tuple (n - 1) |> op ::
442 (* int -> typ -> typ list *)
443 fun dest_n_tuple_type 1 T = [T]
444 | dest_n_tuple_type n (Type (_, [T1, T2])) =
445 T1 :: dest_n_tuple_type (n - 1) T2
446 | dest_n_tuple_type _ T =
447 raise TYPE ("Nitpick_HOL.dest_n_tuple_type", [T], [])
449 (* (typ * typ) list -> typ -> typ *)
450 fun typ_subst [] T = T
455 case AList.lookup (op =) ps T of
457 | NONE => case T of Type (s, Ts) => Type (s, map subst Ts) | _ => T
460 (* theory -> typ -> typ -> typ -> typ *)
461 fun instantiate_type thy T1 T1' T2 =
462 Same.commit (Envir.subst_type_same
463 (Sign.typ_match thy (Logic.varifyT T1, T1') Vartab.empty))
465 handle Type.TYPE_MATCH =>
466 raise TYPE ("Nitpick_HOL.instantiate_type", [T1, T1'], [])
468 (* theory -> typ -> typ -> styp *)
469 fun repair_constr_type thy body_T' T =
470 instantiate_type thy (body_type T) body_T' T
472 (* string -> (string * string) list -> theory -> theory *)
473 fun register_frac_type frac_s ersaetze thy =
475 val {frac_types, codatatypes} = Data.get thy
476 val frac_types = AList.update (op =) (frac_s, ersaetze) frac_types
477 in Data.put {frac_types = frac_types, codatatypes = codatatypes} thy end
478 (* string -> theory -> theory *)
479 fun unregister_frac_type frac_s = register_frac_type frac_s []
481 (* typ -> string -> styp list -> theory -> theory *)
482 fun register_codatatype co_T case_name constr_xs thy =
484 val {frac_types, codatatypes} = Data.get thy
485 val constr_xs = map (apsnd (repair_constr_type thy co_T)) constr_xs
486 val (co_s, co_Ts) = dest_Type co_T
488 if forall is_TFree co_Ts andalso not (has_duplicates (op =) co_Ts) then ()
489 else raise TYPE ("Nitpick_HOL.register_codatatype", [co_T], [])
490 val codatatypes = AList.update (op =) (co_s, (case_name, constr_xs))
492 in Data.put {frac_types = frac_types, codatatypes = codatatypes} thy end
493 (* typ -> theory -> theory *)
494 fun unregister_codatatype co_T = register_codatatype co_T "" []
497 {rep_type: typ, abs_type: typ, Rep_name: string, Abs_name: string,
498 set_def: thm option, prop_of_Rep: thm, set_name: string,
499 Rep_inverse: thm option}
501 (* theory -> string -> typedef_info *)
502 fun typedef_info thy s =
503 if is_frac_type thy (Type (s, [])) then
504 SOME {abs_type = Type (s, []), rep_type = @{typ "int * int"},
505 Abs_name = @{const_name Abs_Frac}, Rep_name = @{const_name Rep_Frac},
506 set_def = NONE, prop_of_Rep = @{prop "Rep_Frac x \<in> Frac"}
508 set_name = @{const_name Frac}, Rep_inverse = NONE}
509 else case Typedef.get_info thy s of
510 SOME {abs_type, rep_type, Abs_name, Rep_name, set_def, Rep, Rep_inverse,
512 SOME {abs_type = abs_type, rep_type = rep_type, Abs_name = Abs_name,
513 Rep_name = Rep_name, set_def = set_def, prop_of_Rep = prop_of Rep,
514 set_name = set_prefix ^ s, Rep_inverse = SOME Rep_inverse}
518 fun is_basic_datatype s =
519 s mem [@{type_name "*"}, @{type_name bool}, @{type_name unit},
520 @{type_name nat}, @{type_name int}]
521 (* theory -> string -> bool *)
522 val is_typedef = is_some oo typedef_info
523 val is_real_datatype = is_some oo Datatype.get_info
524 (* theory -> typ -> bool *)
525 fun is_codatatype thy (T as Type (s, _)) =
526 not (null (AList.lookup (op =) (#codatatypes (Data.get thy)) s
527 |> Option.map snd |> these))
528 | is_codatatype _ _ = false
529 fun is_pure_typedef thy (T as Type (s, _)) =
530 is_typedef thy s andalso
531 not (is_real_datatype thy s orelse is_codatatype thy T
532 orelse is_record_type T orelse is_integer_type T)
533 | is_pure_typedef _ _ = false
534 fun is_univ_typedef thy (Type (s, _)) =
535 (case typedef_info thy s of
536 SOME {set_def, prop_of_Rep, ...} =>
539 try (fst o dest_Const o snd o Logic.dest_equals o prop_of) thm
541 try (fst o dest_Const o snd o HOLogic.dest_mem
542 o HOLogic.dest_Trueprop) prop_of_Rep) = SOME @{const_name UNIV}
544 | is_univ_typedef _ _ = false
545 fun is_datatype thy (T as Type (s, _)) =
546 (is_typedef thy s orelse is_codatatype thy T orelse T = @{typ ind})
547 andalso not (is_basic_datatype s)
548 | is_datatype _ _ = false
550 (* theory -> typ -> (string * typ) list * (string * typ) *)
551 fun all_record_fields thy T =
552 let val (recs, more) = Record.get_extT_fields thy T in
553 recs @ more :: all_record_fields thy (snd more)
557 fun is_record_constr (x as (s, T)) =
558 String.isSuffix Record.extN s andalso
559 let val dataT = body_type T in
560 is_record_type dataT andalso
561 s = unsuffix Record.ext_typeN (fst (dest_Type dataT)) ^ Record.extN
563 (* theory -> typ -> int *)
564 val num_record_fields = Integer.add 1 o length o fst oo Record.get_extT_fields
565 (* theory -> string -> typ -> int *)
566 fun no_of_record_field thy s T1 =
567 find_index (equal s o fst) (Record.get_extT_fields thy T1 ||> single |> op @)
568 (* theory -> styp -> bool *)
569 fun is_record_get thy (s, Type ("fun", [T1, _])) =
570 exists (equal s o fst) (all_record_fields thy T1)
571 | is_record_get _ _ = false
572 fun is_record_update thy (s, T) =
573 String.isSuffix Record.updateN s andalso
574 exists (equal (unsuffix Record.updateN s) o fst)
575 (all_record_fields thy (body_type T))
576 handle TYPE _ => false
577 fun is_abs_fun thy (s, Type ("fun", [_, Type (s', _)])) =
578 (case typedef_info thy s' of
579 SOME {Abs_name, ...} => s = Abs_name
581 | is_abs_fun _ _ = false
582 fun is_rep_fun thy (s, Type ("fun", [Type (s', _), _])) =
583 (case typedef_info thy s' of
584 SOME {Rep_name, ...} => s = Rep_name
586 | is_rep_fun _ _ = false
588 (* theory -> styp -> styp *)
589 fun mate_of_rep_fun thy (x as (_, Type ("fun", [T1 as Type (s', _), T2]))) =
590 (case typedef_info thy s' of
591 SOME {Abs_name, ...} => (Abs_name, Type ("fun", [T2, T1]))
592 | NONE => raise TERM ("Nitpick_HOL.mate_of_rep_fun", [Const x]))
593 | mate_of_rep_fun _ x = raise TERM ("Nitpick_HOL.mate_of_rep_fun", [Const x])
595 (* theory -> styp -> bool *)
596 fun is_coconstr thy (s, T) =
598 val {codatatypes, ...} = Data.get thy
599 val co_T = body_type T
600 val co_s = dest_Type co_T |> fst
602 exists (fn (s', T') => s = s' andalso repair_constr_type thy co_T T' = T)
603 (AList.lookup (op =) codatatypes co_s |> Option.map snd |> these)
605 handle TYPE ("dest_Type", _, _) => false
606 fun is_constr_like thy (s, T) =
607 s mem [@{const_name FunBox}, @{const_name PairBox}] orelse
608 let val (x as (s, T)) = (s, unbox_type T) in
609 Refute.is_IDT_constructor thy x orelse is_record_constr x
610 orelse (is_abs_fun thy x andalso is_pure_typedef thy (range_type T))
611 orelse s mem [@{const_name Zero_Rep}, @{const_name Suc_Rep}]
612 orelse x = (@{const_name zero_nat_inst.zero_nat}, nat_T)
613 orelse is_coconstr thy x
615 fun is_stale_constr thy (x as (_, T)) =
616 is_codatatype thy (body_type T) andalso is_constr_like thy x
617 andalso not (is_coconstr thy x)
618 fun is_constr thy (x as (_, T)) =
620 andalso not (is_basic_datatype (fst (dest_Type (body_type T))))
621 andalso not (is_stale_constr thy x)
623 val is_sel = String.isPrefix discr_prefix orf String.isPrefix sel_prefix
624 val is_sel_like_and_no_discr =
625 String.isPrefix sel_prefix
626 orf (member (op =) [@{const_name fst}, @{const_name snd}])
628 datatype boxability =
629 InConstr | InSel | InExpr | InPair | InFunLHS | InFunRHS1 | InFunRHS2
631 (* boxability -> boxability *)
632 fun in_fun_lhs_for InConstr = InSel
633 | in_fun_lhs_for _ = InFunLHS
634 fun in_fun_rhs_for InConstr = InConstr
635 | in_fun_rhs_for InSel = InSel
636 | in_fun_rhs_for InFunRHS1 = InFunRHS2
637 | in_fun_rhs_for _ = InFunRHS1
639 (* extended_context -> boxability -> typ -> bool *)
640 fun is_boxing_worth_it (ext_ctxt : extended_context) boxy T =
643 boxy mem [InPair, InFunLHS] andalso not (is_boolean_type (body_type T))
645 boxy mem [InPair, InFunRHS1, InFunRHS2]
646 orelse (boxy mem [InExpr, InFunLHS]
647 andalso exists (is_boxing_worth_it ext_ctxt InPair)
648 (map (box_type ext_ctxt InPair) Ts))
650 (* extended_context -> boxability -> string * typ list -> string *)
651 and should_box_type (ext_ctxt as {thy, boxes, ...}) boxy (z as (s, Ts)) =
652 case triple_lookup (type_match thy) boxes (Type z) of
653 SOME (SOME box_me) => box_me
654 | _ => is_boxing_worth_it ext_ctxt boxy (Type z)
655 (* extended_context -> boxability -> typ -> typ *)
656 and box_type ext_ctxt boxy T =
658 Type (z as ("fun", [T1, T2])) =>
659 if not (boxy mem [InConstr, InSel])
660 andalso should_box_type ext_ctxt boxy z then
661 Type (@{type_name fun_box},
662 [box_type ext_ctxt InFunLHS T1, box_type ext_ctxt InFunRHS1 T2])
664 box_type ext_ctxt (in_fun_lhs_for boxy) T1
665 --> box_type ext_ctxt (in_fun_rhs_for boxy) T2
666 | Type (z as ("*", Ts)) =>
667 if should_box_type ext_ctxt boxy z then
668 Type (@{type_name pair_box}, map (box_type ext_ctxt InSel) Ts)
670 Type ("*", map (box_type ext_ctxt
671 (if boxy mem [InConstr, InSel] then boxy
676 fun discr_for_constr (s, T) = (discr_prefix ^ s, body_type T --> bool_T)
679 fun num_sels_for_constr_type T = length (maybe_curried_binder_types T)
680 (* string -> int -> string *)
681 fun nth_sel_name_for_constr_name s n =
682 if s = @{const_name Pair} then
683 if n = 0 then @{const_name fst} else @{const_name snd}
686 (* styp -> int -> styp *)
687 fun nth_sel_for_constr x ~1 = discr_for_constr x
688 | nth_sel_for_constr (s, T) n =
689 (nth_sel_name_for_constr_name s n,
690 body_type T --> nth (maybe_curried_binder_types T) n)
691 (* extended_context -> styp -> int -> styp *)
692 fun boxed_nth_sel_for_constr ext_ctxt =
693 apsnd (box_type ext_ctxt InSel) oo nth_sel_for_constr
696 fun sel_no_from_name s =
697 if String.isPrefix discr_prefix s then
699 else if String.isPrefix sel_prefix s then
700 s |> unprefix sel_prefix |> Int.fromString |> the
701 else if s = @{const_name snd} then
706 (* typ list -> term -> int -> term *)
707 fun eta_expand _ t 0 = t
708 | eta_expand Ts (Abs (s, T, t')) n =
709 Abs (s, T, eta_expand (T :: Ts) t' (n - 1))
710 | eta_expand Ts t n =
711 fold_rev (curry3 Abs ("x\<^isub>\<eta>" ^ nat_subscript n))
712 (List.take (binder_types (fastype_of1 (Ts, t)), n))
713 (list_comb (incr_boundvars n t, map Bound (n - 1 downto 0)))
716 fun extensionalize t =
718 (t0 as @{const Trueprop}) $ t1 => t0 $ extensionalize t1
719 | Const (@{const_name "op ="}, _) $ t1 $ Abs (s, T, t2) =>
720 let val v = Var ((s, maxidx_of_term t + 1), T) in
721 extensionalize (HOLogic.mk_eq (t1 $ v, subst_bound (v, t2)))
725 (* typ -> term list -> term *)
726 fun distinctness_formula T =
727 all_distinct_unordered_pairs_of
728 #> map (fn (t1, t2) => @{const Not} $ (HOLogic.eq_const T $ t1 $ t2))
729 #> List.foldr (s_conj o swap) @{const True}
732 fun zero_const T = Const (@{const_name zero_nat_inst.zero_nat}, T)
733 fun suc_const T = Const (@{const_name Suc}, T --> T)
735 (* theory -> typ -> styp list *)
736 fun uncached_datatype_constrs thy (T as Type (s, Ts)) =
737 (case AList.lookup (op =) (#codatatypes (Data.get thy)) s of
738 SOME (_, xs' as (_ :: _)) =>
739 map (apsnd (repair_constr_type thy T)) xs'
741 if is_datatype thy T then
742 case Datatype.get_info thy s of
743 SOME {index, descr, ...} =>
745 val (_, dtyps, constrs) = AList.lookup (op =) descr index |> the
748 (s', map (Refute.typ_of_dtyp descr (dtyps ~~ Ts)) Us
752 if is_record_type T then
754 val s' = unsuffix Record.ext_typeN s ^ Record.extN
755 val T' = (Record.get_extT_fields thy T
756 |> apsnd single |> uncurry append |> map snd) ---> T
758 else case typedef_info thy s of
759 SOME {abs_type, rep_type, Abs_name, ...} =>
760 [(Abs_name, instantiate_type thy abs_type T rep_type --> T)]
762 if T = @{typ ind} then
763 [dest_Const @{const Zero_Rep}, dest_Const @{const Suc_Rep}]
768 | uncached_datatype_constrs _ _ = []
769 (* extended_context -> typ -> styp list *)
770 fun datatype_constrs (ext_ctxt as {thy, constr_cache, ...} : extended_context)
772 case AList.lookup (op =) (!constr_cache) T of
775 let val xs = uncached_datatype_constrs thy T in
776 (Unsynchronized.change constr_cache (cons (T, xs)); xs)
778 fun boxed_datatype_constrs ext_ctxt =
779 map (apsnd (box_type ext_ctxt InConstr)) o datatype_constrs ext_ctxt
780 (* extended_context -> typ -> int *)
781 val num_datatype_constrs = length oo datatype_constrs
783 (* string -> string *)
784 fun constr_name_for_sel_like @{const_name fst} = @{const_name Pair}
785 | constr_name_for_sel_like @{const_name snd} = @{const_name Pair}
786 | constr_name_for_sel_like s' = original_name s'
787 (* extended_context -> styp -> styp *)
788 fun boxed_constr_for_sel ext_ctxt (s', T') =
789 let val s = constr_name_for_sel_like s' in
790 AList.lookup (op =) (boxed_datatype_constrs ext_ctxt (domain_type T')) s
793 (* extended_context -> styp -> term *)
794 fun discr_term_for_constr ext_ctxt (x as (s, T)) =
795 let val dataT = body_type T in
796 if s = @{const_name Suc} then
798 @{const Not} $ HOLogic.mk_eq (zero_const dataT, Bound 0))
799 else if num_datatype_constrs ext_ctxt dataT >= 2 then
800 Const (discr_for_constr x)
802 Abs (Name.uu, dataT, @{const True})
805 (* extended_context -> styp -> term -> term *)
806 fun discriminate_value (ext_ctxt as {thy, ...}) (x as (_, T)) t =
809 if x = x' then @{const True}
810 else if is_constr_like thy x' then @{const False}
811 else betapply (discr_term_for_constr ext_ctxt x, t)
812 | _ => betapply (discr_term_for_constr ext_ctxt x, t)
814 (* styp -> term -> term *)
815 fun nth_arg_sel_term_for_constr (x as (s, T)) n =
816 let val (arg_Ts, dataT) = strip_type T in
817 if dataT = nat_T then
818 @{term "%n::nat. minus_nat_inst.minus_nat n one_nat_inst.one_nat"}
819 else if is_pair_type dataT then
820 Const (nth_sel_for_constr x n)
823 (* int -> typ -> int * term *)
824 fun aux m (Type ("*", [T1, T2])) =
826 val (m, t1) = aux m T1
827 val (m, t2) = aux m T2
828 in (m, HOLogic.mk_prod (t1, t2)) end
830 (m + 1, Const (nth_sel_name_for_constr_name s m, dataT --> T)
832 val m = fold (Integer.add o num_factors_in_type)
833 (List.take (arg_Ts, n)) 0
834 in Abs ("x", dataT, aux m (nth arg_Ts n) |> snd) end
836 (* theory -> styp -> term -> int -> typ -> term *)
837 fun select_nth_constr_arg thy x t n res_T =
840 if x = x' then nth args n
841 else if is_constr_like thy x' then Const (@{const_name unknown}, res_T)
842 else betapply (nth_arg_sel_term_for_constr x n, t)
843 | _ => betapply (nth_arg_sel_term_for_constr x n, t)
845 (* theory -> styp -> term list -> term *)
846 fun construct_value _ x [] = Const x
847 | construct_value thy (x as (s, _)) args =
848 let val args = map Envir.eta_contract args in
850 Const (x' as (s', _)) $ t =>
851 if is_sel_like_and_no_discr s' andalso constr_name_for_sel_like s' = s
852 andalso forall (fn (n, t') =>
853 select_nth_constr_arg thy x t n dummyT = t')
854 (index_seq 0 (length args) ~~ args) then
857 list_comb (Const x, args)
858 | _ => list_comb (Const x, args)
861 (* extended_context -> typ -> term -> term *)
862 fun constr_expand (ext_ctxt as {thy, ...}) T t =
864 Const x => if is_constr_like thy x then t else raise SAME ()
865 | _ => raise SAME ())
869 if is_pair_type T then
870 let val (T1, T2) = HOLogic.dest_prodT T in
871 (@{const_name Pair}, [T1, T2] ---> T)
874 datatype_constrs ext_ctxt T |> the_single
875 val arg_Ts = binder_types T'
877 list_comb (Const x', map2 (select_nth_constr_arg thy x' t)
878 (index_seq 0 (length arg_Ts)) arg_Ts)
881 (* (typ * int) list -> typ -> int *)
882 fun card_of_type asgns (Type ("fun", [T1, T2])) =
883 reasonable_power (card_of_type asgns T2) (card_of_type asgns T1)
884 | card_of_type asgns (Type ("*", [T1, T2])) =
885 card_of_type asgns T1 * card_of_type asgns T2
886 | card_of_type _ (Type (@{type_name itself}, _)) = 1
887 | card_of_type _ @{typ prop} = 2
888 | card_of_type _ @{typ bool} = 2
889 | card_of_type _ @{typ unit} = 1
890 | card_of_type asgns T =
891 case AList.lookup (op =) asgns T of
893 | NONE => if T = @{typ bisim_iterator} then 0
894 else raise TYPE ("Nitpick_HOL.card_of_type", [T], [])
895 (* int -> (typ * int) list -> typ -> int *)
896 fun bounded_card_of_type max default_card asgns (Type ("fun", [T1, T2])) =
898 val k1 = bounded_card_of_type max default_card asgns T1
899 val k2 = bounded_card_of_type max default_card asgns T2
901 if k1 = max orelse k2 = max then max
902 else Int.min (max, reasonable_power k2 k1)
904 | bounded_card_of_type max default_card asgns (Type ("*", [T1, T2])) =
906 val k1 = bounded_card_of_type max default_card asgns T1
907 val k2 = bounded_card_of_type max default_card asgns T2
908 in if k1 = max orelse k2 = max then max else Int.min (max, k1 * k2) end
909 | bounded_card_of_type max default_card asgns T =
910 Int.min (max, if default_card = ~1 then
914 handle TYPE ("Nitpick_HOL.card_of_type", _, _) =>
916 (* extended_context -> int -> (typ * int) list -> typ -> int *)
917 fun bounded_precise_card_of_type ext_ctxt max default_card asgns T =
919 (* typ list -> typ -> int *)
924 Type ("fun", [T1, T2]) =>
926 val k1 = aux avoid T1
927 val k2 = aux avoid T2
929 if k1 = 0 orelse k2 = 0 then 0
930 else if k1 >= max orelse k2 >= max then max
931 else Int.min (max, reasonable_power k2 k1)
933 | Type ("*", [T1, T2]) =>
935 val k1 = aux avoid T1
936 val k2 = aux avoid T2
938 if k1 = 0 orelse k2 = 0 then 0
939 else if k1 >= max orelse k2 >= max then max
940 else Int.min (max, k1 * k2)
942 | Type (@{type_name itself}, _) => 1
947 (case datatype_constrs ext_ctxt T of
948 [] => if is_integer_type T then 0 else raise SAME ()
952 datatype_constrs ext_ctxt T
953 |> map (Integer.prod o map (aux (T :: avoid)) o binder_types
956 if exists (equal 0) constr_cards then 0
957 else Integer.sum constr_cards
959 | _ => raise SAME ())
960 handle SAME () => AList.lookup (op =) asgns T |> the_default default_card
961 in Int.min (max, aux [] T) end
963 (* extended_context -> typ -> bool *)
964 fun is_finite_type ext_ctxt =
965 not_equal 0 o bounded_precise_card_of_type ext_ctxt 1 2 []
968 fun is_ground_term (t1 $ t2) = is_ground_term t1 andalso is_ground_term t2
969 | is_ground_term (Const _) = true
970 | is_ground_term _ = false
972 (* term -> word -> word *)
973 fun hashw_term (t1 $ t2) = Polyhash.hashw (hashw_term t1, hashw_term t2)
974 | hashw_term (Const (s, _)) = Polyhash.hashw_string (s, 0w0)
977 val hash_term = Word.toInt o hashw_term
979 (* term list -> (indexname * typ) list *)
980 fun special_bounds ts =
981 fold Term.add_vars ts [] |> sort (TermOrd.fast_indexname_ord o pairself fst)
983 (* indexname * typ -> term -> term *)
984 fun abs_var ((s, j), T) body = Abs (s, T, abstract_over (Var ((s, j), T), body))
986 (* theory -> string -> bool *)
987 fun is_funky_typedef_name thy s =
988 s mem [@{type_name unit}, @{type_name "*"}, @{type_name "+"},
990 orelse is_frac_type thy (Type (s, []))
991 (* theory -> term -> bool *)
992 fun is_funky_typedef thy (Type (s, _)) = is_funky_typedef_name thy s
993 | is_funky_typedef _ _ = false
995 fun is_arity_type_axiom (Const (@{const_name HOL.type_class}, _)
996 $ Const (@{const_name TYPE}, _)) = true
997 | is_arity_type_axiom _ = false
998 (* theory -> bool -> term -> bool *)
999 fun is_typedef_axiom thy boring (@{const "==>"} $ _ $ t2) =
1000 is_typedef_axiom thy boring t2
1001 | is_typedef_axiom thy boring
1002 (@{const Trueprop} $ (Const (@{const_name Typedef.type_definition}, _)
1003 $ Const (_, Type ("fun", [Type (s, _), _])) $ Const _ $ _)) =
1004 boring <> is_funky_typedef_name thy s andalso is_typedef thy s
1005 | is_typedef_axiom _ _ _ = false
1007 (* Distinguishes between (1) constant definition axioms, (2) type arity and
1008 typedef axioms, and (3) other axioms, and returns the pair ((1), (3)).
1009 Typedef axioms are uninteresting to Nitpick, because it can retrieve them
1010 using "typedef_info". *)
1011 (* theory -> (string * term) list -> string list -> term list * term list *)
1012 fun partition_axioms_by_definitionality thy axioms def_names =
1014 val axioms = sort (fast_string_ord o pairself fst) axioms
1015 val defs = OrdList.inter (fast_string_ord o apsnd fst) def_names axioms
1017 OrdList.subtract (fast_string_ord o apsnd fst) def_names axioms
1018 |> filter_out ((is_arity_type_axiom orf is_typedef_axiom thy true) o snd)
1019 in pairself (map snd) (defs, nondefs) end
1021 (* Ideally we would check against "Complex_Main", not "Refute", but any theory
1022 will do as long as it contains all the "axioms" and "axiomatization"
1024 (* theory -> bool *)
1025 fun is_built_in_theory thy = Theory.subthy (thy, @{theory Refute})
1028 val is_plain_definition =
1032 case strip_comb t1 of
1033 (Const _, args) => forall is_Var args
1034 andalso not (has_duplicates (op =) args)
1036 fun do_eq (Const (@{const_name "=="}, _) $ t1 $ _) = do_lhs t1
1037 | do_eq (@{const Trueprop} $ (Const (@{const_name "op ="}, _) $ t1 $ _)) =
1042 (* theory -> term list * term list * term list *)
1043 fun all_axioms_of thy =
1045 (* theory list -> term list *)
1046 val axioms_of_thys = maps Thm.axioms_of #> map (apsnd prop_of)
1047 val specs = Defs.all_specifications_of (Theory.defs_of thy)
1048 val def_names = specs |> maps snd |> map_filter #def
1049 |> OrdList.make fast_string_ord
1050 val thys = thy :: Theory.ancestors_of thy
1051 val (built_in_thys, user_thys) = List.partition is_built_in_theory thys
1052 val built_in_axioms = axioms_of_thys built_in_thys
1053 val user_axioms = axioms_of_thys user_thys
1054 val (built_in_defs, built_in_nondefs) =
1055 partition_axioms_by_definitionality thy built_in_axioms def_names
1056 ||> filter (is_typedef_axiom thy false)
1057 val (user_defs, user_nondefs) =
1058 partition_axioms_by_definitionality thy user_axioms def_names
1059 val (built_in_nondefs, user_nondefs) =
1060 List.partition (is_typedef_axiom thy false) user_nondefs
1061 |>> append built_in_nondefs
1062 val defs = (thy |> PureThy.all_thms_of
1063 |> filter (equal Thm.definitionK o Thm.get_kind o snd)
1064 |> map (prop_of o snd) |> filter is_plain_definition) @
1065 user_defs @ built_in_defs
1066 in (defs, built_in_nondefs, user_nondefs) end
1068 (* bool -> styp -> int option *)
1069 fun arity_of_built_in_const fast_descrs (s, T) =
1070 if s = @{const_name If} then
1071 if nth_range_type 3 T = @{typ bool} then NONE else SOME 3
1072 else case AList.lookup (op =)
1074 |> fast_descrs ? append built_in_descr_consts) s of
1077 case AList.lookup (op =) built_in_typed_consts (s, T) of
1080 if is_fun_type T andalso is_set_type (domain_type T) then
1081 AList.lookup (op =) built_in_set_consts s
1084 (* bool -> styp -> bool *)
1085 val is_built_in_const = is_some oo arity_of_built_in_const
1087 (* This function is designed to work for both real definition axioms and
1088 simplification rules (equational specifications). *)
1090 fun term_under_def t =
1092 @{const "==>"} $ _ $ t2 => term_under_def t2
1093 | Const (@{const_name "=="}, _) $ t1 $ _ => term_under_def t1
1094 | @{const Trueprop} $ t1 => term_under_def t1
1095 | Const (@{const_name "op ="}, _) $ t1 $ _ => term_under_def t1
1096 | Abs (_, _, t') => term_under_def t'
1097 | t1 $ _ => term_under_def t1
1100 (* Here we crucially rely on "Refute.specialize_type" performing a preorder
1101 traversal of the term, without which the wrong occurrence of a constant could
1102 be matched in the face of overloading. *)
1103 (* theory -> bool -> const_table -> styp -> term list *)
1104 fun def_props_for_const thy fast_descrs table (x as (s, _)) =
1105 if is_built_in_const fast_descrs x then
1108 these (Symtab.lookup table s)
1109 |> map_filter (try (Refute.specialize_type thy x))
1110 |> filter (equal (Const x) o term_under_def)
1112 (* theory -> term -> term option *)
1113 fun normalized_rhs_of thy t =
1115 (* term option -> term option *)
1116 fun aux (v as Var _) (SOME t) = SOME (lambda v t)
1117 | aux (c as Const (@{const_name TYPE}, T)) (SOME t) = SOME (lambda c t)
1121 Const (@{const_name "=="}, _) $ t1 $ t2 => (t1, t2)
1122 | @{const Trueprop} $ (Const (@{const_name "op ="}, _) $ t1 $ t2) =>
1124 | _ => raise TERM ("Nitpick_HOL.normalized_rhs_of", [t])
1125 val args = strip_comb lhs |> snd
1126 in fold_rev aux args (SOME rhs) end
1128 (* theory -> const_table -> styp -> term option *)
1129 fun def_of_const thy table (x as (s, _)) =
1130 if is_built_in_const false x orelse original_name s <> s then
1133 x |> def_props_for_const thy false table |> List.last
1134 |> normalized_rhs_of thy |> Option.map (prefix_abs_vars s)
1135 handle List.Empty => NONE
1137 datatype fixpoint_kind = Lfp | Gfp | NoFp
1139 (* term -> fixpoint_kind *)
1140 fun fixpoint_kind_of_rhs (Abs (_, _, t)) = fixpoint_kind_of_rhs t
1141 | fixpoint_kind_of_rhs (Const (@{const_name lfp}, _) $ Abs _) = Lfp
1142 | fixpoint_kind_of_rhs (Const (@{const_name gfp}, _) $ Abs _) = Gfp
1143 | fixpoint_kind_of_rhs _ = NoFp
1145 (* theory -> const_table -> term -> bool *)
1146 fun is_mutually_inductive_pred_def thy table t =
1149 fun is_good_arg (Bound _) = true
1150 | is_good_arg (Const (s, _)) =
1151 s mem [@{const_name True}, @{const_name False}, @{const_name undefined}]
1152 | is_good_arg _ = false
1154 case t |> strip_abs_body |> strip_comb of
1155 (Const x, ts as (_ :: _)) =>
1156 (case def_of_const thy table x of
1157 SOME t' => fixpoint_kind_of_rhs t' <> NoFp andalso forall is_good_arg ts
1161 (* theory -> const_table -> term -> term *)
1162 fun unfold_mutually_inductive_preds thy table =
1163 map_aterms (fn t as Const x =>
1164 (case def_of_const thy table x of
1166 let val t' = Envir.eta_contract t' in
1167 if is_mutually_inductive_pred_def thy table t' then t'
1173 (* term -> string * term *)
1174 fun pair_for_prop t =
1175 case term_under_def t of
1176 Const (s, _) => (s, t)
1177 | Free _ => raise NOT_SUPPORTED "local definitions"
1178 | t' => raise TERM ("Nitpick_HOL.pair_for_prop", [t, t'])
1180 (* (Proof.context -> term list) -> Proof.context -> const_table *)
1181 fun table_for get ctxt =
1182 get ctxt |> map pair_for_prop |> AList.group (op =) |> Symtab.make
1184 (* theory -> (string * int) list *)
1185 fun case_const_names thy =
1186 Symtab.fold (fn (dtype_s, {index, descr, case_name, ...}) =>
1187 if is_basic_datatype dtype_s then
1190 cons (case_name, AList.lookup (op =) descr index
1191 |> the |> #3 |> length))
1192 (Datatype.get_all thy) [] @
1193 map (apsnd length o snd) (#codatatypes (Data.get thy))
1195 (* Proof.context -> term list -> const_table *)
1196 fun const_def_table ctxt ts =
1197 table_for (map prop_of o Nitpick_Defs.get) ctxt
1198 |> fold (fn (s, t) => Symtab.map_default (s, []) (cons t))
1199 (map pair_for_prop ts)
1200 (* term list -> const_table *)
1201 fun const_nondef_table ts =
1202 fold (fn t => append (map (fn s => (s, t)) (Term.add_const_names t []))) ts []
1203 |> AList.group (op =) |> Symtab.make
1204 (* Proof.context -> const_table *)
1205 val const_simp_table = table_for (map prop_of o Nitpick_Simps.get)
1206 val const_psimp_table = table_for (map prop_of o Nitpick_Psimps.get)
1207 (* Proof.context -> const_table -> const_table *)
1208 fun inductive_intro_table ctxt def_table =
1209 table_for (map (unfold_mutually_inductive_preds (ProofContext.theory_of ctxt)
1210 def_table o prop_of)
1211 o Nitpick_Intros.get) ctxt
1212 (* theory -> term list Inttab.table *)
1213 fun ground_theorem_table thy =
1214 fold ((fn @{const Trueprop} $ t1 =>
1215 is_ground_term t1 ? Inttab.map_default (hash_term t1, []) (cons t1)
1216 | _ => I) o prop_of o snd) (PureThy.all_thms_of thy) Inttab.empty
1218 val basic_ersatz_table =
1219 [(@{const_name prod_case}, @{const_name split}),
1220 (@{const_name card}, @{const_name card'}),
1221 (@{const_name setsum}, @{const_name setsum'}),
1222 (@{const_name fold_graph}, @{const_name fold_graph'}),
1223 (@{const_name wf}, @{const_name wf'}),
1224 (@{const_name wf_wfrec}, @{const_name wf_wfrec'}),
1225 (@{const_name wfrec}, @{const_name wfrec'})]
1227 (* theory -> (string * string) list *)
1228 fun ersatz_table thy =
1229 fold (append o snd) (#frac_types (Data.get thy)) basic_ersatz_table
1231 (* const_table Unsynchronized.ref -> string -> term list -> unit *)
1232 fun add_simps simp_table s eqs =
1233 Unsynchronized.change simp_table
1234 (Symtab.update (s, eqs @ these (Symtab.lookup (!simp_table) s)))
1236 (* Similar to "Refute.specialize_type" but returns all matches rather than only
1237 the first (preorder) match. *)
1238 (* theory -> styp -> term -> term list *)
1239 fun multi_specialize_type thy slack (x as (s, T)) t =
1241 (* term -> (typ * term) list -> (typ * term) list *)
1242 fun aux (Const (s', T')) ys =
1244 ys |> (if AList.defined (op =) ys T' then
1247 cons (T', Refute.monomorphic_term
1248 (Sign.typ_match thy (T', T) Vartab.empty) t)
1249 handle Type.TYPE_MATCH => I
1250 | Refute.REFUTE _ =>
1254 raise NOT_SUPPORTED ("too much polymorphism in \
1255 \axiom involving " ^ quote s))
1259 in map snd (fold_aterms aux t []) end
1261 (* theory -> bool -> const_table -> styp -> term list *)
1262 fun nondef_props_for_const thy slack table (x as (s, _)) =
1263 these (Symtab.lookup table s) |> maps (multi_specialize_type thy slack x)
1265 (* theory -> styp list -> term list *)
1266 fun optimized_typedef_axioms thy (abs_s, abs_Ts) =
1267 let val abs_T = Type (abs_s, abs_Ts) in
1268 if is_univ_typedef thy abs_T then
1270 else case typedef_info thy abs_s of
1271 SOME {abs_type, rep_type, Abs_name, Rep_name, prop_of_Rep, set_name,
1274 val rep_T = instantiate_type thy abs_type abs_T rep_type
1275 val rep_t = Const (Rep_name, abs_T --> rep_T)
1276 val set_t = Const (set_name, rep_T --> bool_T)
1278 prop_of_Rep |> HOLogic.dest_Trueprop
1279 |> Refute.specialize_type thy (dest_Const rep_t)
1280 |> HOLogic.dest_mem |> snd
1282 [HOLogic.all_const abs_T
1283 $ Abs (Name.uu, abs_T, set_t $ (rep_t $ Bound 0))]
1284 |> set_t <> set_t' ? cons (HOLogic.mk_eq (set_t, set_t'))
1285 |> map HOLogic.mk_Trueprop
1289 (* theory -> styp -> term *)
1290 fun inverse_axiom_for_rep_fun thy (x as (_, T)) =
1291 typedef_info thy (fst (dest_Type (domain_type T)))
1292 |> the |> #Rep_inverse |> the |> prop_of |> Refute.specialize_type thy x
1294 (* theory -> int * styp -> term *)
1295 fun constr_case_body thy (j, (x as (_, T))) =
1296 let val arg_Ts = binder_types T in
1297 list_comb (Bound j, map2 (select_nth_constr_arg thy x (Bound 0))
1298 (index_seq 0 (length arg_Ts)) arg_Ts)
1300 (* extended_context -> typ -> int * styp -> term -> term *)
1301 fun add_constr_case (ext_ctxt as {thy, ...}) res_T (j, x) res_t =
1302 Const (@{const_name If}, [bool_T, res_T, res_T] ---> res_T)
1303 $ discriminate_value ext_ctxt x (Bound 0) $ constr_case_body thy (j, x)
1305 (* extended_context -> typ -> typ -> term *)
1306 fun optimized_case_def (ext_ctxt as {thy, ...}) dataT res_T =
1308 val xs = datatype_constrs ext_ctxt dataT
1309 val func_Ts = map ((fn T => binder_types T ---> res_T) o snd) xs
1310 val (xs', x) = split_last xs
1312 constr_case_body thy (1, x)
1313 |> fold_rev (add_constr_case ext_ctxt res_T) (length xs downto 2 ~~ xs')
1314 |> fold_rev (curry absdummy) (func_Ts @ [dataT])
1317 (* extended_context -> string -> typ -> typ -> term -> term *)
1318 fun optimized_record_get (ext_ctxt as {thy, ...}) s rec_T res_T t =
1319 let val constr_x = the_single (datatype_constrs ext_ctxt rec_T) in
1320 case no_of_record_field thy s rec_T of
1321 ~1 => (case rec_T of
1322 Type (_, Ts as _ :: _) =>
1324 val rec_T' = List.last Ts
1325 val j = num_record_fields thy rec_T - 1
1327 select_nth_constr_arg thy constr_x t j res_T
1328 |> optimized_record_get ext_ctxt s rec_T' res_T
1330 | _ => raise TYPE ("Nitpick_HOL.optimized_record_get", [rec_T],
1332 | j => select_nth_constr_arg thy constr_x t j res_T
1334 (* extended_context -> string -> typ -> term -> term -> term *)
1335 fun optimized_record_update (ext_ctxt as {thy, ...}) s rec_T fun_t rec_t =
1337 val constr_x as (_, constr_T) = the_single (datatype_constrs ext_ctxt rec_T)
1338 val Ts = binder_types constr_T
1340 val special_j = no_of_record_field thy s rec_T
1341 val ts = map2 (fn j => fn T =>
1343 val t = select_nth_constr_arg thy constr_x rec_t j T
1345 if j = special_j then
1347 else if j = n - 1 andalso special_j = ~1 then
1348 optimized_record_update ext_ctxt s
1349 (rec_T |> dest_Type |> snd |> List.last) fun_t t
1352 end) (index_seq 0 n) Ts
1353 in list_comb (Const constr_x, ts) end
1355 (* Constants "c" whose definition is of the form "c == c'", where "c'" is also a
1356 constant, are said to be trivial. For those, we ignore the simplification
1357 rules and use the definition instead, to ensure that built-in symbols like
1358 "ord_nat_inst.less_eq_nat" are picked up correctly. *)
1359 (* theory -> const_table -> styp -> bool *)
1360 fun has_trivial_definition thy table x =
1361 case def_of_const thy table x of SOME (Const _) => true | _ => false
1363 (* theory -> const_table -> string * typ -> fixpoint_kind *)
1364 fun fixpoint_kind_of_const thy table x =
1365 if is_built_in_const false x then
1368 fixpoint_kind_of_rhs (the (def_of_const thy table x))
1369 handle Option.Option => NoFp
1371 (* extended_context -> styp -> bool *)
1372 fun is_real_inductive_pred ({thy, fast_descrs, def_table, intro_table, ...}
1373 : extended_context) x =
1374 not (null (def_props_for_const thy fast_descrs intro_table x))
1375 andalso fixpoint_kind_of_const thy def_table x <> NoFp
1376 fun is_real_equational_fun ({thy, fast_descrs, simp_table, psimp_table, ...}
1377 : extended_context) x =
1378 exists (fn table => not (null (def_props_for_const thy fast_descrs table x)))
1379 [!simp_table, psimp_table]
1380 fun is_inductive_pred ext_ctxt =
1381 is_real_inductive_pred ext_ctxt andf (not o is_real_equational_fun ext_ctxt)
1382 fun is_equational_fun (ext_ctxt as {thy, def_table, ...}) =
1383 (is_real_equational_fun ext_ctxt orf is_real_inductive_pred ext_ctxt
1384 orf (String.isPrefix ubfp_prefix orf String.isPrefix lbfp_prefix) o fst)
1385 andf (not o has_trivial_definition thy def_table)
1387 (* term * term -> term *)
1388 fun s_betapply (Const (@{const_name If}, _) $ @{const True} $ t, _) = t
1389 | s_betapply (Const (@{const_name If}, _) $ @{const False} $ _, t) = t
1390 | s_betapply p = betapply p
1391 (* term * term list -> term *)
1392 val s_betapplys = Library.foldl s_betapply
1395 fun lhs_of_equation t =
1397 Const (@{const_name all}, _) $ Abs (_, _, t1) => lhs_of_equation t1
1398 | Const (@{const_name "=="}, _) $ t1 $ _ => SOME t1
1399 | @{const "==>"} $ _ $ t2 => lhs_of_equation t2
1400 | @{const Trueprop} $ t1 => lhs_of_equation t1
1401 | Const (@{const_name All}, _) $ Abs (_, _, t1) => lhs_of_equation t1
1402 | Const (@{const_name "op ="}, _) $ t1 $ _ => SOME t1
1403 | @{const "op -->"} $ _ $ t2 => lhs_of_equation t2
1405 (* theory -> term -> bool *)
1406 fun is_constr_pattern _ (Bound _) = true
1407 | is_constr_pattern thy t =
1408 case strip_comb t of
1409 (Const (x as (s, _)), args) =>
1410 is_constr_like thy x andalso forall (is_constr_pattern thy) args
1412 fun is_constr_pattern_lhs thy t =
1413 forall (is_constr_pattern thy) (snd (strip_comb t))
1414 fun is_constr_pattern_formula thy t =
1415 case lhs_of_equation t of
1416 SOME t' => is_constr_pattern_lhs thy t'
1419 val unfold_max_depth = 255
1420 val axioms_max_depth = 255
1422 (* extended_context -> term -> term *)
1423 fun unfold_defs_in_term (ext_ctxt as {thy, destroy_constrs, fast_descrs,
1424 case_names, def_table, ground_thm_table,
1425 ersatz_table, ...}) =
1427 (* int -> typ list -> term -> term *)
1428 fun do_term depth Ts t =
1430 (t0 as Const (@{const_name Int.number_class.number_of},
1431 Type ("fun", [_, ran_T]))) $ t1 =>
1432 ((if is_number_type thy ran_T then
1434 val j = t1 |> HOLogic.dest_numeral
1435 |> ran_T <> int_T ? curry Int.max 0
1436 val s = numeral_prefix ^ signed_string_of_int j
1438 if is_integer_type ran_T then
1441 do_term depth Ts (Const (@{const_name of_int}, int_T --> ran_T)
1444 handle TERM _ => raise SAME ()
1447 handle SAME () => betapply (do_term depth Ts t0, do_term depth Ts t1))
1448 | Const (@{const_name refl_on}, T) $ Const (@{const_name UNIV}, _) $ t2 =>
1449 do_const depth Ts t (@{const_name refl'}, range_type T) [t2]
1450 | (t0 as Const (x as (@{const_name Sigma}, T))) $ t1
1451 $ (t2 as Abs (_, _, t2')) =>
1452 betapplys (t0 |> loose_bvar1 (t2', 0) ? do_term depth Ts,
1453 map (do_term depth Ts) [t1, t2])
1454 | Const (x as (@{const_name distinct},
1455 Type ("fun", [Type (@{type_name list}, [T']), _])))
1457 (t1 |> HOLogic.dest_list |> distinctness_formula T'
1458 handle TERM _ => do_const depth Ts t x [t1])
1459 | (t0 as Const (x as (@{const_name If}, _))) $ t1 $ t2 $ t3 =>
1460 if is_ground_term t1
1461 andalso exists (Pattern.matches thy o rpair t1)
1462 (Inttab.lookup_list ground_thm_table
1463 (hash_term t1)) then
1466 do_const depth Ts t x [t1, t2, t3]
1467 | Const x $ t1 $ t2 $ t3 => do_const depth Ts t x [t1, t2, t3]
1468 | Const x $ t1 $ t2 => do_const depth Ts t x [t1, t2]
1469 | Const x $ t1 => do_const depth Ts t x [t1]
1470 | Const x => do_const depth Ts t x []
1471 | t1 $ t2 => betapply (do_term depth Ts t1, do_term depth Ts t2)
1475 | Abs (s, T, body) => Abs (s, T, do_term depth (T :: Ts) body)
1476 (* int -> typ list -> styp -> term list -> int -> typ -> term * term list *)
1477 and select_nth_constr_arg_with_args _ _ (x as (_, T)) [] n res_T =
1478 (Abs (Name.uu, body_type T,
1479 select_nth_constr_arg thy x (Bound 0) n res_T), [])
1480 | select_nth_constr_arg_with_args depth Ts x (t :: ts) n res_T =
1481 (select_nth_constr_arg thy x (do_term depth Ts t) n res_T, ts)
1482 (* int -> typ list -> term -> styp -> term list -> term *)
1483 and do_const depth Ts t (x as (s, T)) ts =
1484 case AList.lookup (op =) ersatz_table s of
1486 do_const (depth + 1) Ts (list_comb (Const (s', T), ts)) (s', T) ts
1490 if is_built_in_const fast_descrs x then
1491 if s = @{const_name finite} then
1492 if is_finite_type ext_ctxt (domain_type T) then
1493 (Abs ("A", domain_type T, @{const True}), ts)
1495 [Const (@{const_name UNIV}, _)] => (@{const False}, [])
1496 | _ => (Const x, ts)
1499 else case AList.lookup (op =) case_names s of
1502 val (dataT, res_T) = nth_range_type n T
1503 |> pairf domain_type range_type
1505 (optimized_case_def ext_ctxt dataT res_T
1506 |> do_term (depth + 1) Ts, ts)
1509 if is_constr thy x then
1511 else if is_stale_constr thy x then
1512 raise NOT_SUPPORTED ("(non-co-)constructors of codatatypes \
1514 else if is_record_get thy x then
1516 0 => (do_term depth Ts (eta_expand Ts t 1), [])
1517 | _ => (optimized_record_get ext_ctxt s (domain_type T)
1518 (range_type T) (hd ts), tl ts)
1519 else if is_record_update thy x then
1521 2 => (optimized_record_update ext_ctxt
1522 (unsuffix Record.updateN s) (nth_range_type 2 T)
1523 (do_term depth Ts (hd ts))
1524 (do_term depth Ts (nth ts 1)), [])
1525 | n => (do_term depth Ts (eta_expand Ts t (2 - n)), [])
1526 else if is_rep_fun thy x then
1527 let val x' = mate_of_rep_fun thy x in
1528 if is_constr thy x' then
1529 select_nth_constr_arg_with_args depth Ts x' ts 0
1534 else if is_equational_fun ext_ctxt x then
1536 else case def_of_const thy def_table x of
1538 if depth > unfold_max_depth then
1539 raise LIMIT ("Nitpick_HOL.unfold_defs_in_term",
1540 "too many nested definitions (" ^
1541 string_of_int depth ^ ") while expanding " ^
1543 else if s = @{const_name wfrec'} then
1544 (do_term (depth + 1) Ts (betapplys (def, ts)), [])
1546 (do_term (depth + 1) Ts def, ts)
1547 | NONE => (Const x, ts)
1548 in s_betapplys (const, map (do_term depth Ts) ts) |> Envir.beta_norm end
1551 (* extended_context -> typ -> term list *)
1552 fun codatatype_bisim_axioms (ext_ctxt as {thy, ...}) T =
1554 val xs = datatype_constrs ext_ctxt T
1555 val set_T = T --> bool_T
1556 val iter_T = @{typ bisim_iterator}
1557 val bisim_const = Const (@{const_name bisim}, [iter_T, T, T] ---> bool_T)
1558 val bisim_max = @{const bisim_iterator_max}
1559 val n_var = Var (("n", 0), iter_T)
1561 Const (@{const_name Tha}, (iter_T --> bool_T) --> iter_T)
1562 $ Abs ("m", iter_T, HOLogic.eq_const iter_T
1563 $ (suc_const iter_T $ Bound 0) $ n_var)
1564 val x_var = Var (("x", 0), T)
1565 val y_var = Var (("y", 0), T)
1566 (* styp -> int -> typ -> term *)
1567 fun nth_sub_bisim x n nth_T =
1568 (if is_codatatype thy nth_T then bisim_const $ n_var_minus_1
1569 else HOLogic.eq_const nth_T)
1570 $ select_nth_constr_arg thy x x_var n nth_T
1571 $ select_nth_constr_arg thy x y_var n nth_T
1573 fun case_func (x as (_, T)) =
1575 val arg_Ts = binder_types T
1577 discriminate_value ext_ctxt x y_var ::
1578 map2 (nth_sub_bisim x) (index_seq 0 (length arg_Ts)) arg_Ts
1580 in List.foldr absdummy core_t arg_Ts end
1582 [HOLogic.eq_const bool_T $ (bisim_const $ n_var $ x_var $ y_var)
1583 $ (@{term "op |"} $ (HOLogic.eq_const iter_T $ n_var $ zero_const iter_T)
1584 $ (betapplys (optimized_case_def ext_ctxt T bool_T,
1585 map case_func xs @ [x_var]))),
1586 HOLogic.eq_const set_T $ (bisim_const $ bisim_max $ x_var)
1587 $ (Const (@{const_name insert}, [T, set_T] ---> set_T)
1588 $ x_var $ Const (@{const_name bot_fun_inst.bot_fun}, set_T))]
1589 |> map HOLogic.mk_Trueprop
1592 exception NO_TRIPLE of unit
1594 (* theory -> styp -> term -> term list * term list * term *)
1595 fun triple_for_intro_rule thy x t =
1597 val prems = Logic.strip_imp_prems t |> map (ObjectLogic.atomize_term thy)
1598 val concl = Logic.strip_imp_concl t |> ObjectLogic.atomize_term thy
1599 val (main, side) = List.partition (exists_Const (equal x)) prems
1601 val is_good_head = equal (Const x) o head_of
1603 if forall is_good_head main then (side, main, concl) else raise NO_TRIPLE ()
1607 val tuple_for_args = HOLogic.mk_tuple o snd o strip_comb
1609 (* indexname * typ -> term list -> term -> term -> term *)
1610 fun wf_constraint_for rel side concl main =
1612 val core = HOLogic.mk_mem (HOLogic.mk_prod (tuple_for_args main,
1613 tuple_for_args concl), Var rel)
1614 val t = List.foldl HOLogic.mk_imp core side
1615 val vars = filter (not_equal rel) (Term.add_vars t [])
1617 Library.foldl (fn (t', ((x, j), T)) =>
1619 $ Abs (x, T, abstract_over (Var ((x, j), T), t')))
1623 (* indexname * typ -> term list * term list * term -> term *)
1624 fun wf_constraint_for_triple rel (side, main, concl) =
1625 map (wf_constraint_for rel side concl) main |> foldr1 s_conj
1627 (* Proof.context -> Time.time option -> thm
1628 -> (Proof.context -> tactic -> tactic) -> bool *)
1629 fun terminates_by ctxt timeout goal tac =
1630 can (SINGLE (Classical.safe_tac (claset_of ctxt)) #> the
1631 #> SINGLE (DETERM_TIMEOUT timeout
1632 (tac ctxt (auto_tac (clasimpset_of ctxt))))
1633 #> the #> Goal.finish ctxt) goal
1635 val max_cached_wfs = 100
1636 val cached_timeout = Unsynchronized.ref (SOME Time.zeroTime)
1637 val cached_wf_props : (term * bool) list Unsynchronized.ref =
1638 Unsynchronized.ref []
1640 val termination_tacs = [Lexicographic_Order.lex_order_tac true,
1641 ScnpReconstruct.sizechange_tac]
1643 (* extended_context -> const_table -> styp -> bool *)
1644 fun uncached_is_well_founded_inductive_pred
1645 ({thy, ctxt, debug, fast_descrs, tac_timeout, intro_table, ...}
1646 : extended_context) (x as (_, T)) =
1647 case def_props_for_const thy fast_descrs intro_table x of
1648 [] => raise TERM ("Nitpick_HOL.uncached_is_well_founded_inductive",
1651 (case map (triple_for_intro_rule thy x) intro_ts
1652 |> filter_out (null o #2) of
1656 val binders_T = HOLogic.mk_tupleT (binder_types T)
1657 val rel_T = HOLogic.mk_prodT (binders_T, binders_T) --> bool_T
1658 val j = List.foldl Int.max 0 (map maxidx_of_term intro_ts) + 1
1659 val rel = (("R", j), rel_T)
1660 val prop = Const (@{const_name wf}, rel_T --> bool_T) $ Var rel ::
1661 map (wf_constraint_for_triple rel) triples
1662 |> foldr1 s_conj |> HOLogic.mk_Trueprop
1663 val _ = if debug then
1664 priority ("Wellfoundedness goal: " ^
1665 Syntax.string_of_term ctxt prop ^ ".")
1669 if tac_timeout = (!cached_timeout)
1670 andalso length (!cached_wf_props) < max_cached_wfs then
1673 (cached_wf_props := []; cached_timeout := tac_timeout);
1674 case AList.lookup (op =) (!cached_wf_props) prop of
1678 val goal = prop |> cterm_of thy |> Goal.init
1679 val wf = exists (terminates_by ctxt tac_timeout goal)
1681 in Unsynchronized.change cached_wf_props (cons (prop, wf)); wf end
1683 handle List.Empty => false
1684 | NO_TRIPLE () => false
1686 (* The type constraint below is a workaround for a Poly/ML bug. *)
1688 (* extended_context -> styp -> bool *)
1689 fun is_well_founded_inductive_pred
1690 (ext_ctxt as {thy, wfs, def_table, wf_cache, ...} : extended_context)
1692 case triple_lookup (const_match thy) wfs x of
1694 | _ => s mem [@{const_name Nats}, @{const_name fold_graph'}]
1695 orelse case AList.lookup (op =) (!wf_cache) x of
1699 val gfp = (fixpoint_kind_of_const thy def_table x = Gfp)
1700 val wf = uncached_is_well_founded_inductive_pred ext_ctxt x
1702 Unsynchronized.change wf_cache (cons (x, (gfp, wf))); wf
1705 (* typ list -> typ -> typ -> term -> term *)
1706 fun ap_curry [_] _ _ t = t
1707 | ap_curry arg_Ts tuple_T body_T t =
1708 let val n = length arg_Ts in
1709 list_abs (map (pair "c") arg_Ts,
1711 $ mk_flat_tuple tuple_T (map Bound (n - 1 downto 0)))
1714 (* int -> term -> int *)
1715 fun num_occs_of_bound_in_term j (t1 $ t2) =
1716 op + (pairself (num_occs_of_bound_in_term j) (t1, t2))
1717 | num_occs_of_bound_in_term j (Abs (s, T, t')) =
1718 num_occs_of_bound_in_term (j + 1) t'
1719 | num_occs_of_bound_in_term j (Bound j') = if j' = j then 1 else 0
1720 | num_occs_of_bound_in_term _ _ = 0
1723 val is_linear_inductive_pred_def =
1725 (* int -> term -> bool *)
1726 fun do_disjunct j (Const (@{const_name Ex}, _) $ Abs (_, _, t2)) =
1727 do_disjunct (j + 1) t2
1729 case num_occs_of_bound_in_term j t of
1731 | 1 => exists (equal (Bound j) o head_of) (conjuncts t)
1734 fun do_lfp_def (Const (@{const_name lfp}, _) $ t2) =
1735 let val (xs, body) = strip_abs t2 in
1738 | n => forall (do_disjunct (n - 1)) (disjuncts body)
1740 | do_lfp_def _ = false
1741 in do_lfp_def o strip_abs_body end
1743 (* typ -> typ -> term -> term *)
1744 fun ap_split tuple_T =
1745 HOLogic.mk_psplits (HOLogic.flat_tupleT_paths tuple_T) tuple_T
1747 (* term -> term * term *)
1748 val linear_pred_base_and_step_rhss =
1751 fun aux (Const (@{const_name lfp}, _) $ t2) =
1753 val (xs, body) = strip_abs t2
1754 val arg_Ts = map snd (tl xs)
1755 val tuple_T = HOLogic.mk_tupleT arg_Ts
1756 val j = length arg_Ts
1757 (* int -> term -> term *)
1758 fun repair_rec j (Const (@{const_name Ex}, T1) $ Abs (s2, T2, t2')) =
1759 Const (@{const_name Ex}, T1)
1760 $ Abs (s2, T2, repair_rec (j + 1) t2')
1761 | repair_rec j (@{const "op &"} $ t1 $ t2) =
1762 @{const "op &"} $ repair_rec j t1 $ repair_rec j t2
1764 let val (head, args) = strip_comb t in
1765 if head = Bound j then
1766 HOLogic.eq_const tuple_T $ Bound j
1767 $ mk_flat_tuple tuple_T args
1771 val (nonrecs, recs) =
1772 List.partition (equal 0 o num_occs_of_bound_in_term j)
1774 val base_body = nonrecs |> List.foldl s_disj @{const False}
1775 val step_body = recs |> map (repair_rec j)
1776 |> List.foldl s_disj @{const False}
1778 (list_abs (tl xs, incr_bv (~1, j, base_body))
1779 |> ap_split tuple_T bool_T,
1780 Abs ("y", tuple_T, list_abs (tl xs, step_body)
1781 |> ap_split tuple_T bool_T))
1784 raise TERM ("Nitpick_HOL.linear_pred_base_and_step_rhss.aux", [t])
1787 (* extended_context -> styp -> term -> term *)
1788 fun closed_linear_pred_const (ext_ctxt as {simp_table, ...}) (x as (s, T)) def =
1790 val j = maxidx_of_term def + 1
1791 val (outer, fp_app) = strip_abs def
1792 val outer_bounds = map Bound (length outer - 1 downto 0)
1793 val outer_vars = map (fn (s, T) => Var ((s, j), T)) outer
1794 val fp_app = subst_bounds (rev outer_vars, fp_app)
1795 val (outer_Ts, rest_T) = strip_n_binders (length outer) T
1796 val tuple_arg_Ts = strip_type rest_T |> fst
1797 val tuple_T = HOLogic.mk_tupleT tuple_arg_Ts
1798 val set_T = tuple_T --> bool_T
1799 val curried_T = tuple_T --> set_T
1800 val uncurried_T = Type ("*", [tuple_T, tuple_T]) --> bool_T
1801 val (base_rhs, step_rhs) = linear_pred_base_and_step_rhss fp_app
1802 val base_x as (base_s, _) = (base_prefix ^ s, outer_Ts ---> set_T)
1803 val base_eq = HOLogic.mk_eq (list_comb (Const base_x, outer_vars), base_rhs)
1804 |> HOLogic.mk_Trueprop
1805 val _ = add_simps simp_table base_s [base_eq]
1806 val step_x as (step_s, _) = (step_prefix ^ s, outer_Ts ---> curried_T)
1807 val step_eq = HOLogic.mk_eq (list_comb (Const step_x, outer_vars), step_rhs)
1808 |> HOLogic.mk_Trueprop
1809 val _ = add_simps simp_table step_s [step_eq]
1812 Const (@{const_name Image}, uncurried_T --> set_T --> set_T)
1813 $ (Const (@{const_name rtrancl}, uncurried_T --> uncurried_T)
1814 $ (Const (@{const_name split}, curried_T --> uncurried_T)
1815 $ list_comb (Const step_x, outer_bounds)))
1816 $ list_comb (Const base_x, outer_bounds)
1817 |> ap_curry tuple_arg_Ts tuple_T bool_T)
1818 |> unfold_defs_in_term ext_ctxt
1821 (* extended_context -> bool -> styp -> term *)
1822 fun unrolled_inductive_pred_const (ext_ctxt as {thy, star_linear_preds,
1823 def_table, simp_table, ...})
1826 val iter_T = iterator_type_for_const gfp x
1827 val x' as (s', _) = (unrolled_prefix ^ s, iter_T --> T)
1828 val unrolled_const = Const x' $ zero_const iter_T
1829 val def = the (def_of_const thy def_table x)
1831 if is_equational_fun ext_ctxt x' then
1832 unrolled_const (* already done *)
1833 else if not gfp andalso is_linear_inductive_pred_def def
1834 andalso star_linear_preds then
1835 closed_linear_pred_const ext_ctxt x def
1838 val j = maxidx_of_term def + 1
1839 val (outer, fp_app) = strip_abs def
1840 val outer_bounds = map Bound (length outer - 1 downto 0)
1841 val cur = Var ((iter_var_prefix, j + 1), iter_T)
1842 val next = suc_const iter_T $ cur
1843 val rhs = case fp_app of
1845 betapply (t, list_comb (Const x', next :: outer_bounds))
1846 | _ => raise TERM ("Nitpick_HOL.unrolled_inductive_pred_\
1848 val (inner, naked_rhs) = strip_abs rhs
1849 val all = outer @ inner
1850 val bounds = map Bound (length all - 1 downto 0)
1851 val vars = map (fn (s, T) => Var ((s, j), T)) all
1852 val eq = HOLogic.mk_eq (list_comb (Const x', cur :: bounds), naked_rhs)
1853 |> HOLogic.mk_Trueprop |> curry subst_bounds (rev vars)
1854 val _ = add_simps simp_table s' [eq]
1855 in unrolled_const end
1858 (* extended_context -> styp -> term *)
1859 fun raw_inductive_pred_axiom ({thy, def_table, ...} : extended_context) x =
1861 val def = the (def_of_const thy def_table x)
1862 val (outer, fp_app) = strip_abs def
1863 val outer_bounds = map Bound (length outer - 1 downto 0)
1864 val rhs = case fp_app of
1865 Const _ $ t => betapply (t, list_comb (Const x, outer_bounds))
1866 | _ => raise TERM ("Nitpick_HOL.raw_inductive_pred_axiom",
1868 val (inner, naked_rhs) = strip_abs rhs
1869 val all = outer @ inner
1870 val bounds = map Bound (length all - 1 downto 0)
1871 val j = maxidx_of_term def + 1
1872 val vars = map (fn (s, T) => Var ((s, j), T)) all
1874 HOLogic.mk_eq (list_comb (Const x, bounds), naked_rhs)
1875 |> HOLogic.mk_Trueprop |> curry subst_bounds (rev vars)
1877 fun inductive_pred_axiom ext_ctxt (x as (s, T)) =
1878 if String.isPrefix ubfp_prefix s orelse String.isPrefix lbfp_prefix s then
1879 let val x' = (after_name_sep s, T) in
1880 raw_inductive_pred_axiom ext_ctxt x' |> subst_atomic [(Const x', Const x)]
1883 raw_inductive_pred_axiom ext_ctxt x
1885 (* extended_context -> styp -> term list *)
1886 fun raw_equational_fun_axioms (ext_ctxt as {thy, fast_descrs, simp_table,
1887 psimp_table, ...}) (x as (s, _)) =
1888 case def_props_for_const thy fast_descrs (!simp_table) x of
1889 [] => (case def_props_for_const thy fast_descrs psimp_table x of
1890 [] => [inductive_pred_axiom ext_ctxt x]
1894 val equational_fun_axioms = map extensionalize oo raw_equational_fun_axioms
1896 (* term list -> term list *)
1897 fun merge_type_vars_in_terms ts =
1899 (* typ -> (sort * string) list -> (sort * string) list *)
1900 fun add_type (TFree (s, S)) table =
1901 (case AList.lookup (op =) table S of
1903 if string_ord (s', s) = LESS then AList.update (op =) (S, s') table
1905 | NONE => (S, s) :: table)
1906 | add_type _ table = table
1907 val table = fold (fold_types (fold_atyps add_type)) ts []
1909 fun coalesce (TFree (s, S)) = TFree (AList.lookup (op =) table S |> the, S)
1911 in map (map_types (map_atyps coalesce)) ts end
1913 (* extended_context -> typ -> typ list -> typ list *)
1914 fun add_ground_types ext_ctxt T accum =
1916 Type ("fun", Ts) => fold (add_ground_types ext_ctxt) Ts accum
1917 | Type ("*", Ts) => fold (add_ground_types ext_ctxt) Ts accum
1918 | Type (@{type_name itself}, [T1]) => add_ground_types ext_ctxt T1 accum
1920 if T mem @{typ prop} :: @{typ bool} :: @{typ unit} :: accum then
1924 |> fold (add_ground_types ext_ctxt)
1925 (case boxed_datatype_constrs ext_ctxt T of
1928 | _ => insert (op =) T accum
1929 (* extended_context -> typ -> typ list *)
1930 fun ground_types_in_type ext_ctxt T = add_ground_types ext_ctxt T []
1931 (* extended_context -> term list -> typ list *)
1932 fun ground_types_in_terms ext_ctxt ts =
1933 fold (fold_types (add_ground_types ext_ctxt)) ts []
1935 (* typ list -> int -> term -> bool *)
1936 fun has_heavy_bounds_or_vars Ts level t =
1938 (* typ list -> bool *)
1940 | aux [T] = is_fun_type T orelse is_pair_type T
1942 in aux (map snd (Term.add_vars t []) @ map (nth Ts) (loose_bnos t)) end
1944 (* typ list -> int -> int -> int -> term -> term *)
1945 fun fresh_value_var Ts k n j t =
1946 Var ((val_var_prefix ^ nat_subscript (n - j), k), fastype_of1 (Ts, t))
1948 (* theory -> typ list -> bool -> int -> int -> term -> term list -> term list
1949 -> term * term list *)
1950 fun pull_out_constr_comb thy Ts relax k level t args seen =
1951 let val t_comb = list_comb (t, args) in
1954 if not relax andalso is_constr thy x
1955 andalso not (is_fun_type (fastype_of1 (Ts, t_comb)))
1956 andalso has_heavy_bounds_or_vars Ts level t_comb
1957 andalso not (loose_bvar (t_comb, level)) then
1959 val (j, seen) = case find_index (equal t_comb) seen of
1960 ~1 => (0, t_comb :: seen)
1962 in (fresh_value_var Ts k (length seen) j t_comb, seen) end
1965 | _ => (t_comb, seen)
1968 (* (term -> term) -> typ list -> int -> term list -> term list *)
1969 fun equations_for_pulled_out_constrs mk_eq Ts k seen =
1970 let val n = length seen in
1971 map2 (fn j => fn t => mk_eq (fresh_value_var Ts k n j t, t))
1972 (index_seq 0 n) seen
1975 (* theory -> bool -> term -> term *)
1976 fun pull_out_universal_constrs thy def t =
1978 val k = maxidx_of_term t + 1
1979 (* typ list -> bool -> term -> term list -> term list -> term * term list *)
1980 fun do_term Ts def t args seen =
1982 (t0 as Const (@{const_name "=="}, _)) $ t1 $ t2 =>
1983 do_eq_or_imp Ts def t0 t1 t2 seen
1984 | (t0 as @{const "==>"}) $ t1 $ t2 => do_eq_or_imp Ts def t0 t1 t2 seen
1985 | (t0 as Const (@{const_name "op ="}, _)) $ t1 $ t2 =>
1986 do_eq_or_imp Ts def t0 t1 t2 seen
1987 | (t0 as @{const "op -->"}) $ t1 $ t2 => do_eq_or_imp Ts def t0 t1 t2 seen
1989 let val (t', seen) = do_term (T :: Ts) def t' [] seen in
1990 (list_comb (Abs (s, T, t'), args), seen)
1993 let val (t2, seen) = do_term Ts def t2 [] seen in
1994 do_term Ts def t1 (t2 :: args) seen
1996 | _ => pull_out_constr_comb thy Ts def k 0 t args seen
1997 (* typ list -> bool -> term -> term -> term -> term list
1998 -> term * term list *)
1999 and do_eq_or_imp Ts def t0 t1 t2 seen =
2001 val (t2, seen) = do_term Ts def t2 [] seen
2002 val (t1, seen) = do_term Ts false t1 [] seen
2003 in (t0 $ t1 $ t2, seen) end
2004 val (concl, seen) = do_term [] def t [] []
2006 Logic.list_implies (equations_for_pulled_out_constrs Logic.mk_equals [] k
2010 (* extended_context -> bool -> term -> term *)
2011 fun destroy_pulled_out_constrs (ext_ctxt as {thy, ...}) axiom t =
2014 val num_occs_of_var =
2015 fold_aterms (fn Var z => (fn f => fn z' => f z' |> z = z' ? Integer.add 1)
2017 (* bool -> term -> term *)
2018 fun aux careful ((t0 as Const (@{const_name "=="}, _)) $ t1 $ t2) =
2019 aux_eq careful true t0 t1 t2
2020 | aux careful ((t0 as @{const "==>"}) $ t1 $ t2) =
2021 t0 $ aux false t1 $ aux careful t2
2022 | aux careful ((t0 as Const (@{const_name "op ="}, _)) $ t1 $ t2) =
2023 aux_eq careful true t0 t1 t2
2024 | aux careful ((t0 as @{const "op -->"}) $ t1 $ t2) =
2025 t0 $ aux false t1 $ aux careful t2
2026 | aux careful (Abs (s, T, t')) = Abs (s, T, aux careful t')
2027 | aux careful (t1 $ t2) = aux careful t1 $ aux careful t2
2029 (* bool -> bool -> term -> term -> term -> term *)
2030 and aux_eq careful pass1 t0 t1 t2 =
2033 else if axiom andalso is_Var t2
2034 andalso num_occs_of_var (dest_Var t2) = 1 then
2036 else case strip_comb t2 of
2037 (Const (x as (s, T)), args) =>
2038 let val arg_Ts = binder_types T in
2039 if length arg_Ts = length args
2040 andalso (is_constr thy x orelse s mem [@{const_name Pair}]
2041 orelse x = dest_Const @{const Suc})
2042 andalso (not careful orelse not (is_Var t1)
2043 orelse String.isPrefix val_var_prefix
2044 (fst (fst (dest_Var t1)))) then
2045 discriminate_value ext_ctxt x t1 ::
2046 map3 (sel_eq x t1) (index_seq 0 (length args)) arg_Ts args
2048 |> body_type (type_of t0) = prop_T ? HOLogic.mk_Trueprop
2052 | _ => raise SAME ())
2053 handle SAME () => if pass1 then aux_eq careful false t0 t2 t1
2054 else t0 $ aux false t2 $ aux false t1
2055 (* styp -> term -> int -> typ -> term -> term *)
2056 and sel_eq x t n nth_T nth_t =
2057 HOLogic.eq_const nth_T $ nth_t $ select_nth_constr_arg thy x t n nth_T
2061 (* theory -> term -> term *)
2062 fun simplify_constrs_and_sels thy t =
2064 (* term -> int -> term *)
2065 fun is_nth_sel_on t' n (Const (s, _) $ t) =
2066 (t = t' andalso is_sel_like_and_no_discr s
2067 andalso sel_no_from_name s = n)
2068 | is_nth_sel_on _ _ _ = false
2069 (* term -> term list -> term *)
2070 fun do_term (Const (@{const_name Rep_Frac}, _)
2071 $ (Const (@{const_name Abs_Frac}, _) $ t1)) [] = do_term t1 []
2072 | do_term (Const (@{const_name Abs_Frac}, _)
2073 $ (Const (@{const_name Rep_Frac}, _) $ t1)) [] = do_term t1 []
2074 | do_term (t1 $ t2) args = do_term t1 (do_term t2 [] :: args)
2075 | do_term (t as Const (x as (s, T))) (args as _ :: _) =
2076 ((if is_constr_like thy x then
2077 if length args = num_binder_types T then
2079 Const (x' as (_, T')) $ t' =>
2080 if domain_type T' = body_type T
2081 andalso forall (uncurry (is_nth_sel_on t'))
2082 (index_seq 0 (length args) ~~ args) then
2086 | _ => raise SAME ()
2089 else if is_sel_like_and_no_discr s then
2090 case strip_comb (hd args) of
2091 (Const (x' as (s', T')), ts') =>
2092 if is_constr_like thy x'
2093 andalso constr_name_for_sel_like s = s'
2094 andalso not (exists is_pair_type (binder_types T')) then
2095 list_comb (nth ts' (sel_no_from_name s), tl args)
2098 | _ => raise SAME ()
2101 handle SAME () => betapplys (t, args))
2102 | do_term (Abs (s, T, t')) args =
2103 betapplys (Abs (s, T, do_term t' []), args)
2104 | do_term t args = betapplys (t, args)
2108 fun curry_assms (@{const "==>"} $ (@{const Trueprop}
2109 $ (@{const "op &"} $ t1 $ t2)) $ t3) =
2110 curry_assms (Logic.list_implies ([t1, t2] |> map HOLogic.mk_Trueprop, t3))
2111 | curry_assms (@{const "==>"} $ t1 $ t2) =
2112 @{const "==>"} $ curry_assms t1 $ curry_assms t2
2116 val destroy_universal_equalities =
2118 (* term list -> (indexname * typ) list -> term -> term *)
2119 fun aux prems zs t =
2121 @{const "==>"} $ t1 $ t2 => aux_implies prems zs t1 t2
2122 | _ => Logic.list_implies (rev prems, t)
2123 (* term list -> (indexname * typ) list -> term -> term -> term *)
2124 and aux_implies prems zs t1 t2 =
2126 Const (@{const_name "=="}, _) $ Var z $ t' => aux_eq prems zs z t' t1 t2
2127 | @{const Trueprop} $ (Const (@{const_name "op ="}, _) $ Var z $ t') =>
2128 aux_eq prems zs z t' t1 t2
2129 | @{const Trueprop} $ (Const (@{const_name "op ="}, _) $ t' $ Var z) =>
2130 aux_eq prems zs z t' t1 t2
2131 | _ => aux (t1 :: prems) (Term.add_vars t1 zs) t2
2132 (* term list -> (indexname * typ) list -> indexname * typ -> term -> term
2134 and aux_eq prems zs z t' t1 t2 =
2135 if not (z mem zs) andalso not (exists_subterm (equal (Var z)) t') then
2136 aux prems zs (subst_free [(Var z, t')] t2)
2138 aux (t1 :: prems) (Term.add_vars t1 zs) t2
2141 (* theory -> term -> term *)
2142 fun pull_out_existential_constrs thy t =
2144 val k = maxidx_of_term t + 1
2145 (* typ list -> int -> term -> term list -> term list -> term * term list *)
2146 fun aux Ts num_exists t args seen =
2148 (t0 as Const (@{const_name Ex}, _)) $ Abs (s1, T1, t1) =>
2150 val (t1, seen') = aux (T1 :: Ts) (num_exists + 1) t1 [] []
2151 val n = length seen'
2152 (* unit -> term list *)
2153 fun vars () = map2 (fresh_value_var Ts k n) (index_seq 0 n) seen'
2155 (equations_for_pulled_out_constrs HOLogic.mk_eq Ts k seen'
2156 |> List.foldl s_conj t1 |> fold mk_exists (vars ())
2157 |> curry3 Abs s1 T1 |> curry (op $) t0, seen)
2160 let val (t2, seen) = aux Ts num_exists t2 [] seen in
2161 aux Ts num_exists t1 (t2 :: args) seen
2165 val (t', seen) = aux (T :: Ts) 0 t' [] (map (incr_boundvars 1) seen)
2166 in (list_comb (Abs (s, T, t'), args), map (incr_boundvars ~1) seen) end
2168 if num_exists > 0 then
2169 pull_out_constr_comb thy Ts false k num_exists t args seen
2171 (list_comb (t, args), seen)
2172 in aux [] 0 t [] [] |> fst end
2174 (* theory -> int -> term list -> term list -> (term * term list) option *)
2175 fun find_bound_assign _ _ _ [] = NONE
2176 | find_bound_assign thy j seen (t :: ts) =
2178 (* bool -> term -> term -> (term * term list) option *)
2179 fun aux pass1 t1 t2 =
2180 (if loose_bvar1 (t2, j) then
2181 if pass1 then aux false t2 t1 else raise SAME ()
2183 Bound j' => if j' = j then SOME (t2, ts @ seen) else raise SAME ()
2184 | Const (s, Type ("fun", [T1, T2])) $ Bound j' =>
2185 if j' = j andalso s = sel_prefix_for 0 ^ @{const_name FunBox} then
2186 SOME (construct_value thy (@{const_name FunBox}, T2 --> T1) [t2],
2190 | _ => raise SAME ())
2191 handle SAME () => find_bound_assign thy j (t :: seen) ts
2194 Const (@{const_name "op ="}, _) $ t1 $ t2 => aux true t1 t2
2195 | _ => find_bound_assign thy j (t :: seen) ts
2198 (* int -> term -> term -> term *)
2199 fun subst_one_bound j arg t =
2201 fun aux (Bound i, lev) =
2202 if i < lev then raise SAME ()
2203 else if i = lev then incr_boundvars (lev - j) arg
2205 | aux (Abs (a, T, body), lev) = Abs (a, T, aux (body, lev + 1))
2206 | aux (f $ t, lev) =
2207 (aux (f, lev) $ (aux (t, lev) handle SAME () => t)
2208 handle SAME () => f $ aux (t, lev))
2209 | aux _ = raise SAME ()
2210 in aux (t, j) handle SAME () => t end
2212 (* theory -> term -> term *)
2213 fun destroy_existential_equalities thy =
2215 (* string list -> typ list -> term list -> term *)
2216 fun kill [] [] ts = foldr1 s_conj ts
2217 | kill (s :: ss) (T :: Ts) ts =
2218 (case find_bound_assign thy (length ss) [] ts of
2219 SOME (_, []) => @{const True}
2220 | SOME (arg_t, ts) =>
2221 kill ss Ts (map (subst_one_bound (length ss)
2222 (incr_bv (~1, length ss + 1, arg_t))) ts)
2224 Const (@{const_name Ex}, (T --> bool_T) --> bool_T)
2225 $ Abs (s, T, kill ss Ts ts))
2226 | kill _ _ _ = raise UnequalLengths
2227 (* string list -> typ list -> term -> term *)
2228 fun gather ss Ts ((t0 as Const (@{const_name Ex}, _)) $ Abs (s1, T1, t1)) =
2229 gather (ss @ [s1]) (Ts @ [T1]) t1
2230 | gather [] [] (Abs (s, T, t1)) = Abs (s, T, gather [] [] t1)
2231 | gather [] [] (t1 $ t2) = gather [] [] t1 $ gather [] [] t2
2232 | gather [] [] t = t
2233 | gather ss Ts t = kill ss Ts (conjuncts (gather [] [] t))
2237 fun distribute_quantifiers t =
2239 (t0 as Const (@{const_name All}, T0)) $ Abs (s, T1, t1) =>
2241 (t10 as @{const "op &"}) $ t11 $ t12 =>
2242 t10 $ distribute_quantifiers (t0 $ Abs (s, T1, t11))
2243 $ distribute_quantifiers (t0 $ Abs (s, T1, t12))
2244 | (t10 as @{const Not}) $ t11 =>
2245 t10 $ distribute_quantifiers (Const (@{const_name Ex}, T0)
2248 if not (loose_bvar1 (t1, 0)) then
2249 distribute_quantifiers (incr_boundvars ~1 t1)
2251 t0 $ Abs (s, T1, distribute_quantifiers t1))
2252 | (t0 as Const (@{const_name Ex}, T0)) $ Abs (s, T1, t1) =>
2253 (case distribute_quantifiers t1 of
2254 (t10 as @{const "op |"}) $ t11 $ t12 =>
2255 t10 $ distribute_quantifiers (t0 $ Abs (s, T1, t11))
2256 $ distribute_quantifiers (t0 $ Abs (s, T1, t12))
2257 | (t10 as @{const "op -->"}) $ t11 $ t12 =>
2258 t10 $ distribute_quantifiers (Const (@{const_name All}, T0)
2260 $ distribute_quantifiers (t0 $ Abs (s, T1, t12))
2261 | (t10 as @{const Not}) $ t11 =>
2262 t10 $ distribute_quantifiers (Const (@{const_name All}, T0)
2265 if not (loose_bvar1 (t1, 0)) then
2266 distribute_quantifiers (incr_boundvars ~1 t1)
2268 t0 $ Abs (s, T1, distribute_quantifiers t1))
2269 | t1 $ t2 => distribute_quantifiers t1 $ distribute_quantifiers t2
2270 | Abs (s, T, t') => Abs (s, T, distribute_quantifiers t')
2273 (* int -> int -> (int -> int) -> term -> term *)
2274 fun renumber_bounds j n f t =
2276 t1 $ t2 => renumber_bounds j n f t1 $ renumber_bounds j n f t2
2277 | Abs (s, T, t') => Abs (s, T, renumber_bounds (j + 1) n f t')
2279 Bound (if j' >= j andalso j' < j + n then f (j' - j) + j else j')
2282 val quantifier_cluster_max_size = 8
2284 (* theory -> term -> term *)
2285 fun push_quantifiers_inward thy =
2287 (* string -> string list -> typ list -> term -> term *)
2288 fun aux quant_s ss Ts t =
2290 (t0 as Const (s0, _)) $ Abs (s1, T1, t1 as _ $ _) =>
2291 if s0 = quant_s andalso length Ts < quantifier_cluster_max_size then
2292 aux s0 (s1 :: ss) (T1 :: Ts) t1
2293 else if quant_s = ""
2294 andalso s0 mem [@{const_name All}, @{const_name Ex}] then
2298 | _ => raise SAME ())
2302 if quant_s = "" then
2303 aux "" [] [] t1 $ aux "" [] [] t2
2306 val typical_card = 4
2307 (* ('a -> ''b list) -> 'a list -> ''b list *)
2308 fun big_union proj ps =
2309 fold (fold (insert (op =)) o proj) ps []
2310 val (ts, connective) = strip_any_connective t
2312 map (bounded_card_of_type 65536 typical_card []) Ts
2313 val t_costs = map size_of_term ts
2314 val num_Ts = length Ts
2316 val flip = curry (op -) (num_Ts - 1)
2317 val t_boundss = map (map flip o loose_bnos) ts
2318 (* (int list * int) list -> int list -> int *)
2319 fun cost boundss_cum_costs [] =
2320 map snd boundss_cum_costs |> Integer.sum
2321 | cost boundss_cum_costs (j :: js) =
2324 List.partition (fn (bounds, _) => j mem bounds)
2326 val yeas_bounds = big_union fst yeas
2327 val yeas_cost = Integer.sum (map snd yeas)
2329 in cost ((yeas_bounds, yeas_cost) :: nays) js end
2330 val js = all_permutations (index_seq 0 num_Ts)
2331 |> map (`(cost (t_boundss ~~ t_costs)))
2332 |> sort (int_ord o pairself fst) |> hd |> snd
2333 val back_js = map (fn j => find_index (equal j) js)
2334 (index_seq 0 num_Ts)
2335 val ts = map (renumber_bounds 0 num_Ts (nth back_js o flip))
2337 (* (term * int list) list -> term *)
2338 fun mk_connection [] =
2339 raise ARG ("Nitpick_HOL.push_quantifiers_inward.aux.\
2340 \mk_connection", "")
2341 | mk_connection ts_cum_bounds =
2342 ts_cum_bounds |> map fst
2343 |> foldr1 (fn (t1, t2) => connective $ t1 $ t2)
2344 (* (term * int list) list -> int list -> term *)
2345 fun build ts_cum_bounds [] = ts_cum_bounds |> mk_connection
2346 | build ts_cum_bounds (j :: js) =
2349 List.partition (fn (_, bounds) => j mem bounds)
2351 ||> map (apfst (incr_boundvars ~1))
2356 let val T = nth Ts (flip j) in
2357 build ((Const (quant_s, (T --> bool_T) --> bool_T)
2358 $ Abs (nth ss (flip j), T,
2359 mk_connection yeas),
2360 big_union snd yeas) :: nays) js
2363 in build (ts ~~ t_boundss) js end
2364 | Abs (s, T, t') => Abs (s, T, aux "" [] [] t')
2368 (* polarity -> string -> bool *)
2369 fun is_positive_existential polar quant_s =
2370 (polar = Pos andalso quant_s = @{const_name Ex})
2371 orelse (polar = Neg andalso quant_s <> @{const_name Ex})
2373 (* extended_context -> int -> term -> term *)
2374 fun skolemize_term_and_more (ext_ctxt as {thy, def_table, skolems, ...})
2377 (* int list -> int list *)
2378 val incrs = map (Integer.add 1)
2379 (* string list -> typ list -> int list -> int -> polarity -> term -> term *)
2380 fun aux ss Ts js depth polar t =
2382 (* string -> typ -> string -> typ -> term -> term *)
2383 fun do_quantifier quant_s quant_T abs_s abs_T t =
2384 if not (loose_bvar1 (t, 0)) then
2385 aux ss Ts js depth polar (incr_boundvars ~1 t)
2386 else if depth <= skolem_depth
2387 andalso is_positive_existential polar quant_s then
2389 val j = length (!skolems) + 1
2390 val sko_s = skolem_prefix_for (length js) j ^ abs_s
2391 val _ = Unsynchronized.change skolems (cons (sko_s, ss))
2392 val sko_t = list_comb (Const (sko_s, rev Ts ---> abs_T),
2394 val abs_t = Abs (abs_s, abs_T, aux ss Ts (incrs js) depth polar t)
2396 if null js then betapply (abs_t, sko_t)
2397 else Const (@{const_name Let}, abs_T --> quant_T) $ sko_t $ abs_t
2400 Const (quant_s, quant_T)
2401 $ Abs (abs_s, abs_T,
2402 if is_higher_order_type abs_T then
2405 aux (abs_s :: ss) (abs_T :: Ts) (0 :: incrs js)
2406 (depth + 1) polar t)
2409 Const (s0 as @{const_name all}, T0) $ Abs (s1, T1, t1) =>
2410 do_quantifier s0 T0 s1 T1 t1
2411 | @{const "==>"} $ t1 $ t2 =>
2412 @{const "==>"} $ aux ss Ts js depth (flip_polarity polar) t1
2413 $ aux ss Ts js depth polar t2
2414 | @{const Pure.conjunction} $ t1 $ t2 =>
2415 @{const Pure.conjunction} $ aux ss Ts js depth polar t1
2416 $ aux ss Ts js depth polar t2
2417 | @{const Trueprop} $ t1 =>
2418 @{const Trueprop} $ aux ss Ts js depth polar t1
2419 | @{const Not} $ t1 =>
2420 @{const Not} $ aux ss Ts js depth (flip_polarity polar) t1
2421 | Const (s0 as @{const_name All}, T0) $ Abs (s1, T1, t1) =>
2422 do_quantifier s0 T0 s1 T1 t1
2423 | Const (s0 as @{const_name Ex}, T0) $ Abs (s1, T1, t1) =>
2424 do_quantifier s0 T0 s1 T1 t1
2425 | @{const "op &"} $ t1 $ t2 =>
2426 @{const "op &"} $ aux ss Ts js depth polar t1
2427 $ aux ss Ts js depth polar t2
2428 | @{const "op |"} $ t1 $ t2 =>
2429 @{const "op |"} $ aux ss Ts js depth polar t1
2430 $ aux ss Ts js depth polar t2
2431 | @{const "op -->"} $ t1 $ t2 =>
2432 @{const "op -->"} $ aux ss Ts js depth (flip_polarity polar) t1
2433 $ aux ss Ts js depth polar t2
2434 | (t0 as Const (@{const_name Let}, T0)) $ t1 $ t2 =>
2435 t0 $ t1 $ aux ss Ts js depth polar t2
2436 | Const (x as (s, T)) =>
2437 if is_inductive_pred ext_ctxt x
2438 andalso not (is_well_founded_inductive_pred ext_ctxt x) then
2440 val gfp = (fixpoint_kind_of_const thy def_table x = Gfp)
2441 val (pref, connective, set_oper) =
2445 @{const_name upper_semilattice_fun_inst.sup_fun})
2449 @{const_name lower_semilattice_fun_inst.inf_fun})
2451 fun pos () = unrolled_inductive_pred_const ext_ctxt gfp x
2452 |> aux ss Ts js depth polar
2453 fun neg () = Const (pref ^ s, T)
2455 (case polar |> gfp ? flip_polarity of
2459 if is_fun_type T then
2461 val ((trunk_arg_Ts, rump_arg_T), body_T) =
2462 T |> strip_type |>> split_last
2463 val set_T = rump_arg_T --> body_T
2464 (* (unit -> term) -> term *)
2467 map Bound (length trunk_arg_Ts - 1 downto 0))
2470 (Const (set_oper, [set_T, set_T] ---> set_T)
2471 $ app pos $ app neg) trunk_arg_Ts
2474 connective $ pos () $ neg ())
2479 betapply (aux ss Ts [] (skolem_depth + 1) polar t1,
2480 aux ss Ts [] depth Neut t2)
2481 | Abs (s, T, t1) => Abs (s, T, aux ss Ts (incrs js) depth polar t1)
2484 in aux [] [] [] 0 Pos end
2486 (* extended_context -> styp -> (int * term option) list *)
2487 fun static_args_in_term ({ersatz_table, ...} : extended_context) x t =
2489 (* term -> term list -> term list -> term list list *)
2490 fun fun_calls (Abs (_, _, t)) _ = fun_calls t []
2491 | fun_calls (t1 $ t2) args = fun_calls t2 [] #> fun_calls t1 (t2 :: args)
2492 | fun_calls t args =
2494 Const (x' as (s', T')) =>
2495 x = x' orelse (case AList.lookup (op =) ersatz_table s' of
2496 SOME s'' => x = (s'', T')
2498 | _ => false) ? cons args
2499 (* term list list -> term list list -> term list -> term list list *)
2500 fun call_sets [] [] vs = [vs]
2501 | call_sets [] uss vs = vs :: call_sets uss [] []
2502 | call_sets ([] :: _) _ _ = []
2503 | call_sets ((t :: ts) :: tss) uss vs =
2504 OrdList.insert TermOrd.term_ord t vs |> call_sets tss (ts :: uss)
2505 val sets = call_sets (fun_calls t [] []) [] []
2506 val indexed_sets = sets ~~ (index_seq 0 (length sets))
2508 fold_rev (fn (set, j) =>
2510 [Var _] => AList.lookup (op =) indexed_sets set = SOME j
2512 | [t as Const _] => cons (j, SOME t)
2513 | [t as Free _] => cons (j, SOME t)
2514 | _ => I) indexed_sets []
2516 (* extended_context -> styp -> term list -> (int * term option) list *)
2517 fun static_args_in_terms ext_ctxt x =
2518 map (static_args_in_term ext_ctxt x)
2519 #> fold1 (OrdList.inter (prod_ord int_ord (option_ord TermOrd.term_ord)))
2521 (* term -> term list *)
2522 fun params_in_equation (@{const "==>"} $ _ $ t2) = params_in_equation t2
2523 | params_in_equation (@{const Trueprop} $ t1) = params_in_equation t1
2524 | params_in_equation (Const (@{const_name "op ="}, _) $ t1 $ _) =
2526 | params_in_equation _ = []
2528 (* styp -> styp -> int list -> term list -> term list -> term -> term *)
2529 fun specialize_fun_axiom x x' fixed_js fixed_args extra_args t =
2531 val k = fold Integer.max (map maxidx_of_term (fixed_args @ extra_args)) 0
2533 val t = map_aterms (fn Var ((s, i), T) => Var ((s, k + i), T) | t' => t') t
2534 val fixed_params = filter_indices fixed_js (params_in_equation t)
2535 (* term list -> term -> term *)
2536 fun aux args (Abs (s, T, t)) = list_comb (Abs (s, T, aux [] t), args)
2537 | aux args (t1 $ t2) = aux (aux [] t2 :: args) t1
2540 list_comb (Const x', extra_args @ filter_out_indices fixed_js args)
2542 let val j = find_index (equal t) fixed_params in
2543 list_comb (if j >= 0 then nth fixed_args j else t, args)
2547 (* typ list -> term -> bool *)
2548 fun is_eligible_arg Ts t =
2549 let val bad_Ts = map snd (Term.add_vars t []) @ map (nth Ts) (loose_bnos t) in
2551 orelse (is_higher_order_type (fastype_of1 (Ts, t))
2552 andalso forall (not o is_higher_order_type) bad_Ts)
2555 (* (int * term option) list -> (int * term) list -> int list *)
2556 fun overlapping_indices [] _ = []
2557 | overlapping_indices _ [] = []
2558 | overlapping_indices (ps1 as (j1, t1) :: ps1') (ps2 as (j2, t2) :: ps2') =
2559 if j1 < j2 then overlapping_indices ps1' ps2
2560 else if j1 > j2 then overlapping_indices ps1 ps2'
2561 else overlapping_indices ps1' ps2' |> the_default t2 t1 = t2 ? cons j1
2563 val special_depth = 20
2565 (* extended_context -> int -> term -> term *)
2566 fun specialize_consts_in_term (ext_ctxt as {thy, specialize, simp_table,
2567 special_funs, ...}) depth t =
2568 if not specialize orelse depth > special_depth then
2572 val blacklist = if depth = 0 then []
2573 else case term_under_def t of Const x => [x] | _ => []
2574 (* term list -> typ list -> term -> term *)
2575 fun aux args Ts (Const (x as (s, T))) =
2576 ((if not (x mem blacklist) andalso not (null args)
2577 andalso not (String.isPrefix special_prefix s)
2578 andalso is_equational_fun ext_ctxt x then
2580 val eligible_args = filter (is_eligible_arg Ts o snd)
2581 (index_seq 0 (length args) ~~ args)
2582 val _ = not (null eligible_args) orelse raise SAME ()
2583 val old_axs = equational_fun_axioms ext_ctxt x
2584 |> map (destroy_existential_equalities thy)
2585 val static_params = static_args_in_terms ext_ctxt x old_axs
2586 val fixed_js = overlapping_indices static_params eligible_args
2587 val _ = not (null fixed_js) orelse raise SAME ()
2588 val fixed_args = filter_indices fixed_js args
2589 val vars = fold Term.add_vars fixed_args []
2590 |> sort (TermOrd.fast_indexname_ord o pairself fst)
2591 val bound_js = fold (fn t => fn js => add_loose_bnos (t, 0, js))
2594 val live_args = filter_out_indices fixed_js args
2595 val extra_args = map Var vars @ map Bound bound_js @ live_args
2596 val extra_Ts = map snd vars @ filter_indices bound_js Ts
2597 val k = maxidx_of_term t + 1
2599 fun var_for_bound_no j =
2600 Var ((bound_var_prefix ^
2601 nat_subscript (find_index (equal j) bound_js + 1), k),
2603 val fixed_args_in_axiom =
2604 map (curry subst_bounds
2605 (map var_for_bound_no (index_seq 0 (length Ts))))
2608 case AList.lookup (op =) (!special_funs)
2609 (x, fixed_js, fixed_args_in_axiom) of
2610 SOME x' => list_comb (Const x', extra_args)
2613 val extra_args_in_axiom =
2614 map Var vars @ map var_for_bound_no bound_js
2616 (special_prefix_for (length (!special_funs) + 1) ^ s,
2617 extra_Ts @ filter_out_indices fixed_js (binder_types T)
2620 map (specialize_fun_axiom x x' fixed_js
2621 fixed_args_in_axiom extra_args_in_axiom) old_axs
2623 Unsynchronized.change special_funs
2624 (cons ((x, fixed_js, fixed_args_in_axiom), x'))
2625 val _ = add_simps simp_table s' new_axs
2626 in list_comb (Const x', extra_args) end
2630 handle SAME () => list_comb (Const x, args))
2631 | aux args Ts (Abs (s, T, t)) =
2632 list_comb (Abs (s, T, aux [] (T :: Ts) t), args)
2633 | aux args Ts (t1 $ t2) = aux (aux [] Ts t2 :: args) Ts t1
2634 | aux args _ t = list_comb (t, args)
2637 (* theory -> term -> int Termtab.tab -> int Termtab.tab *)
2638 fun add_to_uncurry_table thy t =
2640 (* term -> term list -> int Termtab.tab -> int Termtab.tab *)
2641 fun aux (t1 $ t2) args table =
2642 let val table = aux t2 [] table in aux t1 (t2 :: args) table end
2643 | aux (Abs (_, _, t')) _ table = aux t' [] table
2644 | aux (t as Const (x as (s, _))) args table =
2645 if is_built_in_const false x orelse is_constr_like thy x orelse is_sel s
2646 orelse s = @{const_name Sigma} then
2649 Termtab.map_default (t, 65536) (curry Int.min (length args)) table
2650 | aux _ _ table = table
2653 (* int Termtab.tab term -> term *)
2654 fun uncurry_term table t =
2656 (* term -> term list -> term *)
2657 fun aux (t1 $ t2) args = aux t1 (aux t2 [] :: args)
2658 | aux (Abs (s, T, t')) args = betapplys (Abs (s, T, aux t' []), args)
2659 | aux (t as Const (s, T)) args =
2660 (case Termtab.lookup table t of
2664 val (arg_Ts, rest_T) = strip_n_binders n T
2666 if hd arg_Ts = @{typ bisim_iterator}
2667 orelse is_fp_iterator_type (hd arg_Ts) then
2669 else case find_index (not_equal bool_T) arg_Ts of
2672 val ((before_args, tuple_args), after_args) =
2673 args |> chop n |>> chop j
2674 val ((before_arg_Ts, tuple_arg_Ts), rest_T) =
2675 T |> strip_n_binders n |>> chop j
2676 val tuple_T = HOLogic.mk_tupleT tuple_arg_Ts
2681 betapplys (Const (uncurry_prefix_for (n - j) j ^ s,
2682 before_arg_Ts ---> tuple_T --> rest_T),
2683 before_args @ [mk_flat_tuple tuple_T tuple_args] @
2688 | NONE => betapplys (t, args))
2689 | aux t args = betapplys (t, args)
2692 (* (term -> term) -> int -> term -> term *)
2693 fun coerce_bound_no f j t =
2695 t1 $ t2 => coerce_bound_no f j t1 $ coerce_bound_no f j t2
2696 | Abs (s, T, t') => Abs (s, T, coerce_bound_no f (j + 1) t')
2697 | Bound j' => if j' = j then f t else t
2700 (* extended_context -> bool -> term -> term *)
2701 fun box_fun_and_pair_in_term (ext_ctxt as {thy, fast_descrs, ...}) def orig_t =
2704 fun box_relational_operator_type (Type ("fun", Ts)) =
2705 Type ("fun", map box_relational_operator_type Ts)
2706 | box_relational_operator_type (Type ("*", Ts)) =
2707 Type ("*", map (box_type ext_ctxt InPair) Ts)
2708 | box_relational_operator_type T = T
2709 (* typ -> typ -> term -> term *)
2710 fun coerce_bound_0_in_term new_T old_T =
2711 old_T <> new_T ? coerce_bound_no (coerce_term [new_T] old_T new_T) 0
2712 (* typ list -> typ -> term -> term *)
2713 and coerce_term Ts new_T old_T t =
2714 if old_T = new_T then
2717 case (new_T, old_T) of
2718 (Type (new_s, new_Ts as [new_T1, new_T2]),
2719 Type ("fun", [old_T1, old_T2])) =>
2720 (case eta_expand Ts t 1 of
2723 t' |> coerce_bound_0_in_term new_T1 old_T1
2724 |> coerce_term (new_T1 :: Ts) new_T2 old_T2)
2725 |> Envir.eta_contract
2727 ? construct_value thy (@{const_name FunBox},
2728 Type ("fun", new_Ts) --> new_T) o single
2729 | t' => raise TERM ("Nitpick_HOL.box_fun_and_pair_in_term.\
2730 \coerce_term", [t']))
2731 | (Type (new_s, new_Ts as [new_T1, new_T2]),
2732 Type (old_s, old_Ts as [old_T1, old_T2])) =>
2733 if old_s mem [@{type_name fun_box}, @{type_name pair_box}, "*"] then
2734 case constr_expand ext_ctxt old_T t of
2735 Const (@{const_name FunBox}, _) $ t1 =>
2736 if new_s = "fun" then
2737 coerce_term Ts new_T (Type ("fun", old_Ts)) t1
2740 (@{const_name FunBox}, Type ("fun", new_Ts) --> new_T)
2741 [coerce_term Ts (Type ("fun", new_Ts))
2742 (Type ("fun", old_Ts)) t1]
2743 | Const _ $ t1 $ t2 =>
2745 (if new_s = "*" then @{const_name Pair}
2746 else @{const_name PairBox}, new_Ts ---> new_T)
2747 [coerce_term Ts new_T1 old_T1 t1,
2748 coerce_term Ts new_T2 old_T2 t2]
2749 | t' => raise TERM ("Nitpick_HOL.box_fun_and_pair_in_term.\
2750 \coerce_term", [t'])
2752 raise TYPE ("coerce_term", [new_T, old_T], [t])
2753 | _ => raise TYPE ("coerce_term", [new_T, old_T], [t])
2754 (* indexname * typ -> typ * term -> typ option list -> typ option list *)
2755 fun add_boxed_types_for_var (z as (_, T)) (T', t') =
2757 Var z' => z' = z ? insert (op =) T'
2758 | Const (@{const_name Pair}, _) $ t1 $ t2 =>
2760 Type (_, [T1, T2]) =>
2761 fold (add_boxed_types_for_var z) [(T1, t1), (T2, t2)]
2762 | _ => raise TYPE ("Nitpick_HOL.box_fun_and_pair_in_term.\
2763 \add_boxed_types_for_var", [T'], []))
2764 | _ => exists_subterm (equal (Var z)) t' ? insert (op =) T
2765 (* typ list -> typ list -> term -> indexname * typ -> typ *)
2766 fun box_var_in_def new_Ts old_Ts t (z as (_, T)) =
2768 @{const Trueprop} $ t1 => box_var_in_def new_Ts old_Ts t1 z
2769 | Const (s0, _) $ t1 $ _ =>
2770 if s0 mem [@{const_name "=="}, @{const_name "op ="}] then
2772 val (t', args) = strip_comb t1
2773 val T' = fastype_of1 (new_Ts, do_term new_Ts old_Ts Neut t')
2775 case fold (add_boxed_types_for_var z)
2776 (fst (strip_n_binders (length args) T') ~~ args) [] of
2783 (* typ list -> typ list -> polarity -> string -> typ -> string -> typ
2785 and do_quantifier new_Ts old_Ts polar quant_s quant_T abs_s abs_T t =
2788 if polar = Neut orelse is_positive_existential polar quant_s then
2789 box_type ext_ctxt InFunLHS abs_T
2792 val body_T = body_type quant_T
2794 Const (quant_s, (abs_T' --> body_T) --> body_T)
2795 $ Abs (abs_s, abs_T',
2796 t |> do_term (abs_T' :: new_Ts) (abs_T :: old_Ts) polar)
2798 (* typ list -> typ list -> string -> typ -> term -> term -> term *)
2799 and do_equals new_Ts old_Ts s0 T0 t1 t2 =
2801 val (t1, t2) = pairself (do_term new_Ts old_Ts Neut) (t1, t2)
2802 val (T1, T2) = pairself (curry fastype_of1 new_Ts) (t1, t2)
2803 val T = [T1, T2] |> sort TermOrd.typ_ord |> List.last
2805 list_comb (Const (s0, [T, T] ---> body_type T0),
2806 map2 (coerce_term new_Ts T) [T1, T2] [t1, t2])
2808 (* string -> typ -> term *)
2809 and do_description_operator s T =
2810 let val T1 = box_type ext_ctxt InFunLHS (range_type T) in
2811 Const (s, (T1 --> bool_T) --> T1)
2813 (* typ list -> typ list -> polarity -> term -> term *)
2814 and do_term new_Ts old_Ts polar t =
2816 Const (s0 as @{const_name all}, T0) $ Abs (s1, T1, t1) =>
2817 do_quantifier new_Ts old_Ts polar s0 T0 s1 T1 t1
2818 | Const (s0 as @{const_name "=="}, T0) $ t1 $ t2 =>
2819 do_equals new_Ts old_Ts s0 T0 t1 t2
2820 | @{const "==>"} $ t1 $ t2 =>
2821 @{const "==>"} $ do_term new_Ts old_Ts (flip_polarity polar) t1
2822 $ do_term new_Ts old_Ts polar t2
2823 | @{const Pure.conjunction} $ t1 $ t2 =>
2824 @{const Pure.conjunction} $ do_term new_Ts old_Ts polar t1
2825 $ do_term new_Ts old_Ts polar t2
2826 | @{const Trueprop} $ t1 =>
2827 @{const Trueprop} $ do_term new_Ts old_Ts polar t1
2828 | @{const Not} $ t1 =>
2829 @{const Not} $ do_term new_Ts old_Ts (flip_polarity polar) t1
2830 | Const (s0 as @{const_name All}, T0) $ Abs (s1, T1, t1) =>
2831 do_quantifier new_Ts old_Ts polar s0 T0 s1 T1 t1
2832 | Const (s0 as @{const_name Ex}, T0) $ Abs (s1, T1, t1) =>
2833 do_quantifier new_Ts old_Ts polar s0 T0 s1 T1 t1
2834 | Const (s0 as @{const_name "op ="}, T0) $ t1 $ t2 =>
2835 do_equals new_Ts old_Ts s0 T0 t1 t2
2836 | @{const "op &"} $ t1 $ t2 =>
2837 @{const "op &"} $ do_term new_Ts old_Ts polar t1
2838 $ do_term new_Ts old_Ts polar t2
2839 | @{const "op |"} $ t1 $ t2 =>
2840 @{const "op |"} $ do_term new_Ts old_Ts polar t1
2841 $ do_term new_Ts old_Ts polar t2
2842 | @{const "op -->"} $ t1 $ t2 =>
2843 @{const "op -->"} $ do_term new_Ts old_Ts (flip_polarity polar) t1
2844 $ do_term new_Ts old_Ts polar t2
2845 | Const (s as @{const_name The}, T) => do_description_operator s T
2846 | Const (s as @{const_name Eps}, T) => do_description_operator s T
2847 | Const (s as @{const_name Tha}, T) => do_description_operator s T
2848 | Const (x as (s, T)) =>
2849 Const (s, if s mem [@{const_name converse}, @{const_name trancl}] then
2850 box_relational_operator_type T
2851 else if is_built_in_const fast_descrs x
2852 orelse s = @{const_name Sigma} then
2854 else if is_constr_like thy x then
2855 box_type ext_ctxt InConstr T
2856 else if is_sel s orelse is_rep_fun thy x then
2857 box_type ext_ctxt InSel T
2859 box_type ext_ctxt InExpr T)
2860 | t1 $ Abs (s, T, t2') =>
2862 val t1 = do_term new_Ts old_Ts Neut t1
2863 val T1 = fastype_of1 (new_Ts, t1)
2864 val (s1, Ts1) = dest_Type T1
2865 val T' = hd (snd (dest_Type (hd Ts1)))
2866 val t2 = Abs (s, T', do_term (T' :: new_Ts) (T :: old_Ts) Neut t2')
2867 val T2 = fastype_of1 (new_Ts, t2)
2868 val t2 = coerce_term new_Ts (hd Ts1) T2 t2
2870 betapply (if s1 = "fun" then
2873 select_nth_constr_arg thy
2874 (@{const_name FunBox}, Type ("fun", Ts1) --> T1) t1 0
2875 (Type ("fun", Ts1)), t2)
2879 val t1 = do_term new_Ts old_Ts Neut t1
2880 val T1 = fastype_of1 (new_Ts, t1)
2881 val (s1, Ts1) = dest_Type T1
2882 val t2 = do_term new_Ts old_Ts Neut t2
2883 val T2 = fastype_of1 (new_Ts, t2)
2884 val t2 = coerce_term new_Ts (hd Ts1) T2 t2
2886 betapply (if s1 = "fun" then
2889 select_nth_constr_arg thy
2890 (@{const_name FunBox}, Type ("fun", Ts1) --> T1) t1 0
2891 (Type ("fun", Ts1)), t2)
2893 | Free (s, T) => Free (s, box_type ext_ctxt InExpr T)
2894 | Var (z as (x, T)) =>
2895 Var (x, if def then box_var_in_def new_Ts old_Ts orig_t z
2896 else box_type ext_ctxt InExpr T)
2899 Abs (s, T, do_term (T :: new_Ts) (T :: old_Ts) Neut t')
2900 in do_term [] [] Pos orig_t end
2902 (* int -> term -> term *)
2903 fun eval_axiom_for_term j t =
2904 Logic.mk_equals (Const (eval_prefix ^ string_of_int j, fastype_of t), t)
2906 (* extended_context -> styp -> bool *)
2907 fun is_equational_fun_surely_complete ext_ctxt x =
2908 case raw_equational_fun_axioms ext_ctxt x of
2909 [@{const Trueprop} $ (Const (@{const_name "op ="}, _) $ t1 $ _)] =>
2910 strip_comb t1 |> snd |> forall is_Var
2913 type special = int list * term list * styp
2915 (* styp -> special -> special -> term *)
2916 fun special_congruence_axiom (s, T) (js1, ts1, x1) (js2, ts2, x2) =
2918 val (bounds1, bounds2) = pairself (map Var o special_bounds) (ts1, ts2)
2919 val Ts = binder_types T
2920 val max_j = fold (fold (curry Int.max)) [js1, js2] ~1
2921 val (eqs, (args1, args2)) =
2922 fold (fn j => case pairself (fn ps => AList.lookup (op =) ps j)
2923 (js1 ~~ ts1, js2 ~~ ts2) of
2924 (SOME t1, SOME t2) => apfst (cons (t1, t2))
2925 | (SOME t1, NONE) => apsnd (apsnd (cons t1))
2926 | (NONE, SOME t2) => apsnd (apfst (cons t2))
2928 let val v = Var ((cong_var_prefix ^ nat_subscript j, 0),
2930 apsnd (pairself (cons v))
2931 end) (max_j downto 0) ([], ([], []))
2933 Logic.list_implies (eqs |> filter_out (op =) |> distinct (op =)
2934 |> map Logic.mk_equals,
2935 Logic.mk_equals (list_comb (Const x1, bounds1 @ args1),
2936 list_comb (Const x2, bounds2 @ args2)))
2937 |> Refute.close_form
2940 (* extended_context -> styp list -> term list *)
2941 fun special_congruence_axioms (ext_ctxt as {special_funs, ...}) xs =
2945 |> map (fn ((x, js, ts), x') => (x, (js, ts, x')))
2946 |> AList.group (op =)
2947 |> filter_out (is_equational_fun_surely_complete ext_ctxt o fst)
2948 |> map (fn (x, zs) => (x, zs |> (x mem xs) ? cons ([], [], x)))
2949 (* special -> int *)
2950 fun generality (js, _, _) = ~(length js)
2951 (* special -> special -> bool *)
2952 fun is_more_specific (j1, t1, x1) (j2, t2, x2) =
2953 x1 <> x2 andalso OrdList.subset (prod_ord int_ord TermOrd.term_ord)
2954 (j2 ~~ t2, j1 ~~ t1)
2955 (* styp -> special list -> special list -> special list -> term list
2957 fun do_pass_1 _ [] [_] [_] = I
2958 | do_pass_1 x skipped _ [] = do_pass_2 x skipped
2959 | do_pass_1 x skipped all (z :: zs) =
2960 case filter (is_more_specific z) all
2961 |> sort (int_ord o pairself generality) of
2962 [] => do_pass_1 x (z :: skipped) all zs
2963 | (z' :: _) => cons (special_congruence_axiom x z z')
2964 #> do_pass_1 x skipped all zs
2965 (* styp -> special list -> term list -> term list *)
2966 and do_pass_2 _ [] = I
2967 | do_pass_2 x (z :: zs) =
2968 fold (cons o special_congruence_axiom x z) zs #> do_pass_2 x zs
2969 in fold (fn (x, zs) => do_pass_1 x [] zs zs) groups [] end
2972 val is_trivial_equation = the_default false o try (op aconv o Logic.dest_equals)
2974 (* 'a Symtab.table -> 'a list *)
2975 fun all_table_entries table = Symtab.fold (append o snd) table []
2976 (* const_table -> string -> const_table *)
2977 fun extra_table table s = Symtab.make [(s, all_table_entries table)]
2979 (* extended_context -> term -> (term list * term list) * (bool * bool) *)
2981 (ext_ctxt as {thy, max_bisim_depth, user_axioms, fast_descrs, evals,
2982 def_table, nondef_table, user_nondefs, ...}) t =
2984 type accumulator = styp list * (term list * term list)
2985 (* (term list * term list -> term list)
2986 -> ((term list -> term list) -> term list * term list
2987 -> term list * term list)
2988 -> int -> term -> accumulator -> accumulator *)
2989 fun add_axiom get app depth t (accum as (xs, axs)) =
2991 val t = t |> unfold_defs_in_term ext_ctxt
2992 |> skolemize_term_and_more ext_ctxt ~1
2994 if is_trivial_equation t then
2997 let val t' = t |> specialize_consts_in_term ext_ctxt depth in
2998 if exists (member (op aconv) (get axs)) [t, t'] then accum
2999 else add_axioms_for_term (depth + 1) t' (xs, app (cons t') axs)
3002 (* int -> term -> accumulator -> accumulator *)
3003 and add_nondef_axiom depth = add_axiom snd apsnd depth
3004 and add_def_axiom depth t =
3005 (if head_of t = @{const "==>"} then add_nondef_axiom
3006 else add_axiom fst apfst) depth t
3007 (* int -> term -> accumulator -> accumulator *)
3008 and add_axioms_for_term depth t (accum as (xs, axs)) =
3010 t1 $ t2 => accum |> fold (add_axioms_for_term depth) [t1, t2]
3011 | Const (x as (s, T)) =>
3012 (if x mem xs orelse is_built_in_const fast_descrs x then
3015 let val accum as (xs, _) = (x :: xs, axs) in
3016 if depth > axioms_max_depth then
3017 raise LIMIT ("Nitpick_HOL.axioms_for_term.add_axioms_for_term",
3018 "too many nested axioms (" ^ string_of_int depth ^
3020 else if Refute.is_const_of_class thy x then
3022 val class = Logic.class_of_const s
3023 val of_class = Logic.mk_of_class (TVar (("'a", 0), [class]),
3025 val ax1 = try (Refute.specialize_type thy x) of_class
3026 val ax2 = Option.map (Refute.specialize_type thy x o snd)
3027 (Refute.get_classdef thy class)
3028 in fold (add_def_axiom depth) (map_filter I [ax1, ax2]) accum end
3029 else if is_constr thy x then
3031 else if is_equational_fun ext_ctxt x then
3032 fold (add_def_axiom depth) (equational_fun_axioms ext_ctxt x)
3034 else if is_abs_fun thy x then
3035 accum |> fold (add_nondef_axiom depth)
3036 (nondef_props_for_const thy false nondef_table x)
3037 |> is_funky_typedef thy (range_type T)
3038 ? fold (add_def_axiom depth)
3039 (nondef_props_for_const thy true
3040 (extra_table def_table s) x)
3041 else if is_rep_fun thy x then
3042 accum |> fold (add_nondef_axiom depth)
3043 (nondef_props_for_const thy false nondef_table x)
3044 |> is_funky_typedef thy (range_type T)
3045 ? fold (add_def_axiom depth)
3046 (nondef_props_for_const thy true
3047 (extra_table def_table s) x)
3048 |> add_axioms_for_term depth
3049 (Const (mate_of_rep_fun thy x))
3050 |> add_def_axiom depth (inverse_axiom_for_rep_fun thy x)
3052 accum |> user_axioms <> SOME false
3053 ? fold (add_nondef_axiom depth)
3054 (nondef_props_for_const thy false nondef_table x)
3056 |> add_axioms_for_type depth T
3057 | Free (_, T) => add_axioms_for_type depth T accum
3058 | Var (_, T) => add_axioms_for_type depth T accum
3060 | Abs (_, T, t) => accum |> add_axioms_for_term depth t
3061 |> add_axioms_for_type depth T
3062 (* int -> typ -> accumulator -> accumulator *)
3063 and add_axioms_for_type depth T =
3065 Type ("fun", Ts) => fold (add_axioms_for_type depth) Ts
3066 | Type ("*", Ts) => fold (add_axioms_for_type depth) Ts
3070 | TFree (_, S) => add_axioms_for_sort depth T S
3071 | TVar (_, S) => add_axioms_for_sort depth T S
3072 | Type (z as (_, Ts)) =>
3073 fold (add_axioms_for_type depth) Ts
3074 #> (if is_pure_typedef thy T then
3075 fold (add_def_axiom depth) (optimized_typedef_axioms thy z)
3076 else if max_bisim_depth >= 0 andalso is_codatatype thy T then
3077 fold (add_def_axiom depth) (codatatype_bisim_axioms ext_ctxt T)
3080 (* int -> typ -> sort -> accumulator -> accumulator *)
3081 and add_axioms_for_sort depth T S =
3083 val supers = Sign.complete_sort thy S
3085 maps (fn class => map prop_of (AxClass.get_info thy class |> #axioms
3086 handle ERROR _ => [])) supers
3087 val monomorphic_class_axioms =
3088 map (fn t => case Term.add_tvars t [] of
3091 Refute.monomorphic_term (Vartab.make [(x, (S, T))]) t
3092 | _ => raise TERM ("Nitpick_HOL.axioms_for_term.\
3093 \add_axioms_for_sort", [t]))
3095 in fold (add_nondef_axiom depth) monomorphic_class_axioms end
3096 val (mono_user_nondefs, poly_user_nondefs) =
3097 List.partition (null o Term.hidden_polymorphism) user_nondefs
3098 val eval_axioms = map2 eval_axiom_for_term (index_seq 0 (length evals))
3100 val (xs, (defs, nondefs)) =
3101 ([], ([], [])) |> add_axioms_for_term 1 t
3102 |> fold_rev (add_def_axiom 1) eval_axioms
3103 |> user_axioms = SOME true
3104 ? fold (add_nondef_axiom 1) mono_user_nondefs
3105 val defs = defs @ special_congruence_axioms ext_ctxt xs
3107 ((defs, nondefs), (user_axioms = SOME true orelse null mono_user_nondefs,
3108 null poly_user_nondefs))
3111 (* theory -> const_table -> styp -> int list *)
3112 fun const_format thy def_table (x as (s, T)) =
3113 if String.isPrefix unrolled_prefix s then
3114 const_format thy def_table (original_name s, range_type T)
3115 else if String.isPrefix skolem_prefix s then
3117 val k = unprefix skolem_prefix s
3118 |> strip_first_name_sep |> fst |> space_explode "@"
3119 |> hd |> Int.fromString |> the
3120 in [k, num_binder_types T - k] end
3121 else if original_name s <> s then
3122 [num_binder_types T]
3123 else case def_of_const thy def_table x of
3124 SOME t' => if fixpoint_kind_of_rhs t' <> NoFp then
3125 let val k = length (strip_abs_vars t') in
3126 [k, num_binder_types T - k]
3129 [num_binder_types T]
3130 | NONE => [num_binder_types T]
3131 (* int list -> int list -> int list *)
3132 fun intersect_formats _ [] = []
3133 | intersect_formats [] _ = []
3134 | intersect_formats ks1 ks2 =
3135 let val ((ks1', k1), (ks2', k2)) = pairself split_last (ks1, ks2) in
3136 intersect_formats (ks1' @ (if k1 > k2 then [k1 - k2] else []))
3137 (ks2' @ (if k2 > k1 then [k2 - k1] else [])) @
3141 (* theory -> const_table -> (term option * int list) list -> term -> int list *)
3142 fun lookup_format thy def_table formats t =
3143 case AList.lookup (fn (SOME x, SOME y) =>
3144 (term_match thy) (x, y) | _ => false)
3146 SOME format => format
3147 | NONE => let val format = the (AList.lookup (op =) formats NONE) in
3149 Const x => intersect_formats format
3150 (const_format thy def_table x)
3154 (* int list -> int list -> typ -> typ *)
3155 fun format_type default_format format T =
3157 val T = unbox_type T
3158 val format = format |> filter (curry (op <) 0)
3160 if forall (equal 1) format then
3164 val (binder_Ts, body_T) = strip_type T
3167 |> map (format_type default_format default_format)
3168 |> rev |> chunk_list_unevenly (rev format)
3169 |> map (HOLogic.mk_tupleT o rev)
3170 in List.foldl (op -->) body_T batched end
3172 (* theory -> const_table -> (term option * int list) list -> term -> typ *)
3173 fun format_term_type thy def_table formats t =
3174 format_type (the (AList.lookup (op =) formats NONE))
3175 (lookup_format thy def_table formats t) (fastype_of t)
3177 (* int list -> int -> int list -> int list *)
3178 fun repair_special_format js m format =
3179 m - 1 downto 0 |> chunk_list_unevenly (rev format)
3180 |> map (rev o filter_out (member (op =) js))
3181 |> filter_out null |> map length |> rev
3183 (* extended_context -> string * string -> (term option * int list) list
3184 -> styp -> term * typ *)
3185 fun user_friendly_const ({thy, evals, def_table, skolems, special_funs, ...}
3186 : extended_context) (base_name, step_name) formats =
3188 val default_format = the (AList.lookup (op =) formats NONE)
3189 (* styp -> term * typ *)
3190 fun do_const (x as (s, T)) =
3191 (if String.isPrefix special_prefix s then
3194 val do_term = map_aterms (fn Const x => fst (do_const x) | t' => t')
3195 val (x' as (_, T'), js, ts) =
3196 AList.find (op =) (!special_funs) (s, unbox_type T) |> the_single
3197 val max_j = List.last js
3198 val Ts = List.take (binder_types T', max_j + 1)
3199 val missing_js = filter_out (member (op =) js) (0 upto max_j)
3200 val missing_Ts = filter_indices missing_js Ts
3201 (* int -> indexname *)
3202 fun nth_missing_var n =
3203 ((arg_var_prefix ^ nat_subscript (n + 1), 0), nth missing_Ts n)
3204 val missing_vars = map nth_missing_var (0 upto length missing_js - 1)
3205 val vars = special_bounds ts @ missing_vars
3206 val ts' = map2 (fn T => fn j =>
3207 case AList.lookup (op =) (js ~~ ts) j of
3210 Var (nth missing_vars
3211 (find_index (equal j) missing_js)))
3213 val t = do_const x' |> fst
3215 case AList.lookup (fn (SOME t1, SOME t2) => term_match thy (t1, t2)
3216 | _ => false) formats (SOME t) of
3218 repair_special_format js (num_binder_types T') format
3220 const_format thy def_table x'
3221 |> repair_special_format js (num_binder_types T')
3222 |> intersect_formats default_format
3224 (list_comb (t, ts') |> fold_rev abs_var vars,
3225 format_type default_format format T)
3227 else if String.isPrefix uncurry_prefix s then
3229 val (ss, s') = unprefix uncurry_prefix s
3230 |> strip_first_name_sep |>> space_explode "@"
3232 if String.isPrefix step_prefix s' then
3236 val k = the (Int.fromString (hd ss))
3237 val j = the (Int.fromString (List.last ss))
3238 val (before_Ts, (tuple_T, rest_T)) =
3239 strip_n_binders j T ||> (strip_n_binders 1 #>> hd)
3240 val T' = before_Ts ---> dest_n_tuple_type k tuple_T ---> rest_T
3241 in do_const (s', T') end
3243 else if String.isPrefix unrolled_prefix s then
3244 let val t = Const (original_name s, range_type T) in
3245 (lambda (Free (iter_var_prefix, nat_T)) t,
3246 format_type default_format
3247 (lookup_format thy def_table formats t) T)
3249 else if String.isPrefix base_prefix s then
3250 (Const (base_name, T --> T) $ Const (unprefix base_prefix s, T),
3251 format_type default_format default_format T)
3252 else if String.isPrefix step_prefix s then
3253 (Const (step_name, T --> T) $ Const (unprefix step_prefix s, T),
3254 format_type default_format default_format T)
3255 else if String.isPrefix skolem_prefix s then
3257 val ss = the (AList.lookup (op =) (!skolems) s)
3258 val (Ts, Ts') = chop (length ss) (binder_types T)
3259 val frees = map Free (ss ~~ Ts)
3260 val s' = original_name s
3262 (fold lambda frees (Const (s', Ts' ---> T)),
3263 format_type default_format
3264 (lookup_format thy def_table formats (Const x)) T)
3266 else if String.isPrefix eval_prefix s then
3268 val t = nth evals (the (Int.fromString (unprefix eval_prefix s)))
3269 in (t, format_term_type thy def_table formats t) end
3270 else if s = @{const_name undefined_fast_The} then
3271 (Const (nitpick_prefix ^ "The fallback", T),
3272 format_type default_format
3273 (lookup_format thy def_table formats
3274 (Const (@{const_name The}, (T --> bool_T) --> T))) T)
3275 else if s = @{const_name undefined_fast_Eps} then
3276 (Const (nitpick_prefix ^ "Eps fallback", T),
3277 format_type default_format
3278 (lookup_format thy def_table formats
3279 (Const (@{const_name Eps}, (T --> bool_T) --> T))) T)
3281 let val t = Const (original_name s, T) in
3282 (t, format_term_type thy def_table formats t)
3284 |>> map_types (typ_subst [(@{typ bisim_iterator}, nat_T)] o unbox_type)
3285 |>> shorten_const_names_in_term |>> shorten_abs_vars
3288 (* styp -> string *)
3289 fun assign_operator_for_const (s, T) =
3290 if String.isPrefix ubfp_prefix s then
3291 if is_fun_type T then "\<subseteq>" else "\<le>"
3292 else if String.isPrefix lbfp_prefix s then
3293 if is_fun_type T then "\<supseteq>" else "\<ge>"
3294 else if original_name s <> s then
3295 assign_operator_for_const (after_name_sep s, T)
3299 (* extended_context -> term
3300 -> ((term list * term list) * (bool * bool)) * term *)
3301 fun preprocess_term (ext_ctxt as {thy, destroy_constrs, boxes, skolemize,
3304 val skolem_depth = if skolemize then 4 else ~1
3305 val (((def_ts, nondef_ts), (got_all_mono_user_axioms, no_poly_user_axioms)),
3306 core_t) = t |> unfold_defs_in_term ext_ctxt
3307 |> Refute.close_form
3308 |> skolemize_term_and_more ext_ctxt skolem_depth
3309 |> specialize_consts_in_term ext_ctxt 0
3310 |> `(axioms_for_term ext_ctxt)
3311 val maybe_box = exists (not_equal (SOME false) o snd) boxes
3313 Termtab.empty |> uncurry
3314 ? fold (add_to_uncurry_table thy) (core_t :: def_ts @ nondef_ts)
3315 (* bool -> bool -> term -> term *)
3316 fun do_rest def core =
3317 uncurry ? uncurry_term table
3318 #> maybe_box ? box_fun_and_pair_in_term ext_ctxt def
3319 #> destroy_constrs ? (pull_out_universal_constrs thy def
3320 #> pull_out_existential_constrs thy
3321 #> destroy_pulled_out_constrs ext_ctxt def)
3323 #> destroy_universal_equalities
3324 #> destroy_existential_equalities thy
3325 #> simplify_constrs_and_sels thy
3326 #> distribute_quantifiers
3327 #> push_quantifiers_inward thy
3328 #> not core ? Refute.close_form
3331 (((map (do_rest true false) def_ts, map (do_rest false false) nondef_ts),
3332 (got_all_mono_user_axioms, no_poly_user_axioms)),
3333 do_rest false true core_t)