src/Pure/General/linear_set.ML
changeset 38448 62d16c415019
child 44476 e8a87398f35d
equal deleted inserted replaced
38447:f55e77f623ab 38448:62d16c415019
       
     1 (*  Title:      Pure/General/linear_set.ML
       
     2     Author:     Makarius
       
     3 
       
     4 Sets with canonical linear order, or immutable linked-lists.
       
     5 *)
       
     6 
       
     7 signature LINEAR_SET =
       
     8 sig
       
     9   type key
       
    10   type 'a T
       
    11   exception DUPLICATE of key
       
    12   exception UNDEFINED of key
       
    13   exception NEXT_UNDEFINED of key option
       
    14   val empty: 'a T
       
    15   val is_empty: 'a T -> bool
       
    16   val defined: 'a T -> key -> bool
       
    17   val lookup: 'a T -> key -> 'a option
       
    18   val update: key * 'a -> 'a T -> 'a T
       
    19   val fold: key option ->
       
    20     ((key option * key) * 'a -> 'b -> 'b) -> 'a T -> 'b -> 'b
       
    21   val get_first: key option ->
       
    22     ((key option * key) * 'a -> bool) -> 'a T -> ((key option * key) * 'a) option
       
    23   val get_after: 'a T -> key option -> key option
       
    24   val insert_after: key option -> key * 'a -> 'a T -> 'a T
       
    25   val delete_after: key option -> 'a T -> 'a T
       
    26 end;
       
    27 
       
    28 functor Linear_Set(Key: KEY): LINEAR_SET =
       
    29 struct
       
    30 
       
    31 (* type key *)
       
    32 
       
    33 type key = Key.key;
       
    34 structure Table = Table(Key);
       
    35 
       
    36 exception DUPLICATE of key;
       
    37 exception UNDEFINED of key;
       
    38 exception NEXT_UNDEFINED of key option;
       
    39 
       
    40 
       
    41 (* raw entries *)
       
    42 
       
    43 fun the_entry entries key =
       
    44   (case Table.lookup entries key of
       
    45     NONE => raise UNDEFINED key
       
    46   | SOME entry => entry);
       
    47 
       
    48 fun next_entry entries key = snd (the_entry entries key);
       
    49 
       
    50 fun put_entry entry entries = Table.update entry entries;
       
    51 
       
    52 fun new_entry entry entries = Table.update_new entry entries
       
    53   handle Table.DUP key => raise DUPLICATE key;
       
    54 
       
    55 fun del_entry key entries = Table.delete_safe key entries;
       
    56 
       
    57 
       
    58 (* set representation and basic operations *)
       
    59 
       
    60 datatype 'a T = Set of {start: key option, entries: ('a * key option) Table.table};
       
    61 
       
    62 fun make_set (start, entries) = Set {start = start, entries = entries};
       
    63 fun map_set f (Set {start, entries}) = make_set (f (start, entries));
       
    64 
       
    65 fun start_of (Set {start, ...}) = start;
       
    66 fun entries_of (Set {entries, ...}) = entries;
       
    67 
       
    68 val empty = Set {start = NONE, entries = Table.empty};
       
    69 fun is_empty set = is_none (start_of set);
       
    70 
       
    71 fun defined set key = Table.defined (entries_of set) key;
       
    72 
       
    73 fun lookup set key = Option.map fst (Table.lookup (entries_of set) key);
       
    74 
       
    75 fun update (key, x) = map_set (fn (start, entries) =>
       
    76   (start, put_entry (key, (x, next_entry entries key)) entries));
       
    77 
       
    78 
       
    79 (* iterate entries *)
       
    80 
       
    81 fun optional_start set NONE = start_of set
       
    82   | optional_start _ some = some;
       
    83 
       
    84 fun fold opt_start f set =
       
    85   let
       
    86     val entries = entries_of set;
       
    87     fun apply _ NONE y = y
       
    88       | apply prev (SOME key) y =
       
    89           let
       
    90             val (x, next) = the_entry entries key;
       
    91             val item = ((prev, key), x);
       
    92           in apply (SOME key) next (f item y) end;
       
    93   in apply NONE (optional_start set opt_start) end;
       
    94 
       
    95 fun get_first opt_start P set =
       
    96   let
       
    97     val entries = entries_of set;
       
    98     fun first _ NONE = NONE
       
    99       | first prev (SOME key) =
       
   100           let
       
   101             val (x, next) = the_entry entries key;
       
   102             val item = ((prev, key), x);
       
   103           in if P item then SOME item else first (SOME key) next end;
       
   104   in first NONE (optional_start set opt_start) end;
       
   105 
       
   106 
       
   107 (* relative addressing *)
       
   108 
       
   109 fun get_after set hook =
       
   110   (case hook of
       
   111     NONE => start_of set
       
   112   | SOME key => next_entry (entries_of set) key);
       
   113 
       
   114 fun insert_after hook (key, x) = map_set (fn (start, entries) =>
       
   115   (case hook of
       
   116     NONE => (SOME key, new_entry (key, (x, start)) entries)
       
   117   | SOME key1 =>
       
   118       let
       
   119         val (x1, next) = the_entry entries key1;
       
   120         val entries' = entries
       
   121           |> put_entry (key1, (x1, SOME key))
       
   122           |> new_entry (key, (x, next));
       
   123       in (start, entries') end));
       
   124 
       
   125 fun delete_after hook set = set |> map_set (fn (start, entries) =>
       
   126   (case hook of
       
   127     NONE =>
       
   128       (case start of
       
   129         NONE => raise NEXT_UNDEFINED NONE
       
   130       | SOME key1 => (next_entry entries key1, del_entry key1 entries))
       
   131   | SOME key1 =>
       
   132       (case the_entry entries key1 of
       
   133         (_, NONE) => raise NEXT_UNDEFINED (SOME key1)
       
   134       | (x1, SOME key2) =>
       
   135           let
       
   136             val entries' = entries
       
   137               |> put_entry (key1, (x1, next_entry entries key2))
       
   138               |> del_entry key2;
       
   139           in (start, entries') end)));
       
   140 
       
   141 end;
       
   142