'From Cuis 1.0 of 28 November 2009 [latest update: #337] on 7 December 2009 at 10:08:18 pm'!
!classDefinition: #AdditionalMethodState category: #'Kernel-Methods'!
Object variableSubclass: #AdditionalMethodState
	instanceVariableNames: 'method selector'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Kernel-Methods'!

!AdditionalMethodState commentStamp: '<historical>' prior: 0!
I am class holding state for compiled methods. All my instance variables should be actually part of the CompiledMethod itself, but the current implementation of the VM doesn't allow this.  Currently I hold the selector and any pragmas or properties the compiled method has.  Pragmas and properties are stored in indexable fields; pragmas as instances of Pragma, properties as instances of Association.

I am a reimplementation of much of MethodProperties, but eliminating the explicit properties and pragmas dictionaries.  Hence I answer true to isMethodProperties.!

!classDefinition: #BlockClosure category: #'Kernel-Methods'!
Object variableSubclass: #BlockClosure
	instanceVariableNames: 'outerContext startpc numArgs'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Kernel-Methods'!

!BlockClosure commentStamp: '<historical>' prior: 0!
I am a block closure for Eliot's closure implementation.  Not to be confused with the old BlockClosure.!

!classDefinition: #BlockStartLocator category: #'Kernel-Methods'!
InstructionClient subclass: #BlockStartLocator
	instanceVariableNames: 'nextJumpIsAroundBlock'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Kernel-Methods'!
!classDefinition: #InstructionPrinter category: #'Kernel-Methods'!
InstructionClient subclass: #InstructionPrinter
	instanceVariableNames: 'method scanner stream oldPC indent indentSpanOfFollowingJump printPC innerIndents '
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Kernel-Methods'!
!classDefinition: #MessageCatcher category: #'Kernel-Methods'!
ProtoObject subclass: #MessageCatcher
	instanceVariableNames: 'echoToTranscript accumulator '
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Kernel-Methods'!
!classDefinition: #MethodProperties category: #'Kernel-Methods'!
Object subclass: #MethodProperties
	instanceVariableNames: 'properties pragmas selector'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Kernel-Methods'!

!MethodProperties commentStamp: 'lr 2/6/2006 19:31' prior: 0!
I am class holding state for compiled methods. All my instance variables should be actually part of the CompiledMethod itself, but the current implementation of the VM doesn't allow this.

I am a compact class and optimized for size and speed, since every CompiledMethod points onto an instance of myself. I am mostly polymorphic to the protocol of an identity-dictionary, so that key-value pairs can be easily stored and retreived without the need to add new variables. However keep in mind that instantiating a dictionary consumes much more memory than adding an instance-variable, so it might be clever to add a new variable if the property is going to be used by every compiled method.!

!classDefinition: #Pragma category: #'Kernel-Methods'!
Object subclass: #Pragma
	instanceVariableNames: 'method keyword arguments'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Kernel-Methods'!

!Pragma commentStamp: '<historical>' prior: 0!
I represent an occurrence of a pragma in a compiled method.  A pragma is a literal message pattern that occurs between angle brackets at the start of a method after any temporaries.  A common example is the primitive pragma:
	<primitive: 123 errorCode: 'errorCode'>
but one can add one's own and use them as metadata attached to a method.  Because pragmas are messages one can browsse senders and implementors and perform them.  One can query a method for its pragmas by sendng it the pragmas message, which answers an Array of instances of me, one for each pragma in the method.

I can provide information about the defining class, method, its selector, as well as the information about the pragma keyword and its arguments. See the two 'accessing' protocols for details. 'accessing-method' provides information about the method the pragma is found in, while 'accessing-pragma' is about the pragma itself.

Instances are retrieved using one of the pragma search methods of the 'finding' protocol on the class side.

To browse all methods with pragmas in the system evaluate
	SystemNavigation default browseAllSelect: [:m| m pragmas notEmpty]
and to browse all nonprimitive methods with pragmas evaluate
	SystemNavigation default browseAllSelect: [:m| m primitive isZero and: [m pragmas notEmpty]]!

!classDefinition: #RelativeInstructionPrinter category: #'Kernel-Methods'!
InstructionPrinter subclass: #RelativeInstructionPrinter
	instanceVariableNames: 'printCode labels labelling'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Kernel-Methods'!

!AdditionalMethodState methodsFor: 'testing' stamp: 'nice 11/8/2009 12:47'!
analogousCodeTo: aMethodProperties
	| bs |
	(aMethodProperties isKindOf: MethodProperties) ifTrue: [^aMethodProperties analogousCodeTo: self].
	(bs := self basicSize) ~= aMethodProperties basicSize ifTrue:
		[^false].
	1 to: bs do:
		[:i|
		((self basicAt: i) analogousCodeTo: (aMethodProperties basicAt: i)) ifFalse:
			[^false]].
	^true! !

!AdditionalMethodState methodsFor: 'testing' stamp: 'nice 11/8/2009 12:27'!
hasAtLeastTheSamePropertiesAs: aMethodProperties
	"Answer if the recever has at least the same properties as the argument.
	 N.B. The receiver may have additional properties and still answer true."
	aMethodProperties keysAndValuesDo:
		[:k :v|
		(v isKindOf: Pragma)
			"ifTrue: [Pragmas have already been checked]"
			ifFalse: [
				(self includes: k->v) ifFalse: [^false]]].
	^true! !

!AdditionalMethodState methodsFor: 'testing' stamp: 'bgf 12/6/2008 12:15'!
hasLiteralSuchThat: aBlock
	"Answer true if litBlock returns true for any literal in this array, even if embedded in further array structure.
	 This method is only intended for private use by CompiledMethod hasLiteralSuchThat:"
	1 to: self basicSize do: [:i |
		| propertyOrPragma "<Association|Pragma>" |
		propertyOrPragma := self basicAt: i.
		(propertyOrPragma isVariableBinding
			ifTrue: [(aBlock value: propertyOrPragma key)
					or: [(aBlock value: propertyOrPragma value)
					or: [propertyOrPragma value isArray
						and: [propertyOrPragma value hasLiteralSuchThat: aBlock]]]]
			ifFalse: [propertyOrPragma hasLiteralSuchThat: aBlock]) ifTrue:
			[^true]].
	^false! !

!AdditionalMethodState methodsFor: 'testing' stamp: 'eem 11/29/2008 16:40'!
hasLiteralThorough: literal
	"Answer true if any literal in these properties is literal,
	 even if embedded in array structure."
	1 to: self basicSize do: [:i |
		| propertyOrPragma "<Association|Pragma>" |
		propertyOrPragma := self basicAt: i.
		(propertyOrPragma isVariableBinding
			ifTrue: [propertyOrPragma key == literal
					or: [propertyOrPragma value == literal
					or: [propertyOrPragma value isArray
						and: [propertyOrPragma value hasLiteral: literal]]]]
			ifFalse: [propertyOrPragma hasLiteral: literal]) ifTrue:
			[^true]].
	^false! !

!AdditionalMethodState methodsFor: 'testing' stamp: 'eem 12/1/2008 10:53'!
includes: aPropertyOrPragma "<Association|Pragma>"
	"Test if the property or pragma is present."

	1 to: self basicSize do:
		[:i |
		(self basicAt: i) = aPropertyOrPragma ifTrue:
			[^true]].
	^false! !

!AdditionalMethodState methodsFor: 'testing' stamp: 'eem 12/1/2008 10:53'!
includesKey: aKey
	"Test if the property aKey or pragma with selector aKey is present."

	1 to: self basicSize do:
		[:i |
		(self basicAt: i) key == aKey ifTrue:
			[^true]].
	^false! !

!AdditionalMethodState methodsFor: 'testing' stamp: 'eem 11/29/2008 13:47'!
isEmpty
	^self basicSize = 0! !

!AdditionalMethodState methodsFor: 'testing' stamp: 'md 2/19/2006 11:24'!
isMethodProperties
	^true! !

!AdditionalMethodState methodsFor: 'testing' stamp: 'eem 12/1/2008 16:49'!
notEmpty
	^self basicSize > 0! !

!AdditionalMethodState methodsFor: 'accessing' stamp: 'eem 11/29/2008 10:19'!
at: aKey
	"Answer the property value or pragma associated with aKey."
	
	^self at: aKey ifAbsent: [self error: 'not found']! !

!AdditionalMethodState methodsFor: 'accessing' stamp: 'eem 12/1/2008 10:55'!
at: aKey ifAbsent: aBlock
	"Answer the property value or pragma associated with aKey or,
	 if aKey isn't found, answer the result of evaluating aBlock."

	1 to: self basicSize do:
		[:i |
		| propertyOrPragma "<Association|Pragma>" |
		(propertyOrPragma := self basicAt: i) key == aKey ifTrue:
			[^propertyOrPragma isVariableBinding
				ifTrue: [propertyOrPragma value]
				ifFalse: [propertyOrPragma]]].
	^aBlock value! !

!AdditionalMethodState methodsFor: 'accessing' stamp: 'eem 12/1/2008 10:54'!
at: aKey ifAbsentPut: aBlock
	"Answer the property value or pragma associated with aKey or,
	 if aKey isn't found, answer the result of evaluating aBlock."

	1 to: self basicSize do:
		[:i |
		| propertyOrPragma "<Association|Pragma>" |
		(propertyOrPragma := self basicAt: i) key == aKey ifTrue:
			[^propertyOrPragma isVariableBinding
				ifTrue: [propertyOrPragma value]
				ifFalse: [propertyOrPragma]]].
	^method propertyValueAt: aKey put: aBlock value! !

