compiler/PPCCompiler.st
changeset 421 7e08b31e0dae
parent 415 f30eb7ea54cd
child 422 116d2b2af905
equal deleted inserted replaced
420:b2f2f15cef26 421:7e08b31e0dae
     1 "{ Package: 'stx:goodies/petitparser/compiler' }"
     1 "{ Package: 'stx:goodies/petitparser/compiler' }"
     2 
     2 
     3 Object subclass:#PPCCompiler
     3 Object subclass:#PPCCompiler
     4 	instanceVariableNames:'compilerStack compiledParser cache inlining debug profile
     4 	instanceVariableNames:'compilerStack compiledParser cache inlining debug profile
     5 		currentMethod lastMethod guards ids updateContextMethod tokenMode'
     5 		currentMethod guards ids tokenMode rootNode'
     6 	classVariableNames:''
     6 	classVariableNames:''
     7 	poolDictionaries:''
     7 	poolDictionaries:''
     8 	category:'PetitCompiler-Core'
     8 	category:'PetitCompiler-Core'
     9 !
     9 !
    10 
    10 
    27 	^ inlining
    27 	^ inlining
    28 !
    28 !
    29 
    29 
    30 inlining: value
    30 inlining: value
    31 	inlining := value
    31 	inlining := value
    32 !
       
    33 
       
    34 lastMethod
       
    35 	^ lastMethod 
       
    36 !
    32 !
    37 
    33 
    38 parameters: associations
    34 parameters: associations
    39 	| key value |
    35 	| key value |
    40 	associations do: [ :ass |
    36 	associations do: [ :ass |
    53 
    49 
    54 profile: aBoolean
    50 profile: aBoolean
    55 	profile := aBoolean 
    51 	profile := aBoolean 
    56 !
    52 !
    57 
    53 
    58 startInline: id
    54 rootNode
    59 	self push.
    55 	^ rootNode
    60 	
       
    61 	currentMethod := PPCInlinedMethod new.
       
    62 	currentMethod id: id.	
       
    63 	currentMethod profile: self profile.
       
    64 ! !
    56 ! !
    65 
    57 
    66 !PPCCompiler methodsFor:'cleaning'!
    58 !PPCCompiler methodsFor:'cleaning'!
    67 
    59 
    68 clean: class
    60 clean: class
   104 
    96 
   105 add: string
    97 add: string
   106 	currentMethod add: string.
    98 	currentMethod add: string.
   107 !
    99 !
   108 
   100 
       
   101 addComment: string
       
   102 	currentMethod add: '"', string, '"'.
       
   103 !
       
   104 
   109 addConstant: value as: name
   105 addConstant: value as: name
   110 	compiledParser addConstant: value as: name.
   106 	compiledParser addConstant: value as: name.
   111 !
   107 !
   112 
   108 
   113 addOnLine: string
   109 addOnLine: string
   136 
   132 
   137 callOnLine: anotherMethod
   133 callOnLine: anotherMethod
   138 	currentMethod addOnLine: anotherMethod call.
   134 	currentMethod addOnLine: anotherMethod call.
   139 !
   135 !
   140 
   136 
   141 checkCache: id
       
   142 	| method value |
       
   143 	"Check if method is already compiled/hand written"
       
   144 	method := compiledParser compiledMethodAt: id ifAbsent: [ nil ].
       
   145 	method ifNotNil: [ ^ lastMethod := PPCCompiledMethod new id: id; yourself ].
       
   146 	
       
   147 	^ (value := self cachedValue: id) ifNotNil: [ lastMethod := value ].
       
   148 !
       
   149 
       
   150 dedent
   137 dedent
   151 	currentMethod dedent
   138 	currentMethod dedent
   152 !
   139 !
   153 
   140 
   154 indent
   141 indent
   155 	currentMethod indent
   142 	currentMethod indent
   156 !
   143 !
   157 
   144 
   158 nl
   145 nl
   159 	currentMethod nl
   146 	currentMethod nl
   160 !
       
   161 
       
   162 pop
       
   163 	| array |
       
   164 	array := compilerStack pop.
       
   165 	currentMethod := array first	
       
   166 !
       
   167 
       
   168 push
       
   169 	| array |
       
   170 	array := { currentMethod }.
       
   171 	compilerStack push: array.
       
   172 	(compilerStack size > 500 )ifTrue: [ self error: 'unless it is very complex grammar, there is an error somewhere' ]
       
   173 !
   147 !
   174 
   148 
   175 smartRemember: parser
   149 smartRemember: parser
   176 	^ self smartRemember: parser to: #memento 
   150 	^ self smartRemember: parser to: #memento 
   177 !
   151 !
   192 		^ 'context lwRestore: ', mementoName, '.'.
   166 		^ 'context lwRestore: ', mementoName, '.'.
   193 	].
   167 	].
   194 	^ 'context restore: ', mementoName, '.'.
   168 	^ 'context restore: ', mementoName, '.'.
   195 !
   169 !
   196 
   170 
   197 startMethod: id
       
   198 	|  sender |
       
   199 	(cache includesKey: id) ifTrue: [ self error: 'OOOUPS!!' ].
       
   200 	self push.
       
   201 	
       
   202 	
       
   203 	currentMethod := PPCMethod new.
       
   204 	currentMethod id: id.
       
   205 	currentMethod profile: self profile.	
       
   206 	self cache: id as: currentMethod.
       
   207 	
       
   208 	sender := thisContext sender receiver.
       
   209 	self add: '"Method generated from ', sender asString, '"'.
       
   210 !
       
   211 
       
   212 startTokenMode
   171 startTokenMode
   213 	tokenMode := true
   172 	tokenMode := true
   214 !
   173 !
   215 
   174 
   216 stopInline
       
   217 	| sender |
       
   218 	sender := thisContext sender receiver.
       
   219 	self add: '"Inlined by ', sender asString, '"'.
       
   220 	lastMethod := currentMethod.
       
   221 	currentMethod := nil.
       
   222 	self pop.
       
   223 !
       
   224 
       
   225 stopMethod
       
   226 	self cache: currentMethod methodName as: currentMethod.
       
   227 	lastMethod := currentMethod.
       
   228 	currentMethod := nil.
       
   229 	self pop.
       
   230 !
       
   231 
       
   232 stopTokenMode
   175 stopTokenMode
   233 	tokenMode := false
   176 	tokenMode := false
   234 ! !
   177 ! !
   235 
   178 
   236 !PPCCompiler methodsFor:'code generation - ids'!
   179 !PPCCompiler methodsFor:'code generation - ids'!
   242 idFor: object prefixed: prefix effect: effect
   185 idFor: object prefixed: prefix effect: effect
   243 	^ self idFor: object prefixed: prefix suffixed: '' effect: effect.
   186 	^ self idFor: object prefixed: prefix suffixed: '' effect: effect.
   244 !
   187 !
   245 
   188 
   246 idFor: object prefixed: prefix suffixed: suffix effect: effect
   189 idFor: object prefixed: prefix suffixed: suffix effect: effect
   247 	| body |
   190 	| body id |
       
   191 	
       
   192 	"Halt if: [ (object isKindOf: PPCNode) and: [object name = #smalltalk_ws ] ]."
       
   193 	
       
   194 "	((object isKindOf: PPCNode) and: [object name = #smalltalk_ws ])  ifTrue: [ Transcript crShow: 'st_ws' ].
       
   195 "	
   248 	^ ids at: object ifAbsentPut: [ 
   196 	^ ids at: object ifAbsentPut: [ 
   249 		((object isKindOf: PPCNode) and: [object name isNotNil]) ifTrue: [ 
   197 		((object isKindOf: PPCNode) and: [object name isNotNil]) ifTrue: [ 
   250 			 (object name, suffix) asSymbol
   198 			"Halt if: [ object name = #smalltalk_ws ]."
       
   199 "			(object name = #smalltalk_ws) ifTrue: [Transcript crShow: 'NEW st_ws'].
       
   200 "			
       
   201 			id := (object name, suffix) asSymbol.
       
   202 			"Make sure, that the generated ID is uniqe!!"
       
   203 			((ids values select: [ :e | e = id ]) isEmpty) ifTrue: [ id ]
       
   204 			ifFalse: [ 
       
   205 				body := ids size asString.
       
   206 				(id, '_', body) asSymbol 
       
   207 			]
   251 		] ifFalse: [ 
   208 		] ifFalse: [ 
   252 			body := ids size asString.
   209 			body := ids size asString.
   253 			(prefix asString, '_', body, suffix) asSymbol
   210 			(prefix asString, '_', body, suffix) asSymbol
   254 		]
   211 		]
   255 	]
   212 	]
       
   213 ! !
       
   214 
       
   215 !PPCCompiler methodsFor:'code generation - support'!
       
   216 
       
   217 checkCache: id
       
   218 	| method  |
       
   219 	"Check if method is hand written"
       
   220 	method := compiledParser compiledMethodAt: id ifAbsent: [ nil ].
       
   221 	method ifNotNil: [ ^ PPCCompiledMethod new id: id; yourself ].
       
   222 	
       
   223 	^ self cachedValue: id
       
   224 !
       
   225 
       
   226 pop
       
   227         | retval |
       
   228         retval := compilerStack pop.
       
   229         compilerStack isEmpty ifFalse: [ currentMethod := compilerStack top ].
       
   230         ^ retval
       
   231 
       
   232     "Modified: / 21-11-2014 / 12:27:25 / Jan Vrany <jan.vrany@fit.cvut.cz>"
       
   233 !
       
   234 
       
   235 push
       
   236         compilerStack push: currentMethod.
       
   237         (compilerStack size > 500 )ifTrue: [ self error: 'unless it is very complex grammar, there is an error somewhere' ]
       
   238 
       
   239     "Modified: / 21-11-2014 / 12:27:18 / Jan Vrany <jan.vrany@fit.cvut.cz>"
       
   240 !
       
   241 
       
   242 startInline: id
       
   243 	| sender |	
       
   244 	
       
   245 	currentMethod := PPCInlinedMethod new.
       
   246 	currentMethod id: id.	
       
   247 	currentMethod profile: self profile.
       
   248 	self push.
       
   249 	
       
   250 	
       
   251 	sender := thisContext sender receiver.
       
   252 	self addComment: 'START inlining by ', sender asString.
       
   253 !
       
   254 
       
   255 startMethod: id
       
   256 	|  sender |
       
   257 	(cache includesKey: id) ifTrue: [ self error: 'OOOUPS!!' ].
       
   258 	
       
   259 	currentMethod := PPCMethod new.
       
   260 	currentMethod id: id.
       
   261 	currentMethod profile: self profile.	
       
   262 	self push.	
       
   263 		
       
   264 	self cache: id as: currentMethod.
       
   265 	
       
   266 	sender := thisContext sender receiver.
       
   267 	self addComment: 'START of method generated by ', sender asString.
       
   268 !
       
   269 
       
   270 stopInline
       
   271 	| sender |
       
   272 	sender := thisContext sender receiver.
       
   273 	self addComment: 'STOP inlining by ', sender asString.
       
   274 	^ self pop.
       
   275 !
       
   276 
       
   277 stopMethod
       
   278 	| sender |
       
   279 	sender := thisContext sender receiver.
       
   280 	self addComment: 'END of method generated by ', sender asString.
       
   281 
       
   282 	self cache: currentMethod methodName as: currentMethod.
       
   283 	^ self pop.
       
   284 !
       
   285 
       
   286 top
       
   287 	^ compilerStack top
   256 ! !
   288 ! !
   257 
   289 
   258 !PPCCompiler methodsFor:'compiling'!
   290 !PPCCompiler methodsFor:'compiling'!
   259 
   291 
   260 compile: aPPParser as: name
   292 compile: aPPParser as: name
   270 	^ parser
   302 	^ parser
   271 	
   303 	
   272 !
   304 !
   273 
   305 
   274 compileTree: compilerTree as: name parser: parser params: params
   306 compileTree: compilerTree as: name parser: parser params: params
   275         |  |
   307 	|  |
   276         params do: [ :p | 
   308 	params do: [ :p | 
   277                 (p key = #guards) ifTrue: [ self guards: p value ].
   309 		(p key = #guards) ifTrue: [ self guards: p value ].
   278         ].      
   310 	].	
   279 
   311 
   280 
   312 
   281         ((Smalltalk respondsTo:#isSmalltalkX) and:[ Smalltalk isSmalltalkX ]) ifTrue:[
   313 	((Smalltalk respondsTo:#isSmalltalkX) and:[ Smalltalk isSmalltalkX ]) ifTrue:[
   282                 | rPackageOrganizer |
   314 		| rPackageOrganizer |
   283                 rPackageOrganizer := Smalltalk at: #RPackageOrganizer.
   315 		rPackageOrganizer := Smalltalk at: #RPackageOrganizer.
   284                 rPackageOrganizer notNil ifTrue:[
   316 		rPackageOrganizer notNil ifTrue:[
   285                         rPackageOrganizer default registerPackageNamed: 'PetitCompiler-Generated'.
   317 			rPackageOrganizer default registerPackageNamed: 'PetitCompiler-Generated'.
   286                 ].
   318 		].
   287 
   319 
   288       compiledParser := (Smalltalk at: name ifAbsent: [ nil ]).
   320       compiledParser := (Smalltalk at: name ifAbsent: [ nil ]).
   289       compiledParser ifNil: [ 
   321       compiledParser ifNil: [ 
   290                 PPCompiledParser subclass: name
   322                 PPCompiledParser subclass: name
   291                    instanceVariableNames:''
   323                    instanceVariableNames:''
   293                    poolDictionaries:''
   325                    poolDictionaries:''
   294                    category:'PetitCompiler-Generated'.                
   326                    category:'PetitCompiler-Generated'.                
   295                 compiledParser := Smalltalk at: name.
   327                 compiledParser := Smalltalk at: name.
   296       ] ifNotNil: [ 
   328       ] ifNotNil: [ 
   297                 self clean: compiledParser 
   329                 self clean: compiledParser 
   298       ].                
   330       ].      		
   299         ] ifFalse: [ 
   331 	] ifFalse: [ 
   300                 RPackageOrganizer default registerPackageNamed: 'PetitCompiler-Generated'.
   332 		RPackageOrganizer default registerPackageNamed: 'PetitCompiler-Generated'.
   301                 compiledParser := (Smalltalk at: name ifAbsent: [ nil ]).
   333 		compiledParser := (Smalltalk at: name ifAbsent: [ nil ]).
   302                 compiledParser ifNil: [ 
   334 		compiledParser ifNil: [ 
   303                                                         PPCompiledParser subclass: name.
   335 							PPCompiledParser subclass: name.
   304                                                         compiledParser := Smalltalk at: name.
   336 							compiledParser := Smalltalk at: name.
   305                                                         compiledParser category: 'PetitCompiler-Generated'                                                      
   337 							compiledParser category: 'PetitCompiler-Generated'							
   306                                                         ] ifNotNil: [ 
   338 							] ifNotNil: [ 
   307                                                                 self clean: compiledParser 
   339 								self clean: compiledParser 
   308                                                         ].      
   340 							].	
   309         ].
   341 	].
   310         compiledParser constants removeAll.
   342 	compiledParser constants removeAll.
   311         
   343 	
   312 
   344 	rootNode := compilerTree.
   313         self startMethod: #start.
   345 	self precomputeFirstSets: rootNode.
   314         self add: '^ '.
   346 	self precomputeFollowSets: rootNode.
   315         self callOnLine: (compilerTree compileWith: self).
   347 	self precomputeFollowSetsWithTokens: rootNode.
   316         self stopMethod.
   348 	
   317 
   349 	self startMethod: #start.
   318         self installVariablesAndMethods.
   350 	self add: '^ '.
   319 
   351 	self callOnLine: (compilerTree compileWith: self).
   320         compiledParser referringParser: parser.
   352 	self stopMethod.
   321         ^ compiledParser
   353 
   322 
   354 	self installVariablesAndMethods.
   323     "Modified: / 05-11-2014 / 23:17:02 / Jan Vrany <jan.vrany@fit.cvut.cz>"
   355 
       
   356 	compiledParser referringParser: parser.
       
   357 	^ compiledParser
   324 !
   358 !
   325 
   359 
   326 copy: parser
   360 copy: parser
   327 	^ parser transform: [ :p | p copy ].
   361 	^ parser transform: [ :p | p copy ].
   328 !
   362 !
   332 		class compileSilently: method code classified: 'generated'.
   366 		class compileSilently: method code classified: 'generated'.
   333 	]
   367 	]
   334 !
   368 !
   335 
   369 
   336 installVariables: class
   370 installVariables: class
   337         | string |
   371 	| string |
   338         string := class constants keys inject: '' into: [:r :e | r, ' ', e  ].
   372 	string := class constants keys inject: '' into: [:r :e | r, ' ', e  ].
   339         PPCompiledParser subclass: class name instanceVariableNames: string classVariableNames: '' poolDictionaries:'' category: 'PetitCompiler-Generated'.
   373 	PPCompiledParser subclass: class name instanceVariableNames: string classVariableNames: '' poolDictionaries: '' category: 'PetitCompiler-Generated'.
   340 
       
   341     "Modified: / 26-10-2014 / 22:01:45 / Jan Vrany <jan.vrany@fit.cvut.cz>"
       
   342 !
   374 !
   343 
   375 
   344 installVariablesAndMethods
   376 installVariablesAndMethods
   345     "Updates the class and compile generated code"
   377     "Updates the class and compile generated code"
   346 
   378 
   354     instances. Therefore, to install methods in in correct class, we have
   386     instances. Therefore, to install methods in in correct class, we have
   355     to refetch new version from system dictionary. On Pharo it should not harm."
   387     to refetch new version from system dictionary. On Pharo it should not harm."
   356     compiledParser := Smalltalk at: compiledParserClassName.
   388     compiledParser := Smalltalk at: compiledParserClassName.
   357 
   389 
   358     self installMethods: compiledParser.
   390     self installMethods: compiledParser.
   359 
       
   360     "Created: / 30-10-2014 / 23:15:44 / Jan Vrany <jan.vrany@fit.cvut.cz>"
       
   361 !
   391 !
   362 
   392 
   363 optimize: parser params: params
   393 optimize: parser params: params
   364 	| retval |
   394 	| retval |
   365 	retval := parser optimizeTree: params.
   395 	retval := parser optimizeTree: params.
   366 	retval checkTree.
   396 	retval checkTree.
   367 	^ retval
   397 	^ retval
       
   398 !
       
   399 
       
   400 precomputeFirstSets: root
       
   401 	| firstSets |
       
   402 	firstSets := root firstSets.
       
   403 	
       
   404 	root allNodesDo: [ :node |
       
   405 		node firstSet: (firstSets at: node).
       
   406 	]
       
   407 	
       
   408 !
       
   409 
       
   410 precomputeFollowSets: root
       
   411 	| followSets |
       
   412 	followSets := root followSets.
       
   413 	
       
   414 	root allNodesDo: [ :node |
       
   415 		node followSet: (followSets at: node).
       
   416 	]
       
   417 	
       
   418 !
       
   419 
       
   420 precomputeFollowSetsWithTokens: root
       
   421 	| followSets |
       
   422 	followSets := root followSetsSuchThat: [:e | e isTerminal or: [ e isKindOf: PPCTrimmingTokenNode ]].
       
   423 	
       
   424 	root allNodesDo: [ :node |
       
   425 		node followSetWithTokens: (followSets at: node).
       
   426 	]
       
   427 	
   368 !
   428 !
   369 
   429 
   370 toCompilerTree: parser
   430 toCompilerTree: parser
   371 	^ parser asCompilerTree
   431 	^ parser asCompilerTree
   372 ! !
   432 ! !
   427 
   487 
   428 initialize
   488 initialize
   429 	super initialize.
   489 	super initialize.
   430 	compilerStack := Stack new.
   490 	compilerStack := Stack new.
   431 	cache := IdentityDictionary new.
   491 	cache := IdentityDictionary new.
   432 	ids := IdentityDictionary new.
   492 	ids := Dictionary new.
   433 	
   493 	
   434 	tokenMode := false.
   494 	tokenMode := false.
   435 	inlining := true.
   495 	inlining := true.
   436 	profile := false.
   496 	profile := false.
   437 	guards := true.
   497 	guards := true.
   438 ! !
   498 ! !
   439 
   499 
   440 !PPCCompiler methodsFor:'ppcmethod protocol'!
       
   441 
       
   442 bridge
       
   443 	^ PPCBridge on: lastMethod methodName.
       
   444 !
       
   445 
       
   446 call
       
   447 	^ lastMethod call
       
   448 !
       
   449 
       
   450 canInline
       
   451 	^ lastMethod canInline
       
   452 ! !
       
   453 
       
   454 !PPCCompiler class methodsFor:'documentation'!
   500 !PPCCompiler class methodsFor:'documentation'!
   455 
   501 
   456 version_HG
   502 version_HG
   457 
   503 
   458     ^ '$Changeset: <not expanded> $'
   504     ^ '$Changeset: <not expanded> $'