|
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 |