src/HOL/Tools/ATP/atp_problem_generate.ML
author wenzelm
Sat Mar 22 18:19:57 2014 +0100 (2014-03-22)
changeset 56254 a2dd9200854d
parent 56245 84fc7dfa3cd4
child 56636 bb8b37480d3f
permissions -rw-r--r--
more antiquotations;
     1 (*  Title:      HOL/Tools/ATP/atp_problem_generate.ML
     2     Author:     Fabian Immler, TU Muenchen
     3     Author:     Makarius
     4     Author:     Jasmin Blanchette, TU Muenchen
     5 
     6 Translation of HOL to FOL for Metis and Sledgehammer.
     7 *)
     8 
     9 signature ATP_PROBLEM_GENERATE =
    10 sig
    11   type ('a, 'b) atp_term = ('a, 'b) ATP_Problem.atp_term
    12   type atp_connective = ATP_Problem.atp_connective
    13   type ('a, 'b, 'c, 'd) atp_formula = ('a, 'b, 'c, 'd) ATP_Problem.atp_formula
    14   type atp_format = ATP_Problem.atp_format
    15   type atp_formula_role = ATP_Problem.atp_formula_role
    16   type 'a atp_problem = 'a ATP_Problem.atp_problem
    17 
    18   datatype mode = Metis | Sledgehammer | Sledgehammer_Completish | Exporter | Translator
    19 
    20   datatype scope = Global | Local | Assum | Chained
    21   datatype status = General | Induction | Intro | Inductive | Elim | Simp | Non_Rec_Def | Rec_Def
    22 
    23   type stature = scope * status
    24 
    25   datatype strictness = Strict | Non_Strict
    26   datatype uniformity = Uniform | Non_Uniform
    27   datatype ctr_optim = With_Ctr_Optim | Without_Ctr_Optim
    28   datatype type_level =
    29     All_Types |
    30     Undercover_Types |
    31     Nonmono_Types of strictness * uniformity |
    32     Const_Types of ctr_optim |
    33     No_Types
    34   type type_enc
    35 
    36   val no_lamsN : string
    37   val hide_lamsN : string
    38   val liftingN : string
    39   val combsN : string
    40   val combs_and_liftingN : string
    41   val combs_or_liftingN : string
    42   val lam_liftingN : string
    43   val keep_lamsN : string
    44   val schematic_var_prefix : string
    45   val fixed_var_prefix : string
    46   val tvar_prefix : string
    47   val tfree_prefix : string
    48   val const_prefix : string
    49   val type_const_prefix : string
    50   val class_prefix : string
    51   val lam_lifted_prefix : string
    52   val lam_lifted_mono_prefix : string
    53   val lam_lifted_poly_prefix : string
    54   val skolem_const_prefix : string
    55   val old_skolem_const_prefix : string
    56   val new_skolem_const_prefix : string
    57   val combinator_prefix : string
    58   val class_decl_prefix : string
    59   val type_decl_prefix : string
    60   val sym_decl_prefix : string
    61   val datatype_decl_prefix : string
    62   val class_memb_prefix : string
    63   val guards_sym_formula_prefix : string
    64   val tags_sym_formula_prefix : string
    65   val fact_prefix : string
    66   val conjecture_prefix : string
    67   val helper_prefix : string
    68   val subclass_prefix : string
    69   val tcon_clause_prefix : string
    70   val tfree_clause_prefix : string
    71   val lam_fact_prefix : string
    72   val typed_helper_suffix : string
    73   val untyped_helper_suffix : string
    74   val predicator_name : string
    75   val app_op_name : string
    76   val type_guard_name : string
    77   val type_tag_name : string
    78   val native_type_prefix : string
    79   val prefixed_predicator_name : string
    80   val prefixed_app_op_name : string
    81   val prefixed_type_tag_name : string
    82   val ascii_of : string -> string
    83   val unascii_of : string -> string
    84   val unprefix_and_unascii : string -> string -> string option
    85   val proxy_table : (string * (string * (thm * (string * string)))) list
    86   val proxify_const : string -> (string * string) option
    87   val invert_const : string -> string
    88   val unproxify_const : string -> string
    89   val new_skolem_var_name_of_const : string -> string
    90   val atp_logical_consts : string list
    91   val atp_irrelevant_consts : string list
    92   val atp_widely_irrelevant_consts : string list
    93   val is_irrelevant_const : string -> bool
    94   val is_widely_irrelevant_const : string -> bool
    95   val atp_schematic_consts_of : term -> typ list Symtab.table
    96   val is_type_enc_higher_order : type_enc -> bool
    97   val is_type_enc_polymorphic : type_enc -> bool
    98   val level_of_type_enc : type_enc -> type_level
    99   val is_type_enc_sound : type_enc -> bool
   100   val type_enc_of_string : strictness -> string -> type_enc
   101   val adjust_type_enc : atp_format -> type_enc -> type_enc
   102   val is_lambda_free : term -> bool
   103   val mk_aconns :
   104     atp_connective -> ('a, 'b, 'c, 'd) atp_formula list
   105     -> ('a, 'b, 'c, 'd) atp_formula
   106   val unmangled_const : string -> string * (string, 'b) atp_term list
   107   val unmangled_const_name : string -> string list
   108   val helper_table : ((string * bool) * (status * thm) list) list
   109   val trans_lams_of_string :
   110     Proof.context -> type_enc -> string -> term list -> term list * term list
   111   val string_of_status : status -> string
   112   val factsN : string
   113   val prepare_atp_problem :
   114     Proof.context -> atp_format -> atp_formula_role -> type_enc -> mode
   115     -> string -> bool -> bool -> bool -> term list -> term
   116     -> ((string * stature) * term) list
   117     -> string atp_problem * string Symtab.table * (string * stature) list vector
   118        * (string * term) list * int Symtab.table
   119   val atp_problem_selection_weights : string atp_problem -> (string * real) list
   120   val atp_problem_term_order_info : string atp_problem -> (string * int) list
   121 end;
   122 
   123 structure ATP_Problem_Generate : ATP_PROBLEM_GENERATE =
   124 struct
   125 
   126 open ATP_Util
   127 open ATP_Problem
   128 
   129 datatype mode = Metis | Sledgehammer | Sledgehammer_Completish | Exporter | Translator
   130 
   131 datatype scope = Global | Local | Assum | Chained
   132 datatype status = General | Induction | Intro | Inductive | Elim | Simp | Non_Rec_Def | Rec_Def
   133 
   134 type stature = scope * status
   135 
   136 datatype order =
   137   First_Order |
   138   Higher_Order of thf_choice
   139 datatype phantom_policy = Without_Phantom_Type_Vars | With_Phantom_Type_Vars
   140 datatype polymorphism =
   141   Type_Class_Polymorphic |
   142   Raw_Polymorphic of phantom_policy |
   143   Raw_Monomorphic |
   144   Mangled_Monomorphic
   145 datatype strictness = Strict | Non_Strict
   146 datatype uniformity = Uniform | Non_Uniform
   147 datatype ctr_optim = With_Ctr_Optim | Without_Ctr_Optim
   148 datatype type_level =
   149   All_Types |
   150   Undercover_Types |
   151   Nonmono_Types of strictness * uniformity |
   152   Const_Types of ctr_optim |
   153   No_Types
   154 
   155 datatype type_enc =
   156   Native of order * polymorphism * type_level |
   157   Guards of polymorphism * type_level |
   158   Tags of polymorphism * type_level
   159 
   160 (* not clear whether ATPs prefer to have their negative variables tagged *)
   161 val tag_neg_vars = false
   162 
   163 fun is_type_enc_native (Native _) = true
   164   | is_type_enc_native _ = false
   165 fun is_type_enc_higher_order (Native (Higher_Order _, _, _)) = true
   166   | is_type_enc_higher_order _ = false
   167 
   168 fun polymorphism_of_type_enc (Native (_, poly, _)) = poly
   169   | polymorphism_of_type_enc (Guards (poly, _)) = poly
   170   | polymorphism_of_type_enc (Tags (poly, _)) = poly
   171 
   172 fun is_type_enc_polymorphic type_enc =
   173   (case polymorphism_of_type_enc type_enc of
   174     Raw_Polymorphic _ => true
   175   | Type_Class_Polymorphic => true
   176   | _ => false)
   177 
   178 fun is_type_enc_mangling type_enc =
   179   polymorphism_of_type_enc type_enc = Mangled_Monomorphic
   180 
   181 fun level_of_type_enc (Native (_, _, level)) = level
   182   | level_of_type_enc (Guards (_, level)) = level
   183   | level_of_type_enc (Tags (_, level)) = level
   184 
   185 fun is_type_level_uniform (Nonmono_Types (_, Non_Uniform)) = false
   186   | is_type_level_uniform Undercover_Types = false
   187   | is_type_level_uniform _ = true
   188 
   189 fun is_type_level_sound (Const_Types _) = false
   190   | is_type_level_sound No_Types = false
   191   | is_type_level_sound _ = true
   192 val is_type_enc_sound = is_type_level_sound o level_of_type_enc
   193 
   194 fun is_type_level_monotonicity_based (Nonmono_Types _) = true
   195   | is_type_level_monotonicity_based _ = false
   196 
   197 val no_lamsN = "no_lams" (* used internally; undocumented *)
   198 val hide_lamsN = "hide_lams"
   199 val liftingN = "lifting"
   200 val combsN = "combs"
   201 val combs_and_liftingN = "combs_and_lifting"
   202 val combs_or_liftingN = "combs_or_lifting"
   203 val keep_lamsN = "keep_lams"
   204 val lam_liftingN = "lam_lifting" (* legacy FIXME: remove *)
   205 
   206 val bound_var_prefix = "B_"
   207 val all_bound_var_prefix = "A_"
   208 val exist_bound_var_prefix = "E_"
   209 val schematic_var_prefix = "V_"
   210 val fixed_var_prefix = "v_"
   211 val tvar_prefix = "T_"
   212 val tfree_prefix = "tf_"
   213 val const_prefix = "c_"
   214 val type_const_prefix = "t_"
   215 val native_type_prefix = "n_"
   216 val class_prefix = "cl_"
   217 
   218 (* Freshness almost guaranteed! *)
   219 val atp_prefix = "ATP" ^ Long_Name.separator
   220 val atp_weak_prefix = "ATP:"
   221 val atp_weak_suffix = ":ATP"
   222 
   223 val lam_lifted_prefix = atp_weak_prefix ^ "Lam"
   224 val lam_lifted_mono_prefix = lam_lifted_prefix ^ "m"
   225 val lam_lifted_poly_prefix = lam_lifted_prefix ^ "p"
   226 
   227 val skolem_const_prefix = atp_prefix ^ "Sko"
   228 val old_skolem_const_prefix = skolem_const_prefix ^ "o"
   229 val new_skolem_const_prefix = skolem_const_prefix ^ "n"
   230 
   231 val combinator_prefix = "COMB"
   232 
   233 val class_decl_prefix = "cl_"
   234 val type_decl_prefix = "ty_"
   235 val sym_decl_prefix = "sy_"
   236 val datatype_decl_prefix = "dt_"
   237 val class_memb_prefix = "cm_"
   238 val guards_sym_formula_prefix = "gsy_"
   239 val tags_sym_formula_prefix = "tsy_"
   240 val uncurried_alias_eq_prefix = "unc_"
   241 val fact_prefix = "fact_"
   242 val conjecture_prefix = "conj_"
   243 val helper_prefix = "help_"
   244 val subclass_prefix = "subcl_"
   245 val tcon_clause_prefix = "tcon_"
   246 val tfree_clause_prefix = "tfree_"
   247 
   248 val lam_fact_prefix = "ATP.lambda_"
   249 val typed_helper_suffix = "_T"
   250 val untyped_helper_suffix = "_U"
   251 
   252 val predicator_name = "pp"
   253 val app_op_name = "aa"
   254 val type_guard_name = "gg"
   255 val type_tag_name = "tt"
   256 
   257 val prefixed_predicator_name = const_prefix ^ predicator_name
   258 val prefixed_app_op_name = const_prefix ^ app_op_name
   259 val prefixed_type_tag_name = const_prefix ^ type_tag_name
   260 
   261 (*Escaping of special characters.
   262   Alphanumeric characters are left unchanged.
   263   The character _ goes to __.
   264   Characters in the range ASCII space to / go to _A to _P, respectively.
   265   Other characters go to _nnn where nnn is the decimal ASCII code. *)
   266 val upper_a_minus_space = Char.ord #"A" - Char.ord #" "
   267 
   268 fun ascii_of_char c =
   269   if Char.isAlphaNum c then
   270     String.str c
   271   else if c = #"_" then
   272     "__"
   273   else if #" " <= c andalso c <= #"/" then
   274     "_" ^ String.str (Char.chr (Char.ord c + upper_a_minus_space))
   275   else
   276     (* fixed width, in case more digits follow *)
   277     "_" ^ stringN_of_int 3 (Char.ord c)
   278 
   279 val ascii_of = String.translate ascii_of_char
   280 
   281 (** Remove ASCII armoring from names in proof files **)
   282 
   283 (* We don't raise error exceptions because this code can run inside a worker
   284    thread. Also, the errors are impossible. *)
   285 val unascii_of =
   286   let
   287     fun un rcs [] = String.implode (rev rcs)
   288       | un rcs [#"_"] = un (#"_" :: rcs) [] (* ERROR *)
   289         (* Three types of _ escapes: __, _A to _P, _nnn *)
   290       | un rcs (#"_" :: #"_" :: cs) = un (#"_" :: rcs) cs
   291       | un rcs (#"_" :: c :: cs) =
   292         if #"A" <= c andalso c<= #"P" then
   293           (* translation of #" " to #"/" *)
   294           un (Char.chr (Char.ord c - upper_a_minus_space) :: rcs) cs
   295         else
   296           let val digits = List.take (c :: cs, 3) handle General.Subscript => [] in
   297             (case Int.fromString (String.implode digits) of
   298               SOME n => un (Char.chr n :: rcs) (List.drop (cs, 2))
   299             | NONE => un (c :: #"_" :: rcs) cs (* ERROR *))
   300           end
   301       | un rcs (c :: cs) = un (c :: rcs) cs
   302   in un [] o String.explode end
   303 
   304 (* If string s has the prefix s1, return the result of deleting it,
   305    un-ASCII'd. *)
   306 fun unprefix_and_unascii s1 s =
   307   if String.isPrefix s1 s then
   308     SOME (unascii_of (String.extract (s, size s1, NONE)))
   309   else
   310     NONE
   311 
   312 val proxy_table =
   313   [("c_False", (@{const_name False}, (@{thm fFalse_def},
   314        ("fFalse", @{const_name ATP.fFalse})))),
   315    ("c_True", (@{const_name True}, (@{thm fTrue_def},
   316        ("fTrue", @{const_name ATP.fTrue})))),
   317    ("c_Not", (@{const_name Not}, (@{thm fNot_def},
   318        ("fNot", @{const_name ATP.fNot})))),
   319    ("c_conj", (@{const_name conj}, (@{thm fconj_def},
   320        ("fconj", @{const_name ATP.fconj})))),
   321    ("c_disj", (@{const_name disj}, (@{thm fdisj_def},
   322        ("fdisj", @{const_name ATP.fdisj})))),
   323    ("c_implies", (@{const_name implies}, (@{thm fimplies_def},
   324        ("fimplies", @{const_name ATP.fimplies})))),
   325    ("equal", (@{const_name HOL.eq}, (@{thm fequal_def},
   326        ("fequal", @{const_name ATP.fequal})))),
   327    ("c_All", (@{const_name All}, (@{thm fAll_def},
   328        ("fAll", @{const_name ATP.fAll})))),
   329    ("c_Ex", (@{const_name Ex}, (@{thm fEx_def},
   330        ("fEx", @{const_name ATP.fEx}))))]
   331 
   332 val proxify_const = AList.lookup (op =) proxy_table #> Option.map (snd o snd)
   333 
   334 (* Readable names for the more common symbolic functions. Do not mess with the
   335    table unless you know what you are doing. *)
   336 val const_trans_table =
   337   [(@{const_name False}, "False"),
   338    (@{const_name True}, "True"),
   339    (@{const_name Not}, "Not"),
   340    (@{const_name conj}, "conj"),
   341    (@{const_name disj}, "disj"),
   342    (@{const_name implies}, "implies"),
   343    (@{const_name HOL.eq}, "equal"),
   344    (@{const_name All}, "All"),
   345    (@{const_name Ex}, "Ex"),
   346    (@{const_name If}, "If"),
   347    (@{const_name Set.member}, "member"),
   348    (@{const_name Meson.COMBI}, combinator_prefix ^ "I"),
   349    (@{const_name Meson.COMBK}, combinator_prefix ^ "K"),
   350    (@{const_name Meson.COMBB}, combinator_prefix ^ "B"),
   351    (@{const_name Meson.COMBC}, combinator_prefix ^ "C"),
   352    (@{const_name Meson.COMBS}, combinator_prefix ^ "S")]
   353   |> Symtab.make
   354   |> fold (Symtab.update o swap o snd o snd o snd) proxy_table
   355 
   356 (* Invert the table of translations between Isabelle and ATPs. *)
   357 val const_trans_table_inv =
   358   const_trans_table |> Symtab.dest |> map swap |> Symtab.make
   359 val const_trans_table_unprox =
   360   Symtab.empty
   361   |> fold (fn (_, (isa, (_, (_, atp)))) => Symtab.update (atp, isa)) proxy_table
   362 
   363 val invert_const = perhaps (Symtab.lookup const_trans_table_inv)
   364 val unproxify_const = perhaps (Symtab.lookup const_trans_table_unprox)
   365 
   366 fun lookup_const c =
   367   (case Symtab.lookup const_trans_table c of
   368     SOME c' => c'
   369   | NONE => ascii_of c)
   370 
   371 fun ascii_of_indexname (v, 0) = ascii_of v
   372   | ascii_of_indexname (v, i) = ascii_of v ^ "_" ^ string_of_int i
   373 
   374 fun make_bound_var x = bound_var_prefix ^ ascii_of x
   375 fun make_all_bound_var x = all_bound_var_prefix ^ ascii_of x
   376 fun make_exist_bound_var x = exist_bound_var_prefix ^ ascii_of x
   377 fun make_schematic_var v = schematic_var_prefix ^ ascii_of_indexname v
   378 fun make_fixed_var x = fixed_var_prefix ^ ascii_of x
   379 
   380 fun make_tvar (s, i) = tvar_prefix ^ ascii_of_indexname (unquote_tvar s, i)
   381 fun make_tfree s = tfree_prefix ^ ascii_of (unquote_tvar s)
   382 fun tvar_name ((x as (s, _)), _) = (make_tvar x, s)
   383 
   384 (* "HOL.eq" and choice are mapped to the ATP's equivalents *)
   385 local
   386   val choice_const = (fst o dest_Const o HOLogic.choice_const) dummyT
   387   fun default c = const_prefix ^ lookup_const c
   388 in
   389   fun make_fixed_const _ @{const_name HOL.eq} = tptp_old_equal
   390     | make_fixed_const (SOME (Native (Higher_Order THF_With_Choice, _, _))) c =
   391       if c = choice_const then tptp_choice else default c
   392     | make_fixed_const _ c = default c
   393 end
   394 
   395 fun make_fixed_type_const c = type_const_prefix ^ lookup_const c
   396 
   397 fun make_class clas = class_prefix ^ ascii_of clas
   398 
   399 fun new_skolem_var_name_of_const s =
   400   let val ss = s |> space_explode Long_Name.separator in
   401     nth ss (length ss - 2)
   402   end
   403 
   404 (* These are ignored anyway by the relevance filter (unless they appear in
   405    higher-order places) but not by the monomorphizer. *)
   406 val atp_logical_consts =
   407   [@{const_name Pure.prop}, @{const_name Pure.conjunction},
   408    @{const_name Pure.all}, @{const_name Pure.imp}, @{const_name Pure.eq},
   409    @{const_name Trueprop}, @{const_name All}, @{const_name Ex},
   410    @{const_name Ex1}, @{const_name Ball}, @{const_name Bex}]
   411 
   412 (* These are either simplified away by "Meson.presimplify" (most of the time) or
   413    handled specially via "fFalse", "fTrue", ..., "fequal". *)
   414 val atp_irrelevant_consts =
   415   [@{const_name False}, @{const_name True}, @{const_name Not}, @{const_name conj},
   416    @{const_name disj}, @{const_name implies}, @{const_name HOL.eq}, @{const_name If},
   417    @{const_name Let}]
   418 
   419 val atp_widely_irrelevant_consts = atp_logical_consts @ atp_irrelevant_consts
   420 
   421 val atp_irrelevant_const_tab = Symtab.make (map (rpair ()) atp_irrelevant_consts)
   422 val atp_widely_irrelevant_const_tab = Symtab.make (map (rpair ()) atp_widely_irrelevant_consts)
   423 
   424 val is_irrelevant_const = Symtab.defined atp_irrelevant_const_tab
   425 val is_widely_irrelevant_const = Symtab.defined atp_widely_irrelevant_const_tab
   426 
   427 fun add_schematic_const (x as (_, T)) =
   428   Monomorph.typ_has_tvars T ? Symtab.insert_list (op =) x
   429 val add_schematic_consts_of =
   430   Term.fold_aterms (fn Const (x as (s, _)) =>
   431                        not (member (op =) atp_widely_irrelevant_consts s)
   432                        ? add_schematic_const x
   433                       | _ => I)
   434 fun atp_schematic_consts_of t = add_schematic_consts_of t Symtab.empty
   435 
   436 val tvar_a_str = "'a"
   437 val tvar_a_z = ((tvar_a_str, 0), @{sort type})
   438 val tvar_a = TVar tvar_a_z
   439 val tvar_a_name = tvar_name tvar_a_z
   440 val itself_name = `make_fixed_type_const @{type_name itself}
   441 val TYPE_name = `(make_fixed_const NONE) @{const_name Pure.type}
   442 val tvar_a_atype = AType ((tvar_a_name, []), [])
   443 val a_itself_atype = AType ((itself_name, []), [tvar_a_atype])
   444 
   445 (** Definitions and functions for FOL clauses and formulas for TPTP **)
   446 
   447 (** Type class membership **)
   448 
   449 (* In our data structures, [] exceptionally refers to the top class, not to
   450    the empty class. *)
   451 
   452 val class_of_types = the_single @{sort type}
   453 
   454 fun normalize_classes cls = if member (op =) cls class_of_types then [] else cls
   455 
   456 (* Arity of type constructor "s :: (arg1, ..., argN) res" *)
   457 fun make_axiom_tcon_clause (s, name, (cl, args)) =
   458   let
   459     val args = args |> map normalize_classes
   460     val tvars =
   461       1 upto length args |> map (fn j => TVar ((tvar_a_str, j), @{sort type}))
   462   in (name, args ~~ tvars, (cl, Type (s, tvars))) end
   463 
   464 (* Generate all pairs (tycon, class, sorts) such that tycon belongs to class in
   465    theory thy provided its arguments have the corresponding sorts. *)
   466 fun class_pairs thy tycons cls =
   467   let
   468     val alg = Sign.classes_of thy
   469     fun domain_sorts tycon = Sorts.mg_domain alg tycon o single
   470     fun add_class tycon cl =
   471       cons (cl, domain_sorts tycon cl)
   472       handle Sorts.CLASS_ERROR _ => I
   473     fun try_classes tycon = (tycon, fold (add_class tycon) cls [])
   474   in map try_classes tycons end
   475 
   476 (* Proving one (tycon, class) membership may require proving others, so
   477    iterate. *)
   478 fun all_class_pairs _ _ [] = ([], [])
   479   | all_class_pairs thy tycons cls =
   480     let
   481       fun maybe_insert_class s =
   482         (s <> class_of_types andalso not (member (op =) cls s)) ? insert (op =) s
   483       val pairs = class_pairs thy tycons cls
   484       val new_cls =
   485         [] |> fold (fold (fold (fold maybe_insert_class) o snd) o snd) pairs
   486       val (cls', pairs') = all_class_pairs thy tycons new_cls
   487     in (cls' @ cls, union (op =) pairs' pairs) end
   488 
   489 fun tcon_clause _ _ [] = []
   490   | tcon_clause seen n ((_, []) :: rest) = tcon_clause seen n rest
   491   | tcon_clause seen n ((tcons, (ar as (cl, _)) :: ars) :: rest) =
   492     if cl = class_of_types then
   493       tcon_clause seen n ((tcons, ars) :: rest)
   494     else if member (op =) seen cl then
   495       (* multiple clauses for the same (tycon, cl) pair *)
   496       make_axiom_tcon_clause (tcons,
   497         lookup_const tcons ^ "___" ^ ascii_of cl ^ "_" ^ string_of_int n, ar) ::
   498       tcon_clause seen (n + 1) ((tcons, ars) :: rest)
   499     else
   500       make_axiom_tcon_clause (tcons, lookup_const tcons ^ "___" ^ ascii_of cl, ar) ::
   501       tcon_clause (cl :: seen) n ((tcons, ars) :: rest)
   502 
   503 fun make_tcon_clauses thy tycons =
   504   all_class_pairs thy tycons ##> tcon_clause [] 1
   505 
   506 
   507 (** Isabelle class relations **)
   508 
   509 (* Generate a list ("sub", "supers") such that "sub" is a proper subclass of all
   510    "supers". *)
   511 fun make_subclass_pairs thy subs supers =
   512   let
   513     val class_less = curry (Sorts.class_less (Sign.classes_of thy))
   514     fun supers_of sub = (sub, filter (class_less sub) supers)
   515   in map supers_of subs |> filter_out (null o snd) end
   516 
   517 (* intermediate terms *)
   518 datatype iterm =
   519   IConst of (string * string) * typ * typ list |
   520   IVar of (string * string) * typ |
   521   IApp of iterm * iterm |
   522   IAbs of ((string * string) * typ) * iterm
   523 
   524 fun ityp_of (IConst (_, T, _)) = T
   525   | ityp_of (IVar (_, T)) = T
   526   | ityp_of (IApp (t1, _)) = snd (dest_funT (ityp_of t1))
   527   | ityp_of (IAbs ((_, T), tm)) = T --> ityp_of tm
   528 
   529 (*gets the head of a combinator application, along with the list of arguments*)
   530 fun strip_iterm_comb u =
   531   let
   532     fun stripc (IApp (t, u), ts) = stripc (t, u :: ts)
   533       | stripc x = x
   534   in stripc (u, []) end
   535 
   536 fun atomic_types_of T = fold_atyps (insert (op =)) T []
   537 
   538 fun new_skolem_const_name s num_T_args =
   539   [new_skolem_const_prefix, s, string_of_int num_T_args]
   540   |> Long_Name.implode
   541 
   542 val alpha_to_beta = Logic.varifyT_global @{typ "'a => 'b"}
   543 val alpha_to_beta_to_alpha_to_beta = alpha_to_beta --> alpha_to_beta
   544 
   545 fun robust_const_type thy s =
   546   if s = app_op_name then
   547     alpha_to_beta_to_alpha_to_beta
   548   else if String.isPrefix lam_lifted_prefix s then
   549     alpha_to_beta
   550   else
   551     (* Old Skolems throw a "TYPE" exception here, which will be caught. *)
   552     s |> Sign.the_const_type thy
   553 
   554 fun ary_of (Type (@{type_name fun}, [_, T])) = 1 + ary_of T
   555   | ary_of _ = 0
   556 
   557 (* This function only makes sense if "T" is as general as possible. *)
   558 fun robust_const_type_args thy (s, T) =
   559   if s = app_op_name then
   560     let val (T1, T2) = T |> domain_type |> dest_funT in [T1, T2] end
   561   else if String.isPrefix old_skolem_const_prefix s then
   562     [] |> Term.add_tvarsT T |> rev |> map TVar
   563   else if String.isPrefix lam_lifted_prefix s then
   564     if String.isPrefix lam_lifted_poly_prefix s then
   565       let val (T1, T2) = T |> dest_funT in [T1, T2] end
   566     else
   567       []
   568   else
   569     (s, T) |> Sign.const_typargs thy
   570 
   571 (* Converts an Isabelle/HOL term (with combinators) into an intermediate term. Also accumulates sort
   572    infomation. *)
   573 fun iterm_of_term thy type_enc bs (P $ Q) =
   574     let
   575       val (P', P_atomics_Ts) = iterm_of_term thy type_enc bs P
   576       val (Q', Q_atomics_Ts) = iterm_of_term thy type_enc bs Q
   577     in (IApp (P', Q'), union (op =) P_atomics_Ts Q_atomics_Ts) end
   578   | iterm_of_term thy type_enc _ (Const (c, T)) =
   579     (IConst (`(make_fixed_const (SOME type_enc)) c, T, robust_const_type_args thy (c, T)),
   580      atomic_types_of T)
   581   | iterm_of_term _ _ _ (Free (s, T)) = (IConst (`make_fixed_var s, T, []), atomic_types_of T)
   582   | iterm_of_term _ type_enc _ (Var (v as (s, _), T)) =
   583     (if String.isPrefix Meson_Clausify.new_skolem_var_prefix s then
   584        let
   585          val Ts = T |> strip_type |> swap |> op ::
   586          val s' = new_skolem_const_name s (length Ts)
   587        in IConst (`(make_fixed_const (SOME type_enc)) s', T, Ts) end
   588      else
   589        IVar ((make_schematic_var v, s), T), atomic_types_of T)
   590   | iterm_of_term _ _ bs (Bound j) =
   591     nth bs j |> (fn (_, (name, T)) => (IConst (name, T, []), atomic_types_of T))
   592   | iterm_of_term thy type_enc bs (Abs (s, T, t)) =
   593     let
   594       fun vary s = s |> AList.defined (op =) bs s ? vary o Symbol.bump_string
   595       val s = vary s
   596       val name = `make_bound_var s
   597       val (tm, atomic_Ts) = iterm_of_term thy type_enc ((s, (name, T)) :: bs) t
   598     in
   599       (IAbs ((name, T), tm), union (op =) atomic_Ts (atomic_types_of T))
   600     end
   601 
   602 (* "_query" and "_at" are for the ASCII-challenged Metis and Mirabelle. *)
   603 val queries = ["?", "_query"]
   604 val ats = ["@", "_at"]
   605 
   606 fun try_unsuffixes ss s =
   607   fold (fn s' => fn NONE => try (unsuffix s') s | some => some) ss NONE
   608 
   609 fun type_enc_of_string strictness s =
   610   (case try (unprefix "tc_") s of
   611     SOME s => (SOME Type_Class_Polymorphic, s)
   612   | NONE =>
   613     (case try (unprefix "poly_") s of
   614       (* It's still unclear whether all TFF1 implementations will support
   615          type signatures such as "!>[A : $tType] : $o", with phantom type
   616          variables. *)
   617       SOME s => (SOME (Raw_Polymorphic With_Phantom_Type_Vars), s)
   618     | NONE =>
   619       (case try (unprefix "raw_mono_") s of
   620         SOME s => (SOME Raw_Monomorphic, s)
   621       | NONE =>
   622         (case try (unprefix "mono_") s of
   623           SOME s => (SOME Mangled_Monomorphic, s)
   624         | NONE => (NONE, s)))))
   625   ||> (fn s =>
   626        (case try_unsuffixes queries s of
   627          SOME s =>
   628          (case try_unsuffixes queries s of
   629            SOME s => (Nonmono_Types (strictness, Non_Uniform), s)
   630          | NONE => (Nonmono_Types (strictness, Uniform), s))
   631         | NONE =>
   632           (case try_unsuffixes ats s of
   633             SOME s => (Undercover_Types, s)
   634           | NONE => (All_Types, s))))
   635   |> (fn (poly, (level, core)) =>
   636         (case (core, (poly, level)) of
   637           ("native", (SOME poly, _)) =>
   638           (case (poly, level) of
   639             (Mangled_Monomorphic, _) =>
   640             if is_type_level_uniform level then Native (First_Order, Mangled_Monomorphic, level)
   641             else raise Same.SAME
   642           | (Raw_Monomorphic, _) => raise Same.SAME
   643           | (poly, All_Types) => Native (First_Order, poly, All_Types))
   644         | ("native_higher", (SOME poly, _)) =>
   645           (case (poly, level) of
   646             (_, Nonmono_Types _) => raise Same.SAME
   647           | (_, Undercover_Types) => raise Same.SAME
   648           | (Mangled_Monomorphic, _) =>
   649             if is_type_level_uniform level then
   650               Native (Higher_Order THF_With_Choice, Mangled_Monomorphic, level)
   651             else
   652               raise Same.SAME
   653            | (poly as Raw_Polymorphic _, All_Types) =>
   654              Native (Higher_Order THF_With_Choice, poly, All_Types)
   655            | _ => raise Same.SAME)
   656         | ("guards", (SOME poly, _)) =>
   657           if (poly = Mangled_Monomorphic andalso
   658               level = Undercover_Types) orelse
   659              poly = Type_Class_Polymorphic then
   660             raise Same.SAME
   661           else
   662             Guards (poly, level)
   663         | ("tags", (SOME poly, _)) =>
   664           if (poly = Mangled_Monomorphic andalso
   665               level = Undercover_Types) orelse
   666              poly = Type_Class_Polymorphic then
   667             raise Same.SAME
   668           else
   669             Tags (poly, level)
   670         | ("args", (SOME poly, All_Types (* naja *))) =>
   671           if poly = Type_Class_Polymorphic then raise Same.SAME
   672           else Guards (poly, Const_Types Without_Ctr_Optim)
   673         | ("args", (SOME poly, Nonmono_Types (_, Uniform) (* naja *))) =>
   674           if poly = Mangled_Monomorphic orelse
   675              poly = Type_Class_Polymorphic then
   676             raise Same.SAME
   677           else
   678             Guards (poly, Const_Types With_Ctr_Optim)
   679         | ("erased", (NONE, All_Types (* naja *))) =>
   680           Guards (Raw_Polymorphic With_Phantom_Type_Vars, No_Types)
   681         | _ => raise Same.SAME))
   682   handle Same.SAME => error ("Unknown type encoding: " ^ quote s ^ ".")
   683 
   684 fun adjust_order THF_Without_Choice (Higher_Order _) =
   685     Higher_Order THF_Without_Choice
   686   | adjust_order _ type_enc = type_enc
   687 
   688 fun no_type_classes Type_Class_Polymorphic =
   689     Raw_Polymorphic With_Phantom_Type_Vars
   690   | no_type_classes poly = poly
   691 
   692 fun adjust_type_enc (THF (Polymorphic, choice)) (Native (order, poly, level)) =
   693     Native (adjust_order choice order, no_type_classes poly, level)
   694   | adjust_type_enc (THF (Monomorphic, choice)) (Native (order, _, level)) =
   695     Native (adjust_order choice order, Mangled_Monomorphic, level)
   696   | adjust_type_enc (TFF Monomorphic) (Native (_, _, level)) =
   697     Native (First_Order, Mangled_Monomorphic, level)
   698   | adjust_type_enc (DFG Polymorphic) (Native (_, poly, level)) =
   699     Native (First_Order, poly, level)
   700   | adjust_type_enc (DFG Monomorphic) (Native (_, _, level)) =
   701     Native (First_Order, Mangled_Monomorphic, level)
   702   | adjust_type_enc (TFF _) (Native (_, poly, level)) =
   703     Native (First_Order, no_type_classes poly, level)
   704   | adjust_type_enc format (Native (_, poly, level)) =
   705     adjust_type_enc format (Guards (no_type_classes poly, level))
   706   | adjust_type_enc CNF_UEQ (type_enc as Guards stuff) =
   707     (if is_type_enc_sound type_enc then Tags else Guards) stuff
   708   | adjust_type_enc _ type_enc = type_enc
   709 
   710 fun is_lambda_free t =
   711   (case t of
   712     @{const Not} $ t1 => is_lambda_free t1
   713   | Const (@{const_name All}, _) $ Abs (_, _, t') => is_lambda_free t'
   714   | Const (@{const_name All}, _) $ t1 => is_lambda_free t1
   715   | Const (@{const_name Ex}, _) $ Abs (_, _, t') => is_lambda_free t'
   716   | Const (@{const_name Ex}, _) $ t1 => is_lambda_free t1
   717   | @{const HOL.conj} $ t1 $ t2 => is_lambda_free t1 andalso is_lambda_free t2
   718   | @{const HOL.disj} $ t1 $ t2 => is_lambda_free t1 andalso is_lambda_free t2
   719   | @{const HOL.implies} $ t1 $ t2 => is_lambda_free t1 andalso is_lambda_free t2
   720   | Const (@{const_name HOL.eq}, Type (_, [@{typ bool}, _])) $ t1 $ t2 =>
   721     is_lambda_free t1 andalso is_lambda_free t2
   722   | _ => not (exists_subterm (fn Abs _ => true | _ => false) t))
   723 
   724 fun simple_translate_lambdas do_lambdas ctxt t =
   725   if is_lambda_free t then
   726     t
   727   else
   728     let
   729       fun trans Ts t =
   730         (case t of
   731           @{const Not} $ t1 => @{const Not} $ trans Ts t1
   732         | (t0 as Const (@{const_name All}, _)) $ Abs (s, T, t') =>
   733           t0 $ Abs (s, T, trans (T :: Ts) t')
   734         | (t0 as Const (@{const_name All}, _)) $ t1 => trans Ts (t0 $ eta_expand Ts t1 1)
   735         | (t0 as Const (@{const_name Ex}, _)) $ Abs (s, T, t') =>
   736           t0 $ Abs (s, T, trans (T :: Ts) t')
   737         | (t0 as Const (@{const_name Ex}, _)) $ t1 => trans Ts (t0 $ eta_expand Ts t1 1)
   738         | (t0 as @{const HOL.conj}) $ t1 $ t2 => t0 $ trans Ts t1 $ trans Ts t2
   739         | (t0 as @{const HOL.disj}) $ t1 $ t2 => t0 $ trans Ts t1 $ trans Ts t2
   740         | (t0 as @{const HOL.implies}) $ t1 $ t2 => t0 $ trans Ts t1 $ trans Ts t2
   741         | (t0 as Const (@{const_name HOL.eq}, Type (_, [@{typ bool}, _]))) $ t1 $ t2 =>
   742           t0 $ trans Ts t1 $ trans Ts t2
   743         | _ =>
   744           if not (exists_subterm (fn Abs _ => true | _ => false) t) then t
   745           else t |> Envir.eta_contract |> do_lambdas ctxt Ts)
   746       val (t, ctxt') = Variable.import_terms true [t] ctxt |>> the_single
   747     in t |> trans [] |> singleton (Variable.export_terms ctxt' ctxt) end
   748 
   749 fun do_cheaply_conceal_lambdas Ts (t1 $ t2) =
   750     do_cheaply_conceal_lambdas Ts t1
   751     $ do_cheaply_conceal_lambdas Ts t2
   752   | do_cheaply_conceal_lambdas Ts (Abs (_, T, t)) =
   753     Const (lam_lifted_poly_prefix ^ serial_string (),
   754            T --> fastype_of1 (T :: Ts, t))
   755   | do_cheaply_conceal_lambdas _ t = t
   756 
   757 fun concealed_bound_name j = atp_weak_prefix ^ string_of_int j
   758 fun conceal_bounds Ts t =
   759   subst_bounds (map (Free o apfst concealed_bound_name)
   760                     (0 upto length Ts - 1 ~~ Ts), t)
   761 fun reveal_bounds Ts =
   762   subst_atomic (map (fn (j, T) => (Free (concealed_bound_name j, T), Bound j))
   763                     (0 upto length Ts - 1 ~~ Ts))
   764 
   765 fun do_introduce_combinators ctxt Ts t =
   766   let val thy = Proof_Context.theory_of ctxt in
   767     t |> conceal_bounds Ts
   768       |> cterm_of thy
   769       |> Meson_Clausify.introduce_combinators_in_cterm
   770       |> prop_of |> Logic.dest_equals |> snd
   771       |> reveal_bounds Ts
   772   end
   773   (* A type variable of sort "{}" will make abstraction fail. *)
   774   handle THM _ => t |> do_cheaply_conceal_lambdas Ts
   775 val introduce_combinators = simple_translate_lambdas do_introduce_combinators
   776 
   777 fun constify_lifted (t $ u) = constify_lifted t $ constify_lifted u
   778   | constify_lifted (Abs (s, T, t)) = Abs (s, T, constify_lifted t)
   779   | constify_lifted (Free (x as (s, _))) =
   780     (if String.isPrefix lam_lifted_prefix s then Const else Free) x
   781   | constify_lifted t = t
   782 
   783 fun lift_lams_part_1 ctxt type_enc =
   784   map hol_close_form #> rpair ctxt
   785   #-> Lambda_Lifting.lift_lambdas
   786           (SOME ((if is_type_enc_polymorphic type_enc then
   787                     lam_lifted_poly_prefix
   788                   else
   789                     lam_lifted_mono_prefix) ^ "_a"))
   790           Lambda_Lifting.is_quantifier
   791   #> fst
   792 
   793 fun lift_lams_part_2 ctxt (facts, lifted) =
   794   (facts, lifted)
   795   (* Lambda-lifting sometimes leaves some lambdas around; we need some way to
   796      get rid of them *)
   797   |> pairself (map (introduce_combinators ctxt))
   798   |> pairself (map constify_lifted)
   799   (* Requires bound variables not to clash with any schematic variables (as
   800      should be the case right after lambda-lifting). *)
   801   |>> map (hol_open_form (unprefix hol_close_form_prefix))
   802   ||> map (hol_open_form I)
   803 
   804 fun lift_lams ctxt = lift_lams_part_2 ctxt oo lift_lams_part_1 ctxt
   805 
   806 fun intentionalize_def (Const (@{const_name All}, _) $ Abs (_, _, t)) =
   807     intentionalize_def t
   808   | intentionalize_def (Const (@{const_name HOL.eq}, _) $ t $ u) =
   809     let
   810       fun lam T t = Abs (Name.uu, T, t)
   811       val (head, args) = strip_comb t ||> rev
   812       val head_T = fastype_of head
   813       val n = length args
   814       val arg_Ts = head_T |> binder_types |> take n |> rev
   815       val u = u |> subst_atomic (args ~~ map Bound (0 upto n - 1))
   816     in HOLogic.eq_const head_T $ head $ fold lam arg_Ts u end
   817   | intentionalize_def t = t
   818 
   819 type ifact =
   820   {name : string,
   821    stature : stature,
   822    role : atp_formula_role,
   823    iformula : (string * string, typ, iterm, string * string) atp_formula,
   824    atomic_types : typ list}
   825 
   826 fun update_iformula f ({name, stature, role, iformula, atomic_types} : ifact) =
   827   {name = name, stature = stature, role = role, iformula = f iformula, atomic_types = atomic_types}
   828   : ifact
   829 
   830 fun ifact_lift f ({iformula, ...} : ifact) = f iformula
   831 
   832 fun insert_type thy get_T x xs =
   833   let val T = get_T x in
   834     if exists (type_instance thy T o get_T) xs then xs
   835     else x :: filter_out (type_generalization thy T o get_T) xs
   836   end
   837 
   838 fun chop_fun 0 T = ([], T)
   839   | chop_fun n (Type (@{type_name fun}, [dom_T, ran_T])) =
   840     chop_fun (n - 1) ran_T |>> cons dom_T
   841   | chop_fun _ T = ([], T)
   842 
   843 fun filter_type_args thy ctrss type_enc s ary T_args =
   844   let val poly = polymorphism_of_type_enc type_enc in
   845     if s = type_tag_name then (* FIXME: why not "type_guard_name" as well? *)
   846       T_args
   847     else
   848       (case type_enc of
   849         Native (_, Raw_Polymorphic _, _) => T_args
   850       | Native (_, Type_Class_Polymorphic, _) => T_args
   851       | _ =>
   852         let
   853           fun gen_type_args _ _ [] = []
   854             | gen_type_args keep strip_ty T_args =
   855               let
   856                 val U = robust_const_type thy s
   857                 val (binder_Us, body_U) = strip_ty U
   858                 val in_U_vars = fold Term.add_tvarsT binder_Us []
   859                 val out_U_vars = Term.add_tvarsT body_U []
   860                 fun filt (U_var, T) =
   861                   if keep (member (op =) in_U_vars U_var,
   862                            member (op =) out_U_vars U_var) then
   863                     T
   864                   else
   865                     dummyT
   866                 val U_args = (s, U) |> robust_const_type_args thy
   867               in map (filt o apfst dest_TVar) (U_args ~~ T_args) end
   868               handle TYPE _ => T_args
   869           fun is_always_ctr (s', T') =
   870             s' = s andalso type_equiv thy (T', robust_const_type thy s')
   871           val noninfer_type_args = gen_type_args (not o fst) (chop_fun ary)
   872           val ctr_infer_type_args = gen_type_args fst strip_type
   873           val level = level_of_type_enc type_enc
   874         in
   875           if level = No_Types orelse s = @{const_name HOL.eq} orelse
   876              (case level of Const_Types _ => s = app_op_name | _ => false) then
   877             []
   878           else if poly = Mangled_Monomorphic then
   879             T_args
   880           else if level = All_Types then
   881             (case type_enc of
   882               Guards _ => noninfer_type_args T_args
   883             | Tags _ => [])
   884           else if level = Undercover_Types then
   885             noninfer_type_args T_args
   886           else if level <> Const_Types Without_Ctr_Optim andalso
   887                   exists (exists is_always_ctr) ctrss then
   888             ctr_infer_type_args T_args
   889           else
   890             T_args
   891         end)
   892   end
   893 
   894 val fused_infinite_type_name = "ATP.fused_inf" (* shouldn't clash *)
   895 val fused_infinite_type = Type (fused_infinite_type_name, [])
   896 
   897 fun raw_atp_type_of_typ type_enc =
   898   let
   899     fun term (Type (s, Ts)) =
   900       AType ((case (is_type_enc_higher_order type_enc, s) of
   901                (true, @{type_name bool}) => `I tptp_bool_type
   902              | (true, @{type_name fun}) => `I tptp_fun_type
   903              | _ =>
   904                if s = fused_infinite_type_name andalso is_type_enc_native type_enc then
   905                  `I tptp_individual_type
   906                else
   907                  `make_fixed_type_const s, []), map term Ts)
   908     | term (TFree (s, _)) = AType ((`make_tfree s, []), [])
   909     | term (TVar z) = AType ((tvar_name z, []), [])
   910   in term end
   911 
   912 fun atp_term_of_atp_type (AType ((name, _), tys)) = ATerm ((name, []), map atp_term_of_atp_type tys)
   913   | atp_term_of_atp_type _ = raise Fail "unexpected type"
   914 
   915 fun atp_type_of_type_arg type_enc T =
   916   if T = dummyT then NONE else SOME (raw_atp_type_of_typ type_enc T)
   917 
   918 (* This shouldn't clash with anything else. *)
   919 val uncurried_alias_sep = "\000"
   920 val mangled_type_sep = "\001"
   921 
   922 val ascii_of_uncurried_alias_sep = ascii_of uncurried_alias_sep
   923 
   924 fun generic_mangled_type_name f (AType ((name, _), [])) = f name
   925   | generic_mangled_type_name f (AType ((name, _), tys)) =
   926     f name ^ "(" ^ space_implode "," (map (generic_mangled_type_name f) tys) ^ ")"
   927   | generic_mangled_type_name _ _ = raise Fail "unexpected type"
   928 
   929 fun mangled_type type_enc = generic_mangled_type_name fst o raw_atp_type_of_typ type_enc
   930 
   931 fun make_native_type s =
   932   if s = tptp_bool_type orelse s = tptp_fun_type orelse s = tptp_individual_type then s
   933   else native_type_prefix ^ ascii_of s
   934 
   935 fun native_atp_type_of_raw_atp_type type_enc pred_sym ary =
   936   let
   937     fun to_mangled_atype ty =
   938       AType (((make_native_type (generic_mangled_type_name fst ty),
   939                generic_mangled_type_name snd ty), []), [])
   940     fun to_poly_atype (AType ((name, clss), tys)) = AType ((name, clss), map to_poly_atype tys)
   941       | to_poly_atype _ = raise Fail "unexpected type"
   942     val to_atype =
   943       if is_type_enc_polymorphic type_enc then to_poly_atype
   944       else to_mangled_atype
   945     fun to_afun f1 f2 tys = AFun (f1 (hd tys), f2 (nth tys 1))
   946     fun to_fo 0 ty = if pred_sym then bool_atype else to_atype ty
   947       | to_fo ary (AType (_, tys)) = to_afun to_atype (to_fo (ary - 1)) tys
   948       | to_fo _ _ = raise Fail "unexpected type"
   949     fun to_ho (ty as AType (((s, _), _), tys)) =
   950         if s = tptp_fun_type then to_afun to_ho to_ho tys else to_atype ty
   951       | to_ho _ = raise Fail "unexpected type"
   952   in if is_type_enc_higher_order type_enc then to_ho else to_fo ary end
   953 
   954 fun native_atp_type_of_typ type_enc pred_sym ary =
   955   native_atp_type_of_raw_atp_type type_enc pred_sym ary o raw_atp_type_of_typ type_enc
   956 
   957 (* Make atoms for sorted type variables. *)
   958 fun generic_add_sorts_on_type _ [] = I
   959   | generic_add_sorts_on_type T (s :: ss) =
   960     generic_add_sorts_on_type T ss
   961     #> (if s = the_single @{sort type} then I else insert (op =) (s, T))
   962 fun add_sorts_on_tfree (T as TFree (_, S)) = generic_add_sorts_on_type T S
   963   | add_sorts_on_tfree _ = I
   964 fun add_sorts_on_tvar (T as TVar (_, S)) = generic_add_sorts_on_type T S
   965   | add_sorts_on_tvar _ = I
   966 
   967 fun process_type_args type_enc T_args =
   968   if is_type_enc_native type_enc then
   969     (map (native_atp_type_of_typ type_enc false 0) T_args, [])
   970   else
   971     ([], map_filter (Option.map atp_term_of_atp_type o atp_type_of_type_arg type_enc) T_args)
   972 
   973 fun class_atom type_enc (cl, T) =
   974   let
   975     val cl = `make_class cl
   976     val (ty_args, tm_args) = process_type_args type_enc [T]
   977     val tm_args =
   978       tm_args @
   979       (case type_enc of
   980         Native (First_Order, Raw_Polymorphic Without_Phantom_Type_Vars, _) =>
   981         [ATerm ((TYPE_name, ty_args), [])]
   982       | _ => [])
   983   in AAtom (ATerm ((cl, ty_args), tm_args)) end
   984 
   985 fun class_atoms type_enc (cls, T) =
   986   map (fn cl => class_atom type_enc (cl, T)) cls
   987 
   988 fun class_membs_of_types type_enc add_sorts_on_typ Ts =
   989   [] |> level_of_type_enc type_enc <> No_Types ? fold add_sorts_on_typ Ts
   990 
   991 fun mk_aconns c = split_last #> uncurry (fold_rev (mk_aconn c))
   992 
   993 fun mk_ahorn [] phi = phi
   994   | mk_ahorn phis psi = AConn (AImplies, [mk_aconns AAnd phis, psi])
   995 
   996 fun mk_aquant _ [] phi = phi
   997   | mk_aquant q xs (phi as AQuant (q', xs', phi')) =
   998     if q = q' then AQuant (q, xs @ xs', phi') else AQuant (q, xs, phi)
   999   | mk_aquant q xs phi = AQuant (q, xs, phi)
  1000 
  1001 fun mk_atyquant _ [] phi = phi
  1002   | mk_atyquant q xs (phi as ATyQuant (q', xs', phi')) =
  1003     if q = q' then ATyQuant (q, xs @ xs', phi') else ATyQuant (q, xs, phi)
  1004   | mk_atyquant q xs phi = ATyQuant (q, xs, phi)
  1005 
  1006 fun close_universally add_term_vars phi =
  1007   let
  1008     fun add_formula_vars bounds (ATyQuant (_, _, phi)) =
  1009         add_formula_vars bounds phi
  1010       | add_formula_vars bounds (AQuant (_, xs, phi)) =
  1011         add_formula_vars (map fst xs @ bounds) phi
  1012       | add_formula_vars bounds (AConn (_, phis)) =
  1013         fold (add_formula_vars bounds) phis
  1014       | add_formula_vars bounds (AAtom tm) = add_term_vars bounds tm
  1015   in mk_aquant AForall (rev (add_formula_vars [] phi [])) phi end
  1016 
  1017 fun add_term_vars bounds (ATerm ((name as (s, _), _), tms)) =
  1018     (if is_tptp_variable s andalso
  1019         not (String.isPrefix tvar_prefix s) andalso
  1020         not (member (op =) bounds name) then
  1021        insert (op =) (name, NONE)
  1022      else
  1023        I)
  1024     #> fold (add_term_vars bounds) tms
  1025   | add_term_vars bounds (AAbs (((name, _), tm), args)) =
  1026     add_term_vars (name :: bounds) tm #> fold (add_term_vars bounds) args
  1027 
  1028 fun close_formula_universally phi = close_universally add_term_vars phi
  1029 
  1030 fun add_iterm_vars bounds (IApp (tm1, tm2)) =
  1031     fold (add_iterm_vars bounds) [tm1, tm2]
  1032   | add_iterm_vars _ (IConst _) = I
  1033   | add_iterm_vars bounds (IVar (name, T)) =
  1034     not (member (op =) bounds name) ? insert (op =) (name, SOME T)
  1035   | add_iterm_vars bounds (IAbs (_, tm)) = add_iterm_vars bounds tm
  1036 
  1037 fun aliased_uncurried ary (s, s') =
  1038   (s ^ ascii_of_uncurried_alias_sep ^ string_of_int ary, s' ^ string_of_int ary)
  1039 fun unaliased_uncurried (s, s') =
  1040   (case space_explode uncurried_alias_sep s of
  1041     [_] => (s, s')
  1042   | [s1, s2] => (s1, unsuffix s2 s')
  1043   | _ => raise Fail "ill-formed explicit application alias")
  1044 
  1045 fun raw_mangled_const_name type_name ty_args (s, s') =
  1046   let
  1047     fun type_suffix f g =
  1048       fold_rev (curry (op ^) o g o prefix mangled_type_sep o type_name f)
  1049                ty_args ""
  1050   in (s ^ type_suffix fst ascii_of, s' ^ type_suffix snd I) end
  1051 fun mangled_const_name type_enc =
  1052   map_filter (atp_type_of_type_arg type_enc)
  1053   #> raw_mangled_const_name generic_mangled_type_name
  1054 
  1055 val parse_mangled_ident =
  1056   Scan.many1 (not o member (op =) ["(", ")", ","]) >> implode
  1057 
  1058 fun parse_mangled_type x =
  1059   (parse_mangled_ident
  1060    -- Scan.optional ($$ "(" |-- Scan.optional parse_mangled_types [] --| $$ ")")
  1061                     [] >> (ATerm o apfst (rpair []))) x
  1062 and parse_mangled_types x =
  1063   (parse_mangled_type ::: Scan.repeat ($$ "," |-- parse_mangled_type)) x
  1064 
  1065 fun unmangled_type s =
  1066   s |> suffix ")" |> raw_explode
  1067     |> Scan.finite Symbol.stopper
  1068            (Scan.error (!! (fn _ => raise Fail ("unrecognized mangled type " ^
  1069                                                 quote s)) parse_mangled_type))
  1070     |> fst
  1071 
  1072 fun unmangled_const_name s =
  1073   (s, s) |> unaliased_uncurried |> fst |> space_explode mangled_type_sep
  1074 
  1075 fun unmangled_const s =
  1076   let val ss = unmangled_const_name s in
  1077     (hd ss, map unmangled_type (tl ss))
  1078   end
  1079 
  1080 val unmangled_invert_const = invert_const o hd o unmangled_const_name
  1081 
  1082 fun introduce_proxies_in_iterm type_enc =
  1083   let
  1084     fun tweak_ho_quant ho_quant T [IAbs _] = IConst (`I ho_quant, T, [])
  1085       | tweak_ho_quant ho_quant (T as Type (_, [p_T as Type (_, [x_T, _]), _]))
  1086                        _ =
  1087         (* Eta-expand "!!" and "??", to work around LEO-II 1.2.8 parser
  1088            limitation. This works in conjuction with special code in
  1089            "ATP_Problem" that uses the syntactic sugar "!" and "?" whenever
  1090            possible. *)
  1091         IAbs ((`I "P", p_T),
  1092               IApp (IConst (`I ho_quant, T, []),
  1093                     IAbs ((`I "X", x_T),
  1094                           IApp (IConst (`I "P", p_T, []),
  1095                                 IConst (`I "X", x_T, [])))))
  1096       | tweak_ho_quant _ _ _ = raise Fail "unexpected type for quantifier"
  1097     fun intro top_level args (IApp (tm1, tm2)) =
  1098         IApp (intro top_level (tm2 :: args) tm1, intro false [] tm2)
  1099       | intro top_level args (IConst (name as (s, _), T, T_args)) =
  1100         (case proxify_const s of
  1101           SOME proxy_base =>
  1102           if top_level orelse is_type_enc_higher_order type_enc then
  1103             (case (top_level, s) of
  1104               (_, "c_False") => IConst (`I tptp_false, T, [])
  1105             | (_, "c_True") => IConst (`I tptp_true, T, [])
  1106             | (false, "c_Not") => IConst (`I tptp_not, T, [])
  1107             | (false, "c_conj") => IConst (`I tptp_and, T, [])
  1108             | (false, "c_disj") => IConst (`I tptp_or, T, [])
  1109             | (false, "c_implies") => IConst (`I tptp_implies, T, [])
  1110             | (false, "c_All") => tweak_ho_quant tptp_ho_forall T args
  1111             | (false, "c_Ex") => tweak_ho_quant tptp_ho_exists T args
  1112             | (false, s) =>
  1113               if is_tptp_equal s then
  1114                 if length args = 2 then
  1115                   IConst (`I tptp_equal, T, [])
  1116                 else
  1117                   (* Eta-expand partially applied THF equality, because the
  1118                      LEO-II and Satallax parsers complain about not being able to
  1119                      infer the type of "=". *)
  1120                   let val i_T = domain_type T in
  1121                     IAbs ((`I "Y", i_T),
  1122                           IAbs ((`I "Z", i_T),
  1123                                 IApp (IApp (IConst (`I tptp_equal, T, []),
  1124                                             IConst (`I "Y", i_T, [])),
  1125                                       IConst (`I "Z", i_T, []))))
  1126                   end
  1127               else
  1128                 IConst (name, T, [])
  1129             | _ => IConst (name, T, []))
  1130           else
  1131             IConst (proxy_base |>> prefix const_prefix, T, T_args)
  1132          | NONE => if s = tptp_choice then tweak_ho_quant tptp_choice T args
  1133                    else IConst (name, T, T_args))
  1134       | intro _ _ (IAbs (bound, tm)) = IAbs (bound, intro false [] tm)
  1135       | intro _ _ tm = tm
  1136   in intro true [] end
  1137 
  1138 fun mangle_type_args_in_const type_enc (name as (s, _)) T_args =
  1139   if String.isPrefix const_prefix s andalso is_type_enc_mangling type_enc then
  1140     (mangled_const_name type_enc T_args name, [])
  1141   else
  1142     (name, T_args)
  1143 fun mangle_type_args_in_iterm type_enc =
  1144   if is_type_enc_mangling type_enc then
  1145     let
  1146       fun mangle (IApp (tm1, tm2)) = IApp (mangle tm1, mangle tm2)
  1147         | mangle (tm as IConst (_, _, [])) = tm
  1148         | mangle (IConst (name, T, T_args)) =
  1149           mangle_type_args_in_const type_enc name T_args
  1150           |> (fn (name, T_args) => IConst (name, T, T_args))
  1151         | mangle (IAbs (bound, tm)) = IAbs (bound, mangle tm)
  1152         | mangle tm = tm
  1153     in mangle end
  1154   else
  1155     I
  1156 
  1157 fun filter_type_args_in_const _ _ _ _ _ [] = []
  1158   | filter_type_args_in_const thy ctrss type_enc ary s T_args =
  1159     (case unprefix_and_unascii const_prefix s of
  1160       NONE => if level_of_type_enc type_enc = No_Types orelse s = tptp_choice then [] else T_args
  1161     | SOME s'' => filter_type_args thy ctrss type_enc (unmangled_invert_const s'') ary T_args)
  1162 
  1163 fun filter_type_args_in_iterm thy ctrss type_enc =
  1164   let
  1165     fun filt ary (IApp (tm1, tm2)) = IApp (filt (ary + 1) tm1, filt 0 tm2)
  1166       | filt ary (IConst (name as (s, _), T, T_args)) =
  1167         filter_type_args_in_const thy ctrss type_enc ary s T_args
  1168         |> (fn T_args => IConst (name, T, T_args))
  1169       | filt _ (IAbs (bound, tm)) = IAbs (bound, filt 0 tm)
  1170       | filt _ tm = tm
  1171   in filt 0 end
  1172 
  1173 fun iformula_of_prop ctxt type_enc iff_for_eq =
  1174   let
  1175     val thy = Proof_Context.theory_of ctxt
  1176     fun do_term bs t atomic_Ts =
  1177       iterm_of_term thy type_enc bs (Envir.eta_contract t)
  1178       |>> (introduce_proxies_in_iterm type_enc
  1179            #> mangle_type_args_in_iterm type_enc #> AAtom)
  1180       ||> union (op =) atomic_Ts
  1181     fun do_quant bs q pos s T t' =
  1182       let
  1183         val s = singleton (Name.variant_list (map fst bs)) s
  1184         val universal = Option.map (q = AExists ? not) pos
  1185         val name =
  1186           s |> `(case universal of
  1187                    SOME true => make_all_bound_var
  1188                  | SOME false => make_exist_bound_var
  1189                  | NONE => make_bound_var)
  1190       in
  1191         do_formula ((s, (name, T)) :: bs) pos t'
  1192         #>> mk_aquant q [(name, SOME T)]
  1193         ##> union (op =) (atomic_types_of T)
  1194       end
  1195     and do_conn bs c pos1 t1 pos2 t2 =
  1196       do_formula bs pos1 t1 ##>> do_formula bs pos2 t2 #>> uncurry (mk_aconn c)
  1197     and do_formula bs pos t =
  1198       (case t of
  1199         @{const Trueprop} $ t1 => do_formula bs pos t1
  1200       | @{const Not} $ t1 => do_formula bs (Option.map not pos) t1 #>> mk_anot
  1201       | Const (@{const_name All}, _) $ Abs (s, T, t') => do_quant bs AForall pos s T t'
  1202       | (t0 as Const (@{const_name All}, _)) $ t1 =>
  1203         do_formula bs pos (t0 $ eta_expand (map (snd o snd) bs) t1 1)
  1204       | Const (@{const_name Ex}, _) $ Abs (s, T, t') => do_quant bs AExists pos s T t'
  1205       | (t0 as Const (@{const_name Ex}, _)) $ t1 =>
  1206         do_formula bs pos (t0 $ eta_expand (map (snd o snd) bs) t1 1)
  1207       | @{const HOL.conj} $ t1 $ t2 => do_conn bs AAnd pos t1 pos t2
  1208       | @{const HOL.disj} $ t1 $ t2 => do_conn bs AOr pos t1 pos t2
  1209       | @{const HOL.implies} $ t1 $ t2 => do_conn bs AImplies (Option.map not pos) t1 pos t2
  1210       | Const (@{const_name HOL.eq}, Type (_, [@{typ bool}, _])) $ t1 $ t2 =>
  1211         if iff_for_eq then do_conn bs AIff NONE t1 NONE t2 else do_term bs t
  1212       | _ => do_term bs t)
  1213   in do_formula [] end
  1214 
  1215 fun presimplify_term ctxt t =
  1216   if exists_Const (member (op =) Meson.presimplified_consts o fst) t then
  1217     t |> Skip_Proof.make_thm (Proof_Context.theory_of ctxt)
  1218       |> Meson.presimplify ctxt
  1219       |> prop_of
  1220   else
  1221     t
  1222 
  1223 fun preprocess_abstractions_in_terms trans_lams facts =
  1224   let
  1225     val (facts, lambda_ts) =
  1226       facts |> map (snd o snd) |> trans_lams
  1227             |>> map2 (fn (name, (role, _)) => fn t => (name, (role, t))) facts
  1228     val lam_facts =
  1229       map2 (fn t => fn j =>
  1230                ((lam_fact_prefix ^ Int.toString j,
  1231                  (Global, Non_Rec_Def)), (Axiom, t)))
  1232            lambda_ts (1 upto length lambda_ts)
  1233   in (facts, lam_facts) end
  1234 
  1235 (* Metis's use of "resolve_tac" freezes the schematic variables. We simulate the
  1236    same in Sledgehammer to prevent the discovery of unreplayable proofs. *)
  1237 fun freeze_term t =
  1238   let
  1239     (* Freshness is desirable for completeness, but not for soundness. *)
  1240     fun indexed_name (s, i) = s ^ "_" ^ string_of_int i ^ atp_weak_suffix
  1241     fun freeze (t $ u) = freeze t $ freeze u
  1242       | freeze (Abs (s, T, t)) = Abs (s, T, freeze t)
  1243       | freeze (Var (x, T)) = Free (indexed_name x, T)
  1244       | freeze t = t
  1245     fun freeze_tvar (x, S) = TFree (indexed_name x, S)
  1246   in
  1247     t |> exists_subterm is_Var t ? freeze
  1248       |> exists_type (exists_subtype is_TVar) t
  1249          ? map_types (map_type_tvar freeze_tvar)
  1250   end
  1251 
  1252 fun presimp_prop ctxt type_enc t =
  1253   let
  1254     val thy = Proof_Context.theory_of ctxt
  1255     val t = t |> Envir.beta_eta_contract
  1256               |> transform_elim_prop
  1257               |> Object_Logic.atomize_term thy
  1258     val need_trueprop = (fastype_of t = @{typ bool})
  1259     val is_ho = is_type_enc_higher_order type_enc
  1260   in
  1261     t |> need_trueprop ? HOLogic.mk_Trueprop
  1262       |> (if is_ho then unextensionalize_def
  1263           else cong_extensionalize_term thy #> abs_extensionalize_term ctxt)
  1264       |> presimplify_term ctxt
  1265       |> HOLogic.dest_Trueprop
  1266   end
  1267   handle TERM _ => @{const True}
  1268 
  1269 (* Satallax prefers "=" to "<=>" (for definitions) and Metis (CNF) requires "=" for technical
  1270    reasons. *)
  1271 fun should_use_iff_for_eq CNF _ = false
  1272   | should_use_iff_for_eq (THF _) format = not (is_type_enc_higher_order format)
  1273   | should_use_iff_for_eq _ _ = true
  1274 
  1275 fun make_formula ctxt format type_enc iff_for_eq name stature role t =
  1276   let
  1277     val iff_for_eq = iff_for_eq andalso should_use_iff_for_eq format type_enc
  1278     val (iformula, atomic_Ts) =
  1279       iformula_of_prop ctxt type_enc iff_for_eq (SOME (role <> Conjecture)) t []
  1280       |>> close_universally add_iterm_vars
  1281   in
  1282     {name = name, stature = stature, role = role, iformula = iformula,
  1283      atomic_types = atomic_Ts}
  1284   end
  1285 
  1286 fun is_format_with_defs (THF _) = true
  1287   | is_format_with_defs _ = false
  1288 
  1289 fun make_fact ctxt format type_enc iff_for_eq
  1290               ((name, stature as (_, status)), t) =
  1291   let
  1292     val role =
  1293       if is_format_with_defs format andalso status = Non_Rec_Def andalso
  1294          is_legitimate_tptp_def t then
  1295         Definition
  1296       else
  1297         Axiom
  1298   in
  1299     (case t |> make_formula ctxt format type_enc iff_for_eq name stature role of
  1300       formula as {iformula = AAtom (IConst ((s, _), _, _)), ...} =>
  1301       if s = tptp_true then NONE else SOME formula
  1302     | formula => SOME formula)
  1303   end
  1304 
  1305 fun make_conjecture ctxt format type_enc =
  1306   map (fn ((name, stature), (role, t)) =>
  1307           let
  1308             val role =
  1309               if role <> Conjecture andalso is_legitimate_tptp_def t then Definition else role
  1310           in
  1311             t |> role = Conjecture ? s_not
  1312               |> make_formula ctxt format type_enc true name stature role
  1313           end)
  1314 
  1315 (** Finite and infinite type inference **)
  1316 
  1317 fun tvar_footprint thy s ary =
  1318   (case unprefix_and_unascii const_prefix s of
  1319     SOME s =>
  1320     let fun tvars_of T = [] |> Term.add_tvarsT T |> map fst in
  1321       s |> unmangled_invert_const |> robust_const_type thy |> chop_fun ary |> fst |> map tvars_of
  1322     end
  1323   | NONE => [])
  1324   handle TYPE _ => []
  1325 
  1326 fun type_arg_cover thy pos s ary =
  1327   if is_tptp_equal s then
  1328     if pos = SOME false then [] else 0 upto ary - 1
  1329   else
  1330     let
  1331       val footprint = tvar_footprint thy s ary
  1332       val eq = (s = @{const_name HOL.eq})
  1333       fun cover _ [] = []
  1334         | cover seen ((i, tvars) :: args) =
  1335           cover (union (op =) seen tvars) args
  1336           |> (eq orelse exists (fn tvar => not (member (op =) seen tvar)) tvars)
  1337              ? cons i
  1338     in
  1339       if forall null footprint then
  1340         []
  1341       else
  1342         0 upto length footprint - 1 ~~ footprint
  1343         |> sort (rev_order o list_ord Term_Ord.indexname_ord o pairself snd)
  1344         |> cover []
  1345     end
  1346 
  1347 type monotonicity_info =
  1348   {maybe_finite_Ts : typ list,
  1349    surely_infinite_Ts : typ list,
  1350    maybe_nonmono_Ts : typ list}
  1351 
  1352 (* These types witness that the type classes they belong to allow infinite
  1353    models and hence that any types with these type classes is monotonic. *)
  1354 val known_infinite_types =
  1355   [@{typ nat}, HOLogic.intT, HOLogic.realT, @{typ "nat => bool"}]
  1356 
  1357 fun is_type_kind_of_surely_infinite ctxt strictness cached_Ts T =
  1358   strictness <> Strict andalso is_type_surely_infinite ctxt true cached_Ts T
  1359 
  1360 (* Finite types such as "unit", "bool", "bool * bool", and "bool => bool" are
  1361    dangerous because their "exhaust" properties can easily lead to unsound ATP
  1362    proofs. On the other hand, all HOL infinite types can be given the same
  1363    models in first-order logic (via Loewenheim-Skolem). *)
  1364 
  1365 fun should_encode_type ctxt {maybe_finite_Ts, surely_infinite_Ts,
  1366                              maybe_nonmono_Ts}
  1367                        (Nonmono_Types (strictness, _)) T =
  1368     let val thy = Proof_Context.theory_of ctxt in
  1369       (exists (type_intersect thy T) maybe_nonmono_Ts andalso
  1370        not (exists (type_instance thy T) surely_infinite_Ts orelse
  1371             (not (member (type_equiv thy) maybe_finite_Ts T) andalso
  1372              is_type_kind_of_surely_infinite ctxt strictness surely_infinite_Ts
  1373                                              T)))
  1374     end
  1375   | should_encode_type _ _ level _ =
  1376     (level = All_Types orelse level = Undercover_Types)
  1377 
  1378 fun should_guard_type ctxt mono (Guards (_, level)) should_guard_var T =
  1379     should_guard_var () andalso should_encode_type ctxt mono level T
  1380   | should_guard_type _ _ _ _ _ = false
  1381 
  1382 fun is_maybe_universal_name s =
  1383   String.isPrefix bound_var_prefix s orelse
  1384   String.isPrefix all_bound_var_prefix s
  1385 
  1386 fun is_maybe_universal_var (IConst ((s, _), _, _)) = is_maybe_universal_name s
  1387   | is_maybe_universal_var (IVar _) = true
  1388   | is_maybe_universal_var _ = false
  1389 
  1390 datatype site =
  1391   Top_Level of bool option |
  1392   Eq_Arg of bool option |
  1393   Arg of string * int * int |
  1394   Elsewhere
  1395 
  1396 fun should_tag_with_type _ _ _ (Top_Level _) _ _ = false
  1397   | should_tag_with_type ctxt mono (Tags (_, level)) site u T =
  1398     let val thy = Proof_Context.theory_of ctxt in
  1399       (case level of
  1400         Nonmono_Types (_, Non_Uniform) =>
  1401         (case (site, is_maybe_universal_var u) of
  1402           (Eq_Arg pos, true) =>
  1403           (pos <> SOME false orelse tag_neg_vars) andalso should_encode_type ctxt mono level T
  1404         | _ => false)
  1405       | Undercover_Types =>
  1406         (case (site, is_maybe_universal_var u) of
  1407           (Eq_Arg pos, true) => pos <> SOME false
  1408         | (Arg (s, j, ary), true) => member (op =) (type_arg_cover thy NONE s ary) j
  1409         | _ => false)
  1410       | _ => should_encode_type ctxt mono level T)
  1411     end
  1412   | should_tag_with_type _ _ _ _ _ _ = false
  1413 
  1414 fun fused_type ctxt mono level =
  1415   let
  1416     val should_encode = should_encode_type ctxt mono level
  1417     fun fuse 0 T = if should_encode T then T else fused_infinite_type
  1418       | fuse ary (Type (@{type_name fun}, [T1, T2])) =
  1419         fuse 0 T1 --> fuse (ary - 1) T2
  1420       | fuse _ _ = raise Fail "expected function type"
  1421   in fuse end
  1422 
  1423 (** predicators and application operators **)
  1424 
  1425 type sym_info =
  1426   {pred_sym : bool, min_ary : int, max_ary : int, types : typ list,
  1427    in_conj : bool}
  1428 
  1429 fun default_sym_tab_entries type_enc =
  1430   (make_fixed_const NONE @{const_name undefined},
  1431      {pred_sym = false, min_ary = 0, max_ary = 0, types = [], in_conj = false}) ::
  1432   ([tptp_false, tptp_true]
  1433    |> map (rpair {pred_sym = true, min_ary = 0, max_ary = 0, types = [], in_conj = false})) @
  1434   ([tptp_equal, tptp_old_equal]
  1435    |> map (rpair {pred_sym = true, min_ary = 2, max_ary = 2, types = [], in_conj = false}))
  1436   |> not (is_type_enc_higher_order type_enc)
  1437     ? cons (prefixed_predicator_name,
  1438       {pred_sym = true, min_ary = 1, max_ary = 1, types = [], in_conj = false})
  1439 
  1440 datatype app_op_level =
  1441   Min_App_Op |
  1442   Sufficient_App_Op |
  1443   Sufficient_App_Op_And_Predicator |
  1444   Full_App_Op_And_Predicator
  1445 
  1446 fun add_iterm_syms_to_sym_table ctxt app_op_level conj_fact =
  1447   let
  1448     val thy = Proof_Context.theory_of ctxt
  1449     fun consider_var_ary const_T var_T max_ary =
  1450       let
  1451         fun iter ary T =
  1452           if ary = max_ary orelse type_instance thy var_T T orelse type_instance thy T var_T then
  1453             ary
  1454           else
  1455             iter (ary + 1) (range_type T)
  1456       in iter 0 const_T end
  1457     fun add_universal_var T (accum as ((bool_vars, fun_var_Ts), sym_tab)) =
  1458       if (app_op_level = Sufficient_App_Op andalso can dest_funT T) orelse
  1459          (app_op_level = Sufficient_App_Op_And_Predicator andalso
  1460           (can dest_funT T orelse T = @{typ bool})) then
  1461         let
  1462           val bool_vars' =
  1463             bool_vars orelse
  1464             (app_op_level = Sufficient_App_Op_And_Predicator andalso body_type T = @{typ bool})
  1465           fun repair_min_ary {pred_sym, min_ary, max_ary, types, in_conj} =
  1466             {pred_sym = pred_sym andalso not bool_vars',
  1467              min_ary = fold (fn T' => consider_var_ary T' T) types min_ary,
  1468              max_ary = max_ary, types = types, in_conj = in_conj}
  1469           val fun_var_Ts' = fun_var_Ts |> can dest_funT T ? insert_type thy I T
  1470         in
  1471           if bool_vars' = bool_vars andalso pointer_eq (fun_var_Ts', fun_var_Ts) then accum
  1472           else ((bool_vars', fun_var_Ts'), Symtab.map (K repair_min_ary) sym_tab)
  1473         end
  1474       else
  1475         accum
  1476     fun add_iterm_syms top_level tm (accum as ((bool_vars, fun_var_Ts), sym_tab)) =
  1477       let val (head, args) = strip_iterm_comb tm in
  1478         (case head of
  1479           IConst ((s, _), T, _) =>
  1480           if is_maybe_universal_name s then
  1481             add_universal_var T accum
  1482           else if String.isPrefix exist_bound_var_prefix s then
  1483             accum
  1484           else
  1485             let val ary = length args in
  1486               ((bool_vars, fun_var_Ts),
  1487                (case Symtab.lookup sym_tab s of
  1488                  SOME {pred_sym, min_ary, max_ary, types, in_conj} =>
  1489                  let
  1490                    val pred_sym = pred_sym andalso top_level andalso not bool_vars
  1491                    val types' = types |> insert_type thy I T
  1492                    val in_conj = in_conj orelse conj_fact
  1493                    val min_ary =
  1494                      if (app_op_level = Sufficient_App_Op orelse
  1495                          app_op_level = Sufficient_App_Op_And_Predicator)
  1496                         andalso not (pointer_eq (types', types)) then
  1497                        fold (consider_var_ary T) fun_var_Ts min_ary
  1498                      else
  1499                        min_ary
  1500                  in
  1501                    Symtab.update (s, {pred_sym = pred_sym, min_ary = Int.min (ary, min_ary),
  1502                      max_ary = Int.max (ary, max_ary), types = types', in_conj = in_conj}) sym_tab
  1503                  end
  1504                | NONE =>
  1505                  let
  1506                    val max_ary =
  1507                      (case unprefix_and_unascii const_prefix s of
  1508                        SOME s =>
  1509                        (if String.isSubstring uncurried_alias_sep s then
  1510                           ary
  1511                         else
  1512                           (case try (ary_of o robust_const_type thy o unmangled_invert_const) s of
  1513                             SOME ary0 => Int.min (ary0, ary)
  1514                           | NONE => ary))
  1515                      | NONE => ary)
  1516                    val pred_sym = top_level andalso max_ary = ary andalso not bool_vars
  1517                    val min_ary =
  1518                      (case app_op_level of
  1519                        Min_App_Op => max_ary
  1520                      | Full_App_Op_And_Predicator => 0
  1521                      | _ => fold (consider_var_ary T) fun_var_Ts max_ary)
  1522                  in
  1523                    Symtab.update_new (s, {pred_sym = pred_sym, min_ary = min_ary, max_ary = max_ary,
  1524                      types = [T], in_conj = conj_fact}) sym_tab
  1525                  end))
  1526             end
  1527         | IVar (_, T) => add_universal_var T accum
  1528         | IAbs ((_, T), tm) => accum |> add_universal_var T |> add_iterm_syms false tm
  1529         | _ => accum)
  1530         |> fold (add_iterm_syms false) args
  1531       end
  1532   in add_iterm_syms end
  1533 
  1534 fun sym_table_of_facts ctxt type_enc app_op_level conjs facts =
  1535   let
  1536     fun add_iterm_syms conj_fact = add_iterm_syms_to_sym_table ctxt app_op_level conj_fact true
  1537     fun add_fact_syms conj_fact = ifact_lift (formula_fold NONE (K (add_iterm_syms conj_fact)))
  1538   in
  1539     ((false, []), Symtab.empty)
  1540     |> fold (add_fact_syms true) conjs
  1541     |> fold (add_fact_syms false) facts
  1542     ||> fold Symtab.update (default_sym_tab_entries type_enc)
  1543   end
  1544 
  1545 fun min_ary_of sym_tab s =
  1546   (case Symtab.lookup sym_tab s of
  1547     SOME ({min_ary, ...} : sym_info) => min_ary
  1548   | NONE =>
  1549     (case unprefix_and_unascii const_prefix s of
  1550       SOME s =>
  1551       let val s = s |> unmangled_invert_const in
  1552         if s = predicator_name then 1
  1553         else if s = app_op_name then 2
  1554         else if s = type_guard_name then 1
  1555         else 0
  1556       end
  1557     | NONE => 0))
  1558 
  1559 (* True if the constant ever appears outside of the top-level position in
  1560    literals, or if it appears with different arities (e.g., because of different
  1561    type instantiations). If false, the constant always receives all of its
  1562    arguments and is used as a predicate. *)
  1563 fun is_pred_sym sym_tab s =
  1564   (case Symtab.lookup sym_tab s of
  1565     SOME ({pred_sym, min_ary, max_ary, ...} : sym_info) => pred_sym andalso min_ary = max_ary
  1566   | NONE => false)
  1567 
  1568 val fTrue_iconst = IConst ((const_prefix ^ "fTrue", @{const_name ATP.fTrue}), @{typ bool}, [])
  1569 val predicator_iconst = IConst (`(make_fixed_const NONE) predicator_name, @{typ "bool => bool"}, [])
  1570 
  1571 fun predicatify completish tm =
  1572   if completish then
  1573     IApp (IApp (IConst (`I tptp_equal, @{typ "bool => bool => bool"}, []), tm), fTrue_iconst)
  1574   else
  1575     IApp (predicator_iconst, tm)
  1576 
  1577 val app_op = `(make_fixed_const NONE) app_op_name
  1578 
  1579 fun list_app head args = fold (curry (IApp o swap)) args head
  1580 
  1581 fun mk_app_op type_enc head arg =
  1582   let
  1583     val head_T = ityp_of head
  1584     val (arg_T, res_T) = dest_funT head_T
  1585     val app =
  1586       IConst (app_op, head_T --> head_T, [arg_T, res_T])
  1587       |> mangle_type_args_in_iterm type_enc
  1588   in list_app app [head, arg] end
  1589 
  1590 fun firstorderize_fact thy ctrss type_enc uncurried_aliases completish sym_tab =
  1591   let
  1592     fun do_app arg head = mk_app_op type_enc head arg
  1593     fun list_app_ops (head, args) = fold do_app args head
  1594     fun introduce_app_ops tm =
  1595       let val (head, args) = tm |> strip_iterm_comb ||> map introduce_app_ops in
  1596         (case head of
  1597           IConst (name as (s, _), T, T_args) =>
  1598           let
  1599             val min_ary = min_ary_of sym_tab s
  1600             val ary =
  1601               if uncurried_aliases andalso String.isPrefix const_prefix s then
  1602                 let
  1603                   val ary = length args
  1604                   (* In polymorphic native type encodings, it is impossible to
  1605                      declare a fully polymorphic symbol that takes more
  1606                      arguments than its signature (even though such concrete
  1607                      instances, where a type variable is instantiated by a
  1608                      function type, are possible.) *)
  1609                   val official_ary =
  1610                     if is_type_enc_polymorphic type_enc then
  1611                       (case unprefix_and_unascii const_prefix s of
  1612                         SOME s' =>
  1613                         (case try (ary_of o robust_const_type thy) (invert_const s') of
  1614                           SOME ary => ary
  1615                         | NONE => min_ary)
  1616                       | NONE => min_ary)
  1617                     else
  1618                       1000000000 (* irrealistically big arity *)
  1619                 in Int.min (ary, official_ary) end
  1620               else
  1621                 min_ary
  1622             val head =
  1623               if ary = min_ary then head else IConst (aliased_uncurried ary name, T, T_args)
  1624           in
  1625             args |> chop ary |>> list_app head |> list_app_ops
  1626           end
  1627         | _ => list_app_ops (head, args))
  1628       end
  1629     fun introduce_predicators tm =
  1630       (case strip_iterm_comb tm of
  1631         (IConst ((s, _), _, _), _) =>
  1632         if is_pred_sym sym_tab s then tm else predicatify completish tm
  1633       | _ => predicatify completish tm)
  1634     val do_iterm =
  1635       not (is_type_enc_higher_order type_enc) ? (introduce_app_ops #> introduce_predicators)
  1636       #> filter_type_args_in_iterm thy ctrss type_enc
  1637   in update_iformula (formula_map do_iterm) end
  1638 
  1639 (** Helper facts **)
  1640 
  1641 val not_ffalse = @{lemma "~ fFalse" by (unfold fFalse_def) fast}
  1642 val ftrue = @{lemma "fTrue" by (unfold fTrue_def) fast}
  1643 
  1644 (* The Boolean indicates that a fairly sound type encoding is needed. *)
  1645 val base_helper_table =
  1646   [(("COMBI", false), [(Non_Rec_Def, @{thm Meson.COMBI_def})]),
  1647    (("COMBK", false), [(Non_Rec_Def, @{thm Meson.COMBK_def})]),
  1648    (("COMBB", false), [(Non_Rec_Def, @{thm Meson.COMBB_def})]),
  1649    (("COMBC", false), [(Non_Rec_Def, @{thm Meson.COMBC_def})]),
  1650    (("COMBS", false), [(Non_Rec_Def, @{thm Meson.COMBS_def})]),
  1651    ((predicator_name, false), [(General, not_ffalse), (General, ftrue)]),
  1652    (("fFalse", false), [(General, not_ffalse)]),
  1653    (("fFalse", true), [(General, @{thm True_or_False})]),
  1654    (("fTrue", false), [(General, ftrue)]),
  1655    (("fTrue", true), [(General, @{thm True_or_False})]),
  1656    (("If", true),
  1657     [(Non_Rec_Def, @{thm if_True}), (Non_Rec_Def, @{thm if_False}),
  1658      (General, @{thm True_or_False})])]
  1659 
  1660 val helper_table =
  1661   base_helper_table @
  1662   [(("fNot", false),
  1663     @{thms fNot_def [THEN Meson.iff_to_disjD, THEN conjunct1]
  1664            fNot_def [THEN Meson.iff_to_disjD, THEN conjunct2]}
  1665     |> map (pair Non_Rec_Def)),
  1666    (("fconj", false),
  1667     @{lemma "~ P | ~ Q | fconj P Q" "~ fconj P Q | P" "~ fconj P Q | Q" by (unfold fconj_def) fast+}
  1668     |> map (pair General)),
  1669    (("fdisj", false),
  1670     @{lemma "~ P | fdisj P Q" "~ Q | fdisj P Q" "~ fdisj P Q | P | Q" by (unfold fdisj_def) fast+}
  1671     |> map (pair General)),
  1672    (("fimplies", false),
  1673     @{lemma "P | fimplies P Q" "~ Q | fimplies P Q" "~ fimplies P Q | ~ P | Q"
  1674         by (unfold fimplies_def) fast+}
  1675     |> map (pair General)),
  1676    (("fequal", true),
  1677     (* This is a lie: Higher-order equality doesn't need a sound type encoding.
  1678        However, this is done so for backward compatibility: Including the
  1679        equality helpers by default in Metis breaks a few existing proofs. *)
  1680     @{thms fequal_def [THEN Meson.iff_to_disjD, THEN conjunct1]
  1681            fequal_def [THEN Meson.iff_to_disjD, THEN conjunct2]}
  1682     |> map (pair General)),
  1683    (* Partial characterization of "fAll" and "fEx". A complete characterization
  1684       would require the axiom of choice for replay with Metis. *)
  1685    (("fAll", false), [(General, @{lemma "~ fAll P | P x" by (auto simp: fAll_def)})]),
  1686    (("fEx", false), [(General, @{lemma "~ P x | fEx P" by (auto simp: fEx_def)})])]
  1687   |> map (apsnd (map (apsnd zero_var_indexes)))
  1688 
  1689 val completish_helper_table =
  1690   helper_table @
  1691   [((predicator_name, true),
  1692     @{thms True_or_False fTrue_ne_fFalse} |> map (pair General)),
  1693    ((app_op_name, true),
  1694     [(General, @{lemma "EX x. ~ f x = g x | f = g" by blast}),
  1695      (General, @{lemma "EX p. (p x <-> p y) --> x = y" by blast})]),
  1696    (("fconj", false), @{thms fconj_table fconj_laws fdisj_laws} |> map (pair Non_Rec_Def)),
  1697    (("fdisj", false), @{thms fdisj_table fconj_laws fdisj_laws} |> map (pair Non_Rec_Def)),
  1698    (("fimplies", false),
  1699     @{thms fimplies_table fconj_laws fdisj_laws fimplies_laws}
  1700     |> map (pair Non_Rec_Def)),
  1701    (("fequal", false),
  1702     (@{thms fequal_table} |> map (pair Non_Rec_Def)) @
  1703     (@{thms fequal_laws} |> map (pair General))),
  1704    (("fAll", false), @{thms fAll_table fComp_law fAll_law fEx_law} |> map (pair Non_Rec_Def)),
  1705    (("fEx", false), @{thms fEx_table fComp_law fAll_law fEx_law} |> map (pair Non_Rec_Def))]
  1706   |> map (apsnd (map (apsnd zero_var_indexes)))
  1707 
  1708 fun bound_tvars type_enc sorts Ts =
  1709   (case filter is_TVar Ts of
  1710     [] => I
  1711   | Ts =>
  1712     ((sorts andalso polymorphism_of_type_enc type_enc <> Type_Class_Polymorphic)
  1713      ? mk_ahorn (Ts
  1714        |> class_membs_of_types type_enc add_sorts_on_tvar
  1715        |> map (class_atom type_enc)))
  1716     #> (case type_enc of
  1717          Native (_, poly, _) =>
  1718          mk_atyquant AForall (map (fn TVar (z as (_, S)) =>
  1719            (AType ((tvar_name z, []), []),
  1720             if poly = Type_Class_Polymorphic then map (`make_class) (normalize_classes S)
  1721             else [])) Ts)
  1722         | _ => mk_aquant AForall (map (fn TVar z => (tvar_name z, NONE)) Ts)))
  1723 
  1724 fun eq_formula type_enc atomic_Ts bounds pred_sym tm1 tm2 =
  1725   (if pred_sym then AConn (AIff, [AAtom tm1, AAtom tm2])
  1726    else AAtom (ATerm ((`I tptp_equal, []), [tm1, tm2])))
  1727   |> mk_aquant AForall bounds
  1728   |> close_formula_universally
  1729   |> bound_tvars type_enc true atomic_Ts
  1730 
  1731 val helper_rank = default_rank
  1732 val min_rank = 9 * helper_rank div 10
  1733 val max_rank = 4 * min_rank
  1734 
  1735 fun rank_of_fact_num n j = min_rank + (max_rank - min_rank) * j div n
  1736 
  1737 val type_tag = `(make_fixed_const NONE) type_tag_name
  1738 
  1739 fun could_specialize_helpers type_enc =
  1740   not (is_type_enc_polymorphic type_enc) andalso level_of_type_enc type_enc <> No_Types
  1741 
  1742 fun should_specialize_helper type_enc t =
  1743   could_specialize_helpers type_enc andalso not (null (Term.hidden_polymorphism t))
  1744 
  1745 fun add_helper_facts_of_sym ctxt format type_enc completish
  1746                             (s, {types, ...} : sym_info) =
  1747   (case unprefix_and_unascii const_prefix s of
  1748     SOME mangled_s =>
  1749     let
  1750       val thy = Proof_Context.theory_of ctxt
  1751       val unmangled_s = mangled_s |> unmangled_const_name |> hd
  1752       fun dub needs_sound j k =
  1753         ascii_of unmangled_s ^ "_" ^ string_of_int j ^ "_" ^ string_of_int k ^
  1754         (if mangled_s = unmangled_s then "" else "_" ^ ascii_of mangled_s) ^
  1755         (if needs_sound then typed_helper_suffix else untyped_helper_suffix)
  1756       fun specialize_helper t T =
  1757         if unmangled_s = app_op_name then
  1758           let val tyenv = Sign.typ_match thy (alpha_to_beta, domain_type T) Vartab.empty in
  1759             monomorphic_term tyenv t
  1760           end
  1761         else
  1762           specialize_type thy (invert_const unmangled_s, T) t
  1763       fun dub_and_inst needs_sound ((status, t), j) =
  1764         (if should_specialize_helper type_enc t then
  1765            map_filter (try (specialize_helper t)) types
  1766          else
  1767            [t])
  1768         |> tag_list 1
  1769         |> map (fn (k, t) => ((dub needs_sound j k, (Global, status)), t))
  1770       val make_facts = map_filter (make_fact ctxt format type_enc false)
  1771       val sound = is_type_enc_sound type_enc
  1772       val could_specialize = could_specialize_helpers type_enc
  1773     in
  1774       fold (fn ((helper_s, needs_sound), ths) =>
  1775                if (needs_sound andalso not sound) orelse
  1776                   (helper_s <> unmangled_s andalso
  1777                    (not completish orelse could_specialize)) then
  1778                  I
  1779                else
  1780                  ths ~~ (1 upto length ths)
  1781                  |> maps (dub_and_inst needs_sound o apfst (apsnd prop_of))
  1782                  |> make_facts
  1783                  |> union (op = o pairself #iformula))
  1784            (if completish then completish_helper_table else helper_table)
  1785     end
  1786   | NONE => I)
  1787 fun helper_facts_of_sym_table ctxt format type_enc completish sym_tab =
  1788   Symtab.fold_rev (add_helper_facts_of_sym ctxt format type_enc completish)
  1789                   sym_tab []
  1790 
  1791 (***************************************************************)
  1792 (* Type Classes Present in the Axiom or Conjecture Clauses     *)
  1793 (***************************************************************)
  1794 
  1795 fun set_insert (x, s) = Symtab.update (x, ()) s
  1796 
  1797 fun add_classes (cls, cset) = List.foldl set_insert cset (flat cls)
  1798 
  1799 fun classes_of_terms get_Ts =
  1800   map (map snd o get_Ts)
  1801   #> List.foldl add_classes Symtab.empty #> Symtab.delete_safe class_of_types
  1802   #> Symtab.keys
  1803 
  1804 val tfree_classes_of_terms = classes_of_terms Misc_Legacy.term_tfrees
  1805 val tvar_classes_of_terms = classes_of_terms Misc_Legacy.term_tvars
  1806 
  1807 fun fold_type_ctrs f (Type (s, Ts)) x = fold (fold_type_ctrs f) Ts (f (s, x))
  1808   | fold_type_ctrs _ _ x = x
  1809 
  1810 (* Type constructors used to instantiate overloaded constants are the only ones
  1811    needed. *)
  1812 fun add_type_ctrs_in_term thy =
  1813   let
  1814     fun add (Const (@{const_name Meson.skolem}, _) $ _) = I
  1815       | add (t $ u) = add t #> add u
  1816       | add (Const x) =
  1817         x |> robust_const_type_args thy |> fold (fold_type_ctrs set_insert)
  1818       | add (Abs (_, _, u)) = add u
  1819       | add _ = I
  1820   in add end
  1821 
  1822 fun type_ctrs_of_terms thy ts =
  1823   Symtab.keys (fold (add_type_ctrs_in_term thy) ts Symtab.empty)
  1824 
  1825 fun extract_lambda_def (Const (@{const_name HOL.eq}, _) $ t $ u) =
  1826     let val (head, args) = strip_comb t in
  1827       (head |> dest_Const |> fst,
  1828        fold_rev (fn t as Var ((s, _), T) =>
  1829                     (fn u => Abs (s, T, abstract_over (t, u)))
  1830                   | _ => raise Fail "expected \"Var\"") args u)
  1831     end
  1832   | extract_lambda_def _ = raise Fail "malformed lifted lambda"
  1833 
  1834 fun trans_lams_of_string ctxt type_enc lam_trans =
  1835   if lam_trans = no_lamsN then
  1836     rpair []
  1837   else if lam_trans = hide_lamsN then
  1838     lift_lams ctxt type_enc ##> K []
  1839   else if lam_trans = liftingN orelse lam_trans = lam_liftingN then
  1840     lift_lams ctxt type_enc
  1841   else if lam_trans = combsN then
  1842     map (introduce_combinators ctxt) #> rpair []
  1843   else if lam_trans = combs_and_liftingN then
  1844     lift_lams_part_1 ctxt type_enc
  1845     ##> maps (fn t => [t, introduce_combinators ctxt (intentionalize_def t)])
  1846     #> lift_lams_part_2 ctxt
  1847   else if lam_trans = combs_or_liftingN then
  1848     lift_lams_part_1 ctxt type_enc
  1849     ##> map (fn t => (case head_of (strip_qnt_body @{const_name All} t) of
  1850                        @{term "op =::bool => bool => bool"} => t
  1851                      | _ => introduce_combinators ctxt (intentionalize_def t)))
  1852     #> lift_lams_part_2 ctxt
  1853   else if lam_trans = keep_lamsN then
  1854     map (Envir.eta_contract) #> rpair []
  1855   else
  1856     error ("Unknown lambda translation scheme: " ^ quote lam_trans ^ ".")
  1857 
  1858 val pull_and_reorder_definitions =
  1859   let
  1860     fun add_consts (IApp (t, u)) = fold add_consts [t, u]
  1861       | add_consts (IAbs (_, t)) = add_consts t
  1862       | add_consts (IConst (name, _, _)) = insert (op =) name
  1863       | add_consts (IVar _) = I
  1864     fun consts_of_hs l_or_r ({iformula, ...} : ifact) =
  1865       (case iformula of
  1866         AAtom (IApp (IApp (IConst _, t), u)) => add_consts (l_or_r (t, u)) []
  1867       | _ => [])
  1868     (* Quadratic, but usually OK. *)
  1869     fun reorder [] [] = []
  1870       | reorder (fact :: skipped) [] =
  1871         fact :: reorder [] skipped (* break cycle *)
  1872       | reorder skipped (fact :: facts) =
  1873         let val rhs_consts = consts_of_hs snd fact in
  1874           if exists (exists (exists (member (op =) rhs_consts)
  1875                      o consts_of_hs fst)) [skipped, facts] then
  1876             reorder (fact :: skipped) facts
  1877           else
  1878             fact :: reorder [] (facts @ skipped)
  1879         end
  1880   in List.partition (curry (op =) Definition o #role) #>> reorder [] #> op @ end
  1881 
  1882 fun s_not_prop (@{const Trueprop} $ t) = @{const Trueprop} $ s_not t
  1883   | s_not_prop (@{const Pure.imp} $ t $ @{prop False}) = t
  1884   | s_not_prop t = @{const Pure.imp} $ t $ @{prop False}
  1885 
  1886 fun translate_formulas ctxt prem_role format type_enc lam_trans presimp hyp_ts
  1887                        concl_t facts =
  1888   let
  1889     val thy = Proof_Context.theory_of ctxt
  1890     val trans_lams = trans_lams_of_string ctxt type_enc lam_trans
  1891     val fact_ts = facts |> map snd
  1892     (* Remove existing facts from the conjecture, as this can dramatically boost an ATP's
  1893        performance (for some reason). *)
  1894     val hyp_ts = hyp_ts |> map (fn t => if member (op aconv) fact_ts t then @{prop True} else t)
  1895     val facts = facts |> map (apsnd (pair Axiom))
  1896     val conjs =
  1897       map (pair prem_role) hyp_ts @ [(Conjecture, s_not_prop concl_t)]
  1898       |> map (apsnd freeze_term)
  1899       |> map2 (pair o rpair (Local, General) o string_of_int) (0 upto length hyp_ts)
  1900     val ((conjs, facts), lam_facts) =
  1901       (conjs, facts)
  1902       |> presimp ? pairself (map (apsnd (apsnd (presimp_prop ctxt type_enc))))
  1903       |> (if lam_trans = no_lamsN then
  1904             rpair []
  1905           else
  1906             op @
  1907             #> preprocess_abstractions_in_terms trans_lams
  1908             #>> chop (length conjs))
  1909     val conjs =
  1910       conjs |> make_conjecture ctxt format type_enc
  1911             |> pull_and_reorder_definitions
  1912     val facts =
  1913       facts |> map_filter (fn (name, (_, t)) =>
  1914                               make_fact ctxt format type_enc true (name, t))
  1915             |> pull_and_reorder_definitions
  1916     val fact_names = facts |> map (fn {name, stature, ...} : ifact => (name, stature))
  1917     val lifted = lam_facts |> map (extract_lambda_def o snd o snd)
  1918     val lam_facts = lam_facts |> map_filter (make_fact ctxt format type_enc true o apsnd snd)
  1919     val all_ts = concl_t :: hyp_ts @ fact_ts
  1920     val subs = tfree_classes_of_terms all_ts
  1921     val supers = tvar_classes_of_terms all_ts
  1922     val tycons = type_ctrs_of_terms thy all_ts
  1923     val (supers, tcon_clauses) =
  1924       if level_of_type_enc type_enc = No_Types then ([], [])
  1925       else make_tcon_clauses thy tycons supers
  1926     val subclass_pairs = make_subclass_pairs thy subs supers
  1927   in
  1928     (fact_names |> map single, union (op =) subs supers, conjs,
  1929      facts @ lam_facts, subclass_pairs, tcon_clauses, lifted)
  1930   end
  1931 
  1932 val type_guard = `(make_fixed_const NONE) type_guard_name
  1933 
  1934 fun type_guard_iterm type_enc T tm =
  1935   IApp (IConst (type_guard, T --> @{typ bool}, [T])
  1936         |> mangle_type_args_in_iterm type_enc, tm)
  1937 
  1938 fun is_var_positively_naked_in_term _ (SOME false) _ accum = accum
  1939   | is_var_positively_naked_in_term name _ (ATerm (((s, _), _), tms)) accum =
  1940     accum orelse (is_tptp_equal s andalso member (op =) tms (ATerm ((name, []), [])))
  1941   | is_var_positively_naked_in_term _ _ _ _ = true
  1942 
  1943 fun is_var_undercover_in_term thy name pos tm accum =
  1944   accum orelse
  1945   let
  1946     val var = ATerm ((name, []), [])
  1947     fun is_undercover (ATerm (_, [])) = false
  1948       | is_undercover (ATerm (((s, _), _), tms)) =
  1949         let
  1950           val ary = length tms
  1951           val cover = type_arg_cover thy pos s ary
  1952         in
  1953           exists (fn (j, tm) => tm = var andalso member (op =) cover j)
  1954                  (0 upto ary - 1 ~~ tms) orelse
  1955           exists is_undercover tms
  1956         end
  1957       | is_undercover _ = true
  1958   in is_undercover tm end
  1959 
  1960 fun should_guard_var_in_formula thy level pos phi (SOME true) name =
  1961     (case level of
  1962       All_Types => true
  1963     | Undercover_Types => formula_fold pos (is_var_undercover_in_term thy name) phi false
  1964     | Nonmono_Types (_, Uniform) => true
  1965     | Nonmono_Types (_, Non_Uniform) =>
  1966       formula_fold pos (is_var_positively_naked_in_term name) phi false
  1967     | _ => false)
  1968   | should_guard_var_in_formula _ _ _ _ _ _ = true
  1969 
  1970 fun always_guard_var_in_formula _ _ _ _ _ _ = true
  1971 
  1972 fun should_generate_tag_bound_decl _ _ _ (SOME true) _ = false
  1973   | should_generate_tag_bound_decl ctxt mono (Tags (_, level)) _ T =
  1974     not (is_type_level_uniform level) andalso
  1975     should_encode_type ctxt mono level T
  1976   | should_generate_tag_bound_decl _ _ _ _ _ = false
  1977 
  1978 fun mk_aterm type_enc name T_args args =
  1979   let val (ty_args, tm_args) = process_type_args type_enc T_args in
  1980     ATerm ((name, ty_args), tm_args @ args)
  1981   end
  1982 
  1983 fun do_bound_type ctxt mono type_enc =
  1984   (case type_enc of
  1985     Native (_, _, level) =>
  1986     fused_type ctxt mono level 0 #> native_atp_type_of_typ type_enc false 0 #> SOME
  1987   | _ => K NONE)
  1988 
  1989 fun tag_with_type ctxt mono type_enc pos T tm =
  1990   IConst (type_tag, T --> T, [T])
  1991   |> mangle_type_args_in_iterm type_enc
  1992   |> atp_term_of_iterm ctxt mono type_enc pos
  1993   |> (fn ATerm ((s, tys), tms) => ATerm ((s, tys), tms @ [tm])
  1994        | _ => raise Fail "unexpected lambda-abstraction")
  1995 and atp_term_of_iterm ctxt mono type_enc pos =
  1996   let
  1997     fun term site u =
  1998       let
  1999         val (head, args) = strip_iterm_comb u
  2000         val pos = (case site of Top_Level pos => pos | Eq_Arg pos => pos | _ => NONE)
  2001         val T = ityp_of u
  2002         val t =
  2003           (case head of
  2004             IConst (name as (s, _), _, T_args) =>
  2005             let
  2006               val ary = length args
  2007               fun arg_site j = if is_tptp_equal s then Eq_Arg pos else Arg (s, j, ary)
  2008             in
  2009               map2 (fn j => term (arg_site j)) (0 upto ary - 1) args
  2010               |> mk_aterm type_enc name T_args
  2011             end
  2012           | IVar (name, _) =>
  2013             map (term Elsewhere) args |> mk_aterm type_enc name []
  2014           | IAbs ((name, T), tm) =>
  2015             if is_type_enc_higher_order type_enc then
  2016               AAbs (((name, native_atp_type_of_typ type_enc true 0 T), (* FIXME? why "true"? *)
  2017                      term Elsewhere tm), map (term Elsewhere) args)
  2018             else
  2019               raise Fail "unexpected lambda-abstraction"
  2020           | IApp _ => raise Fail "impossible \"IApp\"")
  2021         val tag = should_tag_with_type ctxt mono type_enc site u T
  2022       in t |> tag ? tag_with_type ctxt mono type_enc pos T end
  2023   in term (Top_Level pos) end
  2024 and formula_of_iformula ctxt mono type_enc should_guard_var =
  2025   let
  2026     val thy = Proof_Context.theory_of ctxt
  2027     val level = level_of_type_enc type_enc
  2028     val do_term = atp_term_of_iterm ctxt mono type_enc
  2029     fun do_out_of_bound_type pos phi universal (name, T) =
  2030       if should_guard_type ctxt mono type_enc
  2031              (fn () => should_guard_var thy level pos phi universal name) T then
  2032         IVar (name, T)
  2033         |> type_guard_iterm type_enc T
  2034         |> do_term pos |> AAtom |> SOME
  2035       else if should_generate_tag_bound_decl ctxt mono type_enc universal T then
  2036         let
  2037           val var = ATerm ((name, []), [])
  2038           val tagged_var = tag_with_type ctxt mono type_enc pos T var
  2039         in SOME (AAtom (ATerm ((`I tptp_equal, []), [tagged_var, var]))) end
  2040       else
  2041         NONE
  2042     fun do_formula pos (ATyQuant (q, xs, phi)) =
  2043         ATyQuant (q, map (apfst (native_atp_type_of_typ type_enc false 0)) xs, do_formula pos phi)
  2044       | do_formula pos (AQuant (q, xs, phi)) =
  2045         let
  2046           val phi = phi |> do_formula pos
  2047           val universal = Option.map (q = AExists ? not) pos
  2048           val do_bound_type = do_bound_type ctxt mono type_enc
  2049         in
  2050           AQuant (q, xs |> map (apsnd (fn NONE => NONE
  2051                                         | SOME T => do_bound_type T)),
  2052                   (if q = AForall then mk_ahorn else fold_rev (mk_aconn AAnd))
  2053                       (map_filter
  2054                            (fn (_, NONE) => NONE
  2055                              | (s, SOME T) =>
  2056                                do_out_of_bound_type pos phi universal (s, T))
  2057                            xs)
  2058                       phi)
  2059         end
  2060       | do_formula pos (AConn conn) = aconn_map pos do_formula conn
  2061       | do_formula pos (AAtom tm) = AAtom (do_term pos tm)
  2062   in do_formula end
  2063 
  2064 fun string_of_status General = ""
  2065   | string_of_status Induction = inductionN
  2066   | string_of_status Intro = introN
  2067   | string_of_status Inductive = inductiveN
  2068   | string_of_status Elim = elimN
  2069   | string_of_status Simp = simpN
  2070   | string_of_status Non_Rec_Def = non_rec_defN
  2071   | string_of_status Rec_Def = rec_defN
  2072 
  2073 (* Each fact is given a unique fact number to avoid name clashes (e.g., because
  2074    of monomorphization). The TPTP forbids name clashes, and some of the remote
  2075    provers might care. *)
  2076 fun line_of_fact ctxt prefix encode alt freshen pos mono type_enc rank
  2077         (j, {name, stature = (_, status), role, iformula, atomic_types}) =
  2078   Formula ((prefix ^ (if freshen then string_of_int j ^ "_" else "") ^
  2079             encode name, alt name),
  2080            role,
  2081            iformula
  2082            |> formula_of_iformula ctxt mono type_enc
  2083                   should_guard_var_in_formula (if pos then SOME true else NONE)
  2084            |> close_formula_universally
  2085            |> bound_tvars type_enc true atomic_types,
  2086            NONE, isabelle_info (string_of_status status) (rank j))
  2087 
  2088 fun lines_of_subclass type_enc sub super =
  2089   Formula ((subclass_prefix ^ ascii_of sub ^ "___" ^ ascii_of super, ""), Axiom,
  2090            AConn (AImplies,
  2091                   [sub, super] |> map (fn s => class_atom type_enc (s, tvar_a)))
  2092            |> bound_tvars type_enc false [tvar_a],
  2093            NONE, isabelle_info inductiveN helper_rank)
  2094 
  2095 fun lines_of_subclass_pair type_enc (sub, supers) =
  2096   if polymorphism_of_type_enc type_enc = Type_Class_Polymorphic then
  2097     [Class_Decl (class_decl_prefix ^ ascii_of sub, `make_class sub,
  2098                  map (`make_class) supers)]
  2099   else
  2100     map (lines_of_subclass type_enc sub) supers
  2101 
  2102 fun line_of_tcon_clause type_enc (name, prems, (cl, T)) =
  2103   if polymorphism_of_type_enc type_enc = Type_Class_Polymorphic then
  2104     Class_Memb (class_memb_prefix ^ name,
  2105       map (fn (cls, T) => (T |> dest_TVar |> tvar_name, map (`make_class) cls)) prems,
  2106       native_atp_type_of_typ type_enc false 0 T, `make_class cl)
  2107   else
  2108     Formula ((tcon_clause_prefix ^ name, ""), Axiom,
  2109              mk_ahorn (maps (class_atoms type_enc) prems)
  2110                       (class_atom type_enc (cl, T))
  2111              |> bound_tvars type_enc true (snd (dest_Type T)),
  2112              NONE, isabelle_info inductiveN helper_rank)
  2113 
  2114 fun line_of_conjecture ctxt mono type_enc
  2115                        ({name, role, iformula, atomic_types, ...} : ifact) =
  2116   Formula ((conjecture_prefix ^ name, ""), role,
  2117            iformula
  2118            |> formula_of_iformula ctxt mono type_enc
  2119                   should_guard_var_in_formula (SOME false)
  2120            |> close_formula_universally
  2121            |> bound_tvars type_enc true atomic_types, NONE, [])
  2122 
  2123 fun lines_of_free_types type_enc (facts : ifact list) =
  2124   if is_type_enc_polymorphic type_enc then
  2125     let
  2126       val type_classes = (polymorphism_of_type_enc type_enc = Type_Class_Polymorphic)
  2127       fun line j (cl, T) =
  2128         if type_classes then
  2129           Class_Memb (class_memb_prefix ^ string_of_int j, [],
  2130             native_atp_type_of_typ type_enc false 0 T, `make_class cl)
  2131         else
  2132           Formula ((tfree_clause_prefix ^ string_of_int j, ""), Hypothesis,
  2133             class_atom type_enc (cl, T), NONE, [])
  2134       val membs =
  2135         fold (union (op =)) (map #atomic_types facts) []
  2136         |> class_membs_of_types type_enc add_sorts_on_tfree
  2137     in
  2138       map2 line (0 upto length membs - 1) membs
  2139     end
  2140   else
  2141     []
  2142 
  2143 (** Symbol declarations **)
  2144 
  2145 fun decl_line_of_class phantoms s =
  2146   let val name as (s, _) = `make_class s in
  2147     Sym_Decl (sym_decl_prefix ^ s, name,
  2148               APi ([tvar_a_name],
  2149                    if phantoms = Without_Phantom_Type_Vars then
  2150                      AFun (a_itself_atype, bool_atype)
  2151                    else
  2152                      bool_atype))
  2153   end
  2154 
  2155 fun decl_lines_of_classes type_enc =
  2156   (case type_enc of
  2157     Native (_, Raw_Polymorphic phantoms, _) => map (decl_line_of_class phantoms)
  2158   | _ => K [])
  2159 
  2160 fun sym_decl_table_of_facts thy type_enc sym_tab (conjs, facts, extra_tms) =
  2161   let
  2162     fun add_iterm_syms tm =
  2163       let val (head, args) = strip_iterm_comb tm in
  2164         (case head of
  2165           IConst ((s, s'), T, T_args) =>
  2166           let
  2167             val (pred_sym, in_conj) =
  2168               (case Symtab.lookup sym_tab s of
  2169                 SOME ({pred_sym, in_conj, ...} : sym_info) => (pred_sym, in_conj)
  2170               | NONE => (false, false))
  2171             val decl_sym =
  2172               (case type_enc of Guards _ => not pred_sym | _ => true) andalso is_tptp_user_symbol s
  2173           in
  2174             if decl_sym then
  2175               Symtab.map_default (s, [])
  2176                 (insert_type thy #3 (s', T_args, T, pred_sym, length args, in_conj))
  2177             else
  2178               I
  2179           end
  2180         | IAbs (_, tm) => add_iterm_syms tm
  2181         | _ => I)
  2182         #> fold add_iterm_syms args
  2183       end
  2184     val add_fact_syms = ifact_lift (formula_fold NONE (K add_iterm_syms))
  2185     fun add_formula_var_types (ATyQuant (_, _, phi)) = add_formula_var_types phi
  2186       | add_formula_var_types (AQuant (_, xs, phi)) =
  2187         fold (fn (_, SOME T) => insert_type thy I T | _ => I) xs
  2188         #> add_formula_var_types phi
  2189       | add_formula_var_types (AConn (_, phis)) =
  2190         fold add_formula_var_types phis
  2191       | add_formula_var_types _ = I
  2192     fun var_types () =
  2193       if is_type_enc_polymorphic type_enc then [tvar_a]
  2194       else fold (ifact_lift add_formula_var_types) (conjs @ facts) []
  2195     fun add_undefined_const T =
  2196       let
  2197         (* FIXME: make sure type arguments are filtered / clean up code *)
  2198         val (s, s') =
  2199           `(make_fixed_const NONE) @{const_name undefined}
  2200           |> (is_type_enc_mangling type_enc ? mangled_const_name type_enc [T])
  2201       in
  2202         Symtab.map_default (s, [])
  2203                            (insert_type thy #3 (s', [T], T, false, 0, false))
  2204       end
  2205     fun add_TYPE_const () =
  2206       let val (s, s') = TYPE_name in
  2207         Symtab.map_default (s, [])
  2208             (insert_type thy #3
  2209                          (s', [tvar_a], @{typ "'a itself"}, false, 0, false))
  2210       end
  2211   in
  2212     Symtab.empty
  2213     |> is_type_enc_sound type_enc
  2214        ? (fold (fold add_fact_syms) [conjs, facts]
  2215           #> fold add_iterm_syms extra_tms
  2216           #> (case type_enc of
  2217                 Native (First_Order, Raw_Polymorphic phantoms, _) =>
  2218                 phantoms = Without_Phantom_Type_Vars ? add_TYPE_const ()
  2219               | Native _ => I
  2220               | _ => fold add_undefined_const (var_types ())))
  2221   end
  2222 
  2223 (* We add "bool" in case the helper "True_or_False" is included later. *)
  2224 fun default_mono level completish =
  2225   {maybe_finite_Ts = [@{typ bool}],
  2226    surely_infinite_Ts = (case level of Nonmono_Types (Strict, _) => [] | _ => known_infinite_types),
  2227    maybe_nonmono_Ts = [if completish then tvar_a else @{typ bool}]}
  2228 
  2229 (* This inference is described in section 4 of Blanchette et al., "Encoding
  2230    monomorphic and polymorphic types", TACAS 2013. *)
  2231 fun add_iterm_mononotonicity_info _ _ (SOME false) _ mono = mono
  2232   | add_iterm_mononotonicity_info ctxt level _
  2233         (IApp (IApp (IConst ((s, _), Type (_, [T, _]), _), tm1), tm2))
  2234         (mono as {maybe_finite_Ts, surely_infinite_Ts, maybe_nonmono_Ts}) =
  2235     let val thy = Proof_Context.theory_of ctxt in
  2236       if is_tptp_equal s andalso exists is_maybe_universal_var [tm1, tm2] then
  2237         (case level of
  2238           Nonmono_Types (strictness, _) =>
  2239           if exists (type_instance thy T) surely_infinite_Ts orelse
  2240              member (type_equiv thy) maybe_finite_Ts T then
  2241             mono
  2242           else if is_type_kind_of_surely_infinite ctxt strictness
  2243                                                   surely_infinite_Ts T then
  2244             {maybe_finite_Ts = maybe_finite_Ts,
  2245              surely_infinite_Ts = surely_infinite_Ts |> insert_type thy I T,
  2246              maybe_nonmono_Ts = maybe_nonmono_Ts}
  2247           else
  2248             {maybe_finite_Ts = maybe_finite_Ts |> insert (type_equiv thy) T,
  2249              surely_infinite_Ts = surely_infinite_Ts,
  2250              maybe_nonmono_Ts = maybe_nonmono_Ts |> insert_type thy I T}
  2251         | _ => mono)
  2252       else
  2253         mono
  2254     end
  2255   | add_iterm_mononotonicity_info _ _ _ _ mono = mono
  2256 fun add_fact_mononotonicity_info ctxt level ({role, iformula, ...} : ifact) =
  2257   formula_fold (SOME (role <> Conjecture))
  2258                (add_iterm_mononotonicity_info ctxt level) iformula
  2259 fun mononotonicity_info_of_facts ctxt type_enc completish facts =
  2260   let val level = level_of_type_enc type_enc in
  2261     default_mono level completish
  2262     |> is_type_level_monotonicity_based level
  2263        ? fold (add_fact_mononotonicity_info ctxt level) facts
  2264   end
  2265 
  2266 fun fold_arg_types f (IApp (tm1, tm2)) =
  2267     fold_arg_types f tm1 #> fold_term_types f tm2
  2268   | fold_arg_types _ _ = I
  2269 and fold_term_types f tm = f (ityp_of tm) #> fold_arg_types f tm
  2270 
  2271 fun add_iformula_monotonic_types ctxt mono type_enc =
  2272   let
  2273     val thy = Proof_Context.theory_of ctxt
  2274     val level = level_of_type_enc type_enc
  2275     val should_encode = should_encode_type ctxt mono level
  2276     fun add_type T = not (should_encode T) ? insert_type thy I T
  2277   in formula_fold NONE (K (fold_term_types add_type)) end
  2278 
  2279 fun add_fact_monotonic_types ctxt mono type_enc =
  2280   ifact_lift (add_iformula_monotonic_types ctxt mono type_enc)
  2281 
  2282 fun monotonic_types_of_facts ctxt mono type_enc facts =
  2283   let val level = level_of_type_enc type_enc in
  2284     [] |> (is_type_enc_polymorphic type_enc andalso
  2285            is_type_level_monotonicity_based level)
  2286           ? fold (add_fact_monotonic_types ctxt mono type_enc) facts
  2287   end
  2288 
  2289 fun line_of_guards_mono_type ctxt mono type_enc T =
  2290   Formula ((guards_sym_formula_prefix ^ ascii_of (mangled_type type_enc T), ""),
  2291            Axiom,
  2292            IConst (`make_bound_var "X", T, [])
  2293            |> type_guard_iterm type_enc T
  2294            |> AAtom
  2295            |> formula_of_iformula ctxt mono type_enc always_guard_var_in_formula
  2296                                   (SOME true)
  2297            |> close_formula_universally
  2298            |> bound_tvars type_enc true (atomic_types_of T),
  2299            NONE, isabelle_info inductiveN helper_rank)
  2300 
  2301 fun line_of_tags_mono_type ctxt mono type_enc T =
  2302   let val x_var = ATerm ((`make_bound_var "X", []), []) in
  2303     Formula ((tags_sym_formula_prefix ^ ascii_of (mangled_type type_enc T), ""), Axiom,
  2304              eq_formula type_enc (atomic_types_of T) [] false
  2305                   (tag_with_type ctxt mono type_enc NONE T x_var) x_var,
  2306              NONE, isabelle_info non_rec_defN helper_rank)
  2307   end
  2308 
  2309 fun lines_of_mono_types ctxt mono type_enc =
  2310   (case type_enc of
  2311     Native _ => K []
  2312   | Guards _ => map (line_of_guards_mono_type ctxt mono type_enc)
  2313   | Tags _ => map (line_of_tags_mono_type ctxt mono type_enc))
  2314 
  2315 fun decl_line_of_sym ctxt mono type_enc s (s', T_args, T, pred_sym, ary, _) =
  2316   let
  2317     val thy = Proof_Context.theory_of ctxt
  2318     val (T, T_args) =
  2319       if null T_args then
  2320         (T, [])
  2321       else
  2322         (case unprefix_and_unascii const_prefix s of
  2323           SOME s' =>
  2324           let
  2325             val s' = s' |> unmangled_invert_const
  2326             val T = s' |> robust_const_type thy
  2327           in (T, robust_const_type_args thy (s', T)) end
  2328         | NONE => raise Fail "unexpected type arguments")
  2329   in
  2330     Sym_Decl (sym_decl_prefix ^ s, (s, s'),
  2331               T |> fused_type ctxt mono (level_of_type_enc type_enc) ary
  2332                 |> native_atp_type_of_typ type_enc pred_sym ary
  2333                 |> not (null T_args)
  2334                    ? curry APi (map (tvar_name o dest_TVar) T_args))
  2335   end
  2336 
  2337 fun honor_conj_sym_role in_conj = (if in_conj then Hypothesis else Axiom, I)
  2338 
  2339 fun line_of_guards_sym_decl ctxt mono type_enc n s j
  2340                             (s', T_args, T, _, ary, in_conj) =
  2341   let
  2342     val thy = Proof_Context.theory_of ctxt
  2343     val (role, maybe_negate) = honor_conj_sym_role in_conj
  2344     val (arg_Ts, res_T) = chop_fun ary T
  2345     val bound_names = 1 upto ary |> map (`I o make_bound_var o string_of_int)
  2346     val bounds =
  2347       bound_names ~~ arg_Ts |> map (fn (name, T) => IConst (name, T, []))
  2348     val bound_Ts =
  2349       (case level_of_type_enc type_enc of
  2350         All_Types => if null T_args then replicate ary NONE else map SOME arg_Ts
  2351       | Undercover_Types =>
  2352         let val cover = type_arg_cover thy NONE s ary in
  2353           map2 (fn j => if member (op =) cover j then SOME else K NONE) (0 upto ary - 1) arg_Ts
  2354         end
  2355       | _ => replicate ary NONE)
  2356   in
  2357     Formula ((guards_sym_formula_prefix ^ s ^
  2358               (if n > 1 then "_" ^ string_of_int j else ""), ""),
  2359              role,
  2360              IConst ((s, s'), T, T_args)
  2361              |> fold (curry (IApp o swap)) bounds
  2362              |> type_guard_iterm type_enc res_T
  2363              |> AAtom |> mk_aquant AForall (bound_names ~~ bound_Ts)
  2364              |> formula_of_iformula ctxt mono type_enc
  2365                                     always_guard_var_in_formula (SOME true)
  2366              |> close_formula_universally
  2367              |> bound_tvars type_enc (n > 1) (atomic_types_of T)
  2368              |> maybe_negate,
  2369              NONE, isabelle_info inductiveN helper_rank)
  2370   end
  2371 
  2372 fun lines_of_tags_sym_decl ctxt mono type_enc n s
  2373                            (j, (s', T_args, T, pred_sym, ary, in_conj)) =
  2374   let
  2375     val thy = Proof_Context.theory_of ctxt
  2376     val level = level_of_type_enc type_enc
  2377     val ident =
  2378       tags_sym_formula_prefix ^ s ^
  2379       (if n > 1 then "_" ^ string_of_int j else "")
  2380     val (role, maybe_negate) = honor_conj_sym_role in_conj
  2381     val (arg_Ts, res_T) = chop_fun ary T
  2382     val bound_names = 1 upto ary |> map (`I o make_bound_var o string_of_int)
  2383     val bounds = bound_names |> map (fn name => ATerm ((name, []), []))
  2384     val cst = mk_aterm type_enc (s, s') T_args
  2385     val eq = maybe_negate oo eq_formula type_enc (atomic_types_of T) [] pred_sym
  2386     val tag_with = tag_with_type ctxt mono type_enc NONE
  2387     fun formula c =
  2388       [Formula ((ident, ""), role, eq (tag_with res_T c) c, NONE,
  2389                 isabelle_info non_rec_defN helper_rank)]
  2390   in
  2391     if pred_sym orelse not (should_encode_type ctxt mono level res_T) then
  2392       []
  2393     else if level = Undercover_Types then
  2394       let
  2395         val cover = type_arg_cover thy NONE s ary
  2396         fun maybe_tag (j, arg_T) = member (op =) cover j ? tag_with arg_T
  2397         val bounds = bounds |> map2 maybe_tag (0 upto ary - 1 ~~ arg_Ts)
  2398       in formula (cst bounds) end
  2399     else
  2400       formula (cst bounds)
  2401   end
  2402 
  2403 fun result_type_of_decl (_, _, T, _, ary, _) = chop_fun ary T |> snd
  2404 
  2405 fun rationalize_decls thy (decls as decl :: (decls' as _ :: _)) =
  2406     let
  2407       val T = result_type_of_decl decl |> map_type_tvar (fn (z, _) => TVar (z, @{sort type}))
  2408     in
  2409       if forall (type_generalization thy T o result_type_of_decl) decls' then [decl]
  2410       else decls
  2411     end
  2412   | rationalize_decls _ decls = decls
  2413 
  2414 fun lines_of_sym_decls ctxt mono type_enc (s, decls) =
  2415   (case type_enc of
  2416     Native _ => [decl_line_of_sym ctxt mono type_enc s (hd decls)]
  2417   | Guards (_, level) =>
  2418     let
  2419       val thy = Proof_Context.theory_of ctxt
  2420       val decls = decls |> rationalize_decls thy
  2421       val n = length decls
  2422       val decls = decls |> filter (should_encode_type ctxt mono level o result_type_of_decl)
  2423     in
  2424       (0 upto length decls - 1, decls) |-> map2 (line_of_guards_sym_decl ctxt mono type_enc n s)
  2425     end
  2426   | Tags (_, level) =>
  2427     if is_type_level_uniform level then
  2428       []
  2429     else
  2430       let val n = length decls in
  2431         (0 upto n - 1 ~~ decls) |> maps (lines_of_tags_sym_decl ctxt mono type_enc n s)
  2432       end)
  2433 
  2434 fun lines_of_sym_decl_table ctxt mono type_enc mono_Ts sym_decl_tab =
  2435   let
  2436     val syms = sym_decl_tab |> Symtab.dest |> sort_wrt fst
  2437     val mono_lines = lines_of_mono_types ctxt mono type_enc mono_Ts
  2438     val decl_lines = maps (lines_of_sym_decls ctxt mono type_enc) syms
  2439   in mono_lines @ decl_lines end
  2440 
  2441 fun datatypes_of_sym_table ctxt ctrss (DFG Polymorphic) (type_enc as Native _)
  2442                            uncurried_aliases sym_tab =
  2443     if is_type_enc_polymorphic type_enc then
  2444       let
  2445         val thy = Proof_Context.theory_of ctxt
  2446         fun do_ctr (s, T) =
  2447           let
  2448             val s' = make_fixed_const (SOME type_enc) s
  2449             val ary = ary_of T
  2450             fun mk name = mk_aterm type_enc name (robust_const_type_args thy (s, T)) []
  2451           in
  2452             (case Symtab.lookup sym_tab s' of
  2453               NONE => NONE
  2454             | SOME ({min_ary, ...} : sym_info) =>
  2455               if ary = min_ary then SOME (mk (s', s))
  2456               else if uncurried_aliases then SOME (mk (aliased_uncurried ary (s', s)))
  2457               else NONE)
  2458           end
  2459         fun datatype_of_ctrs (ctrs as (_, T1) :: _) =
  2460           let val ctrs' = map do_ctr ctrs in
  2461             if forall is_some ctrs' then
  2462               SOME (native_atp_type_of_typ type_enc false 0 (body_type T1), map_filter I ctrs')
  2463             else
  2464               NONE
  2465           end
  2466       in
  2467         map_filter datatype_of_ctrs ctrss
  2468       end
  2469     else
  2470       []
  2471   | datatypes_of_sym_table _ _ _ _ _ _ = []
  2472 
  2473 fun decl_line_of_datatype (ty as AType (((_, s'), _), ty_args), ctrs) =
  2474   let val xs = map (fn AType ((name, _), []) => name) ty_args in
  2475     Datatype_Decl (datatype_decl_prefix ^ ascii_of s', map (rpair []) xs, ty, ctrs)
  2476   end
  2477 
  2478 fun pair_append (xs1, xs2) (ys1, ys2) = (xs1 @ ys1, xs2 @ ys2)
  2479 
  2480 fun do_uncurried_alias_lines_of_sym ctxt ctrss mono type_enc sym_tab0 sym_tab
  2481                                     base_s0 types in_conj =
  2482   let
  2483     fun do_alias ary =
  2484       let
  2485         val thy = Proof_Context.theory_of ctxt
  2486         val (role, maybe_negate) = honor_conj_sym_role in_conj
  2487         val base_name = base_s0 |> `(make_fixed_const (SOME type_enc))
  2488         val T = (case types of [T] => T | _ => robust_const_type thy base_s0)
  2489         val T_args = robust_const_type_args thy (base_s0, T)
  2490         val (base_name as (base_s, _), T_args) =
  2491           mangle_type_args_in_const type_enc base_name T_args
  2492         val base_ary = min_ary_of sym_tab0 base_s
  2493         fun do_const name = IConst (name, T, T_args)
  2494         val filter_ty_args = filter_type_args_in_iterm thy ctrss type_enc
  2495         val atp_term_of = atp_term_of_iterm ctxt mono type_enc (SOME true)
  2496         val name1 as (s1, _) =
  2497           base_name |> ary - 1 > base_ary ? aliased_uncurried (ary - 1)
  2498         val name2 as (s2, _) = base_name |> aliased_uncurried ary
  2499         val (arg_Ts, _) = chop_fun ary T
  2500         val bound_names =
  2501           1 upto ary |> map (`I o make_bound_var o string_of_int)
  2502         val bounds = bound_names ~~ arg_Ts
  2503         val (first_bounds, last_bound) =
  2504           bounds |> map (fn (name, T) => IConst (name, T, [])) |> split_last
  2505         val tm1 =
  2506           mk_app_op type_enc (list_app (do_const name1) first_bounds) last_bound
  2507           |> filter_ty_args
  2508         val tm2 =
  2509           list_app (do_const name2) (first_bounds @ [last_bound])
  2510           |> filter_ty_args
  2511         val do_bound_type = do_bound_type ctxt mono type_enc
  2512         val eq =
  2513           eq_formula type_enc (atomic_types_of T) (map (apsnd do_bound_type) bounds) false
  2514             (atp_term_of tm1) (atp_term_of tm2)
  2515       in
  2516         ([tm1, tm2],
  2517          [Formula ((uncurried_alias_eq_prefix ^ s2, ""), role, eq |> maybe_negate, NONE,
  2518             isabelle_info non_rec_defN helper_rank)])
  2519         |> (if ary - 1 = base_ary orelse Symtab.defined sym_tab s1 then I
  2520             else pair_append (do_alias (ary - 1)))
  2521       end
  2522   in do_alias end
  2523 
  2524 fun uncurried_alias_lines_of_sym ctxt ctrss mono type_enc sym_tab0 sym_tab
  2525         (s, {min_ary, types, in_conj, ...} : sym_info) =
  2526   (case unprefix_and_unascii const_prefix s of
  2527     SOME mangled_s =>
  2528     if String.isSubstring uncurried_alias_sep mangled_s then
  2529       let val base_s0 = mangled_s |> unmangled_invert_const in
  2530         do_uncurried_alias_lines_of_sym ctxt ctrss mono type_enc sym_tab0 sym_tab base_s0 types
  2531           in_conj min_ary
  2532       end
  2533     else
  2534       ([], [])
  2535   | NONE => ([], []))
  2536 
  2537 fun uncurried_alias_lines_of_sym_table ctxt ctrss mono type_enc uncurried_aliases sym_tab0 sym_tab =
  2538   ([], [])
  2539   |> uncurried_aliases
  2540     ? Symtab.fold_rev
  2541         (pair_append o uncurried_alias_lines_of_sym ctxt ctrss mono type_enc sym_tab0 sym_tab)
  2542         sym_tab
  2543 
  2544 val implicit_declsN = "Could-be-implicit typings"
  2545 val explicit_declsN = "Explicit typings"
  2546 val uncurried_alias_eqsN = "Uncurried aliases"
  2547 val factsN = "Relevant facts"
  2548 val subclassesN = "Subclasses"
  2549 val tconsN = "Type constructors"
  2550 val helpersN = "Helper facts"
  2551 val conjsN = "Conjectures"
  2552 val free_typesN = "Free types"
  2553 
  2554 (* TFF allows implicit declarations of types, function symbols, and predicate
  2555    symbols (with "$i" as the type of individuals), but some provers (e.g.,
  2556    SNARK) require explicit declarations. The situation is similar for THF. *)
  2557 
  2558 fun default_type pred_sym =
  2559   let
  2560     fun typ 0 0 = if pred_sym then bool_atype else individual_atype
  2561       | typ 0 tm_ary = AFun (individual_atype, typ 0 (tm_ary - 1))
  2562       | typ ty_ary tm_ary = APi (replicate ty_ary tvar_a_name, typ 0 tm_ary)
  2563   in typ end
  2564 
  2565 fun undeclared_in_problem problem =
  2566   let
  2567     fun do_sym (name as (s, _)) value =
  2568       if is_tptp_user_symbol s then Symtab.default (s, (name, value)) else I
  2569     fun do_class name = apfst (apfst (do_sym name ()))
  2570     val do_bound_tvars = fold do_class o snd
  2571     fun do_type (AType ((name, _), tys)) =
  2572         apfst (apsnd (do_sym name (length tys))) #> fold do_type tys
  2573       | do_type (AFun (ty1, ty2)) = do_type ty1 #> do_type ty2
  2574       | do_type (APi (_, ty)) = do_type ty
  2575     fun do_term pred_sym (ATerm ((name, tys), tms)) =
  2576         apsnd (do_sym name (fn _ => default_type pred_sym (length tys) (length tms)))
  2577         #> fold do_type tys #> fold (do_term false) tms
  2578       | do_term _ (AAbs (((_, ty), tm), args)) =
  2579         do_type ty #> do_term false tm #> fold (do_term false) args
  2580     fun do_formula (ATyQuant (_, xs, phi)) =
  2581         fold (do_type o fst) xs #> fold (fold do_class o snd) xs #> do_formula phi
  2582       | do_formula (AQuant (_, xs, phi)) = fold do_type (map_filter snd xs) #> do_formula phi
  2583       | do_formula (AConn (_, phis)) = fold do_formula phis
  2584       | do_formula (AAtom tm) = do_term true tm
  2585     fun do_line (Class_Decl (_, _, cls)) = fold do_class cls
  2586       | do_line (Type_Decl _) = I
  2587       | do_line (Sym_Decl (_, _, ty)) = do_type ty
  2588       | do_line (Datatype_Decl (_, xs, ty, tms)) =
  2589         fold do_bound_tvars xs #> do_type ty #> fold (do_term false) tms
  2590       | do_line (Class_Memb (_, xs, ty, cl)) = fold do_bound_tvars xs #> do_type ty #> do_class cl
  2591       | do_line (Formula (_, _, phi, _, _)) = do_formula phi
  2592     val ((cls, tys), syms) = declared_in_atp_problem problem
  2593   in
  2594     ((Symtab.empty, Symtab.empty), Symtab.empty)
  2595     |>> apfst (fold (fn (s, _) => Symtab.default (s, (("", ""), ()))) cls)
  2596     |>> apsnd (fold (fn (s, _) => Symtab.default (s, (("", ""), 0))) tys)
  2597     ||> fold (fn (s, _) => Symtab.default (s, (("", ""), K tvar_a_atype))) syms
  2598     |> fold (fold do_line o snd) problem
  2599   end
  2600 
  2601 fun declare_undeclared_in_problem heading problem =
  2602   let
  2603     val ((cls, tys), syms) = undeclared_in_problem problem
  2604     val decls =
  2605       Symtab.fold (fn (_, (("", ""), _)) => I (* already declared *)
  2606                     | (s, (cls, ())) => cons (Class_Decl (class_decl_prefix ^ s, cls, []))) cls [] @
  2607       Symtab.fold (fn (_, (("", ""), _)) => I (* already declared *)
  2608                     | (s, (ty, ary)) => cons (Type_Decl (type_decl_prefix ^ s, ty, ary))) tys [] @
  2609       Symtab.fold (fn (_, (("", ""), _)) => I (* already declared *)
  2610                     | (s, (sym, ty)) => cons (Sym_Decl (sym_decl_prefix ^ s, sym, ty ()))) syms []
  2611   in (heading, decls) :: problem end
  2612 
  2613 fun all_ctrss_of_datatypes ctxt =
  2614   map (map_filter (try dest_Const) o #ctrs) (Ctr_Sugar.ctr_sugars_of ctxt)
  2615 
  2616 val app_op_and_predicator_threshold = 45
  2617 
  2618 fun prepare_atp_problem ctxt format prem_role type_enc mode lam_trans uncurried_aliases
  2619     readable_names presimp hyp_ts concl_t facts =
  2620   let
  2621     val thy = Proof_Context.theory_of ctxt
  2622     val type_enc = type_enc |> adjust_type_enc format
  2623     val completish = (mode = Sledgehammer_Completish)
  2624     (* Forcing explicit applications is expensive for polymorphic encodings,
  2625        because it takes only one existential variable ranging over "'a => 'b" to
  2626        ruin everything. Hence we do it only if there are few facts (which is
  2627        normally the case for "metis" and the minimizer). *)
  2628     val app_op_level =
  2629       if completish then
  2630         Full_App_Op_And_Predicator
  2631       else if length facts + length hyp_ts >= app_op_and_predicator_threshold then
  2632         if is_type_enc_polymorphic type_enc then Min_App_Op else Sufficient_App_Op
  2633       else
  2634         Sufficient_App_Op_And_Predicator
  2635     val lam_trans =
  2636       if lam_trans = keep_lamsN andalso not (is_type_enc_higher_order type_enc) then liftingN
  2637       else lam_trans
  2638     val (fact_names, classes, conjs, facts, subclass_pairs, tcon_clauses, lifted) =
  2639       translate_formulas ctxt prem_role format type_enc lam_trans presimp hyp_ts concl_t facts
  2640     val (_, sym_tab0) = sym_table_of_facts ctxt type_enc app_op_level conjs facts
  2641     val mono = conjs @ facts |> mononotonicity_info_of_facts ctxt type_enc completish
  2642     val ctrss = all_ctrss_of_datatypes ctxt
  2643     fun firstorderize in_helper =
  2644       firstorderize_fact thy ctrss type_enc (uncurried_aliases andalso not in_helper) completish
  2645         sym_tab0
  2646     val (conjs, facts) = (conjs, facts) |> pairself (map (firstorderize false))
  2647     val (ho_stuff, sym_tab) =
  2648       sym_table_of_facts ctxt type_enc Min_App_Op conjs facts
  2649     val (uncurried_alias_eq_tms, uncurried_alias_eq_lines) =
  2650       uncurried_alias_lines_of_sym_table ctxt ctrss mono type_enc uncurried_aliases sym_tab0 sym_tab
  2651     val (_, sym_tab) =
  2652       (ho_stuff, sym_tab)
  2653       |> fold (add_iterm_syms_to_sym_table ctxt Min_App_Op false false)
  2654               uncurried_alias_eq_tms
  2655     val helpers =
  2656       sym_tab |> helper_facts_of_sym_table ctxt format type_enc completish
  2657               |> map (firstorderize true)
  2658     val all_facts = helpers @ conjs @ facts
  2659     val mono_Ts = monotonic_types_of_facts ctxt mono type_enc all_facts
  2660     val datatypes = datatypes_of_sym_table ctxt ctrss format type_enc uncurried_aliases sym_tab
  2661     val class_decl_lines = decl_lines_of_classes type_enc classes
  2662     val sym_decl_lines =
  2663       (conjs, helpers @ facts, uncurried_alias_eq_tms)
  2664       |> sym_decl_table_of_facts thy type_enc sym_tab
  2665       |> lines_of_sym_decl_table ctxt mono type_enc mono_Ts
  2666     val datatype_decl_lines = map decl_line_of_datatype datatypes
  2667     val decl_lines = class_decl_lines @ sym_decl_lines @ datatype_decl_lines
  2668     val num_facts = length facts
  2669     val freshen = mode <> Exporter andalso mode <> Translator
  2670     val pos = mode <> Exporter
  2671     val rank_of = rank_of_fact_num num_facts
  2672     val fact_lines =
  2673       map (line_of_fact ctxt fact_prefix ascii_of I freshen pos mono type_enc rank_of)
  2674         (0 upto num_facts - 1 ~~ facts)
  2675     val subclass_lines = maps (lines_of_subclass_pair type_enc) subclass_pairs
  2676     val tcon_lines = map (line_of_tcon_clause type_enc) tcon_clauses
  2677     val helper_lines =
  2678       0 upto length helpers - 1 ~~ helpers
  2679       |> map (line_of_fact ctxt helper_prefix I (K "") false true mono type_enc (K default_rank))
  2680     val free_type_lines = lines_of_free_types type_enc (facts @ conjs)
  2681     val conj_lines = map (line_of_conjecture ctxt mono type_enc) conjs
  2682     (* Reordering these might confuse the proof reconstruction code. *)
  2683     val problem =
  2684       [(explicit_declsN, decl_lines),
  2685        (uncurried_alias_eqsN, uncurried_alias_eq_lines),
  2686        (factsN, fact_lines),
  2687        (subclassesN, subclass_lines),
  2688        (tconsN, tcon_lines),
  2689        (helpersN, helper_lines),
  2690        (free_typesN, free_type_lines),
  2691        (conjsN, conj_lines)]
  2692     val problem =
  2693       problem
  2694       |> (case format of
  2695            CNF => ensure_cnf_problem
  2696          | CNF_UEQ => filter_cnf_ueq_problem
  2697          | FOF => I
  2698          | _ => declare_undeclared_in_problem implicit_declsN)
  2699     val (problem, pool) = problem |> nice_atp_problem readable_names format
  2700     fun add_sym_ary (s, {min_ary, ...} : sym_info) = min_ary > 0 ? Symtab.insert (op =) (s, min_ary)
  2701   in
  2702     (problem, pool |> Option.map snd |> the_default Symtab.empty, fact_names |> Vector.fromList,
  2703      lifted, Symtab.empty |> Symtab.fold add_sym_ary sym_tab)
  2704   end
  2705 
  2706 (* FUDGE *)
  2707 val conj_weight = 0.0
  2708 val hyp_weight = 0.1
  2709 val fact_min_weight = 0.2
  2710 val fact_max_weight = 1.0
  2711 val type_info_default_weight = 0.8
  2712 
  2713 (* Weights are from 0.0 (most important) to 1.0 (least important). *)
  2714 fun atp_problem_selection_weights problem =
  2715   let
  2716     fun add_term_weights weight (ATerm ((s, _), tms)) =
  2717         is_tptp_user_symbol s ? Symtab.default (s, weight) #> fold (add_term_weights weight) tms
  2718       | add_term_weights weight (AAbs ((_, tm), args)) =
  2719         add_term_weights weight tm #> fold (add_term_weights weight) args
  2720     fun add_line_weights weight (Formula (_, _, phi, _, _)) =
  2721         formula_fold NONE (K (add_term_weights weight)) phi
  2722       | add_line_weights _ _ = I
  2723     fun add_conjectures_weights [] = I
  2724       | add_conjectures_weights conjs =
  2725         let val (hyps, conj) = split_last conjs in
  2726           add_line_weights conj_weight conj
  2727           #> fold (add_line_weights hyp_weight) hyps
  2728         end
  2729     fun add_facts_weights facts =
  2730       let
  2731         val num_facts = length facts
  2732         fun weight_of j =
  2733           fact_min_weight + (fact_max_weight - fact_min_weight) * Real.fromInt j
  2734                             / Real.fromInt num_facts
  2735       in
  2736         map weight_of (0 upto num_facts - 1) ~~ facts
  2737         |> fold (uncurry add_line_weights)
  2738       end
  2739     val get = these o AList.lookup (op =) problem
  2740   in
  2741     Symtab.empty
  2742     |> add_conjectures_weights (get free_typesN @ get conjsN)
  2743     |> add_facts_weights (get factsN)
  2744     |> fold (fold (add_line_weights type_info_default_weight) o get)
  2745             [explicit_declsN, subclassesN, tconsN]
  2746     |> Symtab.dest
  2747     |> sort (prod_ord Real.compare string_ord o pairself swap)
  2748   end
  2749 
  2750 (* Ugly hack: may make innocent victims (collateral damage) *)
  2751 fun may_be_app s args = String.isPrefix app_op_name s andalso length args = 2
  2752 fun may_be_predicator s =
  2753   member (op =) [predicator_name, prefixed_predicator_name] s
  2754 
  2755 fun strip_predicator (tm as ATerm ((s, _), [tm'])) = if may_be_predicator s then tm' else tm
  2756   | strip_predicator tm = tm
  2757 
  2758 fun make_head_roll (ATerm ((s, _), tms)) =
  2759     if may_be_app s tms then make_head_roll (hd tms) ||> append (tl tms) else (s, tms)
  2760   | make_head_roll _ = ("", [])
  2761 
  2762 fun strip_up_to_predicator (ATyQuant (_, _, phi)) = strip_up_to_predicator phi
  2763   | strip_up_to_predicator (AQuant (_, _, phi)) = strip_up_to_predicator phi
  2764   | strip_up_to_predicator (AConn (_, phis)) = maps strip_up_to_predicator phis
  2765   | strip_up_to_predicator (AAtom tm) = [strip_predicator tm]
  2766 
  2767 fun strip_ahorn_etc (ATyQuant (_, _, phi)) = strip_ahorn_etc phi
  2768   | strip_ahorn_etc (AQuant (_, _, phi)) = strip_ahorn_etc phi
  2769   | strip_ahorn_etc (AConn (AImplies, [phi1, phi2])) =
  2770     strip_ahorn_etc phi2 |>> append (strip_up_to_predicator phi1)
  2771   | strip_ahorn_etc phi = ([], hd (strip_up_to_predicator phi))
  2772 
  2773 fun strip_iff_etc (ATyQuant (_, _, phi)) = strip_iff_etc phi
  2774   | strip_iff_etc (AQuant (_, _, phi)) = strip_iff_etc phi
  2775   | strip_iff_etc (AConn (AIff, [phi1, phi2])) =
  2776     pairself strip_up_to_predicator (phi1, phi2)
  2777   | strip_iff_etc _ = ([], [])
  2778 
  2779 val max_term_order_weight = 2147483647
  2780 
  2781 fun atp_problem_term_order_info problem =
  2782   let
  2783     fun add_edge s s' =
  2784       Graph.default_node (s, ())
  2785       #> Graph.default_node (s', ())
  2786       #> Graph.add_edge_acyclic (s, s')
  2787     fun add_term_deps head (ATerm ((s, _), args)) =
  2788         if is_tptp_user_symbol head then
  2789           (if is_tptp_user_symbol s then perhaps (try (add_edge s head)) else I)
  2790           #> fold (add_term_deps head) args
  2791         else
  2792           I
  2793       | add_term_deps head (AAbs ((_, tm), args)) =
  2794         add_term_deps head tm #> fold (add_term_deps head) args
  2795     fun add_intro_deps pred (Formula (_, role, phi, _, info)) =
  2796         if pred (role, info) then
  2797           let val (hyps, concl) = strip_ahorn_etc phi in
  2798             (case make_head_roll concl of
  2799               (head, args as _ :: _) => fold (add_term_deps head) (hyps @ args)
  2800             | _ => I)
  2801           end
  2802         else
  2803           I
  2804       | add_intro_deps _ _ = I
  2805     fun add_atom_eq_deps (SOME true) (ATerm ((s, _), [lhs as _, rhs])) =
  2806         if is_tptp_equal s then
  2807           (case make_head_roll lhs of
  2808             (head, args as _ :: _) => fold (add_term_deps head) (rhs :: args)
  2809           | _ => I)
  2810         else
  2811           I
  2812       | add_atom_eq_deps _ _ = I
  2813     fun add_eq_deps pred (Formula (_, role, phi, _, info)) =
  2814         if pred (role, info) then
  2815           (case strip_iff_etc phi of
  2816             ([lhs], rhs) =>
  2817             (case make_head_roll lhs of
  2818               (head, args as _ :: _) => fold (add_term_deps head) (rhs @ args)
  2819             | _ => I)
  2820           | _ => formula_fold (SOME (role <> Conjecture)) add_atom_eq_deps phi)
  2821         else
  2822           I
  2823       | add_eq_deps _ _ = I
  2824     fun has_status status (_, info) = extract_isabelle_status info = SOME status
  2825     fun is_conj (role, _) = (role = Conjecture orelse role = Hypothesis)
  2826     val graph =
  2827       Graph.empty
  2828       |> fold (fold (add_eq_deps (has_status non_rec_defN)) o snd) problem
  2829       |> fold (fold (add_eq_deps (has_status rec_defN orf has_status simpN
  2830                                   orf is_conj)) o snd) problem
  2831       |> fold (fold (add_intro_deps (has_status inductiveN)) o snd) problem
  2832       |> fold (fold (add_intro_deps (has_status introN)) o snd) problem
  2833     fun next_weight w = if w + w <= max_term_order_weight then w + w else w + 1
  2834     fun add_weights _ [] = I
  2835       | add_weights weight syms =
  2836         fold (AList.update (op =) o rpair weight) syms
  2837         #> add_weights (next_weight weight)
  2838                (fold (union (op =) o Graph.immediate_succs graph) syms [])
  2839   in
  2840     (* Sorting is not just for aesthetics: It specifies the precedence order for
  2841        the term ordering (KBO or LPO), from smaller to larger values. *)
  2842     [] |> add_weights 1 (Graph.minimals graph) |> sort (int_ord o pairself snd)
  2843   end
  2844 
  2845 end;