| 6118 |      1 | (*  Title:      Pure/General/table.ML
 | 
| 5015 |      2 |     ID:         $Id$
 | 
|  |      3 |     Author:     Markus Wenzel, TU Muenchen
 | 
| 8806 |      4 |     License:    GPL (GNU GENERAL PUBLIC LICENSE)
 | 
| 5015 |      5 | 
 | 
| 8806 |      6 | Generic tables and tables indexed by strings.  Efficient purely
 | 
|  |      7 | functional implementation using balanced 2-3 trees.  No delete
 | 
|  |      8 | operation (may store options instead).
 | 
| 5015 |      9 | *)
 | 
|  |     10 | 
 | 
|  |     11 | signature KEY =
 | 
|  |     12 | sig
 | 
|  |     13 |   type key
 | 
|  |     14 |   val ord: key * key -> order
 | 
|  |     15 | end;
 | 
|  |     16 | 
 | 
|  |     17 | signature TABLE =
 | 
|  |     18 | sig
 | 
|  |     19 |   type key
 | 
|  |     20 |   type 'a table
 | 
|  |     21 |   exception DUP of key
 | 
|  |     22 |   exception DUPS of key list
 | 
|  |     23 |   val empty: 'a table
 | 
|  |     24 |   val is_empty: 'a table -> bool
 | 
| 5681 |     25 |   val map: ('a -> 'b) -> 'a table -> 'b table
 | 
|  |     26 |   val foldl: ('a * (key * 'b) -> 'a) -> 'a * 'b table -> 'a
 | 
| 5015 |     27 |   val dest: 'a table -> (key * 'a) list
 | 
| 5681 |     28 |   val keys: 'a table -> key list
 | 
| 8409 |     29 |   val min_key: 'a table -> key option
 | 
