src/HOL/Tools/BNF/bnf_lfp_size.ML
author blanchet
Wed, 23 Apr 2014 10:23:27 +0200
changeset 56647 ce8297d5017a
parent 56645 a16d294f7e3f
child 56650 1f9ab71d43a5
permissions -rw-r--r--
pick up all 'nesting' theorems
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
56638
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
     1
(*  Title:      HOL/Tools/BNF/bnf_lfp_size.ML
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
     2
    Author:     Jasmin Blanchette, TU Muenchen
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
     3
    Copyright   2014
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
     4
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
     5
Generation of size functions for new-style datatypes.
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
     6
*)
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
     7
56642
15cd15f9b40c allow registration of custom size functions for BNF-based datatypes
blanchet
parents: 56640
diff changeset
     8
signature BNF_LFP_SIZE =
15cd15f9b40c allow registration of custom size functions for BNF-based datatypes
blanchet
parents: 56640
diff changeset
     9
sig
15cd15f9b40c allow registration of custom size functions for BNF-based datatypes
blanchet
parents: 56640
diff changeset
    10
  val register_size: string -> string -> thm list -> thm list -> theory -> theory
56643
41d3596d8a64 move size hooks together, with new one preceding old one and sharing same theory data
blanchet
parents: 56642
diff changeset
    11
  val lookup_size: theory -> string -> (string * (thm list * thm list)) option
56642
15cd15f9b40c allow registration of custom size functions for BNF-based datatypes
blanchet
parents: 56640
diff changeset
    12
end;
15cd15f9b40c allow registration of custom size functions for BNF-based datatypes
blanchet
parents: 56640
diff changeset
    13
15cd15f9b40c allow registration of custom size functions for BNF-based datatypes
blanchet
parents: 56640
diff changeset
    14
structure BNF_LFP_Size : BNF_LFP_SIZE =
56638
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    15
struct
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    16
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    17
open BNF_Util
56640
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
    18
open BNF_Tactics
56638
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    19
open BNF_Def
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    20
open BNF_FP_Def_Sugar
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    21
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    22
val size_N = "size_"
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    23
56640
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
    24
val rec_o_mapN = "rec_o_map"
56638
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    25
val sizeN = "size"
56640
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
    26
val size_o_mapN = "size_o_map"
56638
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    27
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    28
structure Data = Theory_Data
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    29
(
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    30
  type T = (string * (thm list * thm list)) Symtab.table;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    31
  val empty = Symtab.empty;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    32
  val extend = I
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    33
  fun merge data = Symtab.merge (K true) data;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    34
);
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    35
56642
15cd15f9b40c allow registration of custom size functions for BNF-based datatypes
blanchet
parents: 56640
diff changeset
    36
fun register_size T_name size_name size_simps size_o_maps =
56643
41d3596d8a64 move size hooks together, with new one preceding old one and sharing same theory data
blanchet
parents: 56642
diff changeset
    37
  Data.map (Symtab.update (T_name, (size_name, (size_simps, size_o_maps))));
41d3596d8a64 move size hooks together, with new one preceding old one and sharing same theory data
blanchet
parents: 56642
diff changeset
    38
41d3596d8a64 move size hooks together, with new one preceding old one and sharing same theory data
blanchet
parents: 56642
diff changeset
    39
val lookup_size = Symtab.lookup o Data.get;
56642
15cd15f9b40c allow registration of custom size functions for BNF-based datatypes
blanchet
parents: 56640
diff changeset
    40
56638
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    41
val zero_nat = @{const zero_class.zero (nat)};
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    42
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    43
fun mk_plus_nat (t1, t2) = Const (@{const_name Groups.plus},
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    44
  HOLogic.natT --> HOLogic.natT --> HOLogic.natT) $ t1 $ t2;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    45
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    46
fun mk_to_natT T = T --> HOLogic.natT;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    47
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    48
fun mk_abs_zero_nat T = Term.absdummy T zero_nat;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    49
56640
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
    50
fun pointfill ctxt th = unfold_thms ctxt [o_apply] (th RS fun_cong);
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
    51
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
    52
fun mk_unabs_def_unused_0 n =
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
    53
  funpow n (fn thm => thm RS @{thm fun_cong_unused_0} handle THM _ => thm RS fun_cong);
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
    54
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
    55