!AdditionalMethodState methodsFor: 'accessing' stamp: 'eem 12/1/2008 10:56'!
at: aKey put: aValue
	"Replace the property value or pragma associated with aKey."
	
	1 to: self basicSize do:
		[:i |
		| propertyOrPragma "<Association|Pragma>" |
		(propertyOrPragma := self basicAt: i) key == aKey ifTrue:
			[propertyOrPragma isVariableBinding
				ifTrue: [propertyOrPragma value: aValue]
				ifFalse: [self basicAt: i put: aValue]]].
	^method propertyValueAt: aKey put: aValue! !

!AdditionalMethodState methodsFor: 'accessing' stamp: 'eem 11/29/2008 18:36'!
keysAndValuesDo: aBlock
	"Enumerate the receiver with all the keys and values."

	1 to: self basicSize do: [:i |
		| propertyOrPragma "<Association|Pragma>" |
		(propertyOrPragma := self basicAt: i) isVariableBinding
			ifTrue: [aBlock value: propertyOrPragma key value: propertyOrPragma value]
			ifFalse: [aBlock value: propertyOrPragma keyword value: propertyOrPragma]]! !

!AdditionalMethodState methodsFor: 'accessing' stamp: 'eem 11/29/2008 14:11'!
pragmas
	"Answer the raw messages comprising my pragmas."
	| pragmaStream |
	pragmaStream := WriteStream on: (Array new: self basicSize).
	1 to: self basicSize do: [:i |
		| propertyOrPragma "<Association|Message>" |
		(propertyOrPragma := self basicAt: i) isVariableBinding ifFalse:
			[pragmaStream nextPut: propertyOrPragma]].
	^pragmaStream contents! !

!AdditionalMethodState methodsFor: 'accessing' stamp: 'eem 11/29/2008 10:25'!
properties

	| propertyStream |
	propertyStream := WriteStream on: (Array new: self basicSize * 2).
	1 to: self basicSize do: [:i |
		| propertyOrPragma "<Association|Pragma>" |
		(propertyOrPragma := self basicAt: i) isVariableBinding ifTrue:
			[propertyStream nextPut: propertyOrPragma key; nextPut: propertyOrPragma value]].
	^IdentityDictionary newFromPairs: propertyStream contents! !

!AdditionalMethodState methodsFor: 'accessing' stamp: 'eem 11/29/2008 19:32'!
removeKey: aKey ifAbsent: aBlock
	"Remove the property with aKey. Answer the value or, if aKey isn't found, answer the result of evaluating aBlock."
	
	1 to: self basicSize do: [:i |
		| propertyOrPragma "<Association|Pragma>" |
		propertyOrPragma := self basicAt: i.
		(propertyOrPragma isVariableBinding
				ifTrue: [propertyOrPragma key]
				ifFalse: [propertyOrPragma keyword])
			== aKey ifTrue:
			[^method removeProperty: aKey]].
	^aBlock value! !

!AdditionalMethodState methodsFor: 'accessing' stamp: 'md 2/16/2006 17:50'!
selector
	^selector! !

!AdditionalMethodState methodsFor: 'accessing' stamp: 'md 2/16/2006 17:50'!
selector: aSymbol
	selector := aSymbol! !

!AdditionalMethodState methodsFor: 'accessing' stamp: 'eem 11/29/2008 18:28'!
setMethod: aMethod
	method := aMethod.
	1 to: self basicSize do:
		[:i| | propertyOrPragma "<Association|Pragma>" |
		(propertyOrPragma := self basicAt: i) isVariableBinding ifFalse:
			[propertyOrPragma setMethod: aMethod]]! !

!AdditionalMethodState methodsFor: 'copying' stamp: 'eem 11/29/2008 18:35'!
copyWith: aPropertyOrPragma "<Association|Pragma>"
	"Answer a copy of the receiver which includes aPropertyOrPragma"
	| bs copy |
	(Association == aPropertyOrPragma class
	 or: [Pragma == aPropertyOrPragma class]) ifFalse:
		[self error: self class name, ' instances should hold only Associations or Pragmas.'].
	copy := self class new: (bs := self basicSize) + 1.
	1 to: bs do:
		[:i|
		copy basicAt: i put: (self basicAt: i)].
	copy basicAt: bs + 1 put: aPropertyOrPragma.
	^copy
		selector: selector;
		setMethod: method;
		yourself
! !

!AdditionalMethodState methodsFor: 'copying' stamp: 'eem 11/29/2008 18:35'!
copyWithout: aPropertyOrPragma "<Association|Pragma>"
	"Answer a copy of the receiver which no longer includes aPropertyOrPragma"
	| bs copy offset |
	copy := self class new: (bs := self basicSize) - ((self includes: aPropertyOrPragma)
													ifTrue: [1]
													ifFalse: [0]).
	offset := 0.
	1 to: bs do:
		[:i|
		(self basicAt: i) = aPropertyOrPragma
			ifTrue: [offset := 1]
			ifFalse: [copy basicAt: i - offset put: (self basicAt: i)]].
	^copy
		selector: selector;
		setMethod: method;
		yourself
! !

!AdditionalMethodState methodsFor: 'properties' stamp: 'eem 11/29/2008 10:28'!
includesProperty: aKey
	"Test if the property aKey is present."

	1 to: self basicSize do: [:i |
		| propertyOrPragma "<Association|Pragma>" |
		propertyOrPragma := self basicAt: i.
		(propertyOrPragma isVariableBinding
		 and: [propertyOrPragma key == aKey]) ifTrue:
			[^true]].
	^false! !

!AdditionalMethodState methodsFor: 'properties' stamp: 'eem 11/29/2008 10:18'!
propertyKeysAndValuesDo: aBlock
	"Enumerate the receiver with all the keys and values."

	1 to: self basicSize do: [:i |
		| propertyOrPragma "<Association|Pragma>" |
		(propertyOrPragma := self basicAt: i) isVariableBinding ifTrue:
			[aBlock value: propertyOrPragma key value: propertyOrPragma value]]! !

!AdditionalMethodState methodsFor: 'properties' stamp: 'eem 11/29/2008 11:46'!
propertyValueAt: aKey
	"Answer the property value associated with aKey."
	
	^ self propertyValueAt: aKey ifAbsent: [ self error: 'Property not found' ].! !

!AdditionalMethodState methodsFor: 'properties' stamp: 'eem 11/29/2008 11:45'!
propertyValueAt: aKey ifAbsent: aBlock
	"Answer the property value associated with aKey or, if aKey isn't found, answer the result of evaluating aBlock."

	1 to: self basicSize do: [:i |
		| propertyOrPragma "<Association|Pragma>" |
		propertyOrPragma := self basicAt: i.
		(propertyOrPragma isVariableBinding
		 and: [propertyOrPragma key == aKey]) ifTrue:
			[^propertyOrPragma value]].
	^aBlock value! !

!AdditionalMethodState methodsFor: 'properties' stamp: 'lr 2/6/2006 20:48'!
removeKey: aKey
	"Remove the property with aKey. Answer the property or raise an error if aKey isn't found."
	
	^ self removeKey: aKey ifAbsent: [ self error: 'Property not found' ].! !

!AdditionalMethodState methodsFor: 'decompiling' stamp: 'eem 6/11/2009 17:06'!
method: aMethodNodeOrNil
	"For decompilation"
	method := aMethodNodeOrNil! !


!AdditionalMethodState class methodsFor: 'instance creation' stamp: 'eem 11/29/2008 18:48'!
forMethod: aMethod selector: aSelector
	^(self basicNew: 0)
		selector: aSelector;
		setMethod: aMethod;
		yourself! !

!AdditionalMethodState class methodsFor: 'instance creation' stamp: 'eem 11/28/2008 12:26'!
selector: aSelector with: aPropertyOrPragma
	^(self basicNew: 1)
		selector: aSelector;
		basicAt: 1 put: aPropertyOrPragma;
		yourself! !


!BlockClosure methodsFor: 'accessing' stamp: 'ar 9/1/2009 01:19'!
argumentCount
	"Answers the number of arguments needed to evaluate the receiver.
	For ansi compatibility."
	^ self numArgs! !

!BlockClosure methodsFor: 'accessing' stamp: 'eem 9/3/2008 13:57'!
copiedValueAt: i
	<primitive: 60>
	^self basicAt: i! !

!BlockClosure methodsFor: 'accessing' stamp: 'eem 7/28/2008 13:58'!
home
	^outerContext home! !

!BlockClosure methodsFor: 'accessing' stamp: 'ajh 1/21/2003 13:16'!
isBlock

	^ true! !

!BlockClosure methodsFor: 'accessing' stamp: 'eem 5/29/2008 12:18'!
method
	^outerContext method! !

!BlockClosure methodsFor: 'accessing' stamp: 'eem 5/28/2008 16:02'!
numArgs
	"Answer the number of arguments that must be used to evaluate this block"

	^numArgs! !

!BlockClosure methodsFor: 'accessing' stamp: 'eem 9/3/2008 14:07'!
numCopiedValues
	"Answer the number of copied values of the receiver.  Since these are
	 stored in the receiver's indexable fields this is the receiver's basic size.
	 Primitive. Answer the number of indexable variables in the receiver. 
	 This value is the same as the largest legal subscript."

	<primitive: 62>
	^self basicSize! !

!BlockClosure methodsFor: 'accessing' stamp: 'eem 5/24/2008 11:21'!
outerContext
	^outerContext! !

