'From Squeak3.9 of 7 November 2006 [latest update: #7067] on 19 April 2007 at 10:50:31 am'! !ProtoObject methodsFor: 'testing' stamp: 'vb 4/15/2007 10:54'! ifNil: nilBlock ifNotNil: ifNotNilBlock "Evaluate the block, unless I'm == nil (q.v.)" ^ ifNotNilBlock valueWithPossibleArgs: {self}! ! !ProtoObject methodsFor: 'testing' stamp: 'vb 4/15/2007 10:55'! ifNotNil: ifNotNilBlock ifNil: nilBlock "If I got here, I am not nil, so evaluate the block ifNotNilBlock" ^ ifNotNilBlock valueWithPossibleArgs: {self}! ! !MessageNode methodsFor: 'code generation' stamp: 'vb 4/16/2007 11:40'! emitIfNil: stack on: strm value: forValue "Emits both ifNil: and ifNotNil: code." "vb: The comment seems out of date; #ifNotNil: is expanded to #ifNil:ifNotNil: in 3.9 so this method only handles the ifNil: case." | theNode theSize ifNotNilSelector | theNode _ arguments first. theSize _ sizes at: 1. ifNotNilSelector _ #ifNotNil:. receiver emitForValue: stack on: strm. forValue ifTrue: [strm nextPut: Dup. stack push: 1]. strm nextPut: LdNil. stack push: 1. equalNode emit: stack args: 1 on: strm. self emitBranchOn: (selector key == ifNotNilSelector) dist: theSize pop: stack on: strm. pc _ strm position. forValue ifTrue: [strm nextPut: Pop. stack pop: 1. theNode emitForEvaluatedValue: stack on: strm] ifFalse: [theNode emitForEvaluatedEffect: stack on: strm].! ! !MessageNode methodsFor: 'macro transformations' stamp: 'vb 4/16/2007 11:42'! transformIfNil: encoder "vb: Removed the original transformBoolean: which amounds to a test we perform in each of the branches below." (MacroSelectors at: special) = #ifNotNil: ifTrue: [(self checkBlock: arguments first as: 'ifNotNil arg' from: encoder maxArgs: 1) ifFalse: [^ false]. "Transform 'ifNotNil: [stuff]' to 'ifNil: [nil] ifNotNil: [stuff]'. Slightly better code and more consistent with decompilation." self noteSpecialSelector: #ifNil:ifNotNil:. selector _ SelectorNode new key: (MacroSelectors at: special) code: #macro. arguments _ {BlockNode withJust: NodeNil. arguments first}. (self transform: encoder) ifFalse: [self error: 'compiler logic error']. ^ true] ifFalse: [^ self checkBlock: arguments first as: 'ifNil arg' from: encoder] ! ! !MessageNode methodsFor: 'macro transformations' stamp: 'vb 4/16/2007 11:44'! transformIfNilIfNotNil: encoder "vb: Changed to support one-argument ifNotNil: branch. In the 1-arg case we transform the receiver to (var := receiver) which is further transformed to (var := receiver) == nil ifTrue: .... ifFalse: ... This does not allow the block variable to shadow an existing temp, but it's no different from how to:do: is done." | ifNotNilArg blockVar | ifNotNilArg := arguments at: 2. ((self checkBlock: (arguments at: 1) as: 'Nil arg' from: encoder) and: [self checkBlock: ifNotNilArg as: 'NotNil arg' from: encoder maxArgs: 1]) ifFalse: [^false]. ifNotNilArg numberOfArguments = 1 ifTrue: [blockVar := ifNotNilArg firstArgument. receiver := AssignmentNode new variable: blockVar value: receiver]. selector _ SelectorNode new key: #ifTrue:ifFalse: code: #macro. receiver _ MessageNode new receiver: receiver selector: #== arguments: (Array with: NodeNil) precedence: 2 from: encoder. ^true! ! !MessageNode methodsFor: 'macro transformations' stamp: 'vb 4/16/2007 11:44'! transformIfNotNilIfNil: encoder "vb: Changed to support one-argument ifNotNil: branch. In the 1-arg case we transform the receiver to (var := receiver) which is further transformed to (var := receiver) == nil ifTrue: .... ifFalse: ... This does not allow the block variable to shadow an existing temp, but it's no different from how to:do: is done." | ifNotNilArg blockVar | ifNotNilArg := arguments at: 1. ((self checkBlock: ifNotNilArg as: 'NotNil arg' from: encoder maxArgs: 1) and: [self checkBlock: (arguments at: 2) as: 'Nil arg' from: encoder]) ifFalse: [^false]. ifNotNilArg numberOfArguments = 1 ifTrue: [blockVar := ifNotNilArg firstArgument. receiver := AssignmentNode new variable: blockVar value: receiver]. selector _ SelectorNode new key: #ifTrue:ifFalse: code: #macro. receiver _ MessageNode new receiver: receiver selector: #== arguments: (Array with: NodeNil) precedence: 2 from: encoder. arguments swap: 1 with: 2. ^true ! ! !MessageNode methodsFor: 'private' stamp: 'vb 4/16/2007 11:39'! checkBlock: node as: nodeName from: encoder maxArgs: maxArgs "vb: #canBeSpecialArgument for blocks hardcodes 0 arguments as the requirement for special blocks. We work around that here by further checking the number of arguments for blocks.." node canBeSpecialArgument ifTrue: [^node isMemberOf: BlockNode]. (node isKindOf: BlockNode) ifTrue: [node numberOfArguments <= maxArgs ifTrue: [^true] ifFalse: [^encoder notify: '<- ', nodeName , ' of ' , (MacroSelectors at: special) , ' has too many arguments']] ifFalse: [^encoder notify: '<- ', nodeName , ' of ' , (MacroSelectors at: special) , ' must be a block or variable']! ! !MessageNode methodsFor: 'private' stamp: 'vb 4/15/2007 09:10'! checkBlock: node as: nodeName from: encoder ^self checkBlock: node as: nodeName from: encoder maxArgs: 0! !