The Trunk: Compiler-eem.172.mcz

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

The Trunk: Compiler-eem.172.mcz

commits-2
Eliot Miranda uploaded a new version of Compiler to project The Trunk:
http://source.squeak.org/trunk/Compiler-eem.172.mcz

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

Name: Compiler-eem.172
Author: eem
Time: 31 August 2010, 12:45:25.496 pm
UUID: cbf01579-162b-43d4-ab9e-1099261e3570
Ancestors: Compiler-nice.170

Fix decompilation/pretty-print of expr ifNotNil: [:var| which used to
be rendered as (var := expr) ifNotNil: [:var|.

=============== Diff against Compiler-nice.170 ===============

Item was changed:
  ----- Method: ParseNodeEnumerator>>visitMessageNodeInCascade: (in category 'visiting') -----
  visitMessageNodeInCascade: aMessageNodeInCascade
+ (theSelectBlock isNil or: [theSelectBlock value: aMessageNodeInCascade]) ifFalse:
+ [^nil].
  theBlock value: aMessageNodeInCascade.
  ^super visitMessageNodeInCascade: aMessageNodeInCascade!

Item was changed:
  ----- Method: ParseNodeEnumerator>>visitAssignmentNode: (in category 'visiting') -----
  visitAssignmentNode: anAssignmentNode
+ (theSelectBlock isNil or: [theSelectBlock value: anAssignmentNode]) ifFalse:
+ [^nil].
  theBlock value: anAssignmentNode.
  ^super visitAssignmentNode: anAssignmentNode!

Item was changed:
  ----- Method: BlockNode>>arguments (in category 'accessing') -----
  arguments
+ ^arguments ifNil: [#()]!
- ^arguments!

Item was added:
+ ----- Method: MethodNode>>preen (in category 'converting') -----
+ preen
+ "Preen for pretty-printing and/or decompilation.
+ i.e. post-process to cover up for inadequacies in both algorithms.
+ Currently one case, hiding the assignment to the arg of an inlined block arg to ifNotNil:,
+ (var := expr) ifNil: [...] ifNotNil: [...]    =>    expr ifNil: [...] ifNotNil: [:var| ...]."
+
+ self preenLocalIfNotNilArg!

Item was changed:
  ----- Method: ParseNodeEnumerator>>visitMessageNode: (in category 'visiting') -----
  visitMessageNode: aMessageNode
+ (theSelectBlock isNil or: [theSelectBlock value: aMessageNode]) ifFalse:
+ [^nil].
  theBlock value: aMessageNode.
  ^super visitMessageNode: aMessageNode!

Item was changed:
  ----- Method: ParseNodeEnumerator>>visitInstanceVariableNode: (in category 'visiting') -----
  visitInstanceVariableNode: anInstanceVariableNode
+ (theSelectBlock isNil or: [theSelectBlock value: anInstanceVariableNode]) ifFalse:
+ [^nil].
  theBlock value: anInstanceVariableNode.
  ^super visitInstanceVariableNode: anInstanceVariableNode!

Item was added:
+ ----- Method: ParseNodeEnumerator class>>ofBlock:select: (in category 'instance creation') -----
+ ofBlock: aBlock select: selectBlock
+ ^self new ofBlock: aBlock select: selectBlock!

Item was changed:
  ----- Method: ParseNodeEnumerator>>visitSelectorNode: (in category 'visiting') -----
  visitSelectorNode: aSelectorNode
+ (theSelectBlock isNil or: [theSelectBlock value: aSelectorNode]) ifFalse:
+ [^nil].
  theBlock value: aSelectorNode.
  ^super visitSelectorNode: aSelectorNode!

Item was changed:
  ----- Method: ParseNodeEnumerator>>visitFutureNode: (in category 'visiting') -----
  visitFutureNode: aFutureNode
+ (theSelectBlock isNil or: [theSelectBlock value: aFutureNode]) ifFalse:
+ [^nil].
  theBlock value: aFutureNode.
  ^super visitFutureNode: aFutureNode!

Item was changed:
  ----- Method: Compiler>>format:noPattern:ifFail: (in category 'private') -----
  format: aStream noPattern: noPattern ifFail: failBlock
+ ^(self parser
- ^self parser
  parse: aStream
  class: class
  noPattern: noPattern
  context: context
  notifying: requestor
+ ifFail: [^failBlock value]) preen!
- ifFail: [^failBlock value]!

Item was changed:
  ----- Method: ParseNodeEnumerator>>visitTempVariableNode: (in category 'visiting') -----
  visitTempVariableNode: aTempVariableNode
+ (theSelectBlock isNil or: [theSelectBlock value: aTempVariableNode]) ifFalse:
+ [^nil].
  theBlock value: aTempVariableNode.
  ^super visitTempVariableNode: aTempVariableNode!

Item was changed:
  ----- Method: ParseNodeEnumerator>>visitCascadeNode: (in category 'visiting') -----
  visitCascadeNode: aCascadeNode
+ (theSelectBlock isNil or: [theSelectBlock value: aCascadeNode]) ifFalse:
+ [^nil].
  theBlock value: aCascadeNode.
  ^super visitCascadeNode: aCascadeNode!

Item was changed:
  ----- Method: ParseNodeEnumerator>>visitCommentNode: (in category 'visiting') -----
  visitCommentNode: aCommentNode
+ (theSelectBlock isNil or: [theSelectBlock value: aCommentNode]) ifFalse:
+ [^nil].
  theBlock value: aCommentNode.
  ^super visitCommentNode: aCommentNode!

Item was added:
+ ----- Method: ParseNode>>isOnlySubnodeOf:in: (in category 'testing') -----
+ isOnlySubnodeOf: aSubtree "<ParseNode>" in: aParseTree "<ParseNode>"
+ "Answer if the receiver only occurs within aSubtree of aParseTree, not in the rest of aParseTree.
+ Assumes that aSubtree is in fact a subnode of aParseTree."
+ | isSubnode |
+ isSubnode := false.
+ aSubtree accept: (ParseNodeEnumerator
+ ofBlock: [:node| node == self ifTrue: [isSubnode := true]]).
+ isSubnode ifFalse:
+ [^false].
+ aParseTree accept: (ParseNodeEnumerator
+ ofBlock: [:node| node == self ifTrue: [^false]]
+ select: [:node| node ~= aSubtree]).
+ ^true!

Item was changed:
  ----- Method: ParseNodeEnumerator>>visitBlockNode: (in category 'visiting') -----
  visitBlockNode: aBlockNode
+ (theSelectBlock isNil or: [theSelectBlock value: aBlockNode]) ifFalse:
+ [^nil].
  theBlock value: aBlockNode.
  ^super visitBlockNode: aBlockNode!

Item was changed:
  ----- Method: ParseNodeEnumerator>>visitBraceNode: (in category 'visiting') -----
  visitBraceNode: aBraceNode
+ (theSelectBlock isNil or: [theSelectBlock value: aBraceNode]) ifFalse:
+ [^nil].
  theBlock value: aBraceNode.
  ^super visitBraceNode: aBraceNode!

Item was added:
+ ----- Method: ParseNodeEnumerator>>ofBlock:select: (in category 'initialize-release') -----
+ ofBlock: aBlock select: aSelectBlock
+ theBlock := aBlock.
+ theSelectBlock := aSelectBlock!

Item was added:
+ ----- Method: MethodNode>>preenLocalIfNotNilArg (in category 'converting') -----
+ preenLocalIfNotNilArg
+ "Try and spot a (var := expr) ifNil: [...] ifNotNil: [...] where var is only used in the ifNotNil: block
+ and convert it to expr ifNil: [...] ifNotNil: [:var| ...].  Deal both with the pretty-print case where
+ the block already declares the variable and the decompile case where it does not."
+
+ | varsToHide |
+ varsToHide := Set new.
+ self nodesDo:
+ [:node| | variable |
+ (node isMessageNode
+ and: [node macroPrinter == #printIfNilNotNil:indent:
+ and: [node receiver isMessageNode
+ and: [node receiver selector key == #==
+ and: [node receiver receiver isAssignmentNode
+ and: [(variable := node receiver receiver variable) isTemp
+ and: [variable isRemote not
+ and: [variable isOnlySubnodeOf: node in: self]]]]]]]) ifTrue:
+ [node arguments last arguments isEmpty
+ ifTrue: [node arguments last arguments: { variable }.
+ varsToHide add: variable]
+ ifFalse: [self assert: node arguments last arguments asArray =  { variable }].
+ node receiver receiver: node receiver receiver value]].
+ varsToHide notEmpty ifTrue:
+ [self nodesDo:
+ [:node|
+ ((node == self or: [node isBlockNode])
+ and: [node temporaries anySatisfy: [:temp| varsToHide includes: temp]]) ifTrue:
+ [node temporaries: (node temporaries reject: [:temp| varsToHide includes: temp])]]]!

Item was changed:
  ----- Method: ParseNodeEnumerator>>visitReturnNode: (in category 'visiting') -----
  visitReturnNode: aReturnNode
+ (theSelectBlock isNil or: [theSelectBlock value: aReturnNode]) ifFalse:
+ [^nil].
  theBlock value: aReturnNode.
  ^super visitReturnNode: aReturnNode!

Item was changed:
  ParseNodeVisitor subclass: #ParseNodeEnumerator
+ instanceVariableNames: 'theBlock theSelectBlock'
- instanceVariableNames: 'theBlock'
  classVariableNames: ''
  poolDictionaries: ''
  category: 'Compiler-Support'!
 
+ !ParseNodeEnumerator commentStamp: 'eem 8/31/2010 11:41' prior: 0!
+ ParseNodeEnumerator implements ParseNode>>nodesDo:.  It can be used to enumerate an entire tree via
+ aParseNode accept: (ParseNodeEnumerator ofBlock: aBlock)
+ or selectively, excluding the node and subnodes for which selectBlock answers false, via
+ aParseNode accept: (ParseNodeEnumerator
+ ofBlock: aBlock
+ select: selectBlock)
+
+ Here's a doIt that generates and compiles the visiting methods:
+
- !ParseNodeEnumerator commentStamp: '<historical>' prior: 0!
  self superclass selectors do:
  [:s|
  self compile: (String streamContents:
  [:str| | arg |
  arg := 'a', (s allButFirst: 5) allButLast.
  str nextPutAll: s, ' ', arg; crtab;
+ nextPutAll: '(theSelectBlock isNil or: [theSelectBlock value: '; nextPutAll: arg; nextPutAll: ']) ifFalse:'; crtab;
+ tab: 2; nextPutAll: '[^nil].'; crtab;
  nextPutAll: 'theBlock value: '; nextPutAll: arg; nextPut: $.; crtab;
  nextPutAll: '^super '; nextPutAll: s, ' ', arg])]!

Item was changed:
  ----- Method: ParseNodeEnumerator>>visitMethodNode: (in category 'visiting') -----
  visitMethodNode: aMethodNode
+ (theSelectBlock isNil or: [theSelectBlock value: aMethodNode]) ifFalse:
+ [^nil].
  theBlock value: aMethodNode.
  ^super visitMethodNode: aMethodNode!

Item was changed:
  ----- Method: ParseNodeEnumerator>>visitFieldNode: (in category 'visiting') -----
  visitFieldNode: aFieldNode
+ (theSelectBlock isNil or: [theSelectBlock value: aFieldNode]) ifFalse:
+ [^nil].
  theBlock value: aFieldNode.
  ^super visitFieldNode: aFieldNode!

Item was changed:
  ----- Method: ParseNodeEnumerator>>visitVariableNode: (in category 'visiting') -----
  visitVariableNode: aVariableNode
+ (theSelectBlock isNil or: [theSelectBlock value: aVariableNode]) ifFalse:
+ [^nil].
  theBlock value: aVariableNode.
  ^super visitVariableNode: aVariableNode!

Item was changed:
  ----- Method: ParseNodeEnumerator>>visitNewArrayNode: (in category 'visiting') -----
  visitNewArrayNode: aNewArrayNode
+ (theSelectBlock isNil or: [theSelectBlock value: aNewArrayNode]) ifFalse:
+ [^nil].
  theBlock value: aNewArrayNode.
  ^super visitNewArrayNode: aNewArrayNode!

Item was changed:
  ----- Method: ParseNodeEnumerator>>visitLiteralNode: (in category 'visiting') -----
  visitLiteralNode: aLiteralNode
+ (theSelectBlock isNil or: [theSelectBlock value: aLiteralNode]) ifFalse:
+ [^nil].
  theBlock value: aLiteralNode.
  ^super visitLiteralNode: aLiteralNode!

Item was changed:
  ----- Method: BlockNode>>temporaries (in category 'accessing') -----
  temporaries
+ ^temporaries ifNil: [#()]!
- ^temporaries!

Item was changed:
  ----- Method: ParseNodeEnumerator>>visitRemoteTempVectorNode: (in category 'visiting') -----
  visitRemoteTempVectorNode: aRemoteTempVectorNode
+ (theSelectBlock isNil or: [theSelectBlock value: aRemoteTempVectorNode]) ifFalse:
+ [^nil].
  theBlock value: aRemoteTempVectorNode.
  ^super visitRemoteTempVectorNode: aRemoteTempVectorNode!

Item was changed:
  ----- Method: ParseNodeEnumerator>>visitLiteralVariableNode: (in category 'visiting') -----
  visitLiteralVariableNode: aLiteralVariableNode
+ (theSelectBlock isNil or: [theSelectBlock value: aLiteralVariableNode]) ifFalse:
+ [^nil].
  theBlock value: aLiteralVariableNode.
  ^super visitLiteralVariableNode: aLiteralVariableNode!

Item was changed:
  ----- Method: Decompiler>>decompile:in:method:using: (in category 'public access') -----
  decompile: aSelector in: aClass method: aMethod using: aConstructor
 
  | block node |
  constructor := aConstructor.
  method := aMethod.
  self initSymbols: aClass.  "create symbol tables"
  method isQuick
  ifTrue: [block := self quickMethod]
  ifFalse:
  [stack := OrderedCollection new: method frameSize.
  caseExits := OrderedCollection new.
  statements := OrderedCollection new: 20.
  numLocalTemps := 0.
  super method: method pc: method initialPC.
  "skip primitive error code store if necessary"
  (method primitive ~= 0 and: [self willStore]) ifTrue:
  [pc := pc + 2.
  tempVars := tempVars asOrderedCollection].
  block := self blockTo: method endPC + 1.
  stack isEmpty ifFalse: [self error: 'stack not empty']].
  node := constructor
  codeMethod: aSelector
  block: block
  tempVars: tempVars
  primitive: method primitive
  class: aClass.
  method primitive > 0 ifTrue:
  [node removeAndRenameLastTempIfErrorCode].
+ ^node preen!
- ^node!

Item was removed:
- ----- Method: ParseNode>>optimizedBlockHoistTempsInto: (in category 'code generation (closures)') -----
- optimizedBlockHoistTempsInto: scopeBlock "<BlockNode>"
- "This is a No-op for all nodes except non-optimized BlockNodes."
- ^self!