-
Notifications
You must be signed in to change notification settings - Fork 11
/
Collections.ns
2364 lines (2267 loc) · 69.6 KB
/
Collections.ns
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
Newspeak3
'Root'
class Collections usingPlatform: p = (
(*
Newspeak collections library.
This code was derived by converting the Strongtalk Collections classes to Newspeak, which is why the Sun Microsystems copyright and BSD license below applies.
Copyright (c) 1995-2006 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
Copyright 2008-2009 Yardena Meymann, Gilad Bracha and other contributors.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistribution in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/o other materials provided with the distribution.
Neither the name of Sun Microsystems or the names of contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
>>
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.>> *)
| private MutableAddableList = MutableList mixinApply: AddableList. (* -- streams -- *) private ListReadStream = p streams SeqCltnReadStream. private ListReadWriteStream = p streams SeqCltnReadWriteStream. (* magic collections *) (* Not yet supported by NS2JS or NS2Dart *) public WeakArray = Future computing: [p squeak WeakArray]. |) (
class AbstractList = Collection (
(* This class implements the read-only protocol for indexed collections that order their elements using integer indices. *)
) (
public , other <List[X]> ^<MutableList[E | X]> = (
^self copyReplaceFrom: size + 1 to: size with: other
)
public allButFirst ^ <MutableList[E]> = (
^copyFrom: 2 to: size
)
public allButLast ^ <MutableList[E]> = (
^copyFrom: 1 to: size - 1
)
public anyOne = (
^ first
)
public at: index <Integer> ^<E> = (
subclassResponsibility
)
public at: index <Integer> ifAbsent: fail <[X def]> ^<E|X> = (
^(index between: 1 and: size)
ifTrue: [ at: index ]
ifFalse: [ fail value ]
)
binarySearchFor: el <EL>
between: start <Integer>
and: end <Integer>
toCompare: compare <[:EL def :EL| Boolean]>
^<Int>
= (
(* {where CONSTRAINER <EL> is returnType of #anElement message of receiverType} *)
(* This does a binary search for the index such that if el was inserted before it
the receiver would remain sorted. The receiver must be sorted relative to the
comparison block. The comparison block should return true if the first block argument
cannot appear after the second block argument *)
| low <Integer> high <Integer> |
low:: start.
high:: end.
[ low <= high ]
whileTrue:
[ | mid <Integer> |
mid:: (low + high) // 2.
(* The guaranteed below is safe because of the inference clause *)
(compare value: (
(* guaranteed <EL> *) (at: mid)) value: el)
ifTrue: [ low:: mid + 1 ]
ifFalse: [ high:: mid - 1 ].
].
^low
)
public binarySearchFor: el <EL>
toCompare: compare <[:EL def :EL| Boolean]>
^ <Integer>
= (
#BOGUS. (* Remove me. *)
(* {where CONSTRAINER <EL> is returnType of #anElement message of receiverType} *)
(* The guarantee is safe because of the inference clause *)
^(
(* guaranteed <List[EL]> *) self)
binarySearchFor: el
between: 1
and: size
toCompare: compare
)
public collect: map <[:E | R def]> ^<List[R]> = (
^collectUsingAtPut: map
)
protected collectUsingAtPut: map <[:E | R def]> ^<List[R]> = (
| c <MutableList[R]> |
(* See #newForCollect: for explanation of why the guarantee is safe *)
c:: (* guaranteed <MutableList[R]> ( *)newForCollectUsingAtPut: size(* ) *).
1 to: self size do:
[:i <Integer> |
c at: i put: (map value: (at: i)) ].
^c
)
collection: cltn <List[Object]>
matchesElementsAt: index <Integer>
^<Boolean> = (
(* Test whether we contain the given subcollection at index. This method assumes
that there are at least as many elements in this collection after index as cltn size *)
| offset <Integer> |
offset:: index - 1.
1 to: cltn size do:
[:i <Integer> |
(cltn at: i) = (at: i+offset)
ifFalse: [ ^false ] ].
^true
)
public copyFrom: start <Integer> to: stop <Integer> ^<MutableList[EX]> = (
(* {where EX is returnType of #anElement message of receiverType} *)
(* The guarantee is typesafe since the inference clause guarantees that E < EX at the call site *)
| cp <MutableList[EX]> safeme <List[EX]> |
safeme:: (* guaranteed <List[EX]> *) self.
cp:: (* guaranteed <MutableList[EX]> *)
newCopyOfSize: (stop - start) + 1 thatCanAlsoHoldElementsOf: safeme.
cp replaceFrom: 1 to: cp size with: safeme startingAt: start.
^cp
)
public copyReplaceAll: oldSub <List[Object]> with: newSub <List[X]> ^<MutableList[EX | X]> = (
(* {where EX is returnType of #anElement message of receiverType;
where X is returnType of #anElement message of arg 2} *)
| spots <List[Integer]>
subDelta <Integer>
copy <MutableList[EX | X]>
current <Integer>
offset <Integer>
newSubSize <Integer>
oldSubSize <Integer>
safeself <List[EX]>
|
newSubSize:: newSub size.
oldSubSize:: oldSub size.
subDelta:: newSub size - oldSubSize.
spots:: indicesOfSubCollection: oldSub.
(* This guarantee is typesafe since the inference clause guarantees that E < EX at the call site *)
safeself:: (* guaranteed <List[EX]> *) self.
spots size = 0
ifTrue: [ copy:: safeself newCopyOfSize: size
thatCanAlsoHoldElementsOf: newSub.
copy replaceFrom: 1 to: size with: safeself.
^copy
].
copy:: safeself newCopyOfSize: size + (spots size * subDelta)
thatCanAlsoHoldElementsOf: newSub.
current:: 1.
offset:: 0.
spots do:
[:spot <Int> | | offspot <Int> |
offspot:: spot + offset.
(* copy segment of self before the next occurrence *)
copy replaceFrom: current + offset
to: offspot - 1
with: safeself
startingAt: current.
(* copy the new subcollection at the next occurrence *)
copy replaceFrom: offspot
to: (offspot + newSubSize) - 1
with: newSub.
current:: spot + oldSubSize.
offset:: offset + subDelta. ].
(* copy the final segment from self after the last occurrence *)
copy replaceFrom: current + offset
to: copy size
with: safeself
startingAt: current.
^copy
)
copyReplaceFrom: start <Integer> to: stop <Integer> with: other <List[X]> ^<MutableList[EX | X]> = (
(* {where EX is returnType of #anElement message of receiverType;
where X is returnType of #anElement message of arg 3} *)
| copy <MutableList[EX | X]>
sizeChange <Integer>
sz <Integer>
afterNew <Integer>
safeself <List[EX]> |
(* The guarantee is typesafe since the inference clause guarantees that E < EX at the call site *)
safeself:: (* guaranteed <List[EX]> *) self.
sizeChange:: other size - ((stop - start) + 1).
sz:: size.
copy:: safeself newCopyOfSize: sz + sizeChange
thatCanAlsoHoldElementsOf: other.
afterNew:: start + other size.
copy replaceFrom: 1 to: start - 1 with: safeself startingAt: 1.
copy replaceFrom: start to: afterNew - 1 with: other.
copy replaceFrom: afterNew to: copy size with: (
(* guaranteed <List[EX]> *) self) startingAt: stop + 1.
^copy
)
public copyWith: element <X> ^<MutableList[E | X]> = (
^self , {element}
)
public copyWithSize: s <Integer> ^<MutableList[EX]> = (
(* {where EX is returnType of #anElement message of receiverType} *)
(* return a mutable copy of the receiver of a different size, that is either truncated
or extended with nils as necessary. Note this works even if the receiver itself
is not mutable *)
(* %note: the inference clause above is a tricky way of doing something very difficult:
it allows us to effectively return a mutable copy of the receiver in a typesafe way,
even though the
receiver itself may not be mutable. This would be impossible to type reasonably
without the inference clause, because we would have to have a return type of
<MutableList[E]>, which isn't typesafe since E is a 'covariant' generic variable of this
class, whereas E is an 'unrelated' generic variable in MutableList. - D.G. *)
(* %note: The inference clause above should really read ... EX <E> ..., but the type
system implementation for some reason can't deal with implementations
of such a method in subclasses that have bound E (i.e. are not generic on E).
For an example, see the implementation in ReadString, which would not have to
have a guarantee in the method body if this worked right - D.G. *)
subclassResponsibility
)
public copyWithout: el <Object> ^<MutableList[EX]> = (
(* {where EX is returnType of #anElement message of receiverType} *)
| safeself <List[EX]> |
(* The following guarantee is safe because the inference clause ensures that E < EX
at the call site *)
safeself:: (* guaranteed <List[EX]> *) self.
^safeself copyReplaceAll: (Array(* [Object] *) with: el) with: {}
)
public do: f <[:E]> = (
1 to: size do:
[:i <Integer> |
f value: (at: i) ]
)
public doWithIndex: f <[:E :Integer]> = (
1 to: size do:
[:i <Integer> |
f value: (at: i) value: i]
)
public findFirst: predicate <[:E| Boolean]> ^<Integer> = (
1 to: size do:
[:i <Integer> |
(predicate value: (at: i))
ifTrue: [ ^i ] ].
^0
)
public findLast: predicate <[:E| Boolean]> ^<Integer> = (
size to: 1 by: -1 do:
[:i <Integer> |
(predicate value: (at: i))
ifTrue: [ ^i ] ].
^0
)
public first ^<E> = (
^self at: 1
)
public hasSameElementsAndOrderAs: other <List[Object]> ^<Boolean> = (
#ACCESSBOGUS.
(* Like #hasSameElementsAs:, but also requires the elements to be in the same order *)
size = other size
ifFalse: [ ^false ].
1 to: size do:
[:i <Integer> |
(at: i) = (other at: i)
ifFalse: [ ^false ] ].
^true
)
public hash ^<Integer> = (
(* This function should not be changed, since it is designed to produce the
same results as the identityHash primitive, for strings and symbols *)
| sz <Integer> val <Integer> |
sz:: size.
sz < 2
ifTrue: [ ^sz = 1 ifTrue: [ self hashAt: 1 ] ifFalse: [ 1 ] ].
val:: hashAt: 1.
val:: (val bitShift: 3) bitXor: ((hashAt: 2) bitXor: val).
val:: (val bitShift: 3) bitXor: ((hashAt: sz) bitXor: val).
val:: (val bitShift: 3) bitXor: ((hashAt: sz - 1) bitXor: val).
val:: (val bitShift: 3) bitXor: ((hashAt: (sz bitShift: -1) + 1) bitXor: val).
val:: (val bitShift: 3) bitXor: (sz bitXor: val).
(* mask it to 20 bits to match VM *)
val:: val bitAnd: 16rFFFFF.
^val
)
protected hashAt: index <Integer> ^<Integer> = (
^(at: index) hash
)
protected includesIndex: index <Integer> ^<Boolean> = (
^index between: 1 and: size
)
public indexOf: element <Object> ^<Integer> = (
^self indexOf: element ifAbsent: [ 0 ]
)
public indexOf: element <Object> ifAbsent: f <[X def]> ^<Integer | X> = (
1 to: size do:
[:index <Integer> |
(at: index) =
element ifTrue: [^index]].
^f value
)
indexOfSubCollection: sub <List[Object]>
startingAt: index <Integer>
^<Integer> = (
^indexOfSubCollection: sub
startingAt: index
ifAbsent: [ error: 'subcollection not found' ]
)
indexOfSubCollection: sub <List[Object]>
startingAt: index <Integer>
ifAbsent: f <[X def]>
^<Integer | X> = (
index to: (size - sub size) + 1 do:
[:i <Integer> |
(collection: sub matchesElementsAt: i)
ifTrue: [ ^i ] ].
^f value
)
indicesOfSubCollection: sub <List[Object]> ^<List[Int]> = (
^indicesOfSubCollection: sub startingAt: 1
)
indicesOfSubCollection: sub <List[Object]>
startingAt: index <Integer>
^<List[Integer]> = (
| indices <MutableArrayList[Integer]> subSize <Integer> current <Integer> |
indices:: MutableArrayList(* [Int] *) new.
subSize:: sub size.
current:: index.
[ current:: self indexOfSubCollection: sub startingAt: current ifAbsent: [ 0 ].
current = 0
] whileFalse:
[ indices addLast: current.
current:: current + subSize. ].
^indices
)
public isKindOfList ^ <Boolean> = (
^true
)
public isSequenceable = (
^true
)
isSortedBy: compare <[:E :E | Boolean]> ^<Boolean> = (
(* Returns true if the receiver is in sorted order, using the specified comparison *)
| last <E> |
size < 2
ifTrue: [ ^true ].
last:: at: 1.
2 to: size do:
[:i <Integer> |
(compare value: last value: (at: i))
ifFalse: [ ^false ] ].
^true
)
public keysAndValuesDo: action <[:Integer :E]> = (
1 to: size do:
[:index <Integer> |
action value: index value: (at: index)]
)
public last ^<E> = (
^self at: self size
)
public newCopyOfSize: size <Integer>
thatCanAlsoHoldElementsOf: other <List[X]>
^<MutableList[EX | X]>
= (
(* {where X is returnType of #anElement message of arg 2;
where EX is returnType of #anElement message of receiverType} *)
(* Return a fresh collection of a closely related type
that can hold both elements of self and elements of the other collection *)
^Array(* [EX | X] *) new: size
)
newForCollectUsingAtPut: size <Integer> ^<MutableList[Object]> = (
(* Return a new extensible collection that is as closely related to the receiver's class as possible. The
returned collection must be unaliased and empty, so it is safe for the caller to guarantee that the type
variable is of a more specific type *)
^Array(* [Object] *) new: size
)
public readStream ^<ReadStream[E]> = (
^ListReadStream on: self
)
public reverse ^<MutableList[EX]> = (
(* {where EX is returnType of #anElement message of receiverType} *)
(* The guarantees are typesafe since the inference clause guarantees that E < EX at the call site *)
| copy <MutableList[EX]> |
#BOGUS. (* #reverse implies an in-place operation, should be #reversed *)
copy:: (* guaranteed <MutableList[EX]> *)
(newCopyOfSize: size thatCanAlsoHoldElementsOf: self).
1 to: size do:
[:i <Integer> |
| el <EX> |
el:: (
(* guaranteed <MutableList[EX]> *) self) at: i.
copy at: size + 1 - i put: el. ].
^copy
)
public reverseDo: action <[:E]> = (
size to: 1 by: -1 do:
[:index <Integer> |
action value: (at: index)]
)
public size ^<Integer> = (
subclassResponsibility
)
public species ^<Collection[E] class> = (
^Array(* [E] *)
)
public with: other <List[X def]> do: action <[:E :X]> = (
assert: [ self size = other size ] message: 'Cannot jointly interate collections of different size'.
1 to: size do:
[:index <Integer> |
action value: (at: index) value: (other at: index)].
)
) : (
)
class AddableList = AbstractList (
(* AddableLists are Lists that support the Extensible protocol, and which support indexing in constant time. *)
|
protected contents <Array[E]>
protected startGap <Integer> (* number of empty slots at the beginning of contents *)
protected lastIndex <Integer> (* (internal) index of last occupied table entry *)
|initCapacity: self class defaultCapacity) (
public add: e <E> ^<E> = (
subclassResponsibility
)
public addAll: c <Collection[E]> ^<Collection[E]> = (
c do: [:el <E> |
add: el ].
^c
)
public at: i <Integer> ^<E> = (
| adjusted <Int> |
adjusted:: i + startGap.
((0 < i) and: [adjusted <= self lastIndex])
ifFalse: [ error: 'invalid index' ].
^contents at: adjusted
)
public at: i <Integer> ifAbsent: f <[X def]> ^<E | X> = (
| internal <Int> |
internal:: i + self startGap.
^(internalIndexIsValid: internal)
ifTrue: [ contents at: internal ]
ifFalse: [ f value ]
)
public copyWithSize: s <Integer> ^<MutableList[EX]> = (
(* {where EX is returnType of #anElement message of receiverType} *)
| safeself <List[EX]> |
(* This guarantee is safe because the inference clause guarantees
that E < EX at each call site *)
safeself:: (* guaranteed <List[EX]> *) self.
^(Array(* [EX] *) new: s)
replaceFrom: 1 to: (s min: size) with: safeself
)
public do: action <[:E]> = (
startGap + 1 to: lastIndex do:
[:index <Integer> | action value: (contents at: index) ]
)
endGap ^<Integer> = (
^contents size - lastIndex
)
firstIndex ^<Integer> = (
^1 + startGap
)
public include: e <E> ^<E> = (
^include: e ifNew: []
)
public include: e <E> ifNew: blk <[]> ^<E> = (
(includes: e)
ifFalse: [ add: e.
blk value. ].
^e
)
public includeAll: c <Collection[E]> ^<Collection[E]> = (
c do: [:el <E> |
include: el ].
^c
)
public indexOf: el <Object> ifAbsent: f <[X def]> ^<Integer | X> = (
1 to: size do: [:i <Integer> |
(at: i) = el
ifTrue: [ ^i ]. ].
^f value
)
public initCapacity: c <Integer> = (
(* Need proper factories to pass initial capacity and make this non-public. *)
contents:: Array(* [E] *) new: c.
startGap:: 0.
lastIndex:: 0.
)
internalIndexIsValid: index <Integer> ^<Boolean> = (
^index > startGap and: [ index <= lastIndex ]
)
internalRangeCheck: index <Integer> = (
(internalIndexIsValid: index )
ifFalse: [ error: 'invalid index' ].
)
makeSpace: slots <Integer> beforeIndex: i <Integer> ^<Integer> = (
(* assume: i is a valid internal index. The index is returned, adjusted
for any resizing of the internal array that may have taken place
(i.e. the index of the beginning of the created gap is returned) *)
(* # before i is (i - startGap) - 1, # after is (lastIndex - i) + 1 *)
^((i - startGap) - 1) > ((lastIndex - i) + 1)
ifTrue: [ (* fewer elements after, so move them *)
needSpaceAtEnd: slots.
contents
replaceFrom: i + slots
to: lastIndex + slots
with: contents
startingAt: i.
lastIndex:: lastIndex + slots.
i ]
ifFalse: [ (* fewer elements before, so move them *)
| newI <Integer> |
newI:: i + (needSpaceAtStart: slots) - slots.
contents
replaceFrom: (startGap + 1) - slots
to: newI - 1
with: contents
startingAt: startGap + 1.
startGap:: startGap - slots.
newI ].
)
makeSpaceAtStart: nslots <Integer> ^<Integer> = (
(* Make sure that there are at least nslots of unused capacity at the low
end of contents. The # of slots added at the beginning is returned. *)
| newGap <Integer>
diff <Integer>
newContents <AbsoluteArray[E]>
sz <Integer>
newLastIndex <Integer> |
(isEmpty and: [nslots <= contents size])
ifTrue: [startGap: nslots.
lastIndex: nslots.
^nslots].
sz:: size.
newGap:: nslots max: sz.
diff:: newGap - startGap.
newLastIndex:: newGap + sz.
newContents:: Array(* [E] *) new:
contents size + diff.
newContents
replaceFrom: newGap + 1
to: newLastIndex
with: contents
startingAt: firstIndex.
startGap: newGap.
contents: newContents.
lastIndex: newLastIndex.
^diff
)
needSpaceAtEnd: slots <Integer> = (
slots > endGap
ifTrue: [ contents:
(contents copyWithSize:
contents size + (slots max: size) )]
)
needSpaceAtStart: nslots <Integer> ^<Integer> = (
(* Make sure that there are at least nslots of unused capacity at the low
end of contents. The # of slots added at the beginning is returned. *)
^nslots > startGap
ifTrue: [makeSpaceAtStart: nslots]
ifFalse: [ 0 ]
)
public postCopy = (
super postCopy.
(* We potentially may change the size of the contents array so that this can work for copyWithSize:
as well *)
contents: (contents copyWithSize: (contents size max: lastIndex))
)
public remove: el <E> ^<E> = (
^remove: el
ifAbsent: [ error: 'element not found' ]
)
public remove: nElements <Integer> at: i <Integer> = (
| el <E> internal <Integer> |
el:: at: i.
internal:: startGap + i.
internalRangeCheck: internal.
internalRangeCheck: (internal + nElements) - 1.
internal to: lastIndex - nElements
do: [:index <Integer> |
contents at: index put: (contents at: index + nElements). ].
contents at: lastIndex put: nil.
lastIndex: lastIndex - nElements.
)
public remove: el <E> ifAbsent: f <[X def]> ^<E|X> = (
removeAt: (indexOf: el ifAbsent: [^f value]).
^el
)
public removeAll = (
startGap + 1 to: lastIndex do:
[:i <Integer> |
contents at: i put: nil].
lastIndex: startGap
)
public removeAll: c <Collection[E]> ^<Collection[E]> = (
c do: [:el <E> |
remove: el ].
^c
)
public removeAllSuchThat: test <[:E | Boolean]> = (
| i <Integer> |
i:: 1.
[ i <= size ]
whileTrue:
[ (test value: (at: i))
ifTrue: [ removeAt: i ]
ifFalse: [ i:: i + 1 ] ]
)
public removeAt: index <Integer> ^<E> = (
| el <E> |
el:: at: index.
remove: 1 at: index.
^el
)
public removeEvery: val <E> ^<E> = (
^removeEvery: val startingAt: 1
)
public removeEvery: val <X def> startingAt: start <Integer> ^<X> = (
| index <Integer> |
index:: indexOf: val ifAbsent: [ ^val ].
removeAt: index.
^removeEvery: val startingAt: index
)
public removeFirst ^<E> = (
^removeAt: 1
)
public removeLast ^<E> = (
^removeAt: size
)
public size ^<Integer> = (
^lastIndex - startGap
)
public size: s <Integer> = (
(* Change the size of the ordered collection to s (not the capacity). This will truncate elements at the end if the current size
is larger. If the current size is smaller, the added elements will be undefined, in which case it is erroneous to access them until they have been set.
This method should be used very rarely and carefully as a result. *)
| delta <Integer> newLastIndex <Integer> |
delta:: s - size.
newLastIndex:: lastIndex + delta.
delta < 0
ifTrue: [ newLastIndex + 1 to: lastIndex do:
[:i <Integer> |
contents at: i put: nil]].
delta > 0
ifTrue: [ needSpaceAtEnd: delta ].
lastIndex: lastIndex + delta.
)
public sort: compare <[:E :E | Boolean]> = (
(* In-place sort. *)
lastIndex < firstIndex ifTrue: [^self].
contents
mergeSortFrom: firstIndex
to: lastIndex
by: compare
)
) : (
public defaultCapacity ^<Integer> = (
^5
)
public new: capacity <Integer> ^<Instance> = (
^new initCapacity: capacity
)
public with: val1 <E> ^<Instance> = (
^(new: 1) add: val1; yourself
)
public withAll: cltn <Collection[E]> ^<Instance> = (
^(new: cltn size) addAll: cltn; yourself
)
)
public class Association key: k value: v = (
(* Associates an object of type K with an object of type V. *)
|
public key <K> ::= k.
public value <V> ::= v.
|) (
public = other <Object> ^<Boolean> = (
(* | othera <Assoc[Object,Object]> | *)
(* %todo: replace Association with Assoc when typecase is fully impl *)
(* othera:: Association[Object,Object] coerce: other else: [ ^false ]. *)
^key = other key and: [ value = other value ].
)
public copy = (
^class key: key value: value
)
public hash ^<Integer> = (
^key hash bitXor: value hash
)
public printOn: strm <CharOutputStream> = (
key printOn: strm.
strm nextPutAll: ' -> '.
value printOn: strm.
)
) : (
public new ^<Instance> = (
self warnObsolete.
^self key: nil value: nil
)
)
public class Collection = (
(* A Collection is an object that represents a group of objects.
The only message that must be implemented by subclasses is the #do: message.
All other Collection messages are then defined in terms of #do:.
%responsibility size
Subclasses usually reimplement the #size message if possible, since the
implementation provided in this class is very inefficient.
%responsibility collect:
Subclasses may wish to consider overriding the #collect: (and #select: and #reject:)
messages to specialize their return
types to match the receiver type more closely. *)
) (
public allSatisfy: predicate <[:E | Boolean]> ^<Boolean> = (
self do: [:each | (predicate value: each) ifFalse: [^false]].
^true
)
public anySatisfy: predicate <[:E | Boolean]> ^<Boolean> = (
self do: [:each | (predicate value: each) ifTrue: [^true]].
^false
)
public asArray ^<Array[E]> = (
|
array <Array[E]> = Array new: size.
index <Integer> ::= 1.
|
self do: [:element <E> |
array at: index put: element.
index:: index + 1].
^array
)
public asCollection = (
(* Squeak 5.0 *)
^self
)
public asMutableArrayList ^<MutableArrayList[EX]> = (
(* {where EX is returnType of #anElement message of receiverType} *)
(* Return a new MutableArrayList holding the elements of this collection. The element type of the ordered collection
is whatever the static type of the receiver is at the point of send. *)
^MutableArrayList(* [EX] *) withAll: (* (guaranteed <CollectionEX]> *)self(* ) *)
)
public asSet ^<Extensible[EX]> = (
(* Return a new extensible collection holding the elements of this collection. *)
^Set(* [EX] *) withAll: (* (guaranteed <Collection[EX]> *)self(* ) *)
)
public asSortedList ^<List[Object]> = (
(* This message is NOT typesafe, and should only be used for compatibility reasons, since there is
no way of knowing whether the elements of this collection support #< or not. You should use
#asSortedList: instead, if possible *)
^SortedList(* [Object] *) withAll: self
)
public asSortedList: sortPredicate <[:E :EX | Boolean]> ^ <SortedList[EX]> = (
(* { where EX is arg 1 of #value:value: message of arg 1 } *)
(* Return a new sorted collection ordered by the given sortPredicate. Note that Magnitude
supports the defaultSort message for convenience, so that for example if you have a collection
of strings strc, you can say:
strc asSortedList: String defaultSort
*)
(* This is typesafe despite the guarantee because the inference clause requires that E = EX at the
call site *)
^(SortedList(* [EX] *) new: size sortBlock: (* (guaranteed <[EX,EX,^Boolean]> *)sortPredicate(* ) *))
addAll: (* (guaranteed <Collection[EX]> *)self(* ) *); yourself
)
public collect: map <[:E | R def]> ^<Collection[R]> = (
^self collectUsingAdd: map
)
protected collectUsingAdd: map <[:E | R def]> ^<Collection[R]> = (
| c |
(* See #newForCollect: for explanation of why the guarantee is safe *)
c:: (newForCollectUsingAdd: size).
do: [:e | c add: (map value: e) ].
^c
)
public copy = (
#BOGUS. (* Questionable. Probably should be shallowCopy if we keep it. *)
^self class withAll: self
)
public detect: predicate <[:E | Boolean]> ^<E> = (
^self detect: predicate ifNone: [Error signal: 'No matching element detected']
)
public detect: aBlock ifFound: foundBlock ifNone: exceptionBlock = (
self
do: [ :each |
(aBlock value: each)
ifTrue: [ ^ foundBlock cull: each ] ].
^ exceptionBlock value
)
public detect: predicate <[:E | Boolean]> ifNone: fail <[X def]> ^<E | X> = (
self do: [:element | (predicate value: element) ifTrue: [^element]].
^fail value
)
public do: action <[:E]> = (
subclassResponsibility
)
public do: action <[:E]> separatedBy: betweenAction <[]> = (
(* Useful when you need to do something 'between' elements (i.e. not before the first one, and not after the last one). [action] is evaluated the same way as for #do:, but [betweenAction] is evaluated once between each pair of elements. *)
| firstTime <Boolean> ::= true. |
firstTime:: true.
self do:
[:element <E> |
firstTime
ifTrue: [firstTime:: false]
ifFalse: [betweenAction value].
action value: element].
)
public flatMap: map <[:E | R def]> ^<Collection[R]> = (
^(collect: map) flatten
)
public flatten ^ <Collection[E]> = (
| totalSize <Integer> ::= 0. c |
do: [:e <E> | totalSize:: totalSize + (e isKindOfCollection ifTrue: [e size] ifFalse: [1])].
c:: newForCollectUsingAdd: totalSize.
do: [:e <E> | e isKindOfCollection ifTrue: [e do: [:x | c add: x]] ifFalse: [c add: e]].
^c
)
public hash ^<Integer> = (
| count ::= 0. |
^self inject: 0 into:
[:previousHash <Integer> :element <E> |
| newHash |
newHash:: previousHash bitXor: element hash.
count:: count + 1.
count > 2 ifTrue: [^newHash].
newHash]
)
public includes: o <Object> ^<Boolean> = (
self do: [:element <E> | element = o ifTrue: [^true]].
^false
)
public inject: initialValue <X> into: foldBlock <[:X def :E | X]> ^<X> = (
| runningValue <X> |
runningValue:: initialValue.
self do: [:element <X> | runningValue:: foldBlock value: runningValue value: element].
^runningValue
)
public intersection: other <Collection[Object]> ^<List[E]> = (
^self select: [:each | other includes: each]
)
public isCollection ^<Boolean> = (
^true
)
public isEmpty ^<Boolean> = (
^0 == self size
)
public isKindOfCollection = (
(* Should be auto-generated *)
^true
)
public max = (
^ self inject: self anyOne into: [:m :each | m max: each]
)
protected maxPrintElements ^<Int> = (
^100
)
protected newForCollectUsingAdd: size <Int> ^<MutableArrayList[Object]> = (
(* Return a new extensible collection that is as closely related to the receiver's class as possible. The
returned collection must be unaliased and empty, so it is safe for the caller to guarantee that the type
variable is of a more specific type *)
^MutableArrayList new: size
)
public noneSatisfy: predicate <[:E | Boolean]> ^<Boolean> = (
self do: [:each | (predicate value: each) ifTrue: [^false]].
^true
)
protected occurrencesOf: o <Object> ^<Int> = (
| c <Int> |
#BOGUS. (* Questionable *)
c:: 0.
do: [:e <E> | e = o ifTrue: [ c:: c + 1 ]].
^c
)
public postCopy = (
#BOGUS. (* Squeakism *)
)
protected printElementsDo: f <[:Object]> = (
(* Evaluate the block with all the elements that should be shown as the contents in the printstring. This provides a hook for things like MutableHashedMaps, which want to show their associations, not their values *)
self do: f
)
public printOn: stream <CharOutputStream> = (
| count <Integer> first <Boolean> |
stream nextPutAll: class mixin simpleName;
nextPut: "(".
count:: 0.
first:: true.
self printElementsDo:
[:element <Object> |
first
ifTrue: [ first:: false ]
ifFalse: [ stream space ].
element printOn: stream.
count:: count + 1.
count >= maxPrintElements
ifTrue: [ stream nextPut: "<"; print: size - count; nextPutAll: ' more elements>)'.
^self]].
stream nextPut: ")".
)
public reduce: reduceFn <[:RE def :RE | RE]> ^<RE> = (
(* {where CONSTRAINER <RE> is returnType of #anElement message of receiverType} *)
(* Like reduce:ifEmpty: except that it is a dynamic error to send this to an empty collection *)
^self reduce: reduceFn ifEmpty: [Error signal: 'Cannot reduce an empty collection' ]
)
public reduce: reduceFn <[:RE def :RE| RE]> ifEmpty: onEmpty <[X def]> ^<RE | X> = (
(* {where CONSTRAINER <RE> is returnType of #anElement message of receiverType} *)
(* Reduce is similar to inject except that the first element is used as the injected
element for the rest of the collection. It is often handier than inject. For example:
(#(1 2 3 4) reduce: [:a <Int> :b <Int> | a + b ]) sums a collection of numbers. *)
(* esoteric typing %note: We need to ensure that E is a subtype of RE (the argument type for the reduction
function), but since that would require a
supertype constraint (which neither we nor anyone else support, we accomplish the same
thing indirectly by introducing an unreferenced type
variable CONSTRAINER that is inferred to be E at the call site, and then constraining it with a bound
of RE. This will prevent any call where E > RE from typechecking. However, since the
typesystem doesn't 'know' that, we have to tell it that with a guarantee in the method body.
Because of the CONSTRAINER, we know that the guarantee is true for all calls that typecheck.
Of course, this is tricky, but at least we can express it, and in a way that hides the guarantee from
callers! *)
| current <RE> |
self do:
[:element <E> |
| rel <RE> |
rel:: element.
current isNil
ifTrue: [ current:: rel ]
ifFalse: [ current:: reduceFn value: current value: rel ] ].
^current isNil
ifFalse: [ current ]
ifTrue: [ onEmpty value ]
)
public reject: predicate <[:E | Boolean]> ^<List[E]> = (
^self select: [:e | (predicate value: e) not ]
)
public select: predicate <[:E | Boolean]> ^<List[E]> = (
| result <MutableArrayList[E]> |
result:: self newForCollectUsingAdd: size.
self do: [:element | (predicate value: element) ifTrue: [result add: element]].
^result
)
public size ^<Integer> = (
| count ::= 0. |
self do: [:element <E> | count:: count + 1 ].
^count
)
public species ^<Collection[E] class> = (
^Set
)
public union: other <Collection[Object]> ^ <Set[Object]> = (
^self asSet addAll: other; yourself
)
public value = (
#BOGUS. (* Questionable *)
^self
)
) : (
)
class HashedCollection new: cap = Collection (|
protected table_0 <Array[A|Object]>
(* The table holds either included entries, or an object indicating a deleted entry,
which is currently the table itself. This of course means that the table is not allowed
as a valid element of the collection, but this is only an issue when writing reflective
system code that violates encapsulation. *)