Why you need new Method trailers? :)

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

Why you need new Method trailers? :)

Igor Stasenko
I just created a small changeset

http://bugs.squeak.org/view.php?id=7432

which gives me a long awaited feature:
to see in a browser, where the heck a given method comes from.

If method comes from trait, a method's source tells me , from which one exactly!

Open a browser on Behavior clas and select an #addExclusionOf:to: method.
Usually you'll see:

addExclusionOf: aSymbol to: aTrait
        self setTraitComposition: (
                self traitComposition copyWithExclusionOf: aSymbol to: aTrait)

But with my changes you'll see:

" From: TAccessingTraitCompositionBehavior "
addExclusionOf: aSymbol to: aTrait
        self setTraitComposition: (
                self traitComposition copyWithExclusionOf: aSymbol to: aTrait)

in code pane.

Same applies to traits themselves for instance, browse
TPureBehavior>>isAliasSelector:

" From: TAccessingTraitCompositionBehavior "
isAliasSelector: aSymbol
        "Return true if the selector aSymbol is an alias defined
        in my or in another composition somewhere deeper in
        the tree of traits compositions."

        ^(self includesLocalSelector: aSymbol) not
                and: [self hasTraitComposition]
                and: [self traitComposition isAliasSelector: aSymbol]


There is one problem , which requires better expertise than mine and i
need a help from Traits experts: an aliased methods.
I tried to find out, how to dig out the aliased method from
composition, and get its source to display in code pane .. but no
luck.
Please give me an advice, how a  #getSourceCodeBySelector:
method should be implemented for proper handling of aliases.
Currently, all aliased methods sources shown using decompiler:

Behavior>>methodDictAddSelectorSilently: t1 withMethod: t2
        self basicAddSelector: t1 withMethod: t2

Aliased methods, obviously, will require an additional info in source
header, like:

" From: SomeTrait , originalSelector:  #blablba "

--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: Why you need new Method trailers? :)

Igor Stasenko
A little more.

I made an experiment with compressing a method sources into trailers.

(you need to file in a changeset (trailer-fixes-extensions.1.cs )
http://bugs.squeak.org/view.php?id=7428

What i did is:

CompiledMethod allInstancesDo: [:m | m dropSourcePointer ]

It takes a while (compressing sources).

A more faster way is to do same in workspace:

old := CompiledMethod allInstances select: [ :each | each trailer
hasSourcePointer ].
new := old collect: [ :each |
        each copyWithTrailerBytes: (CompiledMethodTrailer new sourceCode:
each getSource) ].
old elementsForwardIdentityTo: new.


Before:
Image size: 26,192,916 bytes

After:
Image size: 33,348,596 bytes

difference: 7,155,680 bytes.

But this means, that your image doesn't have to use .sources file, which is
17,584,724 bytes long
as well as .changes
11,745,139 bytes long..

of course, stripping like this, will leave you without method stamps.. :)

--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: [Pharo-project] Why you need new Method trailers? :)

Adrian Lienhard
In reply to this post by Igor Stasenko
Hi Igor,

This looks complicated... Note, in Pharo this does not work because  
there is no sharing of compiled methods from traits anymore.

I attached a changeset that does the same as yours but for Pharo.





The only thing that is needed are a few lines in sourceCodeAt:. The  
method #traitOrClassOfSelector: returns the origin of a method -- this  
should work just fine for aliased methods too.

HTH,
Adrian

On Dec 21, 2009, at 01:09 , Igor Stasenko wrote:

> I just created a small changeset
>
> http://bugs.squeak.org/view.php?id=7432
>
> which gives me a long awaited feature:
> to see in a browser, where the heck a given method comes from.
>
> If method comes from trait, a method's source tells me , from which  
> one exactly!
>
> Open a browser on Behavior clas and select an #addExclusionOf:to:  
> method.
> Usually you'll see:
>
> addExclusionOf: aSymbol to: aTrait
> self setTraitComposition: (
> self traitComposition copyWithExclusionOf: aSymbol to: aTrait)
>
> But with my changes you'll see:
>
> " From: TAccessingTraitCompositionBehavior "
> addExclusionOf: aSymbol to: aTrait
> self setTraitComposition: (
> self traitComposition copyWithExclusionOf: aSymbol to: aTrait)
>
> in code pane.
>
> Same applies to traits themselves for instance, browse
> TPureBehavior>>isAliasSelector:
>
> " From: TAccessingTraitCompositionBehavior "
> isAliasSelector: aSymbol
> "Return true if the selector aSymbol is an alias defined
> in my or in another composition somewhere deeper in
> the tree of traits compositions."
>
> ^(self includesLocalSelector: aSymbol) not
> and: [self hasTraitComposition]
> and: [self traitComposition isAliasSelector: aSymbol]
>
>
> There is one problem , which requires better expertise than mine and i
> need a help from Traits experts: an aliased methods.
> I tried to find out, how to dig out the aliased method from
> composition, and get its source to display in code pane .. but no
> luck.
> Please give me an advice, how a  #getSourceCodeBySelector:
> method should be implemented for proper handling of aliases.
> Currently, all aliased methods sources shown using decompiler:
>
> Behavior>>methodDictAddSelectorSilently: t1 withMethod: t2
> self basicAddSelector: t1 withMethod: t2
>
> Aliased methods, obviously, will require an additional info in source
> header, like:
>
> " From: SomeTrait , originalSelector:  #blablba "
>
> --
> Best regards,
> Igor Stasenko AKA sig.
>
> _______________________________________________
> Pharo-project mailing list
> [hidden email]
> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project



