compiler/PPCCodeGenerator.st
changeset 491 82b272c7dc37
parent 489 0ca7a70db0f5
child 492 fc3dbe5654c5
equal deleted inserted replaced
490:a836cbc0d8df 491:82b272c7dc37
   207 ! !
   207 ! !
   208 
   208 
   209 !PPCCodeGenerator methodsFor:'visiting'!
   209 !PPCCodeGenerator methodsFor:'visiting'!
   210 
   210 
   211 visitActionNode: node
   211 visitActionNode: node
   212     | blockNode blockBody blockNodesVar |
   212     | blockNode blockBody blockNodesVar blockNeedsCollection blockMatches childValueVars |
   213 
   213 
   214     blockNode := node block ast copy.
   214     blockNode := node block ast copy.
   215     self assert: blockNode arguments size == 1.
   215     self assert: blockNode arguments size == 1.
   216     blockNodesVar := blockNode arguments first .
   216     blockNodesVar := blockNode arguments first .
   217     blockBody := blockNode body.
   217     blockBody := blockNode body.
   218     "Replace all references to blockNodeVar to retvalVar..."
   218 
   219     blockBody variableNodesDo:[:variableNode| 
   219     "Now, analyze block body, search for all references to
   220         variableNode name = blockNodesVar name ifTrue:[ 
   220      block arg <barg> and check if in all cases it's used 
   221             variableNode token value: self retvalVar.
   221      in one of the following patterns:
       
   222 
       
   223         * <barg> first , <barg> second, ... , <barg> sixth
       
   224         * <barg> at: <integer constant>
       
   225 
       
   226      If so, then the block code can be inlined and the intermediate
       
   227      result collection need not to be created. Keep this information
       
   228      in temporary `blockNeedsCollection`. 
       
   229      During the analysis, remember all nodes that matches the pattern
       
   230      in a dictionary `blockMatches` mapping the node to actual temporary
       
   231      variable where the node is used. This will be later used for block's node
       
   232      rewriting"
       
   233     blockNeedsCollection := true.
       
   234     node child isSequenceNode ifTrue:[
       
   235         blockNeedsCollection := false.
       
   236         blockMatches := IdentityDictionary new."Must use IDENTITY dict as nodes have overwritten their #=!!!!!!"
       
   237         childValueVars := node child preferredChildrenVariableNames.
       
   238         blockBody variableNodesDo:[:variableNode| 
       
   239             variableNode name = blockNodesVar name ifTrue:[ 
       
   240                 "Check if variable node matches..."
       
   241                 variableNode parent isMessage ifTrue:[ 
       
   242                     | parent |
       
   243 
       
   244                     parent := variableNode parent.
       
   245                     "Check for <barg> at: <number>"
       
   246                     ((parent selector == #at:) and:[ parent arguments first isLiteralNumber ]) ifTrue:[ 
       
   247                         blockMatches at: parent put: (childValueVars at: parent arguments first value).
       
   248                     ] ifFalse:[ 
       
   249                         "Check for <barg> first / second / ..."
       
   250                         | i |
       
   251 
       
   252                         i := #(first second third fourth fifth sixth) indexOf: parent selector.
       
   253                         i ~~ 0 ifTrue:[ 
       
   254                             blockMatches at: parent put: (childValueVars at: i).
       
   255                         ] ifFalse:[ 
       
   256                             blockNeedsCollection := true.
       
   257                         ].
       
   258                     ].
       
   259                 ] ifFalse:[ 
       
   260                     blockNeedsCollection := true.
       
   261                 ].
       
   262             ].
   222         ].
   263         ].
   223     ].
   264     ].
       
   265 
       
   266     blockNeedsCollection ifTrue:[
       
   267         "Bad, we have to use the collection.
       
   268          Replace all references to blockNodeVar to retvalVar..."
       
   269         blockBody variableNodesDo:[:variableNode| 
       
   270             variableNode name = blockNodesVar name ifTrue:[ 
       
   271                 variableNode token value: self retvalVar.
       
   272             ].
       
   273         ].
       
   274     ] ifFalse:[ 
       
   275         "Good, can avoid intermediate collection.
       
   276          Replace references to collection with corresponding temporary variable"
       
   277         blockMatches keysAndValuesDo:[:node :childValueVar |
       
   278             node parent replaceNode: node withNode: (RBVariableNode named: childValueVar).
       
   279         ].
       
   280         node child returnParsedObjectsAsCollection: false. 
       
   281     ].
       
   282 
   224     "Block return value is return value of last statement.
   283     "Block return value is return value of last statement.
   225      So if the method is not inline, make last statement a return.
   284      So if the method is not inline, make last statement a return.
   226         if the method is inline, make it assignment to retvalVar."
   285         if the method is inline, make it assignment to retvalVar."
   227     blockBody statements notEmpty ifTrue:["Care for empty blocks - [:t | ] !!"
   286     blockBody statements notEmpty ifTrue:["Care for empty blocks - [:t | ] !!"
   228         compiler currentMethod isInline ifTrue:[ 
   287         compiler currentMethod isInline ifTrue:[ 
   236             return := RBReturnNode value: blockBody statements last.
   295             return := RBReturnNode value: blockBody statements last.
   237             blockBody replaceNode: blockBody statements last withNode: return.
   296             blockBody replaceNode: blockBody statements last withNode: return.
   238         ].
   297         ].
   239     ].
   298     ].
   240 
   299 
   241     compiler 
   300     compiler codeAssignParsedValueOf:[ self visit:node child ] to:self retvalVar.
   242           codeAssignParsedValueOf:[ self visit:node child ]
   301     compiler codeIfErrorThen: [ 
   243           to:self retvalVar.
       
   244     compiler codeIf: 'error' then: [ 
       
   245         compiler codeReturn: 'failure'. 
   302         compiler codeReturn: 'failure'. 
   246     ] else: [
   303     ] else: [
   247         compiler code: blockBody.    
   304         compiler code: blockBody.    
   248     ]
   305     ]
   249 
   306 
   250     "Modified: / 15-06-2015 / 17:08:37 / Jan Vrany <jan.vrany@fit.cvut.cz>"
   307     "Modified: / 16-06-2015 / 07:41:16 / Jan Vrany <jan.vrany@fit.cvut.cz>"
   251 !
   308 !
   252 
   309 
   253 visitAndNode: node
   310 visitAndNode: node
   254     | mementoVar |
   311     | mementoVar |
   255     
   312