!BlockClosure methodsFor: 'accessing' stamp: 'eem 6/26/2008 09:17'!
receiver
	^outerContext receiver! !

!BlockClosure methodsFor: 'accessing' stamp: 'eem 6/1/2008 09:39'!
startpc
	^startpc! !

!BlockClosure methodsFor: 'controlling' stamp: 'jf 9/3/2003 16:45'!
doWhileFalse: conditionBlock
	"Evaluate the receiver once, then again as long the value of conditionBlock is false."
 
	| result |
	[result := self value.
	conditionBlock value] whileFalse.

	^ result! !

!BlockClosure methodsFor: 'controlling' stamp: 'jf 9/3/2003 16:39'!
doWhileTrue: conditionBlock
	"Evaluate the receiver once, then again as long the value of conditionBlock is true."
 
	| result |
	[result := self value.
	conditionBlock value] whileTrue.

	^ result! !

!BlockClosure methodsFor: 'controlling' stamp: 'sma 5/12/2000 13:22'!
repeat
	"Evaluate the receiver repeatedly, ending only if the block explicitly returns."

	[self value. true] whileTrue! !

!BlockClosure methodsFor: 'controlling' stamp: 'ls 9/24/1999 09:45'!
repeatWithGCIf: testBlock
	| ans |
	"run the receiver, and if testBlock returns true, garbage collect and run the receiver again"
	ans := self value.
	(testBlock value: ans) ifTrue: [ Smalltalk garbageCollect. ans := self value ].
	^ans! !

!BlockClosure methodsFor: 'controlling'!
whileFalse
	"Ordinarily compiled in-line, and therefore not overridable.
	This is in case the message is sent to other than a literal block.
	Evaluate the receiver, as long as its value is false."
 
	^ [self value] whileFalse: []! !

!BlockClosure methodsFor: 'controlling'!
whileFalse: aBlock 
	"Ordinarily compiled in-line, and therefore not overridable.
	This is in case the message is sent to other than a literal block.
	Evaluate the argument, aBlock, as long as the value of the receiver is false."

	^ [self value] whileFalse: [aBlock value]! !

!BlockClosure methodsFor: 'controlling' stamp: 'jcg 7/8/2007 18:25'!
whileNil: aBlock 
	"Unlike #whileTrue/False: this is not compiled inline."
	^ [self value isNil] whileTrue: [aBlock value]
	! !

!BlockClosure methodsFor: 'controlling' stamp: 'jcg 7/8/2007 18:25'!
whileNotNil: aBlock 
	"Unlike #whileTrue/False: this is not compiled inline."
	^ [self value notNil] whileTrue: [aBlock value]
	! !

!BlockClosure methodsFor: 'controlling'!
whileTrue
	"Ordinarily compiled in-line, and therefore not overridable.
	This is in case the message is sent to other than a literal block.
	Evaluate the receiver, as long as its value is true."
 
	^ [self value] whileTrue: []! !

!BlockClosure methodsFor: 'controlling'!
whileTrue: aBlock 
	"Ordinarily compiled in-line, and therefore not overridable.
	This is in case the message is sent to other than a literal block.
	Evaluate the argument, aBlock, as long as the value of the receiver is true."

	^ [self value] whileTrue: [aBlock value]! !

