Re: [Pharo-project] Breaking another dependency to Compiler (related to Traits I think)
Hi, great point Marcus. I was wondering why cant a compiled method know the "ast" that generated it? It would ease the queries + manipulation, in the tools a lot! CompiledMethod>>getSourceReplacingSelectorWith: aSelector .... would be instead: CompiledMethod>>withSelector: aSelector ^ (self ast withSelector: aSelector) source. I've been using an AST, instead of the CompiledMethods directly for this reason, to deal with more expressive power. Fernando On Tue, Aug 14, 2012 at 2:56 PM, Marcus Denker <marcus.denker@inria.fr> wrote:
On Aug 14, 2012, at 2:01 PM, Mariano Martinez Peck <marianopeck@gmail.com> wrote:
Hi guys. Today, there is a part of the system coupled with Compiler. Issue is: http://code.google.com/p/pharo/issues/detail?id=6110
Now, if you see the method:
getSourceReplacingSelectorWith: newSelector | oldKeywords newKeywords args newSelectorWithArgs source oldSelector s | source := self sourceCode. oldSelector := self parserClass new parseSelector: source. oldSelector = newSelector ifTrue: [ ^ source ]. oldKeywords := oldSelector keywords. newKeywords := (newSelector ifNil: [self defaultSelector]) keywords. [oldKeywords size = newKeywords size] assert. args := (self methodClass parserClass new parseArgsAndTemps: source string notifying: nil) copyFrom: 1 to: self numArgs. newSelectorWithArgs := String streamContents: [:stream | newKeywords withIndexDo: [:keyword :index | stream nextPutAll: keyword. stream space. args size >= index ifTrue: [ stream nextPutAll: (args at: index); space]]]. s := source string readStream. oldKeywords do: [ :each | s match: each ]. args isEmpty ifFalse: [ s match: args last ]. ^newSelectorWithArgs trimBoth, s upToEnd
The 2 magic lines are:
oldSelector := self parserClass new parseSelector: source. oldSelector = newSelector ifTrue: [ ^ source ].
So, why we cannot just replace "self parserClass new parseSelector: source." with "self selector". Well, I think (talking with Guille) this ONLY because of Trait transformation/aliases that associates a selector with a method of a different selector.
If this is the case, it means that 99% of the cases,"oldSelector = newSelector ifTrue: [ ^ source ]. " is true. Because those aliases are only used in one trait in all the image ().
So...if that is the case, can't we get the oldSelector from elsewhere rather than needing to use the Compiler to get the selector from the source code ?
As we now encode the selector in the CompiledMethod itself, this can be relaced with
oldSelector := self selector.
But what you have left is the arguments...
args := (self methodClass parserClass new parseArgsAndTemps: source string notifying: nil) copyFrom: 1 to: self numArgs.
The only way to get the the argument names (temps) of a method is to compile the source... no way around it.
(I personally think this is another example why bytecode as the model for reflection is just wrong)
Marcus
-- Marcus Denker -- http://marcusdenker.de
On Wed, 15 Aug 2012, Fernando Olivero wrote:
Hi, great point Marcus. I was wondering why cant a compiled method know the "ast" that generated it?
Would you store all ASTs in memory all the time or recreate it every time on demand?
It would ease the queries + manipulation, in the tools a lot!
CompiledMethod>>getSourceReplacingSelectorWith: aSelector ....
would be instead:
CompiledMethod>>withSelector: aSelector ^ (self ast withSelector: aSelector) source.
Is there an implementation of AST that can reproduce the exact same source code? Levente
I've been using an AST, instead of the CompiledMethods directly for this reason, to deal with more expressive power.
Fernando
On Tue, Aug 14, 2012 at 2:56 PM, Marcus Denker <marcus.denker@inria.fr> wrote:
On Aug 14, 2012, at 2:01 PM, Mariano Martinez Peck <marianopeck@gmail.com> wrote:
Hi guys. Today, there is a part of the system coupled with Compiler. Issue is: http://code.google.com/p/pharo/issues/detail?id=6110
Now, if you see the method:
getSourceReplacingSelectorWith: newSelector | oldKeywords newKeywords args newSelectorWithArgs source oldSelector s | source := self sourceCode. oldSelector := self parserClass new parseSelector: source. oldSelector = newSelector ifTrue: [ ^ source ]. oldKeywords := oldSelector keywords. newKeywords := (newSelector ifNil: [self defaultSelector]) keywords. [oldKeywords size = newKeywords size] assert. args := (self methodClass parserClass new parseArgsAndTemps: source string notifying: nil) copyFrom: 1 to: self numArgs. newSelectorWithArgs := String streamContents: [:stream | newKeywords withIndexDo: [:keyword :index | stream nextPutAll: keyword. stream space. args size >= index ifTrue: [ stream nextPutAll: (args at: index); space]]]. s := source string readStream. oldKeywords do: [ :each | s match: each ]. args isEmpty ifFalse: [ s match: args last ]. ^newSelectorWithArgs trimBoth, s upToEnd
The 2 magic lines are:
oldSelector := self parserClass new parseSelector: source. oldSelector = newSelector ifTrue: [ ^ source ].
So, why we cannot just replace "self parserClass new parseSelector: source." with "self selector". Well, I think (talking with Guille) this ONLY because of Trait transformation/aliases that associates a selector with a method of a different selector.
If this is the case, it means that 99% of the cases,"oldSelector = newSelector ifTrue: [ ^ source ]. " is true. Because those aliases are only used in one trait in all the image ().
So...if that is the case, can't we get the oldSelector from elsewhere rather than needing to use the Compiler to get the selector from the source code ?
As we now encode the selector in the CompiledMethod itself, this can be relaced with
oldSelector := self selector.
But what you have left is the arguments...
args := (self methodClass parserClass new parseArgsAndTemps: source string notifying: nil) copyFrom: 1 to: self numArgs.
The only way to get the the argument names (temps) of a method is to compile the source... no way around it.
(I personally think this is another example why bytecode as the model for reflection is just wrong)
Marcus
-- Marcus Denker -- http://marcusdenker.de
participants (2)
-
Fernando Olivero -
Levente Uzonyi