| 7061 |     30 |   val exists: (key * 'a -> bool) -> 'a table -> bool
 | 
| 5015 |     31 |   val lookup: 'a table * key -> 'a option
 | 
|  |     32 |   val update: (key * 'a) * 'a table -> 'a table
 | 
|  |     33 |   val update_new: (key * 'a) * 'a table -> 'a table                 (*exception DUP*)
 | 
|  |     34 |   val make: (key * 'a) list -> 'a table                             (*exception DUPS*)
 | 
|  |     35 |   val extend: 'a table * (key * 'a) list -> 'a table                (*exception DUPS*)
 | 
|  |     36 |   val merge: ('a * 'a -> bool) -> 'a table * 'a table -> 'a table   (*exception DUPS*)
 | 
|  |     37 |   val lookup_multi: 'a list table * key -> 'a list
 | 
| 8606 |     38 |   val update_multi: (key * 'a) * 'a list table -> 'a list table
 | 
| 5015 |     39 |   val make_multi: (key * 'a) list -> 'a list table
 | 
|  |     40 |   val dest_multi: 'a list table -> (key * 'a) list
 | 
|  |     41 | end;
 | 
|  |     42 | 
 | 
|  |     43 | functor TableFun(Key: KEY): TABLE =
 | 
|  |     44 | struct
 | 
|  |     45 | 
 | 
|  |     46 | 
 | 
|  |     47 | (* datatype table *)
 | 
|  |     48 | 
 | 
|  |     49 | type key = Key.key;
 | 
|  |     50 | 
 | 
|  |     51 | datatype 'a table =
 | 
|  |     52 |   Empty |
 | 
|  |     53 |   Branch2 of 'a table * (key * 'a) * 'a table |
 | 
|  |     54 |   Branch3 of 'a table * (key * 'a) * 'a table * (key * 'a) * 'a table;
 | 
|  |     55 | 
 | 
|  |     56 | exception DUP of key;
 | 
|  |     57 | exception DUPS of key list;
 | 
|  |     58 | 
 | 
|  |     59 | 
 | 
| 5681 |     60 | (* empty *)
 | 
|  |     61 | 
 | 
| 5015 |     62 | val empty = Empty;
 | 
|  |     63 | 
 | 
|  |     64 | fun is_empty Empty = true
 | 
|  |     65 |   | is_empty _ = false;
 | 
|  |     66 | 
 | 
| 5681 |     67 | 
 | 
|  |     68 | (* map and fold combinators *)
 | 
|  |     69 | 
 | 
|  |     70 | fun map_table _ Empty = Empty
 | 
|  |     71 |   | map_table f (Branch2 (left, (k, x), right)) =
 | 
|  |     72 |       Branch2 (map_table f left, (k, f x), map_table f right)
 | 
|  |     73 |   | map_table f (Branch3 (left, (k1, x1), mid, (k2, x2), right)) =
 | 
|  |     74 |       Branch3 (map_table f left, (k1, f x1), map_table f mid, (k2, f x2), map_table f right);
 | 
|  |     75 | 
 | 
|  |     76 | fun foldl_table _ (x, Empty) = x
 | 
|  |     77 |   | foldl_table f (x, Branch2 (left, p, right)) =
 | 
|  |     78 |       foldl_table f (f (foldl_table f (x, left), p), right)
 | 
|  |     79 |   | foldl_table f (x, Branch3 (left, p1, mid, p2, right)) =
 | 
|  |     80 |       foldl_table f (f (foldl_table f (f (foldl_table f (x, left), p1), mid), p2), right);
 | 
|  |     81 | 
 | 
|  |     82 | fun dest tab = rev (foldl_table (fn (rev_ps, p) => p :: rev_ps) ([], tab));
 | 
|  |     83 | fun keys tab = rev (foldl_table (fn (rev_ks, (k, _)) => k :: rev_ks) ([], tab));
 | 
| 7061 |     84 | fun exists P tab = foldl_table (fn (false, e) => P e | (b, _) => b) (false, tab);
 | 
| 5015 |     85 | 
 | 
| 8409 |     86 | fun min_key Empty = None
 | 
|  |     87 |   | min_key (Branch2 (left, (k, _), _)) = Some (if_none (min_key left) k)
 | 
|  |     88 |   | min_key (Branch3 (left, (k, _), _, _, _)) = Some (if_none (min_key left) k);
 | 
|  |     89 | 
 | 
| 5015 |     90 | 
 | 
|  |     91 | (* lookup *)
 | 
|  |     92 | 
 | 
|  |     93 | fun lookup (Empty, _) = None
 | 
|  |     94 |   | lookup (Branch2 (left, (k, x), right), key) =
 | 
|  |     95 |       (case Key.ord (key, k) of
 | 
|  |     96 |         LESS => lookup (left, key)
 | 
|  |     97 |       | EQUAL => Some x
 | 
|  |     98 |       | GREATER => lookup (right, key))
 | 
|  |     99 |   | lookup (Branch3 (left, (k1, x1), mid, (k2, x2), right), key) =
 | 
|  |    100 |       (case Key.ord (key, k1) of
 | 
|  |    101 |         LESS => lookup (left, key)
 | 
|  |    102 |       | EQUAL => Some x1
 | 
|  |    103 |       | GREATER =>
 | 
|  |    104 |           (case Key.ord (key, k2) of
 | 
|  |    105 |             LESS => lookup (mid, key)
 | 
|  |    106 |           | EQUAL => Some x2
 | 
|  |    107 |           | GREATER => lookup (right, key)));
 | 
|  |    108 | 
 | 
|  |    109 | 
 | 
|  |    110 | (* update *)
 | 
|  |    111 | 
 | 
|  |    112 | fun compare (k1, _) (k2, _) = Key.ord (k1, k2);
 | 
|  |    113 | 
 | 
|  |    114 | datatype 'a growth =
 | 
|  |    115 |   Stay of 'a table |
 | 
|  |    116 |   Sprout of 'a table * (key * 'a) * 'a table;
 | 
|  |    117 | 
 | 
|  |    118 | fun insert pair Empty = Sprout (Empty, pair, Empty)
 | 
|  |    119 |   | insert pair (Branch2 (left, p, right)) =
 | 
|  |    120 |       (case compare pair p of
 | 
|  |    121 |         LESS =>
 | 
|  |    122 |           (case insert pair left of
 | 
|  |    123 |             Stay left' => Stay (Branch2 (left', p, right))
 | 
|  |    124 |           | Sprout (left1, q, left2) => Stay (Branch3 (left1, q, left2, p, right)))
 | 
|  |    125 |       | EQUAL => Stay (Branch2 (left, pair, right))
 | 
|  |    126 |       | GREATER =>
 | 
|  |    127 |           (case insert pair right of
 | 
|  |    128 |             Stay right' => Stay (Branch2 (left, p, right'))
 | 
|  |    129 |           | Sprout (right1, q, right2) =>
 | 
|  |    130 |               Stay (Branch3 (left, p, right1, q, right2))))
 | 
|  |    131 |   | insert pair (Branch3 (left, p1, mid, p2, right)) =
 | 
|  |    132 |       (case compare pair p1 of
 | 
|  |    133 |         LESS =>
 | 
|  |    134 |           (case insert pair left of
 | 
|  |    135 |             Stay left' => Stay (Branch3 (left', p1, mid, p2, right))
 | 
