src/HOL/Tools/function_package/size.ML
author haftmann
Fri, 07 Dec 2007 15:07:54 +0100
changeset 25569 c597835d5de4
parent 25539 8b7ed8aef001
child 25679 b77f797b528a
permissions -rw-r--r--
dropped Instance.instantiate
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
24710
141df8b68f63 size hook
haftmann
parents:
diff changeset
     1
(*  Title:      HOL/Tools/function_package/size.ML
141df8b68f63 size hook
haftmann
parents:
diff changeset
     2
    ID:         $Id$
141df8b68f63 size hook
haftmann
parents:
diff changeset
     3
    Author:     Stefan Berghofer, Florian Haftmann, TU Muenchen
141df8b68f63 size hook
haftmann
parents:
diff changeset
     4
141df8b68f63 size hook
haftmann
parents:
diff changeset
     5
Size functions for datatypes.
141df8b68f63 size hook
haftmann
parents:
diff changeset
     6
*)
141df8b68f63 size hook
haftmann
parents:
diff changeset
     7
141df8b68f63 size hook
haftmann
parents:
diff changeset
     8
signature SIZE =
141df8b68f63 size hook
haftmann
parents:
diff changeset
     9
sig
141df8b68f63 size hook
haftmann
parents:
diff changeset
    10
  val size_thms: theory -> string -> thm list
141df8b68f63 size hook
haftmann
parents:
diff changeset
    11
  val setup: theory -> theory
141df8b68f63 size hook
haftmann
parents:
diff changeset
    12
end;
141df8b68f63 size hook
haftmann
parents:
diff changeset
    13
141df8b68f63 size hook
haftmann
parents:
diff changeset
    14
structure Size: SIZE =
141df8b68f63 size hook
haftmann
parents:
diff changeset
    15
struct
141df8b68f63 size hook
haftmann
parents:
diff changeset
    16
141df8b68f63 size hook
haftmann
parents:
diff changeset
    17
open DatatypeAux;
141df8b68f63 size hook
haftmann
parents:
diff changeset
    18
24714
1618c2ac1b74 proper Sign operations instead of Theory aliases;
wenzelm
parents: 24711
diff changeset
    19
structure SizeData = TheoryDataFun
1618c2ac1b74 proper Sign operations instead of Theory aliases;
wenzelm
parents: 24711
diff changeset
    20
(
24710
141df8b68f63 size hook
haftmann
parents:
diff changeset
    21
  type T = thm list Symtab.table;
141df8b68f63 size hook
haftmann
parents:
diff changeset
    22
  val empty = Symtab.empty;
141df8b68f63 size hook
haftmann
parents:
diff changeset
    23
  val copy = I
141df8b68f63 size hook
haftmann
parents:
diff changeset
    24
  val extend = I
141df8b68f63 size hook
haftmann
parents:
diff changeset
    25
  fun merge _ = Symtab.merge (K true);
24714
1618c2ac1b74 proper Sign operations instead of Theory aliases;
wenzelm
parents: 24711
diff changeset
    26
);
24710
141df8b68f63 size hook
haftmann
parents:
diff changeset
    27
141df8b68f63 size hook
haftmann
parents:
diff changeset
    28
fun add_axioms label ts atts thy =
141df8b68f63 size hook
haftmann
parents:
diff changeset
    29
  thy
141df8b68f63 size hook
haftmann
parents:
diff changeset
    30
  |> PureThy.add_axiomss_i [((label, ts), atts)];
141df8b68f63 size hook
haftmann
parents:
diff changeset
    31
141df8b68f63 size hook
haftmann
parents:
diff changeset
    32
val Const (size_name, _) = HOLogic.size_const dummyT;
141df8b68f63 size hook
haftmann
parents:
diff changeset
    33
val size_name_base = NameSpace.base size_name;
141df8b68f63 size hook
haftmann
parents:
diff changeset
    34
val size_suffix = "_" ^ size_name_base;
141df8b68f63 size hook
haftmann
parents:
diff changeset
    35
25569
c597835d5de4 dropped Instance.instantiate
haftmann
parents: 25539
diff changeset
    36
fun instance_size_class tyco thy =
c597835d5de4 dropped Instance.instantiate
haftmann
parents: 25539
diff changeset
    37
  thy
c597835d5de4 dropped Instance.instantiate
haftmann
parents: 25539
diff changeset
    38
  |> TheoryTarget.instantiation
c597835d5de4 dropped Instance.instantiate
haftmann
parents: 25539
diff changeset
    39
       ([tyco], replicate (Sign.arity_number thy tyco) HOLogic.typeS, [HOLogic.class_size])
