[squeak-dev] The Trunk: Tools-mt.1086.mcz

commits at source.squeak.org commits at source.squeak.org
Wed Dec 15 14:54:35 UTC 2021


Marcel Taeumel uploaded a new version of Tools to project The Trunk:
http://source.squeak.org/trunk/Tools-mt.1086.mcz

==================== Summary ====================

Name: Tools-mt.1086
Author: mt
Time: 15 December 2021, 3:54:32.768 pm
UUID: 77c9e2bc-974d-4b4b-ba71-1b4fd6dadff4
Ancestors: Tools-mt.1085

Adds custom inspector for (full) block closures.

Please read the commentary in #doItReceiver to not get over-excited about what you can and cannot do in the inspector's "source code" field and the code pane below.

=============== Diff against Tools-mt.1085 ===============

Item was added:
+ ----- Method: BlockClosure>>inspectorClass (in category '*Tools-Inspector') -----
+ inspectorClass
+ 
+ 	^ BlockClosureInspector!

Item was added:
+ Inspector subclass: #BlockClosureInspector
+ 	instanceVariableNames: ''
+ 	classVariableNames: ''
+ 	poolDictionaries: ''
+ 	category: 'Tools-Inspector'!

Item was added:
+ ----- Method: BlockClosureInspector>>bindingOf: (in category 'evaluation') -----
+ bindingOf: aString
+ 	" See commentary in #doItReceiver. Yes, we cannot evalute the closured bindings by name in the code pane. But we can browse and change the bindings through their inspector fields.
+ 	
+ 	self object method literalsDo: [:literal |
+ 		(literal isVariableBinding and: [literal key = aString])
+ 			ifTrue: [^ literal]].
+ 	"
+ 		
+ 	^ super bindingOf: aString!

Item was added:
+ ----- Method: BlockClosureInspector>>doItReceiver (in category 'evaluation') -----
+ doItReceiver
+ 	"Overwritten for documentation only. We cannot expose the closured 'self' here because users expect the closure to be the #doItReceiver so that 'self value' can be used to evaluate the block. We can, however, configure the styler to at least style #fieldSource correctly. See #updateStyler:requestor: and #hasBindingOf:.
+ 	
+ 	Note that you can always debug-it the expression 'self value' to the evaluate parts of the closure."
+ 	
+ 	^ super doItReceiver!

Item was added:
+ ----- Method: BlockClosureInspector>>fieldSource (in category 'fields') -----
+ fieldSource
+ 
+ 	^ (self newFieldForType: #code key: #source)
+ 		name: 'source code' translated; emphasizeName;
+ 		valueGetter: [:blockClosure | '"{1}"\{2}' withCRs format: {blockClosure outerContext. blockClosure decompile decompileString}]; printValueAsIs;
+ 		shouldStyleValue: true;
+ 		yourself!

Item was added:
+ ----- Method: BlockClosureInspector>>hasBindingOf: (in category 'user interface - styling') -----
+ hasBindingOf: aString
+ 	
+ 	self object method literalsDo: [:literal |
+ 		(literal isVariableBinding and: [literal key = aString])
+ 			ifTrue: [^ true]].
+ 	^ self object outerContext tempNames includes: aString!

Item was added:
+ ----- Method: BlockClosureInspector>>streamBaseFieldsOn: (in category 'fields - streaming') -----
+ streamBaseFieldsOn: aStream
+ 	
+ 	super streamBaseFieldsOn: aStream.
+ 	aStream nextPut: self fieldSource.!

Item was added:
+ ----- Method: BlockClosureInspector>>streamBindingsOn: (in category 'fields - streaming') -----
+ streamBindingsOn: aStream
+ 	
+ 	| compiledCode tempNames |
+ 	self flag: #decompile. "mt: Use #to: and #do: instead of #to:do: to avoid inlining to preserve bindings in enumeration block for later decompilation. See InspectorField."
+ 	(1 to: (compiledCode := self object method) numLiterals) do: [:index |
+ 		| literal |
+ 		literal := compiledCode literalAt: index.
+ 		literal isVariableBinding ifTrue: [ 		
+ 			aStream nextPut: ((self newFieldForType: #tempVar key: index)
+ 				name: ('[{1}]' format: {literal key});
+ 				valueGetter: [:closure | (closure method literalAt: index) value];
+ 				valueSetter: [:closure :value | (closure method literalAt: index) value: value];
+ 				yourself)]].
+ 	
+ 	tempNames := self object outerContext tempNames.
+ 	"No need to show closured bindings from outerContext. The important temps are already covered in the indexed fields below."
+ 	"(1 to: tempNames size - self object basicSize) do: [:index |
+ 		aStream nextPut: ((self newFieldForType: #tempVar key: index)
+ 				name: ('[{1}]' format: {tempNames at: index});
+ 				valueGetter: [:closure | closure outerContext tempAt: index];
+ 				valueSetter: [:closure :value | closure outerContext tempAt: index put: value];
+ 				yourself)]."
+ 			
+ 	(1 to: self object basicSize) do: [:index |
+ 		aStream nextPut: ((self newFieldForType: #tempVar key: index)
+ 				name: ('[{1}]' format: {tempNames at: index + tempNames size - self object basicSize});
+ 				valueGetter: [:closure | closure basicAt: index];
+ 				valueSetter: [:closure :value | closure basicAt: index put: value];
+ 				yourself)].
+ 			
+ 		
+ "See commentary in #doItReceiver. No need to expose the closured 'self' here because there is already the #receiver instVar.
+ 
+ fieldReceiver
+ 	^ (self newFieldForType: #tempVar key: #receiver)
+ 		name: '[self]';
+ 		valueGetter: [:obj | obj receiver];
+ 		valueSetter: [:obj :value | obj receiver: value];
+ 		yourself
+ "!

Item was added:
+ ----- Method: BlockClosureInspector>>streamInstanceVariablesOn: (in category 'fields - streaming') -----
+ streamInstanceVariablesOn: aStream
+ 	"Add (closured) bindings to the list."
+ 
+ 	super streamInstanceVariablesOn: aStream.
+ 	self streamBindingsOn: aStream.!

Item was added:
+ ----- Method: BlockClosureInspector>>updateStyler:requestor: (in category 'user interface - styling') -----
+ updateStyler: aStyler requestor: anObject
+ 	"Overwritten to let the receiver behave like a Workspace to be asked for #hasBindingOf:."
+ 	
+ 	super updateStyler: aStyler requestor: anObject.
+ 	aStyler workspace: self.!



More information about the Squeak-dev mailing list