val rec_o_map_simp_thms =
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
    56
  @{thms o_def id_apply case_prod_app case_sum_o_map_sum case_prod_o_map_prod
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
    57
      BNF_Comp.id_bnf_comp_def};
56638
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    58
56640
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
    59
fun mk_rec_o_map_tac ctxt rec_def pre_map_defs abs_inverses ctor_rec_o_map =
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
    60
  unfold_thms_tac ctxt [rec_def] THEN
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
    61
  HEADGOAL (rtac (ctor_rec_o_map RS trans) THEN'
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
    62
    K (PRIMITIVE (Conv.fconv_rule Thm.eta_long_conversion)) THEN' asm_simp_tac
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
    63
      (ss_only (pre_map_defs @ distinct Thm.eq_thm_prop abs_inverses @ rec_o_map_simp_thms) ctxt));
56638
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    64
56640
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
    65
val size_o_map_simp_thms =
56642
15cd15f9b40c allow registration of custom size functions for BNF-based datatypes
blanchet
parents: 56640
diff changeset
    66
  @{thms prod_inj_map inj_on_id snd_comp_apfst[unfolded apfst_def]};
56640
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
    67
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
    68
fun mk_size_o_map_tac ctxt size_def rec_o_map inj_maps size_maps =
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
    69
  unfold_thms_tac ctxt [size_def] THEN
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
    70
  HEADGOAL (rtac (rec_o_map RS trans) THEN'
56642
15cd15f9b40c allow registration of custom size functions for BNF-based datatypes
blanchet
parents: 56640
diff changeset
    71
    asm_simp_tac (ss_only (inj_maps @ size_maps @ size_o_map_simp_thms) ctxt)) THEN
56645
a16d294f7e3f prevent tactic failures by detecting and ignoring BNFs with no 'size' functions early
blanchet
parents: 56643
diff changeset
    72
  IF_UNSOLVED (unfold_thms_tac ctxt @{thms o_def} THEN HEADGOAL (rtac refl));
56638
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    73
56640
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
    74
fun generate_size (fp_sugars as ({T = Type (_, As), BT = Type (_, Bs), fp = Least_FP,
56647
ce8297d5017a pick up all 'nesting' theorems
blanchet
parents: 56645
diff changeset
    75
      fp_res = {bnfs = fp_bnfs, xtor_co_rec_o_map_thms = ctor_rec_o_maps, ...}, nested_bnfs,
ce8297d5017a pick up all 'nesting' theorems
blanchet
parents: 56645
diff changeset
    76
      nesting_bnfs, ...} : fp_sugar) :: _) thy =
56640
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
    77
    let
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
    78
      val data = Data.get thy;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
    79
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
    80
      val Ts = map #T fp_sugars
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
    81
      val T_names = map (fst o dest_Type) Ts;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
    82
      val nn = length Ts;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
    83
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
    84
      val B_ify = Term.typ_subst_atomic (As ~~ Bs);
56638
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    85
56640
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
    86
      val recs = map #co_rec fp_sugars;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
    87
      val rec_thmss = map #co_rec_thms fp_sugars;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
    88
      val rec_Ts as rec_T1 :: _ = map fastype_of recs;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
    89
      val rec_arg_Ts = binder_fun_types rec_T1;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
    90
      val Cs = map body_type rec_Ts;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
    91
      val Cs_rho = map (rpair HOLogic.natT) Cs;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
    92
      val substCnatT = Term.subst_atomic_types Cs_rho;
56638
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    93
56640
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
    94
      val f_Ts = map mk_to_natT As;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
    95
      val f_TsB = map mk_to_natT Bs;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
    96
      val num_As = length As;
56638
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    97
56640
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
    98
      val f_names = map (prefix "f" o string_of_int) (1 upto num_As);
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
    99
      val fs = map2 (curry Free) f_names f_Ts;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   100
      val fsB = map2 (curry Free) f_names f_TsB;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   101
      val As_fs = As ~~ fs;