PrintTraitsMethodOrigin.1.cs (3K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Re: [Pharo-project] Why you need new Method trailers? :)

Igor Stasenko
2009/12/21 Adrian Lienhard <[hidden email]>:
> Hi Igor,
>
> This looks complicated...

Hmm, i wonder, what Traits serve for, if requesting an original source
code of method which being installed in specific behavior using
specific selector
becomes non-trivial task.

> Note, in Pharo this does not work because there is
> no sharing of compiled methods from traits anymore.
>

and it is good that there is no sharing, because in fact, my new code
won't work if traits/behaviors sharing same CompiledMethod instances,
because this could lead to recursion when looking for method's source code.

I'm also made my own 'fix' for that by overriding the

addTraitSelector: aSymbol withMethod: aCompiledMethod

which ALWAYS makes a copy of aCompiledMethod before installing it into
receiver's method dict and replaces its trailer with one
that tells class to use #getSourceCodeBySelector: for finding its source code.

(I hope this is the only entry method, which used by all traits to
install the non-local method in behavior's method dict,
if not, please tell me what other places should be fixed).

I found that because squeak not doing that, there is a funky methods, which
  a) originally belong to some trait
  b) responding a behavior (not trait), where it installed when
sending #methodClass

a regression test is:

Trait allSubInstancesDo:[:t |
   t methodDict do: [:m |
     self assert(m methodClass == t) ]]

> I attached a changeset that does the same as yours but for Pharo.
>

Thanks, i'll take a look.

>
>
>
>
> The only thing that is needed are a few lines in sourceCodeAt:. The method
> #traitOrClassOfSelector: returns the origin of a method -- this should work
> just fine for aliased methods too.
>
> HTH,
> Adrian
>
> On Dec 21, 2009, at 01:09 , Igor Stasenko wrote:
>
>> I just created a small changeset
>>
>> http://bugs.squeak.org/view.php?id=7432
>>
>> which gives me a long awaited feature:
>> to see in a browser, where the heck a given method comes from.
>>
>> If method comes from trait, a method's source tells me , from which one
>> exactly!
>>
>> Open a browser on Behavior clas and select an #addExclusionOf:to: method.
>> Usually you'll see:
>>
>> addExclusionOf: aSymbol to: aTrait
>>        self setTraitComposition: (
>>                self traitComposition copyWithExclusionOf: aSymbol to:
>> aTrait)
>>
>> But with my changes you'll see:
>>
>> " From: TAccessingTraitCompositionBehavior "
>> addExclusionOf: aSymbol to: aTrait
>>        self setTraitComposition: (
>>                self traitComposition copyWithExclusionOf: aSymbol to:
>> aTrait)
>>
>> in code pane.
>>
>> Same applies to traits themselves for instance, browse
>> TPureBehavior>>isAliasSelector:
>>
>> " From: TAccessingTraitCompositionBehavior "
>> isAliasSelector: aSymbol
>>        "Return true if the selector aSymbol is an alias defined
>>        in my or in another composition somewhere deeper in
>>        the tree of traits compositions."
>>
>>        ^(self includesLocalSelector: aSymbol) not
>>                and: [self hasTraitComposition]
>>                and: [self traitComposition isAliasSelector: aSymbol]
>>
>>
>> There is one problem , which requires better expertise than mine and i
>> need a help from Traits experts: an aliased methods.
>> I tried to find out, how to dig out the aliased method from
>> composition, and get its source to display in code pane .. but no
>> luck.
>> Please give me an advice, how a  #getSourceCodeBySelector:
>> method should be implemented for proper handling of aliases.
>> Currently, all aliased methods sources shown using decompiler:
>>
>> Behavior>>methodDictAddSelectorSilently: t1 withMethod: t2
>>        self basicAddSelector: t1 withMethod: t2
>>
>> Aliased methods, obviously, will require an additional info in source
>> header, like:
>>
>> " From: SomeTrait , originalSelector:  #blablba "
>>
>> --
>> Best regards,
>> Igor Stasenko AKA sig.
>>
>> _______________________________________________
>> Pharo-project mailing list
>> [hidden email]
>> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
>
>
>
>
>



