1     type Map<K, V> @abstract =
2         let map = StdMap<K, V>.new
3         let mut is_invoking_callbacks = false
4         let on_added_callbacks = StdList<K * V -> Unit>.new
5         let on_removed_callbacks = StdList<K * V -> Unit>.new
6         let tokens = StdList<Token>.new
7     
8         let invoke_callbacks (callbacks : StdList<K * V -> Unit>
9                               k : K
10                              v : V) =
11            assert not is_invoking_callbacks
12            is_invoking_callbacks = true
13    
14            for f in callbacks do
15                f k v
16    
17            is_invoking_callbacks = false
18    
19        def is_empty = map.is_empty
20        def is_not_empty = map.is_not_empty
21    
22        def try_get (k : K) = map.try_get k
23        def contains (k : K) = map.contains k
24    
25        fun get (k : K) = map[k]
26    
27        def subscribe (f : K * V -> Unit) (g : K * V -> Unit) =
28            assert not is_invoking_callbacks
29            on_added_callbacks.add f
30            on_removed_callbacks.add g
31    
32            Token { assert not is_invoking_callbacks
33                    on_added_callbacks.remove f
34                    on_removed_callbacks.remove g }
35    
36        def bind (f : K * V -> Unit) (g : K * V -> Unit) =
37            assert not is_invoking_callbacks
38            on_added_callbacks.add f
39            on_removed_callbacks.add g
40    
41            for k, v in map do
42                f k v
43    
44            Token { assert not is_invoking_callbacks
45                    on_added_callbacks.remove f
46                    on_removed_callbacks.remove g
47    
48                    for k, v in map do
49                        g k v }
50    
51        def subscribe (f : K * V -> Unit
52                       g : K * V * V -> Unit
53                       h : K * V -> Unit) =
54            let values = StdMap<K, V>.new
55            subscribe
56                { k v ->
57                      if not values.contains k then
58                          values.add k v
59                          f k v
60                      else
61                          let prev_v = values[k]
62                          values[k] = v
63                          g k prev_v v }
64                { k v ->
65                      if not contains k then
66                          values.remove k
67                          h k v }
68    
69        def bind (f : K * V -> Unit
70                  g : K * V * V -> Unit
71                  h : K * V -> Unit) =
72            let token = subscribe f g h
73            for k, v in map do
74                f k v
75    
76            Token { token.discard
77                    for k, v in map do
78                        h k v }
79    
80        fun destruct =
81            for i = tokens.size - 1 downto 0 do
82                tokens[i].discard
83    
84    type MutMap<K, V> @[mut_of Map] =
85        inherit Map<K, V>
86    
87        def insert (k : K) (v : V) =
88            assert not is_invoking_callbacks
89    
90            let result = map.insert k v
91    
92            if result <> Some v then
93                if result ? Some prev_v then
94                    invoke_callbacks on_removed_callbacks k prev_v
95    
96                invoke_callbacks on_added_callbacks k v
97    
98            result
99    
100       fun set (k : K) (v : V) =
101           let result = insert k v
102           assert result.is_some
103   
104       def add (k : K) (v : V) =
105           assert not is_invoking_callbacks
106   
107           map.add k v
108           invoke_callbacks on_added_callbacks k v
109   
110       def remove (k : K) =
111           assert not is_invoking_callbacks
112   
113           let v = map[k]
114           map.remove k
115           invoke_callbacks on_removed_callbacks k v
116   
117       def push_token (token : Token) =
118           tokens.add token
119   
120       def as_readonly = self as Map<K, V>
121