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! |
Free forum by Nabble | Edit this page |