Source file
src/go/token/tree.go
1
2
3
4
5 package token
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 import (
26 "fmt"
27 "iter"
28 )
29
30
31
32
33
34
35 type tree struct {
36 root *node
37 }
38
39 type node struct {
40
41 parent *node
42 left *node
43 right *node
44 file *File
45 key key
46 balance int32
47 height int32
48 }
49
50
51 type key struct{ start, end int }
52
53 func (f *File) key() key {
54 return key{f.base, f.base + f.size}
55 }
56
57
58
59
60
61
62
63
64
65
66 func compareKey(x, y key) int {
67 switch {
68 case x.end < y.start:
69 return -1
70 case y.end < x.start:
71 return +1
72 }
73 return 0
74 }
75
76
77
78 func (n *node) check(parent *node) {
79 const debugging = false
80 if debugging {
81 if n == nil {
82 return
83 }
84 if n.parent != parent {
85 panic("bad parent")
86 }
87 n.left.check(n)
88 n.right.check(n)
89 n.checkBalance()
90 }
91 }
92
93 func (n *node) checkBalance() {
94 lheight, rheight := n.left.safeHeight(), n.right.safeHeight()
95 balance := rheight - lheight
96 if balance != n.balance {
97 panic("bad node.balance")
98 }
99 if !(-2 <= balance && balance <= +2) {
100 panic(fmt.Sprintf("node.balance out of range: %d", balance))
101 }
102 h := 1 + max(lheight, rheight)
103 if h != n.height {
104 panic("bad node.height")
105 }
106 }
107
108
109
110
111
112 func (t *tree) locate(k key) (pos **node, parent *node) {
113 pos, x := &t.root, t.root
114 for x != nil {
115 sign := compareKey(k, x.key)
116 if sign < 0 {
117 pos, x, parent = &x.left, x.left, x
118 } else if sign > 0 {
119 pos, x, parent = &x.right, x.right, x
120 } else {
121 break
122 }
123 }
124 return pos, parent
125 }
126
127
128
129
130
131 func (t *tree) all() iter.Seq[*File] {
132 return func(yield func(*File) bool) {
133 if t == nil {
134 return
135 }
136 x := t.root
137 if x != nil {
138 for x.left != nil {
139 x = x.left
140 }
141 }
142 for x != nil && yield(x.file) {
143 if x.height >= 0 {
144
145 x = x.next()
146 } else {
147
148 x = t.nextAfter(t.locate(x.key))
149 }
150 }
151 }
152 }
153
154
155
156 func (t *tree) nextAfter(pos **node, parent *node) *node {
157 switch {
158 case *pos != nil:
159 return (*pos).next()
160 case parent == nil:
161 return nil
162 case pos == &parent.left:
163 return parent
164 default:
165 return parent.next()
166 }
167 }
168
169 func (x *node) next() *node {
170 if x.right == nil {
171 for x.parent != nil && x.parent.right == x {
172 x = x.parent
173 }
174 return x.parent
175 }
176 x = x.right
177 for x.left != nil {
178 x = x.left
179 }
180 return x
181 }
182
183 func (t *tree) setRoot(x *node) {
184 t.root = x
185 if x != nil {
186 x.parent = nil
187 }
188 }
189
190 func (x *node) setLeft(y *node) {
191 x.left = y
192 if y != nil {
193 y.parent = x
194 }
195 }
196
197 func (x *node) setRight(y *node) {
198 x.right = y
199 if y != nil {
200 y.parent = x
201 }
202 }
203
204 func (n *node) safeHeight() int32 {
205 if n == nil {
206 return -1
207 }
208 return n.height
209 }
210
211 func (n *node) update() {
212 lheight, rheight := n.left.safeHeight(), n.right.safeHeight()
213 n.height = max(lheight, rheight) + 1
214 n.balance = rheight - lheight
215 }
216
217 func (t *tree) replaceChild(parent, old, new *node) {
218 switch {
219 case parent == nil:
220 if t.root != old {
221 panic("corrupt tree")
222 }
223 t.setRoot(new)
224 case parent.left == old:
225 parent.setLeft(new)
226 case parent.right == old:
227 parent.setRight(new)
228 default:
229 panic("corrupt tree")
230 }
231 }
232
233
234
235
236
237
238
239 func (t *tree) rebalanceUp(x *node) {
240 for x != nil {
241 h := x.height
242 x.update()
243 switch x.balance {
244 case -2:
245 if x.left.balance == 1 {
246 t.rotateLeft(x.left)
247 }
248 x = t.rotateRight(x)
249
250 case +2:
251 if x.right.balance == -1 {
252 t.rotateRight(x.right)
253 }
254 x = t.rotateLeft(x)
255 }
256 if x.height == h {
257
258
259
260 return
261 }
262 x = x.parent
263 }
264 }
265
266
267
268 func (t *tree) rotateRight(y *node) *node {
269
270 p := y.parent
271 x := y.left
272 b := x.right
273
274 x.checkBalance()
275 y.checkBalance()
276
277 x.setRight(y)
278 y.setLeft(b)
279 t.replaceChild(p, y, x)
280
281 y.update()
282 x.update()
283 return x
284 }
285
286
287
288 func (t *tree) rotateLeft(x *node) *node {
289
290 p := x.parent
291 y := x.right
292 b := y.left
293
294 x.checkBalance()
295 y.checkBalance()
296
297 y.setLeft(x)
298 x.setRight(b)
299 t.replaceChild(p, x, y)
300
301 x.update()
302 y.update()
303 return y
304 }
305
306
307
308 func (t *tree) add(file *File) {
309 pos, parent := t.locate(file.key())
310 if *pos == nil {
311 t.set(file, pos, parent)
312 return
313 }
314 if prev := (*pos).file; prev != file {
315 panic(fmt.Sprintf("file %s (%d-%d) overlaps with file %s (%d-%d)",
316 prev.Name(), prev.Base(), prev.Base()+prev.Size(),
317 file.Name(), file.Base(), file.Base()+file.Size()))
318 }
319 }
320
321
322
323 func (t *tree) set(file *File, pos **node, parent *node) {
324 if x := *pos; x != nil {
325
326
327
328 if true {
329 panic("unreachable according to current FileSet requirements")
330 }
331 x.file = file
332 return
333 }
334 x := &node{file: file, key: file.key(), parent: parent, height: -1}
335 *pos = x
336 t.rebalanceUp(x)
337 }
338
339
340 func (t *tree) delete(pos **node) {
341 t.root.check(nil)
342
343 x := *pos
344 switch {
345 case x == nil:
346
347
348
349 if true {
350 panic("unreachable according to current FileSet requirements")
351 }
352 return
353
354 case x.left == nil:
355 if *pos = x.right; *pos != nil {
356 (*pos).parent = x.parent
357 }
358 t.rebalanceUp(x.parent)
359
360 case x.right == nil:
361 *pos = x.left
362 x.left.parent = x.parent
363 t.rebalanceUp(x.parent)
364
365 default:
366 t.deleteSwap(pos)
367 }
368
369 x.balance = -100
370 x.parent = nil
371 x.left = nil
372 x.right = nil
373 x.height = -1
374 t.root.check(nil)
375 }
376
377
378
379 func (t *tree) deleteSwap(pos **node) {
380 x := *pos
381 z := t.deleteMin(&x.right)
382
383 *pos = z
384 unbalanced := z.parent
385 if unbalanced == x {
386 unbalanced = z
387 }
388 z.parent = x.parent
389 z.height = x.height
390 z.balance = x.balance
391 z.setLeft(x.left)
392 z.setRight(x.right)
393
394 t.rebalanceUp(unbalanced)
395 }
396
397
398
399
400 func (t *tree) deleteMin(zpos **node) (z *node) {
401 for (*zpos).left != nil {
402 zpos = &(*zpos).left
403 }
404 z = *zpos
405 *zpos = z.right
406 if *zpos != nil {
407 (*zpos).parent = z.parent
408 }
409 return z
410 }
411
View as plain text