'From Cuis 1.0 of 19 April 2009 [latest update: #187] on 18 May 2009 at 1:36:47 pm'!

!WeakMessageSend commentStamp: 'jmv 5/13/2009 09:48' prior: 0!
Main comment stating the purpose of this class and relevant relationship to other classes.

Possible useful expressions for doIt or printIt.

Structure:
 shouldBeNil	Array of: Boolean -- used to distinguish nil arguments from garbage collected arguments

Any further useful comments about the general approach of this implementation.!


!Object methodsFor: 'events-accessing' stamp: 'jmv 5/13/2009 10:14'!
actionForEvent: anEventSelector
    "Answer the action to be evaluated when <anEventSelector> has been triggered."

	^self actionMap
		at: anEventSelector asSymbol
		ifAbsent: [nil]! !

!Object methodsFor: 'events-accessing' stamp: 'jmv 5/13/2009 10:14'!
actionForEvent: anEventSelector
ifAbsent: anExceptionBlock
    "Answer the action to be evaluated when <anEventSelector> has been triggered."

	| actions |
	actions := self actionMap
		at: anEventSelector asSymbol
		ifAbsent: [nil].
	^actions ifNil: [^anExceptionBlock value]! !

!Object methodsFor: 'events-accessing' stamp: 'jmv 5/13/2009 10:16'!
setActionSequence: actionSequence
forEvent: anEventSelector

	| action |
	"This is a good time to compact the action sequence of old, garbage collected stuff."
	action := actionSequence asMinimalRepresentation.
	action
		ifNil: [ self removeActionsForEvent: anEventSelector]
		ifNotNil: [
			self updateableActionMap
				at: anEventSelector asSymbol
				put: action]! !


!WeakActionSequence methodsFor: 'converting' stamp: 'jmv 5/13/2009 10:20'!
asMinimalRepresentation

	| valid |
	valid := self reject: [:e | e isReceiverOrAnyArgumentGarbage ].
	valid size = 0
		ifTrue: [ ^nil ].
	valid size = 1
		ifTrue: [ ^valid first ].
	^valid! !

!WeakActionSequence methodsFor: 'evaluating' stamp: 'jmv 5/13/2009 10:13'!
value
	"Answer the result of evaluating the elements of the receiver.
	Actually, return just the last result."

	| answer |
	self do: [ :each | 
		answer := each value].
	^answer! !

!WeakActionSequence methodsFor: 'evaluating' stamp: 'jmv 5/13/2009 10:13'!
valueWithArguments: anArray
	"Return the last result"

	| answer |
	self do: [ :each |
		answer := each valueWithArguments: anArray ].
	^answer! !


!WeakActionSequenceTrappingErrors methodsFor: 'evaluating' stamp: 'jmv 5/18/2009 13:36'!
valueStartingFrom: startIndex
	"Do the same as my parent, but make sure that all actions that do not 
	give errors are evaluated before resignaling the ones that gave errors 
	(giving the chance to clients to handle them)."

	"Note: I currently trap Halt,Exception so that I am sure to get a Halt event in case of a Halt. This is being fixed in the exception system - when the fix is done it will be enough to capture only Exception."

	| each answer |
	startIndex to: self size do: [:index |
		each := self at: index.
		[ answer := each value ]
			on: Halt, Error
			do: [:exc | 
				self valueStartingFrom: index + 1.
				exc pass]].
	^ answer! !

!WeakActionSequenceTrappingErrors methodsFor: 'evaluating' stamp: 'jmv 5/18/2009 13:36'!
valueWithArguments: anArray startingFrom: startIndex
	"Do the same as my parent, but make sure that all actions that do not 
	give errors are evaluated before resignaling the ones that gave errors 
	(giving the chance to clients to handle them)."

	"Note: I currently trap Halt,Exception so that I am sure to get a Halt event in case of a Halt. This is being fixed in the exception system - when the fix is done it will be enough to capture only Exception."

	| each answer |
	startIndex to: self size do: [:index |
		each := self at: index.
		[ answer := each valueWithArguments: anArray ]
			on: Halt, Error
			do: [:exc | 
				self valueWithArguments: anArray startingFrom: index + 1.
				exc pass]].
	^ answer! !


!WeakMessageSend methodsFor: 'converting' stamp: 'jmv 5/13/2009 10:19'!
asMinimalRepresentation

	^self isReceiverOrAnyArgumentGarbage
		ifTrue: [ nil ]
		ifFalse: [ self ]! !

!WeakMessageSend methodsFor: 'evaluating' stamp: 'jmv 5/13/2009 10:24'!
value
	^ arguments isNil
		ifTrue: [
			self withEnsuredReceiverDo: [ :r | r perform: selector ]]
		ifFalse: [
			self withEnsuredReceiverAndArgumentsDo: [ :r :a |
				r
					perform: selector
					withArguments: a ]]! !

!WeakMessageSend methodsFor: 'evaluating' stamp: 'jmv 5/13/2009 10:24'!
valueWithArguments: anArray
	| argsToUse |
	
	"Safe to use, because they are built before ensureing receiver and args..."
	argsToUse := self collectArguments: anArray.
	^ self withEnsuredReceiverAndArgumentsDo: [ :r :a |
		r
			perform: selector
			withArguments: argsToUse ]! !

!WeakMessageSend methodsFor: 'evaluating' stamp: 'jmv 5/13/2009 10:25'!
valueWithEnoughArguments: anArray

	"call the selector with enough arguments from arguments and anArray"
	| args |
	args := Array new: selector numArgs.
	args replaceFrom: 1
		to: ( arguments size min: args size)
		with: arguments
		startingAt: 1.
	args size > arguments size ifTrue: [
		args replaceFrom: arguments size + 1
			to: (arguments size + anArray size min: args size)
			with: anArray
			startingAt: 1.
	].

	"args is safe to use, because they are built before ensuring receiver and args..."
	^self withEnsuredReceiverAndArgumentsDo: [ :r :a |
		r
			perform: selector
			withArguments: args ]! !

WeakMessageSend removeSelector: #ensureReceiver!
WeakMessageSend removeSelector: #ensureReceiverAndArguments!
WeakMessageSend removeSelector: #isValid!
