1
+ package dotty .tools .dotc .util
2
+
3
+ import collection .mutable .ListBuffer
4
+ import reflect .ClassTag
5
+
6
+ // List Lst
7
+ // 0 0 0
8
+ // 1 1 0
9
+ // 2 2 1
10
+ // 3 3 1
11
+ // 4 4 1
12
+ class Lst [+ T <: AnyRef ](val elems : AnyRef ) extends AnyVal {
13
+ import Lst ._
14
+
15
+ // should be called only if `elems` is an array
16
+ private [this ] def elemTag : ClassTag [T ] = ClassTag [T ](elems.getClass.getComponentType)
17
+
18
+
19
+ def length : Int = elems match {
20
+ case null => 0
21
+ case elems : Array [T ] @ unchecked => elems.length
22
+ case elem : T @ unchecked => 1
23
+ }
24
+
25
+ def isEmpty = elems == null
26
+ def nonEmpty = elems != null
27
+
28
+ inline def foreach (inline op : T => Unit ): Unit = {
29
+ def sharedOp (x : T ) = op(x)
30
+ elems match {
31
+ case null =>
32
+ case elems : Array [T ] @ unchecked =>
33
+ var i = 0
34
+ while (i < elems.length) { sharedOp(elems(i)); i += 1 }
35
+ case elem : T @ unchecked => sharedOp(elem)
36
+ }
37
+ }
38
+
39
+ /** Like `foreach`, but completely inlines `op`, atthe price of generating the code twice.
40
+ * Should be used only of `op` is small
41
+ */
42
+ inline def foreachInlined (inline op : T => Unit ): Unit = elems match {
43
+ case null =>
44
+ case elems : Array [T ] @ unchecked =>
45
+ var i = 0
46
+ while (i < elems.length) { op(elems(i)); i += 1 }
47
+ case elem : T @ unchecked => op(elem)
48
+ }
49
+
50
+ def iterator (): Iterator [T ] = elems match {
51
+ case null => Iterator .empty
52
+ case elems : Array [T ] @ unchecked => elems.iterator
53
+ case elem : T @ unchecked => Iterator .single(elem)
54
+ }
55
+
56
+ def copyToArray [U >: T <: AnyRef ](target : Array [U ], from : Int ) = elems match {
57
+ case null =>
58
+ case elems : Array [T ] @ unchecked => System .arraycopy(elems, 0 , target, from, elems.length)
59
+ case elem : T @ unchecked => target(from) = elem
60
+ }
61
+
62
+ def map [U <: AnyRef : ClassTag ](f : T => U ): Lst [U ] = elems match {
63
+ case null => Empty
64
+ case elems : Array [T ] @ unchecked =>
65
+ val newElems = newArray[U ](elems.length)
66
+ var i = 0
67
+ while (i < elems.length) { newElems(i) = f(elems(i)); i += 1 }
68
+ new Lst (newElems)
69
+ case elem : T @ unchecked => new Lst (f(elem))
70
+ }
71
+
72
+ def mapconserve [U <: AnyRef : ClassTag ](f : T => U ): Lst [U ] = elems match {
73
+ case null => Empty
74
+ case elems : Array [T ] @ unchecked =>
75
+ var newElems : Array [U ] = null
76
+ var i = 0
77
+ while (i < elems.length) {
78
+ val x = elems(i)
79
+ val y = f(x)
80
+ if (newElems != null ) newElems(i) = y
81
+ else if (x `ne` y) {
82
+ newElems = newArray[U ](elems.length)
83
+ System .arraycopy(elems, 0 , newElems, 0 , i)
84
+ newElems(i) = y
85
+ }
86
+ i += 1
87
+ }
88
+ new Lst (newElems)
89
+ case elem : T @ unchecked => new Lst (f(elem))
90
+ }
91
+
92
+ def flatMap [U <: AnyRef : ClassTag ](f : T => Lst [U ]): Lst [U ] = elems match {
93
+ case null => Empty
94
+ case elems : Array [T ] @ unchecked =>
95
+ val newElemss : Array [AnyRef ] = newArray[AnyRef ](elems.length)
96
+ var i = 0
97
+ var len = 0
98
+ while (i < elems.length) {
99
+ val ys = f(elems(i))
100
+ len += ys.length
101
+ newElemss(i) = ys.elems
102
+ i += 1
103
+ }
104
+ if (len == 0 ) Empty
105
+ else if (len == 1 ) {
106
+ i = 0
107
+ while (newElemss(i) == null ) i += 1
108
+ new Lst (newElemss(i))
109
+ }
110
+ else {
111
+ val newElems = newArray[U ](len)
112
+ i = 0
113
+ var j = 0
114
+ while (i < newElemss.length) {
115
+ val ys = new Lst (newElemss(i))
116
+ ys.copyToArray(newElems, j)
117
+ j += ys.length
118
+ i += 1
119
+ }
120
+ new Lst (newElems)
121
+ }
122
+ case elem : T @ unchecked => new Lst (f(elem).elems)
123
+ }
124
+
125
+ def filter (p : T => Boolean ): Lst [T ] = elems match {
126
+ case null => Empty
127
+ case elems : Array [T ] @ unchecked =>
128
+ val scratch = newArray[T ](elems.length)(elemTag)
129
+ var i = 0
130
+ var len = 0
131
+ while (i < elems.length) {
132
+ val x = elems(i)
133
+ if (p(x)) { scratch(len) = x; len += 1 }
134
+ i += 1
135
+ }
136
+ if (len == elems.length) this
137
+ else fromArray(scratch, 0 , len)(elemTag)
138
+ case elem : T @ unchecked =>
139
+ if (p(elem)) this else Empty
140
+ }
141
+ def filterNot (p : T => Boolean ): Lst [T ] = filter(! p(_))
142
+
143
+ def exists (p : T => Boolean ): Boolean = elems match {
144
+ case null => false
145
+ case elems : Array [T ] @ unchecked =>
146
+ var i = 0
147
+ while (i < elems.length && p(elems(i))) i += 1
148
+ i < elems.length
149
+ case elem : T @ unchecked =>
150
+ p(elem)
151
+ }
152
+
153
+ def contains [U >: T ](x : U ): Boolean = elems match {
154
+ case null => false
155
+ case elems : Array [T ] @ unchecked =>
156
+ var i = 0
157
+ while (i < elems.length && elems(i) != x) i += 1
158
+ i < elems.length
159
+ case elem : T @ unchecked =>
160
+ elem == x
161
+ }
162
+
163
+ def forall (p : T => Boolean ): Boolean = elems match {
164
+ case null => true
165
+ case elems : Array [T ] @ unchecked =>
166
+ var i = 0
167
+ while (i < elems.length && p(elems(i))) i += 1
168
+ i == elems.length
169
+ case elem : T @ unchecked =>
170
+ p(elem)
171
+ }
172
+
173
+ def /: [U ](z : U )(op : (U , T ) => U ) = elems match {
174
+ case null => z
175
+ case elems : Array [T ] @ unchecked =>
176
+ var i = 0
177
+ var acc = z
178
+ while (i < elems.length) { acc = op(acc, elems(i)); i += 1 }
179
+ acc
180
+ case elem : T @ unchecked =>
181
+ op(z, elem)
182
+ }
183
+
184
+ def reverse : Lst [T ] = elems match {
185
+ case elems : Array [T ] @ unchecked =>
186
+ val newElems = newArray[T ](elems.length)(elemTag)
187
+ var i = 0
188
+ while (i < elems.length) {
189
+ newElems(elems.length - i) = elems(i)
190
+ i += 1
191
+ }
192
+ new Lst (newElems)
193
+ case _ => this
194
+ }
195
+
196
+ def apply (n : Int ) = elems match {
197
+ case null => throw new IndexOutOfBoundsException (n.toString)
198
+ case elems : Array [T ] @ unchecked => elems(n)
199
+ case elem : T @ unchecked =>
200
+ if (n == 0 ) elem else throw new IndexOutOfBoundsException (n.toString)
201
+ }
202
+
203
+ def head = apply(0 )
204
+ def last = apply(length - 1 )
205
+
206
+ def headOr [U >: T ](alt : => U ): U = if (length == 0 ) alt else head
207
+
208
+ def drop (n : Int ): Lst [T ] =
209
+ if (n <= 0 ) this
210
+ else elems match {
211
+ case null => this
212
+ case elems : Array [T ] @ unchecked => fromArray(elems, n, elems.length)(elemTag)
213
+ case elem : T @ unchecked => Empty
214
+ }
215
+
216
+ def tail = drop(1 )
217
+
218
+ def take (n : Int ): Lst [T ] =
219
+ if (n <= 0 ) Empty
220
+ else elems match {
221
+ case null => this
222
+ case elems : Array [T ] @ unchecked => fromArray(elems, 0 , n min elems.length)(elemTag)
223
+ case elem : T @ unchecked => this
224
+ }
225
+
226
+ def ++ [U >: T <: AnyRef : ClassTag ](that : Lst [U ]): Lst [U ] =
227
+ if (elems == null ) that
228
+ else if (that.elems == null ) this
229
+ else {
230
+ val len1 = this .length
231
+ val len2 = that.length
232
+ val newElems = newArray[U ](len1 + len2)
233
+ this .copyToArray(newElems, 0 )
234
+ that.copyToArray(newElems, len1)
235
+ new Lst (newElems)
236
+ }
237
+
238
+ def zipWith [U <: AnyRef , V <: AnyRef : ClassTag ](that : Lst [U ])(op : (T , U ) => V ): Lst [V ] =
239
+ this .elems match {
240
+ case null => Empty
241
+ case elems1 : Array [T ] @ unchecked =>
242
+ that.elems match {
243
+ case null => Empty
244
+ case elems2 : Array [U ] @ unchecked =>
245
+ val len = elems1.length min elems2.length
246
+ if (len == 0 ) Empty
247
+ else if (len == 1 ) new Lst (op(elems1(0 ), elems2(0 )))
248
+ else {
249
+ var newElems : Array [V ] = null
250
+ var i = 0
251
+ while (i < len) {
252
+ val x = elems1(i)
253
+ val y = op(x, elems2(i))
254
+ if (newElems != null ) newElems(i) = y
255
+ else if (x `ne` y) {
256
+ newElems = newArray[V ](len)
257
+ System .arraycopy(elems, 0 , newElems, 0 , i)
258
+ newElems(i) = y
259
+ }
260
+ i += 1
261
+ }
262
+ new Lst (newElems)
263
+ }
264
+ case elem2 : U @ unchecked =>
265
+ new Lst (op(elems1(0 ), elem2))
266
+ }
267
+ case elem1 : T @ unchecked =>
268
+ that.elems match {
269
+ case null => Empty
270
+ case elems2 : Array [U ] @ unchecked => new Lst (op(elem1, elems2(0 )))
271
+ case elem2 : U @ unchecked => new Lst (op(elem1, elem2))
272
+ }
273
+ }
274
+
275
+ def zip [U <: AnyRef ](that : Lst [U ]): Lst [(T , U )] = zipWith(that)((_, _))
276
+
277
+ def zipWithIndex : Lst [(T , Int )] = elems match {
278
+ case null => Empty
279
+ case elems : Array [T ] @ unchecked =>
280
+ val newElems = newArray[(T , Int )](elems.length)
281
+ var i = 0
282
+ while (i < elems.length) { newElems(i) = (elems(i), i); i += 1 }
283
+ new Lst (newElems)
284
+ case elem : T @ unchecked =>
285
+ new Lst ((elem, 0 ))
286
+ }
287
+
288
+ def corresponds [U <: AnyRef ](that : Lst [U ])(p : (T , U ) => Boolean ): Boolean =
289
+ (this .elems `eq` that.elems) || {
290
+ this .elems match {
291
+ case null => that.elems == null
292
+ case elems1 : Array [T ] @ unchecked =>
293
+ that.elems match {
294
+ case null => false
295
+ case elems2 : Array [U ] @ unchecked =>
296
+ val len = elems1.length
297
+ len == elems2.length && {
298
+ var i = 0
299
+ while (i < len && p(elems1(i), elems2(i))) i += 1
300
+ i == len
301
+ }
302
+ }
303
+ }
304
+ }
305
+
306
+ def eqElements [U <: AnyRef ](that : Lst [U ]): Boolean = corresponds(that)(eqFn)
307
+ def equalElements [U <: AnyRef ](that : Lst [U ]): Boolean = corresponds(that)(equalsFn)
308
+ }
309
+
310
+ object Lst {
311
+ def newArray [T <: AnyRef ](len : Int )(implicit tag : ClassTag [T ]): Array [T ] =
312
+ java.lang.reflect.Array .newInstance(tag.runtimeClass, len).asInstanceOf [Array [T ]]
313
+
314
+ val Empty = new Lst (null )
315
+
316
+ def apply [T <: AnyRef ](): Lst [T ] = Empty
317
+
318
+ def apply [T <: AnyRef ](x0 : T ): Lst [T ] = new Lst (x0)
319
+
320
+ def apply [T <: AnyRef : ClassTag ](x0 : T , x1 : T ): Lst [T ] = {
321
+ val elems = newArray[T ](2 )
322
+ elems(0 ) = x0
323
+ elems(1 ) = x1
324
+ new Lst (elems)
325
+ }
326
+
327
+ def apply [T <: AnyRef : ClassTag ](x0 : T , x1 : T , x2 : T ): Lst [T ] = {
328
+ val elems = newArray[T ](3 )
329
+ elems(0 ) = x0
330
+ elems(1 ) = x1
331
+ elems(2 ) = x2
332
+ new Lst (elems)
333
+ }
334
+
335
+ def apply [T <: AnyRef : ClassTag ](x0 : T , x1 : T , x2 : T , x3 : T ): Lst [T ] = {
336
+ val elems = newArray[T ](4 )
337
+ elems(0 ) = x0
338
+ elems(1 ) = x1
339
+ elems(2 ) = x2
340
+ elems(3 ) = x3
341
+ new Lst (elems)
342
+ }
343
+
344
+ def apply [T <: AnyRef : ClassTag ](x0 : T , x1 : T , x2 : T , x3 : T , x4 : T , xs : T * ): Lst [T ] = {
345
+ val elems = newArray[T ](5 + xs.length)
346
+ elems(0 ) = x0
347
+ elems(1 ) = x1
348
+ elems(2 ) = x2
349
+ elems(3 ) = x3
350
+ elems(4 ) = x4
351
+ xs.copyToArray(elems, 5 )
352
+ new Lst (elems)
353
+ }
354
+
355
+ val eqFn = (x : AnyRef , y : AnyRef ) => x `eq` y
356
+ val equalsFn = (x : AnyRef , y : AnyRef ) => x `equals` y
357
+
358
+ class Buffer [T <: AnyRef : ClassTag ] {
359
+ var len = 0
360
+ private var elem : T = _
361
+ private var elems : Array [T ] = _
362
+
363
+ def += (x : T ) = {
364
+ if (len == 0 ) elem = x
365
+ else {
366
+ if (len == 1 ) {
367
+ elems = newArray[T ](16 )
368
+ elems(0 ) = elem
369
+ }
370
+ else if (len == elems.length) {
371
+ val newElems = newArray[T ](elems.length * 2 )
372
+ System .arraycopy(elems, 0 , newElems, 0 , elems.length)
373
+ elems = newElems
374
+ }
375
+ elems(len) = x
376
+ }
377
+ len += 1
378
+ }
379
+
380
+ def toLst : Lst [T ] =
381
+ if (len == 0 ) Empty
382
+ else if (len == 1 ) new Lst (elem)
383
+ else fromArray(elems, 0 , len)
384
+ }
385
+
386
+ def fromArray [T <: AnyRef : ClassTag ](elems : Array [T ], start : Int , end : Int ) = {
387
+ val len = end - start
388
+ if (len <= 0 ) Empty
389
+ else if (len == 1 ) new Lst (elems(start))
390
+ else if (start == 0 && end == elems.length) new Lst (elems)
391
+ else {
392
+ val newElems = newArray[T ](len)
393
+ System .arraycopy(elems, start, newElems, 0 , len)
394
+ new Lst (newElems)
395
+ }
396
+ }
397
+ }
0 commit comments