c597835d5de4 dropped Instance.instantiate
haftmann
parents: 25539
diff changeset
    40
  |> Class.prove_instantiation_instance (K (Class.intro_classes_tac []))
c597835d5de4 dropped Instance.instantiate
haftmann
parents: 25539
diff changeset
    41
  |> LocalTheory.exit
c597835d5de4 dropped Instance.instantiate
haftmann
parents: 25539
diff changeset
    42
  |> ProofContext.theory_of;
24710
141df8b68f63 size hook
haftmann
parents:
diff changeset
    43
141df8b68f63 size hook
haftmann
parents:
diff changeset
    44
fun plus (t1, t2) = Const ("HOL.plus_class.plus",
141df8b68f63 size hook
haftmann
parents:
diff changeset
    45
  HOLogic.natT --> HOLogic.natT --> HOLogic.natT) $ t1 $ t2;
141df8b68f63 size hook
haftmann
parents:
diff changeset
    46
141df8b68f63 size hook
haftmann
parents:
diff changeset
    47
fun make_size head_len descr' sorts recTs thy =
141df8b68f63 size hook
haftmann
parents:
diff changeset
    48
  let
141df8b68f63 size hook
haftmann
parents:
diff changeset
    49
    val size_names = replicate head_len size_name @
25155
65612c9f7381 dropped code redundancy
haftmann
parents: 25017
diff changeset
    50
      map (Sign.intern_const thy) (DatatypeProp.indexify_names
24710
141df8b68f63 size hook
haftmann
parents:
diff changeset
    51
        (map (fn T => name_of_typ T ^ size_suffix) (Library.drop (head_len, recTs))));
141df8b68f63 size hook
haftmann
parents:
diff changeset
    52
    val size_consts = map2 (fn s => fn T => Const (s, T --> HOLogic.natT))
141df8b68f63 size hook
haftmann
parents:
diff changeset
    53
      size_names recTs;
141df8b68f63 size hook
haftmann
parents:
diff changeset
    54
141df8b68f63 size hook
haftmann
parents:
diff changeset
    55
    fun make_tnames Ts =
141df8b68f63 size hook
haftmann
parents:
diff changeset
    56
      let
141df8b68f63 size hook
haftmann
parents:
diff changeset
    57
        fun type_name (TFree (name, _)) = implode (tl (explode name))
141df8b68f63 size hook
haftmann
parents:
diff changeset
    58
          | type_name (Type (name, _)) = 
141df8b68f63 size hook
haftmann
parents:
diff changeset
    59
              let val name' = Sign.base_name name
141df8b68f63 size hook
haftmann
parents:
diff changeset
    60
              in if Syntax.is_identifier name' then name' else "x" end;
25155
65612c9f7381 dropped code redundancy
haftmann
parents: 25017
diff changeset
    61
      in DatatypeProp.indexify_names (map type_name Ts) end;
24710
141df8b68f63 size hook
haftmann
parents:
diff changeset
    62
141df8b68f63 size hook
haftmann
parents:
diff changeset
    63
    fun make_size_eqn size_const T (cname, cargs) =
141df8b68f63 size hook
haftmann
parents:
diff changeset
    64
      let
141df8b68f63 size hook
haftmann
parents:
diff changeset
    65
        val recs = filter is_rec_type cargs;
