src/Pure/General/change_table.ML
changeset 56139 b7add947a6ef
parent 56068 f74d0a4d8ae3
child 77723 b761c91c2447
equal deleted inserted replaced
56138:f42de6d8ed8e 56139:b7add947a6ef
    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 
    88 
    96 
    89 fun make_change_table (change, table) = Change_Table {change = change, table = table};
    97 fun make_change_table (change, table) = Change_Table {change = change, table = table};
    90 fun map_change_table f (Change_Table {change, table}) = make_change_table (f (change, table));
    98 fun map_change_table f (Change_Table {change, table}) = make_change_table (f (change, table));
    91 
    99 
    92 fun change_base begin = (map_change_table o apfst) (base_change begin);
   100 fun change_base begin = (map_change_table o apfst) (base_change begin);
       
   101 fun change_ignore arg = (map_change_table o apfst) ignore_change arg;
    93 
   102 
    94 
   103 
    95 (* join and merge *)
   104 (* join and merge *)
    96 
   105 
    97 fun join f (arg1, arg2) =
   106 fun join f (arg1, arg2) =
   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