Nominal/Ex/LamTest.thy
branchNominal2-Isabelle2011-1
changeset 3071 11f6a561eb4b
parent 3070 4b4742aa43f2
child 3072 7eb352826b42
equal deleted inserted replaced
3070:4b4742aa43f2 3071:11f6a561eb4b
     1 theory LamTest
       
     2 imports "../Nominal2" 
       
     3 begin
       
     4 
       
     5 atom_decl name
       
     6 
       
     7 nominal_datatype lam =
       
     8   Var "name"
       
     9 | App "lam" "lam"
       
    10 | Lam x::"name" l::"lam"  bind x in l
       
    11 
       
    12 
       
    13 ML {*
       
    14 
       
    15 val trace = Unsynchronized.ref false
       
    16 fun trace_msg msg = if ! trace then tracing (msg ()) else ()
       
    17 
       
    18 val boolT = HOLogic.boolT
       
    19 val mk_eq = HOLogic.mk_eq
       
    20 
       
    21 open Function_Lib
       
    22 open Function_Common
       
    23 
       
    24 datatype globals = Globals of
       
    25  {fvar: term,
       
    26   domT: typ,
       
    27   ranT: typ,
       
    28   h: term,
       
    29   y: term,
       
    30   x: term,
       
    31   z: term,
       
    32   a: term,
       
    33   P: term,
       
    34   D: term,
       
    35   Pbool:term}
       
    36 
       
    37 datatype rec_call_info = RCInfo of
       
    38  {RIvs: (string * typ) list,  (* Call context: fixes and assumes *)
       
    39   CCas: thm list,
       
    40   rcarg: term,                 (* The recursive argument *)
       
    41   llRI: thm,
       
    42   h_assum: term}
       
    43 
       
    44 
       
    45 datatype clause_context = ClauseContext of
       
    46  {ctxt : Proof.context,
       
    47   qs : term list,
       
    48   gs : term list,
       
    49   lhs: term,
       
    50   rhs: term,
       
    51   cqs: cterm list,
       
    52   ags: thm list,
       
    53   case_hyp : thm}
       
    54 
       
    55 
       
    56 fun transfer_clause_ctx thy (ClauseContext { ctxt, qs, gs, lhs, rhs, cqs, ags, case_hyp }) =
       
    57   ClauseContext { ctxt = ProofContext.transfer thy ctxt,
       
    58     qs = qs, gs = gs, lhs = lhs, rhs = rhs, cqs = cqs, ags = ags, case_hyp = case_hyp }
       
    59 
       
    60 
       
    61 datatype clause_info = ClauseInfo of
       
    62  {no: int,
       
    63   qglr : ((string * typ) list * term list * term * term),
       
    64   cdata : clause_context,
       
    65   tree: Function_Ctx_Tree.ctx_tree,
       
    66   lGI: thm,
       
    67   RCs: rec_call_info list}
       
    68 *}
       
    69 
       
    70 thm accp_induct_rule
       
    71 
       
    72 ML {*
       
    73 (* Theory dependencies. *)
       
    74 val acc_induct_rule = @{thm accp_induct_rule}
       
    75 
       
    76 val ex1_implies_ex = @{thm FunDef.fundef_ex1_existence}
       
    77 val ex1_implies_un = @{thm FunDef.fundef_ex1_uniqueness}
       
    78 val ex1_implies_iff = @{thm FunDef.fundef_ex1_iff}
       
    79 
       
    80 val acc_downward = @{thm accp_downward}
       
    81 val accI = @{thm accp.accI}
       
    82 val case_split = @{thm HOL.case_split}
       
    83 val fundef_default_value = @{thm FunDef.fundef_default_value}
       
    84 val not_acc_down = @{thm not_accp_down}
       
    85 *}
       
    86 
       
    87 
       
    88 ML {*
       
    89 fun find_calls tree =
       
    90   let
       
    91     fun add_Ri (fixes,assumes) (_ $ arg) _ (_, xs) =
       
    92       ([], (fixes, assumes, arg) :: xs)
       
    93       | add_Ri _ _ _ _ = raise Match
       
    94   in
       
    95     rev (Function_Ctx_Tree.traverse_tree add_Ri tree [])
       
    96   end
       
    97 *}
       
    98 
       
    99 ML {*
       
   100 fun mk_eqvt_at (f_trm, arg_trm) =
       
   101   let
       
   102     val f_ty = fastype_of f_trm
       
   103     val arg_ty = domain_type f_ty
       
   104   in
       
   105     Const (@{const_name eqvt_at}, [f_ty, arg_ty] ---> @{typ bool}) $ f_trm $ arg_trm
       
   106     |> HOLogic.mk_Trueprop
       
   107   end
       
   108 *}
       
   109 
       
   110 ML {*
       
   111 fun find_calls2 f t = 
       
   112   let
       
   113     fun aux (g $ arg) = aux g #> aux arg #> (if f = g then cons ((g, arg)) else I)
       
   114       | aux (Abs (_, _, t)) = aux t 
       
   115       | aux _ = I
       
   116   in
       
   117     aux t []
       
   118   end 
       
   119 *}
       
   120 
       
   121 
       
   122 ML {*
       
   123 (** building proof obligations *)
       
   124 
       
   125 fun mk_compat_proof_obligations domT ranT fvar f glrs =
       
   126   let
       
   127     fun mk_impl ((qs, gs, lhs, rhs), (qs', gs', lhs', rhs')) =
       
   128       let
       
   129         val shift = incr_boundvars (length qs')
       
   130 
       
   131         val RCs_rhs  = find_calls2 fvar rhs
       
   132         val RCs_rhs' = find_calls2 fvar rhs'
       
   133       in
       
   134         Logic.mk_implies
       
   135           (HOLogic.mk_Trueprop (HOLogic.eq_const domT $ shift lhs $ lhs'),
       
   136             HOLogic.mk_Trueprop (HOLogic.eq_const ranT $ shift rhs $ rhs'))
       
   137         |> fold_rev (curry Logic.mk_implies) (map shift gs @ gs')
       
   138         |> fold_rev (curry Logic.mk_implies) (map (shift o mk_eqvt_at) RCs_rhs) (* HERE *) 
       
   139         (*|> fold_rev (curry Logic.mk_implies) (map mk_eqvt_at RCs_rhs')*) (* HERE *) 
       
   140         |> fold_rev (fn (n,T) => fn b => Term.all T $ Abs(n,T,b)) (qs @ qs')
       
   141         |> curry abstract_over fvar
       
   142         |> curry subst_bound f
       
   143       end
       
   144   in
       
   145     map mk_impl (unordered_pairs glrs)
       
   146   end
       
   147 *}
       
   148 
       
   149 ML {*
       
   150 fun mk_completeness (Globals {x, Pbool, ...}) clauses qglrs =
       
   151   let
       
   152     fun mk_case (ClauseContext {qs, gs, lhs, ...}, (oqs, _, _, _)) =
       
   153       HOLogic.mk_Trueprop Pbool
       
   154       |> curry Logic.mk_implies (HOLogic.mk_Trueprop (mk_eq (x, lhs)))
       
   155       |> fold_rev (curry Logic.mk_implies) gs
       
   156       |> fold_rev mk_forall_rename (map fst oqs ~~ qs)
       
   157   in
       
   158     HOLogic.mk_Trueprop Pbool
       
   159     |> fold_rev (curry Logic.mk_implies o mk_case) (clauses ~~ qglrs)
       
   160     |> mk_forall_rename ("x", x)
       
   161     |> mk_forall_rename ("P", Pbool)
       
   162   end
       
   163 *}
       
   164 
       
   165 (** making a context with it's own local bindings **)
       
   166 ML {*
       
   167 
       
   168 fun mk_clause_context x ctxt (pre_qs,pre_gs,pre_lhs,pre_rhs) =
       
   169   let
       
   170     val (qs, ctxt') = Variable.variant_fixes (map fst pre_qs) ctxt
       
   171       |>> map2 (fn (_, T) => fn n => Free (n, T)) pre_qs
       
   172 
       
   173     val thy = ProofContext.theory_of ctxt'
       
   174 
       
   175     fun inst t = subst_bounds (rev qs, t)
       
   176     val gs = map inst pre_gs
       
   177     val lhs = inst pre_lhs
       
   178     val rhs = inst pre_rhs
       
   179 
       
   180     val cqs = map (cterm_of thy) qs
       
   181     val ags = map (Thm.assume o cterm_of thy) gs
       
   182 
       
   183     val case_hyp = Thm.assume (cterm_of thy (HOLogic.mk_Trueprop (mk_eq (x, lhs))))
       
   184   in
       
   185     ClauseContext { ctxt = ctxt', qs = qs, gs = gs, lhs = lhs, rhs = rhs,
       
   186       cqs = cqs, ags = ags, case_hyp = case_hyp }
       
   187   end
       
   188 *}
       
   189 
       
   190 ML {*
       
   191 (* lowlevel term function. FIXME: remove *)
       
   192 fun abstract_over_list vs body =
       
   193   let
       
   194     fun abs lev v tm =
       
   195       if v aconv tm then Bound lev
       
   196       else
       
   197         (case tm of
       
   198           Abs (a, T, t) => Abs (a, T, abs (lev + 1) v t)
       
   199         | t $ u => abs lev v t $ abs lev v u
       
   200         | t => t)
       
   201   in
       
   202     fold_index (fn (i, v) => fn t => abs i v t) vs body
       
   203   end
       
   204 
       
   205 
       
   206 
       
   207 fun mk_clause_info globals G f no cdata qglr tree RCs GIntro_thm RIntro_thms =
       
   208   let
       
   209     val Globals {h, ...} = globals
       
   210 
       
   211     val ClauseContext { ctxt, qs, cqs, ags, ... } = cdata
       
   212     val cert = Thm.cterm_of (ProofContext.theory_of ctxt)
       
   213 
       
   214     (* Instantiate the GIntro thm with "f" and import into the clause context. *)
       
   215     val lGI = GIntro_thm
       
   216       |> Thm.forall_elim (cert f)
       
   217       |> fold Thm.forall_elim cqs
       
   218       |> fold Thm.elim_implies ags
       
   219 
       
   220     fun mk_call_info (rcfix, rcassm, rcarg) RI =
       
   221       let
       
   222         val llRI = RI
       
   223           |> fold Thm.forall_elim cqs
       
   224           |> fold (Thm.forall_elim o cert o Free) rcfix
       
   225           |> fold Thm.elim_implies ags
       
   226           |> fold Thm.elim_implies rcassm
       
   227 
       
   228         val h_assum =
       
   229           HOLogic.mk_Trueprop (G $ rcarg $ (h $ rcarg))
       
   230           |> fold_rev (curry Logic.mk_implies o prop_of) rcassm
       
   231           |> fold_rev (Logic.all o Free) rcfix
       
   232           |> Pattern.rewrite_term (ProofContext.theory_of ctxt) [(f, h)] []
       
   233           |> abstract_over_list (rev qs)
       
   234       in
       
   235         RCInfo {RIvs=rcfix, rcarg=rcarg, CCas=rcassm, llRI=llRI, h_assum=h_assum}
       
   236       end
       
   237 
       
   238     val RC_infos = map2 mk_call_info RCs RIntro_thms
       
   239   in
       
   240     ClauseInfo {no=no, cdata=cdata, qglr=qglr, lGI=lGI, RCs=RC_infos,
       
   241       tree=tree}
       
   242   end
       
   243 *}
       
   244 
       
   245 ML {*
       
   246 fun store_compat_thms 0 thms = []
       
   247   | store_compat_thms n thms =
       
   248   let
       
   249     val (thms1, thms2) = chop n thms
       
   250   in
       
   251     (thms1 :: store_compat_thms (n - 1) thms2)
       
   252   end
       
   253 *}
       
   254 
       
   255 ML {*
       
   256 (* expects i <= j *)
       
   257 fun lookup_compat_thm i j cts =
       
   258   nth (nth cts (i - 1)) (j - i)
       
   259 
       
   260 (* Returns "Gsi, Gsj, lhs_i = lhs_j |-- rhs_j_f = rhs_i_f" *)
       
   261 (* if j < i, then turn around *)
       
   262 fun get_compat_thm thy cts eqvtsi eqvtsj i j ctxi ctxj =
       
   263   let
       
   264     val ClauseContext {cqs=cqsi,ags=agsi,lhs=lhsi,...} = ctxi
       
   265     val ClauseContext {cqs=cqsj,ags=agsj,lhs=lhsj,...} = ctxj
       
   266 
       
   267     val lhsi_eq_lhsj = cterm_of thy (HOLogic.mk_Trueprop (mk_eq (lhsi, lhsj)))
       
   268   in if j < i then
       
   269     let
       
   270       val compat = lookup_compat_thm j i cts
       
   271     in
       
   272       compat         (* "!!qj qi. Gsj => Gsi => lhsj = lhsi ==> rhsj = rhsi" *)
       
   273       |> fold Thm.forall_elim (cqsj @ cqsi) (* "Gsj => Gsi => lhsj = lhsi ==> rhsj = rhsi" *)
       
   274       |> fold Thm.elim_implies (rev eqvtsj) (* HERE *)
       
   275       |> fold Thm.elim_implies agsj
       
   276       |> fold Thm.elim_implies agsi
       
   277       |> Thm.elim_implies ((Thm.assume lhsi_eq_lhsj) RS sym) (* "Gsj, Gsi, lhsi = lhsj |-- rhsj = rhsi" *)
       
   278     end
       
   279     else
       
   280     let
       
   281       val compat = lookup_compat_thm i j cts
       
   282     in
       
   283       compat        (* "!!qi qj. Gsi => Gsj => lhsi = lhsj ==> rhsi = rhsj" *)
       
   284       |> fold Thm.forall_elim (cqsi @ cqsj) (* "Gsi => Gsj => lhsi = lhsj ==> rhsi = rhsj" *)
       
   285       |> fold Thm.elim_implies (rev eqvtsi)  (* HERE *)
       
   286       |> fold Thm.elim_implies agsi
       
   287       |> fold Thm.elim_implies agsj
       
   288       |> Thm.elim_implies (Thm.assume lhsi_eq_lhsj)
       
   289       |> (fn thm => thm RS sym) (* "Gsi, Gsj, lhsi = lhsj |-- rhsj = rhsi" *)
       
   290     end
       
   291   end
       
   292 *}
       
   293 
       
   294 
       
   295 ML {*
       
   296 (* Generates the replacement lemma in fully quantified form. *)
       
   297 fun mk_replacement_lemma thy h ih_elim clause =
       
   298   let
       
   299     val ClauseInfo {cdata=ClauseContext {qs, cqs, ags, case_hyp, ...},
       
   300       RCs, tree, ...} = clause
       
   301     local open Conv in
       
   302       val ih_conv = arg1_conv o arg_conv o arg_conv
       
   303     end
       
   304 
       
   305     val ih_elim_case =
       
   306       Conv.fconv_rule (ih_conv (K (case_hyp RS eq_reflection))) ih_elim
       
   307 
       
   308     val Ris = map (fn RCInfo {llRI, ...} => llRI) RCs
       
   309     val h_assums = map (fn RCInfo {h_assum, ...} =>
       
   310       Thm.assume (cterm_of thy (subst_bounds (rev qs, h_assum)))) RCs
       
   311 
       
   312     val (eql, _) =
       
   313       Function_Ctx_Tree.rewrite_by_tree thy h ih_elim_case (Ris ~~ h_assums) tree
       
   314 
       
   315     val replace_lemma = (eql RS meta_eq_to_obj_eq)
       
   316       |> Thm.implies_intr (cprop_of case_hyp)
       
   317       |> fold_rev (Thm.implies_intr o cprop_of) h_assums
       
   318       |> fold_rev (Thm.implies_intr o cprop_of) ags
       
   319       |> fold_rev Thm.forall_intr cqs
       
   320       |> Thm.close_derivation
       
   321   in
       
   322     replace_lemma
       
   323   end
       
   324 *}
       
   325 
       
   326 ML {*
       
   327 fun mk_eqvt_lemma thy ih_eqvt clause =
       
   328   let
       
   329     val ClauseInfo {cdata=ClauseContext {cqs, ags, case_hyp, ...}, RCs, ...} = clause
       
   330 
       
   331     local open Conv in
       
   332       val ih_conv = arg1_conv o arg_conv o arg_conv
       
   333     end
       
   334 
       
   335     val ih_eqvt_case =
       
   336       Conv.fconv_rule (ih_conv (K (case_hyp RS eq_reflection))) ih_eqvt
       
   337 
       
   338     fun prep_eqvt (RCInfo {llRI, RIvs, CCas, ...}) = 
       
   339         (llRI RS ih_eqvt_case)
       
   340         |> fold_rev (Thm.implies_intr o cprop_of) CCas
       
   341         |> fold_rev (Thm.forall_intr o cterm_of thy o Free) RIvs
       
   342   in
       
   343     map prep_eqvt RCs
       
   344     |> map (fold_rev (Thm.implies_intr o cprop_of) ags)
       
   345     |> map (Thm.implies_intr (cprop_of case_hyp))
       
   346     |> map (fold_rev Thm.forall_intr cqs)
       
   347     |> map (Thm.close_derivation) 
       
   348   end
       
   349 *}
       
   350 
       
   351 ML {*
       
   352 fun mk_uniqueness_clause thy globals compat_store eqvts clausei clausej RLj =
       
   353   let
       
   354     val Globals {h, y, x, fvar, ...} = globals
       
   355     val ClauseInfo {no=i, cdata=cctxi as ClauseContext {ctxt=ctxti, lhs=lhsi, case_hyp, cqs = cqsi, 
       
   356       ags = agsi, ...}, ...} = clausei
       
   357     val ClauseInfo {no=j, qglr=cdescj, RCs=RCsj, ...} = clausej
       
   358 
       
   359     val cctxj as ClauseContext {ags = agsj', lhs = lhsj', rhs = rhsj', qs = qsj', cqs = cqsj', ...} =
       
   360       mk_clause_context x ctxti cdescj 
       
   361 
       
   362     val rhsj'h = Pattern.rewrite_term thy [(fvar,h)] [] rhsj'
       
   363 
       
   364     val Ghsj' = map 
       
   365       (fn RCInfo {h_assum, ...} => Thm.assume (cterm_of thy (subst_bounds (rev qsj', h_assum)))) RCsj
       
   366 
       
   367     val y_eq_rhsj'h = Thm.assume (cterm_of thy (HOLogic.mk_Trueprop (mk_eq (y, rhsj'h))))
       
   368     val lhsi_eq_lhsj' = Thm.assume (cterm_of thy (HOLogic.mk_Trueprop (mk_eq (lhsi, lhsj'))))
       
   369        (* lhs_i = lhs_j' |-- lhs_i = lhs_j' *) 
       
   370 
       
   371     val case_hypj' = trans OF [case_hyp, lhsi_eq_lhsj']
       
   372 
       
   373     val RLj_import = RLj
       
   374       |> fold Thm.forall_elim cqsj'
       
   375       |> fold Thm.elim_implies agsj'
       
   376       |> fold Thm.elim_implies Ghsj'
       
   377 
       
   378     val eqvtsi = nth eqvts (i - 1)
       
   379       |> map (fold Thm.forall_elim cqsi)
       
   380       |> map (fold Thm.elim_implies [case_hyp])
       
   381       |> map (fold Thm.elim_implies agsi)
       
   382 
       
   383     val eqvtsj = nth eqvts (j - 1)
       
   384       |> map (fold Thm.forall_elim cqsj')
       
   385       |> map (fold Thm.elim_implies [case_hypj'])
       
   386       |> map (fold Thm.elim_implies agsj')
       
   387 
       
   388     val compat = get_compat_thm thy compat_store eqvtsi eqvtsj i j cctxi cctxj
       
   389 
       
   390   in
       
   391     (trans OF [case_hyp, lhsi_eq_lhsj']) (* lhs_i = lhs_j' |-- x = lhs_j' *)
       
   392     |> Thm.implies_elim RLj_import
       
   393       (* Rj1' ... Rjk', lhs_i = lhs_j' |-- rhs_j'_h = rhs_j'_f *)
       
   394     |> (fn it => trans OF [it, compat])
       
   395       (* lhs_i = lhs_j', Gj', Rj1' ... Rjk' |-- rhs_j'_h = rhs_i_f *)
       
   396     |> (fn it => trans OF [y_eq_rhsj'h, it])
       
   397       (* lhs_i = lhs_j', Gj', Rj1' ... Rjk', y = rhs_j_h' |-- y = rhs_i_f *)
       
   398     |> fold_rev (Thm.implies_intr o cprop_of) Ghsj'
       
   399     |> fold_rev (Thm.implies_intr o cprop_of) agsj'
       
   400       (* lhs_i = lhs_j' , y = rhs_j_h' |-- Gj', Rj1'...Rjk' ==> y = rhs_i_f *)
       
   401     |> Thm.implies_intr (cprop_of y_eq_rhsj'h)
       
   402     |> Thm.implies_intr (cprop_of lhsi_eq_lhsj')
       
   403     |> fold_rev Thm.forall_intr (cterm_of thy h :: cqsj')
       
   404   end
       
   405 *}
       
   406 
       
   407 
       
   408 ML {*
       
   409 fun mk_uniqueness_case thy globals G f ihyp ih_intro G_cases compat_store clauses replems eqvtlems clausei =
       
   410   let
       
   411     val Globals {x, y, ranT, fvar, ...} = globals
       
   412     val ClauseInfo {cdata = ClauseContext {lhs, rhs, cqs, ags, case_hyp, ...}, lGI, RCs, ...} = clausei
       
   413     val rhsC = Pattern.rewrite_term thy [(fvar, f)] [] rhs
       
   414 
       
   415     val ih_intro_case = full_simplify (HOL_basic_ss addsimps [case_hyp]) ih_intro
       
   416 
       
   417     fun prep_RC (RCInfo {llRI, RIvs, CCas, ...}) = 
       
   418         (llRI RS ih_intro_case)
       
   419         |> fold_rev (Thm.implies_intr o cprop_of) CCas
       
   420         |> fold_rev (Thm.forall_intr o cterm_of thy o Free) RIvs
       
   421 
       
   422     val existence = fold (curry op COMP o prep_RC) RCs lGI
       
   423 
       
   424     val P = cterm_of thy (mk_eq (y, rhsC))
       
   425     val G_lhs_y = Thm.assume (cterm_of thy (HOLogic.mk_Trueprop (G $ lhs $ y)))
       
   426 
       
   427     val unique_clauses =
       
   428       map2 (mk_uniqueness_clause thy globals compat_store eqvtlems clausei) clauses replems
       
   429 
       
   430     fun elim_implies_eta A AB =
       
   431       Thm.compose_no_flatten true (A, 0) 1 AB |> Seq.list_of |> the_single
       
   432 
       
   433     val uniqueness = G_cases
       
   434       |> Thm.forall_elim (cterm_of thy lhs)
       
   435       |> Thm.forall_elim (cterm_of thy y)
       
   436       |> Thm.forall_elim P
       
   437       |> Thm.elim_implies G_lhs_y
       
   438       |> fold elim_implies_eta unique_clauses
       
   439       |> Thm.implies_intr (cprop_of G_lhs_y)
       
   440       |> Thm.forall_intr (cterm_of thy y)
       
   441 
       
   442     val P2 = cterm_of thy (lambda y (G $ lhs $ y)) (* P2 y := (lhs, y): G *)
       
   443 
       
   444     val exactly_one =
       
   445       ex1I |> instantiate' [SOME (ctyp_of thy ranT)] [SOME P2, SOME (cterm_of thy rhsC)]
       
   446       |> curry (op COMP) existence
       
   447       |> curry (op COMP) uniqueness
       
   448       |> simplify (HOL_basic_ss addsimps [case_hyp RS sym])
       
   449       |> Thm.implies_intr (cprop_of case_hyp)
       
   450       |> fold_rev (Thm.implies_intr o cprop_of) ags
       
   451       |> fold_rev Thm.forall_intr cqs
       
   452 
       
   453     val function_value =
       
   454       existence
       
   455       |> Thm.implies_intr ihyp
       
   456       |> Thm.implies_intr (cprop_of case_hyp)
       
   457       |> Thm.forall_intr (cterm_of thy x)
       
   458       |> Thm.forall_elim (cterm_of thy lhs)
       
   459       |> curry (op RS) refl
       
   460   in
       
   461     (exactly_one, function_value)
       
   462   end
       
   463 *}
       
   464 
       
   465 
       
   466 ML {*
       
   467 fun prove_stuff ctxt globals G f R clauses complete compat compat_store G_elim G_eqvt f_def =
       
   468   let
       
   469     val Globals {h, domT, ranT, x, ...} = globals
       
   470     val thy = ProofContext.theory_of ctxt
       
   471 
       
   472     (* Inductive Hypothesis: !!z. (z,x):R ==> EX!y. (z,y):G *)
       
   473     val ihyp = Term.all domT $ Abs ("z", domT,
       
   474       Logic.mk_implies (HOLogic.mk_Trueprop (R $ Bound 0 $ x),
       
   475         HOLogic.mk_Trueprop (Const (@{const_name Ex1}, (ranT --> boolT) --> boolT) $
       
   476           Abs ("y", ranT, G $ Bound 1 $ Bound 0))))
       
   477       |> cterm_of thy
       
   478 
       
   479     val ihyp_thm = Thm.assume ihyp |> Thm.forall_elim_vars 0
       
   480     val ih_intro = ihyp_thm RS (f_def RS ex1_implies_ex)
       
   481     val ih_elim = ihyp_thm RS (f_def RS ex1_implies_un)
       
   482       |> instantiate' [] [NONE, SOME (cterm_of thy h)]
       
   483     val ih_eqvt = ihyp_thm RS (G_eqvt RS (f_def RS @{thm fundef_ex1_eqvt_at}))
       
   484 
       
   485     val _ = trace_msg (K "Proving Replacement lemmas...")
       
   486     val repLemmas = map (mk_replacement_lemma thy h ih_elim) clauses
       
   487 
       
   488     val _ = trace_msg (K "Proving Equivariance lemmas...")
       
   489     val eqvtLemmas = map (mk_eqvt_lemma thy ih_eqvt) clauses
       
   490 
       
   491     val _ = trace_msg (K "Proving cases for unique existence...")
       
   492     val (ex1s, values) =
       
   493       split_list (map (mk_uniqueness_case thy globals G f 
       
   494         ihyp ih_intro G_elim compat_store clauses repLemmas eqvtLemmas) clauses)
       
   495      
       
   496     val _ = trace_msg (K "Proving: Graph is a function")
       
   497     val graph_is_function = complete
       
   498       |> Thm.forall_elim_vars 0
       
   499       |> fold (curry op COMP) ex1s
       
   500       |> Thm.implies_intr (ihyp)
       
   501       |> Thm.implies_intr (cterm_of thy (HOLogic.mk_Trueprop (mk_acc domT R $ x)))
       
   502       |> Thm.forall_intr (cterm_of thy x)
       
   503       |> (fn it => Drule.compose_single (it, 2, acc_induct_rule)) (* "EX! y. (?x,y):G" *)
       
   504       |> (fn it => fold (Thm.forall_intr o cterm_of thy o Var) (Term.add_vars (prop_of it) []) it)
       
   505 
       
   506     val goalstate =  Conjunction.intr graph_is_function complete
       
   507       |> Thm.close_derivation
       
   508       |> Goal.protect
       
   509       |> fold_rev (Thm.implies_intr o cprop_of) compat
       
   510       |> Thm.implies_intr (cprop_of complete)
       
   511   in
       
   512     (goalstate, values)
       
   513   end
       
   514 *}
       
   515 
       
   516 
       
   517 ML {*
       
   518 (* wrapper -- restores quantifiers in rule specifications *)
       
   519 fun inductive_def eqvt_flag (binding as ((R, T), _)) intrs lthy =
       
   520   let
       
   521     val ({intrs = intrs_gen, elims = [elim_gen], preds = [ Rdef ], induct, raw_induct, ...}, lthy) =
       
   522       lthy
       
   523       |> Local_Theory.conceal 
       
   524       |> Inductive.add_inductive_i
       
   525           {quiet_mode = true,
       
   526             verbose = ! trace,
       
   527             alt_name = Binding.empty,
       
   528             coind = false,
       
   529             no_elim = false,
       
   530             no_ind = false,
       
   531             skip_mono = true,
       
   532             fork_mono = false}
       
   533           [binding] (* relation *)
       
   534           [] (* no parameters *)
       
   535           (map (fn t => (Attrib.empty_binding, t)) intrs) (* intro rules *)
       
   536           [] (* no special monos *)
       
   537       ||> Local_Theory.restore_naming lthy
       
   538 
       
   539     val eqvt_thm' = 
       
   540       if eqvt_flag = false then NONE
       
   541       else 
       
   542         let
       
   543           val ([eqvt_thm], lthy) = Nominal_Eqvt.raw_equivariance false [Rdef] raw_induct intrs_gen lthy
       
   544         in
       
   545           SOME ((Nominal_ThmDecls.eqvt_transform lthy eqvt_thm) RS @{thm eqvtI})
       
   546         end
       
   547 
       
   548     val cert = cterm_of (ProofContext.theory_of lthy)
       
   549     fun requantify orig_intro thm =
       
   550       let
       
   551         val (qs, t) = dest_all_all orig_intro
       
   552         val frees = frees_in_term lthy t |> remove (op =) (Binding.name_of R, T)
       
   553         val vars = Term.add_vars (prop_of thm) [] |> rev
       
   554         val varmap = AList.lookup (op =) (frees ~~ map fst vars)
       
   555           #> the_default ("",0)
       
   556       in
       
   557         fold_rev (fn Free (n, T) =>
       
   558           forall_intr_rename (n, cert (Var (varmap (n, T), T)))) qs thm
       
   559       end
       
   560   in
       
   561     ((Rdef, map2 requantify intrs intrs_gen, forall_intr_vars elim_gen, induct, eqvt_thm'), lthy)
       
   562   end
       
   563 *}
       
   564 
       
   565 ML {*
       
   566 fun define_graph Gname fvar domT ranT clauses RCss lthy =
       
   567   let
       
   568     val GT = domT --> ranT --> boolT
       
   569     val (Gvar as (n, T)) = singleton (Variable.variant_frees lthy []) (Gname, GT)
       
   570 
       
   571     fun mk_GIntro (ClauseContext {qs, gs, lhs, rhs, ...}) RCs =
       
   572       let
       
   573         fun mk_h_assm (rcfix, rcassm, rcarg) =
       
   574           HOLogic.mk_Trueprop (Free Gvar $ rcarg $ (fvar $ rcarg))
       
   575           |> fold_rev (curry Logic.mk_implies o prop_of) rcassm
       
   576           |> fold_rev (Logic.all o Free) rcfix
       
   577       in
       
   578         HOLogic.mk_Trueprop (Free Gvar $ lhs $ rhs)
       
   579         |> fold_rev (curry Logic.mk_implies o mk_h_assm) RCs
       
   580         |> fold_rev (curry Logic.mk_implies) gs
       
   581         |> fold_rev Logic.all (fvar :: qs)
       
   582       end
       
   583 
       
   584     val G_intros = map2 mk_GIntro clauses RCss
       
   585   in
       
   586     inductive_def true ((Binding.name n, T), NoSyn) G_intros lthy
       
   587   end
       
   588 *}
       
   589 
       
   590 ML {*
       
   591 fun define_function fdefname (fname, mixfix) domT ranT G default lthy =
       
   592   let
       
   593     val f_def =
       
   594       Abs ("x", domT, Const (@{const_name FunDef.THE_default}, ranT --> (ranT --> boolT) --> ranT) 
       
   595         $ (default $ Bound 0) $ Abs ("y", ranT, G $ Bound 1 $ Bound 0))
       
   596       |> Syntax.check_term lthy
       
   597   in
       
   598     Local_Theory.define
       
   599       ((Binding.name (function_name fname), mixfix),
       
   600         ((Binding.conceal (Binding.name fdefname), []), f_def)) lthy
       
   601   end
       
   602 
       
   603 fun define_recursion_relation Rname domT qglrs clauses RCss lthy =
       
   604   let
       
   605     val RT = domT --> domT --> boolT
       
   606     val (Rvar as (n, T)) = singleton (Variable.variant_frees lthy []) (Rname, RT)
       
   607 
       
   608     fun mk_RIntro (ClauseContext {qs, gs, lhs, ...}, (oqs, _, _, _)) (rcfix, rcassm, rcarg) =
       
   609       HOLogic.mk_Trueprop (Free Rvar $ rcarg $ lhs)
       
   610       |> fold_rev (curry Logic.mk_implies o prop_of) rcassm
       
   611       |> fold_rev (curry Logic.mk_implies) gs
       
   612       |> fold_rev (Logic.all o Free) rcfix
       
   613       |> fold_rev mk_forall_rename (map fst oqs ~~ qs)
       
   614       (* "!!qs xs. CS ==> G => (r, lhs) : R" *)
       
   615 
       
   616     val R_intross = map2 (map o mk_RIntro) (clauses ~~ qglrs) RCss
       
   617 
       
   618     val ((R, RIntro_thms, R_elim, _, _), lthy) =
       
   619       inductive_def false ((Binding.name n, T), NoSyn) (flat R_intross) lthy
       
   620   in
       
   621     ((R, Library.unflat R_intross RIntro_thms, R_elim), lthy)
       
   622   end
       
   623 
       
   624 
       
   625 fun fix_globals domT ranT fvar ctxt =
       
   626   let
       
   627     val ([h, y, x, z, a, D, P, Pbool],ctxt') = Variable.variant_fixes
       
   628       ["h_fd", "y_fd", "x_fd", "z_fd", "a_fd", "D_fd", "P_fd", "Pb_fd"] ctxt
       
   629   in
       
   630     (Globals {h = Free (h, domT --> ranT),
       
   631       y = Free (y, ranT),
       
   632       x = Free (x, domT),
       
   633       z = Free (z, domT),
       
   634       a = Free (a, domT),
       
   635       D = Free (D, domT --> boolT),
       
   636       P = Free (P, domT --> boolT),
       
   637       Pbool = Free (Pbool, boolT),
       
   638       fvar = fvar,
       
   639       domT = domT,
       
   640       ranT = ranT},
       
   641     ctxt')
       
   642   end
       
   643 
       
   644 fun inst_RC thy fvar f (rcfix, rcassm, rcarg) =
       
   645   let
       
   646     fun inst_term t = subst_bound(f, abstract_over (fvar, t))
       
   647   in
       
   648     (rcfix, map (Thm.assume o cterm_of thy o inst_term o prop_of) rcassm, inst_term rcarg)
       
   649   end
       
   650 
       
   651 
       
   652 
       
   653 (**********************************************************
       
   654  *                   PROVING THE RULES
       
   655  **********************************************************)
       
   656 
       
   657 fun mk_psimps thy globals R clauses valthms f_iff graph_is_function =
       
   658   let
       
   659     val Globals {domT, z, ...} = globals
       
   660 
       
   661     fun mk_psimp (ClauseInfo {qglr = (oqs, _, _, _), cdata = ClauseContext {cqs, lhs, ags, ...}, ...}) valthm =
       
   662       let
       
   663         val lhs_acc = cterm_of thy (HOLogic.mk_Trueprop (mk_acc domT R $ lhs)) (* "acc R lhs" *)
       
   664         val z_smaller = cterm_of thy (HOLogic.mk_Trueprop (R $ z $ lhs)) (* "R z lhs" *)
       
   665       in
       
   666         ((Thm.assume z_smaller) RS ((Thm.assume lhs_acc) RS acc_downward))
       
   667         |> (fn it => it COMP graph_is_function)
       
   668         |> Thm.implies_intr z_smaller
       
   669         |> Thm.forall_intr (cterm_of thy z)
       
   670         |> (fn it => it COMP valthm)
       
   671         |> Thm.implies_intr lhs_acc
       
   672         |> asm_simplify (HOL_basic_ss addsimps [f_iff])
       
   673         |> fold_rev (Thm.implies_intr o cprop_of) ags
       
   674         |> fold_rev forall_intr_rename (map fst oqs ~~ cqs)
       
   675       end
       
   676   in
       
   677     map2 mk_psimp clauses valthms
       
   678   end
       
   679 
       
   680 
       
   681 (** Induction rule **)
       
   682 
       
   683 
       
   684 val acc_subset_induct = @{thm predicate1I} RS @{thm accp_subset_induct}
       
   685 
       
   686 
       
   687 fun mk_partial_induct_rule thy globals R complete_thm clauses =
       
   688   let
       
   689     val Globals {domT, x, z, a, P, D, ...} = globals
       
   690     val acc_R = mk_acc domT R
       
   691 
       
   692     val x_D = Thm.assume (cterm_of thy (HOLogic.mk_Trueprop (D $ x)))
       
   693     val a_D = cterm_of thy (HOLogic.mk_Trueprop (D $ a))
       
   694 
       
   695     val D_subset = cterm_of thy (Logic.all x
       
   696       (Logic.mk_implies (HOLogic.mk_Trueprop (D $ x), HOLogic.mk_Trueprop (acc_R $ x))))
       
   697 
       
   698     val D_dcl = (* "!!x z. [| x: D; (z,x):R |] ==> z:D" *)
       
   699       Logic.all x (Logic.all z (Logic.mk_implies (HOLogic.mk_Trueprop (D $ x),
       
   700         Logic.mk_implies (HOLogic.mk_Trueprop (R $ z $ x),
       
   701           HOLogic.mk_Trueprop (D $ z)))))
       
   702       |> cterm_of thy
       
   703 
       
   704     (* Inductive Hypothesis: !!z. (z,x):R ==> P z *)
       
   705     val ihyp = Term.all domT $ Abs ("z", domT,
       
   706       Logic.mk_implies (HOLogic.mk_Trueprop (R $ Bound 0 $ x),
       
   707         HOLogic.mk_Trueprop (P $ Bound 0)))
       
   708       |> cterm_of thy
       
   709 
       
   710     val aihyp = Thm.assume ihyp
       
   711 
       
   712     fun prove_case clause =
       
   713       let
       
   714         val ClauseInfo {cdata = ClauseContext {ctxt, qs, cqs, ags, gs, lhs, case_hyp, ...},
       
   715           RCs, qglr = (oqs, _, _, _), ...} = clause
       
   716 
       
   717         val case_hyp_conv = K (case_hyp RS eq_reflection)
       
   718         local open Conv in
       
   719           val lhs_D = fconv_rule (arg_conv (arg_conv (case_hyp_conv))) x_D
       
   720           val sih =
       
   721             fconv_rule (Conv.binder_conv
       
   722               (K (arg1_conv (arg_conv (arg_conv case_hyp_conv)))) ctxt) aihyp
       
   723         end
       
   724 
       
   725         fun mk_Prec (RCInfo {llRI, RIvs, CCas, rcarg, ...}) = sih
       
   726           |> Thm.forall_elim (cterm_of thy rcarg)
       
   727           |> Thm.elim_implies llRI
       
   728           |> fold_rev (Thm.implies_intr o cprop_of) CCas
       
   729           |> fold_rev (Thm.forall_intr o cterm_of thy o Free) RIvs
       
   730 
       
   731         val P_recs = map mk_Prec RCs   (*  [P rec1, P rec2, ... ]  *)
       
   732 
       
   733         val step = HOLogic.mk_Trueprop (P $ lhs)
       
   734           |> fold_rev (curry Logic.mk_implies o prop_of) P_recs
       
   735           |> fold_rev (curry Logic.mk_implies) gs
       
   736           |> curry Logic.mk_implies (HOLogic.mk_Trueprop (D $ lhs))
       
   737           |> fold_rev mk_forall_rename (map fst oqs ~~ qs)
       
   738           |> cterm_of thy
       
   739 
       
   740         val P_lhs = Thm.assume step
       
   741           |> fold Thm.forall_elim cqs
       
   742           |> Thm.elim_implies lhs_D
       
   743           |> fold Thm.elim_implies ags
       
   744           |> fold Thm.elim_implies P_recs
       
   745 
       
   746         val res = cterm_of thy (HOLogic.mk_Trueprop (P $ x))
       
   747           |> Conv.arg_conv (Conv.arg_conv case_hyp_conv)
       
   748           |> Thm.symmetric (* P lhs == P x *)
       
   749           |> (fn eql => Thm.equal_elim eql P_lhs) (* "P x" *)
       
   750           |> Thm.implies_intr (cprop_of case_hyp)
       
   751           |> fold_rev (Thm.implies_intr o cprop_of) ags
       
   752           |> fold_rev Thm.forall_intr cqs
       
   753       in
       
   754         (res, step)
       
   755       end
       
   756 
       
   757     val (cases, steps) = split_list (map prove_case clauses)
       
   758 
       
   759     val istep = complete_thm
       
   760       |> Thm.forall_elim_vars 0
       
   761       |> fold (curry op COMP) cases (*  P x  *)
       
   762       |> Thm.implies_intr ihyp
       
   763       |> Thm.implies_intr (cprop_of x_D)
       
   764       |> Thm.forall_intr (cterm_of thy x)
       
   765 
       
   766     val subset_induct_rule =
       
   767       acc_subset_induct
       
   768       |> (curry op COMP) (Thm.assume D_subset)
       
   769       |> (curry op COMP) (Thm.assume D_dcl)
       
   770       |> (curry op COMP) (Thm.assume a_D)
       
   771       |> (curry op COMP) istep
       
   772       |> fold_rev Thm.implies_intr steps
       
   773       |> Thm.implies_intr a_D
       
   774       |> Thm.implies_intr D_dcl
       
   775       |> Thm.implies_intr D_subset
       
   776 
       
   777     val simple_induct_rule =
       
   778       subset_induct_rule
       
   779       |> Thm.forall_intr (cterm_of thy D)
       
   780       |> Thm.forall_elim (cterm_of thy acc_R)
       
   781       |> assume_tac 1 |> Seq.hd
       
   782       |> (curry op COMP) (acc_downward
       
   783         |> (instantiate' [SOME (ctyp_of thy domT)]
       
   784              (map (SOME o cterm_of thy) [R, x, z]))
       
   785         |> Thm.forall_intr (cterm_of thy z)
       
   786         |> Thm.forall_intr (cterm_of thy x))
       
   787       |> Thm.forall_intr (cterm_of thy a)
       
   788       |> Thm.forall_intr (cterm_of thy P)
       
   789   in
       
   790     simple_induct_rule
       
   791   end
       
   792 
       
   793 
       
   794 (* FIXME: broken by design *)
       
   795 fun mk_domain_intro ctxt (Globals {domT, ...}) R R_cases clause =
       
   796   let
       
   797     val thy = ProofContext.theory_of ctxt
       
   798     val ClauseInfo {cdata = ClauseContext {gs, lhs, cqs, ...},
       
   799       qglr = (oqs, _, _, _), ...} = clause
       
   800     val goal = HOLogic.mk_Trueprop (mk_acc domT R $ lhs)
       
   801       |> fold_rev (curry Logic.mk_implies) gs
       
   802       |> cterm_of thy
       
   803   in
       
   804     Goal.init goal
       
   805     |> (SINGLE (resolve_tac [accI] 1)) |> the
       
   806     |> (SINGLE (eresolve_tac [Thm.forall_elim_vars 0 R_cases] 1))  |> the
       
   807     |> (SINGLE (auto_tac (clasimpset_of ctxt))) |> the
       
   808     |> Goal.conclude
       
   809     |> fold_rev forall_intr_rename (map fst oqs ~~ cqs)
       
   810   end
       
   811 
       
   812 
       
   813 
       
   814 (** Termination rule **)
       
   815 
       
   816 val wf_induct_rule = @{thm Wellfounded.wfP_induct_rule}
       
   817 val wf_in_rel = @{thm FunDef.wf_in_rel}
       
   818 val in_rel_def = @{thm FunDef.in_rel_def}
       
   819 
       
   820 fun mk_nest_term_case thy globals R' ihyp clause =
       
   821   let
       
   822     val Globals {z, ...} = globals
       
   823     val ClauseInfo {cdata = ClauseContext {qs, cqs, ags, lhs, case_hyp, ...}, tree,
       
   824       qglr=(oqs, _, _, _), ...} = clause
       
   825 
       
   826     val ih_case = full_simplify (HOL_basic_ss addsimps [case_hyp]) ihyp
       
   827 
       
   828     fun step (fixes, assumes) (_ $ arg) u (sub,(hyps,thms)) =
       
   829       let
       
   830         val used = (u @ sub)
       
   831           |> map (fn (ctx,thm) => Function_Ctx_Tree.export_thm thy ctx thm)
       
   832 
       
   833         val hyp = HOLogic.mk_Trueprop (R' $ arg $ lhs)
       
   834           |> fold_rev (curry Logic.mk_implies o prop_of) used (* additional hyps *)
       
   835           |> Function_Ctx_Tree.export_term (fixes, assumes)
       
   836           |> fold_rev (curry Logic.mk_implies o prop_of) ags
       
   837           |> fold_rev mk_forall_rename (map fst oqs ~~ qs)
       
   838           |> cterm_of thy
       
   839 
       
   840         val thm = Thm.assume hyp
       
   841           |> fold Thm.forall_elim cqs
       
   842           |> fold Thm.elim_implies ags
       
   843           |> Function_Ctx_Tree.import_thm thy (fixes, assumes)
       
   844           |> fold Thm.elim_implies used (*  "(arg, lhs) : R'"  *)
       
   845 
       
   846         val z_eq_arg = HOLogic.mk_Trueprop (mk_eq (z, arg))
       
   847           |> cterm_of thy |> Thm.assume
       
   848 
       
   849         val acc = thm COMP ih_case
       
   850         val z_acc_local = acc
       
   851           |> Conv.fconv_rule
       
   852               (Conv.arg_conv (Conv.arg_conv (K (Thm.symmetric (z_eq_arg RS eq_reflection)))))
       
   853 
       
   854         val ethm = z_acc_local
       
   855           |> Function_Ctx_Tree.export_thm thy (fixes,
       
   856                z_eq_arg :: case_hyp :: ags @ assumes)
       
   857           |> fold_rev forall_intr_rename (map fst oqs ~~ cqs)
       
   858 
       
   859         val sub' = sub @ [(([],[]), acc)]
       
   860       in
       
   861         (sub', (hyp :: hyps, ethm :: thms))
       
   862       end
       
   863       | step _ _ _ _ = raise Match
       
   864   in
       
   865     Function_Ctx_Tree.traverse_tree step tree
       
   866   end
       
   867 
       
   868 
       
   869 fun mk_nest_term_rule thy globals R R_cases clauses =
       
   870   let
       
   871     val Globals { domT, x, z, ... } = globals
       
   872     val acc_R = mk_acc domT R
       
   873 
       
   874     val R' = Free ("R", fastype_of R)
       
   875 
       
   876     val Rrel = Free ("R", HOLogic.mk_setT (HOLogic.mk_prodT (domT, domT)))
       
   877     val inrel_R = Const (@{const_name FunDef.in_rel},
       
   878       HOLogic.mk_setT (HOLogic.mk_prodT (domT, domT)) --> fastype_of R) $ Rrel
       
   879 
       
   880     val wfR' = HOLogic.mk_Trueprop (Const (@{const_name Wellfounded.wfP},
       
   881       (domT --> domT --> boolT) --> boolT) $ R')
       
   882       |> cterm_of thy (* "wf R'" *)
       
   883 
       
   884     (* Inductive Hypothesis: !!z. (z,x):R' ==> z : acc R *)
       
   885     val ihyp = Term.all domT $ Abs ("z", domT,
       
   886       Logic.mk_implies (HOLogic.mk_Trueprop (R' $ Bound 0 $ x),
       
   887         HOLogic.mk_Trueprop (acc_R $ Bound 0)))
       
   888       |> cterm_of thy
       
   889 
       
   890     val ihyp_a = Thm.assume ihyp |> Thm.forall_elim_vars 0
       
   891 
       
   892     val R_z_x = cterm_of thy (HOLogic.mk_Trueprop (R $ z $ x))
       
   893 
       
   894     val (hyps, cases) = fold (mk_nest_term_case thy globals R' ihyp_a) clauses ([], [])
       
   895   in
       
   896     R_cases
       
   897     |> Thm.forall_elim (cterm_of thy z)
       
   898     |> Thm.forall_elim (cterm_of thy x)
       
   899     |> Thm.forall_elim (cterm_of thy (acc_R $ z))
       
   900     |> curry op COMP (Thm.assume R_z_x)
       
   901     |> fold_rev (curry op COMP) cases
       
   902     |> Thm.implies_intr R_z_x
       
   903     |> Thm.forall_intr (cterm_of thy z)
       
   904     |> (fn it => it COMP accI)
       
   905     |> Thm.implies_intr ihyp
       
   906     |> Thm.forall_intr (cterm_of thy x)
       
   907     |> (fn it => Drule.compose_single(it,2,wf_induct_rule))
       
   908     |> curry op RS (Thm.assume wfR')
       
   909     |> forall_intr_vars
       
   910     |> (fn it => it COMP allI)
       
   911     |> fold Thm.implies_intr hyps
       
   912     |> Thm.implies_intr wfR'
       
   913     |> Thm.forall_intr (cterm_of thy R')
       
   914     |> Thm.forall_elim (cterm_of thy (inrel_R))
       
   915     |> curry op RS wf_in_rel
       
   916     |> full_simplify (HOL_basic_ss addsimps [in_rel_def])
       
   917     |> Thm.forall_intr (cterm_of thy Rrel)
       
   918   end
       
   919 
       
   920 
       
   921 
       
   922 (* Tail recursion (probably very fragile)
       
   923  *
       
   924  * FIXME:
       
   925  * - Need to do forall_elim_vars on psimps: Unneccesary, if psimps would be taken from the same context.
       
   926  * - Must we really replace the fvar by f here?
       
   927  * - Splitting is not configured automatically: Problems with case?
       
   928  *)
       
   929 fun mk_trsimps octxt globals f G R f_def R_cases G_induct clauses psimps =
       
   930   let
       
   931     val Globals {domT, ranT, fvar, ...} = globals
       
   932 
       
   933     val R_cases = Thm.forall_elim_vars 0 R_cases (* FIXME: Should be already in standard form. *)
       
   934 
       
   935     val graph_implies_dom = (* "G ?x ?y ==> dom ?x"  *)
       
   936       Goal.prove octxt ["x", "y"] [HOLogic.mk_Trueprop (G $ Free ("x", domT) $ Free ("y", ranT))]
       
   937         (HOLogic.mk_Trueprop (mk_acc domT R $ Free ("x", domT)))
       
   938         (fn {prems=[a], ...} =>
       
   939           ((rtac (G_induct OF [a]))
       
   940           THEN_ALL_NEW rtac accI
       
   941           THEN_ALL_NEW etac R_cases
       
   942           THEN_ALL_NEW asm_full_simp_tac (simpset_of octxt)) 1)
       
   943 
       
   944     val default_thm =
       
   945       forall_intr_vars graph_implies_dom COMP (f_def COMP fundef_default_value)
       
   946 
       
   947     fun mk_trsimp clause psimp =
       
   948       let
       
   949         val ClauseInfo {qglr = (oqs, _, _, _), cdata =
       
   950           ClauseContext {ctxt, cqs, gs, lhs, rhs, ...}, ...} = clause
       
   951         val thy = ProofContext.theory_of ctxt
       
   952         val rhs_f = Pattern.rewrite_term thy [(fvar, f)] [] rhs
       
   953 
       
   954         val trsimp = Logic.list_implies(gs,
       
   955           HOLogic.mk_Trueprop (HOLogic.mk_eq(f $ lhs, rhs_f))) (* "f lhs = rhs" *)
       
   956         val lhs_acc = (mk_acc domT R $ lhs) (* "acc R lhs" *)
       
   957         fun simp_default_tac ss =
       
   958           asm_full_simp_tac (ss addsimps [default_thm, Let_def])
       
   959       in
       
   960         Goal.prove ctxt [] [] trsimp (fn _ =>
       
   961           rtac (instantiate' [] [SOME (cterm_of thy lhs_acc)] case_split) 1
       
   962           THEN (rtac (Thm.forall_elim_vars 0 psimp) THEN_ALL_NEW assume_tac) 1
       
   963           THEN (simp_default_tac (simpset_of ctxt) 1)
       
   964           THEN TRY ((etac not_acc_down 1)
       
   965             THEN ((etac R_cases)
       
   966               THEN_ALL_NEW (simp_default_tac (simpset_of ctxt))) 1))
       
   967         |> fold_rev forall_intr_rename (map fst oqs ~~ cqs)
       
   968       end
       
   969   in
       
   970     map2 mk_trsimp clauses psimps
       
   971   end
       
   972 *}
       
   973 
       
   974 ML {*
       
   975 fun prepare_function config defname [((fname, fT), mixfix)] abstract_qglrs lthy =
       
   976   let
       
   977     val FunctionConfig {domintros, tailrec, default=default_opt, ...} = config
       
   978 
       
   979     val default_str = the_default "%x. undefined" default_opt (*FIXME dynamic scoping*)
       
   980     val fvar = Free (fname, fT)
       
   981     val domT = domain_type fT
       
   982     val ranT = range_type fT
       
   983 
       
   984     val default = Syntax.parse_term lthy default_str
       
   985       |> Type.constraint fT |> Syntax.check_term lthy
       
   986 
       
   987     val (globals, ctxt') = fix_globals domT ranT fvar lthy
       
   988 
       
   989     val Globals { x, h, ... } = globals
       
   990 
       
   991     val clauses = map (mk_clause_context x ctxt') abstract_qglrs
       
   992 
       
   993     val n = length abstract_qglrs
       
   994 
       
   995     fun build_tree (ClauseContext { ctxt, rhs, ...}) =
       
   996        Function_Ctx_Tree.mk_tree (fname, fT) h ctxt rhs
       
   997 
       
   998     val trees = map build_tree clauses
       
   999     val RCss = map find_calls trees
       
  1000 
       
  1001     val ((G, GIntro_thms, G_elim, G_induct, SOME G_eqvt), lthy) =
       
  1002       PROFILE "def_graph" (define_graph (graph_name defname) fvar domT ranT clauses RCss) lthy
       
  1003 
       
  1004     val ((f, (_, f_defthm)), lthy) =
       
  1005       PROFILE "def_fun" (define_function (defname ^ "_sumC_def") (fname, mixfix) domT ranT G default) lthy
       
  1006 
       
  1007     val RCss = map (map (inst_RC (ProofContext.theory_of lthy) fvar f)) RCss
       
  1008     val trees = map (Function_Ctx_Tree.inst_tree (ProofContext.theory_of lthy) fvar f) trees
       
  1009 
       
  1010     val ((R, RIntro_thmss, R_elim), lthy) =
       
  1011       PROFILE "def_rel" (define_recursion_relation (rel_name defname) domT abstract_qglrs clauses RCss) lthy
       
  1012 
       
  1013     val (_, lthy) =
       
  1014       Local_Theory.abbrev Syntax.mode_default ((Binding.name (dom_name defname), NoSyn), mk_acc domT R) lthy
       
  1015 
       
  1016     val newthy = ProofContext.theory_of lthy
       
  1017     val clauses = map (transfer_clause_ctx newthy) clauses
       
  1018 
       
  1019     val cert = cterm_of (ProofContext.theory_of lthy)
       
  1020 
       
  1021     val xclauses = PROFILE "xclauses"
       
  1022       (map7 (mk_clause_info globals G f) (1 upto n) clauses abstract_qglrs trees
       
  1023         RCss GIntro_thms) RIntro_thmss
       
  1024 
       
  1025     val complete =
       
  1026       mk_completeness globals clauses abstract_qglrs |> cert |> Thm.assume
       
  1027 
       
  1028     val compat =
       
  1029       mk_compat_proof_obligations domT ranT fvar f abstract_qglrs 
       
  1030       |> map (cert #> Thm.assume)
       
  1031 
       
  1032     val compat_store = store_compat_thms n compat
       
  1033 
       
  1034     val (goalstate, values) = PROFILE "prove_stuff"
       
  1035       (prove_stuff lthy globals G f R xclauses complete compat
       
  1036          compat_store G_elim G_eqvt) f_defthm
       
  1037      
       
  1038     val mk_trsimps =
       
  1039       mk_trsimps lthy globals f G R f_defthm R_elim G_induct xclauses
       
  1040 
       
  1041     fun mk_partial_rules provedgoal =
       
  1042       let
       
  1043         val newthy = theory_of_thm provedgoal (*FIXME*)
       
  1044 
       
  1045         val (graph_is_function, complete_thm) =
       
  1046           provedgoal
       
  1047           |> Conjunction.elim
       
  1048           |> apfst (Thm.forall_elim_vars 0)
       
  1049 
       
  1050         val f_iff = graph_is_function RS (f_defthm RS ex1_implies_iff)
       
  1051 
       
  1052         val psimps = PROFILE "Proving simplification rules"
       
  1053           (mk_psimps newthy globals R xclauses values f_iff) graph_is_function
       
  1054 
       
  1055         val simple_pinduct = PROFILE "Proving partial induction rule"
       
  1056           (mk_partial_induct_rule newthy globals R complete_thm) xclauses
       
  1057 
       
  1058         val total_intro = PROFILE "Proving nested termination rule"
       
  1059           (mk_nest_term_rule newthy globals R R_elim) xclauses
       
  1060 
       
  1061         val dom_intros =
       
  1062           if domintros then SOME (PROFILE "Proving domain introduction rules"
       
  1063              (map (mk_domain_intro lthy globals R R_elim)) xclauses)
       
  1064            else NONE
       
  1065         val trsimps = if tailrec then SOME (mk_trsimps psimps) else NONE
       
  1066 
       
  1067       in
       
  1068         FunctionResult {fs=[f], G=G, R=R, cases=complete_thm,
       
  1069           psimps=psimps, simple_pinducts=[simple_pinduct],
       
  1070           termination=total_intro, trsimps=trsimps,
       
  1071           domintros=dom_intros}
       
  1072       end
       
  1073   in
       
  1074     ((f, goalstate, mk_partial_rules), lthy)
       
  1075   end
       
  1076 *}
       
  1077 
       
  1078 ML {*
       
  1079 open Function_Lib
       
  1080 open Function_Common
       
  1081 
       
  1082 type qgar = string * (string * typ) list * term list * term list * term
       
  1083 
       
  1084 datatype mutual_part = MutualPart of
       
  1085  {i : int,
       
  1086   i' : int,
       
  1087   fvar : string * typ,
       
  1088   cargTs: typ list,
       
  1089   f_def: term,
       
  1090 
       
  1091   f: term option,
       
  1092   f_defthm : thm option}
       
  1093 
       
  1094 datatype mutual_info = Mutual of
       
  1095  {n : int,
       
  1096   n' : int,
       
  1097   fsum_var : string * typ,
       
  1098 
       
  1099   ST: typ,
       
  1100   RST: typ,
       
  1101 
       
  1102   parts: mutual_part list,
       
  1103   fqgars: qgar list,
       
  1104   qglrs: ((string * typ) list * term list * term * term) list,
       
  1105 
       
  1106   fsum : term option}
       
  1107 
       
  1108 fun mutual_induct_Pnames n =
       
  1109   if n < 5 then fst (chop n ["P","Q","R","S"])
       
  1110   else map (fn i => "P" ^ string_of_int i) (1 upto n)
       
  1111 
       
  1112 fun get_part fname =
       
  1113   the o find_first (fn (MutualPart {fvar=(n,_), ...}) => n = fname)
       
  1114 
       
  1115 (* FIXME *)
       
  1116 fun mk_prod_abs e (t1, t2) =
       
  1117   let
       
  1118     val bTs = rev (map snd e)
       
  1119     val T1 = fastype_of1 (bTs, t1)
       
  1120     val T2 = fastype_of1 (bTs, t2)
       
  1121   in
       
  1122     HOLogic.pair_const T1 T2 $ t1 $ t2
       
  1123   end
       
  1124 
       
  1125 fun analyze_eqs ctxt defname fs eqs =
       
  1126   let
       
  1127     val num = length fs
       
  1128     val fqgars = map (split_def ctxt (K true)) eqs
       
  1129     val arity_of = map (fn (fname,_,_,args,_) => (fname, length args)) fqgars
       
  1130       |> AList.lookup (op =) #> the
       
  1131 
       
  1132     fun curried_types (fname, fT) =
       
  1133       let
       
  1134         val (caTs, uaTs) = chop (arity_of fname) (binder_types fT)
       
  1135       in
       
  1136         (caTs, uaTs ---> body_type fT)
       
  1137       end
       
  1138 
       
  1139     val (caTss, resultTs) = split_list (map curried_types fs)
       
  1140     val argTs = map (foldr1 HOLogic.mk_prodT) caTss
       
  1141 
       
  1142     val dresultTs = distinct (op =) resultTs
       
  1143     val n' = length dresultTs
       
  1144 
       
  1145     val RST = Balanced_Tree.make (uncurry SumTree.mk_sumT) dresultTs
       
  1146     val ST = Balanced_Tree.make (uncurry SumTree.mk_sumT) argTs
       
  1147 
       
  1148     val fsum_type = ST --> RST
       
  1149 
       
  1150     val ([fsum_var_name], _) = Variable.add_fixes [ defname ^ "_sum" ] ctxt
       
  1151     val fsum_var = (fsum_var_name, fsum_type)
       
  1152 
       
  1153     fun define (fvar as (n, _)) caTs resultT i =
       
  1154       let
       
  1155         val vars = map_index (fn (j,T) => Free ("x" ^ string_of_int j, T)) caTs (* FIXME: Bind xs properly *)
       
  1156         val i' = find_index (fn Ta => Ta = resultT) dresultTs + 1
       
  1157 
       
  1158         val f_exp = SumTree.mk_proj RST n' i' 
       
  1159           (Free fsum_var $ SumTree.mk_inj ST num i (foldr1 HOLogic.mk_prod vars))
       
  1160         
       
  1161         val def = Term.abstract_over (Free fsum_var, fold_rev lambda vars f_exp)
       
  1162 
       
  1163         val rew = (n, fold_rev lambda vars f_exp)
       
  1164       in
       
  1165         (MutualPart {i=i, i'=i', fvar=fvar,cargTs=caTs,f_def=def,f=NONE,f_defthm=NONE}, rew)
       
  1166       end
       
  1167 
       
  1168     val (parts, rews) = split_list (map4 define fs caTss resultTs (1 upto num))
       
  1169 
       
  1170     fun convert_eqs (f, qs, gs, args, rhs) =
       
  1171       let
       
  1172         val MutualPart {i, i', ...} = get_part f parts
       
  1173       in
       
  1174         (qs, gs, SumTree.mk_inj ST num i (foldr1 (mk_prod_abs qs) args),
       
  1175          SumTree.mk_inj RST n' i' (replace_frees rews rhs)
       
  1176          |> Envir.beta_norm)
       
  1177       end
       
  1178 
       
  1179     val qglrs = map convert_eqs fqgars
       
  1180   in
       
  1181     Mutual {n=num, n'=n', fsum_var=fsum_var, ST=ST, RST=RST,
       
  1182       parts=parts, fqgars=fqgars, qglrs=qglrs, fsum=NONE}
       
  1183   end
       
  1184 *}
       
  1185 
       
  1186 ML {*
       
  1187 fun define_projections fixes mutual fsum lthy =
       
  1188   let
       
  1189     fun def ((MutualPart {i=i, i'=i', fvar=(fname, fT), cargTs, f_def, ...}), (_, mixfix)) lthy =
       
  1190       let
       
  1191         val ((f, (_, f_defthm)), lthy') =
       
  1192           Local_Theory.define
       
  1193             ((Binding.name fname, mixfix),
       
  1194               ((Binding.conceal (Binding.name (fname ^ "_def")), []),
       
  1195               Term.subst_bound (fsum, f_def))) lthy
       
  1196       in
       
  1197         (MutualPart {i=i, i'=i', fvar=(fname, fT), cargTs=cargTs, f_def=f_def,
       
  1198            f=SOME f, f_defthm=SOME f_defthm },
       
  1199          lthy')
       
  1200       end
       
  1201 
       
  1202     val Mutual { n, n', fsum_var, ST, RST, parts, fqgars, qglrs, ... } = mutual
       
  1203     val (parts', lthy') = fold_map def (parts ~~ fixes) lthy
       
  1204   in
       
  1205     (Mutual { n=n, n'=n', fsum_var=fsum_var, ST=ST, RST=RST, parts=parts',
       
  1206        fqgars=fqgars, qglrs=qglrs, fsum=SOME fsum },
       
  1207      lthy')
       
  1208   end
       
  1209 
       
  1210 fun in_context ctxt (f, pre_qs, pre_gs, pre_args, pre_rhs) F =
       
  1211   let
       
  1212     val thy = ProofContext.theory_of ctxt
       
  1213 
       
  1214     val oqnames = map fst pre_qs
       
  1215     val (qs, _) = Variable.variant_fixes oqnames ctxt
       
  1216       |>> map2 (fn (_, T) => fn n => Free (n, T)) pre_qs
       
  1217 
       
  1218     fun inst t = subst_bounds (rev qs, t)
       
  1219     val gs = map inst pre_gs
       
  1220     val args = map inst pre_args
       
  1221     val rhs = inst pre_rhs
       
  1222 
       
  1223     val cqs = map (cterm_of thy) qs
       
  1224     val ags = map (Thm.assume o cterm_of thy) gs
       
  1225 
       
  1226     val import = fold Thm.forall_elim cqs
       
  1227       #> fold Thm.elim_implies ags
       
  1228 
       
  1229     val export = fold_rev (Thm.implies_intr o cprop_of) ags
       
  1230       #> fold_rev forall_intr_rename (oqnames ~~ cqs)
       
  1231   in
       
  1232     F ctxt (f, qs, gs, args, rhs) import export
       
  1233   end
       
  1234 
       
  1235 fun recover_mutual_psimp all_orig_fdefs parts ctxt (fname, _, _, args, rhs)
       
  1236   import (export : thm -> thm) sum_psimp_eq =
       
  1237   let
       
  1238     val (MutualPart {f=SOME f, ...}) = get_part fname parts
       
  1239 
       
  1240     val psimp = import sum_psimp_eq
       
  1241     val (simp, restore_cond) =
       
  1242       case cprems_of psimp of
       
  1243         [] => (psimp, I)
       
  1244       | [cond] => (Thm.implies_elim psimp (Thm.assume cond), Thm.implies_intr cond)
       
  1245       | _ => raise General.Fail "Too many conditions"
       
  1246 
       
  1247   in
       
  1248     Goal.prove ctxt [] []
       
  1249       (HOLogic.Trueprop $ HOLogic.mk_eq (list_comb (f, args), rhs))
       
  1250       (fn _ => (Local_Defs.unfold_tac ctxt all_orig_fdefs)
       
  1251          THEN EqSubst.eqsubst_tac ctxt [0] [simp] 1
       
  1252          THEN (simp_tac (simpset_of ctxt)) 1) (* FIXME: global simpset?!! *)
       
  1253     |> restore_cond
       
  1254     |> export
       
  1255   end
       
  1256 
       
  1257 fun mk_applied_form ctxt caTs thm =
       
  1258   let
       
  1259     val thy = ProofContext.theory_of ctxt
       
  1260     val xs = map_index (fn (i,T) => cterm_of thy (Free ("x" ^ string_of_int i, T))) caTs (* FIXME: Bind xs properly *)
       
  1261   in
       
  1262     fold (fn x => fn thm => Thm.combination thm (Thm.reflexive x)) xs thm
       
  1263     |> Conv.fconv_rule (Thm.beta_conversion true)
       
  1264     |> fold_rev Thm.forall_intr xs
       
  1265     |> Thm.forall_elim_vars 0
       
  1266   end
       
  1267 
       
  1268 fun mutual_induct_rules lthy induct all_f_defs (Mutual {n, ST, parts, ...}) =
       
  1269   let
       
  1270     val cert = cterm_of (ProofContext.theory_of lthy)
       
  1271     val newPs =
       
  1272       map2 (fn Pname => fn MutualPart {cargTs, ...} =>
       
  1273           Free (Pname, cargTs ---> HOLogic.boolT))
       
  1274         (mutual_induct_Pnames (length parts)) parts
       
  1275 
       
  1276     fun mk_P (MutualPart {cargTs, ...}) P =
       
  1277       let
       
  1278         val avars = map_index (fn (i,T) => Var (("a", i), T)) cargTs
       
  1279         val atup = foldr1 HOLogic.mk_prod avars
       
  1280       in
       
  1281         HOLogic.tupled_lambda atup (list_comb (P, avars))
       
  1282       end
       
  1283 
       
  1284     val Ps = map2 mk_P parts newPs
       
  1285     val case_exp = SumTree.mk_sumcases HOLogic.boolT Ps
       
  1286 
       
  1287     val induct_inst =
       
  1288       Thm.forall_elim (cert case_exp) induct
       
  1289       |> full_simplify SumTree.sumcase_split_ss
       
  1290       |> full_simplify (HOL_basic_ss addsimps all_f_defs)
       
  1291 
       
  1292     fun project rule (MutualPart {cargTs, i, ...}) k =
       
  1293       let
       
  1294         val afs = map_index (fn (j,T) => Free ("a" ^ string_of_int (j + k), T)) cargTs (* FIXME! *)
       
  1295         val inj = SumTree.mk_inj ST n i (foldr1 HOLogic.mk_prod afs)
       
  1296       in
       
  1297         (rule
       
  1298          |> Thm.forall_elim (cert inj)
       
  1299          |> full_simplify SumTree.sumcase_split_ss
       
  1300          |> fold_rev (Thm.forall_intr o cert) (afs @ newPs),
       
  1301          k + length cargTs)
       
  1302       end
       
  1303   in
       
  1304     fst (fold_map (project induct_inst) parts 0)
       
  1305   end
       
  1306 
       
  1307 fun mk_partial_rules_mutual lthy inner_cont (m as Mutual {parts, fqgars, ...}) proof =
       
  1308   let
       
  1309     val result = inner_cont proof
       
  1310     val FunctionResult {G, R, cases, psimps, trsimps, simple_pinducts=[simple_pinduct],
       
  1311       termination, domintros, ...} = result
       
  1312 
       
  1313     val (all_f_defs, fs) =
       
  1314       map (fn MutualPart {f_defthm = SOME f_def, f = SOME f, cargTs, ...} =>
       
  1315         (mk_applied_form lthy cargTs (Thm.symmetric f_def), f))
       
  1316       parts
       
  1317       |> split_list
       
  1318 
       
  1319     val all_orig_fdefs =
       
  1320       map (fn MutualPart {f_defthm = SOME f_def, ...} => f_def) parts
       
  1321 
       
  1322     fun mk_mpsimp fqgar sum_psimp =
       
  1323       in_context lthy fqgar (recover_mutual_psimp all_orig_fdefs parts) sum_psimp
       
  1324 
       
  1325     val rew_ss = HOL_basic_ss addsimps all_f_defs
       
  1326     val mpsimps = map2 mk_mpsimp fqgars psimps
       
  1327     val mtrsimps = Option.map (map2 mk_mpsimp fqgars) trsimps
       
  1328     val minducts = mutual_induct_rules lthy simple_pinduct all_f_defs m
       
  1329     val mtermination = full_simplify rew_ss termination
       
  1330     val mdomintros = Option.map (map (full_simplify rew_ss)) domintros
       
  1331   in
       
  1332     FunctionResult { fs=fs, G=G, R=R,
       
  1333       psimps=mpsimps, simple_pinducts=minducts,
       
  1334       cases=cases, termination=mtermination,
       
  1335       domintros=mdomintros, trsimps=mtrsimps}
       
  1336   end
       
  1337 
       
  1338 fun prepare_function_mutual config defname fixes eqss lthy =
       
  1339   let
       
  1340     val mutual as Mutual {fsum_var=(n, T), qglrs, ...} =
       
  1341       analyze_eqs lthy defname (map fst fixes) (map Envir.beta_eta_contract eqss)
       
  1342 
       
  1343     val ((fsum, goalstate, cont), lthy') =
       
  1344       prepare_function config defname [((n, T), NoSyn)] qglrs lthy
       
  1345 
       
  1346     val (mutual', lthy'') = define_projections fixes mutual fsum lthy'
       
  1347 
       
  1348     val mutual_cont = mk_partial_rules_mutual lthy'' cont mutual'
       
  1349   in
       
  1350     ((goalstate, mutual_cont), lthy'')
       
  1351   end
       
  1352 
       
  1353 *}
       
  1354 
       
  1355 
       
  1356 ML {*
       
  1357 
       
  1358 open Function_Lib
       
  1359 open Function_Common
       
  1360 
       
  1361 val simp_attribs = map (Attrib.internal o K)
       
  1362   [Simplifier.simp_add,
       
  1363    Code.add_default_eqn_attribute,
       
  1364    Nitpick_Simps.add]
       
  1365 
       
  1366 val psimp_attribs = map (Attrib.internal o K)
       
  1367   [Nitpick_Psimps.add]
       
  1368 
       
  1369 fun mk_defname fixes = fixes |> map (fst o fst) |> space_implode "_"
       
  1370 
       
  1371 fun add_simps fnames post sort extra_qualify label mod_binding moreatts
       
  1372   simps lthy =
       
  1373   let
       
  1374     val spec = post simps
       
  1375       |> map (apfst (apsnd (fn ats => moreatts @ ats)))
       
  1376       |> map (apfst (apfst extra_qualify))
       
  1377 
       
  1378     val (saved_spec_simps, lthy) =
       
  1379       fold_map Local_Theory.note spec lthy
       
  1380 
       
  1381     val saved_simps = maps snd saved_spec_simps
       
  1382     val simps_by_f = sort saved_simps
       
  1383 
       
  1384     fun add_for_f fname simps =
       
  1385       Local_Theory.note
       
  1386         ((mod_binding (Binding.qualify true fname (Binding.name label)), []), simps)
       
  1387       #> snd
       
  1388   in
       
  1389     (saved_simps, fold2 add_for_f fnames simps_by_f lthy)
       
  1390   end
       
  1391 
       
  1392 fun prepare_function is_external prep default_constraint fixspec eqns config lthy =
       
  1393   let
       
  1394     val constrn_fxs = map (fn (b, T, mx) => (b, SOME (the_default default_constraint T), mx))
       
  1395     val ((fixes0, spec0), ctxt') = prep (constrn_fxs fixspec) eqns lthy
       
  1396     val fixes = map (apfst (apfst Binding.name_of)) fixes0;
       
  1397     val spec = map (fn (bnd, prop) => (bnd, [prop])) spec0;
       
  1398     val (eqs, post, sort_cont, cnames) = get_preproc lthy config ctxt' fixes spec
       
  1399 
       
  1400     val defname = mk_defname fixes
       
  1401     val FunctionConfig {partials, tailrec, default, ...} = config
       
  1402     val _ =
       
  1403       if tailrec then Output.legacy_feature
       
  1404         "'function (tailrec)' command. Use 'partial_function (tailrec)'."
       
  1405       else ()
       
  1406     val _ =
       
  1407       if is_some default then Output.legacy_feature
       
  1408         "'function (default)'. Use 'partial_function'."
       
  1409       else ()
       
  1410 
       
  1411     val ((goal_state, cont), lthy') =
       
  1412       prepare_function_mutual config defname fixes eqs lthy
       
  1413 
       
  1414     fun afterqed [[proof]] lthy =
       
  1415       let
       
  1416         val FunctionResult {fs, R, psimps, trsimps, simple_pinducts,
       
  1417           termination, domintros, cases, ...} =
       
  1418           cont (Thm.close_derivation proof)
       
  1419 
       
  1420         val fnames = map (fst o fst) fixes
       
  1421         fun qualify n = Binding.name n
       
  1422           |> Binding.qualify true defname
       
  1423         val conceal_partial = if partials then I else Binding.conceal
       
  1424 
       
  1425         val addsmps = add_simps fnames post sort_cont
       
  1426 
       
  1427         val (((psimps', pinducts'), (_, [termination'])), lthy) =
       
  1428           lthy
       
  1429           |> addsmps (conceal_partial o Binding.qualify false "partial")
       
  1430                "psimps" conceal_partial psimp_attribs psimps
       
  1431           ||> (case trsimps of NONE => I | SOME thms =>
       
  1432                    addsmps I "simps" I simp_attribs thms #> snd
       
  1433                    #> Spec_Rules.add Spec_Rules.Equational (fs, thms))
       
  1434           ||>> Local_Theory.note ((conceal_partial (qualify "pinduct"),
       
  1435                  [Attrib.internal (K (Rule_Cases.case_names cnames)),
       
  1436                   Attrib.internal (K (Rule_Cases.consumes 1)),
       
  1437                   Attrib.internal (K (Induct.induct_pred ""))]), simple_pinducts)
       
  1438           ||>> Local_Theory.note ((Binding.conceal (qualify "termination"), []), [termination])
       
  1439           ||> (snd o Local_Theory.note ((qualify "cases",
       
  1440                  [Attrib.internal (K (Rule_Cases.case_names cnames))]), [cases]))
       
  1441           ||> (case domintros of NONE => I | SOME thms => 
       
  1442                    Local_Theory.note ((qualify "domintros", []), thms) #> snd)
       
  1443 
       
  1444         val info = { add_simps=addsmps, case_names=cnames, psimps=psimps',
       
  1445           pinducts=snd pinducts', simps=NONE, inducts=NONE, termination=termination',
       
  1446           fs=fs, R=R, defname=defname, is_partial=true }
       
  1447 
       
  1448         val _ =
       
  1449           if not is_external then ()
       
  1450           else Specification.print_consts lthy (K false) (map fst fixes)
       
  1451       in
       
  1452         (info, 
       
  1453          lthy |> Local_Theory.declaration false (add_function_data o morph_function_data info))
       
  1454       end
       
  1455   in
       
  1456     ((goal_state, afterqed), lthy')
       
  1457   end
       
  1458 
       
  1459 *}
       
  1460 
       
  1461 ML {*
       
  1462 fun gen_function is_external prep default_constraint fixspec eqns config lthy =
       
  1463   let
       
  1464     val ((goal_state, afterqed), lthy') =
       
  1465       prepare_function is_external prep default_constraint fixspec eqns config lthy
       
  1466   in
       
  1467     lthy'
       
  1468     |> Proof.theorem NONE (snd oo afterqed) [[(Logic.unprotect (concl_of goal_state), [])]]
       
  1469     |> Proof.refine (Method.primitive_text (K goal_state)) 
       
  1470     |> Seq.hd
       
  1471   end
       
  1472 *}
       
  1473 
       
  1474 
       
  1475 ML {*
       
  1476 val function = gen_function false Specification.check_spec (Type_Infer.anyT HOLogic.typeS)
       
  1477 val function_cmd = gen_function true Specification.read_spec "_::type"
       
  1478 
       
  1479 fun add_case_cong n thy =
       
  1480   let
       
  1481     val cong = #case_cong (Datatype.the_info thy n)
       
  1482       |> safe_mk_meta_eq
       
  1483   in
       
  1484     Context.theory_map
       
  1485       (Function_Ctx_Tree.map_function_congs (Thm.add_thm cong)) thy
       
  1486   end
       
  1487 
       
  1488 val setup_case_cong = Datatype.interpretation (K (fold add_case_cong))
       
  1489 
       
  1490 
       
  1491 (* setup *)
       
  1492 
       
  1493 val setup =
       
  1494   Attrib.setup @{binding fundef_cong}
       
  1495     (Attrib.add_del Function_Ctx_Tree.cong_add Function_Ctx_Tree.cong_del)
       
  1496     "declaration of congruence rule for function definitions"
       
  1497   #> setup_case_cong
       
  1498   #> Function_Relation.setup
       
  1499   #> Function_Common.Termination_Simps.setup
       
  1500 
       
  1501 val get_congs = Function_Ctx_Tree.get_function_congs
       
  1502 
       
  1503 fun get_info ctxt t = Item_Net.retrieve (get_function ctxt) t
       
  1504   |> the_single |> snd
       
  1505 
       
  1506 
       
  1507 (* outer syntax *)
       
  1508 
       
  1509 val _ =
       
  1510   Outer_Syntax.local_theory_to_proof "nominal_primrec" "define recursive functions for nominal types"
       
  1511   Keyword.thy_goal
       
  1512   (function_parser default_config
       
  1513      >> (fn ((config, fixes), statements) => function_cmd fixes statements config))
       
  1514 *}
       
  1515 
       
  1516 ML {* trace := true *}
       
  1517 
       
  1518 lemma test:
       
  1519   assumes a: "[[x]]lst. t = [[x]]lst. t'"
       
  1520   shows "t = t'"
       
  1521 using a
       
  1522 apply(simp add: Abs_eq_iff)
       
  1523 apply(erule exE)
       
  1524 apply(simp only: alphas)
       
  1525 apply(erule conjE)+
       
  1526 apply(rule sym)
       
  1527 apply(clarify)
       
  1528 apply(rule supp_perm_eq)
       
  1529 apply(subgoal_tac "set [x] \<sharp>* p")
       
  1530 apply(auto simp add: fresh_star_def)[1]
       
  1531 apply(simp)
       
  1532 apply(simp add: fresh_star_def)
       
  1533 apply(simp add: fresh_perm)
       
  1534 done
       
  1535 
       
  1536 lemma test2:
       
  1537   assumes "a \<sharp> x" "c \<sharp> x" "b \<sharp> y" "c \<sharp> y"
       
  1538   and "(a \<rightleftharpoons> c) \<bullet> x = (b \<rightleftharpoons> c) \<bullet> y"
       
  1539   shows "x = y"
       
  1540 using assms by (simp add: swap_fresh_fresh)
       
  1541 
       
  1542 lemma test3:
       
  1543   assumes "x = y"
       
  1544   and "a \<sharp> x" "c \<sharp> x" "b \<sharp> y" "c \<sharp> y"
       
  1545   shows "(a \<rightleftharpoons> c) \<bullet> x = (b \<rightleftharpoons> c) \<bullet> y"
       
  1546 using assms by (simp add: swap_fresh_fresh)
       
  1547 
       
  1548 nominal_primrec
       
  1549   depth :: "lam \<Rightarrow> nat"
       
  1550 where
       
  1551   "depth (Var x) = 1"
       
  1552 | "depth (App t1 t2) = (max (depth t1) (depth t2)) + 1"
       
  1553 | "depth (Lam x t) = (depth t) + 1"
       
  1554 apply(rule_tac y="x" in lam.exhaust)
       
  1555 apply(simp_all)[3]
       
  1556 apply(simp_all only: lam.distinct)
       
  1557 apply(simp add: lam.eq_iff)
       
  1558 apply(simp add: lam.eq_iff)
       
  1559 apply(subst (asm) Abs_eq_iff)
       
  1560 apply(erule exE)
       
  1561 apply(simp add: alphas)
       
  1562 apply(clarify)
       
  1563 oops
       
  1564 
       
  1565 lemma removeAll_eqvt[eqvt]:
       
  1566   shows "p \<bullet> (removeAll x xs) = removeAll (p \<bullet> x) (p \<bullet> xs)"
       
  1567 by (induct xs) (auto)
       
  1568 
       
  1569 nominal_primrec 
       
  1570   frees_lst :: "lam \<Rightarrow> atom list"
       
  1571 where
       
  1572   "frees_lst (Var x) = [atom x]"
       
  1573 | "frees_lst (App t1 t2) = (frees_lst t1) @ (frees_lst t2)"
       
  1574 | "frees_lst (Lam x t) = removeAll (atom x) (frees_lst t)"
       
  1575 apply(rule_tac y="x" in lam.exhaust)
       
  1576 apply(simp_all)[3]
       
  1577 apply(simp_all only: lam.distinct)
       
  1578 apply(simp add: lam.eq_iff)
       
  1579 apply(simp add: lam.eq_iff)
       
  1580 apply(simp add: lam.eq_iff)
       
  1581 apply(simp add: Abs_eq_iff)
       
  1582 apply(erule exE)
       
  1583 apply(simp add: alphas)
       
  1584 apply(simp add: atom_eqvt)
       
  1585 apply(clarify)
       
  1586 oops
       
  1587 
       
  1588 nominal_primrec
       
  1589   subst :: "lam \<Rightarrow> name \<Rightarrow> lam \<Rightarrow> lam"  ("_ [_ ::= _]" [100,100,100] 100)
       
  1590 where
       
  1591   "(Var x)[y ::= s] = (if x=y then s else (Var x))"
       
  1592 | "(App t\<^isub>1 t\<^isub>2)[y ::= s] = App (t\<^isub>1[y ::= s]) (t\<^isub>2[y ::= s])"
       
  1593 | "atom x \<sharp> (y, s) \<Longrightarrow> (Lam x t)[y ::= s] = Lam x (t[y ::= s])"
       
  1594 apply(case_tac x)
       
  1595 apply(simp)
       
  1596 apply(rule_tac y="a" and c="(b, c)" in lam.strong_exhaust)
       
  1597 apply(simp add: lam.eq_iff lam.distinct)
       
  1598 apply(auto)[1]
       
  1599 apply(simp add: lam.eq_iff lam.distinct)
       
  1600 apply(auto)[1]
       
  1601 apply(simp add: fresh_star_def lam.eq_iff lam.distinct)
       
  1602 apply(simp_all add: lam.distinct)[5]
       
  1603 apply(simp add: lam.eq_iff)
       
  1604 apply(simp add: lam.eq_iff)
       
  1605 apply(simp add: lam.eq_iff)
       
  1606 apply(erule conjE)+
       
  1607 oops
       
  1608 
       
  1609 
       
  1610 
       
  1611 nominal_primrec
       
  1612   depth :: "lam \<Rightarrow> nat"
       
  1613 where
       
  1614   "depth (Var x) = 1"
       
  1615 | "depth (App t1 t2) = (max (depth t1) (depth t2)) + 1"
       
  1616 | "depth (Lam x t) = (depth t) + 1"
       
  1617 apply(rule_tac y="x" in lam.exhaust)
       
  1618 apply(simp_all)[3]
       
  1619 apply(simp_all only: lam.distinct)
       
  1620 apply(simp add: lam.eq_iff)
       
  1621 apply(simp add: lam.eq_iff)
       
  1622 (*
       
  1623 apply(subst (asm) Abs_eq_iff)
       
  1624 apply(erule exE)
       
  1625 apply(simp add: alphas)
       
  1626 apply(clarify)
       
  1627 *)
       
  1628 apply(subgoal_tac "finite (supp (x, xa, t, ta, depth_sumC t, depth_sumC ta))")
       
  1629 apply(erule_tac ?'a="name" in obtain_at_base)
       
  1630 unfolding fresh_def[symmetric]
       
  1631 apply(drule_tac a="atom x" and b="atom xa" and c="atom a" in test3)
       
  1632 apply(simp add: Abs_fresh_iff)
       
  1633 apply(simp add: Abs_fresh_iff)
       
  1634 apply(simp add: Abs_fresh_iff)
       
  1635 apply(simp add: Abs_fresh_iff)
       
  1636 apply(rule_tac a="atom x" and b="atom xa" and c="atom a" in test2)
       
  1637 apply(simp add: pure_fresh)
       
  1638 apply(simp add: pure_fresh)
       
  1639 apply(simp add: pure_fresh)
       
  1640 apply(simp add: pure_fresh)
       
  1641 apply(simp add: eqvt_at_def)
       
  1642 apply(drule test)
       
  1643 apply(simp)
       
  1644 apply(simp add: finite_supp)
       
  1645 done
       
  1646 
       
  1647 termination depth
       
  1648   apply(relation "measure size")
       
  1649   apply(auto simp add: lam.size)
       
  1650   done
       
  1651 
       
  1652 thm depth.psimps
       
  1653 thm depth.simps
       
  1654 
       
  1655 
       
  1656 lemma swap_set_not_in_at:
       
  1657   fixes a b::"'a::at"
       
  1658   and   S::"'a::at set"
       
  1659   assumes a: "a \<notin> S" "b \<notin> S"
       
  1660   shows "(a \<leftrightarrow> b) \<bullet> S = S"
       
  1661   unfolding permute_set_eq
       
  1662   using a by (auto simp add: permute_flip_at)
       
  1663 
       
  1664 lemma removeAll_eqvt[eqvt]:
       
  1665   shows "p \<bullet> (removeAll x xs) = removeAll (p \<bullet> x) (p \<bullet> xs)"
       
  1666 by (induct xs) (auto)
       
  1667 
       
  1668 nominal_primrec 
       
  1669   frees_lst :: "lam \<Rightarrow> atom list"
       
  1670 where
       
  1671   "frees_lst (Var x) = [atom x]"
       
  1672 | "frees_lst (App t1 t2) = (frees_lst t1) @ (frees_lst t2)"
       
  1673 | "frees_lst (Lam x t) = removeAll (atom x) (frees_lst t)"
       
  1674 apply(rule_tac y="x" in lam.exhaust)
       
  1675 apply(simp_all)[3]
       
  1676 apply(simp_all only: lam.distinct)
       
  1677 apply(simp add: lam.eq_iff)
       
  1678 apply(simp add: lam.eq_iff)
       
  1679 apply(simp add: lam.eq_iff)
       
  1680 apply(simp add: Abs_eq_iff)
       
  1681 apply(erule exE)
       
  1682 apply(simp add: alphas)
       
  1683 apply(simp add: atom_eqvt)
       
  1684 apply(clarify)
       
  1685 apply(rule trans)
       
  1686 apply(rule sym)
       
  1687 apply(rule_tac p="p" in supp_perm_eq)
       
  1688 oops
       
  1689 
       
  1690 nominal_primrec 
       
  1691   frees :: "lam \<Rightarrow> name set"
       
  1692 where
       
  1693   "frees (Var x) = {x}"
       
  1694 | "frees (App t1 t2) = (frees t1) \<union> (frees t2)"
       
  1695 | "frees (Lam x t) = (frees t) - {x}"
       
  1696 apply(rule_tac y="x" in lam.exhaust)
       
  1697 apply(simp_all)[3]
       
  1698 apply(simp_all only: lam.distinct)
       
  1699 apply(simp add: lam.eq_iff)
       
  1700 apply(simp add: lam.eq_iff)
       
  1701 apply(simp add: lam.eq_iff)
       
  1702 apply(subgoal_tac "finite (supp (x, xa, t, ta, frees_sumC t, frees_sumC ta))")
       
  1703 apply(erule_tac ?'a="name" in obtain_at_base)
       
  1704 unfolding fresh_def[symmetric]
       
  1705 apply(drule_tac a="atom x" and b="atom xa" and c="atom a" in test3)
       
  1706 apply(simp add: Abs_fresh_iff)
       
  1707 apply(simp add: Abs_fresh_iff)
       
  1708 apply(simp add: Abs_fresh_iff)
       
  1709 apply(simp add: Abs_fresh_iff)
       
  1710 apply(simp)
       
  1711 apply(drule test)
       
  1712 apply(rule_tac t="frees_sumC t - {x}" and s="(x \<leftrightarrow> a) \<bullet> (frees_sumC t - {x})" in subst)
       
  1713 oops
       
  1714 
       
  1715 thm Abs_eq_iff[simplified alphas]
       
  1716 
       
  1717 lemma Abs_set_eq_iff2:
       
  1718   fixes x y::"'a::fs"
       
  1719   shows "[bs]set. x = [cs]set. y \<longleftrightarrow>
       
  1720     (\<exists>p. supp ([bs]set. x) = supp ([cs]set. y) \<and>
       
  1721          supp ([bs]set. x) \<sharp>* p \<and>
       
  1722          p \<bullet> x = y \<and> p \<bullet> bs = cs)"
       
  1723 unfolding Abs_eq_iff
       
  1724 unfolding alphas
       
  1725 unfolding supp_Abs
       
  1726 by simp
       
  1727 
       
  1728 lemma Abs_set_eq_iff3:
       
  1729   fixes x y::"'a::fs"
       
  1730   assumes a: "finite bs" "finite cs"
       
  1731   shows "[bs]set. x = [cs]set. y \<longleftrightarrow>
       
  1732     (\<exists>p. supp ([bs]set. x) = supp ([cs]set. y) \<and>
       
  1733          supp ([bs]set. x) \<sharp>* p \<and>
       
  1734          p \<bullet> x = y \<and> p \<bullet> bs = cs \<and>
       
  1735          supp p \<subseteq> bs \<union> cs)"
       
  1736 unfolding Abs_eq_iff
       
  1737 unfolding alphas
       
  1738 unfolding supp_Abs
       
  1739 apply(auto)
       
  1740 using set_renaming_perm
       
  1741 sorry
       
  1742 
       
  1743 lemma Abs_eq_iff2:
       
  1744   fixes x y::"'a::fs"
       
  1745   shows "[bs]lst. x = [cs]lst. y \<longleftrightarrow>
       
  1746     (\<exists>p. supp ([bs]lst. x) = supp ([cs]lst. y) \<and>
       
  1747          supp ([bs]lst. x) \<sharp>* p \<and>
       
  1748          p \<bullet> x = y \<and> p \<bullet> bs = cs)"
       
  1749 unfolding Abs_eq_iff
       
  1750 unfolding alphas
       
  1751 unfolding supp_Abs
       
  1752 by simp
       
  1753 
       
  1754 lemma Abs_eq_iff3:
       
  1755   fixes x y::"'a::fs"
       
  1756   shows "[bs]lst. x = [cs]lst. y \<longleftrightarrow>
       
  1757     (\<exists>p. supp ([bs]lst. x) = supp ([cs]lst. y) \<and>
       
  1758          supp ([bs]lst. x) \<sharp>* p \<and>
       
  1759          p \<bullet> x = y \<and> p \<bullet> bs = cs \<and>
       
  1760          supp p \<subseteq> set bs \<union> set cs)"
       
  1761 unfolding Abs_eq_iff
       
  1762 unfolding alphas
       
  1763 unfolding supp_Abs
       
  1764 apply(auto)
       
  1765 using list_renaming_perm
       
  1766 apply -
       
  1767 apply(drule_tac x="bs" in meta_spec)
       
  1768 apply(drule_tac x="p" in meta_spec)
       
  1769 apply(erule exE)
       
  1770 apply(rule_tac x="q" in exI)
       
  1771 apply(simp add: set_eqvt)
       
  1772 sorry
       
  1773 
       
  1774 nominal_primrec
       
  1775   subst :: "lam \<Rightarrow> name \<Rightarrow> lam \<Rightarrow> lam"  ("_ [_ ::= _]" [100,100,100] 100)
       
  1776 where
       
  1777   "(Var x)[y ::= s] = (if x=y then s else (Var x))"
       
  1778 | "(App t\<^isub>1 t\<^isub>2)[y ::= s] = App (t\<^isub>1[y ::= s]) (t\<^isub>2[y ::= s])"
       
  1779 | "atom x \<sharp> (y, s) \<Longrightarrow> (Lam x t)[y ::= s] = Lam x (t[y ::= s])"
       
  1780 apply(case_tac x)
       
  1781 apply(simp)
       
  1782 apply(rule_tac y="a" and c="(b, c)" in lam.strong_exhaust)
       
  1783 apply(simp add: lam.eq_iff lam.distinct)
       
  1784 apply(auto)[1]
       
  1785 apply(simp add: lam.eq_iff lam.distinct)
       
  1786 apply(auto)[1]
       
  1787 apply(simp add: fresh_star_def lam.eq_iff lam.distinct)
       
  1788 apply(simp_all add: lam.distinct)[5]
       
  1789 apply(simp add: lam.eq_iff)
       
  1790 apply(simp add: lam.eq_iff)
       
  1791 apply(simp add: lam.eq_iff)
       
  1792 apply(erule conjE)+
       
  1793 apply(subst (asm) Abs_eq_iff3) 
       
  1794 apply(erule exE)
       
  1795 apply(erule conjE)+
       
  1796 apply(clarify)
       
  1797 apply(perm_simp)
       
  1798 apply(simp)
       
  1799 apply(rule trans)
       
  1800 apply(rule sym)
       
  1801 apply(rule_tac p="p" in supp_perm_eq)
       
  1802 apply(rule fresh_star_supp_conv)
       
  1803 apply(drule fresh_star_supp_conv)
       
  1804 apply(simp add: Abs_fresh_star_iff)
       
  1805 thm fresh_eqvt_at
       
  1806 apply(rule_tac f="subst_sumC" in fresh_eqvt_at)
       
  1807 apply(assumption)
       
  1808 apply(simp add: finite_supp)
       
  1809 prefer 2
       
  1810 apply(simp)
       
  1811 apply(simp add: eqvt_at_def)
       
  1812 apply(perm_simp)
       
  1813 apply(subgoal_tac "p \<bullet> ya = ya")
       
  1814 apply(subgoal_tac "p \<bullet> sa = sa")
       
  1815 apply(simp)
       
  1816 apply(rule supp_perm_eq)
       
  1817 apply(rule fresh_star_supp_conv)
       
  1818 apply(auto simp add: fresh_star_def fresh_Pair)[1]
       
  1819 apply(rule supp_perm_eq)
       
  1820 apply(rule fresh_star_supp_conv)
       
  1821 apply(auto simp add: fresh_star_def fresh_Pair)[1]
       
  1822 
       
  1823 
       
  1824 
       
  1825 nominal_primrec
       
  1826   subst :: "lam \<Rightarrow> name \<Rightarrow> lam \<Rightarrow> lam"  ("_ [_ ::= _]" [100,100,100] 100)
       
  1827 where
       
  1828   "(Var x)[y ::= s] = (if x=y then s else (Var x))"
       
  1829 | "(App t\<^isub>1 t\<^isub>2)[y ::= s] = App (t\<^isub>1[y ::= s]) (t\<^isub>2[y ::= s])"
       
  1830 | "atom x \<sharp> (y, s) \<Longrightarrow> (Lam x t)[y ::= s] = Lam x (t[y ::= s])"
       
  1831 apply(case_tac x)
       
  1832 apply(simp)
       
  1833 apply(rule_tac y="a" and c="(b, c)" in lam.strong_exhaust)
       
  1834 apply(simp add: lam.eq_iff lam.distinct)
       
  1835 apply(auto)[1]
       
  1836 apply(simp add: lam.eq_iff lam.distinct)
       
  1837 apply(auto)[1]
       
  1838 apply(simp add: fresh_star_def lam.eq_iff lam.distinct)
       
  1839 apply(simp_all add: lam.distinct)[5]
       
  1840 apply(simp add: lam.eq_iff)
       
  1841 apply(simp add: lam.eq_iff)
       
  1842 apply(simp add: lam.eq_iff)
       
  1843 apply(subgoal_tac "finite (supp (ya, sa, x, xa, t, ta, subst_sumC (t, ya, sa), subst_sumC (ta, ya, sa)))")
       
  1844 apply(erule_tac ?'a="name" in obtain_at_base)
       
  1845 unfolding fresh_def[symmetric]
       
  1846 apply(rule_tac a="atom x" and b="atom xa" and c="atom a" in test2)
       
  1847 apply(simp add: Abs_fresh_iff)
       
  1848 apply(simp add: Abs_fresh_iff)
       
  1849 apply(simp add: Abs_fresh_iff)
       
  1850 apply(simp add: Abs_fresh_iff)
       
  1851 apply(erule conjE)+
       
  1852 apply(drule_tac a="atom x" and b="atom xa" and c="atom a" in test3)
       
  1853 apply(simp add: Abs_fresh_iff)
       
  1854 apply(simp add: Abs_fresh_iff)
       
  1855 apply(simp add: Abs_fresh_iff)
       
  1856 apply(simp add: Abs_fresh_iff)
       
  1857 apply(simp add: eqvt_at_def)
       
  1858 apply(drule test)
       
  1859 apply(simp)
       
  1860 apply(subst (2) swap_fresh_fresh)
       
  1861 apply(simp)
       
  1862 apply(simp)
       
  1863 apply(subst (2) swap_fresh_fresh)
       
  1864 apply(simp)
       
  1865 apply(simp)
       
  1866 apply(subst (3) swap_fresh_fresh)
       
  1867 apply(simp)
       
  1868 apply(simp)
       
  1869 apply(subst (3) swap_fresh_fresh)
       
  1870 apply(simp)
       
  1871 apply(simp)
       
  1872 apply(simp)
       
  1873 apply(simp add: finite_supp)
       
  1874 done
       
  1875 
       
  1876 (* this should not work *)
       
  1877 nominal_primrec 
       
  1878   bnds :: "lam \<Rightarrow> name set"
       
  1879 where
       
  1880   "bnds (Var x) = {}"
       
  1881 | "bnds (App t1 t2) = (bnds t1) \<union> (bnds t2)"
       
  1882 | "bnds (Lam x t) = (bnds t) \<union> {x}"
       
  1883 apply(rule_tac y="x" in lam.exhaust)
       
  1884 apply(simp_all)[3]
       
  1885 apply(simp_all only: lam.distinct)
       
  1886 apply(simp add: lam.eq_iff)
       
  1887 apply(simp add: lam.eq_iff)
       
  1888 apply(simp add: lam.eq_iff)
       
  1889 sorry
       
  1890 
       
  1891 end
       
  1892 
       
  1893 
       
  1894