1(*  Title:      HOL/Tools/BNF/bnf_gfp_grec.ML
2    Author:     Jasmin Blanchette, Inria, LORIA, MPII
3    Author:     Aymeric Bouzy, Ecole polytechnique
4    Author:     Dmitriy Traytel, ETH Z��rich
5    Copyright   2015, 2016
6
7Generalized corecursor construction.
8*)
9
10signature BNF_GFP_GREC =
11sig
12  val Tsubst: typ -> typ -> typ -> typ
13  val substT: typ -> typ -> term -> term
14  val freeze_types: Proof.context -> (indexname * sort) list -> typ list -> typ list
15  val dummify_atomic_types: term -> term
16  val define_const: bool -> binding -> int -> string -> term -> local_theory ->
17    (term * thm) * local_theory
18
19  type buffer =
20    {Oper: term,
21     VLeaf: term,
22     CLeaf: term,
23     ctr_wrapper: term,
24     friends: (typ * term) Symtab.table}
25
26  val map_buffer: (term -> term) -> buffer -> buffer
27  val specialize_buffer_types: buffer -> buffer
28
29  type dtor_coinduct_info =
30    {dtor_coinduct: thm,
31     cong_def: thm,
32     cong_locale: thm,
33     cong_base: thm,
34     cong_refl: thm,
35     cong_sym: thm,
36     cong_trans: thm,
37     cong_alg_intros: thm list}
38
39  type corec_info =
40    {fp_b: binding,
41     version: int,
42     fpT: typ,
43     Y: typ,
44     Z: typ,
45     friend_names: string list,
46     sig_fp_sugars: BNF_FP_Def_Sugar.fp_sugar list,
47     ssig_fp_sugar: BNF_FP_Def_Sugar.fp_sugar,
48     Lam: term,
49     proto_sctr: term,
50     flat: term,
51     eval_core: term,
52     eval: term,
53     algLam: term,
54     corecUU: term,
55     dtor_transfer: thm,
56     Lam_transfer: thm,
57     Lam_pointful_natural: thm,
58     proto_sctr_transfer: thm,
59     flat_simps: thm list,
60     eval_core_simps: thm list,
61     eval_thm: thm,
62     eval_simps: thm list,
63     all_algLam_algs: thm list,
64     algLam_thm: thm,
65     dtor_algLam: thm,
66     corecUU_thm: thm,
67     corecUU_unique: thm,
68     corecUU_transfer: thm,
69     buffer: buffer,
70     all_dead_k_bnfs: BNF_Def.bnf list,
71     Retr: term,
72     equivp_Retr: thm,
73     Retr_coinduct: thm,
74     dtor_coinduct_info: dtor_coinduct_info}
75
76  type friend_info =
77    {algrho: term,
78     dtor_algrho: thm,
79     algLam_algrho: thm}
80
81  val not_codatatype: Proof.context -> typ -> 'a
82  val mk_fp_binding: binding -> string -> binding
83  val bnf_kill_all_but: int -> BNF_Def.bnf -> local_theory -> BNF_Def.bnf * local_theory
84
85  val print_corec_infos: Proof.context -> unit
86  val has_no_corec_info: Proof.context -> string -> bool
87  val corec_info_of: typ -> local_theory -> corec_info * local_theory
88  val maybe_corec_info_of: Proof.context -> typ -> corec_info option
89  val corec_infos_of: Proof.context -> string -> corec_info list
90  val corec_infos_of_generic: Context.generic -> Symtab.key -> corec_info list
91  val prepare_friend_corec: string -> typ -> local_theory ->
92    (corec_info * binding * int * typ * typ * typ * typ * typ * BNF_Def.bnf * BNF_Def.bnf
93     * BNF_FP_Def_Sugar.fp_sugar * BNF_FP_Def_Sugar.fp_sugar * buffer) * local_theory
94  val register_friend_corec: string -> binding -> int -> typ -> typ -> typ -> BNF_Def.bnf ->
95    BNF_FP_Def_Sugar.fp_sugar -> BNF_FP_Def_Sugar.fp_sugar -> term -> term -> thm -> corec_info ->
96    local_theory -> friend_info * local_theory
97end;
98
99structure BNF_GFP_Grec : BNF_GFP_GREC =
100struct
101
102open Ctr_Sugar
103open BNF_Util
104open BNF_Def
105open BNF_Comp
106open BNF_FP_Util
107open BNF_LFP
108open BNF_FP_Def_Sugar
109open BNF_LFP_Rec_Sugar
110open BNF_GFP_Grec_Tactics
111
112val algLamN = "algLam";
113val algLam_algLamN = "algLam_algLam";
114val algLam_algrhoN = "algLam_algrho";
115val algrhoN = "algrho";
116val CLeafN = "CLeaf";
117val congN = "congclp";
118val cong_alg_introsN = "cong_alg_intros";
119val cong_localeN = "cong_locale";
120val corecUUN = "corecUU";
121val corecUU_transferN = "corecUU_transfer";
122val corecUU_uniqueN = "corecUU_unique";
123val cutSsigN = "cutSsig";
124val dtor_algLamN = "dtor_algLam";
125val dtor_algrhoN = "dtor_algrho";
126val dtor_coinductN = "dtor_coinduct";
127val dtor_transferN = "dtor_transfer";
128val embLN = "embL";
129val embLLN = "embLL";
130val embLRN = "embLR";
131val embL_pointful_naturalN = "embL_pointful_natural";
132val embL_transferN = "embL_transfer";
133val equivp_RetrN = "equivp_Retr";
134val evalN = "eval";
135val eval_coreN = "eval_core";
136val eval_core_pointful_naturalN = "eval_core_pointful_natural";
137val eval_core_transferN = "eval_core_transfer";
138val eval_flatN = "eval_flat";
139val eval_simpsN = "eval_simps";
140val flatN = "flat";
141val flat_pointful_naturalN = "flat_pointful_natural";
142val flat_transferN = "flat_transfer";
143val k_as_ssig_naturalN = "k_as_ssig_natural";
144val k_as_ssig_transferN = "k_as_ssig_transfer";
145val LamN = "Lam";
146val Lam_transferN = "Lam_transfer";
147val Lam_pointful_naturalN = "Lam_pointful_natural";
148val OperN = "Oper";
149val proto_sctrN = "proto_sctr";
150val proto_sctr_pointful_naturalN = "proto_sctr_pointful_natural";
151val proto_sctr_transferN = "proto_sctr_transfer";
152val rho_transferN = "rho_transfer";
153val Retr_coinductN = "Retr_coinduct";
154val sctrN = "sctr";
155val sctr_transferN = "sctr_transfer";
156val sctr_pointful_naturalN = "sctr_pointful_natural";
157val sigN = "sig";
158val SigN = "Sig";
159val Sig_pointful_naturalN = "Sig_pointful_natural";
160val corecUN = "corecU";
161val corecU_ctorN = "corecU_ctor";
162val corecU_uniqueN = "corecU_unique";
163val unsigN = "unsig";
164val VLeafN = "VLeaf";
165
166val s_prefix = "s"; (* transforms "sig" into "ssig" *)
167
168fun not_codatatype ctxt T =
169  error ("Not a codatatype: " ^ Syntax.string_of_typ ctxt T);
170fun mutual_codatatype () =
171  error ("Mutually corecursive codatatypes are not supported (try " ^
172    quote (#1 \<^command_keyword>\<open>primcorec\<close>) ^ " instead of " ^
173    quote (#1 \<^command_keyword>\<open>corec\<close>) ^ ")");
174fun noncorecursive_codatatype () =
175  error ("Noncorecursive codatatypes are not supported (try " ^
176    quote (#1 \<^command_keyword>\<open>definition\<close>) ^ " instead of " ^
177    quote (#1 \<^command_keyword>\<open>corec\<close>) ^ ")");
178fun singleton_codatatype ctxt =
179  error ("Singleton corecursive codatatypes are not supported (use " ^
180    quote (Syntax.string_of_typ ctxt \<^typ>\<open>unit\<close>) ^ " instead)");
181
182fun merge_lists eq old1 old2 = (old1 |> subtract eq old2) @ old2;
183
184fun add_type_namesT (Type (s, Ts)) = insert (op =) s #> fold add_type_namesT Ts
185  | add_type_namesT _ = I;
186
187fun Tsubst Y T = Term.typ_subst_atomic [(Y, T)];
188fun substT Y T = Term.subst_atomic_types [(Y, T)];
189
190fun freeze_types ctxt except_tvars Ts =
191  let
192    val As = fold Term.add_tvarsT Ts [] |> subtract (op =) except_tvars;
193    val (Bs, _) = ctxt |> mk_TFrees' (map snd As);
194  in
195    map (Term.typ_subst_TVars (map fst As ~~ Bs)) Ts
196  end;
197
198fun typ_unify_disjointly thy (T, T') =
199  if T = T' then
200    T
201  else
202    let
203      val tvars = Term.add_tvar_namesT T [];
204      val tvars' = Term.add_tvar_namesT T' [];
205      val maxidx' = maxidx_of_typ T';
206      val T = T |> exists (member (op =) tvars') tvars ? Logic.incr_tvar (maxidx' + 1);
207      val maxidx = Integer.max (maxidx_of_typ T) maxidx';
208      val (tyenv, _) = Sign.typ_unify thy (T, T') (Vartab.empty, maxidx);
209    in
210      Envir.subst_type tyenv T
211    end;
212
213val dummify_atomic_types = Term.map_types (Term.map_atyps (K Term.dummyT));
214
215fun mk_internal internal ctxt f =
216  if internal andalso not (Config.get ctxt bnf_internals) then f else I
217fun mk_fp_binding fp_b pre = Binding.map_name (K pre) fp_b
218  |> Binding.qualify true (Binding.name_of fp_b);
219fun mk_version_binding version = Binding.qualify false ("v" ^ string_of_int version);
220fun mk_version_fp_binding internal ctxt =
221  mk_internal internal ctxt Binding.concealed ooo (mk_fp_binding oo mk_version_binding);
222(*FIXME: get rid of ugly names when typedef and primrec respect qualification*)
223fun mk_version_binding_ugly version = Binding.suffix_name ("_v" ^ string_of_int version);
224fun mk_version_fp_binding_ugly internal ctxt version fp_b pre =
225  Binding.prefix_name (pre ^ "_") fp_b
226  |> mk_version_binding_ugly version
227  |> mk_internal internal ctxt Binding.concealed;
228
229fun mk_mapN ctxt live_AsBs TA bnf =
230  let val TB = Term.typ_subst_atomic live_AsBs TA in
231    enforce_type ctxt (snd o strip_typeN (length live_AsBs)) (TA --> TB) (map_of_bnf bnf)
232  end;
233
234fun mk_relN ctxt live_AsBs TA bnf =
235  let val TB = Term.typ_subst_atomic live_AsBs TA in
236    enforce_type ctxt (snd o strip_typeN (length live_AsBs)) (mk_pred2T TA TB) (rel_of_bnf bnf)
237  end;
238
239fun mk_map1 ctxt Y Z = mk_mapN ctxt [(Y, Z)];
240fun mk_rel1 ctxt Y Z = mk_relN ctxt [(Y, Z)];
241
242fun define_const internal fp_b version name rhs lthy =
243  let
244    val b = mk_version_fp_binding internal lthy version fp_b name;
245
246    val ((free, (_, def_free)), (lthy, lthy_old)) = lthy
247      |> Local_Theory.open_target |> snd
248      |> Local_Theory.define ((b, NoSyn), ((Thm.def_binding b |> Binding.concealed, []), rhs))
249      ||> `Local_Theory.close_target;
250
251    val phi = Proof_Context.export_morphism lthy_old lthy;
252
253    val const = Morphism.term phi free;
254    val const' = enforce_type lthy I (fastype_of free) const;
255  in
256    ((const', Morphism.thm phi def_free), lthy)
257  end;
258
259fun define_single_primrec b eqs lthy =
260  let
261    val (([free], [def_free], [simps_free]), (lthy, lthy_old)) = lthy
262      |> Local_Theory.open_target |> snd
263      |> Local_Theory.map_background_naming (mk_internal true lthy Name_Space.concealed) (*TODO check*)
264      |> primrec false [] [(b, NONE, NoSyn)] (map (fn eq => ((Binding.empty_atts, eq), [], [])) eqs)
265      ||> `Local_Theory.close_target;
266
267    val phi = Proof_Context.export_morphism lthy_old lthy;
268
269    val const = Morphism.term phi free;
270    val const' = enforce_type lthy I (fastype_of free) const;
271  in
272    ((const', Morphism.thm phi def_free, map (Morphism.thm phi) simps_free), lthy)
273  end;
274
275type buffer =
276  {Oper: term,
277   VLeaf: term,
278   CLeaf: term,
279   ctr_wrapper: term,
280   friends: (typ * term) Symtab.table};
281
282fun map_buffer f {Oper, VLeaf, CLeaf, ctr_wrapper, friends} =
283  {Oper = f Oper, VLeaf = f VLeaf, CLeaf = f CLeaf, ctr_wrapper = f ctr_wrapper,
284   friends = Symtab.map (K (apsnd f)) friends};
285
286fun morph_buffer phi = map_buffer (Morphism.term phi);
287
288fun specialize_buffer_types {Oper, VLeaf, CLeaf, ctr_wrapper, friends} =
289  let
290    val ssig_T as Type (_, Ts) = body_type (fastype_of VLeaf);
291    val Y = List.last Ts;
292    val ssigifyT = substT Y ssig_T;
293  in
294    {Oper = Oper, VLeaf = VLeaf, CLeaf = CLeaf, ctr_wrapper = ssigifyT ctr_wrapper,
295     friends = Symtab.map (K (apsnd ssigifyT)) friends}
296  end;
297
298type dtor_coinduct_info =
299  {dtor_coinduct: thm,
300   cong_def: thm,
301   cong_locale: thm,
302   cong_base: thm,
303   cong_refl: thm,
304   cong_sym: thm,
305   cong_trans: thm,
306   cong_alg_intros: thm list};
307
308fun map_dtor_coinduct_info f {dtor_coinduct, cong_def, cong_locale, cong_base, cong_refl, cong_sym,
309    cong_trans, cong_alg_intros} =
310  {dtor_coinduct = f dtor_coinduct, cong_def = f cong_def, cong_locale = f cong_locale,
311   cong_base = f cong_base, cong_refl = f cong_refl, cong_sym = f cong_sym,
312   cong_trans = f cong_trans, cong_alg_intros = map f cong_alg_intros};
313
314fun morph_dtor_coinduct_info phi = map_dtor_coinduct_info (Morphism.thm phi);
315
316type corec_ad =
317  {fpT: typ,
318   friend_names: string list};
319
320fun morph_corec_ad phi {fpT, friend_names} =
321  {fpT = Morphism.typ phi fpT, friend_names = friend_names};
322
323type corec_info =
324  {fp_b: binding,
325   version: int,
326   fpT: typ,
327   Y: typ,
328   Z: typ,
329   friend_names: string list,
330   sig_fp_sugars: fp_sugar list,
331   ssig_fp_sugar: fp_sugar,
332   Lam: term,
333   proto_sctr: term,
334   flat: term,
335   eval_core: term,
336   eval: term,
337   algLam: term,
338   corecUU: term,
339   dtor_transfer: thm,
340   Lam_transfer: thm,
341   Lam_pointful_natural: thm,
342   proto_sctr_transfer: thm,
343   flat_simps: thm list,
344   eval_core_simps: thm list,
345   eval_thm: thm,
346   eval_simps: thm list,
347   all_algLam_algs: thm list,
348   algLam_thm: thm,
349   dtor_algLam: thm,
350   corecUU_thm: thm,
351   corecUU_unique: thm,
352   corecUU_transfer: thm,
353   buffer: buffer,
354   all_dead_k_bnfs: bnf list,
355   Retr: term,
356   equivp_Retr: thm,
357   Retr_coinduct: thm,
358   dtor_coinduct_info: dtor_coinduct_info};
359
360fun morph_corec_info phi
361    ({fp_b, version, fpT, Y, Z, friend_names, sig_fp_sugars, ssig_fp_sugar, Lam, proto_sctr, flat,
362      eval_core, eval, algLam, corecUU, dtor_transfer, Lam_transfer, Lam_pointful_natural,
363      proto_sctr_transfer, flat_simps, eval_core_simps, eval_thm, eval_simps, all_algLam_algs,
364      algLam_thm, dtor_algLam, corecUU_thm, corecUU_unique, corecUU_transfer, buffer,
365      all_dead_k_bnfs, Retr, equivp_Retr, Retr_coinduct, dtor_coinduct_info} : corec_info) =
366  {fp_b = fp_b, version = version, fpT = Morphism.typ phi fpT, Y = Morphism.typ phi Y,
367   Z = Morphism.typ phi Z, friend_names = friend_names, sig_fp_sugars = sig_fp_sugars (*no morph*),
368   ssig_fp_sugar = ssig_fp_sugar (*no morph*), Lam = Morphism.term phi Lam,
369   proto_sctr = Morphism.term phi proto_sctr, flat = Morphism.term phi flat,
370   eval_core = Morphism.term phi eval_core, eval = Morphism.term phi eval,
371   algLam = Morphism.term phi algLam, corecUU = Morphism.term phi corecUU,
372   dtor_transfer = dtor_transfer, Lam_transfer = Morphism.thm phi Lam_transfer,
373   Lam_pointful_natural = Morphism.thm phi Lam_pointful_natural,
374   proto_sctr_transfer = Morphism.thm phi proto_sctr_transfer,
375   flat_simps = map (Morphism.thm phi) flat_simps,
376   eval_core_simps = map (Morphism.thm phi) eval_core_simps, eval_thm = Morphism.thm phi eval_thm,
377   eval_simps = map (Morphism.thm phi) eval_simps,
378   all_algLam_algs = map (Morphism.thm phi) all_algLam_algs,
379   algLam_thm = Morphism.thm phi algLam_thm, dtor_algLam = Morphism.thm phi dtor_algLam,
380   corecUU_thm = Morphism.thm phi corecUU_thm, corecUU_unique = Morphism.thm phi corecUU_unique,
381   corecUU_transfer = Morphism.thm phi corecUU_transfer, buffer = morph_buffer phi buffer,
382   all_dead_k_bnfs = map (morph_bnf phi) all_dead_k_bnfs, Retr = Morphism.term phi Retr,
383   equivp_Retr = Morphism.thm phi equivp_Retr, Retr_coinduct = Morphism.thm phi Retr_coinduct,
384   dtor_coinduct_info = morph_dtor_coinduct_info phi dtor_coinduct_info};
385
386datatype ('a, 'b) expr =
387  Ad of 'a * (local_theory -> 'b * local_theory) |
388  Info of 'b;
389
390fun is_Ad (Ad _) = true
391  | is_Ad _ = false;
392
393fun is_Info (Info _) = true
394  | is_Info _ = false;
395
396type corec_info_expr = (corec_ad, corec_info) expr;
397
398fun morph_corec_info_expr phi (Ad (ad, f)) = Ad (morph_corec_ad phi ad, f)
399  | morph_corec_info_expr phi (Info info) = Info (morph_corec_info phi info);
400
401val transfer_corec_info_expr = morph_corec_info_expr o Morphism.transfer_morphism;
402
403type corec_data = int Symtab.table * corec_info_expr list Symtab.table list;
404
405structure Data = Generic_Data
406(
407  type T = corec_data;
408  val empty = (Symtab.empty, [Symtab.empty]);
409  val extend = I;
410  fun merge ((version_tab1, info_tabs1), (version_tab2, info_tabs2)) : T =
411    (Symtab.join (K Int.max) (version_tab1, version_tab2), info_tabs1 @ info_tabs2);
412);
413
414fun corec_ad_of_expr (Ad (ad, _)) = ad
415  | corec_ad_of_expr (Info {fpT, friend_names, ...}) = {fpT = fpT, friend_names = friend_names};
416
417fun corec_info_exprs_of_generic context fpT_name =
418  let
419    val thy = Context.theory_of context;
420    val info_tabs = snd (Data.get context);
421  in
422    maps (fn info_tab => these (Symtab.lookup info_tab fpT_name)) info_tabs
423    |> map (transfer_corec_info_expr thy)
424  end;
425
426val corec_info_exprs_of = corec_info_exprs_of_generic o Context.Proof;
427
428val keep_corec_infos = map_filter (fn Ad _ => NONE | Info info => SOME info);
429
430val corec_infos_of_generic = keep_corec_infos oo corec_info_exprs_of_generic;
431val corec_infos_of = keep_corec_infos oo corec_info_exprs_of;
432
433fun str_of_corec_ad ctxt {fpT, friend_names} =
434  "[" ^ Syntax.string_of_typ ctxt fpT ^ "; " ^ commas friend_names ^ "]";
435
436fun str_of_corec_info ctxt {fpT, version, friend_names, ...} =
437  "{" ^ Syntax.string_of_typ ctxt fpT ^ "; " ^ commas friend_names ^ "; v" ^ string_of_int version ^
438  "}";
439
440fun str_of_corec_info_expr ctxt (Ad (ad, _)) = str_of_corec_ad ctxt ad
441  | str_of_corec_info_expr ctxt (Info info) = str_of_corec_info ctxt info;
442
443fun print_corec_infos ctxt =
444  Symtab.fold (fn (fpT_name, exprs) => fn () =>
445      writeln (fpT_name ^ ":\n" ^
446        cat_lines (map (prefix "  " o str_of_corec_info_expr ctxt) exprs)))
447    (the_single (snd (Data.get (Context.Proof ctxt)))) ();
448
449val has_no_corec_info = null oo corec_info_exprs_of;
450
451fun get_name_next_version_of fpT_name ctxt =
452  let
453    val (version_tab, info_tabs) = Data.get (Context.Theory (Proof_Context.theory_of ctxt));
454    val fp_base = Long_Name.base_name fpT_name;
455    val fp_b = Binding.name fp_base;
456    val version_tab' = Symtab.map_default (fp_base, ~1) (Integer.add 1) version_tab;
457    val SOME version = Symtab.lookup version_tab' fp_base;
458    val ctxt' = ctxt
459      |> Local_Theory.background_theory (Context.theory_map (Data.put (version_tab', info_tabs)));
460  in
461    ((fp_b, version), ctxt')
462  end;
463
464type friend_info =
465  {algrho: term,
466   dtor_algrho: thm,
467   algLam_algrho: thm};
468
469fun morph_friend_info phi ({algrho, dtor_algrho, algLam_algrho} : friend_info) =
470  {algrho = Morphism.term phi algrho, dtor_algrho = Morphism.thm phi dtor_algrho,
471   algLam_algrho = Morphism.thm phi algLam_algrho};
472
473fun checked_fp_sugar_of ctxt fpT_name =
474  let
475    val fp_sugar as {X, fp_res = {Ts = fpTs, ...}, fp_ctr_sugar = {ctrXs_Tss, ...}, ...} =
476      (case fp_sugar_of ctxt fpT_name of
477        SOME (fp_sugar as {fp = Greatest_FP, ...}) => fp_sugar
478      | _ => not_codatatype ctxt (Type (fpT_name, [] (*yuck*))));
479
480    val _ =
481      if length fpTs > 1 then
482        mutual_codatatype ()
483      else if not (exists (exists (Term.exists_subtype (curry (op =) X))) ctrXs_Tss) then
484        noncorecursive_codatatype ()
485      else if ctrXs_Tss = [[X]] then
486        singleton_codatatype ctxt
487      else
488        ();
489  in
490    fp_sugar
491  end;
492
493fun bnf_kill_all_but nn bnf lthy =
494  ((empty_comp_cache, empty_unfolds), lthy)
495  |> kill_bnf I (live_of_bnf bnf - nn) bnf
496  ||> snd;
497
498fun bnf_with_deads_and_lives dead_Es live_As Y fpT T lthy =
499   let
500     val qsoty = quote o Syntax.string_of_typ lthy;
501
502     val unfreeze_fp = Tsubst Y fpT;
503
504    fun flatten_tyargs Ass =
505      map dest_TFree live_As
506      |> filter (fn T => exists (fn Ts => member (op =) Ts T) Ass);
507
508    val ((bnf, _), (_, lthy)) =
509      bnf_of_typ false Do_Inline I flatten_tyargs [Term.dest_TFree Y] (map Term.dest_TFree dead_Es)
510        T ((empty_comp_cache, empty_unfolds), lthy)
511      handle BAD_DEAD (Y, Y_backdrop) =>
512        (case Y_backdrop of
513          Type (bad_tc, _) =>
514          let
515            val T = qsoty (unfreeze_fp Y);
516            val T_backdrop = qsoty (unfreeze_fp Y_backdrop);
517            fun register_hint () =
518              "\nUse the " ^ quote (#1 \<^command_keyword>\<open>bnf\<close>) ^ " command to register " ^
519              quote bad_tc ^ " as a bounded natural functor to allow nested (co)recursion through \
520              \it";
521          in
522            if is_some (bnf_of lthy bad_tc) orelse is_some (fp_sugar_of lthy bad_tc) then
523              error ("Inadmissible occurrence of type " ^ T ^ " in type expression " ^
524                T_backdrop)
525            else
526              error ("Unsupported occurrence of type " ^ T ^ " via type constructor " ^
527                quote bad_tc ^ " in type expression " ^ T_backdrop ^ register_hint ())
528          end);
529
530    val phi =
531      Morphism.term_morphism "BNF" (Raw_Simplifier.rewrite_term (Proof_Context.theory_of lthy)
532        @{thms BNF_Composition.id_bnf_def} [])
533      $> Morphism.thm_morphism "BNF" (unfold_thms lthy @{thms BNF_Composition.id_bnf_def});
534  in
535    (morph_bnf phi bnf, lthy)
536  end;
537
538fun define_sig_type fp_b version fp_alives Es Y rhsT lthy =
539  let
540    val T_b = mk_version_fp_binding_ugly true lthy version fp_b sigN;
541    val ctr_b = mk_version_fp_binding false lthy version fp_b SigN;
542    val sel_b = mk_version_fp_binding true lthy version fp_b unsigN;
543
544    val lthy = Local_Theory.open_target lthy |> snd;
545
546    val T_name = Local_Theory.full_name lthy T_b;
547
548    val tyargs = map2 (fn alive => fn T =>
549        (if alive then SOME Binding.empty else NONE, (T, Type.sort_of_atyp T)))
550      (fp_alives @ [true]) (Es @ [Y]);
551    val ctr_specs = [(((Binding.empty, ctr_b), [(sel_b, rhsT)]), NoSyn)];
552    val spec = (((((tyargs, T_b), NoSyn), ctr_specs),
553      (Binding.empty, Binding.empty, Binding.empty)), []);
554
555    val plugins = Plugin_Name.make_filter lthy (K (curry (op =) transfer_plugin));
556    val discs_sels = true;
557
558    val lthy = lthy
559      |> Local_Theory.map_background_naming (mk_internal true lthy Name_Space.concealed) (*TODO check*)
560      |> with_typedef_threshold ~1
561        (co_datatypes Least_FP construct_lfp ((plugins, discs_sels), [spec]))
562      |> Local_Theory.close_target;
563
564    val SOME fp_sugar = fp_sugar_of lthy T_name;
565  in
566    (fp_sugar, lthy)
567  end;
568
569fun define_ssig_type fp_b version fp_alives Es Y fpT lthy =
570  let
571    val sig_T_b = mk_version_fp_binding_ugly true lthy version fp_b sigN;
572    val T_b = Binding.prefix_name s_prefix sig_T_b;
573    val Oper_b = mk_version_fp_binding false lthy version fp_b OperN;
574    val VLeaf_b = mk_version_fp_binding false lthy version fp_b VLeafN;
575    val CLeaf_b = mk_version_fp_binding false lthy version fp_b CLeafN;
576
577    val lthy = Local_Theory.open_target lthy |> snd;
578
579    val sig_T_name = Local_Theory.full_name lthy sig_T_b;
580    val T_name = Long_Name.map_base_name (prefix s_prefix) sig_T_name;
581
582    val As = Es @ [Y];
583    val ssig_sig_T = Type (sig_T_name, Es @ [Type (T_name, As)]);
584
585    val tyargs = map2 (fn alive => fn T =>
586        (if alive then SOME Binding.empty else NONE, (T, Type.sort_of_atyp T)))
587      (fp_alives @ [true]) (Es @ [Y]);
588    val ctr_specs =
589      [(((Binding.empty, Oper_b), [(Binding.empty, ssig_sig_T)]), NoSyn),
590       (((Binding.empty, VLeaf_b), [(Binding.empty, Y)]), NoSyn),
591       (((Binding.empty, CLeaf_b), [(Binding.empty, fpT)]), NoSyn)];
592    val spec = (((((tyargs, T_b), NoSyn), ctr_specs),
593      (Binding.empty, Binding.empty, Binding.empty)), []);
594
595    val plugins = Plugin_Name.make_filter lthy (K (curry (op =) transfer_plugin));
596    val discs_sels = false;
597
598    val lthy = lthy
599      |> Local_Theory.map_background_naming (mk_internal true lthy Name_Space.concealed) (*TODO check*)
600      |> with_typedef_threshold ~1
601        (co_datatypes Least_FP construct_lfp ((plugins, discs_sels), [spec]))
602      |> Local_Theory.close_target;
603
604    val SOME fp_sugar = fp_sugar_of lthy T_name;
605  in
606    (fp_sugar, lthy)
607  end;
608
609fun embed_Sig ctxt Sig inl_or_r t =
610  Library.foldl1 HOLogic.mk_comp [Sig, inl_or_r, dummify_atomic_types t]
611  |> Syntax.check_term ctxt;
612
613fun mk_ctr_wrapper_friends ctxt friend_name friend_T old_sig_T k_T Sig old_buffer =
614  let
615    val embed_Sig_inl = embed_Sig ctxt Sig (Inl_const old_sig_T k_T);
616
617    val ctr_wrapper = embed_Sig_inl (#ctr_wrapper old_buffer);
618    val friends = Symtab.map (K (apsnd embed_Sig_inl)) (#friends old_buffer)
619      |> Symtab.update_new (friend_name, (friend_T,
620        HOLogic.mk_comp (Sig, Inr_const old_sig_T k_T)));
621  in
622    (ctr_wrapper, friends)
623  end;
624
625fun pre_type_of_ctor Y ctor =
626  let
627    val (fp_preT, fpT) = dest_funT (fastype_of ctor);
628  in
629    typ_subst_nonatomic [(fpT, Y)] fp_preT
630  end;
631
632fun mk_k_as_ssig Z old_sig_T k_T ssig_T Sig dead_sig_map Oper VLeaf =
633  let
634    val inr' = Inr_const old_sig_T k_T;
635    val dead_sig_map' = substT Z ssig_T dead_sig_map;
636  in
637    Library.foldl1 HOLogic.mk_comp [Oper, dead_sig_map' $ VLeaf, Sig, inr']
638  end;
639
640fun define_embL name fp_b version Y Z fpT old_sig_T old_ssig_T other_summand_T ssig_T Inl_or_r_const
641    dead_old_sig_map Sig old_Oper old_VLeaf old_CLeaf Oper VLeaf CLeaf lthy =
642  let
643    val embL_b = mk_version_fp_binding true lthy version fp_b name;
644    val old_ssig_old_sig_T = Tsubst Y old_ssig_T old_sig_T;
645    val ssig_old_sig_T = Tsubst Y ssig_T old_sig_T;
646    val ssig_other_summand_T = Tsubst Y ssig_T other_summand_T;
647
648    val sigx = Var (("s", 0), old_ssig_old_sig_T);
649    val x = Var (("x", 0), Y);
650    val j = Var (("j", 0), fpT);
651    val embL = Free (Binding.name_of embL_b, old_ssig_T --> ssig_T);
652    val dead_old_sig_map' = Term.subst_atomic_types [(Y, old_ssig_T), (Z, ssig_T)] dead_old_sig_map;
653    val Sig' = substT Y ssig_T Sig;
654    val inl' = Inl_or_r_const ssig_old_sig_T ssig_other_summand_T;
655
656    val Oper_eq = mk_Trueprop_eq (embL $ (old_Oper $ sigx),
657        Oper $ (Sig' $ (inl' $ (dead_old_sig_map' $ embL $ sigx))))
658      |> Logic.all sigx;
659    val VLeaf_eq = mk_Trueprop_eq (embL $ (old_VLeaf $ x), VLeaf $ x)
660      |> Logic.all x;
661    val CLeaf_eq = mk_Trueprop_eq (embL $ (old_CLeaf $ j), CLeaf $ j)
662      |> Logic.all j;
663  in
664    define_single_primrec embL_b [Oper_eq, VLeaf_eq, CLeaf_eq] lthy
665  end;
666
667fun define_Lam_base fp_b version Y Z preT ssig_T dead_pre_map Sig unsig dead_sig_map Oper VLeaf
668    lthy =
669  let
670    val YpreT = HOLogic.mk_prodT (Y, preT);
671
672    val snd' = snd_const YpreT;
673    val dead_pre_map' = substT Z ssig_T dead_pre_map;
674    val Sig' = substT Y ssig_T Sig;
675    val unsig' = substT Y ssig_T unsig;
676    val dead_sig_map' = Term.subst_atomic_types [(Y, YpreT), (Z, ssig_T)] dead_sig_map;
677
678    val rhs = HOLogic.mk_comp (unsig', dead_sig_map'
679      $ Library.foldl1 HOLogic.mk_comp [Oper, Sig', dead_pre_map' $ VLeaf, snd']);
680  in
681    define_const true fp_b version LamN rhs lthy
682  end;
683
684fun define_Lam_step_or_merge fp_b version Y preT unsig left_case right_case lthy =
685  let
686    val YpreT = HOLogic.mk_prodT (Y, preT);
687
688    val unsig' = substT Y YpreT unsig;
689
690    val rhs = HOLogic.mk_comp (mk_case_sum (left_case, right_case), unsig');
691  in
692    define_const true fp_b version LamN rhs lthy
693  end;
694
695fun define_Lam_step fp_b version Y Z preT old_ssig_T ssig_T dead_pre_map unsig rho embL old_Lam
696    lthy =
697  let
698    val dead_pre_map' = Term.subst_atomic_types [(Y, old_ssig_T), (Z, ssig_T)] dead_pre_map;
699    val left_case = HOLogic.mk_comp (dead_pre_map' $ embL, old_Lam);
700  in
701    define_Lam_step_or_merge fp_b version Y preT unsig left_case rho lthy
702  end;
703
704fun define_Lam_merge fp_b version Y Z preT old1_ssig_T old2_ssig_T ssig_T dead_pre_map unsig embLL
705    embLR old1_Lam old2_Lam lthy =
706  let
707    val dead_pre_map' = Term.subst_atomic_types [(Y, old1_ssig_T), (Z, ssig_T)] dead_pre_map;
708    val dead_pre_map'' = Term.subst_atomic_types [(Y, old2_ssig_T), (Z, ssig_T)] dead_pre_map;
709    val left_case = HOLogic.mk_comp (dead_pre_map' $ embLL, old1_Lam);
710    val right_case = HOLogic.mk_comp (dead_pre_map'' $ embLR, old2_Lam);
711  in
712    define_Lam_step_or_merge fp_b version Y preT unsig left_case right_case lthy
713  end;
714
715fun define_proto_sctr_step_or_merge fp_b version old_sig_T right_T Sig old_proto_sctr =
716  let
717    val rhs = Library.foldl1 HOLogic.mk_comp [Sig, Inl_const old_sig_T right_T, old_proto_sctr];
718  in
719    define_const true fp_b version proto_sctrN rhs
720  end;
721
722fun define_flat fp_b version Y Z fpT sig_T ssig_T Oper VLeaf CLeaf dead_sig_map lthy =
723  let
724    val flat_b = mk_version_fp_binding true lthy version fp_b flatN;
725    val ssig_sig_T = Tsubst Y ssig_T sig_T;
726    val ssig_ssig_sig_T = Tsubst Y ssig_T ssig_sig_T;
727    val ssig_ssig_T = Tsubst Y ssig_T ssig_T;
728
729    val sigx = Var (("s", 0), ssig_ssig_sig_T);
730    val x = Var (("x", 0), ssig_T);
731    val j = Var (("j", 0), fpT);
732    val flat = Free (Binding.name_of flat_b, ssig_ssig_T --> ssig_T);
733    val Oper' = substT Y ssig_T Oper;
734    val VLeaf' = substT Y ssig_T VLeaf;
735    val CLeaf' = substT Y ssig_T CLeaf;
736    val dead_sig_map' = Term.subst_atomic_types [(Y, ssig_ssig_T), (Z, ssig_T)] dead_sig_map;
737
738    val Oper_eq = mk_Trueprop_eq (flat $ (Oper' $ sigx), Oper $ (dead_sig_map' $ flat $ sigx))
739      |> Logic.all sigx;
740    val VLeaf_eq = mk_Trueprop_eq (flat $ (VLeaf' $ x), x)
741      |> Logic.all x;
742    val CLeaf_eq = mk_Trueprop_eq (flat $ (CLeaf' $ j), CLeaf $ j)
743      |> Logic.all j;
744  in
745    define_single_primrec flat_b [Oper_eq, VLeaf_eq, CLeaf_eq] lthy
746  end;
747
748fun define_eval_core fp_b version Y Z preT fpT sig_T ssig_T dtor Oper VLeaf CLeaf dead_pre_map
749    dead_sig_map dead_ssig_map flat Lam lthy =
750  let
751    val eval_core_b = mk_version_fp_binding true lthy version fp_b eval_coreN;
752    val YpreT = HOLogic.mk_prodT (Y, preT);
753    val Ypre_ssig_T = Tsubst Y YpreT ssig_T;
754    val Ypre_ssig_sig_T = Tsubst Y Ypre_ssig_T sig_T;
755    val ssig_preT = Tsubst Y ssig_T preT;
756    val ssig_YpreT = Tsubst Y ssig_T YpreT;
757    val ssig_ssig_T = Tsubst Y ssig_T ssig_T;
758
759    val sigx = Var (("s", 0), Ypre_ssig_sig_T);
760    val x = Var (("x", 0), YpreT);
761    val j = Var (("j", 0), fpT);
762    val eval_core = Free (Binding.name_of eval_core_b, Ypre_ssig_T --> ssig_preT);
763    val Oper' = substT Y YpreT Oper;
764    val VLeaf' = substT Y YpreT VLeaf;
765    val CLeaf' = substT Y YpreT CLeaf;
766    val dead_pre_map' = Term.subst_atomic_types [(Y, ssig_ssig_T), (Z, ssig_T)] dead_pre_map;
767    val dead_pre_map'' = substT Z ssig_T dead_pre_map;
768    val dead_pre_map''' = Term.subst_atomic_types [(Y, fpT), (Z, ssig_T)] dead_pre_map;
769    val dead_sig_map' = Term.subst_atomic_types [(Y, Ypre_ssig_T), (Z, ssig_YpreT)] dead_sig_map;
770    val dead_ssig_map' = Term.subst_atomic_types [(Y, YpreT), (Z, Y)] dead_ssig_map;
771    val Lam' = substT Y ssig_T Lam;
772    val fst' = fst_const YpreT;
773    val snd' = snd_const YpreT;
774
775    val Oper_eq = mk_Trueprop_eq (eval_core $ (Oper' $ sigx),
776        dead_pre_map' $ flat $ (Lam' $ (dead_sig_map' $ (Abs (Name.uu, Ypre_ssig_T,
777          HOLogic.mk_prod (dead_ssig_map' $ fst' $ Bound 0, eval_core $ Bound 0))) $ sigx)))
778      |> Logic.all sigx;
779    val VLeaf_eq = mk_Trueprop_eq (eval_core $ (VLeaf' $ x), dead_pre_map'' $ VLeaf $ (snd' $ x))
780      |> Logic.all x;
781    val CLeaf_eq = mk_Trueprop_eq (eval_core $ (CLeaf' $ j), dead_pre_map''' $ CLeaf $ (dtor $ j))
782      |> Logic.all j;
783  in
784    define_single_primrec eval_core_b [Oper_eq, VLeaf_eq, CLeaf_eq] lthy
785  end;
786
787fun define_eval fp_b version Y Z preT fpT ssig_T dtor dtor_unfold dead_ssig_map eval_core lthy =
788  let
789    val fp_preT = Tsubst Y fpT preT;
790    val fppreT = HOLogic.mk_prodT (fpT, fp_preT);
791    val fp_ssig_T = Tsubst Y fpT ssig_T;
792
793    val dtor_unfold' = substT Z fp_ssig_T dtor_unfold;
794    val dead_ssig_map' = Term.subst_atomic_types [(Y, fpT), (Z, fppreT)] dead_ssig_map;
795    val eval_core' = substT Y fpT eval_core;
796    val id' = HOLogic.id_const fpT;
797
798    val rhs = dtor_unfold' $ HOLogic.mk_comp (eval_core', dead_ssig_map' $ mk_convol (id', dtor));
799  in
800    define_const true fp_b version evalN rhs lthy
801  end;
802
803fun define_cutSsig fp_b version Y Z preT ssig_T dead_pre_map VLeaf dead_ssig_map flat eval_core
804    lthy =
805  let
806    val ssig_preT = Tsubst Y ssig_T preT;
807    val ssig_ssig_T = Tsubst Y ssig_T ssig_T;
808    val ssig_ssig_preT = HOLogic.mk_prodT (ssig_T, ssig_preT);
809
810    val h = Var (("h", 0), Y --> ssig_preT);
811    val dead_pre_map' = Term.subst_atomic_types [(Y, ssig_ssig_T), (Z, ssig_T)] dead_pre_map;
812    val dead_ssig_map' = substT Z ssig_ssig_preT dead_ssig_map;
813    val eval_core' = substT Y ssig_T eval_core;
814
815    val rhs = Library.foldl1 HOLogic.mk_comp [dead_pre_map' $ flat, eval_core',
816        dead_ssig_map' $ mk_convol (VLeaf, h)]
817      |> Term.lambda h;
818  in
819    define_const true fp_b version cutSsigN rhs lthy
820  end;
821
822fun define_algLam fp_b version Y Z fpT ssig_T Oper VLeaf dead_sig_map eval lthy =
823  let
824    val fp_ssig_T = Tsubst Y fpT ssig_T;
825
826    val Oper' = substT Y fpT Oper;
827    val VLeaf' = substT Y fpT VLeaf;
828    val dead_sig_map' = Term.subst_atomic_types [(Y, fpT), (Z, fp_ssig_T)] dead_sig_map;
829
830    val rhs = Library.foldl1 HOLogic.mk_comp [eval, Oper', dead_sig_map' $ VLeaf'];
831  in
832    define_const true fp_b version algLamN rhs lthy
833  end;
834
835fun define_corecU fp_b version Y Z preT ssig_T dtor_unfold VLeaf cutSsig lthy =
836  let
837    val ssig_preT = Tsubst Y ssig_T preT;
838
839    val h = Var (("h", 0), Y --> ssig_preT);
840    val dtor_unfold' = substT Z ssig_T dtor_unfold;
841
842    val rhs = HOLogic.mk_comp (dtor_unfold' $ (cutSsig $ h), VLeaf)
843      |> Term.lambda h;
844  in
845    define_const true fp_b version corecUN rhs lthy
846  end;
847
848fun define_corecUU fp_b version Y Z preT ssig_T dead_pre_map dead_ssig_map flat eval_core sctr
849    corecU lthy =
850  let
851    val ssig_preT = Tsubst Y ssig_T preT;
852    val ssig_ssig_T = Tsubst Y ssig_T ssig_T
853    val ssig_ssig_preT = HOLogic.mk_prodT (ssig_T, ssig_preT);
854
855    val ssig_pre_ssig_T = Tsubst Y ssig_preT ssig_T;
856
857    val h = Var (("h", 0), Y --> ssig_pre_ssig_T);
858    val dead_pre_map' = Term.subst_atomic_types [(Y, ssig_ssig_T), (Z, ssig_T)] dead_pre_map;
859    val eval_core' = substT Y ssig_T eval_core;
860    val dead_ssig_map' =
861      Term.subst_atomic_types [(Y, ssig_preT), (Z, ssig_ssig_preT)] dead_ssig_map;
862    val id' = HOLogic.id_const ssig_preT;
863
864    val rhs = corecU $ Library.foldl1 HOLogic.mk_comp
865        [dead_pre_map' $ flat, eval_core', dead_ssig_map' $ mk_convol (sctr, id'), h]
866      |> Term.lambda h;
867  in
868    define_const true fp_b version corecUUN rhs lthy
869  end;
870
871fun derive_sig_transfer maybe_swap ctxt live_AsBs pre_rel sig_rel Rs R const pre_rel_def
872    preT_rel_eqs transfer_thm =
873  let
874    val RRpre_rel = list_comb (pre_rel, Rs) $ R;
875    val RRsig_rel = list_comb (sig_rel, Rs) $ R;
876    val constB = Term.subst_atomic_types live_AsBs const;
877
878    val goal = uncurry mk_rel_fun (maybe_swap (RRpre_rel, RRsig_rel)) $ const $ constB
879      |> HOLogic.mk_Trueprop;
880  in
881    Variable.add_free_names ctxt goal []
882    |> (fn vars => Goal.prove_sorry ctxt vars [] goal (fn {context = ctxt, prems = _} =>
883      mk_sig_transfer_tac ctxt pre_rel_def preT_rel_eqs transfer_thm))
884    |> Thm.close_derivation \<^here>
885  end;
886
887fun derive_transfer_by_transfer_prover ctxt live_AsBs Rs R const const_defs rel_eqs transfers =
888  let
889    val constB = Term.subst_atomic_types live_AsBs const;
890    val goal = mk_parametricity_goal ctxt (Rs @ [R]) const constB;
891  in
892    Variable.add_free_names ctxt goal []
893    |> (fn vars => Goal.prove (*no sorry*) ctxt vars [] goal (fn {context = ctxt, prems = _} =>
894      mk_transfer_by_transfer_prover_tac ctxt (const_defs @ map (fn thm => thm RS sym) rel_eqs)
895        rel_eqs transfers))
896    |> Thm.close_derivation \<^here>
897  end;
898
899fun derive_dtor_transfer ctxt live_EsFs Y Z pre_rel fp_rel Rs dtor dtor_rel_thm =
900  let
901    val Type (\<^type_name>\<open>fun\<close>, [fpT, Type (\<^type_name>\<open>fun\<close>, [fpTB, \<^typ>\<open>bool\<close>])]) =
902      snd (strip_typeN (length live_EsFs) (fastype_of fp_rel));
903
904    val pre_rel' = Term.subst_atomic_types [(Y, fpT), (Z, fpTB)] pre_rel;
905    val Rpre_rel = list_comb (pre_rel', Rs);
906    val Rfp_rel = list_comb (fp_rel, Rs);
907    val dtorB = Term.subst_atomic_types live_EsFs dtor;
908
909    val goal = HOLogic.mk_Trueprop (mk_rel_fun Rfp_rel (Rpre_rel $ Rfp_rel) $ dtor $ dtorB);
910  in
911    Variable.add_free_names ctxt goal []
912    |> (fn vars => Goal.prove (*no sorry*) ctxt vars [] goal (fn {context = ctxt, prems = _} =>
913      mk_dtor_transfer_tac ctxt dtor_rel_thm))
914    |> Thm.close_derivation \<^here>
915  end;
916
917fun derive_Lam_or_eval_core_transfer ctxt live_AsBs Y Z preT ssig_T Rs R pre_rel sig_or_ssig_rel
918    ssig_rel const const_def rel_eqs transfers =
919  let
920    val YpreT = HOLogic.mk_prodT (Y, preT);
921    val ZpreTB = typ_subst_atomic live_AsBs YpreT;
922    val ssig_TB = typ_subst_atomic live_AsBs ssig_T;
923
924    val pre_rel' = Term.subst_atomic_types [(Y, ssig_T), (Z, ssig_TB)] pre_rel;
925    val sig_or_ssig_rel' = Term.subst_atomic_types [(Y, YpreT), (Z, ZpreTB)] sig_or_ssig_rel;
926    val Rsig_or_ssig_rel' = list_comb (sig_or_ssig_rel', Rs);
927    val RRpre_rel = list_comb (pre_rel, Rs) $ R;
928    val RRssig_rel = list_comb (ssig_rel, Rs) $ R;
929    val Rpre_rel' = list_comb (pre_rel', Rs);
930    val constB = subst_atomic_types live_AsBs const;
931
932    val goal = mk_rel_fun (Rsig_or_ssig_rel' $ mk_rel_prod R RRpre_rel) (Rpre_rel' $ RRssig_rel)
933        $ const $ constB
934      |> HOLogic.mk_Trueprop;
935  in
936    Variable.add_free_names ctxt goal []
937    |> (fn vars => Goal.prove (*no sorry*) ctxt vars [] goal (fn {context = ctxt, prems = _} =>
938      mk_transfer_by_transfer_prover_tac ctxt [const_def] rel_eqs transfers))
939    |> Thm.close_derivation \<^here>
940  end;
941
942fun derive_proto_sctr_transfer_step_or_merge ctxt Y Z R dead_pre_rel dead_sig_rel proto_sctr
943    proto_sctr_def fp_k_T_rel_eqs transfers =
944  let
945    val proto_sctrZ = substT Y Z proto_sctr;
946    val goal = mk_rel_fun (dead_pre_rel $ R) (dead_sig_rel $ R) $ proto_sctr $ proto_sctrZ
947      |> HOLogic.mk_Trueprop;
948  in
949    Variable.add_free_names ctxt goal []
950    |> (fn vars => Goal.prove (*no sorry*) ctxt vars [] goal (fn {context = ctxt, prems = _} =>
951      mk_transfer_by_transfer_prover_tac ctxt [proto_sctr_def] fp_k_T_rel_eqs transfers))
952    |> Thm.close_derivation \<^here>
953  end;
954
955fun derive_sctr_transfer ctxt live_AsBs Y Z ssig_T Rs R pre_rel ssig_rel sctr sctr_def
956    fp_k_T_rel_eqs transfers =
957  let
958    val ssig_TB = typ_subst_atomic live_AsBs ssig_T;
959
960    val pre_rel' = Term.subst_atomic_types [(Y, ssig_T), (Z, ssig_TB)] pre_rel;
961    val Rpre_rel' = list_comb (pre_rel', Rs);
962    val RRssig_rel = list_comb (ssig_rel, Rs) $ R;
963    val sctrB = subst_atomic_types live_AsBs sctr;
964
965    val goal = HOLogic.mk_Trueprop (mk_rel_fun (Rpre_rel' $ RRssig_rel) RRssig_rel $ sctr $ sctrB);
966  in
967    Variable.add_free_names ctxt goal []
968    |> (fn vars => Goal.prove (*no sorry*) ctxt vars [] goal (fn {context = ctxt, prems = _} =>
969      mk_transfer_by_transfer_prover_tac ctxt [sctr_def] fp_k_T_rel_eqs transfers))
970    |> Thm.close_derivation \<^here>
971  end;
972
973fun derive_corecUU_transfer ctxt live_AsBs Y Z Rs R preT ssig_T pre_rel fp_rel ssig_rel corecUU
974    cutSsig_def corecU_def corecUU_def fp_k_T_rel_eqs transfers =
975  let
976    val ssig_preT = Tsubst Y ssig_T preT;
977    val ssig_TB = typ_subst_atomic live_AsBs ssig_T;
978    val ssig_preTB = typ_subst_atomic live_AsBs ssig_preT;
979
980    val pre_rel' = Term.subst_atomic_types [(Y, ssig_T), (Z, ssig_TB)] pre_rel;
981    val ssig_rel' = Term.subst_atomic_types [(Y, ssig_preT), (Z, ssig_preTB)] ssig_rel;
982    val Rpre_rel' = list_comb (pre_rel', Rs);
983    val Rfp_rel = list_comb (fp_rel, Rs);
984    val RRssig_rel = list_comb (ssig_rel, Rs) $ R;
985    val Rssig_rel' = list_comb (ssig_rel', Rs);
986    val corecUUB = subst_atomic_types live_AsBs corecUU;
987
988    val goal = mk_rel_fun (mk_rel_fun R (Rssig_rel' $ (Rpre_rel' $ RRssig_rel)))
989        (mk_rel_fun R Rfp_rel) $ corecUU $ corecUUB
990      |> HOLogic.mk_Trueprop;
991  in
992    Variable.add_free_names ctxt goal []
993    |> (fn vars => Goal.prove (*no sorry*) ctxt vars [] goal (fn {context = ctxt, prems = _} =>
994      mk_transfer_by_transfer_prover_tac ctxt [cutSsig_def, corecU_def, corecUU_def] fp_k_T_rel_eqs
995        transfers))
996    |> Thm.close_derivation \<^here>
997  end;
998
999fun mk_natural_goal ctxt simple_T_mapfs fs t u =
1000  let
1001    fun build_simple (T, _) =
1002      (case AList.lookup (op =) simple_T_mapfs T of
1003        SOME mapf => mapf
1004      | NONE => the (find_first (fn f => domain_type (fastype_of f) = T) fs));
1005
1006    val simple_Ts = map fst simple_T_mapfs;
1007
1008    val t_map = build_map ctxt simple_Ts [] build_simple (apply2 (range_type o fastype_of) (t, u));
1009    val u_map = build_map ctxt simple_Ts [] build_simple (apply2 (domain_type o fastype_of) (t, u));
1010  in
1011    mk_Trueprop_eq (HOLogic.mk_comp (u, u_map), HOLogic.mk_comp (t_map, t))
1012  end;
1013
1014fun derive_natural_by_unfolding ctxt live_AsBs preT pre_map fs f const map_thms =
1015  let
1016    val ffpre_map = list_comb (pre_map, fs) $ f;
1017    val constB = subst_atomic_types live_AsBs const;
1018
1019    val goal = mk_natural_goal ctxt [(preT, ffpre_map)] (fs @ [f]) const constB;
1020  in
1021    Variable.add_free_names ctxt goal []
1022    |> (fn vars => Goal.prove_sorry ctxt vars [] goal (fn {context = ctxt, prems = _} =>
1023      mk_natural_by_unfolding_tac ctxt map_thms))
1024    |> Thm.close_derivation \<^here>
1025  end;
1026
1027fun derive_natural_from_transfer ctxt live_AsBs simple_T_mapfs fs f const transfer bnfs subst_bnfs =
1028  let
1029    val m = length live_AsBs;
1030
1031    val constB = Term.subst_atomic_types live_AsBs const;
1032    val goal = mk_natural_goal ctxt simple_T_mapfs (fs @ [f]) const constB;
1033  in
1034    Variable.add_free_names ctxt goal []
1035    |> (fn vars => Goal.prove_sorry ctxt vars [] goal (fn {context = ctxt, prems = _} =>
1036      mk_natural_from_transfer_tac ctxt m (replicate m true) transfer [] (map rel_Grp_of_bnf bnfs)
1037        (map rel_Grp_of_bnf subst_bnfs)))
1038    |> Thm.close_derivation \<^here>
1039  end;
1040
1041fun derive_natural_from_transfer_with_pre_type ctxt live_AsBs Y Z preT ssig_T pre_map ssig_map fs
1042    f =
1043  let
1044    val ssig_TB = typ_subst_atomic live_AsBs ssig_T;
1045    val preT' = Term.typ_subst_atomic [(Y, ssig_T), (Z, ssig_TB)] preT;
1046
1047    val ffpre_map = list_comb (pre_map, fs) $ f;
1048    val pre_map' = Term.subst_atomic_types [(Y, ssig_T), (Z, ssig_TB)] pre_map;
1049    val fpre_map' = list_comb (pre_map', fs);
1050    val ffssig_map = list_comb (ssig_map, fs) $ f;
1051
1052    val preT_mapfs = [(preT, ffpre_map), (preT', fpre_map' $ ffssig_map)];
1053  in
1054    derive_natural_from_transfer ctxt live_AsBs preT_mapfs fs f
1055  end;
1056
1057fun derive_Lam_Inl_Inr ctxt Y Z preT old_sig_T old_ssig_T k_T ssig_T dead_pre_map Sig embL old_Lam
1058    Lam rho unsig_thm Lam_def =
1059  let
1060    val YpreT = HOLogic.mk_prodT (Y, preT);
1061    val Ypre_old_sig_T = Tsubst Y YpreT old_sig_T;
1062    val Ypre_k_T = Tsubst Y YpreT k_T;
1063
1064    val inl' = Inl_const Ypre_old_sig_T Ypre_k_T;
1065    val inr' = Inr_const Ypre_old_sig_T Ypre_k_T;
1066    val dead_pre_map' = Term.subst_atomic_types [(Y, old_ssig_T), (Z, ssig_T)] dead_pre_map;
1067    val Sig' = substT Y YpreT Sig;
1068    val Lam_o_Sig = HOLogic.mk_comp (Lam, Sig');
1069
1070    val inl_goal = mk_Trueprop_eq (HOLogic.mk_comp (Lam_o_Sig, inl'),
1071      HOLogic.mk_comp (dead_pre_map' $ embL, old_Lam));
1072    val inr_goal = mk_Trueprop_eq (HOLogic.mk_comp (Lam_o_Sig, inr'), rho);
1073    val goals = [inl_goal, inr_goal];
1074    val goal = Logic.mk_conjunction_balanced goals;
1075  in
1076    Variable.add_free_names ctxt goal []
1077    |> (fn vars => Goal.prove_sorry ctxt vars [] goal
1078      (fn {context = ctxt, prems = _} => mk_Lam_Inl_Inr_tac ctxt unsig_thm Lam_def))
1079    |> Conjunction.elim_balanced (length goals)
1080    |> map (Thm.close_derivation \<^here>)
1081  end;
1082
1083fun derive_flat_VLeaf ctxt Y Z ssig_T x VLeaf dead_ssig_map flat ssig_induct fp_map_id sig_map_cong
1084    sig_map_ident sig_map_comp ssig_map_thms flat_simps =
1085  let
1086    val x' = substT Y ssig_T x;
1087    val dead_ssig_map' = substT Z ssig_T dead_ssig_map;
1088
1089    val goal = mk_Trueprop_eq (flat $ (dead_ssig_map' $ VLeaf $ x'), x');
1090
1091    val ssig_induct' = infer_instantiate' ctxt [NONE, SOME (Thm.cterm_of ctxt x')] ssig_induct;
1092  in
1093    Variable.add_free_names ctxt goal []
1094    |> (fn vars => Goal.prove_sorry ctxt vars [] goal (fn {context = ctxt, prems = _} =>
1095      mk_flat_VLeaf_or_flat_tac ctxt ssig_induct' sig_map_cong
1096        (fp_map_id :: sig_map_ident :: sig_map_comp :: ssig_map_thms @ flat_simps @
1097         @{thms o_apply id_apply id_def[symmetric]})))
1098    |> Thm.close_derivation \<^here>
1099  end;
1100
1101fun derive_flat_flat ctxt Y Z ssig_T x dead_ssig_map flat ssig_induct fp_map_id sig_map_cong
1102    sig_map_comp ssig_map_thms flat_simps =
1103  let
1104    val ssig_ssig_T = Tsubst Y ssig_T ssig_T;
1105    val ssig_ssig_ssig_T = Tsubst Y ssig_T ssig_ssig_T;
1106
1107    val x' = substT Y ssig_ssig_ssig_T x;
1108    val dead_ssig_map' = Term.subst_atomic_types [(Y, ssig_ssig_T), (Z, ssig_T)] dead_ssig_map;
1109    val flat' = substT Y ssig_T flat;
1110
1111    val goal = mk_Trueprop_eq (flat $ (dead_ssig_map' $ flat $ x'), flat $ (flat' $ x'));
1112
1113    val ssig_induct' = infer_instantiate' ctxt [NONE, SOME (Thm.cterm_of ctxt x')] ssig_induct;
1114  in
1115    Variable.add_free_names ctxt goal []
1116    |> (fn vars => Goal.prove_sorry ctxt vars [] goal (fn {context = ctxt, prems = _} =>
1117      mk_flat_VLeaf_or_flat_tac ctxt ssig_induct' sig_map_cong
1118        (o_apply :: fp_map_id :: sig_map_comp :: ssig_map_thms @ flat_simps)))
1119    |> Thm.close_derivation \<^here>
1120  end;
1121
1122fun derive_eval_core_flat ctxt Y Z preT ssig_T dead_pre_map dead_ssig_map flat eval_core x
1123    ssig_induct dead_pre_map_id dead_pre_map_comp0 dead_pre_map_comp fp_map_id sig_map_comp
1124    sig_map_cong ssig_map_thms ssig_map_comp flat_simps flat_pointful_natural flat_flat
1125    Lam_pointful_natural eval_core_simps =
1126  let
1127    val YpreT = HOLogic.mk_prodT (Y, preT);
1128    val ssig_ssig_T = Tsubst Y ssig_T ssig_T;
1129    val Ypre_ssig_T = Tsubst Y YpreT ssig_T;
1130    val Ypre_ssig_ssig_T = Tsubst Y YpreT ssig_ssig_T;
1131    val ssig_YpreT = Tsubst Y ssig_T YpreT;
1132
1133    val dead_pre_map' = Term.subst_atomic_types [(Y, ssig_ssig_T), (Z, ssig_T)] dead_pre_map;
1134    val dead_ssig_map' = Term.subst_atomic_types [(Y, Ypre_ssig_T), (Z, ssig_YpreT)] dead_ssig_map;
1135    val dead_ssig_map'' = Term.subst_atomic_types [(Y, YpreT), (Z, Y)] dead_ssig_map;
1136    val flat' = substT Y YpreT flat;
1137    val eval_core' = substT Y ssig_T eval_core;
1138    val x' = substT Y Ypre_ssig_ssig_T x;
1139    val fst' = fst_const YpreT;
1140
1141    val goal = mk_Trueprop_eq (eval_core $ (flat' $ x'), dead_pre_map' $ flat
1142      $ (eval_core' $ (dead_ssig_map' $ mk_convol (dead_ssig_map'' $ fst', eval_core) $ x')));
1143
1144    val ssig_induct' = infer_instantiate' ctxt [NONE, SOME (Thm.cterm_of ctxt x')] ssig_induct;
1145  in
1146    Variable.add_free_names ctxt goal []
1147    |> (fn vars => Goal.prove_sorry ctxt vars [] goal (fn {context = ctxt, prems = _} =>
1148      mk_eval_core_flat_tac ctxt ssig_induct' dead_pre_map_id dead_pre_map_comp0 dead_pre_map_comp
1149        fp_map_id sig_map_comp sig_map_cong ssig_map_thms ssig_map_comp flat_simps
1150        flat_pointful_natural flat_flat Lam_pointful_natural eval_core_simps))
1151    |> Thm.close_derivation \<^here>
1152  end;
1153
1154fun derive_eval_thm ctxt dtor_inject dtor_unfold_thm eval_def =
1155  (trans OF [iffD2 OF [dtor_inject, HOLogic.mk_obj_eq eval_def RS fun_cong], dtor_unfold_thm])
1156  |> unfold_thms ctxt [o_apply, eval_def RS symmetric_thm];
1157
1158fun derive_eval_flat ctxt Y Z fpT ssig_T dead_ssig_map flat eval x dead_pre_map_comp0
1159    dtor_unfold_unique ssig_map_id ssig_map_comp flat_pointful_natural eval_core_pointful_natural
1160    eval_core_flat eval_thm =
1161  let
1162    val fp_ssig_T = Tsubst Y fpT ssig_T;
1163    val fp_ssig_ssig_T = Tsubst Y fp_ssig_T ssig_T;
1164
1165    val dead_ssig_map' = Term.subst_atomic_types [(Y, fp_ssig_T), (Z, fpT)] dead_ssig_map;
1166    val flat' = substT Y fpT flat;
1167    val x' = substT Y fp_ssig_ssig_T x;
1168
1169    val goal = mk_Trueprop_eq (eval $ (flat' $ x'), eval $ (dead_ssig_map' $ eval $ x'));
1170
1171    val cond_eval_o_flat =
1172      infer_instantiate' ctxt [SOME (Thm.cterm_of ctxt (HOLogic.mk_comp (eval, flat')))]
1173        (trans OF [dtor_unfold_unique, dtor_unfold_unique RS sym] RS fun_cong)
1174      OF [ext, ext];
1175  in
1176    Variable.add_free_names ctxt goal []
1177    |> (fn vars => Goal.prove_sorry ctxt vars [] goal (fn {context = ctxt, prems = _} =>
1178      mk_eval_flat_tac ctxt dead_pre_map_comp0 ssig_map_id ssig_map_comp flat_pointful_natural
1179        eval_core_pointful_natural eval_core_flat eval_thm cond_eval_o_flat))
1180    |> Thm.close_derivation \<^here>
1181  end;
1182
1183fun derive_eval_Oper ctxt live Y Z fpT sig_T ssig_T dead_sig_map Oper eval algLam x sig_map_ident
1184    sig_map_comp0 sig_map_comp Oper_natural_pointful VLeaf_natural flat_simps eval_flat algLam_def =
1185  let
1186    val fp_ssig_T = Tsubst Y fpT ssig_T;
1187    val fp_ssig_sig_T = Tsubst Y fp_ssig_T sig_T;
1188
1189    val dead_sig_map' = Term.subst_atomic_types [(Y, fp_ssig_T), (Z, fpT)] dead_sig_map;
1190    val Oper' = substT Y fpT Oper;
1191    val x' = substT Y fp_ssig_sig_T x;
1192
1193    val goal = mk_Trueprop_eq (eval $ (Oper' $ x'), algLam $ (dead_sig_map' $ eval $ x'));
1194  in
1195    Variable.add_free_names ctxt goal []
1196    |> (fn vars => Goal.prove_sorry ctxt vars [] goal (fn {context = ctxt, prems = _} =>
1197      mk_eval_Oper_tac ctxt live sig_map_ident sig_map_comp0 sig_map_comp Oper_natural_pointful
1198        VLeaf_natural flat_simps eval_flat algLam_def))
1199    |> Thm.close_derivation \<^here>
1200  end;
1201
1202fun derive_eval_V_or_CLeaf ctxt Y fpT V_or_CLeaf eval x dead_pre_map_id dead_pre_map_comp fp_map_id
1203    dtor_unfold_unique V_or_CLeaf_map_thm eval_core_simps eval_thm =
1204  let
1205    val V_or_CLeaf' = substT Y fpT V_or_CLeaf;
1206    val x' = substT Y fpT x;
1207
1208    val goal = mk_Trueprop_eq (eval $ (V_or_CLeaf' $ x'), x');
1209  in
1210    Variable.add_free_names ctxt goal []
1211    |> (fn vars => Goal.prove_sorry ctxt vars [] goal (fn {context = ctxt, prems = _} =>
1212      mk_eval_V_or_CLeaf_tac ctxt dead_pre_map_id dead_pre_map_comp fp_map_id dtor_unfold_unique
1213        V_or_CLeaf_map_thm eval_core_simps eval_thm))
1214    |> Thm.close_derivation \<^here>
1215  end;
1216
1217fun derive_extdd_mor ctxt Y Z preT fpT ssig_T dead_pre_map dtor extdd cutSsig f g dead_pre_map_comp0
1218    dead_pre_map_comp VLeaf_map_thm ssig_map_comp flat_pointful_natural eval_core_pointful_natural
1219    eval_thm eval_flat eval_VLeaf cutSsig_def =
1220  let
1221    val ssig_preT = Tsubst Y ssig_T preT;
1222
1223    val dead_pre_map' = Term.subst_atomic_types [(Y, ssig_T), (Z, fpT)] dead_pre_map;
1224    val f' = substT Z fpT f;
1225    val g' = substT Z ssig_preT g;
1226    val extdd_f = extdd $ f';
1227
1228    val prem = mk_Trueprop_eq (HOLogic.mk_comp (dead_pre_map' $ extdd_f, g'),
1229      HOLogic.mk_comp (dtor, f'));
1230    val goal = mk_Trueprop_eq (HOLogic.mk_comp (dead_pre_map' $ extdd_f, cutSsig $ g'),
1231      HOLogic.mk_comp (dtor, extdd_f));
1232  in
1233    fold (Variable.add_free_names ctxt) [prem, goal] []
1234    |> (fn vars => Goal.prove_sorry ctxt vars [prem] goal (fn {context = ctxt, prems = [prem]} =>
1235      mk_extdd_mor_tac ctxt dead_pre_map_comp0 dead_pre_map_comp VLeaf_map_thm ssig_map_comp
1236        flat_pointful_natural eval_core_pointful_natural eval_thm eval_flat eval_VLeaf cutSsig_def
1237        prem))
1238    |> Thm.close_derivation \<^here>
1239  end;
1240
1241fun derive_mor_cutSsig_flat ctxt Y Z preT fpT ssig_T dead_pre_map dead_ssig_map dtor flat eval_core
1242    eval cutSsig f g dead_pre_map_comp0 dead_pre_map_comp dead_pre_map_cong dtor_unfold_unique
1243    dead_ssig_map_comp0 ssig_map_comp flat_simps flat_pointful_natural eval_core_pointful_natural
1244    flat_flat flat_VLeaf eval_core_flat cutSsig_def cutSsig_def_pointful_natural eval_thm =
1245  let
1246    val ssig_preT = Tsubst Y ssig_T preT;
1247
1248    val substYZ = Term.subst_atomic_types [(Y, ssig_T), (Z, fpT)];
1249
1250    val dead_pre_map' = substYZ dead_pre_map;
1251    val dead_ssig_map' = substYZ dead_ssig_map;
1252    val f' = substYZ f;
1253    val g' = substT Z ssig_preT g;
1254    val cutSsig_g = cutSsig $ g';
1255
1256    val id' = HOLogic.id_const ssig_T;
1257    val convol' = mk_convol (id', cutSsig_g);
1258    val dead_ssig_map'' =
1259      Term.subst_atomic_types [(Y, ssig_T), (Z, range_type (fastype_of convol'))] dead_ssig_map;
1260    val eval_core' = substT Y ssig_T eval_core;
1261    val eval_core_o_map = HOLogic.mk_comp (eval_core', dead_ssig_map'' $ convol');
1262
1263    val prem = mk_Trueprop_eq (HOLogic.mk_comp (dead_pre_map' $ f', cutSsig_g),
1264      HOLogic.mk_comp (dtor, f'));
1265    val goal = mk_Trueprop_eq (HOLogic.mk_comp (eval, dead_ssig_map' $ f'),
1266      HOLogic.mk_comp (f', flat));
1267  in
1268    fold (Variable.add_free_names ctxt) [prem, goal] []
1269    |> (fn vars => Goal.prove_sorry ctxt vars [prem] goal (fn {context = ctxt, prems = [prem]} =>
1270      mk_mor_cutSsig_flat_tac ctxt eval_core_o_map dead_pre_map_comp0 dead_pre_map_comp
1271        dead_pre_map_cong dtor_unfold_unique dead_ssig_map_comp0 ssig_map_comp flat_simps
1272        flat_pointful_natural eval_core_pointful_natural flat_flat flat_VLeaf eval_core_flat
1273        cutSsig_def cutSsig_def_pointful_natural eval_thm prem))
1274    |> Thm.close_derivation \<^here>
1275  end;
1276
1277fun derive_extdd_o_VLeaf ctxt Y Z preT fpT ssig_T dead_pre_map dtor VLeaf extdd f g
1278    dead_pre_map_comp0 dead_pre_map_comp dtor_inject ssig_map_thms eval_core_simps eval_thm
1279    eval_VLeaf =
1280  let
1281    val ssig_preT = Tsubst Y ssig_T preT;
1282
1283    val substYZ = Term.subst_atomic_types [(Y, ssig_T), (Z, fpT)];
1284
1285    val dead_pre_map' = substYZ dead_pre_map;
1286    val f' = substT Z fpT f;
1287    val g' = substT Z ssig_preT g;
1288    val extdd_f = extdd $ f';
1289
1290    val prem = mk_Trueprop_eq (HOLogic.mk_comp (dead_pre_map' $ extdd_f, g'),
1291      HOLogic.mk_comp (dtor, f'));
1292    val goal = mk_Trueprop_eq (HOLogic.mk_comp (extdd_f, VLeaf), f');
1293  in
1294    fold (Variable.add_free_names ctxt) [prem, goal] []
1295    |> (fn vars => Goal.prove_sorry ctxt vars [prem] goal (fn {context = ctxt, prems = [prem]} =>
1296      mk_extdd_o_VLeaf_tac ctxt dead_pre_map_comp0 dead_pre_map_comp dtor_inject ssig_map_thms
1297        eval_core_simps eval_thm eval_VLeaf prem))
1298    |> Thm.close_derivation \<^here>
1299  end;
1300
1301fun derive_corecU_pointfree ctxt Y Z preT fpT ssig_T dead_pre_map dtor extdd corecU g
1302    dead_pre_map_comp dtor_unfold_thm ssig_map_thms dead_ssig_map_comp0 flat_simps flat_VLeaf
1303    eval_core_simps cutSsig_def mor_cutSsig_flat corecU_def =
1304  let
1305    val ssig_preT = Tsubst Y ssig_T preT;
1306
1307    val substYZ = Term.subst_atomic_types [(Y, ssig_T), (Z, fpT)];
1308
1309    val dead_pre_map' = substYZ dead_pre_map;
1310    val g' = substT Z ssig_preT g;
1311    val corecU_g = corecU $ g';
1312
1313    val goal = mk_Trueprop_eq (HOLogic.mk_comp (dead_pre_map' $ (extdd $ corecU_g), g'),
1314      HOLogic.mk_comp (dtor, corecU_g));
1315  in
1316    Variable.add_free_names ctxt goal []
1317    |> (fn vars => Goal.prove_sorry ctxt vars [] goal (fn {context = ctxt, prems = _} =>
1318      mk_corecU_pointfree_tac ctxt dead_pre_map_comp dtor_unfold_thm ssig_map_thms
1319      dead_ssig_map_comp0 flat_simps flat_VLeaf eval_core_simps cutSsig_def mor_cutSsig_flat
1320      corecU_def))
1321    |> Thm.close_derivation \<^here>
1322  end;
1323
1324fun derive_corecU_ctor_unique ctxt Y Z preT fpT ssig_T dead_pre_map ctor dtor VLeaf extdd corecU f g
1325    dead_pre_map_comp ctor_dtor dtor_unfold_thm dtor_unfold_unique ssig_map_thms dead_ssig_map_comp0
1326    flat_simps flat_VLeaf eval_core_simps extdd_mor extdd_o_VLeaf cutSsig_def mor_cutSsig_flat
1327    corecU_def =
1328  let
1329    val corecU_pointfree = derive_corecU_pointfree ctxt Y Z preT fpT ssig_T dead_pre_map dtor extdd
1330      corecU g dead_pre_map_comp dtor_unfold_thm ssig_map_thms dead_ssig_map_comp0 flat_simps
1331      flat_VLeaf eval_core_simps cutSsig_def mor_cutSsig_flat corecU_def;
1332
1333    val corecU_thm = corecU_pointfree RS @{thm comp_eq_dest};
1334
1335    val corecU_ctor =
1336      let
1337        val arg_cong' =
1338          infer_instantiate' ctxt [NONE, NONE, SOME (Thm.cterm_of ctxt ctor)] arg_cong;
1339      in
1340        unfold_thms ctxt [ctor_dtor] (corecU_thm RS arg_cong')
1341      end;
1342
1343    val corecU_unique =
1344      let
1345        val substYZ = Term.subst_atomic_types [(Y, ssig_T), (Z, fpT)];
1346
1347        val f' = substYZ f;
1348        val abs_f_o_VLeaf = Term.lambda f' (HOLogic.mk_comp (f', VLeaf));
1349
1350        val inject_refine' = infer_instantiate' ctxt [SOME (Thm.cterm_of ctxt abs_f_o_VLeaf),
1351          SOME (Thm.cterm_of ctxt extdd)] @{thm inject_refine};
1352      in
1353        unfold_thms ctxt @{thms atomize_imp}
1354          (((inject_refine' OF [extdd_o_VLeaf, extdd_o_VLeaf] RS iffD1)
1355            OF [asm_rl, corecU_pointfree])
1356           OF [asm_rl, trans OF [dtor_unfold_unique, dtor_unfold_unique RS sym]
1357             OF [extdd_mor, corecU_pointfree RS extdd_mor]])
1358        RS @{thm obj_distinct_prems}
1359      end;
1360  in
1361    (corecU_ctor, corecU_unique)
1362  end;
1363
1364fun derive_dtor_algLam ctxt Y Z preT fpT sig_T ssig_T dead_pre_map dtor dead_sig_map Lam eval algLam
1365    x pre_map_comp dead_pre_map_id dead_pre_map_comp0 dead_pre_map_comp sig_map_comp
1366    Oper_pointful_natural ssig_map_thms dead_ssig_map_comp0 Lam_pointful_natural eval_core_simps
1367    eval_thm eval_flat eval_VLeaf algLam_def =
1368  let
1369    val fp_preT = Tsubst Y fpT preT;
1370    val fppreT = HOLogic.mk_prodT (fpT, fp_preT);
1371    val fp_sig_T = Tsubst Y fpT sig_T;
1372    val fp_ssig_T = Tsubst Y fpT ssig_T;
1373
1374    val id' = HOLogic.id_const fpT;
1375    val convol' = mk_convol (id', dtor);
1376    val dead_pre_map' = Term.subst_atomic_types [(Y, fp_ssig_T), (Z, fpT)] dead_pre_map;
1377    val dead_sig_map' = Term.subst_atomic_types [(Y, fpT), (Z, fppreT)] dead_sig_map;
1378    val Lam' = substT Y fpT Lam;
1379    val x' = substT Y fp_sig_T x;
1380
1381    val goal = mk_Trueprop_eq (dtor $ (algLam $ x'),
1382      dead_pre_map' $ eval $ (Lam' $ (dead_sig_map' $ convol' $ x')));
1383  in
1384    Variable.add_free_names ctxt goal []
1385    |> (fn vars => Goal.prove_sorry ctxt vars [] goal (fn {context = ctxt, prems = _} =>
1386      mk_dtor_algLam_tac ctxt pre_map_comp dead_pre_map_id dead_pre_map_comp0 dead_pre_map_comp
1387        sig_map_comp Oper_pointful_natural ssig_map_thms dead_ssig_map_comp0 Lam_pointful_natural
1388        eval_core_simps eval_thm eval_flat eval_VLeaf algLam_def))
1389    |> Thm.close_derivation \<^here>
1390  end;
1391
1392fun derive_algLam_base ctxt Y Z preT fpT dead_pre_map ctor dtor algLam proto_sctr dead_pre_map_id
1393    dead_pre_map_comp ctor_dtor dtor_ctor dtor_unfold_unique unsig_thm Sig_pointful_natural
1394    ssig_map_thms Lam_def flat_simps eval_core_simps eval_thm algLam_def =
1395  let
1396    val fp_preT = Tsubst Y fpT preT;
1397
1398    val proto_sctr' = substT Y fpT proto_sctr;
1399
1400    val dead_pre_map' = Term.subst_atomic_types [(Y, fpT), (Z, fp_preT)] dead_pre_map;
1401    val dead_pre_map_dtor = dead_pre_map' $ dtor;
1402
1403    val goal = mk_Trueprop_eq (HOLogic.mk_comp (algLam, proto_sctr'), ctor);
1404  in
1405    Variable.add_free_names ctxt goal []
1406    |> (fn vars => Goal.prove_sorry ctxt vars [] goal (fn {context = ctxt, prems = _} =>
1407      mk_algLam_base_tac ctxt dead_pre_map_dtor dead_pre_map_id dead_pre_map_comp ctor_dtor
1408        dtor_ctor dtor_unfold_unique unsig_thm Sig_pointful_natural ssig_map_thms Lam_def flat_simps
1409        eval_core_simps eval_thm algLam_def))
1410    |> Thm.close_derivation \<^here>
1411  end;
1412
1413fun derive_flat_embL ctxt Y Z old_ssig_T ssig_T dead_old_ssig_map embL old_flat flat x
1414    old_ssig_induct fp_map_id Sig_pointful_natural old_sig_map_comp old_sig_map_cong
1415    old_ssig_map_thms old_flat_simps flat_simps embL_simps =
1416  let
1417    val old_ssig_old_ssig_T = Tsubst Y old_ssig_T old_ssig_T;
1418
1419    val dead_old_ssig_map' =
1420      Term.subst_atomic_types [(Y, old_ssig_T), (Z, ssig_T)] dead_old_ssig_map;
1421    val embL' = substT Y ssig_T embL;
1422    val x' = substT Y old_ssig_old_ssig_T x;
1423
1424    val goal = mk_Trueprop_eq (flat $ (embL' $ (dead_old_ssig_map' $ embL $ x')),
1425      embL $ (old_flat $ x'));
1426
1427    val old_ssig_induct' =
1428      infer_instantiate' ctxt [NONE, SOME (Thm.cterm_of ctxt x')] old_ssig_induct;
1429  in
1430    Variable.add_free_names ctxt goal []
1431    |> (fn vars => Goal.prove_sorry ctxt vars [] goal (fn {context = ctxt, prems = _} =>
1432      mk_flat_embL_tac ctxt old_ssig_induct' fp_map_id Sig_pointful_natural old_sig_map_comp
1433        old_sig_map_cong old_ssig_map_thms old_flat_simps flat_simps embL_simps))
1434    |> Thm.close_derivation \<^here>
1435  end;
1436
1437fun derive_eval_core_embL ctxt Y Z preT old_ssig_T ssig_T dead_pre_map embL old_eval_core eval_core
1438    x old_ssig_induct dead_pre_map_comp0 dead_pre_map_comp Sig_pointful_natural unsig_thm
1439    old_sig_map_comp old_sig_map_cong old_Lam_pointful_natural Lam_def flat_embL embL_simps
1440    embL_pointful_natural old_eval_core_simps eval_core_simps =
1441  let
1442    val YpreT = HOLogic.mk_prodT (Y, preT);
1443    val Ypre_old_ssig_T = Tsubst Y YpreT old_ssig_T;
1444
1445    val dead_pre_map' = Term.subst_atomic_types [(Y, old_ssig_T), (Z, ssig_T)] dead_pre_map;
1446    val embL' = substT Y YpreT embL;
1447    val x' = substT Y Ypre_old_ssig_T x;
1448
1449    val goal =
1450      mk_Trueprop_eq (eval_core $ (embL' $ x'), dead_pre_map' $ embL $ (old_eval_core $ x'));
1451
1452    val old_ssig_induct' =
1453      infer_instantiate' ctxt [NONE, SOME (Thm.cterm_of ctxt x')] old_ssig_induct;
1454  in
1455    Variable.add_free_names ctxt goal []
1456    |> (fn vars => Goal.prove_sorry ctxt vars [] goal (fn {context = ctxt, prems = _} =>
1457      mk_eval_core_embL_tac ctxt old_ssig_induct' dead_pre_map_comp0 dead_pre_map_comp
1458        Sig_pointful_natural unsig_thm old_sig_map_comp old_sig_map_cong old_Lam_pointful_natural
1459        Lam_def flat_embL old_eval_core_simps eval_core_simps embL_simps embL_pointful_natural))
1460    |> Thm.close_derivation \<^here>
1461  end;
1462
1463fun derive_eval_embL ctxt Y fpT embL old_eval eval dead_pre_map_comp0 dtor_unfold_unique
1464    embL_pointful_natural eval_core_embL old_eval_thm eval_thm =
1465  let
1466    val embL' = substT Y fpT embL;
1467    val goal = mk_Trueprop_eq (HOLogic.mk_comp (eval, embL'), old_eval);
1468  in
1469    Variable.add_free_names ctxt goal []
1470    |> (fn vars => Goal.prove_sorry ctxt vars [] goal (fn {context = ctxt, prems = _} =>
1471      mk_eval_embL_tac ctxt dead_pre_map_comp0 dtor_unfold_unique embL_pointful_natural
1472        eval_core_embL old_eval_thm eval_thm))
1473    |> Thm.close_derivation \<^here>
1474  end;
1475
1476fun derive_algLam_algLam ctxt Inx_const Y fpT Sig old_algLam algLam dead_pre_map_comp dtor_inject
1477    unsig_thm sig_map_thm Lam_def eval_embL old_dtor_algLam dtor_algLam =
1478  let
1479    val Sig' = substT Y fpT Sig;
1480    val (left_T, right_T) = dest_sumT (domain_type (fastype_of Sig'));
1481    val inx' = Inx_const left_T right_T;
1482
1483    val goal = mk_Trueprop_eq (Library.foldl1 HOLogic.mk_comp [algLam, Sig', inx'], old_algLam);
1484  in
1485    Variable.add_free_names ctxt goal []
1486    |> (fn vars => Goal.prove_sorry ctxt vars [] goal (fn {context = ctxt, prems = _} =>
1487      mk_algLam_algLam_tac ctxt dead_pre_map_comp dtor_inject unsig_thm sig_map_thm Lam_def
1488        eval_embL old_dtor_algLam dtor_algLam))
1489    |> Thm.close_derivation \<^here>
1490  end;
1491
1492fun derive_eval_core_k_as_ssig ctxt Y preT k_T rho eval_core k_as_ssig x pre_map_comp
1493    dead_pre_map_id sig_map_comp ssig_map_thms Lam_natural_pointful Lam_Inr flat_VLeaf
1494    eval_core_simps =
1495  let
1496    val YpreT = HOLogic.mk_prodT (Y, preT);
1497    val Ypre_k_T = Tsubst Y YpreT k_T;
1498
1499    val k_as_ssig' = substT Y YpreT k_as_ssig;
1500    val x' = substT Y Ypre_k_T x;
1501
1502    val goal = mk_Trueprop_eq (eval_core $ (k_as_ssig' $ x'), rho $ x');
1503  in
1504    Variable.add_free_names ctxt goal []
1505    |> (fn vars => Goal.prove_sorry ctxt vars [] goal (fn {context = ctxt, prems = _} =>
1506      mk_eval_core_k_as_ssig_tac ctxt pre_map_comp dead_pre_map_id sig_map_comp ssig_map_thms
1507        Lam_natural_pointful Lam_Inr flat_VLeaf eval_core_simps))
1508    |> Thm.close_derivation \<^here>
1509  end;
1510
1511fun derive_algLam_algrho ctxt Y fpT Sig algLam algrho algLam_def algrho_def =
1512  let
1513    val Sig' = substT Y fpT Sig;
1514    val (left_T, right_T) = dest_sumT (domain_type (fastype_of Sig'));
1515    val inr' = Inr_const left_T right_T;
1516
1517    val goal = mk_Trueprop_eq (Library.foldl1 HOLogic.mk_comp [algLam, Sig', inr'], algrho);
1518  in
1519    Variable.add_free_names ctxt goal []
1520    |> (fn vars => Goal.prove_sorry ctxt vars [] goal (fn {context = ctxt, prems = _} =>
1521      mk_algLam_algrho_tac ctxt algLam_def algrho_def))
1522    |> Thm.close_derivation \<^here>
1523  end;
1524
1525fun derive_dtor_algrho ctxt Y Z preT fpT k_T ssig_T dead_pre_map dead_k_map dtor rho eval algrho x
1526    eval_thm k_as_ssig_natural_pointful eval_core_k_as_ssig algrho_def =
1527  let
1528    val YpreT = HOLogic.mk_prodT (Y, preT);
1529    val fppreT = Tsubst Y fpT YpreT;
1530    val fp_k_T = Tsubst Y fpT k_T;
1531    val fp_ssig_T = Tsubst Y fpT ssig_T;
1532
1533    val id' = HOLogic.id_const fpT;
1534    val convol' = mk_convol (id', dtor);
1535    val dead_pre_map' = Term.subst_atomic_types [(Y, fp_ssig_T), (Z, fpT)] dead_pre_map;
1536    val dead_k_map' = Term.subst_atomic_types [(Y, fpT), (Z, fppreT)] dead_k_map;
1537    val rho' = substT Y fpT rho;
1538    val x' = substT Y fp_k_T x;
1539
1540    val goal = mk_Trueprop_eq (dtor $ (algrho $ x'),
1541      dead_pre_map' $ eval $ (rho' $ (dead_k_map' $ convol' $ x')));
1542  in
1543    Variable.add_free_names ctxt goal []
1544    |> (fn vars => Goal.prove_sorry ctxt vars [] goal (fn {context = ctxt, prems = _} =>
1545      mk_dtor_algrho_tac ctxt eval_thm k_as_ssig_natural_pointful eval_core_k_as_ssig algrho_def))
1546    |> Thm.close_derivation \<^here>
1547  end;
1548
1549fun derive_algLam_step_or_merge ctxt Y fpT ctor proto_sctr algLam proto_sctr_def old_algLam_pointful
1550    algLam_algLam =
1551  let
1552    val proto_sctr' = substT Y fpT proto_sctr;
1553    val goal = mk_Trueprop_eq (HOLogic.mk_comp (algLam, proto_sctr'), ctor);
1554
1555    val algLam_algLam_pointful = mk_pointful ctxt algLam_algLam;
1556  in
1557    Variable.add_free_names ctxt goal []
1558    |> (fn vars => Goal.prove_sorry ctxt vars [] goal (fn {context = ctxt, prems = _} =>
1559      mk_algLam_step_tac ctxt proto_sctr_def old_algLam_pointful algLam_algLam_pointful))
1560    |> Thm.close_derivation \<^here>
1561  end;
1562
1563fun derive_eval_sctr ctxt Y Z fpT ssig_T dead_pre_map ctor eval sctr proto_sctr_pointful_natural
1564    eval_Oper algLam_thm sctr_def =
1565  let
1566    val fp_ssig_T = Tsubst Y fpT ssig_T;
1567
1568    val dead_pre_map' = Term.subst_atomic_types [(Y, fp_ssig_T), (Z, fpT)] dead_pre_map;
1569    val sctr' = substT Y fpT sctr;
1570
1571    val goal = mk_Trueprop_eq (HOLogic.mk_comp (eval, sctr'),
1572      HOLogic.mk_comp (ctor, dead_pre_map' $ eval));
1573  in
1574    Variable.add_free_names ctxt goal []
1575    |> (fn vars => Goal.prove_sorry ctxt vars [] goal (fn {context = ctxt, prems = _} =>
1576      mk_eval_sctr_tac ctxt proto_sctr_pointful_natural eval_Oper algLam_thm sctr_def))
1577    |> Thm.close_derivation \<^here>
1578  end;
1579
1580fun derive_corecUU_pointfree_unique ctxt Y Z preT fpT ssig_T dead_pre_map ctor dead_ssig_map eval
1581    corecUU f g dead_pre_map_comp0 dead_pre_map_comp dtor_ctor dtor_inject ssig_map_comp
1582    flat_pointful_natural eval_core_pointful_natural eval_thm eval_flat corecU_ctor corecU_unique
1583    sctr_pointful_natural eval_sctr_pointful corecUU_def =
1584  let
1585    val ssig_preT = Tsubst Y ssig_T preT;
1586    val ssig_pre_ssig_T = Tsubst Y ssig_preT ssig_T;
1587    val fp_ssig_T = Tsubst Y fpT ssig_T;
1588
1589    val dead_pre_map' = Term.subst_atomic_types [(Y, fp_ssig_T), (Z, fpT)] dead_pre_map;
1590    val dead_pre_map'' = Term.subst_atomic_types [(Y, ssig_T), (Z, fp_ssig_T)] dead_pre_map;
1591    val dead_ssig_map' = Term.subst_atomic_types [(Y, ssig_preT), (Z, fpT)] dead_ssig_map;
1592    val dead_ssig_map'' = substT Z fpT dead_ssig_map;
1593    val f' = substT Z ssig_pre_ssig_T f;
1594    val g' = substT Z fpT g;
1595    val corecUU_f = corecUU $ f';
1596
1597    fun mk_eq fpf =
1598      mk_Trueprop_eq (fpf, Library.foldl1 HOLogic.mk_comp [eval, dead_ssig_map' $
1599          Library.foldl1 HOLogic.mk_comp [ctor, dead_pre_map' $ eval, dead_pre_map''
1600            $ (dead_ssig_map'' $ fpf)],
1601        f']);
1602
1603    val corecUU_pointfree =
1604      let
1605        val goal = mk_eq corecUU_f;
1606      in
1607        Variable.add_free_names ctxt goal []
1608        |> (fn vars => Goal.prove_sorry ctxt vars [] goal (fn {context = ctxt, prems = _} =>
1609          mk_corecUU_pointfree_tac ctxt dead_pre_map_comp0 dead_pre_map_comp dtor_ctor dtor_inject
1610            ssig_map_comp flat_pointful_natural eval_core_pointful_natural eval_thm eval_flat
1611            corecU_ctor sctr_pointful_natural eval_sctr_pointful corecUU_def))
1612        |> Thm.close_derivation \<^here>
1613      end;
1614
1615    val corecUU_unique =
1616      let
1617        val prem = mk_eq g';
1618        val goal = mk_Trueprop_eq (g', corecUU_f);
1619      in
1620        fold (Variable.add_free_names ctxt) [prem, goal] []
1621        |> (fn vars => Goal.prove_sorry ctxt vars [prem] goal
1622              (fn {context = ctxt, prems = [prem]} =>
1623                mk_corecUU_unique_tac ctxt dead_pre_map_comp0 dead_pre_map_comp dtor_ctor
1624                  ssig_map_comp flat_pointful_natural eval_core_pointful_natural eval_thm eval_flat
1625                  corecU_unique sctr_pointful_natural eval_sctr_pointful corecUU_def prem))
1626        |> Thm.close_derivation \<^here>
1627      end;
1628  in
1629    (corecUU_pointfree, corecUU_unique)
1630  end;
1631
1632fun define_flat_etc fp_b version live_AsBs Y Z preT fpT sig_T ssig_T Oper VLeaf CLeaf pre_rel
1633    dead_pre_map dtor dtor_unfold dead_sig_map ssig_rel dead_ssig_map Lam Rs R pre_map_transfer
1634    fp_k_T_rel_eqs sig_map_transfer ssig_map_transfer Lam_transfer dtor_transfer lthy =
1635  let
1636    val (flat_data as (flat, flat_def, _), lthy) = lthy
1637      |> define_flat fp_b version Y Z fpT sig_T ssig_T Oper VLeaf CLeaf dead_sig_map;
1638
1639    val (eval_core_data as (eval_core, eval_core_def, _), lthy) = lthy
1640      |> define_eval_core fp_b version Y Z preT fpT sig_T ssig_T dtor Oper VLeaf CLeaf dead_pre_map
1641        dead_sig_map dead_ssig_map flat Lam;
1642
1643    val ((eval_data as (eval, _), cutSsig_data as (cutSsig, _)), lthy) = lthy
1644      |> define_eval fp_b version Y Z preT fpT ssig_T dtor dtor_unfold dead_ssig_map eval_core
1645      ||>> define_cutSsig fp_b version Y Z preT ssig_T dead_pre_map VLeaf dead_ssig_map flat
1646        eval_core;
1647
1648    val ((algLam_data, unfold_data), lthy) = lthy
1649      |> define_algLam fp_b version Y Z fpT ssig_T Oper VLeaf dead_sig_map eval
1650      ||>> define_corecU fp_b version Y Z preT ssig_T dtor_unfold VLeaf cutSsig;
1651
1652    val flat_transfer = derive_transfer_by_transfer_prover lthy live_AsBs Rs R flat [flat_def] []
1653      [sig_map_transfer];
1654    val eval_core_transfer = derive_Lam_or_eval_core_transfer lthy live_AsBs Y Z preT ssig_T Rs R
1655      pre_rel ssig_rel ssig_rel eval_core eval_core_def fp_k_T_rel_eqs
1656      [pre_map_transfer, sig_map_transfer, ssig_map_transfer, flat_transfer, Lam_transfer,
1657       dtor_transfer];
1658  in
1659    (((((((flat_data, flat_transfer), (eval_core_data, eval_core_transfer)), eval_data),
1660      cutSsig_data), algLam_data), unfold_data), lthy)
1661  end;
1662
1663fun derive_Sig_natural_etc ctxt live live_AsBs Y Z preT fpT k_or_fpT sig_T ssig_T pre_map
1664    dead_pre_map ctor dtor Sig dead_sig_map Oper VLeaf CLeaf ssig_map dead_ssig_map Lam flat
1665    eval_core eval cutSsig algLam corecU x fs f g ctor_dtor dtor_inject dtor_unfold_thm
1666    dtor_unfold_unique sig_map_thm ssig_induct ssig_map_thms Oper_map_thm VLeaf_map_thm
1667    CLeaf_map_thm Lam_transfer flat_simps flat_transfer eval_core_simps eval_core_transfer eval_def
1668    cutSsig_def algLam_def corecU_def live_pre_bnf pre_bnf dead_pre_bnf fp_bnf sig_bnf ssig_bnf
1669    dead_ssig_bnf =
1670  let
1671    val SOME prod_bnf = bnf_of ctxt \<^type_name>\<open>prod\<close>;
1672
1673    val f' = substT Z fpT f;
1674    val dead_ssig_map' = substT Z fpT dead_ssig_map;
1675    val extdd = Term.lambda f' (HOLogic.mk_comp (eval, dead_ssig_map' $ f'));
1676
1677    val live_pre_map_def = map_def_of_bnf live_pre_bnf;
1678    val pre_map_comp = map_comp_of_bnf pre_bnf;
1679    val dead_pre_map_id = map_id_of_bnf dead_pre_bnf;
1680    val dead_pre_map_comp0 = map_comp0_of_bnf dead_pre_bnf;
1681    val dead_pre_map_comp = map_comp_of_bnf dead_pre_bnf;
1682    val dead_pre_map_cong = map_cong_of_bnf dead_pre_bnf;
1683    val fp_map_id = map_id_of_bnf fp_bnf;
1684    val sig_map_ident = map_ident_of_bnf sig_bnf;
1685    val sig_map_comp0 = map_comp0_of_bnf sig_bnf;
1686    val sig_map_comp = map_comp_of_bnf sig_bnf;
1687    val sig_map_cong = map_cong_of_bnf sig_bnf;
1688    val ssig_map_id = map_id_of_bnf ssig_bnf;
1689    val ssig_map_comp = map_comp_of_bnf ssig_bnf;
1690    val dead_ssig_map_comp0 = map_comp0_of_bnf dead_ssig_bnf;
1691
1692    val k_preT_map_id0s =
1693      map map_id0_of_bnf (map_filter (bnf_of ctxt) (fold add_type_namesT [preT, k_or_fpT] []));
1694
1695    val Sig_natural = derive_natural_by_unfolding ctxt live_AsBs preT pre_map fs f Sig
1696      ([sig_map_thm, live_pre_map_def, @{thm BNF_Composition.id_bnf_def}] @ k_preT_map_id0s);
1697    val Oper_natural =
1698      derive_natural_by_unfolding ctxt live_AsBs preT pre_map fs f Oper [Oper_map_thm];
1699    val VLeaf_natural =
1700      derive_natural_by_unfolding ctxt live_AsBs preT pre_map fs f VLeaf [VLeaf_map_thm];
1701    val Lam_natural = derive_natural_from_transfer_with_pre_type ctxt live_AsBs Y Z preT ssig_T
1702      pre_map ssig_map fs f Lam Lam_transfer [prod_bnf, pre_bnf, sig_bnf, ssig_bnf] [];
1703    val flat_natural = derive_natural_from_transfer ctxt live_AsBs [] fs f flat flat_transfer
1704      [ssig_bnf] [];
1705    val eval_core_natural = derive_natural_from_transfer_with_pre_type ctxt live_AsBs Y Z preT
1706      ssig_T pre_map ssig_map fs f eval_core eval_core_transfer [prod_bnf, pre_bnf, ssig_bnf] [];
1707
1708    val Sig_pointful_natural = mk_pointful ctxt Sig_natural RS sym;
1709    val Oper_natural_pointful = mk_pointful ctxt Oper_natural;
1710    val Oper_pointful_natural = Oper_natural_pointful RS sym;
1711    val flat_pointful_natural = mk_pointful ctxt flat_natural RS sym;
1712    val Lam_natural_pointful = mk_pointful ctxt Lam_natural;
1713    val Lam_pointful_natural = Lam_natural_pointful RS sym;
1714    val eval_core_pointful_natural = mk_pointful ctxt eval_core_natural RS sym;
1715    val cutSsig_def_pointful_natural = mk_pointful ctxt (HOLogic.mk_obj_eq cutSsig_def) RS sym;
1716
1717    val flat_VLeaf = derive_flat_VLeaf ctxt Y Z ssig_T x VLeaf dead_ssig_map flat ssig_induct
1718      fp_map_id sig_map_cong sig_map_ident sig_map_comp ssig_map_thms flat_simps;
1719    val flat_flat = derive_flat_flat ctxt Y Z ssig_T x dead_ssig_map flat ssig_induct fp_map_id
1720      sig_map_cong sig_map_comp ssig_map_thms flat_simps;
1721
1722    val eval_core_flat = derive_eval_core_flat ctxt Y Z preT ssig_T dead_pre_map dead_ssig_map flat
1723      eval_core x ssig_induct dead_pre_map_id dead_pre_map_comp0 dead_pre_map_comp fp_map_id
1724      sig_map_comp sig_map_cong ssig_map_thms ssig_map_comp flat_simps flat_pointful_natural
1725      flat_flat Lam_pointful_natural eval_core_simps;
1726
1727    val eval_thm = derive_eval_thm ctxt dtor_inject dtor_unfold_thm eval_def;
1728    val eval_flat = derive_eval_flat ctxt Y Z fpT ssig_T dead_ssig_map flat eval x
1729      dead_pre_map_comp0 dtor_unfold_unique ssig_map_id ssig_map_comp flat_pointful_natural
1730      eval_core_pointful_natural eval_core_flat eval_thm;
1731    val eval_Oper = derive_eval_Oper ctxt live Y Z fpT sig_T ssig_T dead_sig_map Oper eval algLam x
1732      sig_map_ident sig_map_comp0 sig_map_comp Oper_natural_pointful VLeaf_natural flat_simps
1733      eval_flat algLam_def;
1734    val eval_VLeaf = derive_eval_V_or_CLeaf ctxt Y fpT VLeaf eval x dead_pre_map_id
1735      dead_pre_map_comp fp_map_id dtor_unfold_unique VLeaf_map_thm eval_core_simps eval_thm;
1736    val eval_CLeaf = derive_eval_V_or_CLeaf ctxt Y fpT CLeaf eval x dead_pre_map_id
1737      dead_pre_map_comp fp_map_id dtor_unfold_unique CLeaf_map_thm eval_core_simps eval_thm;
1738
1739    val extdd_mor = derive_extdd_mor ctxt Y Z preT fpT ssig_T dead_pre_map dtor extdd cutSsig f g
1740      dead_pre_map_comp0 dead_pre_map_comp VLeaf_map_thm ssig_map_comp flat_pointful_natural
1741      eval_core_pointful_natural eval_thm eval_flat eval_VLeaf cutSsig_def;
1742    val mor_cutSsig_flat = derive_mor_cutSsig_flat ctxt Y Z preT fpT ssig_T dead_pre_map
1743      dead_ssig_map dtor flat eval_core eval cutSsig f g dead_pre_map_comp0 dead_pre_map_comp
1744      dead_pre_map_cong dtor_unfold_unique dead_ssig_map_comp0 ssig_map_comp flat_simps
1745      flat_pointful_natural eval_core_pointful_natural flat_flat flat_VLeaf eval_core_flat
1746      cutSsig_def cutSsig_def_pointful_natural eval_thm;
1747    val extdd_o_VLeaf = derive_extdd_o_VLeaf ctxt Y Z preT fpT ssig_T dead_pre_map dtor VLeaf extdd
1748      f g dead_pre_map_comp0 dead_pre_map_comp dtor_inject ssig_map_thms eval_core_simps eval_thm
1749      eval_VLeaf;
1750
1751    val (corecU_ctor, corecU_unique) = derive_corecU_ctor_unique ctxt Y Z preT fpT ssig_T
1752      dead_pre_map ctor dtor VLeaf extdd corecU f g dead_pre_map_comp ctor_dtor dtor_unfold_thm
1753      dtor_unfold_unique ssig_map_thms dead_ssig_map_comp0 flat_simps flat_VLeaf eval_core_simps
1754      extdd_mor extdd_o_VLeaf cutSsig_def mor_cutSsig_flat corecU_def;
1755
1756    val dtor_algLam = derive_dtor_algLam ctxt Y Z preT fpT sig_T ssig_T dead_pre_map dtor
1757      dead_sig_map Lam eval algLam x pre_map_comp dead_pre_map_id dead_pre_map_comp0
1758      dead_pre_map_comp sig_map_comp Oper_pointful_natural ssig_map_thms dead_ssig_map_comp0
1759      Lam_pointful_natural eval_core_simps eval_thm eval_flat eval_VLeaf algLam_def;
1760  in
1761    (Sig_pointful_natural, flat_pointful_natural, Lam_natural_pointful, Lam_pointful_natural,
1762     flat_VLeaf, eval_core_pointful_natural, eval_thm, eval_flat,
1763     [eval_Oper, eval_VLeaf, eval_CLeaf], corecU_ctor, corecU_unique, dtor_algLam)
1764  end;
1765
1766fun derive_embL_natural_etc ctxt Inx_const old_ssig_bnf ssig_bnf Y Z preT fpT old_ssig_T ssig_T
1767    dead_pre_map Sig dead_old_ssig_map embL old_algLam algLam old_flat flat old_eval_core eval_core
1768    old_eval eval x f old_ssig_induct dead_pre_map_comp0 dead_pre_map_comp fp_map_id dtor_inject
1769    dtor_unfold_unique Sig_pointful_natural unsig_thm sig_map_thm old_sig_map_comp old_sig_map_cong
1770    old_ssig_map_thms old_Lam_pointful_natural Lam_def old_flat_simps flat_simps embL_simps
1771    embL_transfer old_eval_core_simps eval_core_simps old_eval_thm eval_thm old_dtor_algLam
1772    dtor_algLam old_algLam_thm =
1773  let
1774    val embL_natural = derive_natural_from_transfer ctxt [(Y, Z)] [] [] f embL embL_transfer
1775      [old_ssig_bnf, ssig_bnf] [];
1776
1777    val embL_pointful_natural = mk_pointful ctxt embL_natural RS sym;
1778    val old_algLam_pointful = mk_pointful ctxt old_algLam_thm;
1779
1780    val flat_embL = derive_flat_embL ctxt Y Z old_ssig_T ssig_T dead_old_ssig_map embL old_flat flat
1781      x old_ssig_induct fp_map_id Sig_pointful_natural old_sig_map_comp old_sig_map_cong
1782      old_ssig_map_thms old_flat_simps flat_simps embL_simps;
1783    val eval_core_embL = derive_eval_core_embL ctxt Y Z preT old_ssig_T ssig_T dead_pre_map embL
1784      old_eval_core eval_core x old_ssig_induct dead_pre_map_comp0 dead_pre_map_comp
1785      Sig_pointful_natural unsig_thm old_sig_map_comp old_sig_map_cong old_Lam_pointful_natural
1786      Lam_def flat_embL embL_simps embL_pointful_natural old_eval_core_simps eval_core_simps;
1787    val eval_embL = derive_eval_embL ctxt Y fpT embL old_eval eval dead_pre_map_comp0
1788      dtor_unfold_unique embL_pointful_natural eval_core_embL old_eval_thm eval_thm;
1789
1790    val algLam_algLam = derive_algLam_algLam ctxt Inx_const Y fpT Sig old_algLam algLam
1791      dead_pre_map_comp dtor_inject unsig_thm sig_map_thm Lam_def eval_embL old_dtor_algLam
1792      dtor_algLam;
1793  in
1794    (embL_pointful_natural, old_algLam_pointful, eval_embL, algLam_algLam)
1795  end;
1796
1797fun define_corecUU_etc fp_b version live_AsBs Y Z preT fpT ssig_T pre_map dead_pre_map pre_rel
1798    fp_rel ctor Oper ssig_map dead_ssig_map ssig_rel proto_sctr flat eval_core eval corecU fs f g Rs
1799    R pre_map_transfer fp_k_T_rel_eqs dtor_unfold_transfer dtor_transfer ssig_map_transfer
1800    proto_sctr_transfer proto_sctr_pointful_natural flat_transfer flat_pointful_natural
1801    eval_core_transfer eval_core_pointful_natural eval_thm eval_flat eval_Oper algLam_thm
1802    cutSsig_def corecU_def corecU_ctor corecU_unique pre_bnf dead_pre_bnf fp_res ssig_fp_sugar
1803    lthy =
1804  let
1805    val ssig_bnf = #fp_bnf ssig_fp_sugar;
1806
1807    val dead_pre_map_comp0 = map_comp0_of_bnf dead_pre_bnf;
1808    val dead_pre_map_comp = map_comp_of_bnf dead_pre_bnf;
1809    val [dtor_ctor] = #dtor_ctors fp_res;
1810    val [dtor_inject] = #dtor_injects fp_res;
1811    val ssig_map_comp = map_comp_of_bnf ssig_bnf;
1812
1813    val sctr_rhs = HOLogic.mk_comp (Oper, substT Y ssig_T proto_sctr);
1814    val ((sctr, sctr_def), lthy) = lthy
1815      |> define_const true fp_b version sctrN sctr_rhs;
1816
1817    val (corecUU_data as (corecUU, corecUU_def), lthy) = lthy
1818      |> define_corecUU fp_b version Y Z preT ssig_T dead_pre_map dead_ssig_map flat eval_core sctr
1819        corecU;
1820
1821    val eval_sctr = derive_eval_sctr lthy Y Z fpT ssig_T dead_pre_map ctor eval sctr
1822      proto_sctr_pointful_natural eval_Oper algLam_thm sctr_def;
1823
1824    val sctr_transfer = derive_sctr_transfer lthy live_AsBs Y Z ssig_T Rs R pre_rel ssig_rel sctr
1825      sctr_def fp_k_T_rel_eqs [proto_sctr_transfer];
1826
1827    val sctr_natural = derive_natural_from_transfer_with_pre_type lthy live_AsBs Y Z preT ssig_T
1828      pre_map ssig_map fs f sctr sctr_transfer [pre_bnf, ssig_bnf] [];
1829
1830    val sctr_pointful_natural = mk_pointful lthy sctr_natural RS sym;
1831    val eval_sctr_pointful = mk_pointful lthy eval_sctr RS sym;
1832
1833    val (corecUU_pointfree, corecUU_unique) = derive_corecUU_pointfree_unique lthy Y Z preT fpT
1834      ssig_T dead_pre_map ctor dead_ssig_map eval corecUU f g dead_pre_map_comp0 dead_pre_map_comp
1835      dtor_ctor dtor_inject ssig_map_comp flat_pointful_natural eval_core_pointful_natural eval_thm
1836      eval_flat corecU_ctor corecU_unique sctr_pointful_natural eval_sctr_pointful corecUU_def;
1837
1838    val corecUU_thm = mk_pointful lthy corecUU_pointfree;
1839
1840    val corecUU_transfer = derive_corecUU_transfer lthy live_AsBs Y Z Rs R preT ssig_T pre_rel
1841      fp_rel ssig_rel corecUU cutSsig_def corecU_def corecUU_def fp_k_T_rel_eqs
1842      [pre_map_transfer, dtor_unfold_transfer, dtor_transfer, ssig_map_transfer, flat_transfer,
1843       eval_core_transfer, sctr_transfer, @{thm convol_transfer} (*FIXME: needed?*)];
1844  in
1845    ((corecUU_data, corecUU_thm, corecUU_unique, corecUU_transfer, eval_sctr, sctr_transfer,
1846      sctr_pointful_natural), lthy)
1847  end;
1848
1849fun mk_equivp T = Const (\<^const_name>\<open>equivp\<close>, mk_predT [mk_pred2T T T]);
1850
1851fun derive_equivp_Retr ctxt fpT Retr R dead_pre_rel_refl_thm dead_pre_rel_flip_thm
1852    dead_pre_rel_mono_thm dead_pre_rel_compp_thm =
1853  let
1854    val prem = HOLogic.mk_Trueprop (mk_equivp fpT $ R);
1855    val goal = Logic.mk_implies (prem, HOLogic.mk_Trueprop (mk_equivp fpT $ (betapply (Retr, R))));
1856  in
1857    Variable.add_free_names ctxt goal []
1858    |> (fn vars => Goal.prove_sorry ctxt vars [] goal (fn {context = ctxt, prems = _} =>
1859      mk_equivp_Retr_tac ctxt dead_pre_rel_refl_thm dead_pre_rel_flip_thm dead_pre_rel_mono_thm
1860        dead_pre_rel_compp_thm))
1861    |> Thm.close_derivation \<^here>
1862  end;
1863
1864fun derive_Retr_coinduct ctxt fpT Retr R dtor_rel_coinduct_thm rel_eq_thm =
1865  let
1866    val goal = HOLogic.mk_Trueprop (list_all_free [R]
1867      (HOLogic.mk_imp (mk_leq R (Retr $ R), mk_leq R (HOLogic.eq_const fpT))));
1868  in
1869    Goal.prove_sorry ctxt [] [] goal (fn {context = ctxt, prems = _} =>
1870      mk_Retr_coinduct_tac ctxt dtor_rel_coinduct_thm rel_eq_thm)
1871    |> Thm.close_derivation \<^here>
1872  end;
1873
1874fun derive_Retr fp_sugar fpT dead_pre_bnf ctor dtor names_lthy lthy =
1875  let
1876    val (R, _) = names_lthy
1877      |> yield_singleton (mk_Frees "R") (mk_pred2T fpT fpT);
1878    val pre_fpT = pre_type_of_ctor fpT ctor;
1879    val fp_pre_rel = mk_rel1 lthy fpT fpT pre_fpT dead_pre_bnf;
1880    val Retr = Abs ("R", fastype_of R, Abs ("a", fpT,
1881      Abs ("b", fpT, list_comb (fp_pre_rel, [Bound 2, dtor $ Bound 1, dtor $ Bound 0]))));
1882    val equivp_Retr = derive_equivp_Retr lthy fpT Retr R (rel_refl_of_bnf dead_pre_bnf)
1883      (rel_flip_of_bnf dead_pre_bnf) (rel_mono_of_bnf dead_pre_bnf) (rel_OO_of_bnf dead_pre_bnf);
1884
1885    val Retr_coinduct = derive_Retr_coinduct lthy fpT Retr R
1886      (fp_sugar |> #fp_res |> #xtor_rel_co_induct) (fp_sugar |> #fp_bnf |> rel_eq_of_bnf);
1887  in
1888    (Retr, equivp_Retr, Retr_coinduct)
1889  end;
1890
1891fun mk_gen_cong fpT eval_domT =
1892  let val fp_relT = mk_pred2T fpT fpT in
1893    Const (\<^const_name>\<open>cong.gen_cong\<close>,
1894      [mk_predT [fp_relT, eval_domT, eval_domT], eval_domT --> fpT, fp_relT] ---> fp_relT)
1895  end;
1896
1897fun mk_cong_locale rel eval Retr =
1898  Const (\<^const_name>\<open>cong\<close>, mk_predT (map fastype_of [rel, eval, Retr]));
1899
1900fun derive_cong_locale ctxt rel eval Retr0 tac =
1901  let
1902    val Retr = enforce_type ctxt domain_type (domain_type (fastype_of rel)) Retr0;
1903    val goal = HOLogic.mk_Trueprop (list_comb (mk_cong_locale rel eval Retr, [rel, eval, Retr]));
1904  in
1905    Variable.add_free_names ctxt goal []
1906    |> (fn vars => Goal.prove_sorry ctxt vars [] goal (fn {context = ctxt, prems = _} => tac ctxt))
1907    |> Thm.close_derivation \<^here>
1908  end;
1909
1910fun derive_cong_general fp_b version fpT dead_ssig_bnf dead_pre_bnf eval Retr equivp_Retr
1911    Retr_coinduct eval_thm eval_core_transfer lthy =
1912  let
1913    val eval_domT = domain_type (fastype_of eval);
1914
1915    fun cong_locale_tac ctxt =
1916      mk_cong_locale_tac ctxt (rel_mono_of_bnf dead_pre_bnf) (rel_map_of_bnf dead_pre_bnf)
1917        equivp_Retr (rel_mono_of_bnf dead_ssig_bnf) (rel_map_of_bnf dead_ssig_bnf) eval_thm
1918        eval_core_transfer;
1919
1920    val rel = mk_rel1 lthy fpT fpT eval_domT dead_ssig_bnf;
1921    val cong_rhs = list_comb (mk_gen_cong fpT eval_domT, [rel, eval]);
1922    val ((_, cong_def), lthy) = lthy
1923      |> define_const false fp_b version congN cong_rhs;
1924
1925    val cong_locale = derive_cong_locale lthy rel eval Retr cong_locale_tac;
1926
1927    val fold_cong_def = Local_Defs.fold lthy [cong_def];
1928
1929    fun instance_of_gen thm = fold_cong_def (thm OF [cong_locale]);
1930
1931    val cong_base = instance_of_gen @{thm cong.imp_gen_cong};
1932    val cong_refl = instance_of_gen @{thm cong.gen_cong_reflp};
1933    val cong_sym = instance_of_gen @{thm cong.gen_cong_symp};
1934    val cong_trans = instance_of_gen @{thm cong.gen_cong_transp};
1935
1936    fun mk_cong_rho thm = thm RS instance_of_gen @{thm cong.gen_cong_rho};
1937
1938    val dtor_coinduct = @{thm predicate2I_obj} RS
1939      (Retr_coinduct RS instance_of_gen @{thm cong.coinduction} RS @{thm predicate2D_obj});
1940  in
1941    (cong_def, cong_locale, cong_base, cong_refl, cong_sym, cong_trans, dtor_coinduct, mk_cong_rho,
1942     lthy)
1943  end;
1944
1945fun derive_cong_base fp_b version fpT dead_ssig_bnf ssig_fp_bnf_sugar dead_pre_bnf eval eval_thm
1946    eval_core_transfer eval_VLeaf eval_sctr sctr_transfer Retr equivp_Retr Retr_coinduct lthy =
1947  let
1948    val (cong_def, cong_locale, cong_base, cong_refl, cong_sym, cong_trans, dtor_coinduct,
1949         mk_cong_rho, lthy) =
1950      derive_cong_general fp_b version fpT dead_ssig_bnf dead_pre_bnf eval Retr equivp_Retr
1951        Retr_coinduct eval_thm eval_core_transfer lthy;
1952
1953    val dead_pre_map_id0 = map_id0_of_bnf dead_pre_bnf;
1954    val dead_pre_map_comp0 = map_comp0_of_bnf dead_pre_bnf;
1955    val dead_pre_map_cong0 = map_cong0_of_bnf dead_pre_bnf;
1956    val dead_pre_map_cong0' =
1957      @{thm box_equals[OF _ o_apply[symmetric] id_apply[symmetric]]} RS dead_pre_map_cong0 RS ext;
1958    val dead_pre_rel_map = rel_map_of_bnf dead_pre_bnf;
1959
1960    val ctor_alt_thm = eval_VLeaf RS (@{thm eq_comp_compI} OF [eval_sctr,
1961      trans OF [dead_pre_map_comp0 RS sym, trans OF [dead_pre_map_cong0', dead_pre_map_id0]]]);
1962
1963    val cong_ctor_intro = mk_cong_rho ctor_alt_thm
1964      |> unfold_thms lthy [o_apply]
1965      |> (fn thm => sctr_transfer RS rel_funD RS thm)
1966      |> unfold_thms lthy (id_apply :: dead_pre_rel_map @ #rel_injects ssig_fp_bnf_sugar);
1967  in
1968    ({cong_def = cong_def, cong_locale = cong_locale, cong_base = cong_base, cong_refl = cong_refl,
1969      cong_sym = cong_sym, cong_trans = cong_trans, dtor_coinduct = dtor_coinduct,
1970      cong_alg_intros = [cong_ctor_intro]}, lthy)
1971  end;
1972
1973fun update_cong_alg_intros ctxt cong_def cong_locale old_cong_def old_cong_locale emb =
1974  let
1975    fun instance_of_gen thm = Local_Defs.fold ctxt [cong_def] (thm OF [cong_locale]);
1976    fun instance_of_old_gen thm = Local_Defs.fold ctxt [old_cong_def] (thm OF [old_cong_locale]);
1977
1978    val emb_idem = @{thm ord_le_eq_trans} OF [emb, instance_of_gen @{thm cong.gen_cong_idem}];
1979    fun mk_rel_mono bnf = instance_of_old_gen @{thm cong.leq_gen_cong} RS rel_mono_of_bnf bnf RS
1980      @{thm predicate2D};
1981    fun mk_intro bnf thm = mk_rel_mono bnf RS (@{thm predicate2D} OF [emb_idem, thm]);
1982  in
1983    map2 mk_intro
1984  end
1985
1986fun derive_cong_step fp_b version fpT dead_ssig_bnf dead_pre_bnf eval eval_thm eval_core_transfer
1987    old_dtor_coinduct_info algrho_def k_as_ssig_transfer Retr equivp_Retr Retr_coinduct
1988    eval_embL embL_transfer old_all_dead_k_bnfs lthy =
1989  let
1990    val old_cong_def = #cong_def old_dtor_coinduct_info;
1991    val old_cong_locale = #cong_locale old_dtor_coinduct_info;
1992    val old_cong_alg_intros = #cong_alg_intros old_dtor_coinduct_info;
1993
1994    val (cong_def, cong_locale, cong_base, cong_refl, cong_sym, cong_trans, dtor_coinduct,
1995         mk_cong_rho, lthy) =
1996      derive_cong_general fp_b version fpT dead_ssig_bnf dead_pre_bnf eval Retr equivp_Retr
1997        Retr_coinduct eval_thm eval_core_transfer lthy;
1998
1999    val cong_alg_intro =
2000      k_as_ssig_transfer RS rel_funD RS mk_cong_rho (HOLogic.mk_obj_eq algrho_def);
2001
2002    val gen_cong_emb =
2003      (@{thm gen_cong_emb} OF [old_cong_locale, cong_locale, eval_embL, embL_transfer])
2004      |> Local_Defs.fold lthy [old_cong_def, cong_def];
2005
2006    val cong_alg_intros = update_cong_alg_intros lthy cong_def cong_locale old_cong_def
2007      old_cong_locale gen_cong_emb old_all_dead_k_bnfs old_cong_alg_intros;
2008  in
2009    ({cong_def = cong_def, cong_locale = cong_locale, cong_base = cong_base, cong_refl = cong_refl,
2010      cong_sym = cong_sym, cong_trans = cong_trans, dtor_coinduct = dtor_coinduct,
2011      cong_alg_intros = cong_alg_intro :: cong_alg_intros}, lthy)
2012  end;
2013
2014fun derive_cong_merge fp_b version fpT old1_friend_names old2_friend_names dead_ssig_bnf
2015    dead_pre_bnf eval eval_thm eval_core_transfer old1_dtor_coinduct_info old2_dtor_coinduct_info
2016    Retr equivp_Retr Retr_coinduct eval_embLL embLL_transfer eval_embLR embLR_transfer
2017    old1_all_dead_k_bnfs old2_all_dead_k_bnfs lthy =
2018  let
2019    val old1_cong_def = #cong_def old1_dtor_coinduct_info;
2020    val old1_cong_locale = #cong_locale old1_dtor_coinduct_info;
2021    val old1_cong_alg_intros = #cong_alg_intros old1_dtor_coinduct_info;
2022    val old2_cong_def = #cong_def old2_dtor_coinduct_info;
2023    val old2_cong_locale = #cong_locale old2_dtor_coinduct_info;
2024    val old2_cong_alg_intros = #cong_alg_intros old2_dtor_coinduct_info;
2025
2026    val (cong_def, cong_locale, cong_base, cong_refl, cong_sym, cong_trans, dtor_coinduct, _,
2027         lthy) =
2028      derive_cong_general fp_b version fpT dead_ssig_bnf dead_pre_bnf eval Retr equivp_Retr
2029        Retr_coinduct eval_thm eval_core_transfer lthy;
2030
2031    val emb1 = (@{thm gen_cong_emb} OF [old1_cong_locale, cong_locale, eval_embLL, embLL_transfer])
2032      |> Local_Defs.fold lthy [old1_cong_def, cong_def];
2033    val emb2 = (@{thm gen_cong_emb} OF [old2_cong_locale, cong_locale, eval_embLR, embLR_transfer])
2034      |> Local_Defs.fold lthy [old2_cong_def, cong_def];
2035
2036    val cong_alg_intros1 = update_cong_alg_intros lthy cong_def cong_locale old1_cong_def
2037      old1_cong_locale emb1 old1_all_dead_k_bnfs old1_cong_alg_intros;
2038    val cong_alg_intros2 = update_cong_alg_intros lthy cong_def cong_locale old2_cong_def
2039      old2_cong_locale emb2 old2_all_dead_k_bnfs old2_cong_alg_intros;
2040
2041    val (cong_algrho_intros1, cong_ctor_intro1) = split_last cong_alg_intros1;
2042    val (cong_algrho_intros2, _) = split_last cong_alg_intros2;
2043    val (old1_all_rho_k_bnfs, old1_Sig_bnf) = split_last old1_all_dead_k_bnfs;
2044    val (old2_all_rho_k_bnfs, _) = split_last old2_all_dead_k_bnfs;
2045
2046    val (friend_names, (cong_algrho_intros, all_rho_k_bnfs)) =
2047      merge_lists (op = o apply2 fst)
2048        (old1_friend_names ~~ (cong_algrho_intros1 ~~ old1_all_rho_k_bnfs))
2049        (old2_friend_names ~~ (cong_algrho_intros2 ~~ old2_all_rho_k_bnfs))
2050      |> split_list ||> split_list;
2051  in
2052    (({cong_def = cong_def, cong_locale = cong_locale, cong_base = cong_base, cong_refl = cong_refl,
2053       cong_sym = cong_sym, cong_trans = cong_trans, dtor_coinduct = dtor_coinduct,
2054       cong_alg_intros = cong_algrho_intros @ [cong_ctor_intro1]}, all_rho_k_bnfs @ [old1_Sig_bnf],
2055       friend_names), lthy)
2056  end;
2057
2058fun derive_corecUU_base fpT_name lthy =
2059  let
2060    val fp_sugar as {T = Type (_, fpT_args0), pre_bnf, fp_bnf, fp_res, ...} =
2061      checked_fp_sugar_of lthy fpT_name;
2062    val fpT_Ss = map Type.sort_of_atyp fpT_args0;
2063    val fp_alives = liveness_of_fp_bnf (length fpT_args0) fp_bnf;
2064
2065    val (((Es, Fs0), [Y, Z]), names_lthy) = lthy
2066      |> mk_TFrees' fpT_Ss
2067      ||>> mk_TFrees' fpT_Ss
2068      ||>> mk_TFrees 2;
2069    val Fs = @{map 3} (fn alive => fn E => fn F => if alive then F else E) fp_alives Es Fs0;
2070
2071    val As = Es @ [Y];
2072    val Bs = Es @ [Z];
2073
2074    val live_EsFs = filter (op <>) (Es ~~ Fs);
2075    val live_AsBs = live_EsFs @ [(Y, Z)];
2076    val fTs = map (op -->) live_EsFs;
2077    val RTs = map (uncurry mk_pred2T) live_EsFs;
2078    val live = length live_EsFs;
2079
2080    val ((((((x, fs), f), g), Rs), R), names_lthy) = names_lthy
2081      |> yield_singleton (mk_Frees "x") Y
2082      ||>> mk_Frees "f" fTs
2083      ||>> yield_singleton (mk_Frees "f") (Y --> Z)
2084      ||>> yield_singleton (mk_Frees "g") (Y --> Z)
2085      ||>> mk_Frees "R" RTs
2086      ||>> yield_singleton (mk_Frees "R") (mk_pred2T Y Z);
2087
2088    val ctor = mk_ctor Es (the_single (#ctors fp_res));
2089    val dtor = mk_dtor Es (the_single (#dtors fp_res));
2090
2091    val fpT = Type (fpT_name, Es);
2092    val preT = pre_type_of_ctor Y ctor;
2093
2094    val ((fp_b, version), lthy) = lthy |> get_name_next_version_of fpT_name;
2095
2096    val ((sig_fp_sugar, ssig_fp_sugar), lthy) = lthy
2097      |> define_sig_type fp_b version fp_alives Es Y preT
2098      ||>> define_ssig_type fp_b version fp_alives Es Y fpT;
2099
2100    val sig_bnf = #fp_bnf sig_fp_sugar;
2101    val ssig_bnf = #fp_bnf ssig_fp_sugar;
2102
2103    val (((dead_pre_bnf, dead_sig_bnf), dead_ssig_bnf), lthy) = lthy
2104      |> bnf_kill_all_but 1 pre_bnf
2105      ||>> bnf_kill_all_but 1 sig_bnf
2106      ||>> bnf_kill_all_but 1 ssig_bnf;
2107
2108    val sig_fp_ctr_sugar = #fp_ctr_sugar sig_fp_sugar;
2109    val ssig_fp_ctr_sugar = #fp_ctr_sugar ssig_fp_sugar;
2110
2111    val sig_fp_bnf_sugar = #fp_bnf_sugar sig_fp_sugar;
2112    val ssig_fp_bnf_sugar = #fp_bnf_sugar ssig_fp_sugar;
2113    val ssig_fp_induct_sugar = the (#fp_co_induct_sugar ssig_fp_sugar);
2114
2115    val sig_ctr_sugar = #ctr_sugar sig_fp_ctr_sugar;
2116    val ssig_ctr_sugar = #ctr_sugar ssig_fp_ctr_sugar;
2117
2118    val sig_T_name = fst (dest_Type (#T sig_fp_sugar));
2119    val ssig_T_name = fst (dest_Type (#T ssig_fp_sugar));
2120
2121    val sig_T = Type (sig_T_name, As);
2122    val ssig_T = Type (ssig_T_name, As);
2123
2124    val pre_map = mk_mapN lthy live_AsBs preT pre_bnf;
2125    val pre_rel = mk_relN lthy live_AsBs preT pre_bnf;
2126    val dead_pre_map = mk_map1 lthy Y Z preT dead_pre_bnf;
2127    val fp_rel = mk_relN lthy live_EsFs fpT fp_bnf;
2128    val dtor_unfold = mk_co_rec (Proof_Context.theory_of lthy) Greatest_FP [Z] fpT
2129      (the_single (#xtor_un_folds fp_res));
2130    val Sig = mk_ctr As (the_single (#ctrs sig_ctr_sugar));
2131    val unsig = mk_disc_or_sel As (the_single (the_single (#selss sig_ctr_sugar)));
2132    val sig_rel = mk_relN lthy live_AsBs sig_T sig_bnf;
2133    val dead_sig_map = mk_map 1 As Bs (map_of_bnf dead_sig_bnf);
2134    val [Oper, VLeaf, CLeaf] = map (mk_ctr As) (#ctrs ssig_ctr_sugar);
2135    val ssig_map = mk_mapN lthy live_AsBs ssig_T ssig_bnf;
2136    val ssig_rel = mk_relN lthy live_AsBs ssig_T ssig_bnf;
2137    val dead_ssig_map = mk_map 1 As Bs (map_of_bnf dead_ssig_bnf);
2138
2139    val ((Lam, Lam_def), lthy) = lthy
2140      |> define_Lam_base fp_b version Y Z preT ssig_T dead_pre_map Sig unsig dead_sig_map Oper
2141        VLeaf;
2142
2143    val proto_sctr = Sig;
2144
2145    val pre_map_transfer = map_transfer_of_bnf pre_bnf;
2146    val pre_rel_def = rel_def_of_bnf pre_bnf;
2147    val dead_pre_map_id = map_id_of_bnf dead_pre_bnf;
2148    val dead_pre_map_comp = map_comp_of_bnf dead_pre_bnf;
2149    val fp_rel_eq = rel_eq_of_bnf fp_bnf;
2150    val [ctor_dtor] = #ctor_dtors fp_res;
2151    val [dtor_ctor] = #dtor_ctors fp_res;
2152    val [dtor_inject] = #dtor_injects fp_res;
2153    val [dtor_unfold_thm] = #xtor_un_fold_thms fp_res;
2154    val dtor_unfold_unique = #xtor_un_fold_unique fp_res;
2155    val [dtor_unfold_transfer] = #xtor_un_fold_transfers fp_res;
2156    val [dtor_rel_thm] = #xtor_rels fp_res;
2157    val unsig_thm = the_single (the_single (#sel_thmss sig_ctr_sugar));
2158    val [sig_map_thm] = #map_thms sig_fp_bnf_sugar;
2159    val [Oper_map_thm, VLeaf_map_thm, CLeaf_map_thm] = #map_thms ssig_fp_bnf_sugar;
2160    val sig_map_transfer = map_transfer_of_bnf sig_bnf;
2161    val ssig_map_thms = #map_thms ssig_fp_bnf_sugar;
2162    val ssig_map_transfer = map_transfer_of_bnf ssig_bnf;
2163    val ssig_induct = the_single (#co_inducts ssig_fp_induct_sugar);
2164
2165    val dtor_transfer = derive_dtor_transfer lthy live_EsFs Y Z pre_rel fp_rel Rs dtor dtor_rel_thm;
2166    val preT_rel_eqs = map rel_eq_of_bnf (map_filter (bnf_of lthy) (add_type_namesT preT []));
2167
2168    val Sig_transfer = derive_sig_transfer I lthy live_AsBs pre_rel sig_rel Rs R Sig pre_rel_def
2169      preT_rel_eqs (the_single (#ctr_transfers sig_fp_ctr_sugar));
2170    val proto_sctr_transfer = Sig_transfer;
2171    val unsig_transfer = derive_sig_transfer swap lthy live_AsBs pre_rel sig_rel Rs R unsig
2172      pre_rel_def preT_rel_eqs (the_single (#sel_transfers sig_fp_ctr_sugar));
2173    val Lam_transfer = derive_Lam_or_eval_core_transfer lthy live_AsBs Y Z preT ssig_T Rs R pre_rel
2174      sig_rel ssig_rel Lam Lam_def []
2175      [pre_map_transfer, sig_map_transfer, Sig_transfer, unsig_transfer];
2176
2177    val ((((((((flat, _, flat_simps), flat_transfer),
2178            ((eval_core, _, eval_core_simps), eval_core_transfer)), (eval, eval_def)),
2179          (cutSsig, cutSsig_def)), (algLam, algLam_def)), (corecU, corecU_def)), lthy) = lthy
2180      |> define_flat_etc fp_b version live_AsBs Y Z preT fpT sig_T ssig_T Oper VLeaf CLeaf pre_rel
2181        dead_pre_map dtor dtor_unfold dead_sig_map ssig_rel dead_ssig_map Lam Rs R pre_map_transfer
2182        [fp_rel_eq] sig_map_transfer ssig_map_transfer Lam_transfer dtor_transfer;
2183
2184    val (Sig_pointful_natural, flat_pointful_natural, _, Lam_pointful_natural, _,
2185         eval_core_pointful_natural, eval_thm, eval_flat, eval_simps as [eval_Oper, eval_VLeaf, _],
2186         corecU_ctor, corecU_unique, dtor_algLam) =
2187      derive_Sig_natural_etc lthy live live_AsBs Y Z preT fpT fpT sig_T ssig_T pre_map dead_pre_map
2188        ctor dtor Sig dead_sig_map Oper VLeaf CLeaf ssig_map dead_ssig_map Lam flat eval_core eval
2189        cutSsig algLam corecU x fs f g ctor_dtor dtor_inject dtor_unfold_thm dtor_unfold_unique
2190        sig_map_thm ssig_induct ssig_map_thms Oper_map_thm VLeaf_map_thm CLeaf_map_thm Lam_transfer
2191        flat_simps flat_transfer eval_core_simps eval_core_transfer eval_def cutSsig_def algLam_def
2192        corecU_def pre_bnf pre_bnf dead_pre_bnf fp_bnf sig_bnf ssig_bnf dead_ssig_bnf;
2193
2194    val proto_sctr_pointful_natural = Sig_pointful_natural;
2195
2196    val algLam_thm = derive_algLam_base lthy Y Z preT fpT dead_pre_map ctor dtor algLam proto_sctr
2197      dead_pre_map_id dead_pre_map_comp ctor_dtor dtor_ctor dtor_unfold_unique unsig_thm
2198      Sig_pointful_natural ssig_map_thms Lam_def flat_simps eval_core_simps eval_thm algLam_def;
2199
2200    val (((corecUU, _), corecUU_thm, corecUU_unique, corecUU_transfer, eval_sctr, sctr_transfer,
2201          sctr_pointful_natural), lthy) = lthy
2202      |> define_corecUU_etc fp_b version live_AsBs Y Z preT fpT ssig_T pre_map dead_pre_map pre_rel
2203        fp_rel ctor Oper ssig_map dead_ssig_map ssig_rel proto_sctr flat eval_core eval corecU fs f
2204        g Rs R pre_map_transfer [] dtor_unfold_transfer dtor_transfer ssig_map_transfer
2205        proto_sctr_transfer proto_sctr_pointful_natural flat_transfer flat_pointful_natural
2206        eval_core_transfer eval_core_pointful_natural eval_thm eval_flat eval_Oper algLam_thm
2207        cutSsig_def corecU_def corecU_ctor corecU_unique pre_bnf dead_pre_bnf fp_res ssig_fp_sugar;
2208
2209    val (Retr, equivp_Retr, Retr_coinduct) = lthy
2210      |> derive_Retr fp_sugar fpT dead_pre_bnf ctor dtor names_lthy;
2211
2212    val (dtor_coinduct_info, lthy) = lthy
2213      |> derive_cong_base fp_b version fpT dead_ssig_bnf ssig_fp_bnf_sugar dead_pre_bnf eval
2214      eval_thm eval_core_transfer eval_VLeaf eval_sctr sctr_transfer Retr equivp_Retr Retr_coinduct;
2215
2216    val buffer =
2217      {Oper = Oper, VLeaf = VLeaf, CLeaf = CLeaf, ctr_wrapper = Sig, friends = Symtab.empty};
2218
2219    val notes =
2220      [(corecUU_transferN, [corecUU_transfer])] @
2221      (if Config.get lthy bnf_internals then
2222         [(algLamN, [algLam_thm]),
2223          (cong_alg_introsN, #cong_alg_intros dtor_coinduct_info),
2224          (cong_localeN, [#cong_locale dtor_coinduct_info]),
2225          (corecU_ctorN, [corecU_ctor]),
2226          (corecU_uniqueN, [corecU_unique]),
2227          (corecUUN, [corecUU_thm]),
2228          (corecUU_uniqueN, [corecUU_unique]),
2229          (dtor_algLamN, [dtor_algLam]),
2230          (dtor_coinductN, [#dtor_coinduct dtor_coinduct_info]),
2231          (dtor_transferN, [dtor_transfer]),
2232          (equivp_RetrN, [equivp_Retr]),
2233          (evalN, [eval_thm]),
2234          (eval_core_pointful_naturalN, [eval_core_pointful_natural]),
2235          (eval_core_transferN, [eval_core_transfer]),
2236          (eval_flatN, [eval_flat]),
2237          (eval_simpsN, eval_simps),
2238          (flat_pointful_naturalN, [flat_pointful_natural]),
2239          (flat_transferN, [flat_transfer]),
2240          (Lam_pointful_naturalN, [Lam_pointful_natural]),
2241          (Lam_transferN, [Lam_transfer]),
2242          (proto_sctr_pointful_naturalN, [proto_sctr_pointful_natural]),
2243          (proto_sctr_transferN, [proto_sctr_transfer]),
2244          (Retr_coinductN, [Retr_coinduct]),
2245          (sctr_pointful_naturalN, [sctr_pointful_natural]),
2246          (sctr_transferN, [sctr_transfer]),
2247          (Sig_pointful_naturalN, [Sig_pointful_natural])]
2248        else
2249          [])
2250      |> map (fn (thmN, thms) =>
2251        ((mk_version_fp_binding true lthy version fp_b thmN, []), [(thms, [])]));
2252  in
2253    ({fp_b = fp_b, version = version, fpT = fpT, Y = Y, Z = Z, friend_names = [],
2254      sig_fp_sugars = [sig_fp_sugar], ssig_fp_sugar = ssig_fp_sugar, Lam = Lam,
2255      proto_sctr = proto_sctr, flat = flat, eval_core = eval_core, eval = eval, algLam = algLam,
2256      corecUU = corecUU, dtor_transfer = dtor_transfer, Lam_transfer = Lam_transfer,
2257      Lam_pointful_natural = Lam_pointful_natural, proto_sctr_transfer = proto_sctr_transfer,
2258      flat_simps = flat_simps, eval_core_simps = eval_core_simps, eval_thm = eval_thm,
2259      eval_simps = eval_simps, all_algLam_algs = [algLam_thm], algLam_thm = algLam_thm,
2260      dtor_algLam = dtor_algLam, corecUU_thm = corecUU_thm, corecUU_unique = corecUU_unique,
2261      corecUU_transfer = corecUU_transfer, buffer = buffer, all_dead_k_bnfs = [dead_pre_bnf],
2262      Retr = Retr, equivp_Retr = equivp_Retr, Retr_coinduct = Retr_coinduct,
2263      dtor_coinduct_info = dtor_coinduct_info}
2264     |> morph_corec_info (Local_Theory.target_morphism lthy),
2265     lthy |> Local_Theory.notes notes |> snd)
2266  end;
2267
2268fun derive_corecUU_step (fpT as Type (fpT_name, res_Ds))
2269    ({friend_names = old_friend_names, sig_fp_sugars = old_sig_fp_sugars as old_sig_fp_sugar :: _,
2270      ssig_fp_sugar = old_ssig_fp_sugar, Lam = old_Lam0, proto_sctr = old_proto_sctr0,
2271      flat = old_flat0, eval_core = old_eval_core0, eval = old_eval0, algLam = old_algLam0,
2272      dtor_transfer, Lam_transfer = old_Lam_transfer,
2273      Lam_pointful_natural = old_Lam_pointful_natural,
2274      proto_sctr_transfer = old_proto_sctr_transfer, flat_simps = old_flat_simps,
2275      eval_core_simps = old_eval_core_simps, eval_thm = old_eval_thm,
2276      all_algLam_algs = old_all_algLam_algs, algLam_thm = old_algLam_thm,
2277      dtor_algLam = old_dtor_algLam, buffer = old_buffer, all_dead_k_bnfs = old_all_dead_k_bnfs,
2278      Retr = old_Retr0, equivp_Retr, Retr_coinduct, dtor_coinduct_info = old_dtor_coinduct_info,
2279      ...} : corec_info)
2280    friend_name friend_T fp_b version Y Z k_T dead_k_bnf sig_fp_sugar ssig_fp_sugar rho rho_transfer
2281    lthy =
2282  let
2283    val {pre_bnf = live_pre_bnf, fp_bnf = live_fp_bnf, fp_res, ...} =
2284      checked_fp_sugar_of lthy fpT_name;
2285
2286    val names_lthy = lthy
2287      |> fold Variable.declare_typ [Y, Z];
2288
2289    (* FIXME *)
2290    val live_EsFs = [];
2291    val live_AsBs = live_EsFs @ [(Y, Z)];
2292    val live = length live_EsFs;
2293
2294    val ((((x, f), g), R), _) = names_lthy
2295      |> yield_singleton (mk_Frees "x") Y
2296      ||>> yield_singleton (mk_Frees "f") (Y --> Z)
2297      ||>> yield_singleton (mk_Frees "g") (Y --> Z)
2298      ||>> yield_singleton (mk_Frees "R") (mk_pred2T Y Z);
2299
2300    (* FIXME *)
2301    val fs = [];
2302    val Rs = [];
2303
2304    val ctor = mk_ctor res_Ds (the_single (#ctors fp_res));
2305    val dtor = mk_dtor res_Ds (the_single (#dtors fp_res));
2306
2307    val friend_names = friend_name :: old_friend_names;
2308
2309    val old_sig_bnf = #fp_bnf old_sig_fp_sugar;
2310    val old_ssig_bnf = #fp_bnf old_ssig_fp_sugar;
2311    val sig_bnf = #fp_bnf sig_fp_sugar;
2312    val ssig_bnf = #fp_bnf ssig_fp_sugar;
2313
2314    val ((((((dead_pre_bnf, dead_fp_bnf), dead_old_sig_bnf), dead_old_ssig_bnf), dead_sig_bnf),
2315          dead_ssig_bnf), lthy) = lthy
2316      |> bnf_kill_all_but 1 live_pre_bnf
2317      ||>> bnf_kill_all_but 0 live_fp_bnf
2318      ||>> bnf_kill_all_but 1 old_sig_bnf
2319      ||>> bnf_kill_all_but 1 old_ssig_bnf
2320      ||>> bnf_kill_all_but 1 sig_bnf
2321      ||>> bnf_kill_all_but 1 ssig_bnf;
2322
2323    (* FIXME *)
2324    val pre_bnf = dead_pre_bnf;
2325    val fp_bnf = dead_fp_bnf;
2326
2327    val old_ssig_fp_ctr_sugar = #fp_ctr_sugar old_ssig_fp_sugar;
2328    val sig_fp_ctr_sugar = #fp_ctr_sugar sig_fp_sugar;
2329    val ssig_fp_ctr_sugar = #fp_ctr_sugar ssig_fp_sugar;
2330
2331    val sig_fp_bnf_sugar = #fp_bnf_sugar sig_fp_sugar;
2332    val old_ssig_fp_bnf_sugar = #fp_bnf_sugar old_ssig_fp_sugar;
2333    val ssig_fp_bnf_sugar = #fp_bnf_sugar ssig_fp_sugar;
2334    val old_ssig_fp_induct_sugar = the (#fp_co_induct_sugar old_ssig_fp_sugar);
2335    val ssig_fp_induct_sugar = the (#fp_co_induct_sugar ssig_fp_sugar);
2336
2337    val old_ssig_ctr_sugar = #ctr_sugar old_ssig_fp_ctr_sugar;
2338    val sig_ctr_sugar = #ctr_sugar sig_fp_ctr_sugar;
2339    val ssig_ctr_sugar = #ctr_sugar ssig_fp_ctr_sugar;
2340
2341    val old_sig_T_name = fst (dest_Type (#T old_sig_fp_sugar));
2342    val old_ssig_T_name = fst (dest_Type (#T old_ssig_fp_sugar));
2343    val sig_T_name = fst (dest_Type (#T sig_fp_sugar));
2344    val ssig_T_name = fst (dest_Type (#T ssig_fp_sugar));
2345
2346    val res_As = res_Ds @ [Y];
2347    val res_Bs = res_Ds @ [Z];
2348    val preT = pre_type_of_ctor Y ctor;
2349    val YpreT = HOLogic.mk_prodT (Y, preT);
2350    val old_sig_T = Type (old_sig_T_name, res_As);
2351    val old_ssig_T = Type (old_ssig_T_name, res_As);
2352    val sig_T = Type (sig_T_name, res_As);
2353    val ssig_T = Type (ssig_T_name, res_As);
2354    val old_Lam_domT = Tsubst Y YpreT old_sig_T;
2355    val old_eval_core_domT = Tsubst Y YpreT old_ssig_T;
2356
2357    val pre_map = mk_mapN lthy live_AsBs preT pre_bnf;
2358    val pre_rel = mk_relN lthy live_AsBs preT pre_bnf;
2359    val dead_pre_map = mk_map1 lthy Y Z preT dead_pre_bnf;
2360    val dead_pre_rel = mk_rel1 lthy Y Z preT dead_pre_bnf;
2361    val fp_rel = mk_relN lthy live_EsFs fpT fp_bnf;
2362    val dtor_unfold = mk_co_rec (Proof_Context.theory_of lthy) Greatest_FP [Z] fpT
2363      (the_single (#xtor_un_folds fp_res));
2364    val dead_k_map = mk_map1 lthy Y Z k_T dead_k_bnf;
2365    val Sig = mk_ctr res_As (the_single (#ctrs sig_ctr_sugar));
2366    val unsig = mk_disc_or_sel res_As (the_single (the_single (#selss sig_ctr_sugar)));
2367    val sig_rel = mk_relN lthy live_AsBs sig_T sig_bnf;
2368    val dead_old_sig_map = mk_map 1 res_As res_Bs (map_of_bnf dead_old_sig_bnf);
2369    val dead_sig_map = mk_map 1 res_As res_Bs (map_of_bnf dead_sig_bnf);
2370    val dead_sig_rel = mk_rel 1 res_As res_Bs (rel_of_bnf dead_sig_bnf);
2371    val [old_Oper, old_VLeaf, old_CLeaf] = map (mk_ctr res_As) (#ctrs old_ssig_ctr_sugar);
2372    val [Oper, VLeaf, CLeaf] = map (mk_ctr res_As) (#ctrs ssig_ctr_sugar);
2373    val dead_old_ssig_map = mk_map 1 res_As res_Bs (map_of_bnf dead_old_ssig_bnf);
2374    val ssig_map = mk_mapN lthy live_AsBs ssig_T ssig_bnf;
2375    val ssig_rel = mk_relN lthy live_AsBs ssig_T ssig_bnf;
2376    val dead_ssig_map = mk_map 1 res_As res_Bs (map_of_bnf dead_ssig_bnf);
2377    val old_Lam = enforce_type lthy domain_type old_Lam_domT old_Lam0;
2378    val old_proto_sctr = enforce_type lthy domain_type preT old_proto_sctr0;
2379    val old_flat = enforce_type lthy range_type old_ssig_T old_flat0;
2380    val old_eval_core = enforce_type lthy domain_type old_eval_core_domT old_eval_core0;
2381    val old_eval = enforce_type lthy range_type fpT old_eval0;
2382    val old_algLam = enforce_type lthy range_type fpT old_algLam0;
2383
2384    val ((embL, embL_def, embL_simps), lthy) = lthy
2385      |> define_embL embLN fp_b version Y Z fpT old_sig_T old_ssig_T k_T ssig_T Inl_const
2386        dead_old_sig_map Sig old_Oper old_VLeaf old_CLeaf Oper VLeaf CLeaf;
2387
2388    val ((Lam, Lam_def), lthy) = lthy
2389      |> define_Lam_step fp_b version Y Z preT old_ssig_T ssig_T dead_pre_map unsig rho embL
2390        old_Lam;
2391
2392    val ((proto_sctr, proto_sctr_def), lthy) = lthy
2393      |> define_proto_sctr_step_or_merge fp_b version old_sig_T k_T Sig old_proto_sctr;
2394
2395    val pre_map_comp = map_comp_of_bnf pre_bnf;
2396    val pre_map_transfer = map_transfer_of_bnf pre_bnf;
2397    val dead_pre_map_id = map_id_of_bnf dead_pre_bnf;
2398    val dead_pre_map_comp0 = map_comp0_of_bnf dead_pre_bnf;
2399    val dead_pre_map_comp = map_comp_of_bnf dead_pre_bnf;
2400    val fp_map_id = map_id_of_bnf fp_bnf;
2401    val [ctor_dtor] = #ctor_dtors fp_res;
2402    val [dtor_inject] = #dtor_injects fp_res;
2403    val [dtor_unfold_thm] = #xtor_un_fold_thms fp_res;
2404    val dtor_unfold_unique = #xtor_un_fold_unique fp_res;
2405    val [dtor_unfold_transfer] = #xtor_un_fold_transfers fp_res;
2406    val fp_k_T_rel_eqs =
2407      map rel_eq_of_bnf (map_filter (bnf_of lthy) (fold add_type_namesT [fpT, k_T] []));
2408    val unsig_thm = the_single (the_single (#sel_thmss sig_ctr_sugar));
2409    val [sig_map_thm] = #map_thms sig_fp_bnf_sugar;
2410    val old_sig_map_comp = map_comp_of_bnf old_sig_bnf;
2411    val old_sig_map_cong = map_cong_of_bnf old_sig_bnf;
2412    val old_ssig_map_thms = #map_thms old_ssig_fp_bnf_sugar;
2413    val [Oper_map_thm, VLeaf_map_thm, CLeaf_map_thm] = #map_thms ssig_fp_bnf_sugar;
2414    val old_sig_map_transfer = map_transfer_of_bnf old_sig_bnf;
2415    val sig_map_comp = map_comp_of_bnf sig_bnf;
2416    val sig_map_transfer = map_transfer_of_bnf sig_bnf;
2417    val ssig_map_thms = #map_thms ssig_fp_bnf_sugar;
2418    val ssig_map_transfer = map_transfer_of_bnf ssig_bnf;
2419    val old_ssig_induct = the_single (#co_inducts old_ssig_fp_induct_sugar);
2420    val ssig_induct = the_single (#co_inducts ssig_fp_induct_sugar);
2421
2422    val proto_sctr_transfer = derive_proto_sctr_transfer_step_or_merge lthy Y Z R dead_pre_rel
2423      dead_sig_rel proto_sctr proto_sctr_def fp_k_T_rel_eqs [old_proto_sctr_transfer];
2424    val embL_transfer = derive_transfer_by_transfer_prover lthy live_AsBs Rs R embL [embL_def]
2425      fp_k_T_rel_eqs [old_sig_map_transfer];
2426    val Lam_transfer = derive_Lam_or_eval_core_transfer lthy live_AsBs Y Z preT ssig_T Rs R pre_rel
2427      sig_rel ssig_rel Lam Lam_def fp_k_T_rel_eqs
2428      [pre_map_transfer, old_Lam_transfer, embL_transfer, rho_transfer];
2429
2430    val ((((((((flat, _, flat_simps), flat_transfer),
2431            ((eval_core, _, eval_core_simps), eval_core_transfer)), (eval, eval_def)),
2432          (cutSsig, cutSsig_def)), (algLam, algLam_def)), (corecU, corecU_def)), lthy) = lthy
2433      |> define_flat_etc fp_b version live_AsBs Y Z preT fpT sig_T ssig_T Oper VLeaf CLeaf pre_rel
2434        dead_pre_map dtor dtor_unfold dead_sig_map ssig_rel dead_ssig_map Lam Rs R pre_map_transfer
2435        fp_k_T_rel_eqs sig_map_transfer ssig_map_transfer Lam_transfer dtor_transfer;
2436
2437    val (Sig_pointful_natural, flat_pointful_natural, Lam_natural_pointful, Lam_pointful_natural,
2438         flat_VLeaf, eval_core_pointful_natural, eval_thm, eval_flat,
2439         eval_simps as [eval_Oper, _, _], corecU_ctor, corecU_unique, dtor_algLam) =
2440      derive_Sig_natural_etc lthy live live_AsBs Y Z preT fpT k_T sig_T ssig_T pre_map dead_pre_map
2441        ctor dtor Sig dead_sig_map Oper VLeaf CLeaf ssig_map dead_ssig_map Lam flat eval_core eval
2442        cutSsig algLam corecU x fs f g ctor_dtor dtor_inject dtor_unfold_thm dtor_unfold_unique
2443        sig_map_thm ssig_induct ssig_map_thms Oper_map_thm VLeaf_map_thm CLeaf_map_thm Lam_transfer
2444        flat_simps flat_transfer eval_core_simps eval_core_transfer eval_def cutSsig_def algLam_def
2445        corecU_def live_pre_bnf pre_bnf dead_pre_bnf fp_bnf sig_bnf ssig_bnf dead_ssig_bnf;
2446
2447    val proto_sctr_natural = derive_natural_from_transfer_with_pre_type lthy live_AsBs Y Z preT
2448      ssig_T pre_map ssig_map fs f proto_sctr proto_sctr_transfer [pre_bnf, sig_bnf] [];
2449    val proto_sctr_pointful_natural = mk_pointful lthy proto_sctr_natural RS sym;
2450
2451    val (embL_pointful_natural, old_algLam_pointful, eval_embL, algLam_algLam) =
2452      derive_embL_natural_etc lthy Inl_const old_ssig_bnf ssig_bnf Y Z preT fpT old_ssig_T ssig_T
2453        dead_pre_map Sig dead_old_ssig_map embL old_algLam algLam old_flat flat old_eval_core
2454        eval_core old_eval eval x f old_ssig_induct dead_pre_map_comp0 dead_pre_map_comp fp_map_id
2455        dtor_inject dtor_unfold_unique Sig_pointful_natural unsig_thm sig_map_thm old_sig_map_comp
2456        old_sig_map_cong old_ssig_map_thms old_Lam_pointful_natural Lam_def old_flat_simps
2457        flat_simps embL_simps embL_transfer old_eval_core_simps eval_core_simps old_eval_thm
2458        eval_thm old_dtor_algLam dtor_algLam old_algLam_thm;
2459
2460    val algLam_thm = derive_algLam_step_or_merge lthy Y fpT ctor proto_sctr algLam proto_sctr_def
2461      old_algLam_pointful algLam_algLam;
2462
2463    val k_as_ssig = mk_k_as_ssig Z old_sig_T k_T ssig_T Sig dead_sig_map Oper VLeaf;
2464    val k_as_ssig' = substT Y fpT k_as_ssig;
2465
2466    val algrho_rhs = HOLogic.mk_comp (eval, k_as_ssig');
2467    val ((algrho, algrho_def), lthy) = lthy
2468      |> define_const true fp_b version algrhoN algrho_rhs;
2469
2470    val k_as_ssig_transfer = derive_transfer_by_transfer_prover lthy live_AsBs Rs R k_as_ssig []
2471      fp_k_T_rel_eqs [sig_map_transfer];
2472
2473    val k_as_ssig_natural = derive_natural_from_transfer lthy [(Y, Z)] [] [] f k_as_ssig
2474      k_as_ssig_transfer [ssig_bnf] [dead_k_bnf];
2475
2476    val k_as_ssig_natural_pointful = mk_pointful lthy k_as_ssig_natural;
2477
2478    val [_, Lam_Inr] = derive_Lam_Inl_Inr lthy Y Z preT old_sig_T old_ssig_T k_T ssig_T
2479      dead_pre_map Sig embL old_Lam Lam rho unsig_thm Lam_def;
2480
2481    val eval_core_k_as_ssig = derive_eval_core_k_as_ssig lthy Y preT k_T rho eval_core k_as_ssig x
2482      pre_map_comp dead_pre_map_id sig_map_comp ssig_map_thms Lam_natural_pointful Lam_Inr
2483      flat_VLeaf eval_core_simps;
2484
2485    val algLam_algrho = derive_algLam_algrho lthy Y fpT Sig algLam algrho algLam_def algrho_def;
2486    val dtor_algrho = derive_dtor_algrho lthy Y Z preT fpT k_T ssig_T dead_pre_map dead_k_map dtor
2487      rho eval algrho x eval_thm k_as_ssig_natural_pointful eval_core_k_as_ssig algrho_def;
2488    val all_algLam_algs = algLam_algLam :: algLam_algrho :: old_all_algLam_algs;
2489
2490    val (((corecUU, _), corecUU_thm, corecUU_unique, corecUU_transfer, _, sctr_transfer,
2491          sctr_pointful_natural), lthy) = lthy
2492      |> define_corecUU_etc fp_b version live_AsBs Y Z preT fpT ssig_T pre_map dead_pre_map pre_rel
2493        fp_rel ctor Oper ssig_map dead_ssig_map ssig_rel proto_sctr flat eval_core eval corecU fs f
2494        g Rs R pre_map_transfer fp_k_T_rel_eqs dtor_unfold_transfer dtor_transfer ssig_map_transfer
2495        proto_sctr_transfer proto_sctr_pointful_natural flat_transfer flat_pointful_natural
2496        eval_core_transfer eval_core_pointful_natural eval_thm eval_flat eval_Oper algLam_thm
2497        cutSsig_def corecU_def corecU_ctor corecU_unique pre_bnf dead_pre_bnf fp_res ssig_fp_sugar;
2498
2499    val (ctr_wrapper, friends) =
2500      mk_ctr_wrapper_friends lthy friend_name friend_T old_sig_T k_T Sig old_buffer;
2501
2502    val Retr = enforce_type lthy (domain_type o domain_type) fpT old_Retr0;
2503
2504    val (dtor_coinduct_info, lthy) = lthy
2505      |> derive_cong_step fp_b version fpT dead_ssig_bnf dead_pre_bnf eval eval_thm
2506        eval_core_transfer old_dtor_coinduct_info algrho_def k_as_ssig_transfer Retr equivp_Retr
2507        Retr_coinduct eval_embL embL_transfer old_all_dead_k_bnfs;
2508
2509    val buffer =
2510      {Oper = Oper, VLeaf = VLeaf, CLeaf = CLeaf, ctr_wrapper = ctr_wrapper, friends = friends};
2511
2512    val notes =
2513      [(corecUU_transferN, [corecUU_transfer])] @
2514      (if Config.get lthy bnf_internals then
2515         [(algLamN, [algLam_thm]),
2516          (algLam_algLamN, [algLam_algLam]),
2517          (algLam_algrhoN, [algLam_algrho]),
2518          (cong_alg_introsN, #cong_alg_intros dtor_coinduct_info),
2519          (cong_localeN, [#cong_locale dtor_coinduct_info]),
2520          (corecU_ctorN, [corecU_ctor]),
2521          (corecU_uniqueN, [corecU_unique]),
2522          (corecUUN, [corecUU_thm]),
2523          (corecUU_uniqueN, [corecUU_unique]),
2524          (dtor_algLamN, [dtor_algLam]),
2525          (dtor_algrhoN, [dtor_algrho]),
2526          (dtor_coinductN, [#dtor_coinduct dtor_coinduct_info]),
2527          (embL_pointful_naturalN, [embL_pointful_natural]),
2528          (embL_transferN, [embL_transfer]),
2529          (evalN, [eval_thm]),
2530          (eval_core_pointful_naturalN, [eval_core_pointful_natural]),
2531          (eval_core_transferN, [eval_core_transfer]),
2532          (eval_flatN, [eval_flat]),
2533          (eval_simpsN, eval_simps),
2534          (flat_pointful_naturalN, [flat_pointful_natural]),
2535          (flat_transferN, [flat_transfer]),
2536          (k_as_ssig_naturalN, [k_as_ssig_natural]),
2537          (k_as_ssig_transferN, [k_as_ssig_transfer]),
2538          (Lam_pointful_naturalN, [Lam_pointful_natural]),
2539          (Lam_transferN, [Lam_transfer]),
2540          (proto_sctr_pointful_naturalN, [proto_sctr_pointful_natural]),
2541          (proto_sctr_transferN, [proto_sctr_transfer]),
2542          (rho_transferN, [rho_transfer]),
2543          (sctr_pointful_naturalN, [sctr_pointful_natural]),
2544          (sctr_transferN, [sctr_transfer]),
2545          (Sig_pointful_naturalN, [Sig_pointful_natural])]
2546       else
2547         [])
2548      |> map (fn (thmN, thms) =>
2549        ((mk_version_fp_binding true lthy version fp_b thmN, []), [(thms, [])]));
2550
2551    val phi = Local_Theory.target_morphism lthy;
2552  in
2553    (({fp_b = fp_b, version = version, fpT = fpT, Y = Y, Z = Z, friend_names = friend_names,
2554       sig_fp_sugars = sig_fp_sugar :: old_sig_fp_sugars, ssig_fp_sugar = ssig_fp_sugar, Lam = Lam,
2555       proto_sctr = proto_sctr, flat = flat, eval_core = eval_core, eval = eval, algLam = algLam,
2556       corecUU = corecUU, dtor_transfer = dtor_transfer, Lam_transfer = Lam_transfer,
2557       Lam_pointful_natural = Lam_pointful_natural, proto_sctr_transfer = proto_sctr_transfer,
2558       flat_simps = flat_simps, eval_core_simps = eval_core_simps, eval_thm = eval_thm,
2559       eval_simps = eval_simps, all_algLam_algs = all_algLam_algs, algLam_thm = algLam_thm,
2560       dtor_algLam = dtor_algLam, corecUU_thm = corecUU_thm, corecUU_unique = corecUU_unique,
2561       corecUU_transfer = corecUU_transfer, buffer = buffer,
2562       all_dead_k_bnfs = dead_k_bnf :: old_all_dead_k_bnfs, Retr = Retr, equivp_Retr = equivp_Retr,
2563       Retr_coinduct = Retr_coinduct, dtor_coinduct_info = dtor_coinduct_info}
2564      |> morph_corec_info phi,
2565      ({algrho = algrho, dtor_algrho = dtor_algrho, algLam_algrho = algLam_algrho}
2566       |> morph_friend_info phi)),
2567     lthy |> Local_Theory.notes notes |> snd)
2568  end;
2569
2570fun derive_corecUU_merge (fpT as Type (fpT_name, res_Ds))
2571    ({friend_names = old1_friend_names,
2572      sig_fp_sugars = old1_sig_fp_sugars as old1_sig_fp_sugar :: _,
2573      ssig_fp_sugar = old1_ssig_fp_sugar, Lam = old1_Lam0, proto_sctr = old1_proto_sctr0,
2574      flat = old1_flat0, eval_core = old1_eval_core0, eval = old1_eval0, algLam = old1_algLam0,
2575      dtor_transfer, Lam_transfer = old1_Lam_transfer,
2576      Lam_pointful_natural = old1_Lam_pointful_natural,
2577      proto_sctr_transfer = old1_proto_sctr_transfer, flat_simps = old1_flat_simps,
2578      eval_core_simps = old1_eval_core_simps, eval_thm = old1_eval_thm,
2579      all_algLam_algs = old1_all_algLam_algs, algLam_thm = old1_algLam_thm,
2580      dtor_algLam = old1_dtor_algLam, buffer = old1_buffer, all_dead_k_bnfs = old1_all_dead_k_bnfs,
2581      Retr = old1_Retr0, equivp_Retr, Retr_coinduct, dtor_coinduct_info = old1_dtor_coinduct_info,
2582      ...} : corec_info)
2583    ({friend_names = old2_friend_names,
2584      sig_fp_sugars = old2_sig_fp_sugars as old2_sig_fp_sugar :: _,
2585      ssig_fp_sugar = old2_ssig_fp_sugar, Lam = old2_Lam0, flat = old2_flat0,
2586      eval_core = old2_eval_core0, eval = old2_eval0, algLam = old2_algLam0,
2587      Lam_transfer = old2_Lam_transfer, Lam_pointful_natural = old2_Lam_pointful_natural,
2588      flat_simps = old2_flat_simps, eval_core_simps = old2_eval_core_simps,
2589      eval_thm = old2_eval_thm, all_algLam_algs = old2_all_algLam_algs,
2590      algLam_thm = old2_algLam_thm, dtor_algLam = old2_dtor_algLam, buffer = old2_buffer,
2591      all_dead_k_bnfs = old2_all_dead_k_bnfs, dtor_coinduct_info = old2_dtor_coinduct_info, ...}
2592     : corec_info)
2593    lthy =
2594  let
2595    val {T = Type (_, fpT_args0), pre_bnf = live_pre_bnf, fp_bnf = live_fp_bnf, fp_res, ...} =
2596      checked_fp_sugar_of lthy fpT_name;
2597    val fpT_Ss = map Type.sort_of_atyp fpT_args0;
2598    val live_fp_alives = liveness_of_fp_bnf (length fpT_args0) live_fp_bnf;
2599
2600    val ((Ds, [Y, Z]), names_lthy) = lthy
2601      |> mk_TFrees' fpT_Ss
2602      ||>> mk_TFrees 2;
2603
2604    (* FIXME *)
2605    val live_EsFs = [];
2606    val live_AsBs = live_EsFs @ [(Y, Z)];
2607    val live = length live_EsFs;
2608
2609    val ((((x, f), g), R), _) = names_lthy
2610      |> yield_singleton (mk_Frees "x") Y
2611      ||>> yield_singleton (mk_Frees "f") (Y --> Z)
2612      ||>> yield_singleton (mk_Frees "g") (Y --> Z)
2613      ||>> yield_singleton (mk_Frees "R") (mk_pred2T Y Z);
2614
2615    (* FIXME *)
2616    val fs = [];
2617    val Rs = [];
2618
2619    val ctor = mk_ctor res_Ds (the_single (#ctors fp_res));
2620    val dtor = mk_dtor res_Ds (the_single (#dtors fp_res));
2621
2622    val old1_sig_T_name = fst (dest_Type (#T old1_sig_fp_sugar));
2623    val old2_sig_T_name = fst (dest_Type (#T old2_sig_fp_sugar));
2624    val old1_ssig_T_name = fst (dest_Type (#T old1_ssig_fp_sugar));
2625    val old2_ssig_T_name = fst (dest_Type (#T old2_ssig_fp_sugar));
2626
2627    val fp_alives = map (K false) live_fp_alives;
2628
2629    val As = Ds @ [Y];
2630    val res_As = res_Ds @ [Y];
2631    val res_Bs = res_Ds @ [Z];
2632    val preT = pre_type_of_ctor Y ctor;
2633    val YpreT = HOLogic.mk_prodT (Y, preT);
2634    val fpT0 = Type (fpT_name, Ds);
2635    val old1_sig_T0 = Type (old1_sig_T_name, As);
2636    val old2_sig_T0 = Type (old2_sig_T_name, As);
2637    val old1_sig_T = Type (old1_sig_T_name, res_As);
2638    val old2_sig_T = Type (old2_sig_T_name, res_As);
2639    val old1_ssig_T = Type (old1_ssig_T_name, res_As);
2640    val old2_ssig_T = Type (old2_ssig_T_name, res_As);
2641    val old1_Lam_domT = Tsubst Y YpreT old1_sig_T;
2642    val old2_Lam_domT = Tsubst Y YpreT old2_sig_T;
2643    val old1_eval_core_domT = Tsubst Y YpreT old1_ssig_T;
2644    val old2_eval_core_domT = Tsubst Y YpreT old2_ssig_T;
2645
2646    val ((fp_b, version), lthy) = lthy |> get_name_next_version_of fpT_name;
2647
2648    val ((sig_fp_sugar, ssig_fp_sugar), lthy) = lthy
2649      |> define_sig_type fp_b version fp_alives Ds Y (mk_sumT (old1_sig_T0, old2_sig_T0))
2650      ||>> define_ssig_type fp_b version fp_alives Ds Y fpT0;
2651
2652    val sig_T_name = fst (dest_Type (#T sig_fp_sugar));
2653    val ssig_T_name = fst (dest_Type (#T ssig_fp_sugar));
2654
2655    val old1_sig_bnf = #fp_bnf old1_sig_fp_sugar;
2656    val old2_sig_bnf = #fp_bnf old2_sig_fp_sugar;
2657    val old1_ssig_bnf = #fp_bnf old1_ssig_fp_sugar;
2658    val old2_ssig_bnf = #fp_bnf old2_ssig_fp_sugar;
2659    val sig_bnf = #fp_bnf sig_fp_sugar;
2660    val ssig_bnf = #fp_bnf ssig_fp_sugar;
2661
2662    val ((((((((dead_pre_bnf, dead_fp_bnf), dead_old1_sig_bnf), dead_old2_sig_bnf),
2663        dead_old1_ssig_bnf), dead_old2_ssig_bnf), dead_sig_bnf), dead_ssig_bnf), lthy) = lthy
2664      |> bnf_kill_all_but 1 live_pre_bnf
2665      ||>> bnf_kill_all_but 0 live_fp_bnf
2666      ||>> bnf_kill_all_but 1 old1_sig_bnf
2667      ||>> bnf_kill_all_but 1 old2_sig_bnf
2668      ||>> bnf_kill_all_but 1 old1_ssig_bnf
2669      ||>> bnf_kill_all_but 1 old2_ssig_bnf
2670      ||>> bnf_kill_all_but 1 sig_bnf
2671      ||>> bnf_kill_all_but 1 ssig_bnf;
2672
2673    (* FIXME *)
2674    val pre_bnf = dead_pre_bnf;
2675    val fp_bnf = dead_fp_bnf;
2676
2677    val old1_ssig_fp_ctr_sugar = #fp_ctr_sugar old1_ssig_fp_sugar;
2678    val old2_ssig_fp_ctr_sugar = #fp_ctr_sugar old2_ssig_fp_sugar;
2679    val sig_fp_ctr_sugar = #fp_ctr_sugar sig_fp_sugar;
2680    val ssig_fp_ctr_sugar = #fp_ctr_sugar ssig_fp_sugar;
2681
2682    val sig_fp_bnf_sugar = #fp_bnf_sugar sig_fp_sugar;
2683    val old1_ssig_fp_bnf_sugar = #fp_bnf_sugar old1_ssig_fp_sugar;
2684    val old2_ssig_fp_bnf_sugar = #fp_bnf_sugar old2_ssig_fp_sugar;
2685    val ssig_fp_bnf_sugar = #fp_bnf_sugar ssig_fp_sugar;
2686    val old1_ssig_fp_induct_sugar = the (#fp_co_induct_sugar old1_ssig_fp_sugar);
2687    val old2_ssig_fp_induct_sugar = the (#fp_co_induct_sugar old2_ssig_fp_sugar);
2688    val ssig_fp_induct_sugar = the (#fp_co_induct_sugar ssig_fp_sugar);
2689
2690    val old1_ssig_ctr_sugar = #ctr_sugar old1_ssig_fp_ctr_sugar;
2691    val old2_ssig_ctr_sugar = #ctr_sugar old2_ssig_fp_ctr_sugar;
2692    val sig_ctr_sugar = #ctr_sugar sig_fp_ctr_sugar;
2693    val ssig_ctr_sugar = #ctr_sugar ssig_fp_ctr_sugar;
2694
2695    val sig_T = Type (sig_T_name, res_As);
2696    val ssig_T = Type (ssig_T_name, res_As);
2697
2698    val pre_map = mk_mapN lthy live_AsBs preT pre_bnf;
2699    val pre_rel = mk_relN lthy live_AsBs preT pre_bnf;
2700    val dead_pre_map = mk_map1 lthy Y Z preT dead_pre_bnf;
2701    val dead_pre_rel = mk_rel1 lthy Y Z preT dead_pre_bnf;
2702    val fp_rel = mk_relN lthy live_EsFs fpT fp_bnf;
2703    val dtor_unfold = mk_co_rec (Proof_Context.theory_of lthy) Greatest_FP [Z] fpT
2704      (the_single (#xtor_un_folds fp_res));
2705    val Sig = mk_ctr res_As (the_single (#ctrs sig_ctr_sugar));
2706    val unsig = mk_disc_or_sel res_As (the_single (the_single (#selss sig_ctr_sugar)));
2707    val sig_rel = mk_relN lthy live_AsBs sig_T sig_bnf;
2708    val dead_old1_sig_map = mk_map 1 res_As res_Bs (map_of_bnf dead_old1_sig_bnf);
2709    val dead_old2_sig_map = mk_map 1 res_As res_Bs (map_of_bnf dead_old2_sig_bnf);
2710    val dead_sig_map = mk_map 1 res_As res_Bs (map_of_bnf dead_sig_bnf);
2711    val dead_sig_rel = mk_rel 1 res_As res_Bs (rel_of_bnf dead_sig_bnf);
2712    val [old1_Oper, old1_VLeaf, old1_CLeaf] = map (mk_ctr res_As) (#ctrs old1_ssig_ctr_sugar);
2713    val [old2_Oper, old2_VLeaf, old2_CLeaf] = map (mk_ctr res_As) (#ctrs old2_ssig_ctr_sugar);
2714    val [Oper, VLeaf, CLeaf] = map (mk_ctr res_As) (#ctrs ssig_ctr_sugar);
2715    val old1_ssig_map = mk_map 1 res_As res_Bs (map_of_bnf dead_old1_ssig_bnf);
2716    val old2_ssig_map = mk_map 1 res_As res_Bs (map_of_bnf dead_old2_ssig_bnf);
2717    val ssig_map = mk_mapN lthy live_AsBs ssig_T ssig_bnf;
2718    val ssig_rel = mk_relN lthy live_AsBs ssig_T ssig_bnf;
2719    val dead_ssig_map = mk_map 1 res_As res_Bs (map_of_bnf dead_ssig_bnf);
2720    val old1_Lam = enforce_type lthy domain_type old1_Lam_domT old1_Lam0;
2721    val old2_Lam = enforce_type lthy domain_type old2_Lam_domT old2_Lam0;
2722    val old1_proto_sctr = enforce_type lthy domain_type preT old1_proto_sctr0;
2723    val old1_flat = enforce_type lthy range_type old1_ssig_T old1_flat0;
2724    val old2_flat = enforce_type lthy range_type old2_ssig_T old2_flat0;
2725    val old1_eval_core = enforce_type lthy domain_type old1_eval_core_domT old1_eval_core0;
2726    val old2_eval_core = enforce_type lthy domain_type old2_eval_core_domT old2_eval_core0;
2727    val old1_eval = enforce_type lthy range_type fpT old1_eval0;
2728    val old2_eval = enforce_type lthy range_type fpT old2_eval0;
2729    val old1_algLam = enforce_type lthy range_type fpT old1_algLam0;
2730    val old2_algLam = enforce_type lthy range_type fpT old2_algLam0;
2731
2732    val ((embLL, embLL_def, embLL_simps), lthy) = lthy
2733      |> define_embL embLLN fp_b version Y Z fpT old1_sig_T old1_ssig_T old2_sig_T ssig_T Inl_const
2734        dead_old1_sig_map Sig old1_Oper old1_VLeaf old1_CLeaf Oper VLeaf CLeaf;
2735
2736    val ((embLR, embLR_def, embLR_simps), lthy) = lthy
2737      |> define_embL embLRN fp_b version Y Z fpT old2_sig_T old2_ssig_T old1_sig_T ssig_T
2738        (fn T => fn U => Inr_const U T) dead_old2_sig_map Sig old2_Oper old2_VLeaf old2_CLeaf Oper
2739        VLeaf CLeaf;
2740
2741    val ((Lam, Lam_def), lthy) = lthy
2742      |> define_Lam_merge fp_b version Y Z preT old1_ssig_T old2_ssig_T ssig_T dead_pre_map unsig
2743        embLL embLR old1_Lam old2_Lam;
2744
2745    val ((proto_sctr, proto_sctr_def), lthy) = lthy
2746      |> define_proto_sctr_step_or_merge fp_b version old1_sig_T old2_sig_T Sig old1_proto_sctr;
2747
2748    val pre_map_transfer = map_transfer_of_bnf pre_bnf;
2749    val dead_pre_map_comp0 = map_comp0_of_bnf dead_pre_bnf;
2750    val dead_pre_map_comp = map_comp_of_bnf dead_pre_bnf;
2751    val fp_map_id = map_id_of_bnf fp_bnf;
2752    val fp_rel_eq = rel_eq_of_bnf fp_bnf;
2753    val [ctor_dtor] = #ctor_dtors fp_res;
2754    val [dtor_inject] = #dtor_injects fp_res;
2755    val [dtor_unfold_thm] = #xtor_un_fold_thms fp_res;
2756    val dtor_unfold_unique = #xtor_un_fold_unique fp_res;
2757    val [dtor_unfold_transfer] = #xtor_un_fold_transfers fp_res;
2758    val unsig_thm = the_single (the_single (#sel_thmss sig_ctr_sugar));
2759    val [sig_map_thm] = #map_thms sig_fp_bnf_sugar;
2760    val old1_sig_map_comp = map_comp_of_bnf old1_sig_bnf;
2761    val old2_sig_map_comp = map_comp_of_bnf old2_sig_bnf;
2762    val old1_sig_map_cong = map_cong_of_bnf old1_sig_bnf;
2763    val old2_sig_map_cong = map_cong_of_bnf old2_sig_bnf;
2764    val old1_ssig_map_thms = #map_thms old1_ssig_fp_bnf_sugar;
2765    val old2_ssig_map_thms = #map_thms old2_ssig_fp_bnf_sugar;
2766    val [Oper_map_thm, VLeaf_map_thm, CLeaf_map_thm] = #map_thms ssig_fp_bnf_sugar;
2767    val old1_sig_map_transfer = map_transfer_of_bnf old1_sig_bnf;
2768    val old2_sig_map_transfer = map_transfer_of_bnf old2_sig_bnf;
2769    val sig_map_transfer = map_transfer_of_bnf sig_bnf;
2770    val ssig_map_thms = #map_thms ssig_fp_bnf_sugar;
2771    val ssig_map_transfer = map_transfer_of_bnf ssig_bnf;
2772    val old1_ssig_induct = the_single (#co_inducts old1_ssig_fp_induct_sugar);
2773    val old2_ssig_induct = the_single (#co_inducts old2_ssig_fp_induct_sugar);
2774    val ssig_induct = the_single (#co_inducts ssig_fp_induct_sugar);
2775
2776    val proto_sctr_transfer = derive_proto_sctr_transfer_step_or_merge lthy Y Z R dead_pre_rel
2777      dead_sig_rel proto_sctr proto_sctr_def [] [old1_proto_sctr_transfer];
2778    val embLL_transfer = derive_transfer_by_transfer_prover lthy live_AsBs Rs R embLL [embLL_def] []
2779      [old1_sig_map_transfer];
2780    val embLR_transfer = derive_transfer_by_transfer_prover lthy live_AsBs Rs R embLR [embLR_def] []
2781      [old2_sig_map_transfer];
2782    val Lam_transfer = derive_Lam_or_eval_core_transfer lthy live_AsBs Y Z preT ssig_T Rs R
2783      pre_rel sig_rel ssig_rel Lam Lam_def []
2784      [pre_map_transfer, old1_Lam_transfer, old2_Lam_transfer, embLL_transfer, embLR_transfer];
2785
2786    val ((((((((flat, _, flat_simps), flat_transfer),
2787            ((eval_core, _, eval_core_simps), eval_core_transfer)), (eval, eval_def)),
2788          (cutSsig, cutSsig_def)), (algLam, algLam_def)), (corecU, corecU_def)), lthy) = lthy
2789      |> define_flat_etc fp_b version live_AsBs Y Z preT fpT sig_T ssig_T Oper VLeaf CLeaf pre_rel
2790        dead_pre_map dtor dtor_unfold dead_sig_map ssig_rel dead_ssig_map Lam Rs R pre_map_transfer
2791        [fp_rel_eq] sig_map_transfer ssig_map_transfer Lam_transfer dtor_transfer;
2792
2793    val (Sig_pointful_natural, flat_pointful_natural, _, Lam_pointful_natural, _,
2794         eval_core_pointful_natural, eval_thm, eval_flat, eval_simps as [eval_Oper, _, _],
2795         corecU_ctor, corecU_unique, dtor_algLam) =
2796      derive_Sig_natural_etc lthy live live_AsBs Y Z preT fpT fpT sig_T ssig_T pre_map dead_pre_map
2797        ctor dtor Sig dead_sig_map Oper VLeaf CLeaf ssig_map dead_ssig_map Lam flat eval_core eval
2798        cutSsig algLam corecU x fs f g ctor_dtor dtor_inject dtor_unfold_thm dtor_unfold_unique
2799        sig_map_thm ssig_induct ssig_map_thms Oper_map_thm VLeaf_map_thm CLeaf_map_thm Lam_transfer
2800        flat_simps flat_transfer eval_core_simps eval_core_transfer eval_def cutSsig_def algLam_def
2801        corecU_def live_pre_bnf pre_bnf dead_pre_bnf fp_bnf sig_bnf ssig_bnf dead_ssig_bnf;
2802
2803    val proto_sctr_natural = derive_natural_from_transfer_with_pre_type lthy live_AsBs Y Z preT
2804      ssig_T pre_map ssig_map fs f proto_sctr proto_sctr_transfer [pre_bnf, sig_bnf] [];
2805    val proto_sctr_pointful_natural = mk_pointful lthy proto_sctr_natural RS sym;
2806
2807    val (embLL_pointful_natural, old1_algLam_pointful, eval_embLL, algLam_algLamL) =
2808      derive_embL_natural_etc lthy Inl_const old1_ssig_bnf ssig_bnf Y Z preT fpT old1_ssig_T ssig_T
2809        dead_pre_map Sig old1_ssig_map embLL old1_algLam algLam old1_flat flat old1_eval_core
2810        eval_core old1_eval eval x f old1_ssig_induct dead_pre_map_comp0 dead_pre_map_comp fp_map_id
2811        dtor_inject dtor_unfold_unique Sig_pointful_natural unsig_thm sig_map_thm old1_sig_map_comp
2812        old1_sig_map_cong old1_ssig_map_thms old1_Lam_pointful_natural Lam_def old1_flat_simps
2813        flat_simps embLL_simps embLL_transfer old1_eval_core_simps eval_core_simps old1_eval_thm
2814        eval_thm old1_dtor_algLam dtor_algLam old1_algLam_thm;
2815
2816    val (embLR_pointful_natural, _, eval_embLR, algLam_algLamR) =
2817      derive_embL_natural_etc lthy Inr_const old2_ssig_bnf ssig_bnf Y Z preT fpT old2_ssig_T ssig_T
2818        dead_pre_map Sig old2_ssig_map embLR old2_algLam algLam old2_flat flat old2_eval_core
2819        eval_core old2_eval eval x f old2_ssig_induct dead_pre_map_comp0 dead_pre_map_comp fp_map_id
2820        dtor_inject dtor_unfold_unique Sig_pointful_natural unsig_thm sig_map_thm old2_sig_map_comp
2821        old2_sig_map_cong old2_ssig_map_thms old2_Lam_pointful_natural Lam_def old2_flat_simps
2822        flat_simps embLR_simps embLR_transfer old2_eval_core_simps eval_core_simps old2_eval_thm
2823        eval_thm old2_dtor_algLam dtor_algLam old2_algLam_thm;
2824
2825    val algLam_thm = derive_algLam_step_or_merge lthy Y fpT ctor proto_sctr algLam proto_sctr_def
2826      old1_algLam_pointful algLam_algLamL;
2827
2828    val all_algLam_algs = algLam_algLamL :: algLam_algLamR ::
2829      merge_lists (Thm.eq_thm_prop o apply2 zero_var_indexes) old1_all_algLam_algs
2830        old2_all_algLam_algs;
2831
2832    val (((corecUU, _), corecUU_thm, corecUU_unique, corecUU_transfer, _, sctr_transfer,
2833          sctr_pointful_natural), lthy) = lthy
2834      |> define_corecUU_etc fp_b version live_AsBs Y Z preT fpT ssig_T pre_map dead_pre_map pre_rel
2835        fp_rel ctor Oper ssig_map dead_ssig_map ssig_rel proto_sctr flat eval_core eval corecU fs f
2836        g Rs R pre_map_transfer [] dtor_unfold_transfer dtor_transfer ssig_map_transfer
2837        proto_sctr_transfer proto_sctr_pointful_natural flat_transfer flat_pointful_natural
2838        eval_core_transfer eval_core_pointful_natural eval_thm eval_flat eval_Oper algLam_thm
2839        cutSsig_def corecU_def corecU_ctor corecU_unique pre_bnf dead_pre_bnf fp_res ssig_fp_sugar;
2840
2841    val Retr = enforce_type lthy (domain_type o domain_type) fpT old1_Retr0;
2842
2843    val embed_Sig_inl = embed_Sig lthy Sig (Inl_const old1_sig_T old2_sig_T);
2844    val embed_Sig_inr = embed_Sig lthy Sig (Inr_const old1_sig_T old2_sig_T);
2845
2846    val ctr_wrapper = embed_Sig_inl (#ctr_wrapper old1_buffer);
2847    val friends = Symtab.merge (K true)
2848      (Symtab.map (K (apsnd embed_Sig_inl)) (#friends old1_buffer),
2849       Symtab.map (K (apsnd embed_Sig_inr)) (#friends old2_buffer));
2850
2851    val old_fp_sugars =
2852      merge_lists (op = o apply2 (fst o dest_Type o #T)) old1_sig_fp_sugars old2_sig_fp_sugars;
2853
2854    val ((dtor_coinduct_info, all_dead_k_bnfs, friend_names), lthy) = lthy
2855      |> derive_cong_merge fp_b version fpT old1_friend_names old2_friend_names dead_ssig_bnf
2856        dead_pre_bnf eval eval_thm eval_core_transfer old1_dtor_coinduct_info
2857        old2_dtor_coinduct_info Retr equivp_Retr Retr_coinduct eval_embLL embLL_transfer eval_embLR
2858        embLR_transfer old1_all_dead_k_bnfs old2_all_dead_k_bnfs;
2859
2860    val buffer =
2861      {Oper = Oper, VLeaf = VLeaf, CLeaf = CLeaf, ctr_wrapper = ctr_wrapper, friends = friends};
2862
2863    val notes =
2864      [(corecUU_transferN, [corecUU_transfer])] @
2865      (if Config.get lthy bnf_internals then
2866         [(algLamN, [algLam_thm]),
2867          (algLam_algLamN, [algLam_algLamL, algLam_algLamR]),
2868          (cong_alg_introsN, #cong_alg_intros dtor_coinduct_info),
2869          (cong_localeN, [#cong_locale dtor_coinduct_info]),
2870          (corecU_ctorN, [corecU_ctor]),
2871          (corecU_uniqueN, [corecU_unique]),
2872          (corecUUN, [corecUU_thm]),
2873          (corecUU_uniqueN, [corecUU_unique]),
2874          (dtor_algLamN, [dtor_algLam]),
2875          (dtor_coinductN, [#dtor_coinduct dtor_coinduct_info]),
2876          (eval_core_pointful_naturalN, [eval_core_pointful_natural]),
2877          (eval_core_transferN, [eval_core_transfer]),
2878          (embL_pointful_naturalN, [embLL_pointful_natural, embLR_pointful_natural]),
2879          (embL_transferN, [embLL_transfer, embLR_transfer]),
2880          (evalN, [eval_thm]),
2881          (eval_flatN, [eval_flat]),
2882          (eval_simpsN, eval_simps),
2883          (flat_pointful_naturalN, [flat_pointful_natural]),
2884          (flat_transferN, [flat_transfer]),
2885          (Lam_pointful_naturalN, [Lam_pointful_natural]),
2886          (Lam_transferN, [Lam_transfer]),
2887          (proto_sctr_pointful_naturalN, [proto_sctr_pointful_natural]),
2888          (proto_sctr_transferN, [proto_sctr_transfer]),
2889          (sctr_pointful_naturalN, [sctr_pointful_natural]),
2890          (sctr_transferN, [sctr_transfer]),
2891          (Sig_pointful_naturalN, [Sig_pointful_natural])]
2892       else
2893         [])
2894      |> map (fn (thmN, thms) =>
2895        ((mk_version_fp_binding true lthy version fp_b thmN, []), [(thms, [])]));
2896  in
2897    ({fp_b = fp_b, version = version, fpT = fpT, Y = Y, Z = Z, friend_names = friend_names,
2898      sig_fp_sugars = sig_fp_sugar :: old_fp_sugars, ssig_fp_sugar = ssig_fp_sugar, Lam = Lam,
2899      proto_sctr = proto_sctr, flat = flat, eval_core = eval_core, eval = eval, algLam = algLam,
2900      corecUU = corecUU, dtor_transfer = dtor_transfer, Lam_transfer = Lam_transfer,
2901      Lam_pointful_natural = Lam_pointful_natural, proto_sctr_transfer = proto_sctr_transfer,
2902      flat_simps = flat_simps, eval_core_simps = eval_core_simps, eval_thm = eval_thm,
2903      eval_simps = eval_simps, all_algLam_algs = all_algLam_algs, algLam_thm = algLam_thm,
2904      dtor_algLam = dtor_algLam, corecUU_thm = corecUU_thm, corecUU_unique = corecUU_unique,
2905      corecUU_transfer = corecUU_transfer, buffer = buffer, all_dead_k_bnfs = all_dead_k_bnfs,
2906      Retr = Retr, equivp_Retr = equivp_Retr, Retr_coinduct = Retr_coinduct,
2907      dtor_coinduct_info = dtor_coinduct_info}
2908     |> morph_corec_info (Local_Theory.target_morphism lthy),
2909     lthy |> Local_Theory.notes notes |> snd)
2910  end;
2911
2912fun set_corec_info_exprs fpT_name f =
2913  Local_Theory.declaration {syntax = false, pervasive = true} (fn phi =>
2914    let val exprs = f phi in
2915      Data.map (apsnd (fn [info_tab] => [Symtab.map_default (fpT_name, exprs) (K exprs) info_tab]))
2916    end);
2917
2918fun subsume_corec_info_ad ctxt {fpT = fpT1, friend_names = friend_names1}
2919    {fpT = fpT2, friend_names = friend_names2} =
2920  Sign.typ_instance (Proof_Context.theory_of ctxt) (fpT1, fpT2) andalso
2921  subset (op =) (friend_names1, friend_names2);
2922
2923fun subsume_corec_info_expr ctxt expr1 expr2 =
2924  subsume_corec_info_ad ctxt (corec_ad_of_expr expr1) (corec_ad_of_expr expr2);
2925
2926fun instantiate_corec_info thy res_T (info as {fpT, ...}) =
2927  let
2928    val As_rho = tvar_subst thy [fpT] [res_T];
2929    val substAT = Term.typ_subst_TVars As_rho;
2930    val substA = Term.subst_TVars As_rho;
2931    val phi = Morphism.typ_morphism "BNF" substAT $> Morphism.term_morphism "BNF" substA;
2932  in
2933    morph_corec_info phi info
2934  end;
2935
2936fun instantiate_corec_info_expr thy res_T (Ad ({friend_names, ...}, f)) =
2937    Ad ({fpT = res_T, friend_names = friend_names}, f #>> instantiate_corec_info thy res_T)
2938  | instantiate_corec_info_expr thy res_T (Info info) =
2939    Info (instantiate_corec_info thy res_T info);
2940
2941fun ensure_Info expr = corec_info_of_expr expr #>> Info
2942and ensure_Info_if_Info old_expr (expr, lthy) =
2943  if is_Info old_expr then ensure_Info expr lthy else (expr, lthy)
2944and merge_corec_info_exprs old_exprs expr1 expr2 lthy =
2945  if subsume_corec_info_expr lthy expr2 expr1 then
2946    if subsume_corec_info_expr lthy expr1 expr2 andalso is_Ad expr1 then
2947      (expr2, lthy)
2948    else
2949      ensure_Info_if_Info expr2 (expr1, lthy)
2950  else if subsume_corec_info_expr lthy expr1 expr2 then
2951    ensure_Info_if_Info expr1 (expr2, lthy)
2952  else
2953    let
2954      val thy = Proof_Context.theory_of lthy;
2955
2956      val {fpT = fpT1, friend_names = friend_names1} = corec_ad_of_expr expr1;
2957      val {fpT = fpT2, friend_names = friend_names2} = corec_ad_of_expr expr2;
2958      val fpT0 = typ_unify_disjointly thy (fpT1, fpT2);
2959
2960      val fpT = singleton (freeze_types lthy []) fpT0;
2961      val friend_names = merge_lists (op =) friend_names1 friend_names2;
2962
2963      val expr =
2964        Ad ({fpT = fpT, friend_names = friend_names},
2965          corec_info_of_expr expr1
2966          ##>> corec_info_of_expr expr2
2967          #-> uncurry (derive_corecUU_merge fpT));
2968
2969      val old_same_type_exprs =
2970        if old_exprs then
2971          []
2972          |> Sign.typ_instance thy (fpT1, fpT0) ? cons expr1
2973          |> Sign.typ_instance thy (fpT2, fpT0) ? cons expr2
2974        else
2975          [];
2976    in
2977      (expr, lthy) |> fold ensure_Info_if_Info old_same_type_exprs
2978    end
2979and insert_corec_info_expr expr exprs lthy =
2980  let
2981    val thy = Proof_Context.theory_of lthy;
2982
2983    val {fpT = new_fpT, ...} = corec_ad_of_expr expr;
2984
2985    val is_Tinst = curry (Sign.typ_instance thy);
2986    fun is_Tequiv T U = is_Tinst T U andalso is_Tinst U T;
2987
2988    val (((equiv_exprs, sub_exprs), sup_exprs), incomp_exprs) = exprs
2989      |> List.partition ((fn {fpT, ...} => is_Tequiv fpT new_fpT) o corec_ad_of_expr)
2990      ||>> List.partition ((fn {fpT, ...} => is_Tinst fpT new_fpT) o corec_ad_of_expr)
2991      ||>> List.partition ((fn {fpT, ...} => is_Tinst new_fpT fpT) o corec_ad_of_expr);
2992
2993    fun add_instantiated_incomp_expr expr exprs =
2994      let val {fpT, ...} = corec_ad_of_expr expr in
2995        (case try (typ_unify_disjointly thy) (fpT, new_fpT) of
2996          SOME new_T =>
2997          let val subsumes = (fn {fpT, ...} => is_Tinst new_T fpT) o corec_ad_of_expr in
2998            if exists (exists subsumes) [exprs, sub_exprs] then exprs
2999            else instantiate_corec_info_expr thy new_T expr :: exprs
3000          end
3001        | NONE => exprs)
3002      end;
3003
3004    val unincomp_exprs = fold add_instantiated_incomp_expr incomp_exprs [];
3005    val ((merged_sub_exprs, merged_unincomp_exprs), lthy) = lthy
3006      |> fold_map (merge_corec_info_exprs true expr) sub_exprs
3007      ||>> fold_map (merge_corec_info_exprs false expr) unincomp_exprs;
3008    val (merged_equiv_expr, lthy) = (expr, lthy)
3009      |> fold (uncurry o merge_corec_info_exprs true) equiv_exprs;
3010  in
3011    (merged_unincomp_exprs @ merged_sub_exprs @ merged_equiv_expr :: sup_exprs @ incomp_exprs
3012     |> sort (rev_order o int_ord o apply2 (length o #friend_names o corec_ad_of_expr)),
3013     lthy)
3014  end
3015and register_corec_info (info as {fpT = Type (fpT_name, _), ...}) lthy =
3016  let
3017    val (exprs, lthy) = insert_corec_info_expr (Info info) (corec_info_exprs_of lthy fpT_name) lthy;
3018  in
3019    lthy |> set_corec_info_exprs fpT_name (fn phi => map (morph_corec_info_expr phi) exprs)
3020  end
3021and corec_info_of_expr (Ad (_, f)) lthy = f lthy
3022  | corec_info_of_expr (Info info) lthy = (info, lthy);
3023
3024fun nonempty_corec_info_exprs_of fpT_name lthy =
3025  (case corec_info_exprs_of lthy fpT_name of
3026    [] =>
3027    derive_corecUU_base fpT_name lthy
3028    |> (fn (info, lthy) =>
3029      ([Info info], lthy
3030         |> set_corec_info_exprs fpT_name (fn phi => [Info (morph_corec_info phi info)])))
3031  | exprs => (exprs, lthy));
3032
3033fun corec_info_of res_T lthy =
3034  (case res_T of
3035    Type (fpT_name, _) =>
3036    let
3037      val (exprs, lthy) = nonempty_corec_info_exprs_of fpT_name lthy;
3038      val thy = Proof_Context.theory_of lthy;
3039      val expr =
3040        (case find_first ((fn {fpT, ...} => Sign.typ_instance thy (res_T, fpT)) o corec_ad_of_expr)
3041            exprs of
3042          SOME expr => expr
3043        | NONE => error ("Invalid type: " ^ Syntax.string_of_typ lthy res_T));
3044      val (info, lthy) = corec_info_of_expr expr lthy;
3045    in
3046      (instantiate_corec_info thy res_T info, lthy |> is_Ad expr ? register_corec_info info)
3047    end
3048  | _ => not_codatatype lthy res_T);
3049
3050fun maybe_corec_info_of ctxt res_T =
3051  (case res_T of
3052    Type (fpT_name, _) =>
3053    let
3054      val thy = Proof_Context.theory_of ctxt;
3055      val infos = corec_infos_of ctxt fpT_name;
3056    in
3057      find_first (fn {fpT, ...} => Sign.typ_instance thy (res_T, fpT)) infos
3058      |> Option.map (instantiate_corec_info thy res_T)
3059    end
3060  | _ => not_codatatype ctxt res_T);
3061
3062fun prepare_friend_corec friend_name friend_T lthy =
3063  let
3064    val (arg_Ts, res_T) = strip_type friend_T;
3065    val Type (fpT_name, res_Ds) =
3066      (case res_T of
3067        T as Type _ => T
3068      | T => error (not_codatatype lthy T));
3069
3070    val _ = not (null arg_Ts) orelse
3071      error "Function with no argument cannot be registered as friend";
3072
3073    val {T = Type (fpT_name, fpT_args0), pre_bnf, fp_bnf = live_fp_bnf, fp_res, ...} =
3074      checked_fp_sugar_of lthy fpT_name;
3075    val num_fp_tyargs = length fpT_args0;
3076    val fpT_Ss = map Type.sort_of_atyp fpT_args0;
3077    val live_fp_alives = liveness_of_fp_bnf num_fp_tyargs live_fp_bnf;
3078
3079    val (old_info as {friend_names = old_friend_names, sig_fp_sugars = old_sig_fp_sugar :: _,
3080           buffer = old_buffer, ...}, lthy) =
3081      corec_info_of res_T lthy;
3082    val old_sig_T_name = fst (dest_Type (#T old_sig_fp_sugar));
3083    val old_sig_alives = liveness_of_fp_bnf (num_fp_tyargs + 1) (#fp_bnf old_sig_fp_sugar);
3084
3085    (* FIXME: later *)
3086    val fp_alives = fst (split_last old_sig_alives);
3087    val fp_alives = map (K false) live_fp_alives;
3088
3089    val _ = not (member (op =) old_friend_names friend_name) orelse
3090      error ("Function " ^ quote (Syntax.string_of_term lthy (Const (friend_name, friend_T))) ^
3091        " already registered as friend");
3092
3093    val lthy = lthy |> Variable.declare_typ friend_T;
3094    val ((Ds, [Y, Z]), _) = lthy
3095      |> mk_TFrees' fpT_Ss
3096      ||>> mk_TFrees 2;
3097
3098    (* FIXME *)
3099    val dead_Ds = Ds;
3100    val live_As = [Y];
3101
3102    val ctor = mk_ctor res_Ds (the_single (#ctors fp_res));
3103
3104    val fpT0 = Type (fpT_name, Ds);
3105    val k_Ts0 = map (typ_subst_nonatomic (res_Ds ~~ Ds) o typ_subst_nonatomic [(res_T, Y)]) arg_Ts;
3106    val k_T0 = mk_tupleT_balanced k_Ts0;
3107
3108    val As = Ds @ [Y];
3109    val res_As = res_Ds @ [Y];
3110
3111    val k_As = fold Term.add_tfreesT k_Ts0 [];
3112    val _ = (case filter_out (member (op =) As o TFree) k_As of [] => ()
3113      | k_A :: _ => error ("Cannot have type variable " ^
3114          quote (Syntax.string_of_typ lthy (TFree k_A)) ^
3115          " in the argument types when it does not occur as an immediate argument of the result \
3116          \type constructor"));
3117
3118    val substDT = Term.typ_subst_atomic (Ds ~~ res_Ds);
3119
3120    val old_sig_T0 = Type (old_sig_T_name, As);
3121
3122    val ((fp_b, version), lthy) = lthy |> get_name_next_version_of fpT_name;
3123
3124    val (((dead_k_bnf, sig_fp_sugar), ssig_fp_sugar), lthy) = lthy
3125      |> bnf_with_deads_and_lives dead_Ds live_As Y fpT0 k_T0
3126      ||>> define_sig_type fp_b version fp_alives Ds Y (mk_sumT (old_sig_T0, k_T0))
3127      ||>> define_ssig_type fp_b version fp_alives Ds Y fpT0;
3128
3129    val _ = live_of_bnf dead_k_bnf = 1 orelse
3130      error "Impossible type for friend (the result codatatype must occur live in the arguments)";
3131
3132    val (dead_pre_bnf, lthy) = lthy
3133      |> bnf_kill_all_but 1 pre_bnf;
3134
3135    val sig_fp_ctr_sugar = #fp_ctr_sugar sig_fp_sugar;
3136    val ssig_fp_ctr_sugar = #fp_ctr_sugar ssig_fp_sugar;
3137
3138    val sig_ctr_sugar = #ctr_sugar sig_fp_ctr_sugar;
3139    val ssig_ctr_sugar = #ctr_sugar ssig_fp_ctr_sugar;
3140
3141    val ssig_T_name = fst (dest_Type (#T ssig_fp_sugar));
3142
3143    val preT = pre_type_of_ctor Y ctor;
3144    val old_sig_T = substDT old_sig_T0;
3145    val k_T = substDT k_T0;
3146    val ssig_T = Type (ssig_T_name, res_As);
3147
3148    val Sig = mk_ctr res_As (the_single (#ctrs sig_ctr_sugar));
3149
3150    val [Oper, VLeaf, CLeaf] = map (mk_ctr res_As) (#ctrs ssig_ctr_sugar);
3151    val (ctr_wrapper, friends) =
3152      mk_ctr_wrapper_friends lthy friend_name friend_T old_sig_T k_T Sig old_buffer;
3153
3154    val buffer =
3155      {Oper = Oper, VLeaf = VLeaf, CLeaf = CLeaf, ctr_wrapper = ctr_wrapper, friends = friends};
3156  in
3157    ((old_info, fp_b, version, Y, Z, preT, k_T, ssig_T, dead_pre_bnf, dead_k_bnf, sig_fp_sugar,
3158      ssig_fp_sugar, buffer), lthy)
3159  end;
3160
3161fun register_friend_corec key fp_b version Y Z k_T dead_k_bnf sig_fp_sugar ssig_fp_sugar
3162    friend_const rho rho_transfer old_info lthy =
3163  let
3164    val friend_T = fastype_of friend_const;
3165    val res_T = body_type friend_T;
3166  in
3167    derive_corecUU_step res_T old_info key friend_T fp_b version Y Z k_T dead_k_bnf sig_fp_sugar
3168      ssig_fp_sugar rho rho_transfer lthy
3169    |> (fn ((info, friend_info), lthy) => (friend_info, register_corec_info info lthy))
3170  end;
3171
3172fun merge_corec_info_exprss exprs1 exprs2 lthy =
3173  let
3174    fun all_friend_names_of exprs =
3175      fold (union (op =)) (map (#friend_names o corec_ad_of_expr) exprs) [];
3176
3177    val friend_names1 = all_friend_names_of exprs1;
3178    val friend_names2 = all_friend_names_of exprs2;
3179  in
3180    if subset (op =) (friend_names2, friend_names1) then
3181      if subset (op =) (friend_names1, friend_names2) andalso
3182         length (filter is_Info exprs2) > length (filter is_Info exprs1) then
3183        (exprs2, lthy)
3184      else
3185        (exprs1, lthy)
3186    else if subset (op =) (friend_names1, friend_names2) then
3187      (exprs2, lthy)
3188    else
3189      fold_rev (uncurry o insert_corec_info_expr) exprs2 (exprs1, lthy)
3190  end;
3191
3192fun merge_corec_info_tabs info_tab1 info_tab2 lthy =
3193  let
3194    val fpT_names = union (op =) (Symtab.keys info_tab1) (Symtab.keys info_tab2);
3195
3196    fun add_infos_of fpT_name (info_tab, lthy) =
3197      (case Symtab.lookup info_tab1 fpT_name of
3198        NONE =>
3199        (Symtab.update_new (fpT_name, the (Symtab.lookup info_tab2 fpT_name)) info_tab, lthy)
3200      | SOME exprs1 =>
3201        (case Symtab.lookup info_tab2 fpT_name of
3202          NONE => (Symtab.update_new (fpT_name, exprs1) info_tab, lthy)
3203        | SOME exprs2 =>
3204          let val (exprs, lthy) = merge_corec_info_exprss exprs1 exprs2 lthy in
3205            (Symtab.update_new (fpT_name, exprs) info_tab, lthy)
3206          end));
3207  in
3208    fold add_infos_of fpT_names (Symtab.empty, lthy)
3209  end;
3210
3211fun consolidate lthy =
3212  (case snd (Data.get (Context.Proof lthy)) of
3213    [_] => raise Same.SAME
3214  | info_tab :: info_tabs =>
3215    let
3216      val (info_tab', lthy) = fold_rev (uncurry o merge_corec_info_tabs) info_tabs (info_tab, lthy);
3217    in
3218      Local_Theory.declaration {syntax = false, pervasive = true} (fn phi =>
3219          Data.map (apsnd (fn _ => [Symtab.map (K (map (morph_corec_info_expr phi))) info_tab'])))
3220        lthy
3221    end);
3222
3223fun consolidate_global thy =
3224  SOME (Named_Target.theory_map consolidate thy)
3225  handle Same.SAME => NONE;
3226
3227val _ = Theory.setup (Theory.at_begin consolidate_global);
3228
3229end;
3230