src/HOL/Tools/BNF/bnf_lfp_size.ML
author blanchet
Wed, 23 Apr 2014 10:23:26 +0200
changeset 56639 c9d6b581bd3b
parent 56638 092a306bcc3d
child 56640 0a35354137a5
permissions -rw-r--r--
made old-style 'size' interpretation hook more robust in case 'size' is already specified (either by the user or by the new datatype package)
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
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
     8
structure BNF_LFP_Size : sig end =
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
     9
struct
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    10
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    11
open BNF_Util
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    12
open BNF_Def
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    13
open BNF_FP_Def_Sugar
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    14
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    15
val size_N = "size_"
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
val sizeN = "size"
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    18
val size_mapN = "size_map"
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    19
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    20
structure Data = Theory_Data
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
  type T = (string * (thm list * thm list)) Symtab.table;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    23
  val empty = Symtab.empty;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    24
  val extend = I
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    25
  fun merge data = Symtab.merge (K true) data;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    26
);
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
val zero_nat = @{const zero_class.zero (nat)};
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
fun mk_plus_nat (t1, t2) = Const (@{const_name Groups.plus},
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    31
  HOLogic.natT --> HOLogic.natT --> HOLogic.natT) $ t1 $ t2;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    32
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    33
fun mk_to_natT T = T --> HOLogic.natT;
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
fun mk_abs_zero_nat T = Term.absdummy T zero_nat;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    36
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    37
fun generate_size (fp_sugars as ({T = Type (_, As), BT = Type (_, Bs),
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    38
    fp_res = {bnfs = fp_bnfs, ...}, common_co_inducts = common_inducts, ...} : fp_sugar) :: _) thy =
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    39
  let
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    40
    val data = Data.get thy;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    41
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    42
    val Ts = map #T fp_sugars
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    43
    val T_names = map (fst o dest_Type) Ts;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    44
    val nn = length Ts;
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
    val B_ify = Term.typ_subst_atomic (As ~~ Bs);
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
    val recs = map #co_rec fp_sugars;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    49
    val rec_thmss = map #co_rec_thms fp_sugars;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    50
    val rec_Ts = map fastype_of recs;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    51
    val Cs = map body_type rec_Ts;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    52
    val Cs_rho = map (rpair HOLogic.natT) Cs;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    53
    val substCT = Term.subst_atomic_types Cs_rho;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    54
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    55
    val f_Ts = map mk_to_natT As;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    56
    val f_TsB = map mk_to_natT Bs;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    57
    val num_As = length As;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    58
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    59
    val f_names = map (prefix "f" o string_of_int) (1 upto num_As);
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    60
    val fs = map2 (curry Free) f_names f_Ts;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    61
    val fsB = map2 (curry Free) f_names f_TsB;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    62
    val As_fs = As ~~ fs;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    63
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    64
    val gen_size_names = map (Long_Name.map_base_name (prefix size_N)) T_names;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    65
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    66
    fun is_pair_C @{type_name prod} [_, T'] = member (op =) Cs T'
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    67
      | is_pair_C _ _ = false;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    68
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    69
    fun mk_size_of_typ (T as TFree _) =
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    70
        pair (case AList.lookup (op =) As_fs T of
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    71
            SOME f => f
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    72
          | NONE => if member (op =) Cs T then Term.absdummy T (Bound 0) else mk_abs_zero_nat T)
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    73
      | mk_size_of_typ (T as Type (s, Ts)) =
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    74
        if is_pair_C s Ts then
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    75
          pair (snd_const T)
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    76
        else if exists (exists_subtype_in As) Ts then
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    77
          (case Symtab.lookup data s of
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    78
            SOME (gen_size_name, (_, gen_size_maps)) =>
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    79
            let
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    80
              val (args, gen_size_mapss') = split_list (map (fn T => mk_size_of_typ T []) Ts);
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    81
              val gen_size_const = Const (gen_size_name, map fastype_of args ---> mk_to_natT T);
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    82
            in
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    83
              fold (union Thm.eq_thm) (gen_size_maps :: gen_size_mapss')
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    84
              #> pair (Term.list_comb (gen_size_const, args))
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    85
            end
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    86
          | NONE => pair (mk_abs_zero_nat T))
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    87
        else
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    88
          pair (mk_abs_zero_nat T);
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    89
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    90
    fun mk_size_of_arg t =
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    91
      mk_size_of_typ (fastype_of t) #>> (fn s => substCT (betapply (s, t)));
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    92
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    93
    fun mk_gen_size_arg arg_T gen_size_maps =
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    94
      let
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    95
        val x_Ts = binder_types arg_T;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    96
        val m = length x_Ts;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    97
        val x_names = map (prefix "x" o string_of_int) (1 upto m);
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    98
        val xs = map2 (curry Free) x_names x_Ts;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    99
        val (summands, gen_size_maps') =
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   100
          fold_map mk_size_of_arg xs gen_size_maps
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   101
          |>> remove (op =) zero_nat;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   102
        val sum =
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   103
          if null summands then HOLogic.zero
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   104
          else foldl1 mk_plus_nat (summands @ [HOLogic.Suc_zero]);
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   105
      in
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   106
        (fold_rev Term.lambda (map substCT xs) sum, gen_size_maps')
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   107
      end;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   108
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   109
    fun mk_gen_size_rhs rec_T recx gen_size_maps =
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   110
      let
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   111
        val arg_Ts = binder_fun_types rec_T;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   112
        val (args, gen_size_maps') = fold_map mk_gen_size_arg arg_Ts gen_size_maps;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   113
      in
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   114
        (fold_rev Term.lambda fs (Term.list_comb (substCT recx, args)), gen_size_maps')
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   115
      end;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   116
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   117
    fun mk_def_binding f = Binding.conceal o Binding.name o Thm.def_name o f o Long_Name.base_name;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   118
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   119
    val (gen_size_rhss, nested_gen_size_maps) = fold_map2 mk_gen_size_rhs rec_Ts recs [];
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   120
    val gen_size_Ts = map fastype_of gen_size_rhss;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   121
    val gen_size_consts = map2 (curry Const) gen_size_names gen_size_Ts;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   122
    val gen_size_constsB = map (Term.map_types B_ify) gen_size_consts;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   123
    val gen_size_def_bs = map (mk_def_binding I) gen_size_names;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   124
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   125
    val (gen_size_defs, thy2) =
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   126
      thy
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   127
      |> Sign.add_consts (map (fn (s, T) => (Binding.name (Long_Name.base_name s), T, NoSyn))
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   128
        (gen_size_names ~~ gen_size_Ts))
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   129
      |> Global_Theory.add_defs false (map Thm.no_attributes (gen_size_def_bs ~~
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   130
        map Logic.mk_equals (gen_size_consts ~~ gen_size_rhss)));
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   131
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   132
    val zeros = map mk_abs_zero_nat As;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   133
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   134
    val spec_size_rhss = map (fn c => Term.list_comb (c, zeros)) gen_size_consts;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   135
    val spec_size_Ts = map fastype_of spec_size_rhss;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   136
    val spec_size_consts = map (curry Const @{const_name size}) spec_size_Ts;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   137
    val spec_size_def_bs = map (mk_def_binding (suffix "_overloaded")) gen_size_names;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   138
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   139
    fun define_spec_size def_b lhs0 rhs lthy =
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   140
      let
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   141
        val Free (c, _) = Syntax.check_term lthy lhs0;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   142
        val (thm, lthy') = lthy
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   143
          |> Local_Theory.define ((Binding.name c, NoSyn), ((def_b, []), rhs))
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   144
          |-> (fn (t, (_, thm)) => Spec_Rules.add Spec_Rules.Equational ([t], [thm]) #> pair thm);
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   145
        val ctxt_thy = Proof_Context.init_global (Proof_Context.theory_of lthy');
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   146
        val thm' = singleton (Proof_Context.export lthy' ctxt_thy) thm;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   147
      in (thm', lthy') end;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   148
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   149
    val (spec_size_defs, thy3) = thy2
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   150
      |> Class.instantiation (T_names, map dest_TFree As, [HOLogic.class_size])
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   151
      |> fold_map3 define_spec_size spec_size_def_bs spec_size_consts spec_size_rhss
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   152
      ||> Class.prove_instantiation_instance (K (Class.intro_classes_tac []))
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   153
      ||> Local_Theory.exit_global;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   154
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   155
    val thy3_ctxt = Proof_Context.init_global thy3;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   156
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   157
    val gen_size_defs' =
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   158
      map (mk_unabs_def (num_As + 1) o (fn thm => thm RS meta_eq_to_obj_eq)) gen_size_defs;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   159
    val spec_size_defs' =
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   160
      map (mk_unabs_def 1 o (fn thm => thm RS meta_eq_to_obj_eq)) spec_size_defs;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   161
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   162
    fun derive_size_simp unfolds folds size_def' simp0 =
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   163
      fold_thms thy3_ctxt folds (unfold_thms thy3_ctxt unfolds (trans OF [size_def', simp0]));
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   164
    val derive_gen_size_simp =
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   165
      derive_size_simp (@{thm snd_o_convol} :: nested_gen_size_maps) gen_size_defs';
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   166
    val derive_spec_size_simp = derive_size_simp @{thms add_0_left add_0_right} spec_size_defs';
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   167
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   168
    val gen_size_simpss = map2 (map o derive_gen_size_simp) gen_size_defs' rec_thmss;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   169
    val gen_size_simps = flat gen_size_simpss;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   170
    val spec_size_simpss = map2 (map o derive_spec_size_simp) spec_size_defs' gen_size_simpss;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   171
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   172
    val ABs = As ~~ Bs;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   173
    val g_names = map (prefix "g" o string_of_int) (1 upto num_As);
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   174
    val gs = map2 (curry Free) g_names (map (op -->) ABs);
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   175
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   176
    val liveness = map (op <>) ABs;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   177
    val live_gs = AList.find (op =) (gs ~~ liveness) true;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   178
    val live = length live_gs;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   179
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   180
    val u_names = map (prefix "u" o string_of_int) (1 upto nn);
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   181
    val us = map2 (curry Free) u_names Ts;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   182
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   183
    val maps0 = map map_of_bnf fp_bnfs;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   184
    val map_thms = maps #maps fp_sugars;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   185
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   186
    fun mk_gen_size_map_tac ctxt =
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   187
      HEADGOAL (rtac (co_induct_of common_inducts)) THEN
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   188
      ALLGOALS (asm_simp_tac (ss_only (o_apply :: map_thms @ gen_size_simps) ctxt));
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   189
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   190
    val gen_size_map_thmss =
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   191
      if live = 0 then
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   192
        replicate nn []
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   193
      else if null nested_gen_size_maps then
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   194
        let
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   195
          val xgmaps =
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   196
            map2 (fn map0 => fn u => Term.list_comb (mk_map live As Bs map0, live_gs) $ u) maps0 us;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   197
          val fsizes =
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   198
            map (fn gen_size_constB => Term.list_comb (gen_size_constB, fsB)) gen_size_constsB;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   199
          val lhss = map2 (curry (op $)) fsizes xgmaps;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   200
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   201
          val fgs = map2 (fn fB => fn g as Free (_, Type (_, [A, B])) =>
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   202
            if A = B then fB else HOLogic.mk_comp (fB, g)) fsB gs;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   203
          val rhss = map2 (fn gen_size_const => fn u => Term.list_comb (gen_size_const, fgs) $ u)
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   204
            gen_size_consts us;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   205
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   206
          val goal = Library.foldr1 HOLogic.mk_conj (map2 (curry HOLogic.mk_eq) lhss rhss)
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   207
            |> HOLogic.mk_Trueprop;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   208
        in
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   209
          Goal.prove_global thy3 [] [] goal (mk_gen_size_map_tac o #context)
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   210
          |> Thm.close_derivation
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   211
          |> conj_dests nn
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   212
          |> map single
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   213
        end
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   214
      else
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   215
        (* TODO: implement general case, with nesting of datatypes that themselves nest other
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   216
           types *)
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   217
        replicate nn [];
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   218
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   219
    val (_, thy4) = thy3
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   220
      |> fold_map3 (fn T_name => fn size_simps => fn gen_size_map_thms =>
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   221
          let val qualify = Binding.qualify true (Long_Name.base_name T_name) in
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   222
            Global_Theory.note_thmss ""
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   223
              ([((qualify (Binding.name sizeN),
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   224
                   [Simplifier.simp_add, Nitpick_Simps.add, Thm.declaration_attribute
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   225
                      (fn thm => Context.mapping (Code.add_default_eqn thm) I)]),
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   226
                 [(size_simps, [])]),
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   227
                ((qualify (Binding.name size_mapN), []), [(gen_size_map_thms, [])])]
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   228
               |> filter_out (forall (null o fst) o snd))
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   229
          end)
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   230
        T_names (map2 append gen_size_simpss spec_size_simpss) gen_size_map_thmss
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   231
      ||> Spec_Rules.add_global Spec_Rules.Equational (gen_size_consts, gen_size_simps);
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   232
  in
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   233
    thy4
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   234
    |> Data.map (fold2 (fn T_name => fn gen_size_name =>
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   235
        Symtab.update_new (T_name, (gen_size_name, (gen_size_simps, flat gen_size_map_thmss))))
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   236
      T_names gen_size_names)
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   237
  end;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   238
56639
c9d6b581bd3b made old-style 'size' interpretation hook more robust in case 'size' is already specified (either by the user or by the new datatype package)
blanchet
parents: 56638
diff changeset
   239
(* FIXME: get rid of "perhaps o try" once the code is stable *)
c9d6b581bd3b made old-style 'size' interpretation hook more robust in case 'size' is already specified (either by the user or by the new datatype package)
blanchet
parents: 56638
diff changeset
   240
val _ = Theory.setup (fp_sugar_interpretation (perhaps o try o generate_size));
56638
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   241
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   242
end;