56638
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   102
56640
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   103
      val size_names = map (Long_Name.map_base_name (prefix size_N)) T_names;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   104
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   105
      fun is_pair_C @{type_name prod} [_, T'] = member (op =) Cs T'
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   106
        | is_pair_C _ _ = false;
56638
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   107
56640
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   108
      fun mk_size_of_typ (T as TFree _) =
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   109
          pair (case AList.lookup (op =) As_fs T of
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   110
              SOME f => f
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   111
            | NONE => if member (op =) Cs T then Term.absdummy T (Bound 0) else mk_abs_zero_nat T)
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   112
        | mk_size_of_typ (T as Type (s, Ts)) =
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   113
          if is_pair_C s Ts then
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   114
            pair (snd_const T)
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   115
          else if exists (exists_subtype_in As) Ts then
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   116
            (case Symtab.lookup data s of
56645
a16d294f7e3f prevent tactic failures by detecting and ignoring BNFs with no 'size' functions early
blanchet
parents: 56643
diff changeset
   117
              SOME (size_name, (_, size_o_maps as _ :: _)) =>
56640
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   118
              let
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   119
                val (args, size_o_mapss') = split_list (map (fn T => mk_size_of_typ T []) Ts);
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   120
                val size_const = Const (size_name, map fastype_of args ---> mk_to_natT T);
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   121
              in
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   122
                fold (union Thm.eq_thm) (size_o_maps :: size_o_mapss')
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   123
                #> pair (Term.list_comb (size_const, args))
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   124
              end
56645
a16d294f7e3f prevent tactic failures by detecting and ignoring BNFs with no 'size' functions early
blanchet
parents: 56643
diff changeset
   125
            | _ => pair (mk_abs_zero_nat T))
56640
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   126
          else
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   127
            pair (mk_abs_zero_nat T);
56638
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   128
56640
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   129
      fun mk_size_of_arg t =
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   130
        mk_size_of_typ (fastype_of t) #>> (fn s => substCnatT (betapply (s, t)));
56638
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   131
56640
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   132
      fun mk_size_arg rec_arg_T size_o_maps =
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   133
        let
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   134
          val x_Ts = binder_types rec_arg_T;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   135
          val m = length x_Ts;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   136
          val x_names = map (prefix "x" o string_of_int) (1 upto m);
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   137
          val xs = map2 (curry Free) x_names x_Ts;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   138
          val (summands, size_o_maps') =
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   139
            fold_map mk_size_of_arg xs size_o_maps
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   140
            |>> remove (op =) zero_nat;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   141
          val sum =
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   142
            if null summands then HOLogic.zero
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   143
            else foldl1 mk_plus_nat (summands @ [HOLogic.Suc_zero]);
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   144
        in
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   145
          (fold_rev Term.lambda (map substCnatT xs) sum, size_o_maps')
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   146
        end;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   147
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   148
      fun mk_size_rhs recx size_o_maps =
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   149
        let val (args, size_o_maps') = fold_map mk_size_arg rec_arg_Ts size_o_maps in
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   150
          (fold_rev Term.lambda fs (Term.list_comb (substCnatT recx, args)), size_o_maps')
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   151
        end;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   152
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   153
      fun mk_def_binding f =
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   154
        Binding.conceal o Binding.name o Thm.def_name o f o Long_Name.base_name;
56638
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   155
56640
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   156
      val (size_rhss, nested_size_o_maps) = fold_map mk_size_rhs recs [];
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   157
      val size_Ts = map fastype_of size_rhss;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   158
      val size_consts = map2 (curry Const) size_names size_Ts;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   159
      val size_constsB = map (Term.map_types B_ify) size_consts;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   160
      val size_def_bs = map (mk_def_binding I) size_names;
56638
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   161
56640
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   162
      val (size_defs, thy2) =
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   163
        thy
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   164
        |> Sign.add_consts (map (fn (s, T) => (Binding.name (Long_Name.base_name s), T, NoSyn))
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   165
          (size_names ~~ size_Ts))
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   166
        |> Global_Theory.add_defs false (map Thm.no_attributes (size_def_bs ~~
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   167
          map Logic.mk_equals (size_consts ~~ size_rhss)));
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   168
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   169
      val zeros = map mk_abs_zero_nat As;
56638
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   170
56640
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   171
      val overloaded_size_rhss = map (fn c => Term.list_comb (c, zeros)) size_consts;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   172
      val overloaded_size_Ts = map fastype_of overloaded_size_rhss;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   173
      val overloaded_size_consts = map (curry Const @{const_name size}) overloaded_size_Ts;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   174
      val overloaded_size_def_bs = map (mk_def_binding (suffix "_overloaded")) size_names;
56638
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   175
56640
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   176
      fun define_overloaded_size def_b lhs0 rhs lthy =
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   177
        let
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   178
          val Free (c, _) = Syntax.check_term lthy lhs0;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   179
          val (thm, lthy') = lthy
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   180
            |> Local_Theory.define ((Binding.name c, NoSyn), ((def_b, []), rhs))
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   181
            |-> (fn (t, (_, thm)) => Spec_Rules.add Spec_Rules.Equational ([t], [thm]) #> pair thm);
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   182
          val ctxt_thy = Proof_Context.init_global (Proof_Context.theory_of lthy');
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   183
          val thm' = singleton (Proof_Context.export lthy' ctxt_thy) thm;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   184
        in (thm', lthy') end;
56638
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   185
56640
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   186
      val (overloaded_size_defs, thy3) = thy2
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   187
        |> Class.instantiation (T_names, map dest_TFree As, [HOLogic.class_size])
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   188
        |> fold_map3 define_overloaded_size overloaded_size_def_bs overloaded_size_consts
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   189
          overloaded_size_rhss
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   190
        ||> Class.prove_instantiation_instance (K (Class.intro_classes_tac []))
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   191
        ||> Local_Theory.exit_global;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   192
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   193
      val thy3_ctxt = Proof_Context.init_global thy3;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   194
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   195
      val size_defs' =
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   196
        map (mk_unabs_def (num_As + 1) o (fn thm => thm RS meta_eq_to_obj_eq)) size_defs;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   197
      val size_defs_unused_0 =
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   198
        map (mk_unabs_def_unused_0 (num_As + 1) o (fn thm => thm RS meta_eq_to_obj_eq)) size_defs;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   199
      val overloaded_size_defs' =
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   200
        map (mk_unabs_def 1 o (fn thm => thm RS meta_eq_to_obj_eq)) overloaded_size_defs;
56638
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   201
56640
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   202
      val nested_size_maps = map (pointfill thy3_ctxt) nested_size_o_maps @ nested_size_o_maps;
56647
ce8297d5017a pick up all 'nesting' theorems
blanchet
parents: 56645
diff changeset
   203
      val all_inj_maps = map inj_map_of_bnf (fp_bnfs @ nested_bnfs @ nesting_bnfs);
56638
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   204
56640
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   205
      fun derive_size_simp size_def' simp0 =
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   206
        (trans OF [size_def', simp0])
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   207
        |> Simplifier.asm_full_simplify (ss_only (@{thms inj_on_convol_id snd_o_convol} @
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   208
          all_inj_maps @ nested_size_maps) thy3_ctxt)
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   209
        |> fold_thms thy3_ctxt size_defs_unused_0;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   210
      fun derive_overloaded_size_simp size_def' simp0 =
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   211
        (trans OF [size_def', simp0])
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   212
        |> unfold_thms thy3_ctxt @{thms add_0_left add_0_right}
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   213
        |> fold_thms thy3_ctxt overloaded_size_defs';
56638
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   214
56640
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   215
      val size_simpss = map2 (map o derive_size_simp) size_defs' rec_thmss;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   216
      val size_simps = flat size_simpss;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   217
      val overloaded_size_simpss =
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   218
        map2 (map o derive_overloaded_size_simp) overloaded_size_defs' size_simpss;
56638
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   219
56640
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   220
      val ABs = As ~~ Bs;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   221
      val g_names = map (prefix "g" o string_of_int) (1 upto num_As);
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   222
      val gs = map2 (curry Free) g_names (map (op -->) ABs);
56638
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   223
56640
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   224
      val liveness = map (op <>) ABs;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   225
      val live_gs = AList.find (op =) (gs ~~ liveness) true;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   226
      val live = length live_gs;
56638
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   227
56640
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   228
      val maps0 = map map_of_bnf fp_bnfs;
56638
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   229
56643
41d3596d8a64 move size hooks together, with new one preceding old one and sharing same theory data
blanchet
parents: 56642
diff changeset
   230
      (* This disables much of the functionality of the size extension within a locale. It is not
41d3596d8a64 move size hooks together, with new one preceding old one and sharing same theory data
blanchet
parents: 56642
diff changeset
   231
         clear how to make the code below work with locales, given that interpretations are based on
41d3596d8a64 move size hooks together, with new one preceding old one and sharing same theory data
blanchet
parents: 56642
diff changeset
   232
         theories. *)
41d3596d8a64 move size hooks together, with new one preceding old one and sharing same theory data
blanchet
parents: 56642
diff changeset
   233
      val has_hyps = not (null (Thm.hyps_of (hd (hd rec_thmss))));
41d3596d8a64 move size hooks together, with new one preceding old one and sharing same theory data
blanchet
parents: 56642
diff changeset
   234
56640
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   235
      val (rec_o_map_thmss, size_o_map_thmss) =
56643
41d3596d8a64 move size hooks together, with new one preceding old one and sharing same theory data
blanchet
parents: 56642
diff changeset
   236
        if has_hyps orelse live = 0 then
56640
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   237
          `I (replicate nn [])
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   238
        else
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   239
          let
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   240
            val pre_bnfs = map #pre_bnf fp_sugars;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   241
            val pre_map_defs = map map_def_of_bnf pre_bnfs;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   242
            val abs_inverses = map (#abs_inverse o #absT_info) fp_sugars;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   243
            val rec_defs = map #co_rec_def fp_sugars;
56638
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   244
56640
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   245
            val gmaps = map (fn map0 => Term.list_comb (mk_map live As Bs map0, live_gs)) maps0;
56638
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   246
56640
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   247
            val num_rec_args = length rec_arg_Ts;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   248
            val h_Ts = map B_ify rec_arg_Ts;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   249
            val h_names = map (prefix "h" o string_of_int) (1 upto num_rec_args);
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   250
            val hs = map2 (curry Free) h_names h_Ts;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   251
            val hrecs = map (fn recx => Term.list_comb (Term.map_types B_ify recx, hs)) recs;
56638
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   252
56640
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   253
            val rec_o_map_lhss = map2 (curry HOLogic.mk_comp) hrecs gmaps;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   254
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   255
            val ABgs = ABs ~~ gs;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   256
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   257
            fun mk_rec_arg_arg (x as Free (_, T)) =
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   258
              let val U = B_ify T in
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   259
                if T = U then x else build_map thy3_ctxt (the o AList.lookup (op =) ABgs) (T, U) $ x
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   260
              end;
56638
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   261
56640
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   262
            fun mk_rec_o_map_arg rec_arg_T h =
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   263
              let
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   264
                val x_Ts = binder_types rec_arg_T;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   265
                val m = length x_Ts;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   266
                val x_names = map (prefix "x" o string_of_int) (1 upto m);
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   267
                val xs = map2 (curry Free) x_names x_Ts;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   268
                val xs' = map mk_rec_arg_arg xs;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   269
              in
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   270
                fold_rev Term.lambda xs (Term.list_comb (h, xs'))
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   271
              end;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   272
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   273
            fun mk_rec_o_map_rhs recx =
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   274
              let val args = map2 mk_rec_o_map_arg rec_arg_Ts hs in
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   275
                Term.list_comb (recx, args)
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   276
              end;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   277
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   278
            val rec_o_map_rhss = map mk_rec_o_map_rhs recs;
56638
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   279
56640
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   280
            val rec_o_map_goals =
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   281
              map2 (HOLogic.mk_Trueprop oo curry HOLogic.mk_eq) rec_o_map_lhss rec_o_map_rhss;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   282
            val rec_o_map_thms =
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   283
              map3 (fn goal => fn rec_def => fn ctor_rec_o_map =>
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   284
                  Goal.prove_global thy3 [] [] goal (fn {context = ctxt, ...} =>
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   285
                    mk_rec_o_map_tac ctxt rec_def pre_map_defs abs_inverses ctor_rec_o_map)
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   286
                  |> Thm.close_derivation)
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   287
                rec_o_map_goals rec_defs ctor_rec_o_maps;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   288
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   289
            val size_o_map_conds =
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   290
              if exists (can Logic.dest_implies o Thm.prop_of) nested_size_o_maps then
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   291
                map (HOLogic.mk_Trueprop o mk_inj) live_gs
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   292
              else
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   293
                [];
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   294
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   295
            val fsizes = map (fn size_constB => Term.list_comb (size_constB, fsB)) size_constsB;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   296
            val size_o_map_lhss = map2 (curry HOLogic.mk_comp) fsizes gmaps;
56638
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   297
56640
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   298
            val fgs = map2 (fn fB => fn g as Free (_, Type (_, [A, B])) =>
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   299
              if A = B then fB else HOLogic.mk_comp (fB, g)) fsB gs;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   300
            val size_o_map_rhss = map (fn c => Term.list_comb (c, fgs)) size_consts;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   301
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   302
            val size_o_map_goals =
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   303
              map2 (curry Logic.list_implies size_o_map_conds o HOLogic.mk_Trueprop oo
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   304
                curry HOLogic.mk_eq) size_o_map_lhss size_o_map_rhss;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   305
            val size_o_map_thms =
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   306
              map3 (fn goal => fn size_def => fn rec_o_map =>
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   307
                  Goal.prove_global thy3 [] [] goal (fn {context = ctxt, ...} =>
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   308
                    mk_size_o_map_tac ctxt size_def rec_o_map all_inj_maps nested_size_maps)
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   309
                  |> Thm.close_derivation)
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   310
                size_o_map_goals size_defs rec_o_map_thms;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   311
          in
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   312
            pairself (map single) (rec_o_map_thms, size_o_map_thms)
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   313
          end;
56638
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   314
56640
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   315
      val (_, thy4) = thy3
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   316
        |> fold_map4 (fn T_name => fn size_simps => fn rec_o_map_thms => fn size_o_map_thms =>
56643
41d3596d8a64 move size hooks together, with new one preceding old one and sharing same theory data
blanchet
parents: 56642
diff changeset
   317
            if has_hyps then
41d3596d8a64 move size hooks together, with new one preceding old one and sharing same theory data
blanchet
parents: 56642
diff changeset
   318
              pair []
41d3596d8a64 move size hooks together, with new one preceding old one and sharing same theory data
blanchet
parents: 56642
diff changeset
   319
            else
41d3596d8a64 move size hooks together, with new one preceding old one and sharing same theory data
blanchet
parents: 56642
diff changeset
   320
              let val qualify = Binding.qualify true (Long_Name.base_name T_name) in
41d3596d8a64 move size hooks together, with new one preceding old one and sharing same theory data
blanchet
parents: 56642
diff changeset
   321
                Global_Theory.note_thmss ""
41d3596d8a64 move size hooks together, with new one preceding old one and sharing same theory data
blanchet
parents: 56642
diff changeset
   322
                  ([((qualify (Binding.name rec_o_mapN), []), [(rec_o_map_thms, [])]),
41d3596d8a64 move size hooks together, with new one preceding old one and sharing same theory data
blanchet
parents: 56642
diff changeset
   323
                    ((qualify (Binding.name sizeN),
41d3596d8a64 move size hooks together, with new one preceding old one and sharing same theory data
blanchet
parents: 56642
diff changeset
   324
                       [Simplifier.simp_add, Nitpick_Simps.add, Thm.declaration_attribute
41d3596d8a64 move size hooks together, with new one preceding old one and sharing same theory data
blanchet
parents: 56642
diff changeset
   325
                          (fn thm => Context.mapping (Code.add_default_eqn thm) I)]),
41d3596d8a64 move size hooks together, with new one preceding old one and sharing same theory data
blanchet
parents: 56642
diff changeset
   326
                     [(size_simps, [])]),
41d3596d8a64 move size hooks together, with new one preceding old one and sharing same theory data
blanchet
parents: 56642
diff changeset
   327
                    ((qualify (Binding.name size_o_mapN), []), [(size_o_map_thms, [])])]
41d3596d8a64 move size hooks together, with new one preceding old one and sharing same theory data
blanchet
parents: 56642
diff changeset
   328
                   |> filter_out (forall (null o fst) o snd))
41d3596d8a64 move size hooks together, with new one preceding old one and sharing same theory data
blanchet
parents: 56642
diff changeset
   329
              end)
56640
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   330
          T_names (map2 append size_simpss overloaded_size_simpss) rec_o_map_thmss size_o_map_thmss
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   331
        ||> Spec_Rules.add_global Spec_Rules.Equational (size_consts, size_simps);
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   332
    in
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   333
      thy4
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   334
      |> Data.map (fold2 (fn T_name => fn size_name =>
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   335
          Symtab.update_new (T_name, (size_name, (size_simps, flat size_o_map_thmss))))
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   336
        T_names size_names)
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   337
    end
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   338
  | generate_size _ thy = thy;
56638
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   339
56640
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   340
val _ = Theory.setup (fp_sugar_interpretation generate_size);
56638
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   341
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   342
end;