| 17152 |      1 | (*  Title:      Pure/General/alist.ML
 | 
|  |      2 |     ID:         $Id$
 | 
|  |      3 |     Author:     Florian Haftmann, TU Muenchen
 | 
|  |      4 | 
 | 
|  |      5 | Association lists -- lists of (key, value) pairs with unique keys.
 | 
|  |      6 | A light-weight representation of finite mappings;
 | 
|  |      7 | see also Pure/General/table.ML for a more scalable implementation.
 | 
|  |      8 | *)
 | 
|  |      9 | 
 | 
|  |     10 | signature ALIST =
 | 
|  |     11 | sig
 | 
| 17766 |     12 |   exception DUP
 | 
| 17152 |     13 |   val lookup: ('a * 'b -> bool) -> ('b * 'c) list -> 'a -> 'c option
 | 
|  |     14 |   val defined: ('a * 'b -> bool) -> ('b * 'c) list -> 'a -> bool
 | 
|  |     15 |   val update: ('a * 'a -> bool) -> ('a * 'b)
 | 
|  |     16 |     -> ('a * 'b) list -> ('a * 'b) list
 | 
|  |     17 |   val default: ('a * 'a -> bool) -> ('a * 'b)
 | 
|  |     18 |     -> ('a * 'b) list -> ('a * 'b) list
 | 
|  |     19 |   val delete: ('a * 'b -> bool) -> 'a
 | 
|  |     20 |     -> ('b * 'c) list -> ('b * 'c) list
 | 
|  |     21 |   val map_entry: ('a * 'b -> bool) -> 'a -> ('c -> 'c)
 | 
|  |     22 |     -> ('b * 'c) list -> ('b * 'c) list
 | 
| 17487 |     23 |   val make: ('a -> 'b) -> 'a list -> ('a * 'b) list
 | 
| 17911 |     24 |   val join: ('a * 'a -> bool) -> ('a -> 'b * 'b -> 'b option) ->
 | 
|  |     25 |     ('a * 'b) list * ('a * 'b) list -> ('a * 'b) list         (*exception DUP*)
 | 
| 17766 |     26 |   val merge: ('a * 'a -> bool) -> ('b * 'b -> bool)
 | 
| 17911 |     27 |     -> ('a * 'b) list * ('a * 'b) list -> ('a * 'b) list      (*exception DUP*)
 | 
| 17497 |     28 |   val find: ('a * 'b -> bool) -> ('c * 'b) list -> 'a -> 'c list
 | 
| 17152 |     29 | end;
 | 
|  |     30 | 
 | 
|  |     31 | structure AList: ALIST =
 | 
|  |     32 | struct
 | 
|  |     33 | 
 | 
| 17766 |     34 | fun find_index eq xs key =
 | 
|  |     35 |   let
 | 
|  |     36 |     fun find [] _ = 0
 | 
|  |     37 |       | find ((key', value)::xs) i =
 | 
|  |     38 |           if eq (key, key')
 | 
|  |     39 |           then i
 | 
|  |     40 |           else find xs (i+1);
 | 
|  |     41 |   in find xs 1 end;
 | 
|  |     42 | 
 | 
| 17152 |     43 | fun lookup _ [] _ = NONE
 | 
|  |     44 |   | lookup eq ((key, value)::xs) key' =
 | 
|  |     45 |       if eq (key', key) then SOME value
 | 
|  |     46 |       else lookup eq xs key';
 | 
|  |     47 | 
 | 
|  |     48 | fun defined _ [] _ = false
 | 
|  |     49 |   | defined eq ((key, value)::xs) key' =
 | 
|  |     50 |       eq (key', key) orelse defined eq xs key';
 | 
|  |     51 | 
 | 
| 17766 |     52 | fun update eq (x as (key, value)) xs =
 | 
| 17152 |     53 |   let
 | 
| 17766 |     54 |     val i = find_index eq xs key;
 | 
|  |     55 |     fun upd 1 (_::xs) = (x::xs)
 | 
|  |     56 |       | upd i (x::xs) = x :: upd (i-1) xs;
 | 
|  |     57 |   in if i = 0 then x::xs else upd i xs end;
 | 
| 17152 |     58 | 
 | 
|  |     59 | fun default eq (key, value) xs =
 | 
|  |     60 |   if defined eq xs key then xs else (key, value)::xs;
 | 
|  |     61 | 
 | 
|  |     62 | fun delete eq key xs =
 | 
|  |     63 |   let
 | 
| 17766 |     64 |     val i = find_index eq xs key;
 | 
|  |     65 |     fun del 1 (_::xs) = xs
 | 
|  |     66 |       | del i (x::xs) = x :: del (i-1) xs;
 | 
|  |     67 |   in if i = 0 then xs else del i xs end;
 | 
|  |     68 | 
 | 
|  |     69 | fun map_entry eq key f xs =
 | 
|  |     70 |   let
 | 
|  |     71 |     val i = find_index eq xs key;
 | 
|  |     72 |     fun mapp 1 ((x as (key, value))::xs) = (key, f value) :: xs
 | 
|  |     73 |       | mapp i (x::xs) = x :: mapp (i-1) xs;
 | 
|  |     74 |   in if i = 0 then xs else mapp i xs end;
 | 
| 17152 |     75 | 
 | 
| 17766 |     76 | exception DUP;
 | 
|  |     77 | 
 | 
| 17911 |     78 | fun join eq f (xs, ys) =
 | 
|  |     79 |   let
 | 
|  |     80 |     fun add (key, x) xs =
 | 
|  |     81 |       (case lookup eq xs key of
 | 
|  |     82 |         NONE => update eq (key, x) xs
 | 
|  |     83 |       | SOME y =>
 | 
|  |     84 |           (case f key (y, x) of
 | 
|  |     85 |             SOME z => update eq (key, z) xs
 | 
|  |     86 |           | NONE => raise DUP));
 | 
|  |     87 |   in fold_rev add xs ys end;
 | 
|  |     88 | 
 | 
| 17766 |     89 | fun merge eq_key eq_val (xs, ys) =
 | 
| 17191 |     90 |   let
 | 
| 17766 |     91 |     fun add (x as (key, value)) ys =
 | 
|  |     92 |       case lookup eq_key ys key
 | 
|  |     93 |        of NONE => update eq_key x ys
 | 
|  |     94 |         | SOME value' =>
 | 
|  |     95 |             if eq_val (value, value')
 | 
|  |     96 |             then ys
 | 
|  |     97 |             else raise DUP;
 | 
| 17911 |     98 |   in fold_rev add xs ys end;
 | 
| 17191 |     99 | 
 | 
| 17487 |    100 | fun make keyfun =
 | 
|  |    101 |   let fun keypair x = (x, keyfun x)
 | 
|  |    102 |   in map keypair end;
 | 
|  |    103 | 
 | 
| 17497 |    104 | fun find eq [] _ = []
 | 
|  |    105 |   | find eq ((key, value) :: xs) value' =
 | 
|  |    106 |       let
 | 
| 17766 |    107 |         val values = find eq xs value';
 | 
| 17497 |    108 |       in if eq (value', value) then key :: values else values end;
 | 
|  |    109 | 
 | 
| 17152 |    110 | end;
 |