[Pharo-project] Breaking another dependency to Compiler (related to Traits I think)

Levente Uzonyi leves at elte.hu
Wed Aug 15 23:10:57 CEST 2012


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 at inria.fr> wrote:
>>
>> On Aug 14, 2012, at 2:01 PM, Mariano Martinez Peck <marianopeck at 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
>>
>>
>
>



More information about the Pharo-project mailing list