src/Pure/data.ML
changeset 4256 e768c42069bb
parent 4255 63ab0616900b
child 4257 1663f9056045
equal deleted inserted replaced
4255:63ab0616900b 4256:e768c42069bb
     1 (*  Title:      Pure/data.ML
       
     2     ID:         $Id$
       
     3     Author:     Markus Wenzel, TU Muenchen
       
     4 
       
     5 Arbitrarily typed data.  Fools the ML type system via exception
       
     6 constructors.
       
     7 *)
       
     8 
       
     9 type object = exn;
       
    10 
       
    11 signature DATA =
       
    12 sig
       
    13   type T
       
    14   val empty: T
       
    15   val merge: T * T -> T
       
    16   val prep_ext: T -> T
       
    17   val kinds: T -> string list
       
    18   val init: T -> string -> object ->
       
    19     (object -> object) -> (object * object -> object) -> (object -> unit) -> T
       
    20   val get: T -> string -> object
       
    21   val put: T -> string -> object -> T
       
    22   val print: T -> string -> unit
       
    23 end;
       
    24 
       
    25 
       
    26 structure Data: DATA =
       
    27 struct
       
    28 
       
    29 
       
    30 (* datatype T *)
       
    31 
       
    32 datatype T = Data of
       
    33   (object *                             (*value*)
       
    34    ((object -> object) *                (*prepare extend method*)
       
    35     (object * object -> object) *       (*merge and prepare extend method*)
       
    36     (object -> unit)))                  (*print method*)
       
    37   Symtab.table;
       
    38 
       
    39 val empty = Data Symtab.null;
       
    40 
       
    41 fun kinds (Data tab) = map fst (Symtab.dest tab);
       
    42 
       
    43 
       
    44 (* errors *)
       
    45 
       
    46 fun err_method name kind =
       
    47   error ("Error while invoking " ^ quote kind ^ " " ^ name ^ " method");
       
    48 
       
    49 fun err_dup_init kind =
       
    50   error ("Duplicate initialization of " ^ quote kind ^ " data");
       
    51 
       
    52 fun err_uninit kind =
       
    53   error ("Tried to access uninitialized " ^ quote kind ^ " data");
       
    54 
       
    55 
       
    56 (* prepare data *)
       
    57 
       
    58 fun merge (Data tab1, Data tab2) =
       
    59   let
       
    60     val data1 = Symtab.dest tab1;
       
    61     val data2 = Symtab.dest tab2;
       
    62     val all_data = data1 @ data2;
       
    63     val kinds = distinct (map fst all_data);
       
    64 
       
    65    fun entry data kind =
       
    66      (case assoc (data, kind) of
       
    67        None => []
       
    68      | Some x => [(kind, x)]);
       
    69 
       
    70     fun merge_entries [(kind, (e, mths as (ext, _, _)))] =
       
    71           (kind, (ext e handle _ => err_method "prep_ext" kind, mths))
       
    72       | merge_entries [(kind, (e1, mths as (_, mrg, _))), (_, (e2, _))] =
       
    73           (kind, (mrg (e1, e2) handle _ => err_method "merge" kind, mths))
       
    74       | merge_entries _ = sys_error "merge_entries";
       
    75 
       
    76     val data = map (fn k => merge_entries (entry data1 k @ entry data2 k)) kinds;
       
    77   in Data (Symtab.make data) end;
       
    78 
       
    79 
       
    80 fun prep_ext data = merge (data, empty);
       
    81 
       
    82 fun init (Data tab) kind e ext mrg prt =
       
    83   Data (Symtab.update_new ((kind, (e, (ext, mrg, prt))), tab))
       
    84     handle Symtab.DUPLICATE _ => err_dup_init kind;
       
    85 
       
    86 
       
    87 (* access data *)
       
    88 
       
    89 fun lookup tab kind =
       
    90   (case Symtab.lookup (tab, kind) of
       
    91     Some x => x
       
    92   | None => err_uninit kind);
       
    93 
       
    94 fun get (Data tab) kind = fst (lookup tab kind);
       
    95 
       
    96 fun put (Data tab) kind e =
       
    97   Data (Symtab.update ((kind, (e, snd (lookup tab kind))), tab));
       
    98 
       
    99 fun print (Data tab) kind =
       
   100   let val (e, (_, _, prt)) = lookup tab kind
       
   101   in prt e handle _ => err_method "print" kind end;
       
   102 
       
   103 
       
   104 end;