src/HOL/record.ML
author paulson
Sat, 10 Jan 1998 17:59:32 +0100
changeset 4552 bb8ff763c93d
parent 4459 4066db36616b
child 4564 dc45cf21dbd2
permissions -rw-r--r--
Simplified proofs by omitting PA = {|XA, ...|} from RA2
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
4454
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
     1
(*  Title:      HOL/record.ML
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
     2
    ID:         $Id$
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
     3
    Author:     Wolfgang Naraschewski and Markus Wenzel, TU Muenchen
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
     4
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
     5
Internal interface for records.
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
     6
*)
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
     7
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
     8
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
     9
signature RECORD =
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    10
sig
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    11
  val add_record: 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    12
    (string list * bstring) -> string option -> 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    13
      (bstring * string) list -> theory -> theory
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    14
  val add_record_i: 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    15
    (string list * bstring) -> (typ list * string) option -> 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    16
      (bstring * typ) list -> theory -> theory
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    17
end;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    18
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    19
structure Record: RECORD =
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    20
struct
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    21
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    22
val base = Sign.base_name; 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    23
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    24
(* FIXME move to Pure/library.ML *)
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    25
fun set_minus xs [] = xs
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    26
  | set_minus xs (y::ys) = set_minus (xs \ y) ys;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    27
