src/HOL/Tools/BNF/bnf_lfp_size.ML
author wenzelm
Mon, 02 Dec 2019 15:04:38 +0100
changeset 71214 5727bcc3c47c
parent 71179 592e2afdd50c
child 72154 2b41b710f6ef
permissions -rw-r--r--
proper spec_rule name via naming/binding/Morphism.binding;
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
58315
6d8458bc6e27 tuning terminology
blanchet
parents: 58208
diff changeset
     5
Generation of size functions for datatypes.
56638
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
62082
614ef6d7a6b6 nicer 'Spec_Rules' for size function
blanchet
parents: 61786
diff changeset
    10
  val register_size: string -> string -> thm -> thm list -> thm list -> local_theory -> local_theory
614ef6d7a6b6 nicer 'Spec_Rules' for size function
blanchet
parents: 61786
diff changeset
    11
  val register_size_global: string -> string -> thm -> thm list -> thm list -> theory -> theory
614ef6d7a6b6 nicer 'Spec_Rules' for size function
blanchet
parents: 61786
diff changeset
    12
  val size_of: Proof.context -> string -> (string * (thm * thm list * thm list)) option
614ef6d7a6b6 nicer 'Spec_Rules' for size function
blanchet
parents: 61786
diff changeset
    13
  val size_of_global: theory -> string -> (string * (thm * thm list * thm list)) option
56642
15cd15f9b40c allow registration of custom size functions for BNF-based datatypes
blanchet
parents: 56640
diff changeset
    14
end;
15cd15f9b40c allow registration of custom size functions for BNF-based datatypes
blanchet
parents: 56640
diff changeset
    15
15cd15f9b40c allow registration of custom size functions for BNF-based datatypes
blanchet
parents: 56640
diff changeset
    16
structure BNF_LFP_Size : BNF_LFP_SIZE =
56638
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    17
struct
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    18
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    19
open BNF_Util
56640
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
    20
open BNF_Tactics
56638
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    21
open BNF_Def
58179
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
    22
open BNF_FP_Def_Sugar
56638
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    23
58337
blanchet
parents: 58335
diff changeset
    24
val size_N = "size_";
blanchet
parents: 58335
diff changeset
    25
val sizeN = "size";
58736
552ccec3f00f generate 'size_gen' for datatypes
desharna
parents: 58734
diff changeset
    26
val size_genN = "size_gen";
58738
2af42aecc120 rename 'size_o_map' to 'size_gen_o_map'
desharna
parents: 58736
diff changeset
    27
val size_gen_o_mapN = "size_gen_o_map";
58913
5be251101978 generate 'size_neq' for datatypes
desharna
parents: 58738
diff changeset
    28
val size_neqN = "size_neq";
56638
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    29
56651
fc105315822a localize new size function generation code
blanchet
parents: 56650
diff changeset
    30
val nitpicksimp_attrs = @{attributes [nitpick_simp]};
fc105315822a localize new size function generation code
blanchet
parents: 56650
diff changeset
    31
val simp_attrs = @{attributes [simp]};
fc105315822a localize new size function generation code
blanchet
parents: 56650
diff changeset
    32
69593
3dda49e08b9d isabelle update -u control_cartouches;
wenzelm
parents: 67710
diff changeset
    33
fun mk_plus_nat (t1, t2) = Const (\<^const_name>\<open>Groups.plus\<close>,
56638
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    34
  HOLogic.natT --> HOLogic.natT --> HOLogic.natT) $ t1 $ t2;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    35
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    36
fun mk_to_natT T = T --> HOLogic.natT;
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    37
58337
blanchet
parents: 58335
diff changeset
    38
fun mk_abs_zero_nat T = Term.absdummy T HOLogic.zero;
56638
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    39
56640
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
    40
fun mk_unabs_def_unused_0 n =
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
    41
  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
    42
61786
6c42d55097c1 nicer error when the given size function has the wrong type
blanchet
parents: 61760
diff changeset
    43
structure Data = Generic_Data
6c42d55097c1 nicer error when the given size function has the wrong type
blanchet
parents: 61760
diff changeset
    44
(
62082
614ef6d7a6b6 nicer 'Spec_Rules' for size function
blanchet
parents: 61786
diff changeset
    45
  type T = (string * (thm * thm list * thm list)) Symtab.table;
61786
6c42d55097c1 nicer error when the given size function has the wrong type
blanchet
parents: 61760
diff changeset
    46
  val empty = Symtab.empty;
6c42d55097c1 nicer error when the given size function has the wrong type
blanchet
parents: 61760
diff changeset
    47
  val extend = I
6c42d55097c1 nicer error when the given size function has the wrong type
blanchet
parents: 61760
diff changeset
    48
  fun merge data = Symtab.merge (K true) data;
6c42d55097c1 nicer error when the given size function has the wrong type
blanchet
parents: 61760
diff changeset
    49
);
6c42d55097c1 nicer error when the given size function has the wrong type
blanchet
parents: 61760
diff changeset
    50
6c42d55097c1 nicer error when the given size function has the wrong type
blanchet
parents: 61760
diff changeset
    51
fun check_size_type thy T_name size_name =
6c42d55097c1 nicer error when the given size function has the wrong type
blanchet
parents: 61760
diff changeset
    52
  let
6c42d55097c1 nicer error when the given size function has the wrong type
blanchet
parents: 61760
diff changeset
    53
    val n = Sign.arity_number thy T_name;
69593
3dda49e08b9d isabelle update -u control_cartouches;
wenzelm
parents: 67710
diff changeset
    54
    val As = map (fn s => TFree (s, \<^sort>\<open>type\<close>)) (Name.invent Name.context Name.aT n);
61786
6c42d55097c1 nicer error when the given size function has the wrong type
blanchet
parents: 61760
diff changeset
    55
    val T = Type (T_name, As);
6c42d55097c1 nicer error when the given size function has the wrong type
blanchet
parents: 61760
diff changeset
    56
    val size_T = map mk_to_natT As ---> mk_to_natT T;
