/
Object.class.st
2147 lines (1720 loc) · 69.6 KB
/
Object.class.st
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
"
`Object` is the root class for almost all of the other classes in the class hierarchy. The exceptions are ProtoObject (the superclass of Object) and its subclasses.
Class `Object` provides default behavior common to all normal objects, such as access, copying, comparison, error handling, message sending, and reflection. Also utility messages that all objects should respond to are defined here.
`Object` has no instance variables, nor should any be added. This is due to several classes of objects that inherit from Object that have special implementations (SmallInteger and UndefinedObject for example) or the VM knows about and depends on the structure and layout of certain standard classes.
Class Variables:
DependentsFields an IdentityDictionary
Provides a virtual 'dependents' field so that any object may have one
or more dependent views, synchronized by the changed:/update: protocol.
Note that class Model has a real slot for its dependents, and overrides
the associated protocol with more efficient implementations.
Because `Object` is the root of the inheritance tree, methods are often defined in Object to give all objects special behaviors needed by certain subsystems or applications, or to respond to certain general test messages such as isMorph.
###Miscellanous Discussions
About `at:` index accepting float and not only integers
This behavior is also free in the sense that the failure code is only invoked when the primitive fails and so adds nothing to the cost of successful accesses, which are the high dynamic frequency operation. It will also show up under
profiling if one is concerned about efficiency, and so isn't a hidden cost.
It is also in keeping with Pharo's mixed mode/arbitrary precision
implicit coercion number system that one *can* use fractions or floats as
indices. Stripping out coercions like this will make the system more brittle. So
please do *not* remove this hack. I think it's a feature and a useful one.
Can you give me an example that demonstrates the usefulness of this feature?
```
| a r |
a := Array new: 10 withAll: 0.
r := Random new.
100 timesRepeat: [| v | v := r next * 10 + 1. a at: v put: (a at: v) + 1].
a
```
i.e. I didn't have to provide an explicit rounding step. That's useful. But in general anywhere
where an index is derived by some calculation not having to provide the rounding step could be
useful/helpful/more concise. e.g. (n roundTo: 0.1) * 10 vs ((n roundTo: 0.1) * 10) asInteger.
Some thought went into the original choice. It is not a hack but there by intent. The integers are
simply a subset of the reals and forcing the programmer to use them is favouring the machine
above the programmer.
But I think you should justify getting rid of it rather than my having to justify keeping it. Getting
rid of it risks breaking code. If it is there but does not harm then why get rid of it?
best Eliot Miranda
"
Class {
#name : #Object,
#superclass : #ProtoObject,
#classVars : [
'DependentsFields'
],
#category : #'Kernel-Objects'
}
{ #category : #'class initialization' }
Object class >> flushDependents [
DependentsFields keysAndValuesDo:[:key :dep|
key ifNotNil:[key removeDependent: nil].
].
DependentsFields finalizeValues.
]
{ #category : #documentation }
Object class >> howToModifyPrimitives [
"You are allowed to write methods which specify primitives, but please use
caution. If you make a subclass of a class which contains a primitive method,
the subclass inherits the primitive. The message which is implemented
primitively may be overridden in the subclass (E.g., see at:put: in String's
subclass Symbol). The primitive behavior can be invoked using super (see
Symbol string:).
A class which attempts to mimic the behavior of another class without being
its subclass may or may not be able to use the primitives of the original class.
In general, if the instance variables read or written by a primitive have the
same meanings and are in the same fields in both classes, the primitive will
work.
For certain frequently used 'special selectors', the compiler emits a
send-special-selector bytecode instead of a send-message bytecode.
Special selectors were created because they offer two advantages. Code
which sends special selectors compiles into fewer bytes than normal. For
some pairs of receiver classes and special selectors, the interpreter jumps
directly to a primitive routine without looking up the method in the class.
This is much faster than a normal message lookup.
A selector which is a special selector solely in order to save space has a
normal behavior. Methods whose selectors are special in order to
gain speed contain the comment, 'No Lookup'. When the interpreter
encounters a send-special-selector bytecode, it checks the class of the
receiver and the selector. If the class-selector pair is a no-lookup pair,
then the interpreter swiftly jumps to the routine which implements the
corresponding primitive. (A special selector whose receiver is not of the
right class to make a no-lookup pair, is looked up normally). The pairs are
listed below. No-lookup methods contain a primitive number specification,
<primitive: xx>, which is redundant. Since the method is not normally looked
up, deleting the primitive number specification cannot prevent this
primitive from running. If a no-lookup primitive fails, the method is looked
up normally, and the expressions in it are executed.
No Lookup pairs of (class, selector)
SmallInteger with any of + - * / \\ bitOr: bitShift: bitAnd: //
SmallInteger with any of = ~= > < >= <=
Any class with ==
Any class with @
Point with either of x y
Context with blockCopy:
BlockContext with either of value value:
"
self error: 'comment only'
]
{ #category : #'class initialization' }
Object class >> initialize [
"Object initialize"
DependentsFields ifNil:[ self initializeDependentsFields ]
]
{ #category : #'class initialization' }
Object class >> initializeDependentsFields [
<script: 'Object initialize'>
DependentsFields := WeakIdentityKeyDictionary new
]
{ #category : #'instance creation' }
Object class >> newFrom: aSimilarObject [
"Create an object that has similar contents to aSimilarObject. If the classes have any instance variables with the same names, copy them across. If this is bad for a class, override this method."
^ (self isVariable
ifTrue: [self basicNew: aSimilarObject basicSize]
ifFalse: [self basicNew]) copySameFrom: aSimilarObject
]
{ #category : #'class initialization' }
Object class >> reInitializeDependentsFields [
<script>
| oldFields |
oldFields := DependentsFields.
DependentsFields := WeakIdentityKeyDictionary new.
oldFields
keysAndValuesDo: [ :obj :deps | deps do: [ :d | obj addDependent: d ] ]
]
{ #category : #'instance creation' }
Object class >> readFrom: textStringOrStream [
"Create an object based on the contents of textStringOrStream."
| object |
object := self class compiler evaluate: textStringOrStream.
(object isKindOf: self) ifFalse: [self error: self name, ' expected'].
^object
]
{ #category : #documentation }
Object class >> whatIsAPrimitive [
"Some messages in the system are responded to primitively. A primitive
response is performed directly by the interpreter rather than by evaluating
expressions in a method. The methods for these messages indicate the
presence of a primitive response by including <primitive: xx> or
<primitive: 79 error: ec>before the first expression in the method.
In the second case, ec is a special temporary variable that holds an error code.
In the VM primitive, failure is indicated by a variable called primFailCode being
non-zero. On activating a method with a failing primitive, if the index is in
bounds of the primitiveFailCodes array in the VMspecialObjectsArray then the
failure code substitutes the symbol in the primitiveFailCodes array, otherwise
it supplies the integer value.
Primitives exist for several reasons. Certain basic or 'primitive'
operations cannot be performed in any other way. Smalltalk without
primitives can move values from one variable to another, but cannot add two
SmallIntegers together. Many methods for arithmetic and comparison
between numbers are primitives. Some primitives allow Smalltalk to
communicate with I/O devices such as the disk, the display, and the keyboard.
Some primitives exist only to make the system run faster; each does the same
thing as a certain Smalltalk method, and its implementation as a primitive is
optional.
When the Smalltalk interpreter begins to execute a method which specifies a
primitive response, it tries to perform the primitive action and to return a
result. If the routine in the interpreter for this primitive is successful,
it will return a value and the expressions in the method will not be evaluated.
If the primitive routine is not successful, the primitive 'fails', and the
Smalltalk expressions in the method are executed instead. These
expressions are evaluated as though the primitive routine had not been
called.
The Smalltalk code that is evaluated when a primitive fails usually
anticipates why that primitive might fail. If the primitive is optional, the
expressions in the method do exactly what the primitive would have done (See
Number @). If the primitive only works on certain classes of arguments, the
Smalltalk code tries to coerce the argument or appeals to a superclass to find
a more general way of doing the operation (see SmallInteger +). If the
primitive is never supposed to fail, the expressions signal an error (see
SmallInteger asFloat).
Each method that specifies a primitive has a comment in it. If the primitive is
optional, the comment will say 'Optional'. An optional primitive that is not
implemented always fails, and the Smalltalk expressions do the work
instead.
If a primitive is not optional, the comment will say, 'Essential'. Some
methods will have the comment, 'No Lookup'. See Object
howToModifyPrimitives for an explanation of special selectors which are
not looked up.
For the primitives for +, -, *, and bitShift: in SmallInteger, and truncated
in Float, the primitive constructs and returns a 16-bit
LargePositiveInteger when the result warrants it. Returning 16-bit
LargePositiveIntegers from these primitives instead of failing is
optional in the same sense that the LargePositiveInteger arithmetic
primitives are optional. The comments in the SmallInteger primitives say,
'Fails if result is not a SmallInteger', even though the implementor has the
option to construct a LargePositiveInteger. For further information on
primitives, see the 'Primitive Methods' part of the chapter on the formal
specification of the interpreter in the Smalltalk book."
self error: 'comment only'
]
{ #category : #associating }
Object >> -> anObject [
"Answer an Association between self and anObject"
"The following example creates an association whose key is number 1 and value string 'one'."
"(1 -> 'one') key >>> 1"
"(1 -> 'one') value >>> 'one'"
"Note that key and value can be ANY object."
^Association key: self value: anObject
]
{ #category : #comparing }
Object >> = anObject [
"Answer whether the receiver and the argument represent the same
object. If = is redefined in any subclass, consider also redefining the
message hash."
^self == anObject
]
{ #category : #finalization }
Object >> actAsExecutor [
"Prepare the receiver to act as executor for any resources associated with it"
self breakDependents
]
{ #category : #converting }
Object >> adaptToFloat: rcvr andCompare: selector [
"If I am involved in comparison with a Float.
Default behaviour is to process comparison as any other selectors."
^ self adaptToFloat: rcvr andSend: selector
]
{ #category : #converting }
Object >> adaptToFloat: rcvr andSend: selector [
"If no method has been provided for adapting an object to a Float,
then it may be adequate to simply adapt it to a number."
^ self adaptToNumber: rcvr andSend: selector
]
{ #category : #converting }
Object >> adaptToFraction: rcvr andCompare: selector [
"If I am involved in comparison with a Fraction.
Default behaviour is to process comparison as any other selectors."
^ self adaptToFraction: rcvr andSend: selector
]
{ #category : #converting }
Object >> adaptToFraction: rcvr andSend: selector [
"If no method has been provided for adapting an object to a Fraction,
then it may be adequate to simply adapt it to a number."
^ self adaptToNumber: rcvr andSend: selector
]
{ #category : #converting }
Object >> adaptToInteger: rcvr andCompare: selector [
"If I am involved in comparison with an Integer.
Default behaviour is to process comparison as any other selectors."
^ self adaptToInteger: rcvr andSend: selector
]
{ #category : #converting }
Object >> adaptToInteger: rcvr andSend: selector [
"If no method has been provided for adapting an object to a Integer,
then it may be adequate to simply adapt it to a number."
^ self adaptToNumber: rcvr andSend: selector
]
{ #category : #dependencies }
Object >> addDependent: anObject [
"Make the given object one of the receiver's dependents."
| dependents |
dependents := self dependents.
(dependents includes: anObject) ifFalse:
[self myDependents: (dependents copyWithDependent: anObject)].
^ anObject
]
{ #category : #converting }
Object >> as: aSimilarClass [
"Create an object of class aSimilarClass that has similar contents to the receiver if the object is not already an instance of this class."
aSimilarClass == self class ifTrue: [ ^ self ].
^ aSimilarClass newFrom: self
]
{ #category : #converting }
Object >> asCollectionElement [
"Answer an object, which can be put into a Set as element , wrapped
by one of SetElement instance, if necessary.
Default implementation is to answer self"
]
{ #category : #converting }
Object >> asLink [
"Answer a string that represents the receiver."
^ ValueLink value: self
]
{ #category : #converting }
Object >> asOrderedCollection [
"Answer an OrderedCollection with the receiver as its only element."
^ OrderedCollection with: self
]
{ #category : #converting }
Object >> asString [
"Answer a string that represents the receiver."
^ self printString
]
{ #category : #asserting }
Object >> assert: aBlock [
"Throw an assertion error if aBlock does not evaluates to true.
We check for true explicitly to make the assertion fail for non booleans"
<debuggerCompleteToSender>
self assert: aBlock description: 'Assertion failed'.
]
{ #category : #asserting }
Object >> assert: aBlock description: aStringOrBlock [
"Throw an assertion error if aBlock does not evaluates to true."
<debuggerCompleteToSender>
aBlock value
ifFalse: [ AssertionFailure signal: aStringOrBlock value ]
]
{ #category : #accessing }
Object >> at: index [
"Primitive. Assumes receiver is indexable. Answer the value of an
indexable element in the receiver. Fail if the argument index is not an
Integer or is out of bounds. Essential. See Object documentation
whatIsAPrimitive. Read the class comment for a discussion about that the fact
that the index can be a float."
<primitive: 60>
index isInteger ifTrue:
[self class isVariable
ifTrue: [self errorSubscriptBounds: index]
ifFalse: [self errorNotIndexable]].
self errorNonIntegerIndex
]
{ #category : #accessing }
Object >> at: index put: value [
"Primitive. Assumes receiver is indexable. Store the argument value in
the indexable element of the receiver indicated by index. Fail if the
index is not an Integer or is out of bounds. Or fail if the value is not of
the right type for this kind of collection. Answer the value that was
stored. Essential. See Object documentation whatIsAPrimitive."
<primitive: 61>
index isInteger
ifTrue: [self class isVariable
ifTrue: [(index between: 1 and: self size)
ifFalse: [ ^ self errorSubscriptBounds: index]]
ifFalse: [ ^ self errorNotIndexable ]]
ifFalse: [ ^ self errorNonIntegerIndex ].
self isReadOnlyObject
ifTrue: [ ^ self modificationForbiddenFor: #at:put: index: index value: value ].
self errorImproperStore
]
{ #category : #'write barrier' }
Object >> attemptToAssign: value withIndex: index [
"Called by the VM when assigning an instance variable of an immutable object.
Upon return, executing will resume *after* the inst var assignment. If the inst var mutation has to be
performed, do it manually here in the call back with instVarAt:put:.
This method has to return *no* value by jumping to the context's sender"
self modificationForbiddenFor: #instVarAt:put: index: index value: value.
thisContext sender jump
"CAN'T REACH"
]
{ #category : #accessing }
Object >> basicAt: index [
"Primitive. Assumes receiver is indexable. Answer the value of an
indexable element in the receiver. Fail if the argument index is not an
Integer or is out of bounds. Essential. Do not override in a subclass. See
Object documentation whatIsAPrimitive."
<primitive: 60>
index isInteger ifTrue: [self errorSubscriptBounds: index].
self errorNonIntegerIndex
]
{ #category : #accessing }
Object >> basicAt: index put: value [
"Primitive. Assumes receiver is indexable. Store the second argument
value in the indexable element of the receiver indicated by index. Fail
if the index is not an Integer or is out of bounds. Or fail if the value is
not of the right type for this kind of collection. Answer the value that
was stored. Essential. Do not override in a subclass. See Object
documentation whatIsAPrimitive."
<primitive: 61>
index isInteger
ifTrue: [self class isVariable
ifTrue: [(index between: 1 and: self size)
ifFalse: [ ^ self errorSubscriptBounds: index ]]
ifFalse: [ ^ self errorNotIndexable ]]
ifFalse: [ ^ self errorNonIntegerIndex ].
self isReadOnlyObject
ifTrue: [ ^ self modificationForbiddenFor: #basicAt:put: index: index value: value ].
self errorImproperStore
]
{ #category : #accessing }
Object >> basicSize [
"Primitive. Answer the number of indexable variables in the receiver.
This value is the same as the largest legal subscript. Essential. Do not
override in any subclass. See Object documentation whatIsAPrimitive."
<primitive: 62>
"The number of indexable fields of fixed-length objects is 0"
^0
]
{ #category : #'write barrier' }
Object >> beReadOnlyObject [
"If the VM supports read-only objects it will not write to read-only objects.
An attempt to write to an instance variable of a read-only object will
cause the VM to send attemptToAssign:withIndex: to the read-only object.
An attempt to modify a read-only object in a primitive will cause the
primitive to fail with a #'no modification' error code.
Set the read-only flag of the receiver to true and answer the previous vaue of the flag."
^self setIsReadOnlyObject: true
]
{ #category : #'write barrier' }
Object >> beWritableObject [
"If the VM supports read-only objects it will not write to read-only objects.
An attempt to write to an instance variable of a read-only object will
cause the VM to send attemptToAssign:withIndex: to the read-only object.
An attempt to modify a read-only object in a primitive will cause the
primitive to fail with a #'no modification' error code.
Set the read-only flag of the receiver to false and answer the previous vaue of the flag."
^self setIsReadOnlyObject: false
]
{ #category : #binding }
Object >> bindingOf: aString [
^nil
]
{ #category : #dependencies }
Object >> breakDependents [
"Remove all of the receiver's dependents."
self myDependents: nil
]
{ #category : #dependencies }
Object >> canDiscardEdits [
"Answer true if none of the views on this model has unaccepted edits that matter."
self dependents
do: [:each | each canDiscardEdits ifFalse: [^ false]]
without: self.
^ true
]
{ #category : #'casing-To be deprecated' }
Object >> caseError [
"DO NOT USE THIS METHOD! It will be removed from Pharo."
"Report an error from an in-line or explicit case statement."
self error: 'Case not found (', self printString, '), and no otherwise clause'
]
{ #category : #'casing-To be deprecated' }
Object >> caseOf: aBlockAssociationCollection [
"DO NOT USE THIS METHOD! It will be removed from Pharo."
"The elements of aBlockAssociationCollection are associations between blocks.
Answer the evaluated value of the first association in aBlockAssociationCollection
whose evaluated key equals the receiver. If no match is found, report an error."
^ self caseOf: aBlockAssociationCollection otherwise: [self caseError]
"| z | z := {[#a]->[1+1]. ['b' asSymbol]->[2+2]. [#c]->[3+3]}. #b caseOf: z"
"| z | z := {[#a]->[1+1]. ['d' asSymbol]->[2+2]. [#c]->[3+3]}. #b caseOf: z"
"The following are compiled in-line:"
"#b caseOf: {[#a]->[1+1]. ['b' asSymbol]->[2+2]. [#c]->[3+3]}"
"#b caseOf: {[#a]->[1+1]. ['d' asSymbol]->[2+2]. [#c]->[3+3]}"
]
{ #category : #'casing-To be deprecated' }
Object >> caseOf: aBlockAssociationCollection otherwise: aBlock [
"DO NOT USE THIS METHOD! It will be removed from Pharo."
"The elements of aBlockAssociationCollection are associations between blocks.
Answer the evaluated value of the first association in aBlockAssociationCollection
whose evaluated key equals the receiver. If no match is found, answer the result
of evaluating aBlock."
aBlockAssociationCollection associationsDo:
[:assoc | (assoc key value = self) ifTrue: [^assoc value value]].
^ aBlock value
"| z | z := {[#a]->[1+1]. ['b' asSymbol]->[2+2]. [#c]->[3+3]}. #b caseOf: z otherwise: [0]"
"| z | z := {[#a]->[1+1]. ['d' asSymbol]->[2+2]. [#c]->[3+3]}. #b caseOf: z otherwise: [0]"
"The following are compiled in-line:"
"#b caseOf: {[#a]->[1+1]. ['b' asSymbol]->[2+2]. [#c]->[3+3]} otherwise: [0]"
"#b caseOf: {[#a]->[1+1]. ['d' asSymbol]->[2+2]. [#c]->[3+3]} otherwise: [0]"
]
{ #category : #updating }
Object >> changed [
"Receiver changed in a general way; inform all the dependents by
sending each dependent an update: message."
self changed: self
]
{ #category : #updating }
Object >> changed: aParameter [
"Receiver changed. The change is denoted by the argument aParameter.
Usually the argument is a Symbol that is part of the dependent's change
protocol. Inform all of the dependents."
self dependents do: [:aDependent | aDependent update: aParameter]
]
{ #category : #updating }
Object >> changed: anAspect with: anObject [
"Receiver changed. The change is denoted by the argument anAspect.
Usually the argument is a Symbol that is part of the dependent's change
protocol. Inform all of the dependents. Also pass anObject for additional information."
self dependents do: [:aDependent | aDependent update: anAspect with: anObject]
]
{ #category : #introspection }
Object >> className [
"Answer a string characterizing the receiver's class, for use in list views for example"
^ self class name asString
]
{ #category : #copying }
Object >> clone [
"Answer a shallow copy of the receiver."
<primitive: 148 error: ec>
| class newObject |
ec == #'insufficient object memory' ifFalse:
[^self primitiveFailed].
"If the primitive fails due to insufficient memory, instantiate via basicNew: to invoke
the garbage collector before retrying, and use copyFrom: to copy state."
newObject := (class := self class) isVariable
ifTrue:
[class isCompiledMethodClass
ifTrue:
[class newMethod: self basicSize - self initialPC + 1 header: self header]
ifFalse:
[class basicNew: self basicSize]]
ifFalse:
[class basicNew].
^newObject copyFrom: self
]
{ #category : #copying }
Object >> copy [
"Answer another instance just like the receiver. Subclasses typically override postCopy; they typically do not override shallowCopy. Copy is a template method in the sense of Design Patterns. So do not override it. Override postCopy instead. Pay attention that normally you should call postCopy of your superclass too."
^self shallowCopy postCopy
]
{ #category : #copying }
Object >> copyFrom: anotherObject [
"Copy to myself all instance variables I have in common with anotherObject. This is dangerous because it ignores an object's control over its own inst vars. "
| mine his |
<primitive: 168>
mine := self class allInstVarNames.
his := anotherObject class allInstVarNames.
1 to: (mine size min: his size) do: [:ind |
(mine at: ind) = (his at: ind) ifTrue: [
self instVarAt: ind put: (anotherObject instVarAt: ind)]].
self class isVariable & anotherObject class isVariable ifTrue: [
1 to: (self basicSize min: anotherObject basicSize) do: [:ind |
self basicAt: ind put: (anotherObject basicAt: ind)]].
]
{ #category : #copying }
Object >> copySameFrom: otherObject [
"Copy to myself all instance variables named the same in otherObject.
This ignores otherObject's control over its own inst vars."
| myInstVars otherInstVars |
myInstVars := self class allInstVarNames.
otherInstVars := otherObject class allInstVarNames.
myInstVars doWithIndex: [:each :index | | match |
(match := otherInstVars indexOf: each) > 0 ifTrue:
[self instVarAt: index put: (otherObject instVarAt: match)]].
1 to: (self basicSize min: otherObject basicSize) do: [:i |
self basicAt: i put: (otherObject basicAt: i)].
]
{ #category : #copying }
Object >> deepCopy [
"Answer a copy of the receiver with its own copy of each instance variable. deepCopy does a deep copy. It should never be overridden and only be used if you want to get these very specific semantics.
It doesn't handle cycles, #veryDeepCopy does. In the future we will make it handle cycles and deprecate veryDeepCopy"
| newObject class index |
class := self class.
(class == Object) ifTrue: [^self].
class isVariable
ifTrue:
[index := self basicSize.
newObject := class basicNew: index.
[index > 0]
whileTrue:
[newObject basicAt: index put: (self basicAt: index) deepCopy.
index := index - 1]]
ifFalse: [newObject := class basicNew].
index := class instSize.
[index > 0]
whileTrue:
[newObject instVarAt: index put: (self instVarAt: index) deepCopy.
index := index - 1].
^newObject
]
{ #category : #dependencies }
Object >> dependents [
"Answer a collection of objects that are 'dependent' on the receiver;
that is, all objects that should be notified if the receiver changes."
^ self myDependents ifNil: [#()]
]
{ #category : #deprecation }
Object >> deprecated: anExplanationString [
"Warn that the sending method has been deprecated"
Deprecation new
context: thisContext sender;
explanation: anExplanationString;
signal
]
{ #category : #deprecation }
Object >> deprecated: anExplanationString on: date in: version [
"Warn that the sending method has been deprecated"
Deprecation new
context: thisContext sender;
explanation: anExplanationString;
date: date;
version: version;
signal
]
{ #category : #deprecation }
Object >> deprecated: anExplanationString on: date in: version transformWith: aRule [
"Automatically tranform the deprecated call"
Deprecation new
context: thisContext sender;
explanation: anExplanationString;
date: date;
version: version;
rule: aRule;
transform.
]
{ #category : #deprecation }
Object >> deprecated: anExplanationString on: date in: version transformWith: aRule when: conditionBlock [
"Automatically tranform the deprecated call if it matches the condition"
Deprecation new
context: thisContext sender;
explanation: anExplanationString;
date: date;
version: version;
rule: aRule;
condition: conditionBlock;
transform.
]
{ #category : #deprecation }
Object >> deprecated: anExplanationString transformWith: aRule [
"Automatically tranform the deprecated call"
Deprecation new
context: thisContext sender;
explanation: anExplanationString;
rule: aRule;
transform.
]
{ #category : #deprecation }
Object >> deprecated: anExplanationString transformWith: aRule when: conditionBlock [
"Automatically tranform the deprecated call if it matches the condition"
Deprecation new
context: thisContext sender;
explanation: anExplanationString;
rule: aRule;
condition: conditionBlock;
transform.
]
{ #category : #displaying }
Object >> displayString [
"While printString is about to give a detailled information about an object, displayString is a message that should return a short string-based representation to be used by list and related UI frameworks. By default, simply return printString.
Subclasses should not override this method
but instead stream based method #displayStringOn:"
^ self displayStringLimitedTo: 50000
]
{ #category : #displaying }
Object >> displayStringLimitedTo: limit [
"Answer a String whose characters are a description of the receiver.
If you want to print without a character limit, use fullDisplayString."
^self printStringLimitedTo: limit using: [:s | self displayStringOn: s]
]
{ #category : #displaying }
Object >> displayStringOn: aStream [
"While #printOn: is about to give a detailled information about an object, #displayStringOn: is a message that should return a string-based representation to be used by list and related UI frameworks. By default, simply use printOn: method.
Subclasses should override this method instead of #displayString"
self printOn: aStream
]
{ #category : #'reflective operations' }
Object >> doesNotUnderstand: aMessage [
<debuggerCompleteToSender>
"Handle the fact that there was an attempt to send the given message to the receiver but the receiver does not understand this message (typically sent from the machine when a message is sent to the receiver and no method is defined for that selector)."
"Testing: (3 activeProcess)"
| exception resumeValue |
(exception := MessageNotUnderstood new)
message: aMessage;
receiver: self.
resumeValue := exception signal.
^exception reachedDefaultHandler
ifTrue: [aMessage sentTo: self]
ifFalse: [resumeValue]
]
{ #category : #accessing }
Object >> enclosedElement [
"The receiver is included into a set as an element.
Since some objects require wrappers (see SetElement) to be able to be included into a Set,
a set sends this message to its element to make sure it getting real object,
instead of its wrapper.
Only SetElement instance or its subclasses allowed to answer something different than receiver itself"
]
{ #category : #'error handling' }
Object >> error [
"Throw a generic Error exception."
^self error: 'Error!'.
]
{ #category : #'error handling' }
Object >> error: aString [
"Throw a generic Error exception."
^Error new signal: aString
]
{ #category : #private }
Object >> errorImproperStore [
"Create an error notification that an improper store was attempted."
self error: 'Improper store into indexable object'
]
{ #category : #private }
Object >> errorNonIntegerIndex [
"Create an error notification that an improper object was used as an index."
self error: 'only integers should be used as indices'
]
{ #category : #private }
Object >> errorNotIndexable [
"Create an error notification that the receiver is not indexable."
self error: ('Instances of {1} are not indexable' format: {self class name})
]
{ #category : #private }
Object >> errorSubscriptBounds: index [
"Create an error notification that an improper integer was used as an index."
SubscriptOutOfBounds signalFor: index
]
{ #category : #finalization }
Object >> executor [
"Return an object which can act as executor for finalization of the receiver"
^self shallowCopy actAsExecutor
]
{ #category : #'error handling' }
Object >> explicitRequirement [
"If one of the superclasses can perform the selector, we execute the method of that class, otherwise, the explicit requirement error is thrown"
| originalMethod originalArguments errorBlock originalReceiver callingContext originalSelector |
errorBlock := [ ^ self error: 'Explicitly required method' ].
callingContext := thisContext sender.
originalMethod := callingContext compiledCode method.
originalMethod isFromTrait
ifFalse: errorBlock.
originalReceiver := callingContext receiver.
originalSelector := originalMethod selector.
originalArguments := callingContext arguments.
originalReceiver class superclass
withAllSuperclassesDo: [ :superClass |
superClass
compiledMethodAt: originalSelector
ifPresent: [ :method |
(method isProvided or: [ method isFromTrait not ])
ifTrue: [ callingContext
return:
(method
valueWithReceiver: originalReceiver
arguments: originalArguments) ] ] ].
errorBlock value
]
{ #category : #finalization }
Object >> finalizationRegistry [
"Answer the finalization registry associated with the receiver."
^WeakRegistry default
]
{ #category : #finalization }
Object >> finalize [
"Finalize the resource associated with the receiver. This message should only be sent during the finalization process. There is NO garantuee that the resource associated with the receiver hasn't been free'd before so take care that you don't run into trouble - this all may happen with interrupt priority."
]
{ #category : #enumerating }
Object >> flattenOn: aStream [
aStream nextPut: self
]
{ #category : #displaying }
Object >> fullDisplayString [
"Answer a String whose characters are a description of the receiver suitable for UI"
^ String streamContents: [:s | self displayStringOn: s]
]
{ #category : #printing }
Object >> fullPrintString [
"Answer a String whose characters are a description of the receiver."
^ String streamContents: [:s | self printOn: s]
]
{ #category : #halting }
Object >> halt [
"This is the typical message to use for inserting breakpoints during debugging."
<debuggerCompleteToSender>
Halt now
]
{ #category : #halting }
Object >> halt: aString [
<debuggerCompleteToSender>
Halt now: aString
]
{ #category : #halting }
Object >> haltFromCount: anInteger [
"Always halt after a count has been reached"
<debuggerCompleteToSender>
Halt fromCount: anInteger
]
{ #category : #halting }
Object >> haltIf: condition [
<debuggerCompleteToSender>
Halt if: condition.
]
{ #category : #testing }
Object >> haltIfNil [
]
{ #category : #halting }
Object >> haltIfNotTest [
"Halt if execution was not started by a test. This is useful as this means one can just run tests undisturbed, while a execution for example from the Playground would be halted"
<debuggerCompleteToSender>
Halt ifNotTest
]
{ #category : #halting }
Object >> haltIfTest [
"Halt if execution was started by a test. These #halts are just active in the tests, useful when you want to add a halt in methods that are executed a lot (e.g. collections)"
<debuggerCompleteToSender>
Halt ifTest
]
{ #category : #halting }
Object >> haltOnCount: anInteger [
"Halts once when a count is reached"
<debuggerCompleteToSender>
Halt onCount: anInteger
]
{ #category : #halting }
Object >> haltOnce [
<debuggerCompleteToSender>
Halt once.
]
{ #category : #'process termination handling' }
Object >> handleProcessTerminationOfWaitingContext: suspendedContext [
^suspendedContext
]
{ #category : #'error handling' }
Object >> handles: exception [
"This method exists in case a non exception class is the first arg in an on:do: (for instance using a exception class that is not loaded). We prefer this to raising an error during error handling itself. Also, semantically it makes sense that the exception handler is not active if its exception class is not loaded"
^ false
]
{ #category : #binding }
Object >> hasBindingOf: aString [
^false
]
{ #category : #'literal testing' }
Object >> hasLiteralSuchThat: testBlock [
"This is the end of the imbedded structure path so return false."
^ false
]
{ #category : #finalization }
Object >> hasMultipleExecutors [
"All objects, except ObjectFinalizerCollection instances should answer false to this message"
^ false
]
{ #category : #comparing }
Object >> hash [