src/HOL/Tools/res_axioms.ML
author paulson
Thu Oct 05 10:42:39 2006 +0200 (2006-10-05)
changeset 20863 4ee61dbf192d
parent 20789 e279499c4f80
child 20867 e7b92a48e22b
permissions -rw-r--r--
improvements to abstraction, ensuring more re-use of abstraction functions
moving some functions to Pure/drule.ML
paulson@15347
     1
(*  Author: Jia Meng, Cambridge University Computer Laboratory
paulson@15347
     2
    ID: $Id$
paulson@15347
     3
    Copyright 2004 University of Cambridge
paulson@15347
     4
wenzelm@20461
     5
Transformation of axiom rules (elim/intro/etc) into CNF forms.
paulson@15347
     6
*)
paulson@15347
     7
paulson@20445
     8
(*FIXME: does this signature serve any purpose?*)
paulson@15997
     9
signature RES_AXIOMS =
paulson@15997
    10
  sig
paulson@15997
    11
  val elimRule_tac : thm -> Tactical.tactic
paulson@16012
    12
  val elimR2Fol : thm -> term
paulson@15997
    13
  val transform_elim : thm -> thm
paulson@15997
    14
  val cnf_axiom : (string * thm) -> thm list
paulson@15997
    15
  val meta_cnf_axiom : thm -> thm list
paulson@15997
    16
  val claset_rules_of_thy : theory -> (string * thm) list
paulson@15997
    17
  val simpset_rules_of_thy : theory -> (string * thm) list
paulson@17484
    18
  val claset_rules_of_ctxt: Proof.context -> (string * thm) list
paulson@17484
    19
  val simpset_rules_of_ctxt : Proof.context -> (string * thm) list
mengj@17905
    20
  val pairname : thm -> (string * thm)
paulson@18510
    21
  val skolem_thm : thm -> thm list
paulson@20419
    22
  val to_nnf : thm -> thm
mengj@19353
    23
  val cnf_rules_pairs : (string * Thm.thm) list -> (Thm.thm * (string * int)) list list;
wenzelm@18708
    24
  val meson_method_setup : theory -> theory
wenzelm@18708
    25
  val setup : theory -> theory
mengj@19196
    26
mengj@19196
    27
  val atpset_rules_of_thy : theory -> (string * thm) list
mengj@19196
    28
  val atpset_rules_of_ctxt : Proof.context -> (string * thm) list
paulson@15997
    29
  end;
wenzelm@20461
    30
paulson@20419
    31
structure ResAxioms =
wenzelm@20461
    32
paulson@15997
    33
struct
paulson@15347
    34
paulson@20419
    35
(*FIXME DELETE: For running the comparison between combinators and abstractions.
paulson@20419
    36
  CANNOT be a ref, as the setting is used while Isabelle is built.*)
paulson@20419
    37
val abstract_lambdas = true;
paulson@20419
    38
paulson@20419
    39
val trace_abs = ref false;
mengj@18000
    40
paulson@20863
    41
(*FIXME: move some of these functions to Pure/drule.ML *)
paulson@20863
    42
paulson@20863
    43
fun freeze_thm th = #1 (Drule.freeze_thaw th);
paulson@20863
    44
paulson@20863
    45
fun lhs_of th =
paulson@20863
    46
  case prop_of th of (Const("==",_) $ lhs $ _) => lhs
paulson@20863
    47
    | _ => raise THM ("lhs_of", 1, [th]);
paulson@20863
    48
paulson@20863
    49
fun rhs_of th =
paulson@20863
    50
  case prop_of th of (Const("==",_) $ _ $ rhs) => rhs
paulson@20863
    51
    | _ => raise THM ("rhs_of", 1, [th]);
paulson@20863
    52
paulson@20445
    53
(*Store definitions of abstraction functions, ensuring that identical right-hand
paulson@20445
    54
  sides are denoted by the same functions and thereby reducing the need for
paulson@20445
    55
  extensionality in proofs.
paulson@20445
    56
  FIXME!  Store in theory data!!*)
paulson@20863
    57
paulson@20863
    58
fun seed th net =
paulson@20863
    59
  let val (_,ct) = Thm.dest_abs NONE (Drule.crhs_of th)
paulson@20863
    60
  in  Net.insert_term eq_thm (term_of ct, th) net end;
paulson@20863
    61
  
paulson@20863
    62
val abstraction_cache = ref 
paulson@20863
    63
  (seed (thm"COMBI1") (seed (thm"COMBB1") (seed (thm"COMBK1") Net.empty)));
paulson@20445
    64
paulson@15997
    65
(**** Transformation of Elimination Rules into First-Order Formulas****)
paulson@15347
    66
paulson@15390
    67
(* a tactic used to prove an elim-rule. *)
paulson@16009
    68
fun elimRule_tac th =
paulson@20419
    69
    (resolve_tac [impI,notI] 1) THEN (etac th 1) THEN REPEAT(fast_tac HOL_cs 1);
paulson@15347
    70
paulson@15956
    71
fun add_EX tm [] = tm
paulson@15956
    72
  | add_EX tm ((x,xtp)::xs) = add_EX (HOLogic.exists_const xtp $ Abs(x,xtp,tm)) xs;
paulson@15347
    73
paulson@19894
    74
(*Checks for the premise ~P when the conclusion is P.*)
wenzelm@20461
    75
fun is_neg (Const("Trueprop",_) $ (Const("Not",_) $ Free(p,_)))
paulson@19894
    76
           (Const("Trueprop",_) $ Free(q,_)) = (p = q)
paulson@15371
    77
  | is_neg _ _ = false;
paulson@15371
    78
paulson@20017
    79
exception ELIMR2FOL;
paulson@20017
    80
paulson@20017
    81
(*Handles the case where the dummy "conclusion" variable appears negated in the
paulson@20017
    82
  premises, so the final consequent must be kept.*)
paulson@15371
    83
fun strip_concl' prems bvs (Const ("==>",_) $ P $ Q) =
paulson@19894
    84
      strip_concl' (HOLogic.dest_Trueprop P :: prems) bvs  Q
wenzelm@20461
    85
  | strip_concl' prems bvs P =
paulson@15956
    86
      let val P' = HOLogic.Not $ (HOLogic.dest_Trueprop P)