|  |    136 |           | Sprout (left1, q, left2) =>
 | 
|  |    137 |               Sprout (Branch2 (left1, q, left2), p1, Branch2 (mid, p2, right)))
 | 
|  |    138 |       | EQUAL => Stay (Branch3 (left, pair, mid, p2, right))
 | 
|  |    139 |       | GREATER =>
 | 
|  |    140 |           (case compare pair p2 of
 | 
|  |    141 |             LESS =>
 | 
|  |    142 |               (case insert pair mid of
 | 
|  |    143 |                 Stay mid' => Stay (Branch3 (left, p1, mid', p2, right))
 | 
|  |    144 |               | Sprout (mid1, q, mid2) =>
 | 
|  |    145 |                   Sprout (Branch2 (left, p1, mid1), q, Branch2 (mid2, p2, right)))
 | 
|  |    146 |           | EQUAL => Stay (Branch3 (left, p1, mid, pair, right))
 | 
|  |    147 |           | GREATER =>
 | 
|  |    148 |               (case insert pair right of
 | 
|  |    149 |                 Stay right' => Stay (Branch3 (left, p1, mid, p2, right'))
 | 
|  |    150 |               | Sprout (right1, q, right2) =>
 | 
|  |    151 |                   Sprout (Branch2 (left, p1, mid), p2, Branch2 (right1, q, right2)))));
 | 
|  |    152 | 
 | 
|  |    153 | fun update (pair, tab) =
 | 
|  |    154 |   (case insert pair tab of
 | 
|  |    155 |     Stay tab => tab
 | 
|  |    156 |   | Sprout br => Branch2 br);
 | 
|  |    157 | 
 | 
|  |    158 | fun update_new (pair as (key, _), tab) =
 | 
|  |    159 |   if is_none (lookup (tab, key)) then update (pair, tab)
 | 
|  |    160 |   else raise DUP key;
 | 
|  |    161 | 
 | 
|  |    162 | 
 | 
|  |    163 | (* make, extend, merge tables *)
 | 
|  |    164 | 
 | 
|  |    165 | fun add eq ((tab, dups), (key, x)) =
 | 
|  |    166 |   (case lookup (tab, key) of
 | 
|  |    167 |     None => (update ((key, x), tab), dups)
 | 
|  |    168 |   | Some x' =>
 | 
|  |    169 |       if eq (x, x') then (tab, dups)
 | 
|  |    170 |       else (tab, dups @ [key]));
 | 
|  |    171 | 
 | 
|  |    172 | fun enter eq (tab, pairs) =
 | 
|  |    173 |   (case foldl (add eq) ((tab, []), pairs) of
 | 
|  |    174 |     (tab', []) => tab'
 | 
|  |    175 |   | (_, dups) => raise DUPS dups);
 | 
|  |    176 | 
 | 
|  |    177 | fun extend tab_pairs = enter (K false) tab_pairs;
 | 
|  |    178 | fun make pairs = extend (empty, pairs);
 | 
|  |    179 | fun merge eq (tab1, tab2) = enter eq (tab1, dest tab2);
 | 
|  |    180 | 
 | 
|  |    181 | 
 | 
|  |    182 | (* tables with multiple entries per key (preserving order) *)
 | 
|  |    183 | 
 | 
|  |    184 | fun lookup_multi tab_key = if_none (lookup tab_key) [];
 | 
|  |    185 | 
 | 
| 8606 |    186 | fun update_multi ((key, x), tab) =
 | 
| 5015 |    187 |   update ((key, x :: lookup_multi (tab, key)), tab);
 | 
|  |    188 | 
 | 
| 8606 |    189 | fun make_multi pairs = foldr update_multi (pairs, empty);
 | 
| 5015 |    190 | 
 | 
|  |    191 | fun dest_multi tab =
 | 
|  |    192 |   flat (map (fn (key, xs) => map (Library.pair key) xs) (dest tab));
 | 
|  |    193 | 
 | 
|  |    194 | 
 | 
| 5681 |    195 | (*final declarations of this structure!*)
 | 
|  |    196 | val map = map_table;
 | 
|  |    197 | val foldl = foldl_table;
 | 
| 5015 |    198 | 
 | 
|  |    199 | 
 | 
|  |    200 | end;
 | 
|  |    201 | 
 | 
|  |    202 | 
 | 
|  |    203 | (*tables indexed by strings*)
 | 
|  |    204 | structure Symtab = TableFun(type key = string val ord = string_ord);
 |