6c42d55097c1 nicer error when the given size function has the wrong type
blanchet
parents: 61760
diff changeset
    57
    val size_const = Const (size_name, size_T);
6c42d55097c1 nicer error when the given size function has the wrong type
blanchet
parents: 61760
diff changeset
    58
  in
6c42d55097c1 nicer error when the given size function has the wrong type
blanchet
parents: 61760
diff changeset
    59
    can (Thm.global_cterm_of thy) size_const orelse
6c42d55097c1 nicer error when the given size function has the wrong type
blanchet
parents: 61760
diff changeset
    60
    error ("Constant " ^ quote size_name ^ " registered as size function for " ^ quote T_name ^
6c42d55097c1 nicer error when the given size function has the wrong type
blanchet
parents: 61760
diff changeset
    61
      " must have type\n" ^ quote (Syntax.string_of_typ_global thy size_T))
6c42d55097c1 nicer error when the given size function has the wrong type
blanchet
parents: 61760
diff changeset
    62
  end;
6c42d55097c1 nicer error when the given size function has the wrong type
blanchet
parents: 61760
diff changeset
    63
62082
614ef6d7a6b6 nicer 'Spec_Rules' for size function
blanchet
parents: 61786
diff changeset
    64
fun register_size T_name size_name overloaded_size_def size_simps size_gen_o_maps lthy =
61786
6c42d55097c1 nicer error when the given size function has the wrong type
blanchet
parents: 61760
diff changeset
    65
  (check_size_type (Proof_Context.theory_of lthy) T_name size_name;
62082
614ef6d7a6b6 nicer 'Spec_Rules' for size function
blanchet
parents: 61786
diff changeset
    66
   Context.proof_map (Data.map (Symtab.update
614ef6d7a6b6 nicer 'Spec_Rules' for size function
blanchet
parents: 61786
diff changeset
    67
       (T_name, (size_name, (overloaded_size_def, size_simps, size_gen_o_maps)))))
61786
6c42d55097c1 nicer error when the given size function has the wrong type
blanchet
parents: 61760
diff changeset
    68
     lthy);
6c42d55097c1 nicer error when the given size function has the wrong type
blanchet
parents: 61760
diff changeset
    69
62082
614ef6d7a6b6 nicer 'Spec_Rules' for size function
blanchet
parents: 61786
diff changeset
    70
fun register_size_global T_name size_name overloaded_size_def size_simps size_gen_o_maps thy =
61786
6c42d55097c1 nicer error when the given size function has the wrong type
blanchet
parents: 61760
diff changeset
    71
  (check_size_type thy T_name size_name;
62082
614ef6d7a6b6 nicer 'Spec_Rules' for size function
blanchet
parents: 61786
diff changeset
    72
   Context.theory_map (Data.map (Symtab.update
614ef6d7a6b6 nicer 'Spec_Rules' for size function
blanchet
parents: 61786
diff changeset
    73
       (T_name, (size_name, (overloaded_size_def, size_simps, size_gen_o_maps)))))
614ef6d7a6b6 nicer 'Spec_Rules' for size function
blanchet
parents: 61786
diff changeset
    74
     thy);
61786
6c42d55097c1 nicer error when the given size function has the wrong type
blanchet
parents: 61760
diff changeset
    75
6c42d55097c1 nicer error when the given size function has the wrong type
blanchet
parents: 61760
diff changeset
    76
val size_of = Symtab.lookup o Data.get o Context.Proof;
6c42d55097c1 nicer error when the given size function has the wrong type
blanchet
parents: 61760
diff changeset
    77
val size_of_global = Symtab.lookup o Data.get o Context.Theory;
6c42d55097c1 nicer error when the given size function has the wrong type
blanchet
parents: 61760
diff changeset
    78
62082
614ef6d7a6b6 nicer 'Spec_Rules' for size function
blanchet
parents: 61786
diff changeset
    79
fun all_overloaded_size_defs_of ctxt =
62536
656e9653c645 made 'size' plugin compatible with locales again (and added regression test)
blanchet
parents: 62124
diff changeset
    80
  Symtab.fold (fn (_, (_, (overloaded_size_def, _, _))) =>
656e9653c645 made 'size' plugin compatible with locales again (and added regression test)
blanchet
parents: 62124
diff changeset
    81
      can (Logic.dest_equals o Thm.prop_of) overloaded_size_def ? cons overloaded_size_def)
62082
614ef6d7a6b6 nicer 'Spec_Rules' for size function
blanchet
parents: 61786
diff changeset
    82
    (Data.get (Context.Proof ctxt)) [];
614ef6d7a6b6 nicer 'Spec_Rules' for size function
blanchet
parents: 61786
diff changeset
    83
63170
eae6549dbea2 tuned proofs, to allow unfold_abs_def;
wenzelm
parents: 62690
diff changeset
    84
val size_gen_o_map_simps = @{thms inj_on_id snd_comp_apfst[simplified apfst_def]};
56640
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
    85
58738
2af42aecc120 rename 'size_o_map' to 'size_gen_o_map'
desharna
parents: 58736
diff changeset
    86
fun mk_size_gen_o_map_tac ctxt size_def rec_o_map inj_maps size_maps =
56640
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
    87
  unfold_thms_tac ctxt [size_def] THEN
60728
26ffdb966759 {r,e,d,f}tac with proper context in BNF
traytel
parents: 59988
diff changeset
    88
  HEADGOAL (rtac ctxt (rec_o_map RS trans) THEN'
58738
2af42aecc120 rename 'size_o_map' to 'size_gen_o_map'
desharna
parents: 58736
diff changeset
    89
    asm_simp_tac (ss_only (inj_maps @ size_maps @ size_gen_o_map_simps) ctxt)) THEN
60728
26ffdb966759 {r,e,d,f}tac with proper context in BNF
traytel
parents: 59988
diff changeset
    90
  IF_UNSOLVED (unfold_thms_tac ctxt @{thms id_def o_def} THEN HEADGOAL (rtac ctxt refl));
56638
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
    91
58913
5be251101978 generate 'size_neq' for datatypes
desharna
parents: 58738
diff changeset
    92
