-
Notifications
You must be signed in to change notification settings - Fork 65
/
Integer.extension.st
375 lines (313 loc) · 11.8 KB
/
Integer.extension.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
Extension { #name : #Integer }
{ #category : #'*VMMaker-bit manipulation' }
Integer >> >>> shiftAmount [ "right shift, but causes CCodeGenerator to generate a signed shift"
shiftAmount < 0 ifTrue: [self error: 'negative arg'].
^self bitShift: 0 - shiftAmount
]
{ #category : #'*VMMaker-interpreter simulator' }
Integer >> addBreakpoint: address [
^{self. address}
]
{ #category : #'*VMMaker-interpreter simulator' }
Integer >> asC_int [
^self >= 0
ifTrue: [self bitAnd: 16rFFFFFFFF]
ifFalse: [(self bitAnd: 16rFFFFFFFF) - 16r100000000]
]
{ #category : #'*VMMaker-interpreter simulator' }
Integer >> asC_unsigned_int [
^self bitAnd: 16rFFFFFFFF
]
{ #category : #'*VMMaker-interpreter simulator' }
Integer >> asCharPtr [
^(Notification new tag: #getInterpreter; signal)
ifNotNil: [:interpreter|
(interpreter firstIndexableField: self) asInteger
coerceTo: #'char *'
sim: interpreter]
ifNil: [self]
]
{ #category : #'*VMMaker-interpreter simulator' }
Integer >> asIntegerPtr [
^self
]
{ #category : #'*VMMaker-interpreter simulator' }
Integer >> asLong [
^self
]
{ #category : #'*VMMaker-interpreter simulator' }
Integer >> asPositiveIntegerObj [
"This is a SmartSyntaxPlugin convenience, invented with little thought for simulation (grrr).
In the VM this is equivalent to
interpreterProxy methodReturnValue: (interpreterProxy positive32BitIntegerFor: self)
but if a plugin is being developed I /think/ it is just
^self
So search the stack to discover what context it is being used in."
(thisContext findContextSuchThat: [:ctxt| ctxt receiver isInterpreterPlugin]) ifNotNil:
[:ctxt| | interpreter |
interpreter := ctxt receiver getInterpreter.
interpreter methodReturnValue: (interpreter positive32BitIntegerFor: self)].
^self
]
{ #category : #'*VMMaker-interpreter simulator' }
Integer >> asSmallIntegerObj [
^(Notification new tag: #getInterpreter; signal)
ifNotNil: [:interpreter| interpreter integerObjectOf: self]
ifNil: [self]
]
{ #category : #'*VMMaker-interpreter simulator' }
Integer >> asUnsignedInteger [
"Since the simulator deals with positive integers most of the time we assert that the receiver is greater than zero.
But one major exception is stack pointers in the StackInterpreterSimulator, which are negative. So don't fail
if the sender is a StackInterpreter and the receiver could be a stack pointer."
self >= 0 ifFalse:
[self assert: (((thisContext sender methodClass includesBehavior: CoInterpreter)
and: [self between: Cogit maxNegativeErrorCode and: -1])
or: [(thisContext sender methodClass includesBehavior: StackInterpreter)
and: [thisContext sender receiver stackPages couldBeFramePointer: self]])].
^self
]
{ #category : #'*VMMaker-interpreter simulator' }
Integer >> asUnsignedIntegerPtr [
"Since the simulator deals with positive integers most of the time we assert that the receiver is greater than zero.
But one major exception is stack pointers in the StackInterpreterSimulator, which are negative. So don't fail
if the sender is a StackInterpreter and the receiver could be a stack pointer."
self >= 0 ifFalse:
[self assert: ((thisContext sender methodClass includesBehavior: StackInterpreter)
and: [thisContext sender receiver stackPages couldBeFramePointer: self])].
^self
]
{ #category : #'*VMMaker-interpreter simulator' }
Integer >> asUnsignedLong [
self assert: self >= 0.
^self
]
{ #category : #'*VMMaker-interpreter simulator' }
Integer >> asUnsignedLongLong [
self assert: self >= 0.
^self
]
{ #category : #'*VMMaker-interpreter simulator' }
Integer >> asVoidPointer [
^self
]
{ #category : #'*VMMaker-bit manipulation' }
Integer >> bitInvert64 [
"Answer the 64-bit complement of the receiver."
^self bitXor: 16rFFFFFFFFFFFFFFFF
]
{ #category : #'*VMMaker-bit manipulation' }
Integer >> byteSwap32 [
"swap the bytes of a 32 bit unsigned integer"
^((self << 24) bitAnd: 16rFF000000) bitOr:
(((self << 8) bitAnd: 16rFF0000) bitOr:
(((self >> 8) bitAnd: 16rFF00) bitOr:
(((self >> 24) bitAnd: 16rFF))))
]
{ #category : #'*VMMaker-bit manipulation' }
Integer >> byteSwap64 [
"swap the bytes of a 64 bit unsigned integer"
^(((self << 56) bitAnd: 16rFF00000000000000) bitOr:
(((self << 40) bitAnd: 16rFF000000000000) bitOr:
(((self << 24) bitAnd: 16rFF0000000000) bitOr:
(((self << 8) bitAnd: 16rFF00000000) bitOr:
(((self >> 8) bitAnd: 16rFF000000) bitOr:
(((self >> 24) bitAnd: 16rFF0000) bitOr:
(((self >> 40) bitAnd: 16rFF00) bitOr:
((self >> 56) bitAnd: 16rFF))))))))
]
{ #category : #'*VMMaker-plugin generation' }
Integer class >> ccg: cg prolog: aBlock expr: aString index: anInteger [
^cg ccgLoad: aBlock expr: aString asKindOfIntegerFrom: anInteger
]
{ #category : #'*VMMaker-interpreter simulator' }
Integer >> coerceTo: cTypeString sim: interpreter [
| unitSize |
cTypeString last = $* ifTrue: "C pointer"
[unitSize := cTypeString caseOf: {
[#'char *'] -> [1].
[#'short *'] -> [2].
[#'int *'] -> [4].
[#'long long *'] -> [8].
[#'float *'] -> [^CFloatArray basicNew interpreter: interpreter address: self unitSize: 4; yourself].
[#'double *'] -> [^CFloatArray basicNew interpreter: interpreter address: self unitSize: 8; yourself].
[#'unsigned *'] -> [4].
[#'unsigned int *'] -> [4].
[#'unsigned char *'] -> [1].
[#'signed char *'] -> [1].
[#'unsigned short *'] -> [2].
[#'unsigned long long *'] -> [8].
[#'oop *'] -> [interpreter objectMemory bytesPerOop].
}
otherwise: [interpreter objectMemory wordSize].
^CArray basicNew
interpreter: interpreter address: self unitSize: unitSize;
yourself].
^self "C number (int, char, float, etc)"
]
{ #category : #'*VMMaker' }
Integer >> gtInspectorIntegerIn: composite [
<gtInspectorPresentationOrder: 30>
^ composite table
title: 'Integer';
display: [ | associations oop32Bit value32Bit oop64Bit value64Bit |
self > 0
ifTrue: [ "simple version, negatives aren't taken into account"
oop32Bit := ((self bitShift: 1) bitOr: 1).
value32Bit := (self bitShift: -1).
oop64Bit := ((self bitShift: 3) bitOr: 1).
value64Bit := (self bitShift: -3) ]
ifFalse: [ oop32Bit := value32Bit := oop64Bit := value64Bit := 0 ].
associations := {
'decimal' -> self printString.
'hex' -> self printStringHex.
'octal' -> (self printStringBase: 8).
'binary' -> (self printStringBase: 2).
'32Bit oop' -> (oop32Bit printString , ' / ' , oop32Bit hex).
'32Bit value' -> (value32Bit printString , ' / ' , value32Bit hex).
'64Bit oop' -> (oop64Bit printString , ' / ' , oop64Bit hex).
'64Bit value' -> (value64Bit printString , ' / ' , value64Bit hex)} asOrderedCollection.
(self between: 0 and: 16r10FFFF)
ifTrue: [ associations add: 'character' -> self asCharacter ].
associations ];
column: 'Key' evaluated: #key;
column: 'Value' evaluated: [ :each | each value printString ];
send: #value
]
{ #category : #'*VMMaker-printing' }
Integer >> hex8 [
"Print the receiver in base 16 with prefixed base, using at least 8 digits.
DO NOT CHANGE THIS! The Cog VMMaker depends on this.
Consider using storeStringBase: 16 length: 11 padded: true instead."
"16r3333 hex8"
| hex |
hex := self hex. "16rNNN"
^hex size < 11
ifTrue: [hex copyReplaceFrom: 4 to: 3
with: ('00000000' copyFrom: 1 to: 11-hex size)]
ifFalse: [hex]
]
{ #category : #'*VMMaker' }
Integer >> inspectIntegerIn: aBuilder [
<inspectorPresentationOrder: 30 title: 'Integer'>
| keysColumn valuesColumn items oop32Bit value32Bit oop64Bit value64Bit |
self > 0
ifTrue: [ "simple version, negatives aren't taken into account"
oop32Bit := ((self bitShift: 1) bitOr: 1).
value32Bit := (self bitShift: -1).
oop64Bit := ((self bitShift: 3) bitOr: 1).
value64Bit := (self bitShift: -3) ]
ifFalse: [ oop32Bit := value32Bit := oop64Bit := value64Bit := 0 ].
items := {
'decimal' -> self printString.
'hex' -> self printStringHex.
'octal' -> (self printStringBase: 8).
'binary' -> (self printStringBase: 2).
'32Bit oop' -> (oop32Bit printString , ' / ' , oop32Bit hex).
'32Bit value' -> (value32Bit printString , ' / ' , value32Bit hex).
'64Bit oop' -> (oop64Bit printString , ' / ' , oop64Bit hex).
'64Bit value' -> (value64Bit printString , ' / ' , value64Bit hex)} asOrderedCollection.
keysColumn := SpStringTableColumn title: #key evaluated: [ :anAssociation | anAssociation key ].
valuesColumn := SpStringTableColumn title: #value evaluated: [ :anAssociation | anAssociation value ].
^ aBuilder newTable
addColumn: keysColumn;
addColumn: valuesColumn;
items: items;
yourself
]
{ #category : #'*VMMaker-interpreter simulator' }
Integer >> isActiveBreakpoint [
^true
]
{ #category : #'*VMMaker-interpreter simulator' }
Integer >> isBreakpointFor: address [
^self = address
]
{ #category : #'*VMMaker-interpreter simulator' }
Integer >> menuPrompt [
^' (', self hex, ')'
]
{ #category : #'*VMMaker-interpreter simulator' }
Integer >> removeBreakpoint: address [
^nil
]
{ #category : #'*VMMaker-interpreter simulator' }
Integer >> signedBitShift: anInteger [
"For historical reasons Slang generates an unsigned shift from all of the shift operators >>, << & bitShift:.
These are too deeply entrenched to try and redefine the semantics. So instead we provide a signed bitShift:
that signals to Slang that its argument should be cast to signed, not to unsigned, when being shifted."
^self bitShift: anInteger
]
{ #category : #'*VMMaker-interpreter simulator' }
Integer >> signedIntFromChar [
"Self is an unsigned 8-bit integer in twos-comp form"
| shortBits |
shortBits := self bitAnd: 16rFF.
^(self bitAnd: 16r80) "sign bit" = 0
ifTrue: [shortBits]
ifFalse: [shortBits - 16r100]
]
{ #category : #'*VMMaker-interpreter simulator' }
Integer >> signedIntFromLong [
"Self is a signed or unsigned 32-bit integer"
| bits |
(self >= -1073741824 and: [self <= 1073741823]) ifTrue: "These are known to be SmallIntegers..."
[^self].
bits := self bitAnd: 16rFFFFFFFF.
(bits byteAt: 4) <= 16r7F ifTrue: [^bits].
^bits - 16r100000000
]
{ #category : #'*VMMaker-interpreter simulator' }
Integer >> signedIntFromLong64 [
"Self is a signed or unsigned 64-bit integer"
| bits |
"This case is handled by the SmallInteger subclass..."
"(self >= -1073741824 and: [self <= 1073741823]) ifTrue:
[^self]."
bits := self bitAnd: 16rFFFFFFFFFFFFFFFF.
(bits byteAt: 8) <= 16r7F ifTrue: [^bits].
^bits - 16r10000000000000000
]
{ #category : #'*VMMaker-interpreter simulator' }
Integer >> signedIntFromShort [
"Self is an unsigned 16-bit integer in twos-comp form"
| shortBits |
shortBits := self bitAnd: 16rFFFF.
^(self bitAnd: 16r8000) "sign bit" = 0
ifTrue: [shortBits]
ifFalse: [shortBits - 16r10000]
]
{ #category : #'*VMMaker-interpreter simulator' }
Integer >> signedIntToChar [
"Produces an 8-bit value in twos-comp form. Truncates if out-of-range as per a C cast"
^self bitAnd: 16rFF
]
{ #category : #'*VMMaker-interpreter simulator' }
Integer >> signedIntToLong [
"Produces a 32-bit value in twos-comp form. Truncates if out-of-range as per a C cast"
^self bitAnd: 16rFFFFFFFF
]
{ #category : #'*VMMaker-interpreter simulator' }
Integer >> signedIntToLong64 [
"Produces a 64-bit value in twos-comp form. Truncates if out-of-range as per a C cast"
^self bitAnd: 16rFFFFFFFFFFFFFFFF
]
{ #category : #'*VMMaker-interpreter simulator' }
Integer >> signedIntToShort [
"Produces a 16-bit value in twos-comp form. Truncates if out-of-range as per a C cast"
^self bitAnd: 16rFFFF
]
{ #category : #'*VMMaker-interpreter simulator' }
Integer >> singleStepRequiredToTriggerIn: aCogit [
^self between: aCogit cogCodeBase and: aCogit methodZone limitZony
]
{ #category : #'*VMMaker' }
Integer >> twoComplementOfBitSize: aBitSize [
| mask result |
self >= 0 ifTrue: [ ^ self ].
mask := (1 << aBitSize) - 1.
result := mask - self abs + 1.
(result < 0 or: [ result > mask ])
ifTrue: [ self error: 'The number does not fit in the required size' ].
^ result.
]