compiler/PPCASTUtilities.st
changeset 515 b5316ef15274
child 516 3b81c9e53352
equal deleted inserted replaced
502:1e45d3c96ec5 515:b5316ef15274
       
     1 "{ Package: 'stx:goodies/petitparser/compiler' }"
       
     2 
       
     3 "{ NameSpace: Smalltalk }"
       
     4 
       
     5 Object subclass:#PPCASTUtilities
       
     6 	instanceVariableNames:''
       
     7 	classVariableNames:''
       
     8 	poolDictionaries:''
       
     9 	category:'PetitCompiler-Support'
       
    10 !
       
    11 
       
    12 !PPCASTUtilities methodsFor:'checks'!
       
    13 
       
    14 checkNodeIsFunctional: anRBBlockNode inClass: aClaas
       
    15     "Check whether the given node is purely functional or not. 
       
    16      If no, raise an erorr. If not, this method is noop.
       
    17 
       
    18      A block is purely functional if and only if:
       
    19        (i) it does not refer to any instance or class variable or non-local variable
       
    20       (ii) all self-sends within the block are to 'purely-functional' methods
       
    21            (transitively)
       
    22      (iiI) contains no super-sends.
       
    23     "
       
    24     | allDefinedVarNames allInstVarNames allClassVarNames cls |
       
    25 
       
    26     allDefinedVarNames := anRBBlockNode allDefinedVariables.
       
    27     allInstVarNames := Set new.
       
    28     allClassVarNames := Set new.
       
    29     cls := aClaas.
       
    30     [ cls notNil ] whileTrue:[ 
       
    31         | instanceVariables classVariables |
       
    32                 
       
    33         instanceVariables := cls instanceVariables.
       
    34         classVariables := cls classVariables.
       
    35         instanceVariables notNil ifTrue:[
       
    36             allInstVarNames addAll: instanceVariables.
       
    37         ]. 
       
    38         classVariables notNil ifTrue:[
       
    39             allClassVarNames addAll: classVariables.
       
    40         ].
       
    41         cls := cls superclass.
       
    42     ].
       
    43 
       
    44     self withAllVariableNodesOf: anRBBlockNode  do: [ :node | 
       
    45         (allDefinedVarNames includes: node name) ifFalse:[ 
       
    46             (allInstVarNames includes: node name) ifTrue:[
       
    47                 PPCCompilationError new signalWith: 'code refers to an instance variable named `',node name,'`'.
       
    48                 ^ self.
       
    49             ].
       
    50             (allClassVarNames includes: node name) ifTrue:[
       
    51                 PPCCompilationError new signalWith: 'code refers to a class variable named `',node name,'`'.
       
    52                 ^ self.
       
    53             ].
       
    54             (Smalltalk includesKey: node name asSymbol) ifFalse:[ 
       
    55                 PPCCompilationError new signalWith: 'code refers to an unknown variable named `',node name,'`'.
       
    56                 ^ self.                    
       
    57             ].
       
    58         ]
       
    59     ].
       
    60     self withAllMessageNodesOf: anRBBlockNode sentToSelfDo:[:node |
       
    61         | method |
       
    62         
       
    63         method := aClaas lookupSelector: node selector.
       
    64         method isNil ifTrue:[
       
    65             PPCCompilationError new signalWith: 'code contains self-send to non-existent method'.        
       
    66             ^ self
       
    67         ].
       
    68         self checkNodeIsFunctional: method parseTree inClass: method methodClass.
       
    69     ].      
       
    70     self withAllSuperNodesOf: anRBBlockNode do: [ :node | 
       
    71         PPCCompilationError new signalWith: 'code contains a super-send'.
       
    72         ^ self
       
    73     ].
       
    74 
       
    75     "Created: / 27-07-2015 / 12:15:28 / Jan Vrany <jan.vrany@fit.cvut.cz>"
       
    76     "Modified: / 27-07-2015 / 14:43:07 / Jan Vrany <jan.vrany@fit.cvut.cz>"
       
    77 ! !
       
    78 
       
    79 !PPCASTUtilities methodsFor:'enumerating'!
       
    80 
       
    81 withAllMessageNodesOf: anRBProgramNode do: aBlock
       
    82     "Enumerate all chilren of `anRBProgramNode` (including itself)
       
    83      and evaluate `aBlock` for each message node."
       
    84 
       
    85     self withAllNodesOf: anRBProgramNode suchThat: [ :node | node isMessage ] do: aBlock.
       
    86 
       
    87     "Created: / 18-06-2015 / 22:02:43 / Jan Vrany <jan.vrany@fit.cvut.cz>"
       
    88     "Modified (comment): / 27-07-2015 / 11:26:29 / Jan Vrany <jan.vrany@fit.cvut.cz>"
       
    89 !
       
    90 
       
    91 withAllMessageNodesOf: anRBProgramNode sentToSelfDo: aBlock
       
    92     "Enumerate all chilren of `anRBProgramNode` (including itself)
       
    93      and evaluate `aBlock` for each message node which sends a message
       
    94      to self (i.e., for self-sends)."
       
    95 
       
    96     self withAllNodesOf: anRBProgramNode suchThat: [ :node | node isMessage and:[node receiver isSelf ] ] do: aBlock.
       
    97 
       
    98     "Created: / 27-07-2015 / 14:41:30 / Jan Vrany <jan.vrany@fit.cvut.cz>"
       
    99 !
       
   100 
       
   101 withAllNodesOf: node suchThat: predicate do: action
       
   102     "Enumerate all chilren of `node` (including itself)
       
   103      and evaluate `aBlock` for each node for which `predicate` returns true."
       
   104 
       
   105     (predicate value: node) ifTrue:[ 
       
   106         action value: node.
       
   107     ].
       
   108     node children do:[:each | 
       
   109         self withAllNodesOf: each suchThat: predicate do: action
       
   110     ].
       
   111 
       
   112     "Created: / 18-06-2015 / 22:02:43 / Jan Vrany <jan.vrany@fit.cvut.cz>"
       
   113     "Modified (comment): / 27-07-2015 / 11:26:46 / Jan Vrany <jan.vrany@fit.cvut.cz>"
       
   114 !
       
   115 
       
   116 withAllSelfNodesOf: anRBProgramNode do: aBlock
       
   117     "Enumerate all chilren of `anRBProgramNode` (including itself)
       
   118      and evaluate `aBlock` for each `self` node."
       
   119 
       
   120     self withAllNodesOf: anRBProgramNode suchThat: [ :node | node isSelf ] do: aBlock.
       
   121 
       
   122     "Created: / 18-06-2015 / 22:02:43 / Jan Vrany <jan.vrany@fit.cvut.cz>"
       
   123     "Modified (comment): / 27-07-2015 / 11:26:52 / Jan Vrany <jan.vrany@fit.cvut.cz>"
       
   124 !
       
   125 
       
   126 withAllSuperNodesOf: anRBProgramNode do: aBlock
       
   127     "Enumerate all chilren of `anRBProgramNode` (including itself)
       
   128      and evaluate `aBlock` for each `super` node."
       
   129 
       
   130     self withAllNodesOf: anRBProgramNode suchThat: [ :node | node isSuper ] do: aBlock.
       
   131 
       
   132     "Created: / 27-07-2015 / 14:42:28 / Jan Vrany <jan.vrany@fit.cvut.cz>"
       
   133 !
       
   134 
       
   135 withAllVariableNodesOf: anRBProgramNode do: aBlock
       
   136     "Enumerate all chilren of `anRBProgramNode` (including itself)
       
   137      and evaluate `aBlock` for each variable node.
       
   138      This is a replacement for Smalltalk/X's RBProgramNode>>variableNodesDo:
       
   139      which is not present in Pharo"
       
   140 
       
   141     self withAllNodesOf: anRBProgramNode suchThat: [ :node | node isVariable and:[node isSelf not and:[node isSuper not]]] do: aBlock.
       
   142 
       
   143     "Created: / 18-06-2015 / 22:02:43 / Jan Vrany <jan.vrany@fit.cvut.cz>"
       
   144     "Modified (comment): / 27-07-2015 / 11:27:00 / Jan Vrany <jan.vrany@fit.cvut.cz>"
       
   145 ! !
       
   146