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