!BlockClosure methodsFor: 'evaluating' stamp: 'cmm 2/16/2003 16:08'!
bench
	"See how many times I can value in 5 seconds.  I'll answer a meaningful description."

	| startTime endTime count |
	count := 0.
	endTime := Time millisecondClockValue + 5000.
	startTime := Time millisecondClockValue.
	[ Time millisecondClockValue > endTime ] whileFalse: [ self value.  count := count + 1 ].
	endTime := Time millisecondClockValue.
	^count = 1
		ifTrue: [ ((endTime - startTime) // 1000) printString, ' seconds.' ]
		ifFalse:
			[ ((count * 1000) / (endTime - startTime)) asFloat printString, ' per second.' ]! !

!BlockClosure methodsFor: 'evaluating' stamp: 'brp 9/25/2003 13:49'!
durationToRun

	"Answer the duration taken to execute this block."



	^ Duration milliSeconds: self timeToRun



! !

!BlockClosure methodsFor: 'evaluating' stamp: 'ajh 1/13/2002 13:36'!
ifError: errorHandlerBlock
	"Evaluate the block represented by the receiver, and normally return it's value.  If an error occurs, the errorHandlerBlock is evaluated, and it's value is instead returned.  The errorHandlerBlock must accept zero, one, or two parameters (the error message and the receiver)."
	"Examples:
		[1 whatsUpDoc] ifError: [:err :rcvr | 'huh?'].
		[1 / 0] ifError: [:err :rcvr |
			'ZeroDivide' = err
				ifTrue: [Float infinity]
				ifFalse: [self error: err]]
"

	^ self on: Error do: [:ex |
		errorHandlerBlock valueWithPossibleArgs: {ex description. ex receiver}]! !

!BlockClosure methodsFor: 'evaluating' stamp: 'eem 9/5/2009 13:05'!
simulateValueWithArguments: anArray caller: aContext
	| newContext sz |
	(anArray class ~~ Array
	 or: [numArgs ~= anArray size]) ifTrue:
		[^ContextPart primitiveFailToken].
	newContext := (MethodContext newForMethod: outerContext method)
						setSender: aContext
						receiver: outerContext receiver
						method: outerContext method
						closure: self
						startpc: startpc.
	sz := self basicSize.
	newContext stackp: sz + numArgs.
	1 to: numArgs do:
		[:i| newContext at: i put: (anArray at: i)].
	1 to: sz do:
		[:i| newContext at: i + numArgs put: (self at: i)].
	^newContext! !

!BlockClosure methodsFor: 'evaluating' stamp: 'jm 6/3/1998 14:25'!
timeToRun
	"Answer the number of milliseconds taken to execute this block."

	^ Time millisecondsToRun: self
! !

!BlockClosure methodsFor: 'evaluating' stamp: 'ul 9/25/2009 23:27'!
timeToRunWithoutGC
	"Answer the number of milliseconds taken to execute this block without GC time."

	^(SmalltalkImage current vmParameterAt: 8) + 
		(SmalltalkImage current vmParameterAt: 10) +
		self timeToRun -
		(SmalltalkImage current vmParameterAt: 8) - 
		(SmalltalkImage current vmParameterAt: 10)
! !

!BlockClosure methodsFor: 'evaluating' stamp: 'eem 9/3/2008 14:09'!
value
	"Activate the receiver, creating a closure activation (MethodContext)
	 whose closure is the receiver and whose caller is the sender of this message.
	 Supply the copied values to the activation as its arguments and copied temps.
	 Primitive. Optional (but you're going to want this for performance)."
	| newContext ncv |
	<primitive: 201>
	numArgs ~= 0 ifTrue:
		[self numArgsError: 0].
	newContext := self asContextWithSender: thisContext sender.
	(ncv := self numCopiedValues) > 0 ifTrue:
		[newContext stackp: ncv.
		1 to: ncv do: "nil basicSize = 0"
			[:i| newContext at: i put: (self at: i)]].
	thisContext privSender: newContext! !

!BlockClosure methodsFor: 'evaluating' stamp: 'eem 9/3/2008 14:09'!
value: anArg
	"Activate the receiver, creating a closure activation (MethodContext)
	 whose closure is the receiver and whose caller is the sender of this message.
	 Supply the argument and copied values to the activation as its arguments and copied temps.
	 Primitive. Optional (but you're going to want this for performance)."
	| newContext ncv |
	<primitive: 202>
	numArgs ~= 1 ifTrue:
		[self numArgsError: 1].
	newContext := self asContextWithSender: thisContext sender.
	ncv := self numCopiedValues.
	newContext stackp: ncv + 1.
	newContext at: 1 put: anArg.
	1 to: ncv do:
		[:i| newContext at: i + 1 put: (self at: i)].
	thisContext privSender: newContext! !

!BlockClosure methodsFor: 'evaluating' stamp: 'eem 9/3/2008 14:10'!
value: firstArg value: secondArg
	"Activate the receiver, creating a closure activation (MethodContext)
	 whose closure is the receiver and whose caller is the sender of this message.
	 Supply the arguments and copied values to the activation as its arguments and copied temps.
	 Primitive. Optional (but you're going to want this for performance)."
	| newContext ncv |
	<primitive: 203>
	numArgs ~= 2 ifTrue:
		[self numArgsError: 2].
	newContext := self asContextWithSender: thisContext sender.
	ncv := self numCopiedValues.
	newContext stackp: ncv + 2.
	newContext at: 1 put: firstArg.
	newContext at: 2 put: secondArg.
	1 to: ncv do:
		[:i| newContext at: i + 2 put: (self at: i)].
	thisContext privSender: newContext! !

!BlockClosure methodsFor: 'evaluating' stamp: 'eem 9/3/2008 14:11'!
value: firstArg value: secondArg value: thirdArg
	"Activate the receiver, creating a closure activation (MethodContext)
	 whose closure is the receiver and whose caller is the sender of this message.
	 Supply the arguments and copied values to the activation as its arguments and copied temps.
	 Primitive. Optional (but you're going to want this for performance)."
	| newContext ncv |
	<primitive: 204>
	numArgs ~= 3 ifTrue:
		[self numArgsError: 3].
	newContext := self asContextWithSender: thisContext sender.
	ncv := self numCopiedValues.
	newContext stackp: ncv + 3.
	newContext at: 1 put: firstArg.
	newContext at: 2 put: secondArg.
	newContext at: 3 put: thirdArg.
	1 to: ncv do:
		[:i| newContext at: i + 3 put: (self at: i)].
	thisContext privSender: newContext! !

!BlockClosure methodsFor: 'evaluating' stamp: 'eem 9/3/2008 14:11'!
value: firstArg value: secondArg value: thirdArg value: fourthArg
	"Activate the receiver, creating a closure activation (MethodContext)
	 whose closure is the receiver and whose caller is the sender of this message.
	 Supply the arguments and copied values to the activation as its arguments and copied temps.
	 Primitive. Optional (but you're going to want this for performance)."
	| newContext ncv |
	<primitive: 205>
	numArgs ~= 4 ifTrue:
		[self numArgsError: 4].
	newContext := self asContextWithSender: thisContext sender.
	ncv := self numCopiedValues.
	newContext stackp: ncv + 4.
	newContext at: 1 put: firstArg.
	newContext at: 2 put: secondArg.
	newContext at: 3 put: thirdArg.
	newContext at: 4 put: fourthArg.
	1 to: ncv do:
		[:i| newContext at: i + 4 put: (self at: i)].
	thisContext privSender: newContext! !

!BlockClosure methodsFor: 'evaluating' stamp: 'ar 7/20/2009 00:12'!
valueAt: blockPriority 
	"Evaluate the receiver (block), with another priority as the actual one 
	and restore it afterwards. The caller should be careful with using 
	higher priorities."
	| activeProcess result outsidePriority |
	activeProcess := Processor activeProcess.
	outsidePriority := activeProcess priority.
	activeProcess priority: blockPriority.
	result := self ensure: [activeProcess priority: outsidePriority].
	"Yield after restoring lower priority to give the preempted processes a  
	chance to run."
	blockPriority > outsidePriority
		ifTrue: [Processor yield].
	^ result! !

!BlockClosure methodsFor: 'evaluating' stamp: 'eem 8/22/2008 14:21'!
valueNoContextSwitch
	"An exact copy of BlockClosure>>value except that this version will not preempt
	 the current process on block activation if a higher-priority process is runnable.
	 Primitive. Essential."
	<primitive: 221>
	numArgs ~= 0 ifTrue:
		[self numArgsError: 0].
	self primitiveFailed! !

!BlockClosure methodsFor: 'evaluating' stamp: 'eem 8/22/2008 14:21'!
valueNoContextSwitch: anArg
	"An exact copy of BlockClosure>>value: except that this version will not preempt
	 the current process on block activation if a higher-priority process is runnable.
	 Primitive. Essential."
	<primitive: 222>
	numArgs ~= 1 ifTrue:
		[self numArgsError: 1].
	self primitiveFailed! !

!BlockClosure methodsFor: 'evaluating' stamp: 'ar 7/20/2009 00:14'!
valueSupplyingAnswer: anObject

	^ (anObject isCollection and: [anObject isString not])
		ifTrue: [self valueSupplyingAnswers: {anObject}]
		ifFalse: [self valueSupplyingAnswers: {{'*'. anObject}}]! !

!BlockClosure methodsFor: 'evaluating' stamp: 'ar 7/20/2009 00:14'!
valueSupplyingAnswers: aListOfPairs
	"evaluate the block using a list of questions / answers that might be called upon to
	automatically respond to Object>>confirm: or FillInTheBlank requests"

	^ [self value] 
		on: ProvideAnswerNotification
		do: 
			[:notify | | answer caption |
			
			caption := notify messageText withSeparatorsCompacted. "to remove new lines"
			answer := aListOfPairs
				detect: 
					[:each | caption = each first or:
						[caption includesSubstring: each first caseSensitive: false] or:
						[each first match: caption]]
					ifNone: [nil].
			answer
				ifNotNil: [notify resume: answer second]
				ifNil: 
					[ | outerAnswer |
					outerAnswer := ProvideAnswerNotification signal: notify messageText.
					outerAnswer 
						ifNil: [notify resume] 
						ifNotNil: [notify resume: outerAnswer]]]! !

!BlockClosure methodsFor: 'evaluating' stamp: 'ar 7/20/2009 00:13'!
valueSuppressingAllMessages

	^ self valueSuppressingMessages: #('*')! !

!BlockClosure methodsFor: 'evaluating' stamp: 'ar 7/20/2009 00:14'!
valueSuppressingMessages: aListOfStrings

	^ self
		valueSuppressingMessages: aListOfStrings
		supplyingAnswers: #()! !

!BlockClosure methodsFor: 'evaluating' stamp: 'ar 7/20/2009 00:14'!
valueSuppressingMessages: aListOfStrings supplyingAnswers: aListOfPairs

	^ self valueSupplyingAnswers: aListOfPairs, (aListOfStrings collect: [:each | {each. true}])! !

!BlockClosure methodsFor: 'evaluating' stamp: 'eem 9/3/2008 14:08'!
valueWithArguments: anArray
	"Activate the receiver, creating a closure activation (MethodContext)
	 whose closure is the receiver and whose caller is the sender of this message.
	 Supply the arguments in an anArray and copied values to the activation as its arguments and copied temps.
	 Primitive. Optional (but you're going to want this for performance)."
	| newContext ncv |
	<primitive: 206>
	numArgs ~= anArray size ifTrue:
		[self numArgsError: anArray size].
	newContext := self asContextWithSender: thisContext sender.
	ncv := self numCopiedValues.
	newContext stackp: ncv + numArgs.
	1 to: numArgs do:
		[:i| newContext at: i put: (anArray at: i)].
	1 to: ncv do:
		[:i| newContext at: i + numArgs put: (self at: i)].
	thisContext privSender: newContext! !

!BlockClosure methodsFor: 'evaluating' stamp: 'eem 5/28/2008 15:03'!
valueWithPossibleArgs: anArray 

	^numArgs = 0
		ifTrue: [self value]
		ifFalse:
			[self valueWithArguments:
				(numArgs = anArray size
					ifTrue: [anArray]
					ifFalse:
						[numArgs > anArray size
							ifTrue: [anArray, (Array new: numArgs - anArray size)]
							ifFalse: [anArray copyFrom: 1 to: numArgs]])]! !

!BlockClosure methodsFor: 'evaluating' stamp: 'eem 5/25/2008 14:47'!
valueWithPossibleArgument: anArg 
	"Evaluate the block represented by the receiver. 
	 If the block requires one argument, use anArg, if it requires more than one,
	 fill up the rest with nils."

	| a |
	numArgs = 0 ifTrue: [^self value].
	numArgs = 1 ifTrue: [^self value: anArg].
	a := Array new: numArgs.
	a at: 1 put: anArg.
	^self valueWithArguments: a! !

!BlockClosure methodsFor: 'evaluating' stamp: 'ar 8/17/2007 13:15'!
valueWithin: aDuration onTimeout: timeoutBlock
	"Evaluate the receiver.
	If the evaluation does not complete in less than aDuration evaluate the timeoutBlock instead"

	| theProcess delay watchdog |

	aDuration <= Duration zero ifTrue: [^ timeoutBlock value ].

	"the block will be executed in the current process"
	theProcess := Processor activeProcess.
	delay := aDuration asDelay.

	"make a watchdog process"
	watchdog := [
		delay wait. 	"wait for timeout or completion"
		theProcess ifNotNil:[ theProcess signalException: TimedOut ] 
	] newProcess.

	"Watchdog needs to run at high priority to do its job (but not at timing priority)"
	watchdog priority: Processor timingPriority-1.

	"catch the timeout signal"
	^ [	watchdog resume.				"start up the watchdog"
		self ensure:[						"evaluate the receiver"
			theProcess := nil.				"it has completed, so ..."
			delay delaySemaphore signal.	"arrange for the watchdog to exit"
		]] on: TimedOut do: [ :e | timeoutBlock value ].
! !

!BlockClosure methodsFor: 'exceptions' stamp: 'sma 5/11/2000 19:38'!
assert
	self assert: self! !

!BlockClosure methodsFor: 'exceptions' stamp: 'ar 12/4/2009 18:30'!
ensure: aBlock
	"Evaluate a termination block after evaluating the receiver, regardless of
	 whether the receiver's evaluation completes.  N.B.  This method is *not*
	 implemented as a primitive.  Primitive 198 always fails.  The VM uses prim
	 198 in a context's method as the mark for an ensure:/ifCurtailed: activation."

	| complete returnValue |
	<primitive: 198>
	returnValue := self valueNoContextSwitch.
	complete ifNil:[
		complete := true.
		aBlock value.
	].
	^ returnValue! !

!BlockClosure methodsFor: 'exceptions' stamp: 'ar 12/4/2009 18:41'!
ifCurtailed: aBlock
	"Evaluate the receiver with an abnormal termination action.
	 Evaluate aBlock only if execution is unwound during execution
	 of the receiver.  If execution of the receiver finishes normally do
	 not evaluate aBlock.  N.B.  This method is *not* implemented as a
	 primitive.  Primitive 198 always fails.  The VM uses prim 198 in a
	 context's method as the mark for an ensure:/ifCurtailed: activation."
	| complete result |
	<primitive: 198>
	result := self valueNoContextSwitch.
	complete := true.
	^result! !

!BlockClosure methodsFor: 'exceptions' stamp: 'ajh 2/1/2003 00:30'!
on: exception do: handlerAction
	"Evaluate the receiver in the scope of an exception handler."

	| handlerActive |
	<primitive: 199>  "just a marker, fail and execute the following"
	handlerActive := true.
	^ self value! !

!BlockClosure methodsFor: 'exceptions' stamp: 'ajh 10/9/2001 16:51'!
onDNU: selector do: handleBlock
	"Catch MessageNotUnderstood exceptions but only those of the given selector (DNU stands for doesNotUnderstand:)"

	^ self on: MessageNotUnderstood do: [:exception |
		exception message selector = selector
			ifTrue: [handleBlock valueWithPossibleArgs: {exception}]
			ifFalse: [exception pass]
	  ]! !

!BlockClosure methodsFor: 'exceptions' stamp: 'ajh 7/26/2002 11:49'!
valueUninterruptably
	"Prevent remote returns from escaping the sender.  Even attempts to terminate (unwind) this process will be halted and the process will resume here.  A terminate message is needed for every one of these in the sender chain to get the entire process unwound."

	^ self ifCurtailed: [^ self]! !

!BlockClosure methodsFor: 'printing' stamp: 'eem 7/28/2008 14:06'!
decompile
	^Decompiler new decompileBlock: self! !

!BlockClosure methodsFor: 'printing' stamp: 'eem 7/28/2008 14:09'!
fullPrintOn: aStream
	aStream print: self; cr.
	(self decompile ifNil: ['--source missing--']) printOn: aStream indent: 0! !

!BlockClosure methodsFor: 'printing' stamp: 'eem 5/24/2008 11:23'!
printOn: aStream
	aStream nextPutAll: '[closure] in '.
	outerContext printOn: aStream! !

!BlockClosure methodsFor: 'scheduling' stamp: 'eem 5/28/2008 16:16'!
asContext
	"Create a MethodContext that is ready to execute self.  Assumes self takes no args (if it does the args will be nil)"

	^self asContextWithSender: nil! !

!BlockClosure methodsFor: 'scheduling' stamp: 'ajh 7/15/2001 16:03'!
fork
	"Create and schedule a Process running the code in the receiver."

	^ self newProcess resume! !

!BlockClosure methodsFor: 'scheduling' stamp: 'ajh 10/16/2002 11:14'!
forkAndWait
	"Suspend current process and execute self in new process, when it completes resume current process"

	| semaphore |
	semaphore := Semaphore new.
	[self ensure: [semaphore signal]] fork.
	semaphore wait.
! !

!BlockClosure methodsFor: 'scheduling' stamp: 'ajh 9/29/2001 21:00'!
forkAt: priority 
	"Create and schedule a Process running the code in the receiver at the given priority. Answer the newly created process."

	^ self newProcess
		priority: priority;
		resume! !

!BlockClosure methodsFor: 'scheduling' stamp: 'svp 6/23/2003 10:59'!
forkAt: priority named: name

	"Create and schedule a Process running the code in the receiver at the

	given priority and having the given name. Answer the newly created 

	process."



	| forkedProcess |

	forkedProcess := self newProcess.

	forkedProcess priority: priority.

	forkedProcess name: name.

	^ forkedProcess resume! !

!BlockClosure methodsFor: 'scheduling' stamp: 'svp 6/23/2003 10:59'!
forkNamed: aString

	"Create and schedule a Process running the code in the receiver and

	having the given name."



	^ self newProcess name: aString; resume! !

!BlockClosure methodsFor: 'scheduling' stamp: 'ajh 2/10/2003 14:25'!
newProcess
	"Answer a Process running the code in the receiver. The process is not 
	scheduled."
	<primitive: 19> "Simulation guard"
	^Process
		forContext: 
			[self value.
			Processor terminateActive] asContext
		priority: Processor activePriority! !

!BlockClosure methodsFor: 'private' stamp: 'eem 6/11/2008 11:38'!
asContextWithSender: aContext
	"Inner private support method for evaluation.  Do not use unless you know what you're doing."

	^(MethodContext newForMethod: outerContext method)
		setSender: aContext
		receiver: outerContext receiver
		method: outerContext method
		closure: self
		startpc: startpc! !

!BlockClosure methodsFor: 'private' stamp: 'eem 5/28/2008 14:50'!
copyForSaving
	"Answer a copy of the receiver suitable for serialization.
	 Notionally, if the receiver's outerContext has been returned from then nothing
	 needs to be done and we can use the receiver. But there's a race condition
	 determining if the receiver has been returned from (it could be executing in a
	 different process). So answer a copy anyway."
	^self shallowCopy postCopy! !

!BlockClosure methodsFor: 'private' stamp: 'eem 12/14/2008 16:47'!
fixTemps
	"Fix the values of the temporary variables used in the block that
	 are  ordinarily shared with the method in which the block is defined.
	 This is a no-op for closures, provided for backward-compatibility with
	 old BlockContexts that needed the fixTemps hack to persist."! !

!BlockClosure methodsFor: 'private' stamp: 'eem 5/28/2008 14:56'!
reentrant
	"Answer a version of the recever that can be reentered.
	 Closures are reentrant (unlike BlockContect) so simply answer self."
	^self! !

!BlockClosure methodsFor: 'private' stamp: 'ar 3/2/2001 01:16'!
valueUnpreemptively
	"Evaluate the receiver (block), without the possibility of preemption by higher priority processes. Use this facility VERY sparingly!!"
	"Think about using Block>>valueUninterruptably first, and think about using Semaphore>>critical: before that, and think about redesigning your application even before that!! 
	After you've done all that thinking, go right ahead and use it..."
	| activeProcess oldPriority result |
	activeProcess := Processor activeProcess.
	oldPriority := activeProcess priority.
	activeProcess priority: Processor highestPriority.
	result := self ensure: [activeProcess priority: oldPriority].
	"Yield after restoring priority to give the preempted processes a chance to run"
	Processor yield.
	^result! !

!BlockClosure methodsFor: 'testing' stamp: 'eem 5/29/2008 12:20'!
hasMethodReturn
	"Answer whether the receiver has a method-return ('^') in its code."
	| myMethod scanner preceedingBytecodeMessage end |
	"Determine end of block from the instruction preceding it.
	 Find the instruction by using an MNU handler to capture
	 the instruction message sent by the scanner."
	myMethod := outerContext method.
	scanner := InstructionStream new method: myMethod pc: myMethod initialPC.
	[scanner pc < startpc] whileTrue:
		[[scanner interpretNextInstructionFor: nil]
			on: MessageNotUnderstood
			do: [:ex| preceedingBytecodeMessage := ex message]].
	end := preceedingBytecodeMessage arguments last + startpc - 1.
	scanner method: myMethod pc: startpc.
	scanner scanFor: [:byte | (byte between: 120 and: 124) or: [scanner pc > end]].
	^scanner pc <= end! !

!BlockClosure methodsFor: 'testing' stamp: 'eem 5/23/2008 13:48'!
isClosure
	^true! !

!BlockClosure methodsFor: 'testing' stamp: 'eem 11/26/2008 20:27'!
isDead
	"Has self finished"
	^false! !

!BlockClosure methodsFor: 'error handing' stamp: 'eem 11/26/2008 20:03'!
numArgsError: numArgsForInvocation

	| printNArgs |
	printNArgs := [:n| n printString, ' argument', (n = 1 ifTrue: [''] ifFalse:['s'])]. 
	self error: 
			'This block accepts ', (printNArgs value: numArgs), 
			', but was called with ', (printNArgs value: numArgsForInvocation), '.'! !

!BlockClosure methodsFor: 'initialize-release' stamp: 'eem 9/3/2008 14:08'!
outerContext: aContext startpc: aStartpc numArgs: argCount copiedValues: anArrayOrNil
	outerContext := aContext.
	startpc := aStartpc.
	numArgs := argCount.
	1 to: self numCopiedValues do:
		[:i|
		self at: i put: (anArrayOrNil at: i)]! !

!BlockClosure methodsFor: '*services-base' stamp: 'ar 8/14/2009 20:01'!
valueWithRequestor: aRequestor 
	"To do later: make the fillInTheBlank display more informative captions.
	Include the description of the service, and maybe record steps"

	^ self numArgs isZero 
		ifTrue: [self value]
		ifFalse: [self value: aRequestor]! !

!BlockClosure methodsFor: 'events-support' stamp: 'ar 8/26/2009 21:36'!
asMinimalRepresentation
	"For use in the when:evaluate: protocol, i.e.,
		foo when: #bar evaluate:[self handleBar].
	Return the receiver."
	^self! !

!BlockClosure methodsFor: 'events-support' stamp: 'ar 8/26/2009 20:58'!
isValid
	"For use in the when:evaluate: protocol, i.e.,
		foo when: #bar evaluate:[self handleBar].
	Return true."
	^true! !

!BlockClosure methodsFor: '*Tools' stamp: 'ul 10/9/2009 00:19'!
timeProfile

	^TimeProfileBrowser onBlock: self! !


!BlockClosure class methodsFor: 'instance creation' stamp: 'eem 9/3/2008 14:02'!
outerContext: aContext startpc: aStartpc numArgs: argCount copiedValues: anArrayOrNil
	^(self new: anArrayOrNil basicSize)
		outerContext: aContext
		startpc: aStartpc
		numArgs: argCount
		copiedValues: anArrayOrNil! !


!BlockStartLocator methodsFor: 'initialize-release' stamp: 'eem 5/31/2008 13:43'!
initialize
	nextJumpIsAroundBlock := false! !

!BlockStartLocator methodsFor: 'instruction decoding' stamp: 'eem 5/31/2008 13:48'!
jump: offset
	"If this jump is around a block answer the size of that block."

	nextJumpIsAroundBlock ifTrue:
		[nextJumpIsAroundBlock := false.
		 ^offset]! !

!BlockStartLocator methodsFor: 'instruction decoding' stamp: 'eem 5/31/2008 13:54'!
pushClosureCopyNumCopiedValues: numCopied numArgs: numArgs blockSize: blockSize
	"Answer the size of the block"
	^blockSize! !

!BlockStartLocator methodsFor: 'instruction decoding' stamp: 'eem 5/31/2008 14:16'!
send: selector super: supered numArgs: numberArguments
	nextJumpIsAroundBlock := #closureCopy:copiedValues: == selector
	"Don't use
		nextJumpIsAroundBlock := #(blockCopy: closureCopy:copiedValues:) includes: selector
	 since BlueBook BlockContexts do not have their own temps."! !


!CompiledMethod methodsFor: 'debugger support' stamp: 'eem 6/5/2008 10:32'!
abstractPCForConcretePC: concretePC
	"Answer the abstractPC matching concretePC."

	| abstractPC scanner client |
	self flag: 'belongs in DebuggerMethodMap?'.
	abstractPC := 1.
	scanner := InstructionStream on: self.
	client := InstructionClient new.
	[(scanner atEnd
	  or: [scanner pc >= concretePC]) ifTrue:
		[^abstractPC].
	 abstractPC := abstractPC + 1.
	 scanner interpretNextInstructionFor: client.
	 true] whileTrue! !

!CompiledMethod methodsFor: 'debugger support' stamp: 'eem 6/3/2008 16:15'!
blockExtentsInto: aDictionary from: initialPC to: endPC scanner: scanner numberer: numbererBlock
	"Support routine for startpcsToBlockExtents"
	| extentStart blockSizeOrLocator |
	self flag: 'belongs in DebuggerMethodMap'.
	extentStart := numbererBlock value.
	[scanner pc <= endPC] whileTrue:
		[blockSizeOrLocator := scanner interpretNextInstructionFor: BlockStartLocator new.
		 blockSizeOrLocator isInteger ifTrue:
			[self
				blockExtentsInto: aDictionary
				from: scanner pc
				to: scanner pc + blockSizeOrLocator - 1
				scanner: scanner
				numberer: numbererBlock]].
	aDictionary at: initialPC put: (extentStart to: numbererBlock value).
	^aDictionary! !

!CompiledMethod methodsFor: 'debugger support' stamp: 'eem 6/30/2009 12:37'!
blockExtentsToTempsMap
	"If the receiver has been copied with temp names answer a
	 map from blockExtent to temps map in the same format as
	 BytecodeEncoder>>blockExtentsToTempNamesMap.  if the
	 receiver has not been copied with temps answer nil."
	^self holdsTempNames ifTrue:
		[self mapFromBlockKeys: ((self startpcsToBlockExtents associations asSortedCollection:
										[:a1 :a2| a1 key < a2 key]) collect:
									[:assoc| assoc value])
			toSchematicTemps: self tempNamesString]! !

!CompiledMethod methodsFor: 'debugger support' stamp: 'eem 6/5/2008 09:10'!
debuggerMap
	^DebuggerMethodMap forMethod: self! !

!CompiledMethod methodsFor: 'debugger support' stamp: 'eem 6/29/2009 09:48'!
mapFromBlockKeys: keys toSchematicTemps: schematicTempNamesString
	"Decode a schematicTempNamesString that encodes the layout of temp names
	 in a method and any closures/blocks within it, matching keys in keys to
	 vectors of temp names."
	| map tempNames |
	map := Dictionary new.
	tempNames := schematicTempNamesString readStream.
	keys do:
		[:key| | tempSequence tempIndex |
		tempSequence := OrderedCollection new.
		tempIndex := 0.
		[(tempNames skipSeparators; peek) ifNil: [true] ifNotNil: [:ch| '[]' includes: ch]] whileFalse:
			[tempNames peek = $(
				ifTrue: [tempSequence addAllLast: ((self tempsSubSequenceFrom: (tempNames next; yourself)) withIndexCollect:
														[:temp :index|
														{ temp. { tempIndex + 1. index } }]).
						tempNames peek ~= $) ifTrue: [self error: 'parse error'].
						tempIndex := tempIndex + 1.
						tempNames next]
				ifFalse: [tempSequence addAllLast: ((self tempsSubSequenceFrom: tempNames) withIndexCollect:
														[:temp :index|
														{ temp. tempIndex := tempIndex + 1 }])]].
		map at: key put: tempSequence asArray.
		[tempNames peek = $]] whileTrue: [tempNames next].
		tempNames peek = $[ ifTrue:
			[tempNames next]].
	^map! !

!CompiledMethod methodsFor: 'debugger support' stamp: 'eem 6/14/2008 18:58'!
pcPreviousTo: pc
	| scanner client prevPc |
	self flag: 'belongs in DebuggerMethodMap?'.
	pc > self endPC ifTrue: [^self endPC].
	scanner := InstructionStream on: self.
	client := InstructionClient new.
	[scanner pc < pc] whileTrue:
		[prevPc := scanner pc.
		 scanner interpretNextInstructionFor: client].
	^prevPc! !

!CompiledMethod methodsFor: 'debugger support' stamp: 'eem 6/29/2009 09:50'!
startpcsToBlockExtents
	"Answer a Dictionary of startpc to Interval of blockExtent, using the
	 identical numbering scheme described in and orchestrated by
	 BlockNode>>analyseArguments:temporaries:rootNode:.  This is
	 used in part to find the temp names for any block in a method, as
	 needed by the debugger.  The other half is to recompile the method,
	 obtaining the temp names for each block extent.  By indirecting through
	 the blockExtent instead of using the startpc directly we decouple the
	 debugger's access to temp names from the exact bytecode; insulating
	 debugging from minor changes in the compiler (e.g. changes in literal
	 pooling, adding prefix bytecodes, adding inst vars to CompiledMethod
	 in literals towards the end of the literal frame, etc).  If the recompilation
	 doesn't produce exactly the same bytecode at exactly the same offset
	 no matter; the blockExtents will be the same."
	| index |
	self flag: 'belongs in DebuggerMethodMap'.
	index := 0.
	^self
		blockExtentsInto: Dictionary new
		from: self initialPC
		to: self endPC
		scanner: (InstructionStream on: self)
		numberer: [| value | value := index. index := index + 2. value]! !

!CompiledMethod methodsFor: 'debugger support' stamp: 'eem 7/1/2009 10:09'!
tempsSubSequenceFrom: tempNamesStream
	^Array streamContents:
		[:tsss|
		[tempNamesStream skipSeparators.
		 tempNamesStream atEnd
		 or: ['[]()' includes: tempNamesStream peek]] whileFalse:
			[tsss nextPut: (String streamContents:
							[:s|
							[s nextPut: tempNamesStream next.
							 tempNamesStream peek
								ifNil: [true]
								ifNotNil: [:peek| ' []()' includes: peek]] whileFalse])]]

	"thisContext method tempsSubSequenceFrom: 'les temps perdu(sont n''est pas la)' readStream"
	"thisContext method tempsSubSequenceFrom: ('les temps perdu(sont n''est pas la)' readStream skipTo: $(; yourself)"! !


!MessageCatcher methodsFor: 'as yet unclassified' stamp: 'ajh 7/7/2004 18:22'!
doesNotUnderstand: aMessage

	accumulator ifNotNil: [accumulator add: aMessage].
	^ aMessage! !

!MessageCatcher methodsFor: 'as yet unclassified' stamp: 'ajh 7/7/2004 18:22'!
privAccumulator

	^ accumulator! !

!MessageCatcher methodsFor: 'as yet unclassified' stamp: 'ajh 7/7/2004 18:22'!
privAccumulator: collection

	accumulator := collection! !


!MethodProperties methodsFor: 'accessing' stamp: 'ar 2/28/2006 18:30'!
pragmas
	^pragmas ifNil:[#()]! !

!MethodProperties methodsFor: 'accessing' stamp: 'ar 2/28/2006 18:31'!
pragmas: anArray
	pragmas := anArray! !

!MethodProperties methodsFor: 'accessing' stamp: 'md 2/16/2006 17:50'!
selector
	^selector! !

!MethodProperties methodsFor: 'accessing' stamp: 'md 2/16/2006 17:50'!
selector: aSymbol
	selector := aSymbol! !

!MethodProperties methodsFor: 'initialization' stamp: 'lr 2/6/2006 19:12'!
initialize
	super initialize.
	pragmas := #().! !

!MethodProperties methodsFor: 'properties' stamp: 'lr 2/6/2006 19:04'!
at: aKey
	"Answer the property value associated with aKey."
	
	^ self at: aKey ifAbsent: [ self error: 'Property not found' ].! !

!MethodProperties methodsFor: 'properties' stamp: 'lr 2/6/2006 19:07'!
at: aKey ifAbsent: aBlock
	"Answer the property value associated with aKey or, if aKey isn't found, answer the result of evaluating aBlock."
	
	properties isNil ifTrue: [ ^ aBlock value ].
	^ properties at: aKey ifAbsent: aBlock.! !

!MethodProperties methodsFor: 'properties' stamp: 'lr 2/6/2006 20:47'!
at: aKey ifAbsentPut: aBlock
	"Answer the property associated with aKey or, if aKey isn't found store the result of evaluating aBlock as new value."
	
	^ self at: aKey ifAbsent: [ self at: aKey put: aBlock value ].! !

!MethodProperties methodsFor: 'properties' stamp: 'lr 2/6/2006 19:06'!
at: aKey put: anObject
	"Set the property at aKey to be anObject. If aKey is not found, create a new entry for aKey and set is value to anObject. Answer anObject."

	properties ifNil: [ properties :=  IdentityDictionary new ].
	^ properties at: aKey put: anObject.! !

!MethodProperties methodsFor: 'properties' stamp: 'lr 2/6/2006 19:11'!
includesKey: aKey
	"Test if the property aKey is present."
	
	^ properties notNil and: [ properties includesKey: aKey ].! !

!MethodProperties methodsFor: 'properties' stamp: 'ar 3/8/2006 00:24'!
keysAndValuesDo: aBlock
	"Enumerate the receiver with all the keys and values."
	^properties ifNotNil:[properties keysAndValuesDo: aBlock]! !

!MethodProperties methodsFor: 'properties' stamp: 'eem 9/5/2009 15:01'!
propertyKeysAndValuesDo: aBlock
	"Enumerate the receiver with all the keys and values."
	^properties ifNotNil:[properties keysAndValuesDo: aBlock]! !

!MethodProperties methodsFor: 'properties' stamp: 'eem 12/1/2008 17:49'!
propertyValueAt: aKey ifAbsent: aBlock
	"Answer the property value associated with aKey or, if aKey isn't found, answer the result of evaluating aBlock."
	^self at: aKey ifAbsent: aBlock! !

!MethodProperties methodsFor: 'properties' stamp: 'lr 2/6/2006 20:48'!
removeKey: aKey
	"Remove the property with aKey. Answer the property or raise an error if aKey isn't found."
	
	^ self removeKey: aKey ifAbsent: [ self error: 'Property not found' ].! !

!MethodProperties methodsFor: 'properties' stamp: 'lr 2/6/2006 19:07'!
removeKey: aKey ifAbsent: aBlock
	"Remove the property with aKey. Answer the value or, if aKey isn't found, answer the result of evaluating aBlock."
	
	| answer |
	properties isNil ifTrue: [ ^ aBlock value ].
	answer := properties removeKey: aKey ifAbsent: aBlock.
	properties isEmpty ifTrue: [ properties := nil ].
	^ answer.! !

!MethodProperties methodsFor: 'private' stamp: 'ar 2/28/2006 18:30'!
addPragma: aPragma
	pragmas := self pragmas copyWith: aPragma.! !

!MethodProperties methodsFor: 'testing' stamp: 'nice 11/8/2009 15:30'!
analogousCodeTo: aMethodProperties
	pragmas
		ifNil: [aMethodProperties pragmas notEmpty ifTrue: [^false]]
		ifNotNil:
			[pragmas size ~= aMethodProperties pragmas size ifTrue:
				[^false].
			 pragmas with: aMethodProperties pragmas do:
				[:mine :others|
				(mine analogousCodeTo: others) ifFalse: [^false]]].
	^(self hasAtLeastTheSamePropertiesAs: aMethodProperties)
	  and: [aMethodProperties hasAtLeastTheSamePropertiesAs: self]! !

!MethodProperties methodsFor: 'testing' stamp: 'nice 11/8/2009 12:22'!
hasAtLeastTheSamePropertiesAs: aMethodProperties
	"Answer if the recever has at least the same properties as the argument.
	 N.B. The receiver may have additional properties and still answer true."
	aMethodProperties keysAndValuesDo:
		[:k :v|
		(v isKindOf: Pragma)
			"ifTrue: [Pragmas have already been checked]"
			ifFalse: [
				properties ifNil: [^false].
				^(properties at: k ifAbsent: [^false]) = v]].
	^true! !

!MethodProperties methodsFor: 'testing' stamp: 'eem 12/3/2008 11:00'!
hasLiteralSuchThat: aBlock
	"Answer true if litBlock returns true for any literal in this array, even if embedded in further array structure.
	 This method is only intended for private use by CompiledMethod hasLiteralSuchThat:"
	properties ifNil:[^false].
	properties keysAndValuesDo: [:key :value |
		((aBlock value: key)
		 or: [(aBlock value: value)
		 or: [value isArray
			and: [value hasLiteralSuchThat: aBlock]]]) ifTrue: [^true]].
	^false! !

!MethodProperties methodsFor: 'testing' stamp: 'ar 3/7/2006 16:35'!
hasLiteralThorough: literal
	"Answer true if any literal in this method is literal,
	even if embedded in array structure."
	properties ifNil:[^false].
	properties keysAndValuesDo: [:key :value |
		key == literal ifTrue: [^true].
		value == literal ifTrue:[^true].
		(value class == Array and: [value hasLiteral: literal]) ifTrue: [^ true]].
	^false! !

!MethodProperties methodsFor: 'testing' stamp: 'eem 11/29/2008 13:48'!
isEmpty
	^(properties isNil or: [properties isEmpty])
	   and: [pragmas isNil or: [pragmas isEmpty]]! !

!MethodProperties methodsFor: 'testing' stamp: 'md 2/19/2006 11:24'!
isMethodProperties
	^true! !

!MethodProperties methodsFor: 'testing' stamp: 'eem 12/1/2008 16:49'!
notEmpty
	^(properties notNil and: [properties notEmpty])
	   or: [pragmas notNil and: [pragmas notEmpty]]! !

!MethodProperties methodsFor: 'testing' stamp: 'MagmaCollectionTester 8/26/2009 23:08'!
propertiesIsNil
	^ properties isNil! !

!MethodProperties methodsFor: 'copying' stamp: 'md 3/1/2006 15:30'!
postCopy
	properties := properties copy.
	pragmas := pragmas copy.
! !

!MethodProperties methodsFor: 'forward compatibility' stamp: 'eem 9/5/2009 15:09'!
method: ignored
	"For forward compatibility wth AdditionalMethodState, for decompilation"! !

!MethodProperties methodsFor: 'forward compatibility' stamp: 'eem 9/5/2009 14:31'!
setMethod: ignored
	"For forward compatibility wth AdditionalMethodState"! !


!MethodProperties class methodsFor: 'class initialization' stamp: 'lr 2/6/2006 22:06'!
initialize
	self becomeCompact.! !


!Pragma methodsFor: 'accessing-method' stamp: 'lr 1/20/2006 02:04'!
method
	"Answer the compiled-method containing the pragma."
	
	^ method! !

!Pragma methodsFor: 'accessing-method' stamp: 'lr 1/20/2006 02:08'!
methodClass
	"Answer the class of the method containing the pragma."
	
	^ method methodClass! !

!Pragma methodsFor: 'accessing-method' stamp: 'eem 12/1/2008 10:43'!
selector
	"Answer the selector of the method containing the pragma.
	 Do not confuse this with the selector of the pragma's message pattern."
	
	^method selector! !

!Pragma methodsFor: 'accessing-pragma' stamp: 'lr 1/20/2006 02:10'!
argumentAt: anInteger
	"Answer one of the arguments of the pragma."
	
	^ self arguments at: anInteger.! !

!Pragma methodsFor: 'accessing-pragma' stamp: 'lr 1/19/2006 20:54'!
arguments
	"Answer the arguments of the receiving pragma. For a pragma defined as <key1: val1 key2: val2> this will answer #(val1 val2)."
	
	^ arguments! !

!Pragma methodsFor: 'accessing-pragma' stamp: 'eem 12/1/2008 10:42'!
key
	"Answer the keyword of the pragma (the selector of its message pattern).
	 This accessor provides polymorphism with Associations used for properties."
	^keyword! !

!Pragma methodsFor: 'accessing-pragma' stamp: 'eem 12/1/2008 10:42'!
keyword
	"Answer the keyword of the pragma (the selector of its message pattern).
	 For a pragma defined as <key1: val1 key2: val2> this will answer #key1:key2:."
	
	^ keyword! !

!Pragma methodsFor: 'accessing-pragma' stamp: 'lr 1/19/2006 20:55'!
message
	"Answer the message of the receiving pragma."
	
	^ Message selector: self keyword arguments: self arguments. ! !

!Pragma methodsFor: 'accessing-pragma' stamp: 'lr 1/20/2006 02:10'!
numArgs
	"Answer the number of arguments in the pragma."

	^ self arguments size.! !

!Pragma methodsFor: 'initialization' stamp: 'lr 1/20/2006 00:53'!
setArguments: anArray
	arguments := anArray! !

!Pragma methodsFor: 'initialization' stamp: 'lr 1/20/2006 00:53'!
setKeyword: aSymbol
	keyword := aSymbol! !

!Pragma methodsFor: 'initialization' stamp: 'lr 1/19/2006 23:39'!
setMethod: aCompiledMethod
	method := aCompiledMethod! !

!Pragma methodsFor: 'printing' stamp: 'lr 2/6/2006 19:56'!
printOn: aStream
	aStream nextPut: $<.
	self keyword precedence = 1
		ifTrue: [ aStream nextPutAll: self keyword ]
		ifFalse: [
			self keyword keywords with: self arguments do: [ :key :arg |
				aStream nextPutAll: key; space; print: arg; space ].
			aStream skip: -1 ].
	aStream nextPut: $>.! !

!Pragma methodsFor: 'testing' stamp: 'eem 11/29/2008 16:39'!
hasLiteral: aLiteral
	^keyword == aLiteral 
	   or: [arguments hasLiteral: aLiteral]! !

!Pragma methodsFor: 'testing' stamp: 'eem 11/29/2008 17:03'!
hasLiteralSuchThat: aBlock
	"Answer true if litBlock returns true for any literal in the receiver, even if embedded in further array structure.
	 This method is only intended for private use by CompiledMethod hasLiteralSuchThat:"
	^(aBlock value: keyword)
	   or: [arguments hasLiteralSuchThat: aBlock]! !

!Pragma methodsFor: 'comparing' stamp: 'eem 3/7/2009 11:54'!
analogousCodeTo: anObject 
	^self class == anObject class
	  and: [keyword == anObject keyword
	  and: [arguments = anObject arguments]]! !


!Pragma class methodsFor: 'finding' stamp: 'lr 1/20/2006 08:54'!
allNamed: aSymbol from: aSubClass to: aSuperClass
	"Answer a collection of all pragmas found in methods of all classes between aSubClass and aSuperClass (inclusive) whose keyword is aSymbol."
	
	^ Array streamContents: [ :stream |
		aSubClass withAllSuperclassesDo: [ :class |
			self withPragmasIn: class do:  [ :pragma |
				pragma keyword = aSymbol
					ifTrue: [ stream nextPut: pragma ] ].
			aSuperClass = class
				ifTrue: [ ^ stream contents ] ] ].! !

!Pragma class methodsFor: 'finding' stamp: 'lr 1/20/2006 18:16'!
allNamed: aSymbol from: aSubClass to: aSuperClass sortedByArgument: anInteger
	"Answer a collection of all pragmas found in methods of all classes between aSubClass and aSuperClass (inclusive) whose keyword is aSymbol, sorted according to argument anInteger."

	^ self allNamed: aSymbol from: aSubClass to: aSuperClass sortedUsing: [ :a :b | (a argumentAt: anInteger) < (b argumentAt: anInteger) ].! !

!Pragma class methodsFor: 'finding' stamp: 'lr 1/19/2006 20:12'!
allNamed: aSymbol from: aSubClass to: aSuperClass sortedUsing: aSortBlock
	"Answer a collection of all pragmas found in methods of all classes between aSubClass and aSuperClass (inclusive) whose keyword is aSymbol, sorted according to aSortBlock."
	
	^ (self allNamed: aSymbol from: aSubClass to: aSuperClass) sort: aSortBlock.! !

!Pragma class methodsFor: 'finding' stamp: 'lr 1/20/2006 08:55'!
allNamed: aSymbol in: aClass
	"Answer a collection of all pragmas found in methods of aClass whose keyword is aSymbol."
	
	^ Array streamContents: [ :stream |
		self withPragmasIn: aClass do: [ :pragma |
			pragma keyword = aSymbol
				ifTrue: [ stream nextPut: pragma ] ] ].! !

!Pragma class methodsFor: 'finding' stamp: 'lr 1/20/2006 18:16'!
allNamed: aSymbol in: aClass sortedByArgument: anInteger
	"Answer a collection of all pragmas found in methods of aClass whose keyword is aSymbol, sorted according to argument anInteger."

	^ self allNamed: aSymbol in: aClass sortedUsing: [ :a :b | (a argumentAt: anInteger) < (b argumentAt: anInteger) ].! !

!Pragma class methodsFor: 'finding' stamp: 'lr 1/19/2006 20:06'!
allNamed: aSymbol in: aClass sortedUsing: aSortBlock
	"Answer a collection of all pragmas found in methods of aClass whose keyword is aSymbol, sorted according to aSortBlock."
	
	^ (self allNamed: aSymbol in: aClass) sort: aSortBlock.! !

!Pragma class methodsFor: 'private' stamp: 'lr 1/20/2006 00:34'!
keyword: aSymbol arguments: anArray
	^ self new
		setKeyword: aSymbol;
		setArguments: anArray;
		yourself.! !

!Pragma class methodsFor: 'private' stamp: 'lr 1/20/2006 08:50'!
withPragmasIn: aClass do: aBlock
	aClass selectorsAndMethodsDo: [ :selector :method | method pragmas do: aBlock ].! !

!Pragma class methodsFor: 'instance creation' stamp: 'eem 11/29/2008 14:00'!
for: aMethod selector: aSelector arguments: anArray
	^self new
		setMethod: aMethod;
		setKeyword: aSelector;
		setArguments: anArray;
		yourself! !


!RelativeInstructionPrinter methodsFor: 'instruction decoding' stamp: 'eem 5/15/2008 11:29'!
jump: offset
	"Print the Unconditional Jump bytecode."

	labelling
		ifTrue:
			[labels at: scanner pc + offset + 1 put: true.
			 self print: 'jumpBy: ', offset printString,
				' to: ', (scanner pc + offset - method initialPC) printString]
		ifFalse:
			[self print: 'jumpTo: ', (labels at: scanner pc + offset + 1)]! !

!RelativeInstructionPrinter methodsFor: 'instruction decoding' stamp: 'eem 5/15/2008 11:29'!
jump: offset if: condition 
	"Print the Conditional Jump bytecode."

	labelling
		ifTrue:
			[labels at: scanner pc + offset + 1 put: true.
			 self print: 
				(condition ifTrue: ['jumpTrueBy: '] ifFalse: ['jumpFalseBy: ']), offset printString,
				' to: ', (labelling
							ifTrue: [(scanner pc + offset - method initialPC) printString]
							ifFalse: [labels at: scanner pc + offset])]
		ifFalse:
			[self print: 
				(condition ifTrue: ['jumpTrueTo: '] ifFalse: ['jumpFalseTo: ']), (labels at: scanner pc + offset + 1)]! !

!RelativeInstructionPrinter methodsFor: 'instruction decoding' stamp: 'eem 5/16/2008 17:10'!
send: selector super: supered numArgs: numArgs
	"Print the Send Message With Selector, selector, bytecode. The argument, 
	supered, indicates whether the receiver of the message is specified with 
	'super' in the source method. The arguments of the message are found in 
	the top numArguments locations on the stack and the receiver just 
	below them."

	self print: (supered
				ifTrue: ['superSend: ']
				ifFalse: ['send: '])
			, selector storeString
			, (numArgs = 1
				ifTrue: [' (1 arg)']
				ifFalse: [' (', numArgs printString, ' args)'])! !

!RelativeInstructionPrinter methodsFor: 'printing' stamp: 'eem 5/29/2008 13:49'!
print: instruction 
	"Append to the receiver a description of the bytecode, instruction." 

	stream tab: self indent.
	labelling
		ifTrue: [stream print: oldPC - method initialPC; space]
		ifFalse: [stream tab].
	stream tab: (innerIndents at: oldPC).
	self printCode ifTrue:
		[stream nextPut: $<.
		 oldPC to: scanner pc - 1 do: 
			[:i | | code |
			code := (method at: i) radix: 16.
			stream
				nextPut: (code size < 2 ifTrue: [$0] ifFalse: [code at: 1]);
				nextPut: code last;
				space].
		 stream skip: -1; nextPut: $>; space].
	stream nextPutAll: instruction.
	stream cr.
	labelling ifFalse:
		[(labels at: scanner pc + 1) ~~ false ifTrue:
			[stream nextPutAll: (labels at: scanner pc + 1); nextPut: $:; cr]].
	oldPC := scanner pc! !

!RelativeInstructionPrinter methodsFor: 'printing' stamp: 'eem 5/15/2008 10:56'!
printCode
	^printCode ~~ false! !

!RelativeInstructionPrinter methodsFor: 'printing' stamp: 'eem 5/21/2008 12:24'!
printInstructionsOn: aStream
	"Append to the stream, aStream, a description of each bytecode in the instruction stream."
	
	| label |
	labelling := true.
	labels := Array new: method size + 1 withAll: false.
	super printInstructionsOn: (String new: 1024) writeStream.
	label := 0.
	labels withIndexDo:
		[:bool :index|
		bool ifTrue: [labels at: index put: 'L', (label := label + 1) printString]].
	labelling := false.
	super printInstructionsOn: aStream! !

!RelativeInstructionPrinter methodsFor: 'printing' stamp: 'eem 5/15/2008 13:17'!
printInstructionsOn: aStream do: aBlock
	"Append to the stream, aStream, a description of each bytecode in the instruction stream.
	  Evaluate aBlock with the receiver, the scanner and the stream after each instruction."
	
	| label |
	labelling := true.
	labels := Array new: method size withAll: false.
	super printInstructionsOn: (String new: 1024) writeStream do: [:ig :no :re|].
	label := 0.
	labels withIndexDo:
		[:bool :index|
		bool ifTrue: [labels at: index put: 'L', (label := label + 1) printString]].
	labelling := false.
	super printInstructionsOn: aStream do: aBlock! !

!RelativeInstructionPrinter methodsFor: 'initialize-release' stamp: 'eem 5/15/2008 10:56'!
printCode: aBoolean
	printCode := aBoolean! !

MethodProperties initialize!
MessageCatcher removeSelector: #privEchoToTranscript!
MessageCatcher removeSelector: #privEchoToTranscript:!
!classDefinition: #MessageCatcher category: #'Kernel-Methods'!
ProtoObject subclass: #MessageCatcher
	instanceVariableNames: 'accumulator'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Kernel-Methods'!
!classDefinition: #InstructionPrinter category: #'Kernel-Methods'!
InstructionClient subclass: #InstructionPrinter
	instanceVariableNames: 'method scanner stream oldPC innerIndents indent printPC indentSpanOfFollowingJump'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Kernel-Methods'!
