[squeak-dev] cascading ifTrue:

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[squeak-dev] cascading ifTrue:

Nicolas Cellier-3

Lurking at recent IRC http://tunes.org/~nef/logs/squeak/09.01.12,
Why couldn't we write:

^0=1
        ifTrue: [self become: 'idiot'];
        ifFalse: [Transcript show: 'Math world is safe'];
        yourself

Well, why not, we just let cascade dup...
Here is a little changeSet for trivial if: cases...
(as usual MIT etc...)

Nicolas

'From Pharo0.1 of 16 May 2008 [Latest update: #10201] on 12 January 2009 at 10:31:01 pm'!
"Change Set: CascadeIfTrue-nice
Date: 12 January 2009
Author: nice

After seeing discussion at http://tunes.org/~nef/logs/squeak/09.01.12
about cascading after a ifTrue:ifFalse:

I told to myself: why not?
At bytecode level, this is easy, just let the cascade dup.
MessageReceiver of cascaded message is just pushed once, dup at each next message.
This behaviour is implemented by letting the receiver be nil.
For some special Macros, this is not easy, to handle absence of receiver, because some have to do special things with receiver (like pushing into an Assignment). But this would be possible, we have the magical dup. haven''t we?
For the first 6 macros like ifTrue:ifFalse:, this is extremely easy here is a primer...

You can then test

^0=1
        inspect;
        ifTrue: [self become: 'idiot']
        ifFalse: [Transcript show: 'Math world is safe'];
        or: [0 ~= 1]
 "!


!MessageNode methodsFor: 'code generation' stamp: 'nice 1/12/2009 21:59'!
emitIf: stack on: strm value: forValue
        | thenExpr thenSize elseExpr elseSize |
        thenSize := sizes at: 1.
        elseSize := sizes at: 2.
        (forValue not and: [(elseSize*thenSize) > 0])
                ifTrue:  "Two-armed IFs forEffect share a single pop"
                        [^ super emitForEffect: stack on: strm].
        thenExpr := arguments at: 1.
        elseExpr := arguments at: 2.
        receiver ifNotNil: [receiver emitForValue: stack on: strm].
        forValue
                ifTrue:  "Code all forValue as two-armed"
                        [self emitBranchOn: false dist: thenSize pop: stack on: strm.
                        pc := strm position.
                        thenExpr emitForEvaluatedValue: stack on: strm.
                        stack pop: 1.  "then and else alternate; they don't accumulate"
                        thenExpr returns not
                                ifTrue:  "Elide jump over else after a return"
                                        [self emitJump: elseSize on: strm].
                        elseExpr emitForEvaluatedValue: stack on: strm]
                ifFalse:  "One arm is empty here (two-arms code forValue)"
                        [thenSize > 0
                                ifTrue:
                                        [self emitBranchOn: false dist: thenSize pop: stack on: strm.
                                        pc := strm position.
                                        thenExpr emitForEvaluatedEffect: stack on: strm]
                                ifFalse:
                                        [self emitBranchOn: true dist: elseSize pop: stack on: strm.
                                        pc := strm position.
                                        elseExpr emitForEvaluatedEffect: stack on: strm]]! !

!MessageNode methodsFor: 'code generation' stamp: 'nice 1/12/2009 21:57'!
sizeIf: encoder value: forValue
        | thenExpr elseExpr branchSize thenSize elseSize |
        thenExpr := arguments at: 1.
        elseExpr := arguments at: 2.
        (forValue
                or: [(thenExpr isJust: NodeNil)
                or: [elseExpr isJust: NodeNil]]) not
                        "(...not ifTrue: avoids using ifFalse: alone during this compile)"
                ifTrue:  "Two-armed IFs forEffect share a single pop"
                        [^ super sizeForEffect: encoder].
        forValue
                ifTrue:  "Code all forValue as two-armed"
                        [elseSize := elseExpr sizeForEvaluatedValue: encoder.
                        thenSize := (thenExpr sizeForEvaluatedValue: encoder)
                                        + (thenExpr returns
                                                ifTrue: [0]  "Elide jump over else after a return"
                                                ifFalse: [self sizeJump: elseSize]).
                        branchSize := self sizeBranchOn: false dist: thenSize]
                ifFalse:  "One arm is empty here (two-arms code forValue)"
                        [(elseExpr isJust: NodeNil)
                                ifTrue:
                                        [elseSize := 0.
                                        thenSize := thenExpr sizeForEvaluatedEffect: encoder.
                                        branchSize := self sizeBranchOn: false dist: thenSize]
                                ifFalse:
                                        [thenSize := 0.
                                        elseSize := elseExpr sizeForEvaluatedEffect: encoder.
                                        branchSize := self sizeBranchOn: true dist: elseSize]].
        sizes := Array with: thenSize with: elseSize.
        ^ (receiver ifNil: [0] ifNotNil: [receiver sizeForValue: encoder]) + branchSize
                        + thenSize + elseSize! !

!MessageNode methodsFor: 'testing' stamp: 'nice 1/12/2009 22:12'!
canCascade

        ^(receiver == NodeSuper or: [special > 6]) not! !