fun mk_size_neq ctxt cts exhaust sizes =
60784
4f590c08fd5d updated to infer_instantiate;
wenzelm
parents: 60728
diff changeset
    93
  HEADGOAL (rtac ctxt (infer_instantiate' ctxt (map SOME cts) exhaust)) THEN
58913
5be251101978 generate 'size_neq' for datatypes
desharna
parents: 58738
diff changeset
    94
  ALLGOALS (hyp_subst_tac ctxt) THEN
61760
1647bb489522 tuned whitespace
blanchet
parents: 61334
diff changeset
    95
  unfold_thms_tac ctxt (@{thm neq0_conv} :: sizes) THEN
1647bb489522 tuned whitespace
blanchet
parents: 61334
diff changeset
    96
  ALLGOALS (REPEAT_DETERM o (rtac ctxt @{thm zero_less_Suc} ORELSE'
1647bb489522 tuned whitespace
blanchet
parents: 61334
diff changeset
    97
    rtac ctxt @{thm trans_less_add2}));
58913
5be251101978 generate 'size_neq' for datatypes
desharna
parents: 58738
diff changeset
    98
58179
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
    99
fun generate_datatype_size (fp_sugars as ({T = Type (_, As), BT = Type (_, Bs), fp = Least_FP,
63859
dca6fabd8060 make (co)induct component of 'fp_sugar' optional, for the benefit of nonuniform (co)datatypes and other similar extensions
blanchet
parents: 63239
diff changeset
   100
        fp_res = {bnfs = fp_bnfs, ...}, fp_nesting_bnfs, live_nesting_bnfs,
dca6fabd8060 make (co)induct component of 'fp_sugar' optional, for the benefit of nonuniform (co)datatypes and other similar extensions
blanchet
parents: 63239
diff changeset
   101
        fp_co_induct_sugar = SOME _, ...} : fp_sugar) :: _)
59145
blanchet
parents: 59058
diff changeset
   102
      lthy0 =
58179
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   103
    let
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   104
      val data = Data.get (Context.Proof lthy0);
56651
fc105315822a localize new size function generation code
blanchet
parents: 56650
diff changeset
   105
58179
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   106
      val Ts = map #T fp_sugars
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   107
      val T_names = map (fst o dest_Type) Ts;
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   108
      val nn = length Ts;
56640
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   109
58179
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   110
      val B_ify = Term.typ_subst_atomic (As ~~ Bs);
56651
fc105315822a localize new size function generation code
blanchet
parents: 56650
diff changeset
   111
63859
dca6fabd8060 make (co)induct component of 'fp_sugar' optional, for the benefit of nonuniform (co)datatypes and other similar extensions
blanchet
parents: 63239
diff changeset
   112
      val recs = map (#co_rec o the o #fp_co_induct_sugar) fp_sugars;
dca6fabd8060 make (co)induct component of 'fp_sugar' optional, for the benefit of nonuniform (co)datatypes and other similar extensions
blanchet
parents: 63239
diff changeset
   113
      val rec_thmss = map (#co_rec_thms o the o #fp_co_induct_sugar) fp_sugars;
58179
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   114
      val rec_Ts as rec_T1 :: _ = map fastype_of recs;
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   115
      val rec_arg_Ts = binder_fun_types rec_T1;
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   116
      val Cs = map body_type rec_Ts;
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   117
      val Cs_rho = map (rpair HOLogic.natT) Cs;
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   118
      val substCnatT = Term.subst_atomic_types Cs_rho;
56651
fc105315822a localize new size function generation code
blanchet
parents: 56650
diff changeset
   119
58179
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   120
      val f_Ts = map mk_to_natT As;
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   121
      val f_TsB = map mk_to_natT Bs;
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   122
      val num_As = length As;
56651
fc105315822a localize new size function generation code
blanchet
parents: 56650
diff changeset
   123
58179
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   124
      fun variant_names n pre = fst (Variable.variant_fixes (replicate n pre) lthy0);
56651
fc105315822a localize new size function generation code
blanchet
parents: 56650
diff changeset
   125
58179
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   126
      val f_names = variant_names num_As "f";
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   127
      val fs = map2 (curry Free) f_names f_Ts;
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   128
      val fsB = map2 (curry Free) f_names f_TsB;
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   129
      val As_fs = As ~~ fs;
56638
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   130
58179
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   131
      val size_bs =
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   132
        map ((fn base => Binding.qualify false base (Binding.name (prefix size_N base))) o
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   133
          Long_Name.base_name) T_names;
56638
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   134
69593
3dda49e08b9d isabelle update -u control_cartouches;
wenzelm
parents: 67710
diff changeset
   135
      fun is_prod_C \<^type_name>\<open>prod\<close> [_, T'] = member (op =) Cs T'
58208
blanchet
parents: 58191
diff changeset
   136
        | is_prod_C _ _ = false;
56651
fc105315822a localize new size function generation code
blanchet
parents: 56650
diff changeset
   137
58179
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   138
      fun mk_size_of_typ (T as TFree _) =
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   139
          pair (case AList.lookup (op =) As_fs T of
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   140
              SOME f => f
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   141
            | NONE => if member (op =) Cs T then Term.absdummy T (Bound 0) else mk_abs_zero_nat T)
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   142
        | mk_size_of_typ (T as Type (s, Ts)) =
58208
blanchet
parents: 58191
diff changeset
   143
          if is_prod_C s Ts then
58179
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   144
            pair (snd_const T)
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   145
          else if exists (exists_subtype_in (As @ Cs)) Ts then
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   146
            (case Symtab.lookup data s of
62082
614ef6d7a6b6 nicer 'Spec_Rules' for size function
blanchet
parents: 61786
diff changeset
   147
              SOME (size_name, (_, _, size_gen_o_maps)) =>
58179
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   148
              let
58738
2af42aecc120 rename 'size_o_map' to 'size_gen_o_map'
desharna
parents: 58736
diff changeset
   149
                val (args, size_gen_o_mapss') = fold_map mk_size_of_typ Ts [];
61786
6c42d55097c1 nicer error when the given size function has the wrong type
blanchet
parents: 61760
diff changeset
   150
                val size_T = map fastype_of args ---> mk_to_natT T;
6c42d55097c1 nicer error when the given size function has the wrong type
blanchet
parents: 61760
diff changeset
   151
                val size_const = Const (size_name, size_T);
58179
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   152
              in
58738
2af42aecc120 rename 'size_o_map' to 'size_gen_o_map'
desharna
parents: 58736
diff changeset
   153
                append (size_gen_o_maps :: size_gen_o_mapss')
58179
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   154
                #> pair (Term.list_comb (size_const, args))
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   155
              end
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   156
            | _ => pair (mk_abs_zero_nat T))
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   157
          else
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   158
            pair (mk_abs_zero_nat T);
56651
fc105315822a localize new size function generation code
blanchet
parents: 56650
diff changeset
   159
58179
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   160
      fun mk_size_of_arg t =
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   161
        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
   162
58338
d109244b89aa tuned definition of 'size' function to get nicer properties
blanchet
parents: 58337
diff changeset
   163
      fun is_recursive_or_plain_case Ts =
d109244b89aa tuned definition of 'size' function to get nicer properties
blanchet
parents: 58337
diff changeset
   164
        exists (exists_subtype_in Cs) Ts orelse forall (not o exists_subtype_in As) Ts;
d109244b89aa tuned definition of 'size' function to get nicer properties
blanchet
parents: 58337
diff changeset
   165
d109244b89aa tuned definition of 'size' function to get nicer properties
blanchet
parents: 58337
diff changeset
   166
      (* We want the size function to enjoy the following properties:
d109244b89aa tuned definition of 'size' function to get nicer properties
blanchet
parents: 58337
diff changeset
   167
58355
9a041a55ee95 syntactic check to determine when to prove 'nested_size_o_map'
blanchet
parents: 58353
diff changeset
   168
          1. The size of a list should coincide with its length.
9a041a55ee95 syntactic check to determine when to prove 'nested_size_o_map'
blanchet
parents: 58353
diff changeset
   169
          2. All the nonrecursive constructors of a type should have the same size.
9a041a55ee95 syntactic check to determine when to prove 'nested_size_o_map'
blanchet
parents: 58353
diff changeset
   170
          3. Each constructor through which nested recursion takes place should count as at least
9a041a55ee95 syntactic check to determine when to prove 'nested_size_o_map'
blanchet
parents: 58353
diff changeset
   171
             one in the generic size function.
9a041a55ee95 syntactic check to determine when to prove 'nested_size_o_map'
blanchet
parents: 58353
diff changeset
   172
          4. The "size" function should be definable as "size_t (%_. 0) ... (%_. 0)", where "size_t"
9a041a55ee95 syntactic check to determine when to prove 'nested_size_o_map'
blanchet
parents: 58353
diff changeset
   173
             is the generic function.
58338
d109244b89aa tuned definition of 'size' function to get nicer properties
blanchet
parents: 58337
diff changeset
   174
58355
9a041a55ee95 syntactic check to determine when to prove 'nested_size_o_map'
blanchet
parents: 58353
diff changeset
   175
         This explains the somewhat convoluted logic ahead. *)
58338
d109244b89aa tuned definition of 'size' function to get nicer properties
blanchet
parents: 58337
diff changeset
   176
d109244b89aa tuned definition of 'size' function to get nicer properties
blanchet
parents: 58337
diff changeset
   177
      val base_case =
d109244b89aa tuned definition of 'size' function to get nicer properties
blanchet
parents: 58337
diff changeset
   178
        if forall (is_recursive_or_plain_case o binder_types) rec_arg_Ts then HOLogic.zero
d109244b89aa tuned definition of 'size' function to get nicer properties
blanchet
parents: 58337
diff changeset
   179
        else HOLogic.Suc_zero;
d109244b89aa tuned definition of 'size' function to get nicer properties
blanchet
parents: 58337
diff changeset
   180
58355
9a041a55ee95 syntactic check to determine when to prove 'nested_size_o_map'
blanchet
parents: 58353
diff changeset
   181
      fun mk_size_arg rec_arg_T =
58179
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   182
        let
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   183
          val x_Ts = binder_types rec_arg_T;
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   184
          val m = length x_Ts;
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   185
          val x_names = variant_names m "x";
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   186
          val xs = map2 (curry Free) x_names x_Ts;
58738
2af42aecc120 rename 'size_o_map' to 'size_gen_o_map'
desharna
parents: 58736
diff changeset
   187
          val (summands, size_gen_o_mapss) =
58355
9a041a55ee95 syntactic check to determine when to prove 'nested_size_o_map'
blanchet
parents: 58353
diff changeset
   188
            fold_map mk_size_of_arg xs []
58337
blanchet
parents: 58335
diff changeset
   189
            |>> remove (op =) HOLogic.zero;
58179
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   190
          val sum =
62690
c4fad0569a24 nicer error
blanchet
parents: 62536
diff changeset
   191
            if null summands then base_case else foldl1 mk_plus_nat (summands @ [HOLogic.Suc_zero]);
56640
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   192
        in
58738
2af42aecc120 rename 'size_o_map' to 'size_gen_o_map'
desharna
parents: 58736
diff changeset
   193
          append size_gen_o_mapss
58355
9a041a55ee95 syntactic check to determine when to prove 'nested_size_o_map'
blanchet
parents: 58353
diff changeset
   194
          #> pair (fold_rev Term.lambda (map substCnatT xs) sum)
56640
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   195
        end;
0a35354137a5 generate 'rec_o_map' and 'size_o_map' in size extension
blanchet
parents: 56639
diff changeset
   196
58355
9a041a55ee95 syntactic check to determine when to prove 'nested_size_o_map'
blanchet
parents: 58353
diff changeset
   197
      fun mk_size_rhs recx =
9a041a55ee95 syntactic check to determine when to prove 'nested_size_o_map'
blanchet
parents: 58353
diff changeset
   198
        fold_map mk_size_arg rec_arg_Ts
9a041a55ee95 syntactic check to determine when to prove 'nested_size_o_map'
blanchet
parents: 58353
diff changeset
   199
        #>> (fn args => fold_rev Term.lambda fs (Term.list_comb (substCnatT recx, args)));
58179
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   200
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   201
      val maybe_conceal_def_binding = Thm.def_binding
62093
bd73a2279fcd more uniform treatment of package internals;
wenzelm
parents: 62082
diff changeset
   202
        #> not (Config.get lthy0 bnf_internals) ? Binding.concealed;
58179
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   203
58738
2af42aecc120 rename 'size_o_map' to 'size_gen_o_map'
desharna
parents: 58736
diff changeset
   204
      val (size_rhss, nested_size_gen_o_mapss) = fold_map mk_size_rhs recs [];
58179
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   205
      val size_Ts = map fastype_of size_rhss;
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   206
58738
2af42aecc120 rename 'size_o_map' to 'size_gen_o_map'
desharna
parents: 58736
diff changeset
   207
      val nested_size_gen_o_maps_complete = forall (not o null) nested_size_gen_o_mapss;
2af42aecc120 rename 'size_o_map' to 'size_gen_o_map'
desharna
parents: 58736
diff changeset
   208
      val nested_size_gen_o_maps = fold (union Thm.eq_thm_prop) nested_size_gen_o_mapss [];
58355
9a041a55ee95 syntactic check to determine when to prove 'nested_size_o_map'
blanchet
parents: 58353
diff changeset
   209
61101
7b915ca69af1 use open/close_target rather than Local_Theory.restore to get polymorphic definitions;
traytel
parents: 60784
diff changeset
   210
      val ((raw_size_consts, raw_size_defs), (lthy1, lthy1_old)) = lthy0
7b915ca69af1 use open/close_target rather than Local_Theory.restore to get polymorphic definitions;
traytel
parents: 60784
diff changeset
   211
        |> Local_Theory.open_target |> snd
58634
9f10d82e8188 added parameterized ML antiquotations @{map N}, @{fold N}, @{fold_map N}, @{split_list N};
wenzelm
parents: 58578
diff changeset
   212
        |> apfst split_list o @{fold_map 2} (fn b => fn rhs =>
58179
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   213
            Local_Theory.define ((b, NoSyn), ((maybe_conceal_def_binding b, []), rhs))
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   214
            #>> apsnd snd)
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   215
          size_bs size_rhss
61101
7b915ca69af1 use open/close_target rather than Local_Theory.restore to get polymorphic definitions;
traytel
parents: 60784
diff changeset
   216
        ||> `Local_Theory.close_target;
58179
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   217
61101
7b915ca69af1 use open/close_target rather than Local_Theory.restore to get polymorphic definitions;
traytel
parents: 60784
diff changeset
   218
      val phi = Proof_Context.export_morphism lthy1_old lthy1;
58179
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   219
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   220
      val size_defs = map (Morphism.thm phi) raw_size_defs;
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   221
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   222
      val size_consts0 = map (Morphism.term phi) raw_size_consts;
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   223
      val size_consts = map2 retype_const_or_free size_Ts size_consts0;
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   224
      val size_constsB = map (Term.map_types B_ify) size_consts;
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   225
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   226
      val zeros = map mk_abs_zero_nat As;
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   227
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   228
      val overloaded_size_rhss = map (fn c => Term.list_comb (c, zeros)) size_consts;
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   229
      val overloaded_size_Ts = map fastype_of overloaded_size_rhss;
69593
3dda49e08b9d isabelle update -u control_cartouches;
wenzelm
parents: 67710
diff changeset
   230
      val overloaded_size_consts = map (curry Const \<^const_name>\<open>size\<close>) overloaded_size_Ts;
58179
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   231
      val overloaded_size_def_bs =
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   232
        map (maybe_conceal_def_binding o Binding.suffix_name "_overloaded") size_bs;
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   233
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   234
      fun define_overloaded_size def_b lhs0 rhs lthy =
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   235
        let
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   236
          val Free (c, _) = Syntax.check_term lthy lhs0;
62082
614ef6d7a6b6 nicer 'Spec_Rules' for size function
blanchet
parents: 61786
diff changeset
   237
          val ((_, (_, thm)), lthy') = lthy
614ef6d7a6b6 nicer 'Spec_Rules' for size function
blanchet
parents: 61786
diff changeset
   238
            |> Local_Theory.define ((Binding.name c, NoSyn), ((def_b, []), rhs));
59644
wenzelm
parents: 59621
diff changeset
   239
          val thy_ctxt = Proof_Context.init_global (Proof_Context.theory_of lthy');
wenzelm
parents: 59621
diff changeset
   240
          val thm' = singleton (Proof_Context.export lthy' thy_ctxt) thm;
58179
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   241
        in (thm', lthy') end;
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   242
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   243
      val (overloaded_size_defs, lthy2) = lthy1
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   244
        |> Local_Theory.background_theory_result
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   245
          (Class.instantiation (T_names, map dest_TFree As, [HOLogic.class_size])
58634
9f10d82e8188 added parameterized ML antiquotations @{map N}, @{fold N}, @{fold_map N}, @{split_list N};
wenzelm
parents: 58578
diff changeset
   246
           #> @{fold_map 3} define_overloaded_size overloaded_size_def_bs overloaded_size_consts
58179
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   247
             overloaded_size_rhss
59498
50b60f501b05 proper context for resolve_tac, eresolve_tac, dresolve_tac, forward_tac etc.;
wenzelm
parents: 59145
diff changeset
   248
           ##> Class.prove_instantiation_instance (fn ctxt => Class.intro_classes_tac ctxt [])
58179
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   249
           ##> Local_Theory.exit_global);
56638
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   250
58179
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   251
      val size_defs' =
67710
cc2db3239932 added HOLogic.mk_obj_eq convenience and eliminated some clones;
wenzelm
parents: 67314
diff changeset
   252
        map (mk_unabs_def (num_As + 1) o HOLogic.mk_obj_eq) size_defs;
58179
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   253
      val size_defs_unused_0 =
67710
cc2db3239932 added HOLogic.mk_obj_eq convenience and eliminated some clones;
wenzelm
parents: 67314
diff changeset
   254
        map (mk_unabs_def_unused_0 (num_As + 1) o HOLogic.mk_obj_eq) size_defs;
58179
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   255
      val overloaded_size_defs' =
67710
cc2db3239932 added HOLogic.mk_obj_eq convenience and eliminated some clones;
wenzelm
parents: 67314
diff changeset
   256
        map (mk_unabs_def 1 o HOLogic.mk_obj_eq) overloaded_size_defs;
58179
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   257
61760
1647bb489522 tuned whitespace
blanchet
parents: 61334
diff changeset
   258
      val nested_size_maps =
1647bb489522 tuned whitespace
blanchet
parents: 61334
diff changeset
   259
        map (mk_pointful lthy2) nested_size_gen_o_maps @ nested_size_gen_o_maps;
59576
913c4afb0388 avoid duplicate simp warning for datatypes with explicit products
blanchet
parents: 59498
diff changeset
   260
      val all_inj_maps =
913c4afb0388 avoid duplicate simp warning for datatypes with explicit products
blanchet
parents: 59498
diff changeset
   261
        @{thm prod.inj_map} :: map inj_map_of_bnf (fp_bnfs @ fp_nesting_bnfs @ live_nesting_bnfs)
58179
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   262
        |> distinct Thm.eq_thm_prop;
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   263
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   264
      fun derive_size_simp size_def' simp0 =
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   265
        (trans OF [size_def', simp0])
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   266
        |> Simplifier.asm_full_simplify (ss_only (@{thms inj_on_convol_ident id_def o_def
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   267
          snd_conv} @ all_inj_maps @ nested_size_maps) lthy2)
63222
fe92356ade42 eliminated pointless alias (no warning for duplicates);
wenzelm
parents: 63170
diff changeset
   268
        |> Local_Defs.fold lthy2 size_defs_unused_0;
58179
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   269
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   270
      fun derive_overloaded_size_simp overloaded_size_def' simp0 =
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   271
        (trans OF [overloaded_size_def', simp0])
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   272
        |> unfold_thms lthy2 @{thms add_0_left add_0_right}
63222
fe92356ade42 eliminated pointless alias (no warning for duplicates);
wenzelm
parents: 63170
diff changeset
   273
        |> Local_Defs.fold lthy2 (overloaded_size_defs @ all_overloaded_size_defs_of lthy2);
58179
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   274
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   275
      val size_simpss = map2 (map o derive_size_simp) size_defs' rec_thmss;
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   276
      val size_simps = flat size_simpss;
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   277
      val overloaded_size_simpss =
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   278
        map2 (map o derive_overloaded_size_simp) overloaded_size_defs' size_simpss;
62082
614ef6d7a6b6 nicer 'Spec_Rules' for size function
blanchet
parents: 61786
diff changeset
   279
      val overloaded_size_simps = flat overloaded_size_simpss;
58179
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   280
      val size_thmss = map2 append size_simpss overloaded_size_simpss;
66494
8645dc296dca tuning (proofs and code)
blanchet
parents: 66251
diff changeset
   281
      val size_gen_thmss = size_simpss;
8645dc296dca tuning (proofs and code)
blanchet
parents: 66251
diff changeset
   282
58913
5be251101978 generate 'size_neq' for datatypes
desharna
parents: 58738
diff changeset
   283
      fun rhs_is_zero thm =
59582
0fbed69ff081 tuned signature -- prefer qualified names;
wenzelm
parents: 59580
diff changeset
   284
        let val Const (trueprop, _) $ (Const (eq, _) $ _ $ rhs) = Thm.prop_of thm in
69593
3dda49e08b9d isabelle update -u control_cartouches;
wenzelm
parents: 67710
diff changeset
   285
          trueprop = \<^const_name>\<open>Trueprop\<close> andalso eq = \<^const_name>\<open>HOL.eq\<close> andalso
58913
5be251101978 generate 'size_neq' for datatypes
desharna
parents: 58738
diff changeset
   286
          rhs = HOLogic.zero
5be251101978 generate 'size_neq' for datatypes
desharna
parents: 58738
diff changeset
   287
        end;
5be251101978 generate 'size_neq' for datatypes
desharna
parents: 58738
diff changeset
   288
5be251101978 generate 'size_neq' for datatypes
desharna
parents: 58738
diff changeset
   289
      val size_neq_thmss = @{map 3} (fn fp_sugar => fn size => fn size_thms =>
62082
614ef6d7a6b6 nicer 'Spec_Rules' for size function
blanchet
parents: 61786
diff changeset
   290
        if exists rhs_is_zero size_thms then
614ef6d7a6b6 nicer 'Spec_Rules' for size function
blanchet
parents: 61786
diff changeset
   291
          []
58913
5be251101978 generate 'size_neq' for datatypes
desharna
parents: 58738
diff changeset
   292
        else
5be251101978 generate 'size_neq' for datatypes
desharna
parents: 58738
diff changeset
   293
          let
61334
8d40ddaa427f collect the names from goals in favor of fragile exports
traytel
parents: 61101
diff changeset
   294
            val (xs, _) = mk_Frees "x" (binder_types (fastype_of size)) lthy2;
58913
5be251101978 generate 'size_neq' for datatypes
desharna
parents: 58738
diff changeset
   295
            val goal =
5be251101978 generate 'size_neq' for datatypes
desharna
parents: 58738
diff changeset
   296
              HOLogic.mk_Trueprop (BNF_LFP_Util.mk_not_eq (list_comb (size, xs)) HOLogic.zero);
61334
8d40ddaa427f collect the names from goals in favor of fragile exports
traytel
parents: 61101
diff changeset
   297
            val vars = Variable.add_free_names lthy2 goal [];
58913
5be251101978 generate 'size_neq' for datatypes
desharna
parents: 58738
diff changeset
   298
            val thm =
61334
8d40ddaa427f collect the names from goals in favor of fragile exports
traytel
parents: 61101
diff changeset
   299
              Goal.prove_sorry lthy2 vars [] goal (fn {context = ctxt, ...} =>
59621
291934bac95e Thm.cterm_of and Thm.ctyp_of operate on local context;
wenzelm
parents: 59582
diff changeset
   300
                mk_size_neq ctxt (map (Thm.cterm_of lthy2) xs)
58913
5be251101978 generate 'size_neq' for datatypes
desharna
parents: 58738
diff changeset
   301
                (#exhaust (#ctr_sugar (#fp_ctr_sugar fp_sugar))) size_thms)
5be251101978 generate 'size_neq' for datatypes
desharna
parents: 58738
diff changeset
   302
              |> single
70494
41108e3e9ca5 formal position for PThm nodes;
wenzelm
parents: 69992
diff changeset
   303
              |> map (Thm.close_derivation \<^here>);
62082
614ef6d7a6b6 nicer 'Spec_Rules' for size function
blanchet
parents: 61786
diff changeset
   304
          in thm end) fp_sugars overloaded_size_consts overloaded_size_simpss;
58179
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   305
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   306
      val ABs = As ~~ Bs;
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   307
      val g_names = variant_names num_As "g";
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   308
      val gs = map2 (curry Free) g_names (map (op -->) ABs);
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   309
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   310
      val liveness = map (op <>) ABs;
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   311
      val live_gs = AList.find (op =) (gs ~~ liveness) true;
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   312
      val live = length live_gs;
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   313
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   314
      val maps0 = map map_of_bnf fp_bnfs;
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   315
58738
2af42aecc120 rename 'size_o_map' to 'size_gen_o_map'
desharna
parents: 58736
diff changeset
   316
      val size_gen_o_map_thmss =
62690
c4fad0569a24 nicer error
blanchet
parents: 62536
diff changeset
   317
        if live = 0 then
c4fad0569a24 nicer error
blanchet
parents: 62536
diff changeset
   318
          replicate nn []
58179
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   319
        else
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   320
          let
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   321
            val gmaps = map (fn map0 => Term.list_comb (mk_map live As Bs map0, live_gs)) maps0;
57631
959caab43a3d use the noted theorem whenever possible, also in 'BNF_Def'
blanchet
parents: 57399
diff changeset
   322
58738
2af42aecc120 rename 'size_o_map' to 'size_gen_o_map'
desharna
parents: 58736
diff changeset
   323
            val size_gen_o_map_conds =
2af42aecc120 rename 'size_o_map' to 'size_gen_o_map'
desharna
parents: 58736
diff changeset
   324
              if exists (can Logic.dest_implies o Thm.prop_of) nested_size_gen_o_maps then
58179
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   325
                map (HOLogic.mk_Trueprop o mk_inj) live_gs
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   326
              else
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   327
                [];
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   328
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   329
            val fsizes = map (fn size_constB => Term.list_comb (size_constB, fsB)) size_constsB;
58738
2af42aecc120 rename 'size_o_map' to 'size_gen_o_map'
desharna
parents: 58736
diff changeset
   330
            val size_gen_o_map_lhss = map2 (curry HOLogic.mk_comp) fsizes gmaps;
57631
959caab43a3d use the noted theorem whenever possible, also in 'BNF_Def'
blanchet
parents: 57399
diff changeset
   331
58179
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   332
            val fgs = map2 (fn fB => fn g as Free (_, Type (_, [A, B])) =>
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   333
              if A = B then fB else HOLogic.mk_comp (fB, g)) fsB gs;
58738
2af42aecc120 rename 'size_o_map' to 'size_gen_o_map'
desharna
parents: 58736
diff changeset
   334
            val size_gen_o_map_rhss = map (fn c => Term.list_comb (c, fgs)) size_consts;
58179
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   335
58738
2af42aecc120 rename 'size_o_map' to 'size_gen_o_map'
desharna
parents: 58736
diff changeset
   336
            val size_gen_o_map_goals =
58179
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   337
              map2 (fold_rev (fold_rev Logic.all) [fsB, gs] o
58738
2af42aecc120 rename 'size_o_map' to 'size_gen_o_map'
desharna
parents: 58736
diff changeset
   338
                curry Logic.list_implies size_gen_o_map_conds o HOLogic.mk_Trueprop oo
2af42aecc120 rename 'size_o_map' to 'size_gen_o_map'
desharna
parents: 58736
diff changeset
   339
                curry HOLogic.mk_eq) size_gen_o_map_lhss size_gen_o_map_rhss;
58179
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   340
58734
20235f0512e2 generate 'map_o_corec' for (co)datatypes
desharna
parents: 58732
diff changeset
   341
            val rec_o_maps =
63859
dca6fabd8060 make (co)induct component of 'fp_sugar' optional, for the benefit of nonuniform (co)datatypes and other similar extensions
blanchet
parents: 63239
diff changeset
   342
              fold_rev (curry (op @) o #co_rec_o_maps o the o #fp_co_induct_sugar) fp_sugars [];
58732
854eed6e5aed move theorem 'rec_o_map'
desharna
parents: 58659
diff changeset
   343
58738
2af42aecc120 rename 'size_o_map' to 'size_gen_o_map'
desharna
parents: 58736
diff changeset
   344
            val size_gen_o_map_thmss =
64532
fc2835a932d9 don't generate 'size_gen_o_map' property if its type variable is too limited anyway to be useful
blanchet
parents: 63859
diff changeset
   345
              if nested_size_gen_o_maps_complete
69593
3dda49e08b9d isabelle update -u control_cartouches;
wenzelm
parents: 67710
diff changeset
   346
                 andalso forall (fn TFree (_, S) => S = \<^sort>\<open>type\<close>) As then
58634
9f10d82e8188 added parameterized ML antiquotations @{map N}, @{fold N}, @{fold_map N}, @{split_list N};
wenzelm
parents: 58578
diff changeset
   347
                @{map 3} (fn goal => fn size_def => fn rec_o_map =>
58355
9a041a55ee95 syntactic check to determine when to prove 'nested_size_o_map'
blanchet
parents: 58353
diff changeset
   348
                    Goal.prove_sorry lthy2 [] [] goal (fn {context = ctxt, ...} =>
58738
2af42aecc120 rename 'size_o_map' to 'size_gen_o_map'
desharna
parents: 58736
diff changeset
   349
                      mk_size_gen_o_map_tac ctxt size_def rec_o_map all_inj_maps nested_size_maps)
70494
41108e3e9ca5 formal position for PThm nodes;
wenzelm
parents: 69992
diff changeset
   350
                    |> Thm.close_derivation \<^here>
58355
9a041a55ee95 syntactic check to determine when to prove 'nested_size_o_map'
blanchet
parents: 58353
diff changeset
   351
                    |> single)
58738
2af42aecc120 rename 'size_o_map' to 'size_gen_o_map'
desharna
parents: 58736
diff changeset
   352
                  size_gen_o_map_goals size_defs rec_o_maps
58355
9a041a55ee95 syntactic check to determine when to prove 'nested_size_o_map'
blanchet
parents: 58353
diff changeset
   353
              else
9a041a55ee95 syntactic check to determine when to prove 'nested_size_o_map'
blanchet
parents: 58353
diff changeset
   354
                replicate nn [];
58179
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   355
          in
58738
2af42aecc120 rename 'size_o_map' to 'size_gen_o_map'
desharna
parents: 58736
diff changeset
   356
            size_gen_o_map_thmss
58179
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   357
          end;
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   358
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   359
      val massage_multi_notes =
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   360
        maps (fn (thmN, thmss, attrs) =>
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   361
          map2 (fn T_name => fn thms =>
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   362
              ((Binding.qualify true (Long_Name.base_name T_name) (Binding.name thmN), attrs),
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   363
               [(thms, [])]))
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   364
            T_names thmss)
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   365
        #> filter_out (null o fst o hd o snd);
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   366
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   367
      val notes =
66251
cd935b7cb3fb proper concept of code declaration wrt. atomicity and Isar declarations
haftmann
parents: 64532
diff changeset
   368
        [(sizeN, size_thmss, nitpicksimp_attrs @ simp_attrs),
58736
552ccec3f00f generate 'size_gen' for datatypes
desharna
parents: 58734
diff changeset
   369
         (size_genN, size_gen_thmss, []),
58913
5be251101978 generate 'size_neq' for datatypes
desharna
parents: 58738
diff changeset
   370
         (size_gen_o_mapN, size_gen_o_map_thmss, []),
5be251101978 generate 'size_neq' for datatypes
desharna
parents: 58738
diff changeset
   371
         (size_neqN, size_neq_thmss, [])]
58179
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   372
        |> massage_multi_notes;
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   373
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   374
      val (noted, lthy3) =
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   375
        lthy2
71214
5727bcc3c47c proper spec_rule name via naming/binding/Morphism.binding;
wenzelm
parents: 71179
diff changeset
   376
        |> Spec_Rules.add Binding.empty Spec_Rules.equational size_consts size_simps
5727bcc3c47c proper spec_rule name via naming/binding/Morphism.binding;
wenzelm
parents: 71179
diff changeset
   377
        |> Spec_Rules.add Binding.empty Spec_Rules.equational
5727bcc3c47c proper spec_rule name via naming/binding/Morphism.binding;
wenzelm
parents: 71179
diff changeset
   378
            overloaded_size_consts overloaded_size_simps
66251
cd935b7cb3fb proper concept of code declaration wrt. atomicity and Isar declarations
haftmann
parents: 64532
diff changeset
   379
        |> Code.declare_default_eqns (map (rpair true) (flat size_thmss))
67314
315b5c29e927 store high-level 'size' equations
blanchet
parents: 66494
diff changeset
   380
          (*Ideally, this would be issued only if the "code" plugin is enabled.*)
58179
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   381
        |> Local_Theory.notes notes;
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   382
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   383
      val phi0 = substitute_noted_thm noted;
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   384
    in
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   385
      lthy3
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   386
      |> Local_Theory.declaration {syntax = false, pervasive = true}
62082
614ef6d7a6b6 nicer 'Spec_Rules' for size function
blanchet
parents: 61786
diff changeset
   387
        (fn phi => Data.map (@{fold 3} (fn T_name => fn Const (size_name, _) =>
614ef6d7a6b6 nicer 'Spec_Rules' for size function
blanchet
parents: 61786
diff changeset
   388
            fn overloaded_size_def =>
614ef6d7a6b6 nicer 'Spec_Rules' for size function
blanchet
parents: 61786
diff changeset
   389
               let val morph = Morphism.thm (phi0 $> phi) in
67314
315b5c29e927 store high-level 'size' equations
blanchet
parents: 66494
diff changeset
   390
                 Symtab.update (T_name, (size_name, (morph overloaded_size_def,
315b5c29e927 store high-level 'size' equations
blanchet
parents: 66494
diff changeset
   391
                   map morph overloaded_size_simps, maps (map morph) size_gen_o_map_thmss)))
62082
614ef6d7a6b6 nicer 'Spec_Rules' for size function
blanchet
parents: 61786
diff changeset
   392
               end)
614ef6d7a6b6 nicer 'Spec_Rules' for size function
blanchet
parents: 61786
diff changeset
   393
           T_names size_consts overloaded_size_defs))
58179
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   394
    end
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   395
  | generate_datatype_size _ lthy = lthy;
2de7b0313de3 tuned size function generation
blanchet
parents: 58128
diff changeset
   396
69593
3dda49e08b9d isabelle update -u control_cartouches;
wenzelm
parents: 67710
diff changeset
   397
val size_plugin = Plugin_Name.declare_setup \<^binding>\<open>size\<close>;
58659
6c9821c32dd5 Local_Interpretation is superseded by Plugin with formal Plugin_Name management, avoiding undeclared strings;
wenzelm
parents: 58634
diff changeset
   398
val _ = Theory.setup (fp_sugars_interpretation size_plugin generate_datatype_size);
56638
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   399
092a306bcc3d generate size instances for new-style datatypes
blanchet
parents:
diff changeset
   400
end;