(* FIXME *)
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    28
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    29
(* FIXME move to Pure/sign.ML *)
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    30
fun of_sort sg = 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    31
  Sorts.of_sort 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    32
    (#classrel (Type.rep_tsig (#tsig (Sign.rep_sg sg))))
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    33
    (#arities (Type.rep_tsig (#tsig (Sign.rep_sg sg))));
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    34
(* FIXME *)
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    35
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    36
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    37
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    38
(** record info **)
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    39
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    40
fun get_record thy name = 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    41
  let val table = ThyData.get_records thy
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    42
  in
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    43
    Symtab.lookup (table, name)
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    44
  end;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    45
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    46
fun put_record thy name info = 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    47
  let val table = ThyData.get_records thy 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    48
  in
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    49
    ThyData.put_records (Symtab.update ((name, info), table))
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    50
  end;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    51
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    52
local
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    53
  fun record_infos thy None = []
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    54
    | record_infos thy (Some info) =
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    55
        case #parent info of 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    56
            None => [info]
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    57
          | Some (_, parent) => record_infos thy (get_record thy parent) @ [info];
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    58
  fun record_parass thy info = 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    59
    (map (map (fn (str, _) => (str, 0)) o #args) (record_infos thy (Some info))) 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    60
    : indexname list list; 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    61
  fun record_argss thy info = 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    62
    map (fst o the) (tl (map #parent (record_infos thy (Some info)))) @ 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    63
    [map TFree (#args info)];
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    64
in  
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    65
  fun record_field_names thy info = 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    66
    flat (map (map fst o #fields) (record_infos thy (Some info)));
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    67
  fun record_field_types thy info = 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    68
    let 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    69
      val paras_args = map (op ~~) (record_parass thy info ~~ record_argss thy info);
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    70
      val raw_substs = map typ_subst_TVars paras_args;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    71
      fun make_substs [] = []
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    72
        | make_substs (x::xs) = (foldr1 (op o) (x::xs)) :: make_substs xs; 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    73
      val free_TFree = map (map (map_type_tfree (fn (str, s) => TVar((str, 0), s))));
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    74
      val raw_record_field_types = map (map snd o #fields) (record_infos thy (Some info))
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    75
    in 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    76
      flat (ListPair.map (fn (s, ts) => map s ts) 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    77
                         (make_substs raw_substs, free_TFree raw_record_field_types))
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    78
    end;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    79
end;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    80
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    81
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    82
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    83
(** abstract syntax **)
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    84
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    85
(* tuples *)
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    86
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    87
val unitT = Type ("unit",[]);
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    88
val unit = Const ("()",unitT);
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    89
fun mk_prodT (T1, T2) = Type ("*", [T1,T2]);
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    90
fun mk_Pair (t1, t2) = 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    91
  let val T1 = fastype_of t1
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    92
      and T2 = fastype_of t2
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    93
  in Const ("Pair", [T1, T2] ---> mk_prodT (T1,T2)) $ t1 $ t2  end;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    94
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    95
fun dest_prodT (Type ("*", [T1, T2])) = (T1, T2)
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    96
  | dest_prodT T = raise TYPE ("dest_prodT: product type expected", [T], []);
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    97
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    98
fun mk_fst pT = Const ("fst", pT --> fst (dest_prodT pT));
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
    99
fun mk_snd pT = Const ("snd", pT --> snd (dest_prodT pT));
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   100
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   101
fun ap_fst t = mk_fst (fastype_of t) $ t;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   102
fun ap_snd t = mk_snd (fastype_of t) $ t;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   103
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   104
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   105
(* records *)
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   106
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   107
fun selT T recT = recT --> T; 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   108
fun updateT T recT = T --> recT --> recT;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   109
val base_free = Free o apfst base;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   110
val make_scheme_name = "make_scheme";
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   111
val make_name = "make";
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   112
val update_suffix = "_update";
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   113
fun make_schemeC full make_schemeT = Const (full make_scheme_name, make_schemeT);
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   114
fun makeC full makeT = Const (full make_name, makeT);
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   115
fun selC s T recT = Const (s, selT T recT);
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   116
fun updateC full s T recT = Const (full (base s ^ update_suffix), updateT T recT);
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   117
fun frees xs = foldr add_typ_tfree_names (xs, []);
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   118
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   119
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   120
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   121
(** constants, definitions, axioms **)
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   122
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   123
(* constant declarations for make, selectors and update *)
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   124
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   125
fun decls make_schemeT makeT selT updateT recT current_fields =
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   126
  let val make_scheme_decl = (make_scheme_name, make_schemeT, NoSyn);
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   127
      val make_decl = (make_name, makeT, NoSyn);
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   128
      val sel_decls = map (fn (c, T) => (c, selT T recT, NoSyn)) current_fields;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   129
      val update_decls = 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   130
        map (fn (c, T) => (c ^ update_suffix, updateT T recT, NoSyn)) current_fields
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   131
  in 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   132
    make_scheme_decl :: make_decl :: sel_decls @ update_decls
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   133
  end;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   134
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   135
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   136
(* definitions for make, selectors and update *)
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   137
 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   138
(*make*)
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   139
fun make_defs make_schemeT makeT base_frees z thy =
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   140
  let
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   141
    val sign = sign_of thy;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   142
    val full = Sign.full_name sign;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   143
    val make_args_scheme = list_comb (make_schemeC full make_schemeT, base_frees) $ z;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   144
    val make_args = list_comb (makeC full makeT, base_frees); 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   145
    val make_scheme_def = 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   146
      mk_defpair (make_args_scheme, foldr mk_Pair (base_frees, z));
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   147
    val make_def = 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   148
      mk_defpair (make_args, foldr mk_Pair (base_frees, unit))
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   149
  in
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   150
    make_scheme_def :: [make_def]
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   151
  end;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   152
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   153
(*selectors*)
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   154
fun sel_defs recT r all_fields current_fullfields = 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   155
  let 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   156
    val prefix_len = length all_fields  - length current_fullfields;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   157
    val sel_terms = 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   158
        map (fn k => ap_fst o funpow k ap_snd)
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   159
            (prefix_len upto length all_fields - 1)
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   160
  in
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   161
    ListPair.map 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   162
      (fn ((s, T), t) => mk_defpair (selC s T recT $ r, t r)) 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   163
      (current_fullfields, sel_terms)
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   164
  end;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   165
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   166
(*update*)
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   167
fun update_defs recT r all_fields current_fullfields thy = 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   168
  let
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   169
    val sign = sign_of thy;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   170
    val full = Sign.full_name sign;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   171
    val len_all_fields = length all_fields;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   172
    fun sel_last r = funpow len_all_fields ap_snd r;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   173
    fun update_def_s (s, T) = 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   174
      let val updates = map (fn (s', T') => 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   175
        if s = s' then base_free (s, T) else selC s' T' recT $ r)
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   176
        all_fields
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   177
      in
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   178
        mk_defpair (updateC full s T recT $ base_free (s, T) $ r,
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   179
                    foldr mk_Pair (updates, sel_last r)) 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   180
      end;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   181
  in 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   182
    map update_def_s current_fullfields 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   183
  end
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   184
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   185
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   186
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   187
(** errors **)
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   188
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   189
fun check_duplicate_fields all_field_names =
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   190
  let val has_dupl = findrep all_field_names
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   191
  in
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   192
    if null has_dupl then []
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   193
      else ["Duplicate field declaration: " ^ quote (hd has_dupl) ^
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   194
            " (Double might be in ancestor)"]
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   195
  end;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   196
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   197
fun check_parent None name thy = []
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   198
  | check_parent (Some (args, parent)) name thy = 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   199
     let 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   200
       val opt_info = get_record thy parent;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   201
       val sign = sign_of thy;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   202
       fun check_sorts [] [] = []
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   203
         | check_sorts ((str, sort)::xs) (y::ys) = 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   204
            if of_sort sign (y, sort)
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   205
              then check_sorts xs ys 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   206
              else ["Sort of " ^ 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   207
                    quote (Pretty.string_of (Sign.pretty_typ sign y)) ^ 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   208
                    " does not match parent declaration"] 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   209
     in 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   210
       case opt_info of 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   211
         None => ["Parent " ^ quote parent ^" not defined"]
4459
4066db36616b records without signature
narasche
parents: 4454
diff changeset
   212
       | Some {args = pargs, parent = pparent, fields = pfields} =>
4454
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   213
           if (length args = length pargs) 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   214
             then check_sorts pargs args
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   215
             else ["Mismatching arities for parent " ^ quote (base parent)] 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   216
     end;    
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   217
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   218
fun check_duplicate_records thy full_name =
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   219
  if is_none (get_record thy full_name) then [] 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   220
    else ["Duplicate record declaration"];
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   221
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   222
fun check_duplicate_args raw_args =
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   223
  let val has_dupl = findrep raw_args
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   224
  in
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   225
    if null has_dupl then []
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   226
      else ["Duplicate parameter: " ^ quote (hd has_dupl)]
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   227
  end;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   228
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   229
fun check_raw_args raw_args free_vars thy = 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   230
  let
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   231
    val free_vars_names = map fst free_vars;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   232
    val diff_set = set_minus free_vars_names raw_args;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   233
    val default_sort =  Type.defaultS ((#tsig o Sign.rep_sg) (sign_of thy));
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   234
    val assign_sorts = 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   235
      map (fn x => case assoc (free_vars, x) of
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   236
                     None => (x, default_sort)
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   237
                   | Some sort => (x, sort)) raw_args
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   238
  in
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   239
    if free_vars_names subset raw_args 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   240
      then ([], assign_sorts)
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   241
      else (["Free type variable(s): " ^ 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   242
               (foldr1 (fn (s, s') => s ^ ", " ^ s') (map quote diff_set))],
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   243
            []) 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   244
  end;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   245
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   246
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   247
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   248
(** ext_record **)
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   249
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   250
fun ext_record (args, name) opt_parent current_fields thy =
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   251
  let
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   252
    val full_name = Sign.full_name (sign_of thy) name;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   253
    val thy = thy |> Theory.add_path name;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   254
    val sign = sign_of thy;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   255
    val full = Sign.full_name sign;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   256
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   257
    val current_fullfields = map (apfst full) current_fields;
4459
4066db36616b records without signature
narasche
parents: 4454
diff changeset
   258
    val info = {args = args, fields = current_fullfields, parent = opt_parent};
4454
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   259
    val thy = thy |> put_record thy full_name info;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   260
    val all_types = record_field_types thy info; 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   261
    val all_fields = record_field_names thy info ~~ all_types;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   262
    val base_frees = map base_free all_fields;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   263
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   264
    val tfrees = frees all_types;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   265
    val zeta = variant tfrees "'z";
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   266
    val zetaT = TFree (zeta, HOLogic.termS); 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   267
    val z = base_free ("z", zetaT);
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   268
    val recT = foldr mk_prodT (all_types, zetaT);
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   269
    val recT_unitT = foldr mk_prodT (all_types, unitT);
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   270
    val make_schemeT = (all_types @ [zetaT]) ---> recT;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   271
    val makeT = all_types ---> recT_unitT;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   272
    val r = base_free ("r", recT);
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   273
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   274
    val errors = check_duplicate_fields (map base (record_field_names thy info))
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   275
  in
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   276
    if not (null errors) 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   277
      then error (cat_lines errors) else 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   278
        thy |> Theory.add_path ".."
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   279
            |> Theory.add_tyabbrs_i [(name, tfrees @ [zeta], recT, NoSyn)]  
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   280
            |> Theory.add_path name
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   281
            |> Theory.add_consts_i (decls make_schemeT makeT selT updateT recT current_fields)
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   282
            |> Theory.add_defs_i 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   283
                  ((make_defs make_schemeT makeT base_frees z thy) @ 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   284
                   (sel_defs recT r all_fields current_fullfields) @
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   285
                   (update_defs recT r all_fields current_fullfields thy))
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   286
            |> Theory.add_path ".." 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   287
  end;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   288
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   289
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   290
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   291
(** external interfaces **)
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   292
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   293
(* add_record *)
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   294
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   295
fun add_record_aux prep_typ prep_parent (raw_args, name) raw_parent raw_fields thy =
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   296
  let
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   297
    val _ = require_thy thy "Prod" "record definitions";
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   298
    val sign = sign_of thy;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   299
    val full_name = Sign.full_name sign name;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   300
    val make_assocs = map (fn (a, b) => ((a, ~1), b));
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   301
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   302
    val parent = apsome (prep_parent sign) raw_parent;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   303
    val parent_args = if_none (apsome fst parent) [];
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   304
    val parent_assoc = make_assocs (foldr (op union) ((map typ_tfrees parent_args), []));
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   305
 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   306
    fun prepare_fields ass [] = []
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   307
      | prepare_fields ass ((name, str)::xs) = 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   308
         let val type_of_name = prep_typ sign ass str
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   309
         in (name, type_of_name)::
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   310
              (prepare_fields (ass union (make_assocs (typ_tfrees type_of_name))) xs)
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   311
         end;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   312
    val fields = prepare_fields (parent_assoc) raw_fields;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   313
    val fields_types = map snd fields;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   314
    val free_vars = foldr (op union) ((map typ_tfrees fields_types), []);
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   315
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   316
    val check_args = check_raw_args raw_args free_vars thy;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   317
    val args = snd check_args;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   318
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   319
    val errors = (check_parent parent name thy) @ 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   320
                 (check_duplicate_records thy full_name) @
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   321
                 (check_duplicate_args raw_args) @
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   322
                 (fst check_args)
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   323
  in 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   324
    if not (null errors) 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   325
      then error (cat_lines errors)
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   326
      else ext_record (args, name) parent fields thy 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   327
  end
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   328
  handle ERROR =>
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   329
    error ("The error(s) above occurred in record declaration " ^ quote name);
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   330
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   331
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   332
(* internalization methods *)
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   333
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   334
fun read_parent sign name =
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   335
  (case Sign.read_raw_typ (sign, K None) name of
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   336
    Type (name, Ts) => (Ts, name)
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   337
  | _ => error ("Malformed parent specification: " ^ name));
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   338
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   339
fun read_typ sign ass name = 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   340
  Sign.read_typ (sign, curry assoc ass) name handle TYPE (msg, _, _) => error msg;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   341
 
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   342
fun cert_typ sign ass T =
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   343
  Sign.certify_typ sign T handle TYPE (msg, _, _) => error msg;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   344
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   345
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   346
(* add_record(_i) *)
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   347
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   348
val add_record = add_record_aux read_typ read_parent;
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   349
val add_record_i = add_record_aux cert_typ (K I);
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   350
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   351
2e089fae6ed7 first version of records
narasche
parents:
diff changeset
   352
end;