15 type 'a T |
15 type 'a T |
16 val table_of: 'a T -> 'a Table.table |
16 val table_of: 'a T -> 'a Table.table |
17 val empty: 'a T |
17 val empty: 'a T |
18 val is_empty: 'a T -> bool |
18 val is_empty: 'a T -> bool |
19 val change_base: bool -> 'a T -> 'a T |
19 val change_base: bool -> 'a T -> 'a T |
|
20 val change_ignore: 'a T -> 'a T |
20 val join: (key -> 'a * 'a -> 'a) (*exception SAME*) -> 'a T * 'a T -> 'a T (*exception DUP*) |
21 val join: (key -> 'a * 'a -> 'a) (*exception SAME*) -> 'a T * 'a T -> 'a T (*exception DUP*) |
21 val merge: ('a * 'a -> bool) -> 'a T * 'a T -> 'a T (*exception DUP*) |
22 val merge: ('a * 'a -> bool) -> 'a T * 'a T -> 'a T (*exception DUP*) |
22 val fold: (key * 'b -> 'a -> 'a) -> 'b T -> 'a -> 'a |
23 val fold: (key * 'b -> 'a -> 'a) -> 'b T -> 'a -> 'a |
23 val dest: 'a T -> (key * 'a) list |
24 val dest: 'a T -> (key * 'a) list |
24 val lookup_key: 'a T -> key -> (key * 'a) option |
25 val lookup_key: 'a T -> key -> (key * 'a) option |
41 exception DUP = Table.DUP; |
42 exception DUP = Table.DUP; |
42 |
43 |
43 |
44 |
44 (* optional change *) |
45 (* optional change *) |
45 |
46 |
46 datatype change = No_Change | Change of {base: serial, depth: int, changes: Table.set}; |
47 datatype change = |
|
48 No_Change | Change of {base: serial, depth: int, changes: Table.set option}; |
47 |
49 |
48 fun make_change base depth changes = |
50 fun make_change base depth changes = |
49 Change {base = base, depth = depth, changes = changes}; |
51 Change {base = base, depth = depth, changes = changes}; |
50 |
52 |
|
53 fun ignore_change (Change {base, depth, changes = SOME _}) = |
|
54 make_change base depth NONE |
|
55 | ignore_change change = change; |
|
56 |
|
57 fun update_change key (Change {base, depth, changes = SOME ch}) = |
|
58 make_change base depth (SOME (Table.insert (K true) (key, ()) ch)) |
|
59 | update_change _ change = change; |
|
60 |
51 fun base_change true No_Change = |
61 fun base_change true No_Change = |
52 make_change (serial ()) 0 Table.empty |
62 make_change (serial ()) 0 (SOME Table.empty) |
53 | base_change true (Change {base, depth, changes}) = |
63 | base_change true (Change {base, depth, changes}) = |
54 make_change base (depth + 1) changes |
64 make_change base (depth + 1) changes |
55 | base_change false (Change {base, depth, changes}) = |
65 | base_change false (Change {base, depth, changes}) = |
56 if depth = 0 then No_Change else make_change base (depth - 1) changes |
66 if depth = 0 then No_Change else make_change base (depth - 1) changes |
57 | base_change false No_Change = raise Fail "Unbalanced block structure of change table"; |
67 | base_change false No_Change = raise Fail "Unbalanced change structure"; |
58 |
68 |
59 fun update_change _ No_Change = No_Change |
69 fun cannot_merge () = raise Fail "Cannot merge: incompatible change structure"; |
60 | update_change key (Change {base, depth, changes}) = |
|
61 make_change base depth (Table.insert (K true) (key, ()) changes); |
|
62 |
|
63 fun cannot_merge () = raise Fail "Attempt to merge tables with incompatible change base"; |
|
64 |
70 |
65 fun merge_change (No_Change, No_Change) = NONE |
71 fun merge_change (No_Change, No_Change) = NONE |
66 | merge_change (Change change1, Change change2) = |
72 | merge_change (Change change1, Change change2) = |
67 let |
73 let |
68 val {base = base1, depth = depth1, changes = changes1} = change1; |
74 val {base = base1, depth = depth1, changes = changes1} = change1; |
69 val {base = base2, depth = depth2, changes = changes2} = change2; |
75 val {base = base2, depth = depth2, changes = changes2} = change2; |
70 in |
76 val _ = if base1 = base2 andalso depth1 = depth2 then () else cannot_merge (); |
71 if base1 = base2 andalso depth1 = depth2 then |
77 val (swapped, ch2) = |
72 SOME ((changes2, make_change base1 depth1 (Table.merge (K true) (changes1, changes2)))) |
78 (case (changes1, changes2) of |
73 else cannot_merge () |
79 (_, SOME ch2) => (false, ch2) |
74 end |
80 | (SOME ch1, _) => (true, ch1) |
|
81 | _ => cannot_merge ()); |
|
82 in SOME (swapped, ch2, make_change base1 depth1 NONE) end |
75 | merge_change _ = cannot_merge (); |
83 | merge_change _ = cannot_merge (); |
76 |
84 |
77 |
85 |
78 (* table with changes *) |
86 (* table with changes *) |
79 |
87 |
103 else if is_empty arg2 then arg1 |
112 else if is_empty arg2 then arg1 |
104 else if is_empty arg1 then arg2 |
113 else if is_empty arg1 then arg2 |
105 else |
114 else |
106 (case merge_change (change1, change2) of |
115 (case merge_change (change1, change2) of |
107 NONE => make_change_table (No_Change, Table.join f (table1, table2)) |
116 NONE => make_change_table (No_Change, Table.join f (table1, table2)) |
108 | SOME (changes2, change') => |
117 | SOME (swapped, ch2, change') => |
109 let |
118 let |
110 fun update key table = |
119 fun maybe_swap (x, y) = if swapped then (y, x) else (x, y); |
111 (case Table.lookup table2 key of |
120 val (tab1, tab2) = maybe_swap (table1, table2); |
112 NONE => table |
121 fun update key tab = |
|
122 (case Table.lookup tab2 key of |
|
123 NONE => tab |
113 | SOME y => |
124 | SOME y => |
114 (case Table.lookup table key of |
125 (case Table.lookup tab key of |
115 NONE => Table.update (key, y) table |
126 NONE => Table.update (key, y) tab |
116 | SOME x => |
127 | SOME x => |
117 (case (SOME (f key (x, y)) handle Table.SAME => NONE) of |
128 (case (SOME (f key (maybe_swap (x, y))) handle Table.SAME => NONE) of |
118 NONE => table |
129 NONE => tab |
119 | SOME z => Table.update (key, z) table))); |
130 | SOME z => Table.update (key, z) tab))); |
120 val table' = Table.fold (update o #1) changes2 table1; |
131 in make_change_table (change', Table.fold (update o #1) ch2 tab1) end) |
121 in make_change_table (change', table') end) |
|
122 end; |
132 end; |
123 |
133 |
124 fun merge eq = |
134 fun merge eq = |
125 join (fn key => fn xy => if eq xy then raise Table.SAME else raise Table.DUP key); |
135 join (fn key => fn xy => if eq xy then raise Table.SAME else raise Table.DUP key); |
126 |
136 |