" As I traverste the graph, I find equivalent nodes and I merge the equivalent nodes under the single one. This saves compiler time, number of instance variables needed and makes compiled class more compact. I am using `node:equals:` because of performance (I do cache allNodes) which took too much time to constantly compute... " Class { #name : 'PPCMergingVisitor', #superclass : 'PPCRewritingVisitor', #instVars : [ 'nodeSet', 'childrenCache' ], #category : 'PetitCompiler-Visitors' } { #category : 'children cache' } PPCMergingVisitor >> cachedChildren: node [ ^ childrenCache at: node ifAbsentPut: [ node dfsOrder ] ] { #category : 'node comparison' } PPCMergingVisitor >> equivalentNode: node [ self halt: 'not used?'. ^ nodeSet detect: [ :e | self node: e equals: node ] ] { #category : 'node comparison' } PPCMergingVisitor >> equivalentNode: node ifNone: block [ ^ nodeSet detect: [ :e | self node: e equals: node ] ifNone: block ] { #category : 'node comparison' } PPCMergingVisitor >> hasEquivalentNode: node [ ^ nodeSet contains: [ :e | self node: e equals: node ] ] { #category : 'initialization' } PPCMergingVisitor >> initialize [ super initialize. "Though this is IdentitySet, I do assert node:equals: befoere inserting node into the set" nodeSet := IdentitySet new. childrenCache := IdentityDictionary new. ] { #category : 'node comparison' } PPCMergingVisitor >> node: node equals: anotherNode [ | children anotherChildren | (node equals: anotherNode) ifFalse: [ ^ false ]. children := self cachedChildren: node. anotherChildren := self cachedChildren: anotherNode. (children size = anotherChildren size) ifFalse: [ ^ false ]. children with: anotherChildren do: [ :n1 :n2 | (n1 equals: n2) ifFalse: [ ^ false ] ]. ^ true ] { #category : 'node comparison' } PPCMergingVisitor >> store: node [ self assert: (self hasEquivalentNode: node) not. nodeSet add: node ] { #category : 'traversing' } PPCMergingVisitor >> visitNode: node [ | equivalent | "merge the conntent of the node" super visitNode: node. (equivalent := self equivalentNode: node ifNone: nil ) isNil ifFalse: [ self cache: node value: equivalent. ^ equivalent ]. self store: node. ^ node ]