1
+ package dotty .tools .dotc .util
2
+
3
+ import collection .mutable .ListBuffer
4
+
5
+ /** A simple linked set with `eq` as the comparison, optimized for small sets.
6
+ * It has linear complexity for `contains`, `+`, and `-`.
7
+ */
8
+ abstract class SimpleIdentitySet [+ Elem <: AnyRef ] {
9
+ def size : Int
10
+ def + [E >: Elem <: AnyRef ](x : E ): SimpleIdentitySet [E ]
11
+ def - [E >: Elem <: AnyRef ](x : E ): SimpleIdentitySet [Elem ]
12
+ def contains [E >: Elem <: AnyRef ](x : E ): Boolean
13
+ def foreach (f : Elem => Unit ): Unit
14
+ def toList : List [Elem ] = {
15
+ val buf = new ListBuffer [Elem ]
16
+ foreach(buf += _)
17
+ buf.toList
18
+ }
19
+ def ++ [E >: Elem <: AnyRef ](that : SimpleIdentitySet [E ]) =
20
+ ((this : SimpleIdentitySet [E ]) /: that.toList)(_ + _)
21
+ def -- [E >: Elem <: AnyRef ](that : SimpleIdentitySet [E ]) =
22
+ (this /: that.toList)(_ - _)
23
+ override def toString = toList.mkString(" (" , " , " , " )" )
24
+ }
25
+
26
+ object SimpleIdentitySet {
27
+ object empty extends SimpleIdentitySet [Nothing ] {
28
+ def size = 0
29
+ def + [E <: AnyRef ](x : E ): SimpleIdentitySet [E ] =
30
+ new Set1 [E ](x)
31
+ def - [E <: AnyRef ](x : E ): SimpleIdentitySet [Nothing ] =
32
+ this
33
+ def contains [E <: AnyRef ](x : E ): Boolean = false
34
+ def foreach (f : Nothing => Unit ): Unit = ()
35
+ }
36
+
37
+ private class Set1 [+ Elem <: AnyRef ](x0 : AnyRef ) extends SimpleIdentitySet [Elem ] {
38
+ def size = 1
39
+ def + [E >: Elem <: AnyRef ](x : E ): SimpleIdentitySet [E ] =
40
+ new Set2 [E ](x0, x)
41
+ def - [E >: Elem <: AnyRef ](x : E ): SimpleIdentitySet [Elem ] =
42
+ if (x `eq` x0) empty else this
43
+ def contains [E >: Elem <: AnyRef ](x : E ): Boolean = x `eq` x0
44
+ def foreach (f : Elem => Unit ): Unit = f(x0.asInstanceOf [Elem ])
45
+ }
46
+
47
+ private class Set2 [+ Elem <: AnyRef ](x0 : AnyRef , x1 : AnyRef ) extends SimpleIdentitySet [Elem ] {
48
+ def size = 2
49
+ def + [E >: Elem <: AnyRef ](x : E ): SimpleIdentitySet [E ] = {
50
+ val xs = new Array [AnyRef ](3 )
51
+ xs(0 ) = x0
52
+ xs(1 ) = x1
53
+ xs(2 ) = x
54
+ new SetN [E ](xs)
55
+ }
56
+ def - [E >: Elem <: AnyRef ](x : E ): SimpleIdentitySet [Elem ] =
57
+ if (x `eq` x0) new Set1 (x1)
58
+ else if (x `eq` x1) new Set1 (x0)
59
+ else this
60
+ def contains [E >: Elem <: AnyRef ](x : E ): Boolean = (x `eq` x0) || (x `eq` x1)
61
+ def foreach (f : Elem => Unit ): Unit = { f(x0.asInstanceOf [Elem ]); f(x1.asInstanceOf [Elem ]) }
62
+ }
63
+
64
+ private class SetN [+ Elem <: AnyRef ](xs : Array [AnyRef ]) extends SimpleIdentitySet [Elem ] {
65
+ def size = xs.length
66
+ def + [E >: Elem <: AnyRef ](x : E ): SimpleIdentitySet [E ] = {
67
+ val xs1 = new Array [AnyRef ](size + 1 )
68
+ Array .copy(xs, 0 , xs1, 0 , size)
69
+ xs1(size) = x
70
+ new SetN [E ](xs1)
71
+ }
72
+ def - [E >: Elem <: AnyRef ](x : E ): SimpleIdentitySet [Elem ] = {
73
+ var i = 0
74
+ while (i < size && (xs(i) `ne` x)) i += 1
75
+ if (i == size) this
76
+ else if (size == 3 )
77
+ if (i == 0 ) new Set2 (xs(1 ), xs(2 ))
78
+ else if (i == 1 ) new Set2 (xs(0 ), xs(2 ))
79
+ else new Set2 (xs(0 ), xs(1 ))
80
+ else {
81
+ val xs1 = new Array [AnyRef ](size - 1 )
82
+ Array .copy(xs, 0 , xs1, 0 , i)
83
+ Array .copy(xs, i + 1 , xs1, i, size - (i + 1 ))
84
+ new SetN (xs1)
85
+ }
86
+ }
87
+ def contains [E >: Elem <: AnyRef ](x : E ): Boolean = {
88
+ var i = 0
89
+ while (i < size && (xs(i) `ne` x)) i += 1
90
+ i < size
91
+ }
92
+ def foreach (f : Elem => Unit ): Unit = {
93
+ var i = 0
94
+ while (i < size) { f(xs(i).asInstanceOf [Elem ]); i += 1 }
95
+ }
96
+ }
97
+ }
0 commit comments