141df8b68f63 size hook
haftmann
parents:
diff changeset
    66
        val Ts = map (typ_of_dtyp descr' sorts) cargs;
141df8b68f63 size hook
haftmann
parents:
diff changeset
    67
        val recTs = map (typ_of_dtyp descr' sorts) recs;
141df8b68f63 size hook
haftmann
parents:
diff changeset
    68
        val tnames = make_tnames Ts;
141df8b68f63 size hook
haftmann
parents:
diff changeset
    69
        val rec_tnames = map fst (filter (is_rec_type o snd) (tnames ~~ cargs));
141df8b68f63 size hook
haftmann
parents:
diff changeset
    70
        val ts = map2 (fn (r, s) => fn T => nth size_consts (dest_DtRec r) $
141df8b68f63 size hook
haftmann
parents:
diff changeset
    71
          Free (s, T)) (recs ~~ rec_tnames) recTs;
141df8b68f63 size hook
haftmann
parents:
diff changeset
    72
        val t = if null ts then HOLogic.zero else
141df8b68f63 size hook
haftmann
parents:
diff changeset
    73
          Library.foldl plus (hd ts, tl ts @ [HOLogic.Suc_zero]);
141df8b68f63 size hook
haftmann
parents:
diff changeset
    74
      in
141df8b68f63 size hook
haftmann
parents:
diff changeset
    75
        HOLogic.mk_Trueprop (HOLogic.mk_eq (size_const $
141df8b68f63 size hook
haftmann
parents:
diff changeset
    76
          list_comb (Const (cname, Ts ---> T), map2 (curry Free) tnames Ts), t))
141df8b68f63 size hook
haftmann
parents:
diff changeset
    77
      end
141df8b68f63 size hook
haftmann
parents:
diff changeset
    78
141df8b68f63 size hook
haftmann
parents:
diff changeset
    79
  in
141df8b68f63 size hook
haftmann
parents:
diff changeset
    80
    maps (fn (((_, (_, _, constrs)), size_const), T) =>
141df8b68f63 size hook
haftmann
parents:
diff changeset
    81
      map (make_size_eqn size_const T) constrs) (descr' ~~ size_consts ~~ recTs)
141df8b68f63 size hook
haftmann
parents:
diff changeset
    82
  end;
141df8b68f63 size hook
haftmann
parents:
diff changeset
    83
141df8b68f63 size hook
haftmann
parents:
diff changeset
    84
fun prove_size_thms (info : datatype_info) head_len thy =
141df8b68f63 size hook
haftmann
parents:
diff changeset
    85
  let
141df8b68f63 size hook
haftmann
parents:
diff changeset
    86
    val descr' = #descr info;
141df8b68f63 size hook
haftmann
parents:
diff changeset
    87
    val sorts = #sorts info;
141df8b68f63 size hook
haftmann
parents:
diff changeset
    88
    val reccomb_names = #rec_names info;
141df8b68f63 size hook
haftmann
parents:
diff changeset
    89
    val primrec_thms = #rec_rewrites info;
141df8b68f63 size hook
haftmann
parents:
diff changeset
    90
    val recTs = get_rec_types descr' sorts;
141df8b68f63 size hook
haftmann
parents:
diff changeset
    91
141df8b68f63 size hook
haftmann
parents:
diff changeset
    92
    val size_names = replicate head_len size_name @
141df8b68f63 size hook
haftmann
parents:
diff changeset
    93
      map (Sign.full_name thy) (DatatypeProp.indexify_names
141df8b68f63 size hook
haftmann
parents:
diff changeset
    94
        (map (fn T => name_of_typ T ^ size_suffix) (Library.drop (head_len, recTs))));
141df8b68f63 size hook
haftmann
parents:
diff changeset
    95
    val def_names = map (fn s => s ^ "_def") (DatatypeProp.indexify_names
141df8b68f63 size hook
haftmann
parents:
diff changeset
    96
      (map (fn T => name_of_typ T ^ size_suffix) recTs));
141df8b68f63 size hook
haftmann
parents:
diff changeset
    97
141df8b68f63 size hook
haftmann
parents:
diff changeset
    98
    fun make_sizefun (_, cargs) =
141df8b68f63 size hook
haftmann
parents:
diff changeset
    99
      let
141df8b68f63 size hook
haftmann
parents:
diff changeset
   100
        val Ts = map (typ_of_dtyp descr' sorts) cargs;
141df8b68f63 size hook
haftmann
parents:
diff changeset
   101
        val k = length (filter is_rec_type cargs);
141df8b68f63 size hook
haftmann
parents:
diff changeset
   102
        val ts = map Bound (k - 1 downto 0);
141df8b68f63 size hook
haftmann
parents:
diff changeset
   103
        val t = if null ts then HOLogic.zero else
141df8b68f63 size hook
haftmann
parents:
diff changeset
   104
          Library.foldl plus (hd ts, tl ts @ [HOLogic.Suc_zero]);
141df8b68f63 size hook
haftmann
parents:
diff changeset
   105
141df8b68f63 size hook
haftmann
parents:
diff changeset
   106
      in
141df8b68f63 size hook
haftmann
parents:
diff changeset
   107
        foldr (fn (T, t') => Abs ("x", T, t')) t (Ts @ replicate k HOLogic.natT)
141df8b68f63 size hook
haftmann
parents:
diff changeset
   108
      end;
141df8b68f63 size hook
haftmann
parents:
diff changeset
   109
141df8b68f63 size hook
haftmann
parents:
diff changeset
   110
    val fs = maps (fn (_, (_, _, constrs)) => map make_sizefun constrs) descr';
141df8b68f63 size hook
haftmann
parents:
diff changeset
   111
    val fTs = map fastype_of fs;
141df8b68f63 size hook
haftmann
parents:
diff changeset
   112
141df8b68f63 size hook
haftmann
parents:
diff changeset
   113
    val (size_def_thms, thy') =
141df8b68f63 size hook
haftmann
parents:
diff changeset
   114
      thy
24714
1618c2ac1b74 proper Sign operations instead of Theory aliases;
wenzelm
parents: 24711
diff changeset
   115
      |> Sign.add_consts_i (map (fn (s, T) =>
24710
141df8b68f63 size hook
haftmann
parents:
diff changeset
   116
           (Sign.base_name s, T --> HOLogic.natT, NoSyn))
141df8b68f63 size hook
haftmann
parents:
diff changeset
   117
           (Library.drop (head_len, size_names ~~ recTs)))
141df8b68f63 size hook
haftmann
parents:
diff changeset
   118
      |> fold (fn (_, (name, _, _)) => instance_size_class name) descr'
141df8b68f63 size hook
haftmann
parents:
diff changeset
   119
      |> PureThy.add_defs_i true (map (Thm.no_attributes o (fn (((s, T), def_name), rec_name) =>
141df8b68f63 size hook
haftmann
parents:
diff changeset
   120
           (def_name, Logic.mk_equals (Const (s, T --> HOLogic.natT),
141df8b68f63 size hook
haftmann
parents:
diff changeset
   121
            list_comb (Const (rec_name, fTs @ [T] ---> HOLogic.natT), fs)))))
141df8b68f63 size hook
haftmann
parents:
diff changeset
   122
            (size_names ~~ recTs ~~ def_names ~~ reccomb_names));
141df8b68f63 size hook
haftmann
parents:
diff changeset
   123
141df8b68f63 size hook
haftmann
parents:
diff changeset
   124
    val rewrites = size_def_thms @ map mk_meta_eq primrec_thms;
141df8b68f63 size hook
haftmann
parents:
diff changeset
   125
141df8b68f63 size hook
haftmann
parents:
diff changeset
   126
    val size_thms = map (fn t => Goal.prove_global thy' [] [] t
141df8b68f63 size hook
haftmann
parents:
diff changeset
   127
      (fn _ => EVERY [rewrite_goals_tac rewrites, rtac refl 1]))
141df8b68f63 size hook
haftmann
parents:
diff changeset
   128
        (make_size head_len descr' sorts recTs thy')
141df8b68f63 size hook
haftmann
parents:
diff changeset
   129
141df8b68f63 size hook
haftmann
parents:
diff changeset
   130
  in
141df8b68f63 size hook
haftmann
parents:
diff changeset
   131
    thy'
141df8b68f63 size hook
haftmann
parents:
diff changeset
   132
    |> PureThy.add_thmss [((size_name_base, size_thms), [])]
141df8b68f63 size hook
haftmann
parents:
diff changeset
   133
    |>> flat
141df8b68f63 size hook
haftmann
parents:
diff changeset
   134
  end;
141df8b68f63 size hook
haftmann
parents:
diff changeset
   135
141df8b68f63 size hook
haftmann
parents:
diff changeset
   136
fun axiomatize_size_thms (info : datatype_info) head_len thy =
141df8b68f63 size hook
haftmann
parents:
diff changeset
   137
  let
141df8b68f63 size hook
haftmann
parents:
diff changeset
   138
    val descr' = #descr info;
141df8b68f63 size hook
haftmann
parents:
diff changeset
   139
    val sorts = #sorts info;
141df8b68f63 size hook
haftmann
parents:
diff changeset
   140
    val recTs = get_rec_types descr' sorts;
141df8b68f63 size hook
haftmann
parents:
diff changeset
   141
141df8b68f63 size hook
haftmann
parents:
diff changeset
   142
    val used = map fst (fold Term.add_tfreesT recTs []);
141df8b68f63 size hook
haftmann
parents:
diff changeset
   143
141df8b68f63 size hook
haftmann
parents:
diff changeset
   144
    val size_names = DatatypeProp.indexify_names
141df8b68f63 size hook
haftmann
parents:
diff changeset
   145
      (map (fn T => name_of_typ T ^ size_suffix) (Library.drop (head_len, recTs)));
141df8b68f63 size hook
haftmann
parents:
diff changeset
   146
24962
60d33fb8ea5d Theory.specify_const;
wenzelm
parents: 24770
diff changeset
   147
    val thy' = thy |> fold (fn (s, T) =>
25017
e82ab4962f80 Theory.specify_const: added deps argument;
wenzelm
parents: 24962
diff changeset
   148
        snd o Theory.specify_const [] (Sign.base_name s, T --> HOLogic.natT, NoSyn) [])
24962
60d33fb8ea5d Theory.specify_const;
wenzelm
parents: 24770
diff changeset
   149
      (size_names ~~ Library.drop (head_len, recTs))
24710
141df8b68f63 size hook
haftmann
parents:
diff changeset
   150
    val size_axs = make_size head_len descr' sorts recTs thy';
141df8b68f63 size hook
haftmann
parents:
diff changeset
   151
  in
141df8b68f63 size hook
haftmann
parents:
diff changeset
   152
    thy'
141df8b68f63 size hook
haftmann
parents:
diff changeset
   153
    |> add_axioms size_name_base size_axs []
141df8b68f63 size hook
haftmann
parents:
diff changeset
   154
    ||> fold (fn (_, (name, _, _)) => instance_size_class name) descr'
141df8b68f63 size hook
haftmann
parents:
diff changeset
   155
    |>> flat
141df8b68f63 size hook
haftmann
parents:
diff changeset
   156
  end;
141df8b68f63 size hook
haftmann
parents:
diff changeset
   157
141df8b68f63 size hook
haftmann
parents:
diff changeset
   158
fun add_size_thms (name :: _) thy =
141df8b68f63 size hook
haftmann
parents:
diff changeset
   159
  let
141df8b68f63 size hook
haftmann
parents:
diff changeset
   160
    val info = DatatypePackage.the_datatype thy name;
141df8b68f63 size hook
haftmann
parents:
diff changeset
   161
    val descr' = #descr info;
141df8b68f63 size hook
haftmann
parents:
diff changeset
   162
    val head_len = #head_len info;
141df8b68f63 size hook
haftmann
parents:
diff changeset
   163
    val typnames = map (#1 o snd) (curry Library.take head_len descr');
141df8b68f63 size hook
haftmann
parents:
diff changeset
   164
    val prefix = space_implode "_" (map NameSpace.base typnames);
141df8b68f63 size hook
haftmann
parents:
diff changeset
   165
    val no_size = exists (fn (_, (_, _, constrs)) => exists (fn (_, cargs) => exists (fn dt =>
141df8b68f63 size hook
haftmann
parents:
diff changeset
   166
      is_rec_type dt andalso not (null (fst (strip_dtyp dt)))) cargs) constrs)
141df8b68f63 size hook
haftmann
parents:
diff changeset
   167
        (#descr info)
141df8b68f63 size hook
haftmann
parents:
diff changeset
   168
  in if no_size then thy
141df8b68f63 size hook
haftmann
parents:
diff changeset
   169
    else
141df8b68f63 size hook
haftmann
parents:
diff changeset
   170
      thy
24714
1618c2ac1b74 proper Sign operations instead of Theory aliases;
wenzelm
parents: 24711
diff changeset
   171
      |> Sign.add_path prefix
24710
141df8b68f63 size hook
haftmann
parents:
diff changeset
   172
      |> (if ! quick_and_dirty
141df8b68f63 size hook
haftmann
parents:
diff changeset
   173
        then axiomatize_size_thms info head_len
141df8b68f63 size hook
haftmann
parents:
diff changeset
   174
        else prove_size_thms info head_len)
24714
1618c2ac1b74 proper Sign operations instead of Theory aliases;
wenzelm
parents: 24711
diff changeset
   175
      ||> Sign.parent_path
24710
141df8b68f63 size hook
haftmann
parents:
diff changeset
   176
      |-> (fn thms => PureThy.add_thmss [(("", thms),
141df8b68f63 size hook
haftmann
parents:
diff changeset
   177
            [Simplifier.simp_add, Thm.declaration_attribute
141df8b68f63 size hook
haftmann
parents:
diff changeset
   178
              (fn thm => Context.mapping (Code.add_default_func thm) I)])])
141df8b68f63 size hook
haftmann
parents:
diff changeset
   179
      |-> (fn thms => SizeData.map (fold (fn typname => Symtab.update_new
141df8b68f63 size hook
haftmann
parents:
diff changeset
   180
            (typname, flat thms)) typnames))
141df8b68f63 size hook
haftmann
parents:
diff changeset
   181
  end;
141df8b68f63 size hook
haftmann
parents:
diff changeset
   182
141df8b68f63 size hook
haftmann
parents:
diff changeset
   183
fun size_thms thy = the o Symtab.lookup (SizeData.get thy);
141df8b68f63 size hook
haftmann
parents:
diff changeset
   184
24711
e8bba7723858 simplified interpretation setup;
wenzelm
parents: 24710
diff changeset
   185
val setup = DatatypePackage.interpretation add_size_thms;
24710
141df8b68f63 size hook
haftmann
parents:
diff changeset
   186
141df8b68f63 size hook
haftmann
parents:
diff changeset
   187
end;