author | Claus Gittinger <cg@exept.de> |
Sat, 11 Nov 1995 16:31:47 +0100 | |
changeset 135 | aa4f7b8f121e |
parent 117 | 3736a828cb50 |
child 140 | 1ef1d1395146 |
permissions | -rw-r--r-- |
0 | 1 |
" |
4 | 2 |
COPYRIGHT (c) 1989 by Claus Gittinger |
47 | 3 |
All Rights Reserved |
0 | 4 |
|
5 |
This software is furnished under a license and may be used |
|
6 |
only in accordance with the terms of that license and with the |
|
7 |
inclusion of the above copyright notice. This software may not |
|
8 |
be provided or otherwise made available to, or used by, any |
|
9 |
other person. No title to or ownership of the software is |
|
10 |
hereby transferred. |
|
11 |
" |
|
12 |
||
13 |
ParseNode subclass:#MessageNode |
|
14 |
instanceVariableNames:'receiver selector argArray lineNr' |
|
15 |
classVariableNames:'' |
|
16 |
poolDictionaries:'' |
|
17 |
category:'System-Compiler-Support' |
|
18 |
! |
|
19 |
||
20 | 20 |
!MessageNode class methodsFor:'documentation'! |
21 |
||
22 |
copyright |
|
23 |
" |
|
24 |
COPYRIGHT (c) 1989 by Claus Gittinger |
|
47 | 25 |
All Rights Reserved |
20 | 26 |
|
27 |
This software is furnished under a license and may be used |
|
28 |
only in accordance with the terms of that license and with the |
|
29 |
inclusion of the above copyright notice. This software may not |
|
30 |
be provided or otherwise made available to, or used by, any |
|
31 |
other person. No title to or ownership of the software is |
|
32 |
hereby transferred. |
|
33 |
" |
|
34 |
! |
|
35 |
||
36 |
version |
|
135
aa4f7b8f121e
uff - version methods changed to return stings
Claus Gittinger <cg@exept.de>
parents:
117
diff
changeset
|
37 |
^ '$Header: /cvs/stx/stx/libcomp/MessageNode.st,v 1.31 1995-11-11 15:30:33 cg Exp $' |
20 | 38 |
! |
39 |
||
40 |
documentation |
|
41 |
" |
|
42 |
node for parse-trees, representing message sends |
|
43 |
" |
|
44 |
! ! |
|
0 | 45 |
|
46 |
!MessageNode class methodsFor:'instance creation'! |
|
47 |
||
48 |
receiver:recNode selector:selectorString |
|
49 |
^ (self basicNew) receiver:recNode selector:selectorString args:nil lineno:0 |
|
50 |
! |
|
51 |
||
52 |
receiver:recNode selector:selectorString arg:argNode |
|
53 |
^ self receiver:recNode selector:selectorString arg:argNode fold:true |
|
54 |
! |
|
55 |
||
56 |
receiver:recNode selector:selectorString arg:argNode fold:folding |
|
53 | 57 |
|result recVal argVal selector canFold| |
0 | 58 |
|
20 | 59 |
" |
60 |
The constant folding code can usually not optimize much |
|
61 |
- this may change when some kind of constant/macro declaration is added to smalltalk. |
|
62 |
" |
|
0 | 63 |
folding ifTrue:[ |
47 | 64 |
"do constant folding ..." |
65 |
(recNode isConstant and:[argNode isConstant]) ifTrue:[ |
|
66 |
"check if we can do it ..." |
|
63 | 67 |
selector := selectorString asSymbolIfInterned. |
68 |
selector notNil ifTrue:[ |
|
47 | 69 |
recVal := recNode evaluate. |
70 |
(recVal respondsTo:selector) ifTrue:[ |
|
53 | 71 |
canFold := false. |
47 | 72 |
" |
73 |
we could do much more here - but then, we need a dependency from |
|
74 |
the folded selectors method to the method we generate code for ... |
|
75 |
limit optimizations to those that will never change |
|
76 |
(or - if you change them - you will crash so bad ...) |
|
77 |
" |
|
78 |
argVal := argNode evaluate. |
|
79 |
(recVal respondsToArithmetic and:[argVal respondsToArithmetic]) ifTrue:[ |
|
80 |
(#( @ + - * / // \\ min: max: quo:) includes:selector) ifTrue:[ |
|
81 |
(#( / // \\ ) includes:selector) ifTrue:[ |
|
82 |
argVal = 0 ifTrue:[ |
|
83 |
^ 'division by zero in constant expression' |
|
84 |
]. |
|
85 |
]. |
|
53 | 86 |
canFold := true |
47 | 87 |
] |
88 |
]. |
|
89 |
(recVal isMemberOf:String) ifTrue:[ |
|
53 | 90 |
(argVal isInteger and:[selector == #at:]) ifTrue:[ |
91 |
canFold := true |
|
47 | 92 |
]. |
53 | 93 |
((argVal isMemberOf:String) and:[selector == #',']) ifTrue:[ |
94 |
canFold := true |
|
47 | 95 |
] |
53 | 96 |
]. |
97 |
canFold ifTrue:[ |
|
98 |
(SignalSet anySignal catch:[ |
|
99 |
result := recVal perform:selector with:argVal. |
|
100 |
]) ifTrue:[ |
|
101 |
^ 'error in constant expression' |
|
102 |
]. |
|
103 |
^ ConstantNode type:(ConstantNode typeOfConstant:result) value:result |
|
47 | 104 |
] |
105 |
] |
|
106 |
] |
|
53 | 107 |
]. |
108 |
" |
|
109 |
the folloing optimization cannot be done (although it would be nice) |
|
110 |
since the array may be modified later. |
|
111 |
" |
|
112 |
"/ (recNode isGlobal and:[argNode isConstant])ifTrue:[ |
|
113 |
"/ selectorString knownAsSymbol ifTrue:[ |
|
114 |
"/ selector := selectorString asSymbol. |
|
115 |
"/ recVal := recNode evaluate. |
|
116 |
"/ (recVal respondsTo:selector) ifTrue:[ |
|
117 |
"/ (recVal == FloatArray) ifTrue:[ |
|
118 |
"/ argVal := argNode evaluate. |
|
119 |
"/ (argVal isMemberOf:Array) ifTrue:[ |
|
120 |
"/ (SignalSet anySignal catch:[ |
|
121 |
"/ result := recVal perform:selector with:argVal with:argVal. |
|
122 |
"/ ]) ifTrue:[ |
|
123 |
"/ ^ 'error in constant expression' |
|
124 |
"/ ]. |
|
125 |
"/ ^ ConstantNode type:(ConstantNode typeOfConstant:result) value:result |
|
126 |
"/ ] |
|
127 |
"/ ] |
|
128 |
"/ ] |
|
129 |
"/ ] |
|
130 |
"/ ] |
|
0 | 131 |
]. |
132 |
^ (self basicNew) receiver:recNode selector:selectorString args:(Array with:argNode) lineno:0 |
|
133 |
! |
|
134 |
||
20 | 135 |
receiver:recNode selector:selectorString arg1:argNode1 arg2:argNode2 fold:folding |
136 |
|result recVal argVal selector| |
|
137 |
||
138 |
" |
|
139 |
This is just a demonstration - of how complex constants can be folded. |
|
140 |
This was inspired by some discussion in c.l.s about enhancing the language - I prefer |
|
141 |
enhancing the compiler .... |
|
142 |
The following optimization will convert '#(...) with:#(...) collect:[...]' into an array constant, |
|
143 |
allowing a constant arrays of complex objects. |
|
144 |
||
145 |
Notice: this method is normally disabled - its just a demo after all. |
|
146 |
" |
|
147 |
folding ifTrue:[ |
|
47 | 148 |
"do constant folding ..." |
149 |
(recNode isConstant and:[argNode1 isConstant]) ifTrue:[ |
|
150 |
"check if we can do it ..." |
|
63 | 151 |
selector := selectorString asSymbolIfInterned. |
152 |
selector notNil ifTrue:[ |
|
47 | 153 |
recVal := recNode evaluate. |
154 |
(recVal respondsTo:selector) ifTrue:[ |
|
155 |
" |
|
156 |
we could do much more here - but then, we need a dependency from |
|
157 |
the folded selectors method to the method we generate code for ... |
|
158 |
limit optimizations to those that will never change |
|
159 |
(or - if you change them - you will crash so bad ...) |
|
160 |
" |
|
161 |
argVal := argNode1 evaluate. |
|
162 |
((recVal isMemberOf:Array) and:[argVal isMemberOf:Array]) ifTrue:[ |
|
163 |
(selector == #with:collect:) ifTrue:[ |
|
164 |
(argNode2 isMemberOf:BlockNode) ifTrue:[ |
|
165 |
(SignalSet anySignal catch:[ |
|
166 |
result := recVal perform:selector with:argVal with:(argNode2 evaluate). |
|
167 |
]) ifTrue:[ |
|
168 |
^ 'error in constant expression' |
|
169 |
]. |
|
170 |
^ ConstantNode type:(ConstantNode typeOfConstant:result) value:result |
|
171 |
] |
|
172 |
] |
|
173 |
] |
|
174 |
] |
|
175 |
] |
|
176 |
] |
|
20 | 177 |
]. |
178 |
^ (self basicNew) receiver:recNode selector:selectorString args:(Array with:argNode1 with:argNode2) lineno:0 |
|
179 |
! |
|
180 |
||
0 | 181 |
receiver:recNode selector:selectorString args:anArray |
182 |
^ self receiver:recNode selector:selectorString args:anArray fold:true |
|
183 |
! |
|
184 |
||
185 |
receiver:recNode selector:selectorString args:argArray fold:folding |
|
117 | 186 |
|numArgs| |
187 |
||
188 |
numArgs := argArray size. |
|
20 | 189 |
folding ifTrue:[ |
117 | 190 |
(numArgs == 1) ifTrue:[ |
47 | 191 |
^ self receiver:recNode selector:selectorString arg:(argArray at:1) fold:true |
192 |
]. |
|
20 | 193 |
|
47 | 194 |
"uncomment the follwoing for a nice array initializer optimization ..." |
117 | 195 |
"/ (numArgs == 2) ifTrue:[ |
20 | 196 |
"/ ^ self receiver:recNode selector:selectorString arg1:(argArray at:1) arg2:(argArray at:2) fold:true |
197 |
"/ ]. |
|
117 | 198 |
numArgs > Method maxNumberOfArguments ifTrue:[ |
199 |
^ 'too many arguments for current VM implementation'. |
|
200 |
]. |
|
0 | 201 |
]. |
117 | 202 |
|
0 | 203 |
^ (self basicNew) receiver:recNode selector:selectorString args:argArray lineno:0 |
117 | 204 |
|
205 |
"Modified: 3.9.1995 / 16:41:39 / claus" |
|
0 | 206 |
! ! |
207 |
||
208 |
!MessageNode methodsFor:'accessing'! |
|
209 |
||
210 |
receiver:r selector:s args:a lineno:l |
|
211 |
receiver := r. |
|
212 |
selector := s asSymbol. |
|
213 |
argArray := a. |
|
214 |
lineNr := l |
|
215 |
! |
|
216 |
||
217 |
receiver |
|
218 |
^ receiver |
|
219 |
! |
|
220 |
||
221 |
selector |
|
222 |
^ selector |
|
223 |
! |
|
224 |
||
225 |
args |
|
226 |
^ argArray |
|
227 |
! |
|
228 |
||
229 |
arg1 |
|
230 |
^ argArray at:1 |
|
231 |
! |
|
232 |
||
6 | 233 |
lineNumber |
234 |
^ lineNr |
|
235 |
! |
|
236 |
||
0 | 237 |
lineNumber:num |
238 |
lineNr := num |
|
239 |
! ! |
|
240 |
||
3 | 241 |
!MessageNode methodsFor:'queries'! |
0 | 242 |
|
243 |
isMessage |
|
244 |
^ true |
|
3 | 245 |
! ! |
246 |
||
247 |
!MessageNode class methodsFor:'queries'! |
|
0 | 248 |
|
6 | 249 |
hasLineNumber:sel |
250 |
"return true, if special send code needs lineNr" |
|
251 |
||
252 |
(sel == #==) ifTrue:[^ false]. |
|
253 |
(sel == #~~) ifTrue:[^ false]. |
|
254 |
(sel == #class) ifTrue:[^ false]. |
|
76 | 255 |
(sel == #isNil) ifTrue:[^ false]. |
256 |
(sel == #notNil) ifTrue:[^ false]. |
|
6 | 257 |
^ true |
258 |
! |
|
259 |
||
0 | 260 |
isBuiltInUnarySelector:sel |
19 | 261 |
"return true, if unary selector sel is built-in. |
262 |
(i.e. there is a single bytecode for it)" |
|
0 | 263 |
|
264 |
(sel == #peek) ifTrue:[^ true]. |
|
265 |
(sel == #value) ifTrue:[^ true]. |
|
266 |
(sel == #next) ifTrue:[^ true]. |
|
267 |
(sel == #class) ifTrue:[^ true]. |
|
268 |
(sel == #size) ifTrue:[^ true]. |
|
269 |
(sel == #x) ifTrue:[^ true]. |
|
270 |
(sel == #y) ifTrue:[^ true]. |
|
271 |
(sel == #width) ifTrue:[^ true]. |
|
272 |
(sel == #height) ifTrue:[^ true]. |
|
273 |
(sel == #origin) ifTrue:[^ true]. |
|
274 |
(sel == #extent) ifTrue:[^ true]. |
|
6 | 275 |
(sel == #asInteger) ifTrue:[^ true]. |
276 |
(sel == #rounded) ifTrue:[^ true]. |
|
76 | 277 |
(sel == #isNil) ifTrue:[^ true]. |
278 |
(sel == #notNil) ifTrue:[^ true]. |
|
279 |
(sel == #not) ifTrue:[^ true]. |
|
106 | 280 |
(sel == #new) ifTrue:[^ true]. |
281 |
(sel == #basicNew) ifTrue:[^ true]. |
|
0 | 282 |
^ false |
283 |
! |
|
284 |
||
285 |
isBuiltIn1ArgSelector:sel |
|
19 | 286 |
"return true, if selector sel is built-in. |
287 |
(i.e. there is a single bytecode for it)" |
|
0 | 288 |
|
289 |
(sel == #at:) ifTrue:[^ true]. |
|
290 |
(sel == #value:) ifTrue:[^ true]. |
|
291 |
(sel == #bitAnd:) ifTrue:[^ true]. |
|
292 |
(sel == #bitOr:) ifTrue:[^ true]. |
|
111 | 293 |
(sel == #new:) ifTrue:[^ true]. |
294 |
(sel == #basicNew:) ifTrue:[^ true]. |
|
0 | 295 |
^ false |
296 |
! |
|
297 |
||
298 |
isBuiltIn2ArgSelector:sel |
|
19 | 299 |
"return true, if selector sel is built-in. |
300 |
(i.e. there is a single bytecode for it)" |
|
0 | 301 |
|
302 |
(sel == #at:put:) ifTrue:[^ true]. |
|
303 |
^ false |
|
304 |
! ! |
|
305 |
||
306 |
!MessageNode methodsFor:'printing'! |
|
307 |
||
308 |
printOn:aStream indent:i |
|
309 |
|needParen selectorParts index index2 arg| |
|
310 |
||
311 |
(#(whileTrue: whileFalse:) includes:selector) ifTrue:[ |
|
62 | 312 |
receiver isBlock ifTrue:[ |
47 | 313 |
^ self printWhileOn:aStream indent:i |
314 |
]. |
|
0 | 315 |
]. |
316 |
||
317 |
index := 1. |
|
318 |
selectorParts := OrderedCollection new. |
|
319 |
[index == 0] whileFalse:[ |
|
47 | 320 |
index2 := selector indexOf:$: startingAt:index. |
321 |
index2 ~~ 0 ifTrue:[ |
|
322 |
selectorParts add:(selector copyFrom:index to:index2). |
|
323 |
index2 := index2 + 1 |
|
324 |
]. |
|
325 |
index := index2 |
|
0 | 326 |
]. |
327 |
||
328 |
needParen := false. |
|
329 |
receiver isMessage ifTrue:[ |
|
47 | 330 |
receiver isUnaryMessage ifFalse:[ |
331 |
receiver isBinaryMessage ifFalse:[ |
|
332 |
needParen := true |
|
333 |
]. |
|
334 |
]. |
|
0 | 335 |
]. |
336 |
needParen ifTrue:[ |
|
47 | 337 |
aStream nextPutAll:'(' |
0 | 338 |
]. |
339 |
receiver printOn:aStream indent:i. |
|
340 |
needParen ifTrue:[ |
|
47 | 341 |
aStream nextPutAll:')' |
0 | 342 |
]. |
343 |
||
344 |
1 to:(argArray size) do:[:argIndex | |
|
47 | 345 |
aStream space. |
346 |
(selectorParts at:argIndex) printOn:aStream. |
|
347 |
aStream space. |
|
348 |
arg := argArray at:argIndex. |
|
349 |
needParen := false. |
|
350 |
arg isMessage ifTrue:[ |
|
351 |
arg isBinaryMessage ifFalse:[ |
|
352 |
arg isUnaryMessage ifFalse:[ |
|
353 |
needParen := true |
|
354 |
] |
|
355 |
]. |
|
356 |
]. |
|
357 |
needParen ifTrue:[ |
|
358 |
aStream nextPutAll:'(' |
|
359 |
]. |
|
360 |
arg printOn:aStream indent:i. |
|
361 |
needParen ifTrue:[ |
|
362 |
aStream nextPutAll:') ' |
|
363 |
]. |
|
0 | 364 |
] |
365 |
! |
|
366 |
||
367 |
printWhileOn:aStream indent:i |
|
12 | 368 |
|needParen arg| |
0 | 369 |
|
370 |
"special handling of whileTrue/whileFalse" |
|
371 |
||
372 |
aStream nextPutAll:'['. |
|
373 |
receiver statements printOn:aStream indent:i. |
|
374 |
aStream nextPutAll:'] whileTrue: '. |
|
375 |
||
376 |
arg := argArray at:1. |
|
377 |
needParen := false. |
|
378 |
arg isMessage ifTrue:[ |
|
47 | 379 |
arg isBinaryMessage ifFalse:[ |
380 |
arg isUnaryMessage ifFalse:[ |
|
381 |
needParen := true |
|
382 |
] |
|
383 |
]. |
|
0 | 384 |
]. |
385 |
needParen ifTrue:[ |
|
47 | 386 |
aStream nextPutAll:'(' |
0 | 387 |
]. |
388 |
arg printOn:aStream indent:i. |
|
389 |
needParen ifTrue:[ |
|
47 | 390 |
aStream nextPutAll:') ' |
0 | 391 |
]. |
392 |
! ! |
|
393 |
||
394 |
!MessageNode methodsFor:'checks'! |
|
395 |
||
396 |
plausibilityCheck |
|
397 |
|rec arg operand| |
|
398 |
||
3 | 399 |
" |
400 |
it once took me almost an hour, to find a '==' which |
|
401 |
should have been an '=' (you cannot compare floats with ==) |
|
19 | 402 |
(well, I looked at the '==' at least 50 times - |
403 |
- but didn't think about it ...). |
|
404 |
thats reason enough to add this check here. |
|
405 |
I will add more as heuristic knowledge increases ... |
|
406 |
(send me comments on common programming errors ...) |
|
407 |
" |
|
408 |
||
409 |
" |
|
410 |
check #== appled to Floats, Strings or Fractions |
|
0 | 411 |
" |
412 |
((selector == #==) or:[selector == #~~]) ifTrue:[ |
|
47 | 413 |
receiver isConstant ifTrue:[ |
414 |
rec := receiver evaluate. |
|
415 |
((rec isMemberOf:String) or:[ |
|
416 |
(rec isMemberOf:Float) or:[ |
|
417 |
(rec isMemberOf:Fraction)]]) ifTrue:[ |
|
418 |
operand := rec |
|
419 |
]. |
|
420 |
]. |
|
421 |
(argArray at:1) isConstant ifTrue:[ |
|
422 |
arg := (argArray at:1) evaluate. |
|
423 |
((arg isMemberOf:String) or:[ |
|
424 |
(arg isMemberOf:Float) or:[ |
|
425 |
(arg isMemberOf:Fraction)]]) ifTrue:[ |
|
426 |
operand := arg |
|
427 |
]. |
|
428 |
]. |
|
429 |
operand notNil ifTrue:[ |
|
430 |
(selector == #==) ifTrue:[ |
|
431 |
^ 'identity compare is unsafe here' |
|
432 |
]. |
|
433 |
^ 'identity compare will usually return true here' |
|
434 |
] |
|
0 | 435 |
]. |
3 | 436 |
|
437 |
" |
|
19 | 438 |
[...] ifTrue:... |
3 | 439 |
an error often occuring when you are a beginner ... |
440 |
" |
|
441 |
((selector == #ifTrue:) or:[selector == #ifFalse:]) ifTrue:[ |
|
47 | 442 |
receiver isBlock ifTrue:[ |
443 |
(Block canUnderstand:selector) ifFalse:[ |
|
444 |
^ 'blocks usually do not respond to ' , selector , ' messages' |
|
445 |
]. |
|
446 |
]. |
|
447 |
(argArray at:1) isBlock ifFalse:[ |
|
448 |
^ 'will fail at runtime, if argument to ' , selector , ' does not evaluate to a block' |
|
449 |
] |
|
3 | 450 |
]. |
19 | 451 |
((selector == #ifTrue:ifFalse:) or:[selector == #ifFalse:ifTrue:]) ifTrue:[ |
47 | 452 |
receiver isBlock ifTrue:[ |
453 |
(Block canUnderstand:selector) ifFalse:[ |
|
454 |
^ 'blocks usually do not respond to ' , selector , ' messages' |
|
455 |
]. |
|
456 |
]. |
|
457 |
(argArray at:1) isBlock ifFalse:[ |
|
458 |
^ 'will fail at runtime, if 1st. argument to ' , selector , ' does not evaluate to a block' |
|
459 |
]. |
|
460 |
(argArray at:2) isBlock ifFalse:[ |
|
461 |
^ 'will fail at runtime, if 2nd. argument to ' , selector , ' does not evaluate to a block' |
|
462 |
] |
|
3 | 463 |
]. |
19 | 464 |
|
465 |
" |
|
466 |
(...) whileTrue:[ |
|
467 |
" |
|
3 | 468 |
((selector == #whileTrue:) or:[selector == #whileFalse:]) ifTrue:[ |
47 | 469 |
receiver isBlock ifFalse:[ |
470 |
" |
|
471 |
only warn, if code was originally parenthized |
|
472 |
" |
|
473 |
receiver parenthized ifTrue:[ |
|
474 |
^ 'will fail at runtime, if receiver of ' , selector , ' does not evaluate to a block' |
|
475 |
] |
|
476 |
]. |
|
477 |
(argArray at:1) isBlock ifFalse:[ |
|
478 |
^ 'will fail at runtime, if argument to ' , selector , ' does not evaluate to a block' |
|
479 |
]. |
|
3 | 480 |
]. |
0 | 481 |
^ nil |
482 |
! ! |
|
483 |
||
484 |
!MessageNode methodsFor:'evaluating'! |
|
485 |
||
486 |
evaluate |
|
13 | 487 |
|r nargs argValueArray class| |
488 |
||
489 |
receiver isSuper ifTrue:[ |
|
47 | 490 |
r := receiver value. |
49 | 491 |
receiver isHere ifTrue:[ |
492 |
class := receiver definingClass. |
|
493 |
] ifFalse:[ |
|
494 |
class := receiver definingClass superclass. |
|
495 |
]. |
|
47 | 496 |
argArray notNil ifTrue:[ |
497 |
argValueArray := argArray collect:[:arg | arg evaluate]. |
|
498 |
] ifFalse:[ |
|
499 |
argValueArray := #() |
|
500 |
]. |
|
501 |
^ r perform:selector inClass:class withArguments:argValueArray |
|
13 | 502 |
]. |
503 |
||
0 | 504 |
|
505 |
argArray isNil ifTrue:[ |
|
47 | 506 |
^ (receiver evaluate) perform:selector |
0 | 507 |
]. |
508 |
nargs := argArray size. |
|
509 |
(nargs == 1) ifTrue:[ |
|
47 | 510 |
^ (receiver evaluate) perform:selector with:(argArray at:1) evaluate |
0 | 511 |
]. |
512 |
(nargs == 2) ifTrue:[ |
|
47 | 513 |
^ (receiver evaluate) perform:selector |
514 |
with:(argArray at:1) evaluate |
|
515 |
with:(argArray at:2) evaluate |
|
0 | 516 |
]. |
517 |
(nargs == 3) ifTrue:[ |
|
47 | 518 |
^ (receiver evaluate) perform:selector |
519 |
with:(argArray at:1) evaluate |
|
520 |
with:(argArray at:2) evaluate |
|
521 |
with:(argArray at:3) evaluate |
|
0 | 522 |
]. |
523 |
r := receiver evaluate. |
|
13 | 524 |
argValueArray := argArray collect:[:arg | arg evaluate]. |
0 | 525 |
^ r perform:selector withArguments:argValueArray |
526 |
! |
|
527 |
||
528 |
evaluateForCascade |
|
13 | 529 |
|r nargs argValueArray class| |
530 |
||
531 |
receiver isSuper ifTrue:[ |
|
47 | 532 |
r := receiver value. |
96 | 533 |
class := receiver definingClass. |
534 |
receiver isHere ifFalse:[ |
|
535 |
class := class superclass. |
|
49 | 536 |
]. |
47 | 537 |
argArray notNil ifTrue:[ |
538 |
argValueArray := argArray collect:[:arg | arg evaluate]. |
|
539 |
] ifFalse:[ |
|
540 |
argValueArray := #() |
|
541 |
]. |
|
542 |
r perform:selector inClass:class withArguments:argValueArray. |
|
543 |
^ r |
|
13 | 544 |
]. |
0 | 545 |
|
546 |
r := receiver evaluate. |
|
547 |
argArray isNil ifTrue:[ |
|
47 | 548 |
r perform:selector. |
549 |
^ r |
|
0 | 550 |
]. |
551 |
nargs := argArray size. |
|
552 |
(nargs == 1) ifTrue:[ |
|
47 | 553 |
r perform:selector with:(argArray at:1) evaluate. |
554 |
^ r |
|
0 | 555 |
]. |
556 |
(nargs == 2) ifTrue:[ |
|
47 | 557 |
r perform:selector with:(argArray at:1) evaluate |
558 |
with:(argArray at:2) evaluate. |
|
559 |
^ r |
|
0 | 560 |
]. |
561 |
(nargs == 3) ifTrue:[ |
|
47 | 562 |
r perform:selector with:(argArray at:1) evaluate |
563 |
with:(argArray at:2) evaluate |
|
564 |
with:(argArray at:3) evaluate. |
|
565 |
^ r |
|
0 | 566 |
]. |
13 | 567 |
argValueArray := argArray collect:[:arg | arg evaluate]. |
0 | 568 |
r perform:selector withArguments:argValueArray. |
569 |
^ r |
|
570 |
! ! |
|
571 |
||
572 |
!MessageNode methodsFor:'code generation'! |
|
573 |
||
104 | 574 |
codeForSideEffectOn:aStream inBlock:b for:aCompiler |
575 |
self codeOn:aStream inBlock:b valueNeeded:false for:aCompiler |
|
0 | 576 |
! |
577 |
||
104 | 578 |
codeOn:aStream inBlock:b for:aCompiler |
579 |
self codeOn:aStream inBlock:b valueNeeded:true for:aCompiler |
|
0 | 580 |
! |
581 |
||
582 |
optimizedConditionFor:aReceiver with:aByteCode |
|
583 |
|rec sel| |
|
584 |
||
585 |
rec := aReceiver. |
|
76 | 586 |
(rec isBlock) ifTrue:[ |
47 | 587 |
rec statements nextStatement isNil ifTrue:[ |
588 |
rec := rec statements expression |
|
589 |
] |
|
0 | 590 |
]. |
76 | 591 |
(rec isUnaryMessage) ifTrue:[ |
47 | 592 |
sel := rec selector. |
593 |
(sel == #isNil) ifTrue:[ |
|
76 | 594 |
"/ |
595 |
"/ isNil trueJmp -> nilJump |
|
596 |
"/ isNil falseJmp -> notNilJump |
|
597 |
"/ |
|
47 | 598 |
(aByteCode == #trueJump) ifTrue:[^ #nilJump]. |
599 |
(aByteCode == #falseJump) ifTrue:[^ #notNilJump] |
|
600 |
]. |
|
601 |
(sel == #notNil) ifTrue:[ |
|
76 | 602 |
"/ |
603 |
"/ notNil trueJmp -> notNilJump |
|
604 |
"/ notNil falseJmp -> nilJump |
|
605 |
"/ |
|
47 | 606 |
(aByteCode == #trueJump) ifTrue:[^ #notNilJump]. |
607 |
(aByteCode == #falseJump) ifTrue:[^ #nilJump] |
|
608 |
]. |
|
609 |
(sel == #not) ifTrue:[ |
|
76 | 610 |
"/ |
611 |
"/ not trueJmp -> falseJump |
|
612 |
"/ not falseJmp -> trueJump |
|
613 |
"/ |
|
47 | 614 |
(aByteCode == #trueJump) ifTrue:[^ #falseJump]. |
615 |
(aByteCode == #falseJump) ifTrue:[^ #trueJump] |
|
616 |
]. |
|
617 |
^ nil |
|
0 | 618 |
]. |
76 | 619 |
(rec isBinaryMessage) ifTrue:[ |
47 | 620 |
sel := rec selector. |
621 |
rec arg1 isConstant ifTrue:[ |
|
622 |
(rec arg1 value == 0) ifTrue:[ |
|
76 | 623 |
"/ |
624 |
"/ ==0 trueJmp -> zeroJump |
|
625 |
"/ ==0 falseJmp -> notZeroJump |
|
626 |
"/ |
|
47 | 627 |
(sel == #==) ifTrue:[ |
628 |
(aByteCode == #trueJump) ifTrue:[^ #zeroJump]. |
|
629 |
(aByteCode == #falseJump) ifTrue:[^ #notZeroJump] |
|
630 |
]. |
|
76 | 631 |
"/ |
632 |
"/ ~~0 trueJmp -> notZeroJump |
|
633 |
"/ ~~0 falseJmp -> zeroJump |
|
634 |
"/ |
|
47 | 635 |
(sel == #~~) ifTrue:[ |
636 |
(aByteCode == #falseJump) ifTrue:[^ #zeroJump]. |
|
637 |
(aByteCode == #trueJump) ifTrue:[^ #notZeroJump] |
|
638 |
]. |
|
639 |
^ nil |
|
640 |
] |
|
641 |
]. |
|
642 |
(sel == #==) ifTrue:[ |
|
76 | 643 |
"/ |
644 |
"/ == trueJmp -> eqJump |
|
645 |
"/ == falseJmp -> notEqJump |
|
646 |
"/ |
|
47 | 647 |
(aByteCode == #trueJump) ifTrue:[^ #eqJump]. |
648 |
(aByteCode == #falseJump) ifTrue:[^ #notEqJump] |
|
649 |
]. |
|
650 |
(sel == #~~) ifTrue:[ |
|
76 | 651 |
"/ |
652 |
"/ ~~ trueJmp -> notEqJump |
|
653 |
"/ ~~ falseJmp -> eqJump |
|
654 |
"/ |
|
47 | 655 |
(aByteCode == #falseJump) ifTrue:[^ #eqJump]. |
656 |
(aByteCode == #trueJump) ifTrue:[^ #notEqJump] |
|
657 |
] |
|
0 | 658 |
]. |
659 |
^ nil |
|
660 |
! |
|
661 |
||
104 | 662 |
codeWhileOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler |
0 | 663 |
"generate code for [...] whilexxx:[ ... ]" |
664 |
||
665 |
|pos pos2 theReceiver theArg theByteCode optByteCode| |
|
666 |
||
667 |
(selector == #whileTrue:) ifTrue:[ |
|
111 | 668 |
theByteCode := #falseJump |
106 | 669 |
] ifFalse:[ |
111 | 670 |
theByteCode := #trueJump |
106 | 671 |
]. |
672 |
||
673 |
theReceiver := receiver. |
|
674 |
optByteCode := self optimizedConditionFor:theReceiver with:theByteCode. |
|
675 |
optByteCode notNil ifTrue:[ |
|
111 | 676 |
((optByteCode == #eqJump) or:[optByteCode == #notEqJump]) ifTrue:[ |
677 |
theArg := receiver statements expression arg1 |
|
678 |
]. |
|
679 |
theReceiver := receiver statements expression receiver. |
|
680 |
theByteCode := optByteCode |
|
106 | 681 |
]. |
682 |
||
683 |
"/ OLD: |
|
684 |
"/ valueNeeded ifTrue:[aStream nextPut:#pushNil]. |
|
685 |
"/ |
|
686 |
pos := aStream position. |
|
687 |
optByteCode notNil ifTrue:[ |
|
111 | 688 |
theReceiver codeOn:aStream inBlock:b for:aCompiler. |
689 |
theArg notNil ifTrue:[ |
|
690 |
theArg codeOn:aStream inBlock:b for:aCompiler |
|
691 |
] |
|
106 | 692 |
] ifFalse:[ |
111 | 693 |
theReceiver codeInlineOn:aStream inBlock:b for:aCompiler |
106 | 694 |
]. |
695 |
||
696 |
(lineNr between:1 and:255) ifTrue:[ |
|
111 | 697 |
aStream nextPut:#lineno; nextPut:lineNr. |
106 | 698 |
]. |
699 |
||
700 |
aStream nextPut:theByteCode. |
|
701 |
pos2 := aStream position. |
|
702 |
aStream nextPut:0. |
|
703 |
"/ OLD: |
|
704 |
"/ valueNeeded ifTrue:[aStream nextPut:#drop]. |
|
705 |
"/ |
|
706 |
"/ OLD: |
|
707 |
"/ (argArray at:1) codeInlineOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler. |
|
708 |
"/ NEW: |
|
709 |
(argArray at:1) codeInlineOn:aStream inBlock:b valueNeeded:false for:aCompiler. |
|
710 |
aStream nextPut:#jump; nextPut:pos. |
|
711 |
(aStream contents) at:pos2 put:(aStream position). |
|
712 |
"/ NEW: |
|
713 |
valueNeeded ifTrue:[aStream nextPut:#pushNil]. |
|
714 |
! |
|
715 |
||
716 |
XXcodeWhileOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler |
|
717 |
"generate code for [...] whilexxx:[ ... ]" |
|
718 |
||
719 |
|pos pos2 theReceiver theArg theByteCode optByteCode| |
|
720 |
||
721 |
(selector == #whileTrue:) ifTrue:[ |
|
47 | 722 |
theByteCode := #falseJump |
0 | 723 |
] ifFalse:[ |
47 | 724 |
theByteCode := #trueJump |
0 | 725 |
]. |
726 |
||
727 |
theReceiver := receiver. |
|
728 |
optByteCode := self optimizedConditionFor:theReceiver with:theByteCode. |
|
729 |
optByteCode notNil ifTrue:[ |
|
47 | 730 |
((optByteCode == #eqJump) or:[optByteCode == #notEqJump]) ifTrue:[ |
731 |
theArg := receiver statements expression arg1 |
|
732 |
]. |
|
733 |
theReceiver := receiver statements expression receiver. |
|
734 |
theByteCode := optByteCode |
|
0 | 735 |
]. |
736 |
||
737 |
valueNeeded ifTrue:[aStream nextPut:#pushNil]. |
|
738 |
pos := aStream position. |
|
739 |
optByteCode notNil ifTrue:[ |
|
104 | 740 |
theReceiver codeOn:aStream inBlock:b for:aCompiler. |
47 | 741 |
theArg notNil ifTrue:[ |
104 | 742 |
theArg codeOn:aStream inBlock:b for:aCompiler |
47 | 743 |
] |
0 | 744 |
] ifFalse:[ |
104 | 745 |
theReceiver codeInlineOn:aStream inBlock:b for:aCompiler |
0 | 746 |
]. |
53 | 747 |
|
748 |
(lineNr between:1 and:255) ifTrue:[ |
|
95 | 749 |
aStream nextPut:#lineno; nextPut:lineNr. |
53 | 750 |
]. |
751 |
||
0 | 752 |
aStream nextPut:theByteCode. |
753 |
pos2 := aStream position. |
|
754 |
aStream nextPut:0. |
|
755 |
valueNeeded ifTrue:[aStream nextPut:#drop]. |
|
104 | 756 |
(argArray at:1) codeInlineOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler. |
95 | 757 |
aStream nextPut:#jump; nextPut:pos. |
106 | 758 |
(aStream contents) at:pos2 put:(aStream position). |
0 | 759 |
! |
760 |
||
104 | 761 |
codeTimesRepeatOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler |
0 | 762 |
"generate code for n timesRepeat:[ ... ]" |
763 |
||
12 | 764 |
|pos pos2 theReceiver| |
0 | 765 |
|
766 |
theReceiver := receiver. |
|
104 | 767 |
theReceiver codeOn:aStream inBlock:b for:aCompiler. |
0 | 768 |
valueNeeded ifTrue:[aStream nextPut:#dup]. |
769 |
||
770 |
pos := aStream position. |
|
103 | 771 |
"/ aStream nextPut:#dup; nextPut:#push0; nextPut:#>; nextPut:lineNr; nextPut:#falseJump. |
117 | 772 |
"/ aStream nextPut:#dup; nextPut:#gt0; nextPut:lineNr; nextPut:#falseJump. |
773 |
aStream nextPut:#pushgt0; nextPut:lineNr; nextPut:#falseJump. |
|
0 | 774 |
pos2 := aStream position. |
775 |
aStream nextPut:0. |
|
776 |
||
104 | 777 |
(argArray at:1) codeInlineOn:aStream inBlock:b valueNeeded:false for:aCompiler. |
95 | 778 |
aStream nextPut:#minus1; nextPut:lineNr; nextPut:#jump; nextPut:pos. |
0 | 779 |
|
75 | 780 |
(aStream contents) at:pos2 put:(aStream position). |
74 | 781 |
aStream nextPut:#drop. |
0 | 782 |
! |
783 |
||
104 | 784 |
codeIfElseOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler |
0 | 785 |
"generate code for x ifxxx:[ ... ] yyy:[ ...]" |
786 |
||
76 | 787 |
|pos pos2 theReceiver theArg theByteCode optByteCode subsel code| |
0 | 788 |
|
789 |
theReceiver := receiver. |
|
76 | 790 |
|
791 |
" |
|
792 |
(theReceiver isMessage) ifTrue:[ |
|
793 |
subsel := theReceiver selector. |
|
794 |
(subsel == #and:) ifTrue:[ |
|
104 | 795 |
self codeAndIfElseOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler. |
76 | 796 |
^ self |
797 |
]. |
|
798 |
(subsel == #or:) ifTrue:[ |
|
104 | 799 |
self codeOrIfElseOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler. |
76 | 800 |
^ self |
801 |
] |
|
802 |
]. |
|
803 |
" |
|
0 | 804 |
(selector == #ifTrue:ifFalse:) ifTrue:[ |
47 | 805 |
theByteCode := #falseJump |
0 | 806 |
] ifFalse:[ |
47 | 807 |
(selector == #ifFalse:ifTrue:) ifTrue:[ |
808 |
theByteCode := #trueJump |
|
809 |
] |
|
0 | 810 |
]. |
811 |
optByteCode := self optimizedConditionFor:theReceiver |
|
47 | 812 |
with:theByteCode. |
0 | 813 |
optByteCode notNil ifTrue:[ |
47 | 814 |
((optByteCode == #eqJump) or:[optByteCode == #notEqJump]) ifTrue:[ |
815 |
theArg := theReceiver arg1 |
|
816 |
]. |
|
817 |
theReceiver := theReceiver receiver. |
|
818 |
theByteCode := optByteCode |
|
0 | 819 |
]. |
820 |
theByteCode notNil ifTrue:[ |
|
104 | 821 |
theReceiver codeOn:aStream inBlock:b for:aCompiler. |
47 | 822 |
theArg notNil ifTrue:[ |
104 | 823 |
theArg codeOn:aStream inBlock:b for:aCompiler |
47 | 824 |
]. |
53 | 825 |
|
826 |
(lineNr between:1 and:255) ifTrue:[ |
|
95 | 827 |
aStream nextPut:#lineno; nextPut:lineNr. |
53 | 828 |
]. |
829 |
||
47 | 830 |
aStream nextPut:theByteCode. |
831 |
pos := aStream position. |
|
832 |
aStream nextPut:0. |
|
104 | 833 |
(argArray at:1) codeInlineOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler. |
47 | 834 |
aStream nextPut:#jump. |
835 |
pos2 := aStream position. |
|
836 |
aStream nextPut:0. |
|
76 | 837 |
code := aStream contents. |
838 |
code at:pos put:(aStream position). |
|
104 | 839 |
(argArray at:2) codeInlineOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler. |
76 | 840 |
code at:pos2 put:(aStream position) |
0 | 841 |
] |
842 |
! |
|
843 |
||
104 | 844 |
codeIfOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler |
0 | 845 |
"generate code for x ifxxx:[ ... ]" |
846 |
||
103 | 847 |
|pos pos2 theReceiver theArg theByteCode optByteCode subsel code |
848 |
needLineNr| |
|
0 | 849 |
|
850 |
theReceiver := receiver. |
|
851 |
||
76 | 852 |
(theReceiver isMessage) ifTrue:[ |
47 | 853 |
subsel := theReceiver selector. |
854 |
(subsel == #and:) ifTrue:[ |
|
104 | 855 |
self codeAndIfOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler. |
47 | 856 |
^ self |
857 |
]. |
|
858 |
(subsel == #or:) ifTrue:[ |
|
104 | 859 |
self codeOrIfOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler. |
47 | 860 |
^ self |
861 |
] |
|
0 | 862 |
]. |
863 |
(selector == #ifTrue:) ifTrue:[ |
|
47 | 864 |
theByteCode := #falseJump |
0 | 865 |
] ifFalse:[ |
47 | 866 |
theByteCode := #trueJump |
0 | 867 |
]. |
868 |
optByteCode := self optimizedConditionFor:theReceiver |
|
47 | 869 |
with:theByteCode. |
0 | 870 |
optByteCode notNil ifTrue:[ |
47 | 871 |
((optByteCode == #eqJump) or:[optByteCode == #notEqJump]) ifTrue:[ |
872 |
theArg := theReceiver arg1 |
|
873 |
]. |
|
874 |
theReceiver := theReceiver receiver. |
|
875 |
theByteCode := optByteCode |
|
0 | 876 |
]. |
877 |
||
104 | 878 |
theReceiver codeOn:aStream inBlock:b for:aCompiler. |
0 | 879 |
theArg notNil ifTrue:[ |
104 | 880 |
theArg codeOn:aStream inBlock:b for:aCompiler |
0 | 881 |
]. |
53 | 882 |
|
103 | 883 |
needLineNr := true. |
884 |
theArg isNil ifTrue:[ |
|
885 |
theReceiver isMessage ifTrue:[ |
|
886 |
(self class hasLineNumber:(theReceiver selector)) ifTrue:[ |
|
887 |
theReceiver lineNumber == lineNr ifTrue:[ |
|
888 |
needLineNr := false |
|
889 |
] |
|
890 |
] |
|
891 |
] |
|
892 |
]. |
|
893 |
||
894 |
needLineNr ifTrue:[ |
|
895 |
(lineNr between:1 and:255) ifTrue:[ |
|
896 |
aStream nextPut:#lineno; nextPut:lineNr. |
|
897 |
] |
|
53 | 898 |
]. |
899 |
||
0 | 900 |
aStream nextPut:theByteCode. |
901 |
pos := aStream position. |
|
902 |
aStream nextPut:0. |
|
104 | 903 |
(argArray at: 1) codeInlineOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler. |
76 | 904 |
|
905 |
code := aStream contents. |
|
0 | 906 |
valueNeeded ifTrue:[ |
47 | 907 |
aStream nextPut:#jump. |
908 |
pos2 := aStream position. |
|
909 |
aStream nextPut:0. |
|
76 | 910 |
code at:pos put:(aStream position). |
47 | 911 |
aStream nextPut:#pushNil. |
76 | 912 |
code at:pos2 put:(aStream position) |
0 | 913 |
] ifFalse:[ |
76 | 914 |
code at:pos put:(aStream position) |
0 | 915 |
] |
916 |
! |
|
917 |
||
104 | 918 |
codeAndIfOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler |
0 | 919 |
"generate code for (x and:[y]) ifxxx:[ ... ]" |
920 |
||
95 | 921 |
|theByteCode optByteCode theReceiver theArg pos1 pos2 pos3 code here jmp| |
0 | 922 |
|
923 |
||
924 |
theByteCode := #falseJump. |
|
925 |
theReceiver := receiver receiver. |
|
926 |
||
927 |
optByteCode := self optimizedConditionFor:theReceiver |
|
47 | 928 |
with:theByteCode. |
0 | 929 |
optByteCode notNil ifTrue:[ |
47 | 930 |
((optByteCode == #eqJump) or:[optByteCode == #notEqJump]) ifTrue:[ |
931 |
theArg := theReceiver arg1 |
|
932 |
]. |
|
933 |
theReceiver := theReceiver receiver. |
|
934 |
theByteCode := optByteCode |
|
0 | 935 |
]. |
104 | 936 |
theReceiver codeOn:aStream inBlock:b for:aCompiler. |
0 | 937 |
theArg notNil ifTrue:[ |
104 | 938 |
theArg codeOn:aStream inBlock:b for:aCompiler |
0 | 939 |
]. |
940 |
aStream nextPut:theByteCode. |
|
941 |
pos1 := aStream position. |
|
942 |
aStream nextPut:0. |
|
943 |
||
944 |
theReceiver := receiver arg1. |
|
104 | 945 |
theReceiver codeInlineOn:aStream inBlock:b for:aCompiler. |
0 | 946 |
(selector == #ifTrue:) ifTrue:[ |
95 | 947 |
jmp := #falseJump |
0 | 948 |
] ifFalse:[ |
95 | 949 |
jmp := #trueJump |
0 | 950 |
]. |
95 | 951 |
aStream nextPut:jmp. |
0 | 952 |
pos2 := aStream position. |
953 |
aStream nextPut:0. |
|
76 | 954 |
|
955 |
code := aStream contents. |
|
0 | 956 |
(selector == #ifFalse:) ifTrue:[ |
76 | 957 |
code at:pos1 put:(aStream position) |
0 | 958 |
]. |
104 | 959 |
(argArray at: 1) codeInlineOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler. |
76 | 960 |
|
0 | 961 |
valueNeeded ifTrue:[ |
47 | 962 |
aStream nextPut:#jump. |
963 |
pos3 := aStream position. |
|
964 |
aStream nextPut:0. |
|
76 | 965 |
here := aStream position. |
47 | 966 |
(selector == #ifTrue:) ifTrue:[ |
76 | 967 |
code at:pos1 put:here |
47 | 968 |
]. |
76 | 969 |
code at:pos2 put:here. |
47 | 970 |
aStream nextPut:#pushNil. |
76 | 971 |
code at:pos3 put:(aStream position) |
0 | 972 |
] ifFalse:[ |
76 | 973 |
here := aStream position. |
47 | 974 |
(selector == #ifTrue:) ifTrue:[ |
76 | 975 |
code at:pos1 put:here |
47 | 976 |
]. |
76 | 977 |
code at:pos2 put:here |
0 | 978 |
] |
979 |
! |
|
980 |
||
104 | 981 |
codeOrIfOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler |
0 | 982 |
"generate code for (x or:[y]) ifxxx:[ ... ]" |
983 |
||
95 | 984 |
|theByteCode optByteCode theReceiver theArg pos1 pos2 pos3 code here jmp| |
0 | 985 |
|
986 |
theByteCode := #trueJump. |
|
987 |
theReceiver := receiver receiver. |
|
988 |
||
3 | 989 |
optByteCode := self optimizedConditionFor:theReceiver with:theByteCode. |
0 | 990 |
optByteCode notNil ifTrue:[ |
47 | 991 |
((optByteCode == #eqJump) or:[optByteCode == #notEqJump]) ifTrue:[ |
992 |
theArg := theReceiver arg1 |
|
993 |
]. |
|
994 |
theReceiver := theReceiver receiver. |
|
995 |
theByteCode := optByteCode |
|
0 | 996 |
]. |
104 | 997 |
theReceiver codeOn:aStream inBlock:b for:aCompiler. |
0 | 998 |
theArg notNil ifTrue:[ |
104 | 999 |
theArg codeOn:aStream inBlock:b for:aCompiler |
0 | 1000 |
]. |
1001 |
aStream nextPut:theByteCode. |
|
1002 |
pos1 := aStream position. |
|
1003 |
aStream nextPut:0. |
|
1004 |
||
3 | 1005 |
|
0 | 1006 |
theReceiver := receiver arg1. |
3 | 1007 |
|
1008 |
"new:" |
|
0 | 1009 |
(selector == #ifTrue:) ifTrue:[ |
47 | 1010 |
theByteCode := #falseJump |
0 | 1011 |
] ifFalse:[ |
47 | 1012 |
theByteCode := #trueJump |
3 | 1013 |
]. |
1014 |
optByteCode := self optimizedConditionFor:theReceiver with:theByteCode. |
|
1015 |
optByteCode notNil ifTrue:[ |
|
47 | 1016 |
theReceiver isBlock ifTrue:[ |
1017 |
theReceiver := theReceiver statements expression |
|
1018 |
]. |
|
1019 |
((optByteCode == #eqJump) or:[optByteCode == #notEqJump]) ifTrue:[ |
|
1020 |
theArg := theReceiver arg1 |
|
1021 |
]. |
|
1022 |
theReceiver := theReceiver receiver. |
|
1023 |
theByteCode := optByteCode. |
|
3 | 1024 |
|
104 | 1025 |
theReceiver codeOn:aStream inBlock:b for:aCompiler. |
47 | 1026 |
theArg notNil ifTrue:[ |
104 | 1027 |
theArg codeOn:aStream inBlock:b for:aCompiler |
47 | 1028 |
]. |
1029 |
aStream nextPut:theByteCode. |
|
3 | 1030 |
|
1031 |
] ifFalse:[ |
|
1032 |
"org" |
|
104 | 1033 |
theReceiver codeInlineOn:aStream inBlock:b for:aCompiler. |
47 | 1034 |
(selector == #ifTrue:) ifTrue:[ |
95 | 1035 |
jmp := #falseJump |
47 | 1036 |
] ifFalse:[ |
95 | 1037 |
jmp := #trueJump |
47 | 1038 |
]. |
95 | 1039 |
aStream nextPut:jmp |
0 | 1040 |
]. |
1041 |
pos2 := aStream position. |
|
1042 |
aStream nextPut:0. |
|
1043 |
(selector == #ifTrue:) ifTrue:[ |
|
47 | 1044 |
(aStream contents) at:pos1 put:(aStream position) |
0 | 1045 |
]. |
104 | 1046 |
(argArray at: 1) codeInlineOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler. |
76 | 1047 |
|
1048 |
code := aStream contents. |
|
0 | 1049 |
valueNeeded ifTrue:[ |
47 | 1050 |
aStream nextPut:#jump. |
1051 |
pos3 := aStream position. |
|
1052 |
aStream nextPut:0. |
|
76 | 1053 |
here := aStream position. |
47 | 1054 |
(selector == #ifFalse:) ifTrue:[ |
76 | 1055 |
code at:pos1 put:here |
47 | 1056 |
]. |
76 | 1057 |
code at:pos2 put:here. |
47 | 1058 |
aStream nextPut:#pushNil. |
76 | 1059 |
code at:pos3 put:(aStream position) |
0 | 1060 |
] ifFalse:[ |
76 | 1061 |
here := aStream position. |
47 | 1062 |
(selector == #ifFalse:) ifTrue:[ |
76 | 1063 |
code at:pos1 put:here |
47 | 1064 |
]. |
76 | 1065 |
code at:pos2 put:here |
0 | 1066 |
] |
1067 |
! |
|
1068 |
||
104 | 1069 |
codeAndOrOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler |
0 | 1070 |
"generate code for x and/or:[y] - but not in an if" |
1071 |
||
1072 |
|pos theReceiver theByteCode| |
|
1073 |
||
1074 |
self halt. |
|
1075 |
theReceiver := receiver. |
|
1076 |
(selector == #and:) ifTrue:[ |
|
47 | 1077 |
theByteCode := #falseJump |
0 | 1078 |
] ifFalse:[ |
47 | 1079 |
theByteCode := #trueJump |
0 | 1080 |
]. |
1081 |
" |
|
1082 |
(self canOptimizeConditionFor:receiver) ifTrue:[ |
|
47 | 1083 |
theByteCode := self optimizedConditionFor:theReceiver |
1084 |
with:theByteCode. |
|
1085 |
theReceiver := theReceiver receiver |
|
0 | 1086 |
]. |
1087 |
" |
|
104 | 1088 |
theReceiver codeOn:aStream inBlock:b for:aCompiler. |
0 | 1089 |
aStream nextPut:theByteCode. |
1090 |
pos := aStream position. |
|
1091 |
aStream nextPut:0. |
|
104 | 1092 |
(argArray at: 1) codeInlineOn:aStream inBlock:b for:aCompiler. |
0 | 1093 |
(aStream contents) at:pos put:(aStream position). |
1094 |
valueNeeded ifFalse:[aStream nextPut:#drop] |
|
1095 |
! |
|
1096 |
||
104 | 1097 |
codeOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler |
117 | 1098 |
|recType nargs isBuiltIn litIndex cls clsLitIndex code| |
0 | 1099 |
|
1100 |
argArray isNil ifTrue:[ |
|
47 | 1101 |
nargs := 0 |
0 | 1102 |
] ifFalse:[ |
47 | 1103 |
nargs := argArray size |
0 | 1104 |
]. |
1105 |
||
1106 |
isBuiltIn := false. |
|
117 | 1107 |
recType := receiver type. |
0 | 1108 |
|
1109 |
(nargs == 0) ifTrue:[ |
|
117 | 1110 |
(recType == #ThisContext) ifTrue:[ |
47 | 1111 |
valueNeeded ifFalse:[ |
1112 |
"for now, only do it in methods" |
|
1113 |
b isNil ifTrue:[ |
|
1114 |
(selector == #restart) ifTrue:[ |
|
95 | 1115 |
aStream nextPut:#jump; nextPut:1. "jump to start" |
47 | 1116 |
^ self |
1117 |
]. |
|
1118 |
]. |
|
1119 |
(selector == #return) ifTrue:[ "^ nil" |
|
1120 |
aStream nextPut:#retNil. |
|
1121 |
^ self |
|
1122 |
]. |
|
1123 |
] |
|
1124 |
]. |
|
52 | 1125 |
|
1126 |
receiver isBlock ifTrue:[ |
|
1127 |
selector == #value ifTrue:[ |
|
104 | 1128 |
receiver codeInlineOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler. |
52 | 1129 |
^ self |
1130 |
]. |
|
1131 |
]. |
|
47 | 1132 |
isBuiltIn := self class isBuiltInUnarySelector:selector |
0 | 1133 |
]. |
1134 |
||
1135 |
(nargs == 1) ifTrue:[ |
|
117 | 1136 |
(recType == #ThisContext) ifTrue:[ |
47 | 1137 |
valueNeeded ifFalse:[ |
1138 |
(selector == #return:) ifTrue:[ |
|
104 | 1139 |
(argArray at:1) codeOn:aStream inBlock:b for:aCompiler. "^ value" |
47 | 1140 |
aStream nextPut:#retTop. |
1141 |
^ self |
|
1142 |
]. |
|
1143 |
]. |
|
1144 |
]. |
|
19 | 1145 |
|
47 | 1146 |
((argArray at:1) isBlock) ifTrue:[ |
1147 |
((selector == #ifTrue:) or:[selector == #ifFalse:]) ifTrue:[ |
|
55 | 1148 |
receiver isBlock ifFalse:[ |
104 | 1149 |
self codeIfOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler. |
55 | 1150 |
^ self |
1151 |
]. |
|
47 | 1152 |
]. |
0 | 1153 |
" |
47 | 1154 |
((selector == #and:) or:[selector == #or:]) ifTrue:[ |
104 | 1155 |
self codeAndOrOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler. |
47 | 1156 |
^ self |
1157 |
]. |
|
0 | 1158 |
" |
47 | 1159 |
(selector == #timesRepeat:) ifTrue:[ |
1160 |
(receiver isConstant and:[receiver evaluate isNumber]) ifTrue:[ |
|
104 | 1161 |
self codeTimesRepeatOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler. |
47 | 1162 |
^ self |
1163 |
] |
|
1164 |
]. |
|
0 | 1165 |
|
47 | 1166 |
((selector == #whileTrue:) or:[selector == #whileFalse:]) ifTrue:[ |
1167 |
(receiver isBlock) ifTrue:[ |
|
104 | 1168 |
self codeWhileOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler. |
47 | 1169 |
^ self |
1170 |
] |
|
1171 |
] |
|
1172 |
]. |
|
1173 |
isBuiltIn := self class isBuiltIn1ArgSelector:selector |
|
0 | 1174 |
]. |
1175 |
||
1176 |
(nargs == 2) ifTrue:[ |
|
47 | 1177 |
((selector == #ifTrue:ifFalse:) or:[selector == #ifFalse:ifTrue:]) ifTrue:[ |
55 | 1178 |
receiver isBlock ifFalse:[ |
1179 |
(argArray at:1) isBlock ifTrue:[ |
|
1180 |
(argArray at:2) isBlock ifTrue:[ |
|
104 | 1181 |
self codeIfElseOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler. |
55 | 1182 |
^ self |
1183 |
] |
|
47 | 1184 |
] |
1185 |
] |
|
1186 |
]. |
|
1187 |
isBuiltIn := self class isBuiltIn2ArgSelector:selector |
|
0 | 1188 |
]. |
1189 |
||
1190 |
"can we use a send-bytecode ?" |
|
1191 |
isBuiltIn ifTrue:[ |
|
48 | 1192 |
receiver isSuper ifFalse:[ |
104 | 1193 |
receiver codeOn:aStream inBlock:b for:aCompiler. |
47 | 1194 |
(nargs > 0) ifTrue:[ |
104 | 1195 |
(argArray at:1) codeOn:aStream inBlock:b for:aCompiler. |
47 | 1196 |
(nargs > 1) ifTrue:[ |
104 | 1197 |
(argArray at:2) codeOn:aStream inBlock:b for:aCompiler |
47 | 1198 |
] |
1199 |
]. |
|
1200 |
aStream nextPut:selector. |
|
1201 |
(self class hasLineNumber:selector) ifTrue:[ |
|
1202 |
aStream nextPut:lineNr. |
|
1203 |
]. |
|
1204 |
valueNeeded ifFalse:[ |
|
1205 |
aStream nextPut:#drop |
|
1206 |
]. |
|
1207 |
^ self |
|
1208 |
] |
|
0 | 1209 |
]. |
1210 |
||
1211 |
((nargs == 0) and:[selector == #yourself]) ifTrue:[ |
|
47 | 1212 |
"yourself is often added to get the receiver - |
1213 |
we get it without the yourself-message" |
|
0 | 1214 |
|
47 | 1215 |
valueNeeded ifTrue:[ |
104 | 1216 |
receiver codeOn:aStream inBlock:b for:aCompiler |
47 | 1217 |
]. |
1218 |
^ self |
|
0 | 1219 |
]. |
1220 |
||
1221 |
"no - generate a send" |
|
117 | 1222 |
|
1223 |
receiver isSuper ifTrue:[ |
|
1224 |
cls := aCompiler targetClass. |
|
1225 |
receiver isHere ifTrue:[ |
|
1226 |
code := #hereSend. |
|
1227 |
] ifFalse:[ |
|
1228 |
code := #superSend. |
|
1229 |
cls := cls superclass. |
|
1230 |
]. |
|
1231 |
clsLitIndex := aCompiler addLiteral:cls. |
|
1232 |
] ifFalse:[ |
|
1233 |
clsLitIndex := 0. |
|
0 | 1234 |
]. |
106 | 1235 |
|
117 | 1236 |
litIndex := aCompiler addLiteral:selector. |
1237 |
(litIndex <= 255 and:[clsLitIndex <= 255]) ifTrue:[ |
|
1238 |
(recType ~~ #Self) ifTrue:[ |
|
1239 |
receiver codeOn:aStream inBlock:b for:aCompiler |
|
1240 |
]. |
|
1241 |
argArray notNil ifTrue:[ |
|
1242 |
argArray do:[:arg | |
|
1243 |
arg codeOn:aStream inBlock:b for:aCompiler |
|
1244 |
] |
|
1245 |
]. |
|
1246 |
||
106 | 1247 |
receiver isSuper ifTrue:[ |
117 | 1248 |
aStream nextPut:code; nextPut:lineNr; nextPut:litIndex; nextPut:nargs; nextPut:clsLitIndex. |
106 | 1249 |
valueNeeded ifFalse:[ |
1250 |
aStream nextPut:#drop |
|
1251 |
]. |
|
1252 |
^ self |
|
1253 |
]. |
|
1254 |
||
1255 |
(nargs <= 3) ifTrue:[ |
|
1256 |
|codes| |
|
1257 |
||
1258 |
valueNeeded ifTrue:[ |
|
1259 |
(receiver type == #Self) ifTrue:[ |
|
1260 |
codes := #(sendSelf0 sendSelf1 sendSelf2 sendSelf3) |
|
1261 |
] ifFalse:[ |
|
1262 |
codes := #(send0 send1 send2 send3) |
|
1263 |
] |
|
1264 |
] ifFalse:[ |
|
1265 |
(receiver type == #Self) ifTrue:[ |
|
1266 |
codes := #(sendSelfDrop0 sendSelfDrop1 sendSelfDrop2 sendSelfDrop3) |
|
1267 |
] ifFalse:[ |
|
1268 |
codes := #(sendDrop0 sendDrop1 sendDrop2 sendDrop3) |
|
1269 |
] |
|
1270 |
]. |
|
117 | 1271 |
aStream nextPut:(codes at:(nargs + 1)); nextPut:lineNr; nextPut:litIndex. |
106 | 1272 |
^ self |
1273 |
]. |
|
1274 |
||
117 | 1275 |
(recType == #Self) ifTrue:[ |
1276 |
code := #sendSelf |
|
106 | 1277 |
] ifFalse:[ |
117 | 1278 |
valueNeeded ifTrue:[ |
1279 |
code := #send |
|
1280 |
] ifFalse:[ |
|
1281 |
code := #sendDrop |
|
1282 |
] |
|
106 | 1283 |
]. |
117 | 1284 |
aStream nextPut:code; nextPut:lineNr; nextPut:litIndex; nextPut:nargs. |
1285 |
valueNeeded ifFalse:[ |
|
1286 |
(recType == #Self) ifTrue:[ |
|
1287 |
aStream nextPut:#drop |
|
1288 |
] |
|
1289 |
]. |
|
106 | 1290 |
^ self |
1291 |
]. |
|
1292 |
||
1293 |
"needs 16bit literal index" |
|
117 | 1294 |
|
48 | 1295 |
receiver isSuper ifTrue:[ |
117 | 1296 |
argArray notNil ifTrue:[ |
1297 |
argArray do:[:arg | |
|
1298 |
arg codeOn:aStream inBlock:b for:aCompiler |
|
1299 |
] |
|
1300 |
]. |
|
49 | 1301 |
receiver isHere ifTrue:[ |
106 | 1302 |
code := #hereSendL |
49 | 1303 |
] ifFalse:[ |
106 | 1304 |
code := #superSendL. |
49 | 1305 |
]. |
117 | 1306 |
aStream nextPut:code; nextPut:lineNr; nextPut:litIndex; nextPut:0; nextPut:nargs; nextPut:clsLitIndex; nextPut:0. |
1307 |
] ifFalse:[ |
|
1308 |
recType ~~ #Self ifTrue:[ |
|
1309 |
receiver codeOn:aStream inBlock:b for:aCompiler. |
|
47 | 1310 |
]. |
117 | 1311 |
argArray notNil ifTrue:[ |
1312 |
argArray do:[:arg | |
|
1313 |
arg codeOn:aStream inBlock:b for:aCompiler |
|
1314 |
] |
|
1315 |
]. |
|
1316 |
||
1317 |
recType == #Self ifTrue:[ |
|
1318 |
code := #sendSelfL |
|
1319 |
] ifFalse:[ |
|
1320 |
code := #sendL |
|
1321 |
]. |
|
1322 |
aStream nextPut:code; nextPut:lineNr; nextPut:litIndex; nextPut:0; nextPut:nargs. |
|
0 | 1323 |
]. |
117 | 1324 |
valueNeeded ifFalse:[ |
1325 |
aStream nextPut:#drop |
|
0 | 1326 |
]. |
117 | 1327 |
|
1328 |
"Modified: 3.9.1995 / 12:55:42 / claus" |
|
0 | 1329 |
! |
1330 |
||
104 | 1331 |
codeSendOn:aStream inBlock:b valueNeeded:valueNeeded for:aCompiler |
0 | 1332 |
"like code on, but assumes that receiver has already been |
1333 |
coded onto stack - needed for cascade" |
|
1334 |
||
117 | 1335 |
|nargs isBuiltIn code litIndex| |
0 | 1336 |
|
1337 |
argArray isNil ifTrue:[ |
|
47 | 1338 |
nargs := 0 |
0 | 1339 |
] ifFalse:[ |
47 | 1340 |
nargs := argArray size |
0 | 1341 |
]. |
1342 |
||
1343 |
isBuiltIn := false. |
|
1344 |
||
1345 |
(nargs == 0) ifTrue:[ |
|
47 | 1346 |
isBuiltIn := self class isBuiltInUnarySelector:selector |
0 | 1347 |
]. |
1348 |
(nargs == 1) ifTrue:[ |
|
47 | 1349 |
isBuiltIn := self class isBuiltIn1ArgSelector:selector |
0 | 1350 |
]. |
1351 |
(nargs == 2) ifTrue:[ |
|
47 | 1352 |
isBuiltIn := self class isBuiltIn2ArgSelector:selector |
0 | 1353 |
]. |
1354 |
||
1355 |
"can we use a send-bytecode ?" |
|
1356 |
isBuiltIn ifTrue:[ |
|
48 | 1357 |
receiver isSuper ifFalse:[ |
47 | 1358 |
(nargs > 0) ifTrue:[ |
104 | 1359 |
(argArray at:1) codeOn:aStream inBlock:b for:aCompiler. |
47 | 1360 |
(nargs > 1) ifTrue:[ |
104 | 1361 |
(argArray at:2) codeOn:aStream inBlock:b for:aCompiler |
47 | 1362 |
] |
1363 |
]. |
|
1364 |
aStream nextPut:selector. |
|
1365 |
(self class hasLineNumber:selector) ifTrue:[ |
|
1366 |
aStream nextPut:lineNr. |
|
1367 |
]. |
|
1368 |
valueNeeded ifFalse:[ |
|
1369 |
aStream nextPut:#drop |
|
1370 |
]. |
|
1371 |
^ self |
|
1372 |
] |
|
0 | 1373 |
]. |
1374 |
||
1375 |
argArray notNil ifTrue:[ |
|
47 | 1376 |
argArray do:[:arg | |
104 | 1377 |
arg codeOn:aStream inBlock:b for:aCompiler |
47 | 1378 |
] |
0 | 1379 |
]. |
1380 |
||
48 | 1381 |
receiver isSuper ifTrue:[ |
117 | 1382 |
litIndex := aCompiler addLiteral:selector. |
1383 |
litIndex <= 255 ifTrue:[ |
|
106 | 1384 |
receiver isHere ifTrue:[ |
1385 |
code := #hereSend |
|
1386 |
] ifFalse:[ |
|
1387 |
code := #superSend. |
|
1388 |
]. |
|
117 | 1389 |
aStream nextPut:code; nextPut:lineNr; nextPut:litIndex; nextPut:nargs; nextPut:nil. |
49 | 1390 |
] ifFalse:[ |
106 | 1391 |
receiver isHere ifTrue:[ |
1392 |
code := #hereSendL |
|
1393 |
] ifFalse:[ |
|
1394 |
code := #superSendL. |
|
1395 |
]. |
|
117 | 1396 |
aStream nextPut:code; nextPut:lineNr; nextPut:litIndex; nextPut:0; nextPut:nargs; nextPut:nil. |
49 | 1397 |
]. |
47 | 1398 |
valueNeeded ifFalse:[ |
1399 |
aStream nextPut:#drop |
|
1400 |
]. |
|
1401 |
^ self |
|
0 | 1402 |
]. |
1403 |
(nargs == 0) ifTrue:[ |
|
47 | 1404 |
(selector == #yourself) ifTrue:[ |
1405 |
"yourself is often added to get the receiver - |
|
1406 |
we get it without the yourself-message" |
|
0 | 1407 |
|
47 | 1408 |
valueNeeded ifFalse:[ |
1409 |
aStream nextPut:#drop |
|
1410 |
]. |
|
1411 |
^ self |
|
1412 |
]. |
|
49 | 1413 |
]. |
0 | 1414 |
|
117 | 1415 |
litIndex := aCompiler addLiteral:selector. |
1416 |
litIndex <= 255 ifTrue:[ |
|
106 | 1417 |
(nargs <= 3) ifTrue:[ |
1418 |
valueNeeded ifTrue:[ |
|
1419 |
code := #(send0 send1 send2 send3) at:(nargs+1). |
|
1420 |
] ifFalse:[ |
|
1421 |
code := #(sendDrop0 sendDrop1 sendDrop2 sendDrop3) at:(nargs+1). |
|
1422 |
]. |
|
117 | 1423 |
aStream nextPut:code; nextPut:lineNr; nextPut:litIndex. |
106 | 1424 |
^ self |
1425 |
]. |
|
1426 |
||
47 | 1427 |
valueNeeded ifTrue:[ |
106 | 1428 |
code := #send |
47 | 1429 |
] ifFalse:[ |
106 | 1430 |
code := #sendDrop |
47 | 1431 |
]. |
117 | 1432 |
aStream nextPut:code; nextPut:lineNr; nextPut:litIndex; nextPut:nargs. |
47 | 1433 |
^ self |
0 | 1434 |
]. |
49 | 1435 |
|
0 | 1436 |
valueNeeded ifTrue:[ |
106 | 1437 |
code := #sendL |
0 | 1438 |
] ifFalse:[ |
106 | 1439 |
code := #sendDropL |
0 | 1440 |
]. |
117 | 1441 |
aStream nextPut:code; nextPut:lineNr; nextPut:litIndex; nextPut:0; nextPut:nargs |
0 | 1442 |
! |
1443 |
||
104 | 1444 |
codeForCascadeOn:aStream inBlock:b for:aCompiler |
0 | 1445 |
"like codeOn, but always leave the receiver instead of the result" |
96 | 1446 |
|
117 | 1447 |
|nargs isBuiltIn code litIndex| |
0 | 1448 |
|
1449 |
argArray isNil ifTrue:[ |
|
47 | 1450 |
nargs := 0 |
0 | 1451 |
] ifFalse:[ |
47 | 1452 |
nargs := argArray size |
0 | 1453 |
]. |
1454 |
||
1455 |
isBuiltIn := false. |
|
1456 |
||
1457 |
(nargs == 0) ifTrue:[ |
|
47 | 1458 |
isBuiltIn := self class isBuiltInUnarySelector:selector |
0 | 1459 |
]. |
1460 |
(nargs == 1) ifTrue:[ |
|
47 | 1461 |
isBuiltIn := self class isBuiltIn1ArgSelector:selector |
0 | 1462 |
]. |
1463 |
(nargs == 2) ifTrue:[ |
|
47 | 1464 |
isBuiltIn := self class isBuiltIn2ArgSelector:selector |
0 | 1465 |
]. |
1466 |
||
104 | 1467 |
receiver codeOn:aStream inBlock:b for:aCompiler. |
0 | 1468 |
aStream nextPut:#dup. |
1469 |
||
1470 |
"can we use a send-bytecode ?" |
|
1471 |
isBuiltIn ifTrue:[ |
|
48 | 1472 |
receiver isSuper ifFalse:[ |
47 | 1473 |
(nargs > 0) ifTrue:[ |
104 | 1474 |
(argArray at:1) codeOn:aStream inBlock:b for:aCompiler. |
47 | 1475 |
(nargs > 1) ifTrue:[ |
104 | 1476 |
(argArray at:2) codeOn:aStream inBlock:b for:aCompiler |
47 | 1477 |
] |
1478 |
]. |
|
106 | 1479 |
aStream nextPut:selector. |
1480 |
(self class hasLineNumber:selector) ifTrue:[ |
|
1481 |
aStream nextPut:lineNr. |
|
1482 |
]. |
|
1483 |
aStream nextPut:#drop. |
|
47 | 1484 |
^ self |
1485 |
] |
|
0 | 1486 |
]. |
1487 |
||
1488 |
"no - generate a send" |
|
1489 |
argArray notNil ifTrue:[ |
|
47 | 1490 |
argArray do:[:arg | |
104 | 1491 |
arg codeOn:aStream inBlock:b for:aCompiler |
47 | 1492 |
] |
0 | 1493 |
]. |
117 | 1494 |
litIndex := aCompiler addLiteral:selector. |
1495 |
litIndex <= 255 ifTrue:[ |
|
106 | 1496 |
receiver isSuper ifTrue:[ |
1497 |
receiver isHere ifTrue:[ |
|
1498 |
code := #hereSend |
|
1499 |
] ifFalse:[ |
|
1500 |
code := #superSend. |
|
1501 |
]. |
|
117 | 1502 |
aStream nextPut:code; nextPut:lineNr; nextPut:litIndex; nextPut:nargs; nextPut:nil; nextPut:#drop. |
106 | 1503 |
^ self |
49 | 1504 |
]. |
106 | 1505 |
(nargs <= 3) ifTrue:[ |
1506 |
code := #(sendDrop0 sendDrop1 sendDrop2 sendDrop3) at:(nargs+1). |
|
117 | 1507 |
aStream nextPut:code; nextPut:lineNr; nextPut:litIndex. |
106 | 1508 |
^ self |
1509 |
]. |
|
1510 |
||
117 | 1511 |
aStream nextPut:#sendDrop; nextPut:lineNr; nextPut:litIndex; nextPut:nargs. |
47 | 1512 |
^ self |
0 | 1513 |
]. |
106 | 1514 |
"need 16bit litIndex" |
1515 |
receiver isSuper ifTrue:[ |
|
1516 |
receiver isHere ifTrue:[ |
|
1517 |
code := #hereSendL |
|
1518 |
] ifFalse:[ |
|
1519 |
code := #superSendL. |
|
1520 |
]. |
|
117 | 1521 |
aStream nextPut:code; nextPut:lineNr; nextPut:litIndex; nextPut:0; nextPut:nargs; nextPut:nil; nextPut:#drop. |
47 | 1522 |
^ self |
0 | 1523 |
]. |
117 | 1524 |
aStream nextPut:#sendDropL; nextPut:lineNr; nextPut:litIndex; nextPut:0; nextPut:nargs |
0 | 1525 |
! ! |