paulson@19894
    87
      in add_EX (foldr1 HOLogic.mk_conj (P'::prems)) bvs end;
paulson@15371
    88
paulson@20017
    89
(*Recurrsion over the minor premise of an elimination rule. Final consequent
paulson@20017
    90
  is ignored, as it is the dummy "conclusion" variable.*)
wenzelm@20461
    91
fun strip_concl prems bvs concl (Const ("all", _) $ Abs (x,xtp,body)) =
paulson@18141
    92
      strip_concl prems ((x,xtp)::bvs) concl body
paulson@15371
    93
  | strip_concl prems bvs concl (Const ("==>",_) $ P $ Q) =
paulson@18141
    94
      if (is_neg P concl) then (strip_concl' prems bvs Q)
paulson@18141
    95
      else strip_concl (HOLogic.dest_Trueprop P::prems) bvs  concl Q
wenzelm@20461
    96
  | strip_concl prems bvs concl Q =
paulson@20017
    97
      if concl aconv Q then add_EX (foldr1 HOLogic.mk_conj prems) bvs
paulson@20017
    98
      else raise ELIMR2FOL (*expected conclusion not found!*)
wenzelm@20461
    99
paulson@20017
   100
fun trans_elim (major,[],_) = HOLogic.Not $ major
paulson@20017
   101
  | trans_elim (major,minors,concl) =
paulson@20017
   102
      let val disjs = foldr1 HOLogic.mk_disj (map (strip_concl [] [] concl) minors)
paulson@20017
   103
      in  HOLogic.mk_imp (major, disjs)  end;
paulson@15347
   104
paulson@16012
   105
(* convert an elim rule into an equivalent formula, of type term. *)
wenzelm@20461
   106
fun elimR2Fol elimR =
paulson@20863
   107
  let val elimR' = freeze_thm elimR
paulson@19894
   108
      val (prems,concl) = (prems_of elimR', concl_of elimR')
paulson@20017
   109
      val cv = case concl of    (*conclusion variable*)
wenzelm@20461
   110
                  Const("Trueprop",_) $ (v as Free(_,Type("bool",[]))) => v
wenzelm@20461
   111
                | v as Free(_, Type("prop",[])) => v
wenzelm@20461
   112
                | _ => raise ELIMR2FOL
paulson@20017
   113
  in case prems of
paulson@20017
   114
      [] => raise ELIMR2FOL
wenzelm@20461
   115
    | (Const("Trueprop",_) $ major) :: minors =>
paulson@20017
   116
        if member (op aconv) (term_frees major) cv then raise ELIMR2FOL
paulson@20017
   117
        else (trans_elim (major, minors, concl) handle TERM _ => raise ELIMR2FOL)
paulson@20017
   118
    | _ => raise ELIMR2FOL
paulson@20017
   119
  end;
paulson@15347
   120
wenzelm@20461
   121
(* convert an elim-rule into an equivalent theorem that does not have the
wenzelm@20461
   122
   predicate variable.  Leave other theorems unchanged.*)
paulson@16009
   123
fun transform_elim th =
paulson@20017
   124
    let val ctm = cterm_of (sign_of_thm th) (HOLogic.mk_Trueprop (elimR2Fol th))
paulson@18009
   125
    in Goal.prove_raw [] ctm (fn _ => elimRule_tac th) end
paulson@20017
   126
    handle ELIMR2FOL => th (*not an elimination rule*)
wenzelm@20461
   127
         | exn => (warning ("transform_elim failed: " ^ Toplevel.exn_message exn ^
wenzelm@20461
   128
                            " for theorem " ^ string_of_thm th); th)
paulson@20017
   129
paulson@15997
   130
paulson@15997
   131
(**** Transformation of Clasets and Simpsets into First-Order Axioms ****)
paulson@15997
   132
paulson@16563
   133
(*Transfer a theorem into theory Reconstruction.thy if it is not already
paulson@15359
   134
  inside that theory -- because it's needed for Skolemization *)
paulson@15359
   135
paulson@16563
   136
(*This will refer to the final version of theory Reconstruction.*)
wenzelm@20461
   137
val recon_thy_ref = Theory.self_ref (the_context ());
paulson@15359
   138
paulson@16563
   139
(*If called while Reconstruction is being created, it will transfer to the
paulson@16563
   140
  current version. If called afterward, it will transfer to the final version.*)
paulson@16009
   141
fun transfer_to_Reconstruction th =
paulson@16563
   142
    transfer (Theory.deref recon_thy_ref) th handle THM _ => th;
paulson@15347
   143
paulson@15955
   144
fun is_taut th =
paulson@15955
   145
      case (prop_of th) of
paulson@15955
   146
           (Const ("Trueprop", _) $ Const ("True", _)) => true
paulson@15955
   147
         | _ => false;
paulson@15955
   148
paulson@15955
   149
(* remove tautologous clauses *)
paulson@15955
   150
val rm_redundant_cls = List.filter (not o is_taut);
wenzelm@20461
   151
wenzelm@20461
   152
paulson@16009
   153
(**** SKOLEMIZATION BY INFERENCE (lcp) ****)
paulson@16009
   154
paulson@18141
   155
(*Traverse a theorem, declaring Skolem function definitions. String s is the suggested
paulson@18141
   156
  prefix for the Skolem constant. Result is a new theory*)
paulson@18141
   157
fun declare_skofuns s th thy =
paulson@20419
   158
  let fun dec_sko (Const ("Ex",_) $ (xtp as Abs(_,T,p))) (thy, axs) =
wenzelm@20461
   159
            (*Existential: declare a Skolem function, then insert into body and continue*)
wenzelm@20624
   160
            let val cname = Name.internal (gensym ("sko_" ^ s ^ "_"))
wenzelm@20461
   161
                val args = term_frees xtp  (*get the formal parameter list*)
wenzelm@20461
   162
                val Ts = map type_of args
wenzelm@20461
   163
                val cT = Ts ---> T
wenzelm@20461
   164
                val c = Const (Sign.full_name thy cname, cT)
wenzelm@20461
   165
                val rhs = list_abs_free (map dest_Free args, HOLogic.choice_const T $ xtp)
wenzelm@20461
   166
                        (*Forms a lambda-abstraction over the formal parameters*)
wenzelm@20783
   167
                val thy' = Sign.add_consts_authentic [(cname, cT, NoSyn)] thy
wenzelm@20461
   168
                           (*Theory is augmented with the constant, then its def*)
wenzelm@20461
   169
                val cdef = cname ^ "_def"
wenzelm@20461
   170
                val thy'' = Theory.add_defs_i false false [(cdef, equals cT $ c $ rhs)] thy'
wenzelm@20461
   171
            in dec_sko (subst_bound (list_comb(c,args), p))
wenzelm@20461
   172
                       (thy'', get_axiom thy'' cdef :: axs)
wenzelm@20461
   173
            end
wenzelm@20461
   174
        | dec_sko (Const ("All",_) $ (xtp as Abs(a,T,p))) thx =
wenzelm@20461
   175
            (*Universal quant: insert a free variable into body and continue*)
wenzelm@20461
   176
            let val fname = Name.variant (add_term_names (p,[])) a
wenzelm@20461
   177
            in dec_sko (subst_bound (Free(fname,T), p)) thx end
wenzelm@20461
   178
        | dec_sko (Const ("op &", _) $ p $ q) thx = dec_sko q (dec_sko p thx)
wenzelm@20461
   179
        | dec_sko (Const ("op |", _) $ p $ q) thx = dec_sko q (dec_sko p thx)
wenzelm@20461
   180
        | dec_sko (Const ("Trueprop", _) $ p) thx = dec_sko p thx
wenzelm@20461
   181
        | dec_sko t thx = thx (*Do nothing otherwise*)
paulson@20419
   182
  in  dec_sko (prop_of th) (thy,[])  end;
paulson@18141
   183
paulson@18141
   184
(*Traverse a theorem, accumulating Skolem function definitions.*)
paulson@18141
   185
fun assume_skofuns th =
paulson@18141
   186
  let fun dec_sko (Const ("Ex",_) $ (xtp as Abs(_,T,p))) defs =
wenzelm@20461
   187
            (*Existential: declare a Skolem function, then insert into body and continue*)
wenzelm@20461
   188
            let val skos = map (#1 o Logic.dest_equals) defs  (*existing sko fns*)
wenzelm@20461
   189
                val args = term_frees xtp \\ skos  (*the formal parameters*)
wenzelm@20461
   190
                val Ts = map type_of args
wenzelm@20461
   191
                val cT = Ts ---> T
wenzelm@20461
   192
                val c = Free (gensym "sko_", cT)
wenzelm@20461
   193
                val rhs = list_abs_free (map dest_Free args,
wenzelm@20461
   194
                                         HOLogic.choice_const T $ xtp)
wenzelm@20461
   195
                      (*Forms a lambda-abstraction over the formal parameters*)
wenzelm@20461
   196
                val def = equals cT $ c $ rhs
wenzelm@20461
   197
            in dec_sko (subst_bound (list_comb(c,args), p))
wenzelm@20461
   198
                       (def :: defs)
wenzelm@20461
   199
            end
wenzelm@20461
   200
        | dec_sko (Const ("All",_) $ (xtp as Abs(a,T,p))) defs =
wenzelm@20461
   201
            (*Universal quant: insert a free variable into body and continue*)
wenzelm@20461
   202
            let val fname = Name.variant (add_term_names (p,[])) a
wenzelm@20461
   203
            in dec_sko (subst_bound (Free(fname,T), p)) defs end
wenzelm@20461
   204
        | dec_sko (Const ("op &", _) $ p $ q) defs = dec_sko q (dec_sko p defs)
wenzelm@20461
   205
        | dec_sko (Const ("op |", _) $ p $ q) defs = dec_sko q (dec_sko p defs)
wenzelm@20461
   206
        | dec_sko (Const ("Trueprop", _) $ p) defs = dec_sko p defs
wenzelm@20461
   207
        | dec_sko t defs = defs (*Do nothing otherwise*)
paulson@20419
   208
  in  dec_sko (prop_of th) []  end;
paulson@20419
   209
paulson@20419
   210
paulson@20419
   211
(**** REPLACING ABSTRACTIONS BY FUNCTION DEFINITIONS ****)
paulson@20419
   212
paulson@20419
   213
(*Returns the vars of a theorem*)
paulson@20419
   214
fun vars_of_thm th =
paulson@20445
   215
  map (Thm.cterm_of (theory_of_thm th) o Var) (Drule.fold_terms Term.add_vars th []);
paulson@20419
   216
paulson@20419
   217
(*Make a version of fun_cong with a given variable name*)
paulson@20419
   218
local
paulson@20419
   219
    val fun_cong' = fun_cong RS asm_rl; (*renumber f, g to prevent clashes with (a,0)*)
paulson@20419
   220
    val cx = hd (vars_of_thm fun_cong');
paulson@20419
   221
    val ty = typ_of (ctyp_of_term cx);
paulson@20445
   222
    val thy = theory_of_thm fun_cong;
paulson@20419
   223
    fun mkvar a = cterm_of thy (Var((a,0),ty));
paulson@20419
   224
in
paulson@20419
   225
fun xfun_cong x = Thm.instantiate ([], [(cx, mkvar x)]) fun_cong'
paulson@20419
   226
end;
paulson@20419
   227
paulson@20863
   228
(*Removes the lambdas from an equation of the form t = (%x. u).  A non-negative n,
paulson@20863
   229
  serves as an upper bound on how many to remove.*)
paulson@20863
   230
fun strip_lambdas 0 th = th
paulson@20863
   231
  | strip_lambdas n th = 
paulson@20863
   232
      case prop_of th of
paulson@20863
   233
	  _ $ (Const ("op =", _) $ _ $ Abs (x,_,_)) =>
paulson@20863
   234
	      strip_lambdas (n-1) (freeze_thm (th RS xfun_cong x))
paulson@20863
   235
	| _ => th;
paulson@20419
   236
wenzelm@20461
   237
(*Convert meta- to object-equality. Fails for theorems like split_comp_eq,
paulson@20419
   238
  where some types have the empty sort.*)
paulson@20863
   239
fun mk_object_eq th = th RS def_imp_eq
paulson@20419
   240
    handle THM _ => error ("Theorem contains empty sort: " ^ string_of_thm th);
wenzelm@20461
   241
paulson@20419
   242
(*Apply a function definition to an argument, beta-reducing the result.*)
paulson@20419
   243
fun beta_comb cf x =
paulson@20419
   244
  let val th1 = combination cf (reflexive x)
paulson@20863
   245
      val th2 = beta_conversion false (Drule.crhs_of th1)
paulson@20419
   246
  in  transitive th1 th2  end;
paulson@20419
   247
paulson@20419
   248
(*Apply a function definition to arguments, beta-reducing along the way.*)
paulson@20419
   249
fun list_combination cf [] = cf
paulson@20419
   250
  | list_combination cf (x::xs) = list_combination (beta_comb cf x) xs;
paulson@20419
   251
paulson@20419
   252
fun list_cabs ([] ,     t) = t
paulson@20419
   253
  | list_cabs (v::vars, t) = Thm.cabs v (list_cabs(vars,t));
paulson@20419
   254
wenzelm@20461
   255
fun assert_eta_free ct =
wenzelm@20461
   256
  let val t = term_of ct
wenzelm@20461
   257
  in if (t aconv Envir.eta_contract t) then ()
paulson@20419
   258
     else error ("Eta redex in term: " ^ string_of_cterm ct)
paulson@20419
   259
  end;
paulson@20419
   260
wenzelm@20461
   261
fun eq_absdef (th1, th2) =
paulson@20445
   262
    Context.joinable (theory_of_thm th1, theory_of_thm th2)  andalso
paulson@20445
   263
    rhs_of th1 aconv rhs_of th2;
paulson@20445
   264
paulson@20445
   265
fun lambda_free (Abs _) = false
paulson@20445
   266
  | lambda_free (t $ u) = lambda_free t andalso lambda_free u
paulson@20445
   267
  | lambda_free _ = true;
wenzelm@20461
   268
wenzelm@20461
   269
fun monomorphic t =
wenzelm@20461
   270
  Term.fold_types (Term.fold_atyps (fn TVar _ => K false | _ => I)) t true;
wenzelm@20461
   271
paulson@20710
   272
fun dest_abs_list ct =
paulson@20710
   273
  let val (cv,ct') = Thm.dest_abs NONE ct
paulson@20710
   274
      val (cvs,cu) = dest_abs_list ct'
paulson@20710
   275
  in (cv::cvs, cu) end
paulson@20710
   276
  handle CTERM _ => ([],ct);
paulson@20710
   277
paulson@20710
   278
fun lambda_list [] u = u
paulson@20710
   279
  | lambda_list (v::vs) u = lambda v (lambda_list vs u);
paulson@20710
   280
paulson@20710
   281
fun abstract_rule_list [] [] th = th
paulson@20710
   282
  | abstract_rule_list (v::vs) (ct::cts) th = abstract_rule v ct (abstract_rule_list vs cts th)
paulson@20710
   283
  | abstract_rule_list _ _ th = raise THM ("abstract_rule_list", 0, [th]);
paulson@20710
   284
paulson@20863
   285
paulson@20863
   286
val Envir.Envir {asol = tenv0, iTs = tyenv0, ...} = Envir.empty 0
paulson@20863
   287
paulson@20863
   288
(*Does an existing abstraction definition have an RHS that matches the one we need now?*)
paulson@20863
   289
fun match_rhs thy0 t th =
paulson@20863
   290
  let val thy = theory_of_thm th
paulson@20863
   291
      val _ = if !trace_abs then warning ("match_rhs: " ^ string_of_cterm (cterm_of thy t) ^ 
paulson@20863
   292
                                          " against\n" ^ string_of_thm th) else ();
paulson@20863
   293
      val (tyenv,tenv) = if Context.joinable (thy0,thy) then
paulson@20863
   294
                            Pattern.first_order_match thy (rhs_of th, t) (tyenv0,tenv0)
paulson@20863
   295
                         else raise Pattern.MATCH
paulson@20863
   296
      val term_insts = map Meson.term_pair_of (Vartab.dest tenv)
paulson@20863
   297
      val ct_pairs = if forall lambda_free (map #2 term_insts) then
paulson@20863
   298
                         map (pairself (cterm_of thy)) term_insts
paulson@20863
   299
                     else raise Pattern.MATCH (*Cannot allow lambdas in the instantiation*)
paulson@20863
   300
      fun ctyp2 (ixn, (S, T)) = (ctyp_of thy (TVar (ixn, S)), ctyp_of thy T)
paulson@20863
   301
      val th' = cterm_instantiate ct_pairs th
paulson@20863
   302
  in  SOME (th, instantiate (map ctyp2 (Vartab.dest tyenv), []) th')  end
paulson@20863
   303
  handle _ => NONE;
paulson@20863
   304
paulson@20419
   305
(*Traverse a theorem, declaring abstraction function definitions. String s is the suggested
paulson@20419
   306
  prefix for the constants. Resulting theory is returned in the first theorem. *)
paulson@20419
   307
fun declare_absfuns th =
wenzelm@20461
   308
  let fun abstract thy ct =
paulson@20445
   309
        if lambda_free (term_of ct) then (transfer thy (reflexive ct), [])
paulson@20445
   310
        else
paulson@20445
   311
        case term_of ct of
paulson@20710
   312
          Abs _ =>
wenzelm@20624
   313
            let val cname = Name.internal (gensym "abs_");
wenzelm@20461
   314
                val _ = assert_eta_free ct;
paulson@20710
   315
                val (cvs,cta) = dest_abs_list ct
paulson@20710
   316
                val (vs,Tvs) = ListPair.unzip (map (dest_Free o term_of) cvs)
paulson@20863
   317
                val _ = if !trace_abs then warning ("Nested lambda: " ^ string_of_cterm cta) else ();
wenzelm@20461
   318
                val (u'_th,defs) = abstract thy cta
paulson@20863
   319
                val _ = if !trace_abs then warning ("Returned " ^ string_of_thm u'_th) else ();
paulson@20863
   320
                val cu' = Drule.crhs_of u'_th
paulson@20863
   321
                val u' = term_of cu'
paulson@20863
   322
                val abs_v_u = lambda_list (map term_of cvs) u'
wenzelm@20461
   323
                (*get the formal parameters: ALL variables free in the term*)
wenzelm@20461
   324
                val args = term_frees abs_v_u
paulson@20863
   325
                val _ = if !trace_abs then warning (Int.toString (length args) ^ " arguments") else ();
wenzelm@20461
   326
                val rhs = list_abs_free (map dest_Free args, abs_v_u)
wenzelm@20461
   327
                      (*Forms a lambda-abstraction over the formal parameters*)
wenzelm@20461
   328
                val v_rhs = Logic.varify rhs
paulson@20863
   329
                val _ = if !trace_abs then warning ("Looking up " ^ string_of_cterm cu') else ();
paulson@20863
   330
                val (ax,ax',thy) =
paulson@20863
   331
                 case List.mapPartial (match_rhs thy abs_v_u) (Net.match_term (!abstraction_cache) u')
paulson@20863
   332
                        of
paulson@20863
   333
                     (ax,ax')::_ => 
paulson@20863
   334
                       (if !trace_abs then warning ("Re-using axiom " ^ string_of_thm ax) else ();
paulson@20863
   335
                        (ax,ax',thy))
paulson@20863
   336
                   | [] =>
paulson@20863
   337
                      let val _ = if !trace_abs then warning "Lookup was empty" else ();
paulson@20863
   338
                          val Ts = map type_of args
paulson@20710
   339
                          val cT = Ts ---> (Tvs ---> typ_of (ctyp_of_term cu'))
wenzelm@20461
   340
                          val thy = theory_of_thm u'_th
wenzelm@20461
   341
                          val c = Const (Sign.full_name thy cname, cT)
wenzelm@20783
   342
                          val thy = Sign.add_consts_authentic [(cname, cT, NoSyn)] thy
wenzelm@20461
   343
                                     (*Theory is augmented with the constant,
wenzelm@20461
   344
                                       then its definition*)
wenzelm@20461
   345
                          val cdef = cname ^ "_def"
wenzelm@20461
   346
                          val thy = Theory.add_defs_i false false
wenzelm@20461
   347
                                       [(cdef, equals cT $ c $ rhs)] thy
paulson@20863
   348
                          val _ = if !trace_abs then (warning ("Definition is " ^ 
paulson@20863
   349
                                                      string_of_thm (get_axiom thy cdef))) 
paulson@20863
   350
                                  else ();
paulson@20863
   351
                          val ax = get_axiom thy cdef |> freeze_thm
paulson@20863
   352
                                     |> mk_object_eq |> strip_lambdas (length args)
paulson@20863
   353
                                     |> mk_meta_eq |> Meson.generalize
paulson@20863
   354
                          val (_,ax') = Option.valOf (match_rhs thy abs_v_u ax)
paulson@20863
   355
                          val _ = if !trace_abs then 
paulson@20863
   356
                                    (warning ("Declaring: " ^ string_of_thm ax);
paulson@20863
   357
                                     warning ("Instance: " ^ string_of_thm ax')) 
paulson@20863
   358
                                  else ();
paulson@20863
   359
                          val _ = abstraction_cache := Net.insert_term eq_absdef 
paulson@20863
   360
                                            ((Logic.varify u'), ax) (!abstraction_cache)
wenzelm@20461
   361
                            handle Net.INSERT =>
wenzelm@20461
   362
                              raise THM ("declare_absfuns: INSERT", 0, [th,u'_th,ax])
paulson@20863
   363
                       in  (ax,ax',thy)  end
paulson@20863
   364
            in if !trace_abs then warning ("Lookup result: " ^ string_of_thm ax') else ();
paulson@20863
   365
               (transitive (abstract_rule_list vs cvs u'_th) (symmetric ax'), ax::defs) end
wenzelm@20461
   366
        | (t1$t2) =>
wenzelm@20461
   367
            let val (ct1,ct2) = Thm.dest_comb ct
wenzelm@20461
   368
                val (th1,defs1) = abstract thy ct1
wenzelm@20461
   369
                val (th2,defs2) = abstract (theory_of_thm th1) ct2
wenzelm@20461
   370
            in  (combination th1 th2, defs1@defs2)  end
paulson@20863
   371
      val _ = if !trace_abs then warning ("declare_absfuns, Abstracting: " ^ string_of_thm th) else ();
paulson@20419
   372
      val (eqth,defs) = abstract (theory_of_thm th) (cprop_of th)
paulson@20863
   373
      val ths = equal_elim eqth th :: map (strip_lambdas ~1 o mk_object_eq o freeze_thm) defs
paulson@20863
   374
      val _ = if !trace_abs then warning ("declare_absfuns, Result: " ^ string_of_thm (hd ths)) else ();
paulson@20863
   375
  in  (theory_of_thm eqth, map Drule.eta_contraction_rule ths)  end;
paulson@20419
   376
paulson@20567
   377
fun name_of def = SOME (#1 (dest_Free (lhs_of def))) handle _ => NONE;
paulson@20567
   378
paulson@20525
   379
(*A name is valid provided it isn't the name of a defined abstraction.*)
paulson@20567
   380
fun valid_name defs (Free(x,T)) = not (x mem_string (List.mapPartial name_of defs))
paulson@20525
   381
  | valid_name defs _ = false;
paulson@20525
   382
paulson@20419
   383
fun assume_absfuns th =
paulson@20445
   384
  let val thy = theory_of_thm th
paulson@20445
   385
      val cterm = cterm_of thy
paulson@20525
   386
      fun abstract ct =
paulson@20445
   387
        if lambda_free (term_of ct) then (reflexive ct, [])
paulson@20445
   388
        else
paulson@20445
   389
        case term_of ct of
paulson@20419
   390
          Abs (_,T,u) =>
paulson@20710
   391
            let val _ = assert_eta_free ct;
paulson@20710
   392
                val (cvs,cta) = dest_abs_list ct
paulson@20710
   393
                val (vs,Tvs) = ListPair.unzip (map (dest_Free o term_of) cvs)
paulson@20525
   394
                val (u'_th,defs) = abstract cta
paulson@20863
   395
                val cu' = Drule.crhs_of u'_th
paulson@20863
   396
                val u' = term_of cu'
paulson@20710
   397
                (*Could use Thm.cabs instead of lambda to work at level of cterms*)
paulson@20710
   398
                val abs_v_u = lambda_list (map term_of cvs) (term_of cu')
paulson@20525
   399
                (*get the formal parameters: free variables not present in the defs
paulson@20525
   400
                  (to avoid taking abstraction function names as parameters) *)
paulson@20710
   401
                val args = filter (valid_name defs) (term_frees abs_v_u)
paulson@20710
   402
                val crhs = list_cabs (map cterm args, cterm abs_v_u)
wenzelm@20461
   403
                      (*Forms a lambda-abstraction over the formal parameters*)
wenzelm@20461
   404
                val rhs = term_of crhs
paulson@20863
   405
                val (ax,ax') =
paulson@20863
   406
                 case List.mapPartial (match_rhs thy abs_v_u) 
paulson@20863
   407
                        (Net.match_term (!abstraction_cache) u') of
paulson@20863
   408
                     (ax,ax')::_ => 
paulson@20863
   409
                       (if !trace_abs then warning ("Re-using axiom " ^ string_of_thm ax) else ();
paulson@20863
   410
                        (ax,ax'))
paulson@20863
   411
                   | [] =>
wenzelm@20461
   412
                      let val Ts = map type_of args
paulson@20710
   413
                          val const_ty = Ts ---> (Tvs ---> typ_of (ctyp_of_term cu'))
wenzelm@20461
   414
                          val c = Free (gensym "abs_", const_ty)
wenzelm@20461
   415
                          val ax = assume (Thm.capply (cterm (equals const_ty $ c)) crhs)
paulson@20863
   416
                                     |> mk_object_eq |> strip_lambdas (length args)
paulson@20863
   417
                                     |> mk_meta_eq |> Meson.generalize
paulson@20863
   418
                          val (_,ax') = Option.valOf (match_rhs thy abs_v_u ax)
wenzelm@20461
   419
                          val _ = abstraction_cache := Net.insert_term eq_absdef (rhs,ax)
wenzelm@20461
   420
                                    (!abstraction_cache)
wenzelm@20461
   421
                            handle Net.INSERT =>
wenzelm@20461
   422
                              raise THM ("assume_absfuns: INSERT", 0, [th,u'_th,ax])
paulson@20863
   423
                      in (ax,ax') end
paulson@20863
   424
            in if !trace_abs then warning ("Lookup result: " ^ string_of_thm ax') else ();
paulson@20863
   425
               (transitive (abstract_rule_list vs cvs u'_th) (symmetric ax'), ax::defs) end
wenzelm@20461
   426
        | (t1$t2) =>
wenzelm@20461
   427
            let val (ct1,ct2) = Thm.dest_comb ct
paulson@20525
   428
                val (t1',defs1) = abstract ct1
paulson@20525
   429
                val (t2',defs2) = abstract ct2
wenzelm@20461
   430
            in  (combination t1' t2', defs1@defs2)  end
paulson@20863
   431
      val _ = if !trace_abs then warning ("assume_absfuns, Abstracting: " ^ string_of_thm th) else ();
paulson@20525
   432
      val (eqth,defs) = abstract (cprop_of th)
paulson@20863
   433
      val ths = equal_elim eqth th :: map (strip_lambdas ~1 o mk_object_eq o freeze_thm) defs
paulson@20863
   434
      val _ = if !trace_abs then warning ("assume_absfuns, Result: " ^ string_of_thm (hd ths)) else ();
paulson@20863
   435
  in  map Drule.eta_contraction_rule ths  end;
paulson@20419
   436
paulson@16009
   437
paulson@16009
   438
(*cterms are used throughout for efficiency*)
paulson@18141
   439
val cTrueprop = Thm.cterm_of HOL.thy HOLogic.Trueprop;
paulson@16009
   440
paulson@16009
   441
(*cterm version of mk_cTrueprop*)
paulson@16009
   442
fun c_mkTrueprop A = Thm.capply cTrueprop A;
paulson@16009
   443
paulson@16009
   444
(*Given an abstraction over n variables, replace the bound variables by free
paulson@16009
   445
  ones. Return the body, along with the list of free variables.*)
wenzelm@20461
   446
fun c_variant_abs_multi (ct0, vars) =
paulson@16009
   447
      let val (cv,ct) = Thm.dest_abs NONE ct0
paulson@16009
   448
      in  c_variant_abs_multi (ct, cv::vars)  end
paulson@16009
   449
      handle CTERM _ => (ct0, rev vars);
paulson@16009
   450
wenzelm@20461
   451
(*Given the definition of a Skolem function, return a theorem to replace
wenzelm@20461
   452
  an existential formula by a use of that function.
paulson@18141
   453
   Example: "EX x. x : A & x ~: B ==> sko A B : A & sko A B ~: B"  [.] *)
wenzelm@20461
   454
fun skolem_of_def def =
paulson@20863
   455
  let val (c,rhs) = Drule.dest_equals (cprop_of (freeze_thm def))
paulson@16009
   456
      val (ch, frees) = c_variant_abs_multi (rhs, [])
paulson@18141
   457
      val (chilbert,cabs) = Thm.dest_comb ch
paulson@18141
   458
      val {sign,t, ...} = rep_cterm chilbert
paulson@18141
   459
      val T = case t of Const ("Hilbert_Choice.Eps", Type("fun",[_,T])) => T
paulson@18141
   460
                      | _ => raise THM ("skolem_of_def: expected Eps", 0, [def])
paulson@16009
   461
      val cex = Thm.cterm_of sign (HOLogic.exists_const T)
paulson@16009
   462
      val ex_tm = c_mkTrueprop (Thm.capply cex cabs)
paulson@16009
   463
      and conc =  c_mkTrueprop (Drule.beta_conv cabs (Drule.list_comb(c,frees)));
paulson@18141
   464
      fun tacf [prem] = rewrite_goals_tac [def] THEN rtac (prem RS someI_ex) 1
wenzelm@20461
   465
  in  Goal.prove_raw [ex_tm] conc tacf
paulson@18141
   466
       |> forall_intr_list frees
paulson@18141
   467
       |> forall_elim_vars 0  (*Introduce Vars, but don't discharge defs.*)
paulson@18141
   468
       |> Thm.varifyT
paulson@18141
   469
  end;
paulson@16009
   470
paulson@20863
   471
(*Converts an Isabelle theorem (intro, elim or simp format, even higher-order) into NNF.*)
wenzelm@20461
   472
fun to_nnf th =
paulson@18141
   473
    th |> transfer_to_Reconstruction
paulson@20863
   474
       |> transform_elim |> zero_var_indexes |> freeze_thm
paulson@20863
   475
       |> ObjectLogic.atomize_thm |> make_nnf |> strip_lambdas ~1;
paulson@16009
   476
wenzelm@20461
   477
(*The cache prevents repeated clausification of a theorem,
wenzelm@20461
   478
  and also repeated declaration of Skolem functions*)
paulson@18510
   479
  (* FIXME better use Termtab!? No, we MUST use theory data!!*)
paulson@15955
   480
val clause_cache = ref (Symtab.empty : (thm * thm list) Symtab.table)
paulson@15955
   481
paulson@18141
   482
paulson@18141
   483
(*Generate Skolem functions for a theorem supplied in nnf*)
paulson@18141
   484
fun skolem_of_nnf th =
paulson@18141
   485
  map (skolem_of_def o assume o (cterm_of (theory_of_thm th))) (assume_skofuns th);
paulson@18141
   486
paulson@20863
   487
fun assert_lambda_free ths msg = 
paulson@20863
   488
  case filter (not o lambda_free o prop_of) ths of
paulson@20863
   489
      [] => ()
paulson@20863
   490
     | ths' => error (msg ^ "\n" ^ space_implode "\n" (map string_of_thm ths'));
paulson@20457
   491
paulson@20445
   492
fun assume_abstract th =
paulson@20457
   493
  if lambda_free (prop_of th) then [th]
paulson@20863
   494
  else th |> Drule.eta_contraction_rule |> assume_absfuns
paulson@20457
   495
          |> tap (fn ths => assert_lambda_free ths "assume_abstract: lambdas")
paulson@20445
   496
paulson@20419
   497
(*Replace lambdas by assumed function definitions in the theorems*)
paulson@20445
   498
fun assume_abstract_list ths =
paulson@20445
   499
  if abstract_lambdas then List.concat (map assume_abstract ths)
paulson@20863
   500
  else map Drule.eta_contraction_rule ths;
paulson@20419
   501
paulson@20419
   502
(*Replace lambdas by declared function definitions in the theorems*)
paulson@20419
   503
fun declare_abstract' (thy, []) = (thy, [])
paulson@20419
   504
  | declare_abstract' (thy, th::ths) =
wenzelm@20461
   505
      let val (thy', th_defs) =
paulson@20457
   506
            if lambda_free (prop_of th) then (thy, [th])
paulson@20445
   507
            else
paulson@20863
   508
                th |> zero_var_indexes |> freeze_thm
paulson@20863
   509
                   |> Drule.eta_contraction_rule |> transfer thy |> declare_absfuns
wenzelm@20461
   510
          val _ = assert_lambda_free th_defs "declare_abstract: lambdas"
wenzelm@20461
   511
          val (thy'', ths') = declare_abstract' (thy', ths)
paulson@20419
   512
      in  (thy'', th_defs @ ths')  end;
paulson@20419
   513
paulson@20421
   514
(*FIXME DELETE if we decide to switch to abstractions*)
paulson@20419
   515
fun declare_abstract (thy, ths) =
paulson@20419
   516
  if abstract_lambdas then declare_abstract' (thy, ths)
paulson@20863
   517
  else (thy, map Drule.eta_contraction_rule ths);
paulson@20419
   518
paulson@18510
   519
(*Skolemize a named theorem, with Skolem functions as additional premises.*)
wenzelm@20461
   520
(*also works for HOL*)
wenzelm@20461
   521
fun skolem_thm th =
paulson@18510
   522
  let val nnfth = to_nnf th
paulson@20419
   523
  in  Meson.make_cnf (skolem_of_nnf nnfth) nnfth
paulson@20445
   524
      |> assume_abstract_list |> Meson.finish_cnf |> rm_redundant_cls
paulson@18510
   525
  end
paulson@18510
   526
  handle THM _ => [];
paulson@18141
   527
paulson@18510
   528
(*Declare Skolem functions for a theorem, supplied in nnf and with its name.
paulson@18510
   529
  It returns a modified theory, unless skolemization fails.*)
paulson@16009
   530
fun skolem thy (name,th) =
paulson@20419
   531
  let val cname = (case name of "" => gensym "" | s => Sign.base_name s)
paulson@20419
   532
      val _ = Output.debug ("skolemizing " ^ name ^ ": ")
wenzelm@20461
   533
  in Option.map
wenzelm@20461
   534
        (fn nnfth =>
paulson@18141
   535
          let val (thy',defs) = declare_skofuns cname nnfth thy
paulson@20419
   536
              val cnfs = Meson.make_cnf (map skolem_of_def defs) nnfth
paulson@20419
   537
              val (thy'',cnfs') = declare_abstract (thy',cnfs)
paulson@20419
   538
          in (thy'', rm_redundant_cls (Meson.finish_cnf cnfs'))
paulson@20419
   539
          end)
wenzelm@20461
   540
      (SOME (to_nnf th)  handle THM _ => NONE)
paulson@18141
   541
  end;
paulson@16009
   542
paulson@18510
   543
(*Populate the clause cache using the supplied theorem. Return the clausal form
paulson@18510
   544
  and modified theory.*)
wenzelm@20461
   545
fun skolem_cache_thm (name,th) thy =
paulson@18144
   546
  case Symtab.lookup (!clause_cache) name of
wenzelm@20461
   547
      NONE =>
wenzelm@20461
   548
        (case skolem thy (name, Thm.transfer thy th) of
wenzelm@20461
   549
             NONE => ([th],thy)
paulson@20473
   550
           | SOME (thy',cls) => 
paulson@20473
   551
               let val cls = map Drule.local_standard cls
paulson@20473
   552
               in
paulson@20473
   553
                  if null cls then warning ("skolem_cache: empty clause set for " ^ name)
paulson@20473
   554
                  else ();
paulson@20473
   555
                  change clause_cache (Symtab.update (name, (th, cls))); 
paulson@20473
   556
                  (cls,thy')
paulson@20473
   557
               end)
paulson@18144
   558
    | SOME (th',cls) =>
paulson@18510
   559
        if eq_thm(th,th') then (cls,thy)
wenzelm@20461
   560
        else (Output.debug ("skolem_cache: Ignoring variant of theorem " ^ name);
wenzelm@20461
   561
              Output.debug (string_of_thm th);
wenzelm@20461
   562
              Output.debug (string_of_thm th');
wenzelm@20461
   563
              ([th],thy));
wenzelm@20461
   564
wenzelm@20461
   565
(*Exported function to convert Isabelle theorems into axiom clauses*)
paulson@19894
   566
fun cnf_axiom (name,th) =
paulson@18144
   567
  case name of
wenzelm@20461
   568
        "" => skolem_thm th (*no name, so can't cache*)
paulson@18144
   569
      | s  => case Symtab.lookup (!clause_cache) s of
paulson@20473
   570
                NONE => 
paulson@20473
   571
                  let val cls = map Drule.local_standard (skolem_thm th)
wenzelm@20461
   572
                  in change clause_cache (Symtab.update (s, (th, cls))); cls end
wenzelm@20461
   573
              | SOME(th',cls) =>
wenzelm@20461
   574
                  if eq_thm(th,th') then cls
wenzelm@20461
   575
                  else (Output.debug ("cnf_axiom: duplicate or variant of theorem " ^ name);
wenzelm@20461
   576
                        Output.debug (string_of_thm th);
wenzelm@20461
   577
                        Output.debug (string_of_thm th');
wenzelm@20461
   578
                        cls);
paulson@15347
   579
paulson@18141
   580
fun pairname th = (Thm.name_of_thm th, th);
paulson@18141
   581
wenzelm@20461
   582
fun meta_cnf_axiom th =
paulson@15956
   583
    map Meson.make_meta_clause (cnf_axiom (pairname th));
paulson@15499
   584
paulson@15347
   585
paulson@15872
   586
(**** Extract and Clausify theorems from a theory's claset and simpset ****)
paulson@15347
   587
paulson@17404
   588
(*Preserve the name of "th" after the transformation "f"*)
paulson@17404
   589
fun preserve_name f th = Thm.name_thm (Thm.name_of_thm th, f th);
paulson@17404
   590
paulson@17484
   591
fun rules_of_claset cs =
paulson@17484
   592
  let val {safeIs,safeEs,hazIs,hazEs,...} = rep_cs cs
paulson@19175
   593
      val intros = safeIs @ hazIs
wenzelm@18532
   594
      val elims  = map Classical.classical_rule (safeEs @ hazEs)
paulson@17404
   595
  in
wenzelm@20461
   596
     Output.debug ("rules_of_claset intros: " ^ Int.toString(length intros) ^
paulson@17484
   597
            " elims: " ^ Int.toString(length elims));
paulson@20017
   598
     map pairname (intros @ elims)
paulson@17404
   599
  end;
paulson@15347
   600
paulson@17484
   601
fun rules_of_simpset ss =
paulson@17484
   602
  let val ({rules,...}, _) = rep_ss ss
paulson@17484
   603
      val simps = Net.entries rules
wenzelm@20461
   604
  in
wenzelm@18680
   605
      Output.debug ("rules_of_simpset: " ^ Int.toString(length simps));
paulson@17484
   606
      map (fn r => (#name r, #thm r)) simps
paulson@17484
   607
  end;
paulson@17484
   608
paulson@17484
   609
fun claset_rules_of_thy thy = rules_of_claset (claset_of thy);
paulson@17484
   610
fun simpset_rules_of_thy thy = rules_of_simpset (simpset_of thy);
paulson@17484
   611
wenzelm@20774
   612
fun atpset_rules_of_thy thy = map pairname (ResAtpset.get_atpset (Context.Theory thy));
mengj@19196
   613
mengj@19196
   614
paulson@17484
   615
fun claset_rules_of_ctxt ctxt = rules_of_claset (local_claset_of ctxt);
paulson@17484
   616
fun simpset_rules_of_ctxt ctxt = rules_of_simpset (local_simpset_of ctxt);
paulson@15347
   617
wenzelm@20774
   618
fun atpset_rules_of_ctxt ctxt = map pairname (ResAtpset.get_atpset (Context.Proof ctxt));
wenzelm@20774
   619
paulson@15347
   620
paulson@15872
   621
(**** Translate a set of classical/simplifier rules into CNF (still as type "thm")  ****)
paulson@15347
   622
paulson@19894
   623
(* classical rules: works for both FOL and HOL *)
paulson@19894
   624
fun cnf_rules [] err_list = ([],err_list)
wenzelm@20461
   625
  | cnf_rules ((name,th) :: ths) err_list =
paulson@19894
   626
      let val (ts,es) = cnf_rules ths err_list
wenzelm@20461
   627
      in  (cnf_axiom (name,th) :: ts,es) handle  _ => (ts, (th::es))  end;
paulson@15347
   628
paulson@19894
   629
fun pair_name_cls k (n, []) = []
paulson@19894
   630
  | pair_name_cls k (n, cls::clss) = (cls, (n,k)) :: pair_name_cls (k+1) (n, clss)
wenzelm@20461
   631
paulson@19894
   632
fun cnf_rules_pairs_aux pairs [] = pairs
paulson@19894
   633
  | cnf_rules_pairs_aux pairs ((name,th)::ths) =
paulson@20457
   634
      let val pairs' = (pair_name_cls 0 (name, cnf_axiom(name,th))) @ pairs
wenzelm@20461
   635
                       handle THM _ => pairs | ResClause.CLAUSE _ => pairs
paulson@19894
   636
      in  cnf_rules_pairs_aux pairs' ths  end;
wenzelm@20461
   637
paulson@19894
   638
val cnf_rules_pairs = cnf_rules_pairs_aux [];
mengj@19353
   639
mengj@19196
   640
mengj@18198
   641
(**** Convert all theorems of a claset/simpset into clauses (ResClause.clause, or ResHolClause.clause) ****)
paulson@15347
   642
paulson@20419
   643
(*Setup function: takes a theory and installs ALL known theorems into the clause cache*)
paulson@20457
   644
wenzelm@20461
   645
fun skolem_cache (name,th) thy =
wenzelm@20461
   646
  let val prop = Thm.prop_of th
paulson@20457
   647
  in
paulson@20863
   648
      if lambda_free prop (*orelse monomorphic prop*)
paulson@20457
   649
      then thy    (*monomorphic theorems can be Skolemized on demand*)
wenzelm@20461
   650
      else #2 (skolem_cache_thm (name,th) thy)
paulson@20457
   651
  end;
paulson@20457
   652
wenzelm@20461
   653
fun clause_cache_setup thy = fold skolem_cache (PureThy.all_thms_of thy) thy;
wenzelm@20461
   654
paulson@16563
   655
paulson@16563
   656
(*** meson proof methods ***)
paulson@16563
   657
paulson@16563
   658
fun cnf_rules_of_ths ths = List.concat (#1 (cnf_rules (map pairname ths) []));
paulson@16563
   659
paulson@16563
   660
fun meson_meth ths ctxt =
paulson@16563
   661
  Method.SIMPLE_METHOD' HEADGOAL
paulson@16563
   662
    (CHANGED_PROP o Meson.meson_claset_tac (cnf_rules_of_ths ths) (local_claset_of ctxt));
paulson@16563
   663
paulson@16563
   664
val meson_method_setup =
wenzelm@18708
   665
  Method.add_methods
wenzelm@20461
   666
    [("meson", Method.thms_ctxt_args meson_meth,
wenzelm@18833
   667
      "MESON resolution proof procedure")];
paulson@15347
   668
paulson@18510
   669
paulson@18510
   670
paulson@18510
   671
(*** The Skolemization attribute ***)
paulson@18510
   672
paulson@18510
   673
fun conj2_rule (th1,th2) = conjI OF [th1,th2];
paulson@18510
   674
paulson@20457
   675
(*Conjoin a list of theorems to form a single theorem*)
paulson@20457
   676
fun conj_rule []  = TrueI
paulson@20445
   677
  | conj_rule ths = foldr1 conj2_rule ths;
paulson@18510
   678
paulson@20419
   679
fun skolem_attr (Context.Theory thy, th) =
paulson@20419
   680
      let val name = Thm.name_of_thm th
wenzelm@20461
   681
          val (cls, thy') = skolem_cache_thm (name, th) thy
wenzelm@18728
   682
      in (Context.Theory thy', conj_rule cls) end
paulson@20419
   683
  | skolem_attr (context, th) = (context, conj_rule (skolem_thm th));
paulson@18510
   684
paulson@18510
   685
val setup_attrs = Attrib.add_attributes
paulson@20419
   686
  [("skolem", Attrib.no_args skolem_attr, "skolemization of a theorem")];
paulson@18510
   687
wenzelm@18708
   688
val setup = clause_cache_setup #> setup_attrs;
paulson@18510
   689
wenzelm@20461
   690
end;