'From Squeak5.3beta of 21 February 2020 [latest update: #19401] on 21 February 2020 at 5:07:28 pm'!

!Object methodsFor: 'casing' stamp: 'ct 2/21/2020 16:56'!
caseOf: aBlockAssociationCollection otherwise: aBlock
	"The elements of aBlockAssociationCollection are associations between blocks.  Answer the evaluated value of the first association in aBlockAssociationCollection whose evaluated key equals the receiver.  If no match is found, answer the result of evaluating aBlock."

	aBlockAssociationCollection associationsDo:
		[:assoc | (assoc key value = self) ifTrue: [^assoc value value]].
	^ aBlock cull: self

"| z | z := {[#a]->[1+1]. ['b' asSymbol]->[2+2]. [#c]->[3+3]}. #b caseOf: z otherwise: [0]"
"| z | z := {[#a]->[1+1]. ['d' asSymbol]->[2+2]. [#c]->[3+3]}. #b caseOf: z otherwise: [0]"
"The following are compiled in-line:"
"#b caseOf: {[#a]->[1+1]. ['b' asSymbol]->[2+2]. [#c]->[3+3]} otherwise: [0]"
"#b caseOf: {[#a]->[1+1]. ['d' asSymbol]->[2+2]. [#c]->[3+3]} otherwise: [0]"
"#b caseOf: {[#a]->[1+1]. ['d' asSymbol]->[2+2]. [#c]->[3+3]} otherwise: [:x | x halt]"! !


!MessageNode methodsFor: 'macro transformations' stamp: 'ct 2/21/2020 17:06'!
transformCase: encoder

	| caseNode |
	caseNode := arguments first.
	(caseNode isMemberOf: BraceNode) ifFalse: [^false].
	(caseNode blockAssociationCheck: encoder) ifFalse: [^false].
	(arguments size = 1
	 or: [self checkBlock: arguments last as: 'otherwise arg' from: encoder maxArgs: 1]) ifFalse:
		[^false].
	 caseNode elements do:
		[:messageNode |
		messageNode receiver noteOptimizedIn: self.
		messageNode arguments first noteOptimizedIn: self].
	 arguments size = 2 ifTrue:
		[| otherwiseBlock |
		otherwiseBlock := arguments last noteOptimizedIn: self.
		otherwiseBlock numberOfArguments = 1 ifTrue:
			[receiver := AssignmentNode new
				variable: otherwiseBlock firstArgument
				value: receiver.
			encoder noteSourceRange: (encoder sourceRangeFor: self) forNode: receiver]].
	 ^true! !


!ObjectTest methodsFor: 'tests' stamp: 'ct 2/21/2020 17:03'!
testCaseOf

	| a b c dict |
	a := Object new.
	b := Object new.
	c := Object new.
	dict := {
		[a] -> [b].
		[b] -> [c].
		[c] -> [a] }.
	self assert: b equals: (a caseOf: dict).
	self assert: c equals: (b caseOf: dict).
	self assert: a equals: (c caseOf: dict).
	self should: [nil caseOf: dict] raise: Error.! !

!ObjectTest methodsFor: 'tests' stamp: 'ct 2/21/2020 17:03'!
testCaseOfInlined

	| a b c |
	a := Object new.
	b := Object new.
	c := Object new.
	self assert: b equals: (a caseOf: { [a] -> [b]. [b] -> [c]. [c] -> [a] }).
	self assert: c equals: (b caseOf: { [a] -> [b]. [b] -> [c]. [c] -> [a] }).
	self assert: a equals: (c caseOf: { [a] -> [b]. [b] -> [c]. [c] -> [a] }).
	self should: [nil caseOf: { [a] -> [b]. [b] -> [c]. [c] -> [a] }] raise: Error.! !

!ObjectTest methodsFor: 'tests' stamp: 'ct 2/21/2020 17:02'!
testCaseOfOtherwise

	| a b c dict |
	a := Object new.
	b := Object new.
	c := Object new.
	dict := {
		[a] -> [b].
		[b] -> [c].
		[c] -> [a] }.
	
	self assert: b equals: (a caseOf: dict otherwise: [self fail]).
	self assert: c equals: (b caseOf: dict otherwise: [self fail]).
	self assert: a equals: (c caseOf: dict otherwise: [self fail]).
	self assert: 42 equals: (nil caseOf: dict otherwise: [42]).
	self assert: 42 equals: (6 caseOf: dict otherwise: [:x | x * 7]).! !

!ObjectTest methodsFor: 'tests' stamp: 'ct 2/21/2020 17:04'!
testCaseOfOtherwiseInlined

	| a b c |
	a := Object new.
	b := Object new.
	c := Object new.
	self assert: b equals: (a caseOf: { [a] -> [b]. [b] -> [c]. [c] -> [a] } otherwise: [self fail]).
	self assert: c equals: (b caseOf: { [a] -> [b]. [b] -> [c]. [c] -> [a] } otherwise: [self fail]).
	self assert: a equals: (c caseOf: { [a] -> [b]. [b] -> [c]. [c] -> [a] } otherwise: [self fail]).
	self assert: 42 equals: (nil caseOf: { [a] -> [b]. [b] -> [c]. [c] -> [a] } otherwise: [42]).
	self assert: 42 equals: (6 caseOf: { [a] -> [b]. [b] -> [c]. [c] -> [a] } otherwise: [:x | x * 7]).! !