--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: Re: [Pharo-project] Why you need new Method trailers? :)

Adrian Lienhard

On Dec 21, 2009, at 13:36 , Igor Stasenko wrote:

> 2009/12/21 Adrian Lienhard <[hidden email]>:
>> Hi Igor,
>>
>> This looks complicated...
>
> Hmm, i wonder, what Traits serve for, if requesting an original source
> code of method which being installed in specific behavior using
> specific selector
> becomes non-trivial task.

Well, it *is* trivial -- at least with the version of the Traits  
implementation in Pharo. See the changeset I attached.

Cheers,
Adrian

Reply | Threaded
Open this post in threaded view
|

Re: Re: [Pharo-project] Why you need new Method trailers? :)

Igor Stasenko
2009/12/21 Adrian Lienhard <[hidden email]>:

>
> On Dec 21, 2009, at 13:36 , Igor Stasenko wrote:
>
>> 2009/12/21 Adrian Lienhard <[hidden email]>:
>>>
>>> Hi Igor,
>>>
>>> This looks complicated...
>>
>> Hmm, i wonder, what Traits serve for, if requesting an original source
>> code of method which being installed in specific behavior using
>> specific selector
>> becomes non-trivial task.
>
> Well, it *is* trivial -- at least with the version of the Traits
> implementation in Pharo. See the changeset I attached.
>
will it work for aliased ones?

I found that in both trunk & pharo, aliases seem disfunctional.

create
Trait named: #Foo

create method:
Foo>>methodA .

create
Trait named: #Bar
using: Foo @ {#methodA -> #methodB }.

Bar shows a single method (methodA) ... but i expected to see #methodB instead.

Same for classes..

Object subclass: #Zork
uses: Bar
..
shows methodA, not methodB in browser.
I am doing something wrong?

> Cheers,
> Adrian
>
>



--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: [Pharo-project] Re: Why you need new Method trailers? :)

Adrian Lienhard
Yes, it also works for aliased methods.

It should be ... @ {#methodB -> #methodA} meaning methodB is an alias  
for methodA

Cheers,
Adrian


On Dec 21, 2009, at 13:50 , Igor Stasenko wrote:

> 2009/12/21 Adrian Lienhard <[hidden email]>:
>>
>> On Dec 21, 2009, at 13:36 , Igor Stasenko wrote:
>>
>>> 2009/12/21 Adrian Lienhard <[hidden email]>:
>>>>
>>>> Hi Igor,
>>>>
>>>> This looks complicated...
>>>
>>> Hmm, i wonder, what Traits serve for, if requesting an original  
>>> source
>>> code of method which being installed in specific behavior using
>>> specific selector
>>> becomes non-trivial task.
>>
>> Well, it *is* trivial -- at least with the version of the Traits
>> implementation in Pharo. See the changeset I attached.
>>
> will it work for aliased ones?
>
> I found that in both trunk & pharo, aliases seem disfunctional.
>
> create
> Trait named: #Foo
>
> create method:
> Foo>>methodA .
>
> create
> Trait named: #Bar
> using: Foo @ {#methodA -> #methodB }.
>
> Bar shows a single method (methodA) ... but i expected to see  
> #methodB instead.
>
> Same for classes..
>
> Object subclass: #Zork
> uses: Bar
> ..
> shows methodA, not methodB in browser.
> I am doing something wrong?
>
>> Cheers,
>> Adrian
>>
>>
>
>
>
> --
> Best regards,
> Igor Stasenko AKA sig.
>
> _______________________________________________
> Pharo-project mailing list
> [hidden email]
> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project


Reply | Threaded
Open this post in threaded view
|

Re: [Pharo-project] Re: Why you need new Method trailers? :)

Igor Stasenko
2009/12/21 Adrian Lienhard <[hidden email]>:
> Yes, it also works for aliased methods.
>
> It should be ... @ {#methodB -> #methodA} meaning methodB is an alias for
> methodA
>

So, the pattern is:

@ { #newName -> #oldName }

hmm.. then there is no wonder, since i interpret it differently ,
assuming that pattern is:

@ { #existingName -> #aliasedName }

because, as to me , by reading this expression its more natural to
think that operand to the left of  '->'  is the 'initial' or
'original' state, and to the right - intended state,
but not reverse.

Otherwise, maybe its worth to use an explicit & different selector:

@ { #aliasedName <- #existingName }.
And in #<- create something other than Association, which will make
trait definitions a bit more error proof , by not allowing
associations in composition.
(just guessing)

Btw, it would be good to assert at such point, saying to user that he
attempts to make an alias of non-existing method.

> Cheers,
> Adrian
>
>



--
Best regards,
Igor Stasenko AKA sig.