Modify AST to send a message on Character nodes

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

Modify AST to send a message on Character nodes

Julien Delplanque
Hi everyone,

I would like to modify the AST of a smalltalk expression compiled to
automatically send a certain message
when a node represents a Character (so the user does not have to write
the message sending explicitly).
I would of course add a special button in the menu you get when right
clicking in a playground so the user
knows it is a "special" do-it...

For example:
     $a.
would transform into an ast that the source code looks like
     $a aMessage

How can I do this? :)

Julien

Reply | Threaded
Open this post in threaded view
|

Re: Modify AST to send a message on Character nodes

Peter Uhnak
If you don't want to manually operate on AST, you can use Mark's Rewrite Tool ( http://screencast.com/t/LCEl0hFlhttps://medium.com/@peteruhnak/using-rewrite-tool-for-fixing-deprecated-code-12a595b291d8 )

As for ASTs I would be also curious about the answer, as this seems like it should be a simple task.

Peter

On Sat, Sep 12, 2015 at 2:24 PM, Julien Delplanque <[hidden email]> wrote:
Hi everyone,

I would like to modify the AST of a smalltalk expression compiled to automatically send a certain message
when a node represents a Character (so the user does not have to write the message sending explicitly).
I would of course add a special button in the menu you get when right clicking in a playground so the user
knows it is a "special" do-it...

For example:
    $a.
would transform into an ast that the source code looks like
    $a aMessage

How can I do this? :)

Julien


Reply | Threaded
Open this post in threaded view
|

Re: Modify AST to send a message on Character nodes

Mark Rizun
Hi everyone,

I believe you should be able to do this transformation with Rewrite Tool.
The only problem I see is that you want to do this only with single symbol. 
Because, in my tool you can do: 

transform: `#literal into: `#literal aMessage.
In this case `#literal means any literal, not only symbols.
In other words it will transform 

$a into  $a aMessage

Also, this rule will transform, for instance 
123 into 123 aMessage

If I understand right, you would like to do this programatically, so you don't need RewriteTool in that case.

Mark

2015-09-12 16:46 GMT+03:00 Peter Uhnák <[hidden email]>:
If you don't want to manually operate on AST, you can use Mark's Rewrite Tool ( http://screencast.com/t/LCEl0hFlhttps://medium.com/@peteruhnak/using-rewrite-tool-for-fixing-deprecated-code-12a595b291d8 )

As for ASTs I would be also curious about the answer, as this seems like it should be a simple task.

Peter

On Sat, Sep 12, 2015 at 2:24 PM, Julien Delplanque <[hidden email]> wrote:
Hi everyone,

I would like to modify the AST of a smalltalk expression compiled to automatically send a certain message
when a node represents a Character (so the user does not have to write the message sending explicitly).
I would of course add a special button in the menu you get when right clicking in a playground so the user
knows it is a "special" do-it...

For example:
    $a.
would transform into an ast that the source code looks like
    $a aMessage

How can I do this? :)

Julien



Reply | Threaded
Open this post in threaded view
|

Re: Modify AST to send a message on Character nodes

Thierry Goubier
In reply to this post by Peter Uhnak
Le 12/09/2015 15:46, Peter Uhnák a écrit :
> If you don't want to manually operate on AST, you can use Mark's Rewrite
> Tool ( http://screencast.com/t/LCEl0hFl ,
> https://medium.com/@peteruhnak/using-rewrite-tool-for-fixing-deprecated-code-12a595b291d8
> )
>
> As for ASTs I would be also curious about the answer, as this seems like
> it should be a simple task.

It is fairly easy if you write a RB AST visitor subclass, with a single
method / case to handle character literal.

Now, I'm sure you can use RBParseTreeRewriter to do it with a single call...

Thierry

> Peter
>
> On Sat, Sep 12, 2015 at 2:24 PM, Julien Delplanque <[hidden email]
> <mailto:[hidden email]>> wrote:
>
>     Hi everyone,
>
>     I would like to modify the AST of a smalltalk expression compiled to
>     automatically send a certain message
>     when a node represents a Character (so the user does not have to
>     write the message sending explicitly).
>     I would of course add a special button in the menu you get when
>     right clicking in a playground so the user
>     knows it is a "special" do-it...
>
>     For example:
>          $a.
>     would transform into an ast that the source code looks like
>          $a aMessage
>
>     How can I do this? :)
>
>     Julien
>
>


Reply | Threaded
Open this post in threaded view
|

Re: Modify AST to send a message on Character nodes

Thierry Goubier
In reply to this post by Mark Rizun
Hi Julien, Mark and Peter,

here is a RB approach:

| rewriter |
rewriter := RBParseTreeRewriter new
replace: ' `#aLiteral `{:node | node value isCharacter}'
        with: '`#aLiteral aMessage'; yourself.
rewriter executeTree: (RBParser parseExpression: 'Array with: $a
asciiValue with: $b with: #c with: d').
rewriter tree formattedCode

And the result is:

  'Array
        with: $a aMessage asciiValue
        with: $b aMessage
        with: #c
        with: d'

Need to keep all those snipets somewhere. And I think the chapter in
Pharo for the enterprise does not explain well the conditional stuff in { }.

Thierry


Le 12/09/2015 16:03, Mark Rizun a écrit :

> Hi everyone,
>
> I believe you should be able to do this transformation with Rewrite Tool.
> The only problem I see is that you want to do this only with single symbol.
> Because, in my tool you can do:
>
> transform: *`#literal* into: *`#literal aMessage*.
> In this case `#literal**means any literal, not only symbols.
> In other words it will transform
>
> $a into $a aMessage
>
> Also, this rule will transform, for instance
> 123 into 123 aMessage
>
> If I understand right, you would like to do this programatically, so you
> don't need RewriteTool in that case.
>
> Mark
>
> 2015-09-12 16:46 GMT+03:00 Peter Uhnák <[hidden email]
> <mailto:[hidden email]>>:
>
>     If you don't want to manually operate on AST, you can use Mark's
>     Rewrite Tool ( http://screencast.com/t/LCEl0hFl ,
>     https://medium.com/@peteruhnak/using-rewrite-tool-for-fixing-deprecated-code-12a595b291d8
>     )
>
>     As for ASTs I would be also curious about the answer, as this seems
>     like it should be a simple task.
>
>     Peter
>
>     On Sat, Sep 12, 2015 at 2:24 PM, Julien Delplanque <[hidden email]
>     <mailto:[hidden email]>> wrote:
>
>         Hi everyone,
>
>         I would like to modify the AST of a smalltalk expression
>         compiled to automatically send a certain message
>         when a node represents a Character (so the user does not have to
>         write the message sending explicitly).
>         I would of course add a special button in the menu you get when
>         right clicking in a playground so the user
>         knows it is a "special" do-it...
>
>         For example:
>              $a.
>         would transform into an ast that the source code looks like
>              $a aMessage
>
>         How can I do this? :)
>
>         Julien
>
>
>


Reply | Threaded
Open this post in threaded view
|

Re: Modify AST to send a message on Character nodes

Mark Rizun
Need to keep all those snipets somewhere. And I think the chapter in Pharo for the enterprise does not explain well the conditional stuff in { }.

I always forget the syntax of writing condition on nodes :)
Reply | Threaded
Open this post in threaded view
|

Re: Modify AST to send a message on Character nodes

Julien Delplanque
In reply to this post by Thierry Goubier
Great! Thats what I was looking for.

On 12/09/15 18:12, Thierry Goubier wrote:

> Hi Julien, Mark and Peter,
>
> here is a RB approach:
>
> | rewriter |
> rewriter := RBParseTreeRewriter new
> replace: ' `#aLiteral `{:node | node value isCharacter}'
>     with: '`#aLiteral aMessage'; yourself.
> rewriter executeTree: (RBParser parseExpression: 'Array with: $a
> asciiValue with: $b with: #c with: d').
> rewriter tree formattedCode
>
> And the result is:
>
>  'Array
>     with: $a aMessage asciiValue
>     with: $b aMessage
>     with: #c
>     with: d'
>
> Need to keep all those snipets somewhere. And I think the chapter in
> Pharo for the enterprise does not explain well the conditional stuff
> in { }.
>
> Thierry
>
>
> Le 12/09/2015 16:03, Mark Rizun a écrit :
>> Hi everyone,
>>
>> I believe you should be able to do this transformation with Rewrite
>> Tool.
>> The only problem I see is that you want to do this only with single
>> symbol.
>> Because, in my tool you can do:
>>
>> transform: *`#literal* into: *`#literal aMessage*.
>> In this case `#literal**means any literal, not only symbols.
>> In other words it will transform
>>
>> $a into $a aMessage
>>
>> Also, this rule will transform, for instance
>> 123 into 123 aMessage
>>
>> If I understand right, you would like to do this programatically, so you
>> don't need RewriteTool in that case.
>>
>> Mark
>>
>> 2015-09-12 16:46 GMT+03:00 Peter Uhnák <[hidden email]
>> <mailto:[hidden email]>>:
>>
>>     If you don't want to manually operate on AST, you can use Mark's
>>     Rewrite Tool ( http://screencast.com/t/LCEl0hFl ,
>> https://medium.com/@peteruhnak/using-rewrite-tool-for-fixing-deprecated-code-12a595b291d8
>>     )
>>
>>     As for ASTs I would be also curious about the answer, as this seems
>>     like it should be a simple task.
>>
>>     Peter
>>
>>     On Sat, Sep 12, 2015 at 2:24 PM, Julien Delplanque <[hidden email]
>>     <mailto:[hidden email]>> wrote:
>>
>>         Hi everyone,
>>
>>         I would like to modify the AST of a smalltalk expression
>>         compiled to automatically send a certain message
>>         when a node represents a Character (so the user does not have to
>>         write the message sending explicitly).
>>         I would of course add a special button in the menu you get when
>>         right clicking in a playground so the user
>>         knows it is a "special" do-it...
>>
>>         For example:
>>              $a.
>>         would transform into an ast that the source code looks like
>>              $a aMessage
>>
>>         How can I do this? :)
>>
>>         Julien
>>
>>
>>
>
>


Reply | Threaded
Open this post in threaded view
|

Re: Modify AST to send a message on Character nodes

Thierry Goubier
In reply to this post by Mark Rizun
Le 12/09/2015 18:20, Mark Rizun a écrit :
>     Need to keep all those snipets somewhere. And I think the chapter in
>     Pharo for the enterprise does not explain well the conditional stuff
>     in { }.
>
>
> I always forget the syntax of writing condition on nodes :)

I was missing the fact that the condition apply to the previous pattern
variable?

Conditions are very convenient, however, to execute code during the
matching part of the rewrite. Especially code with side effects ;)

Thierry

Reply | Threaded
Open this post in threaded view
|

Re: Modify AST to send a message on Character nodes

Peter Uhnak
| rewriter |
rewriter := RBParseTreeRewriter new
replace: ' `#aLiteral `{:node | node value isCharacter}'
        with: '`#aLiteral aMessage'; yourself.
rewriter executeTree: (RBParser parseExpression: 'Array with: $a asciiValue with: $b with: #c with: d').
rewriter tree formattedCode

This is cool! And so simple!

 Need to keep all those snipets somewhere. And I think the chapter in Pharo for the enterprise does not explain well the conditional stuff in { }.

P4E is still work-in-progress, no? So it still can be added there.
I think we need some better way to present the content of the books than just a "book"... like with side menu showing topics within a chapter, search, or whatever.
Maybe it could be made available somewhere with Guille's Ecstatic generator.

Peter
Reply | Threaded
Open this post in threaded view
|

Re: Modify AST to send a message on Character nodes

Marcus Denker-4

On 12 Sep 2015, at 19:23, Peter Uhnák <[hidden email]> wrote:

| rewriter |
rewriter := RBParseTreeRewriter new
replace: ' `#aLiteral `{:node | node value isCharacter}'
        with: '`#aLiteral aMessage'; yourself.
rewriter executeTree: (RBParser parseExpression: 'Array with: $a asciiValue with: $b with: #c with: d').
rewriter tree formattedCode

This is cool! And so simple!


This can be combined with the compiler transform plugins of Opal:

-> make subclass of OCCompilerASTPlugin
-> put your code in a method called #transform

now when you override #compiler on the class side of a class like this:

compiler
^super compiler addPlugin: ASTPluginMeaningOfLife.

the plugin will be active for the hierarchy, which means that all code compiled will be transformed.

There is a simple example ASTPluginMeaningOfLife in the image.

Marcus

 
Reply | Threaded
Open this post in threaded view
|

Re: Modify AST to send a message on Character nodes

Thierry Goubier
Le 13/09/2015 08:56, Marcus Denker a écrit :

>
>> On 12 Sep 2015, at 19:23, Peter Uhnák <[hidden email]
>> <mailto:[hidden email]>> wrote:
>>
>>     | rewriter |
>>     rewriter := RBParseTreeRewriter new
>>     replace: ' `#aLiteral `{:node | node value isCharacter}'
>>             with: '`#aLiteral aMessage'; yourself.
>>     rewriter executeTree: (RBParser parseExpression: 'Array with: $a
>>     asciiValue with: $b with: #c with: d').
>>     rewriter tree formattedCode
>>
>>
>> This is cool! And so simple!
>>
>
> This can be combined with the compiler transform plugins of Opal:
>
> -> make subclass of OCCompilerASTPlugin
> -> put your code in a method called #transform
>
> now when you override #compiler on the class side of a class like this:
>
> compiler
> ^super compiler addPlugin: ASTPluginMeaningOfLife.
>
> the plugin will be active for the hierarchy, which means that all code
> compiled will be transformed.
>
> There is a simple example ASTPluginMeaningOfLife in the image.

Cool. Intriguing.

I'm sure I can use it to:
- patch problematic code on the fly without registering an override
- change the semantics of some smalltalk statement (so that a := becomes
self a: or anything else)

Would it be possible to couple it with Clement work to have some ability
to pre-compile some code in specific classes (strength reduction, once
literals) where we know that this is valuable?

It would also be nice to have a way not to write bytecode by hand, like,
say, in the slots example of a few days back.

Oh, ok, for the literal stuff, I think I know how to do it:

In a method:
- replace target expression with symbol literal.
- evaluate target expression in isolation, store value.
- compile method with symbol literal.
- in compiled method, replace symbol literal with value stored above.

Would that work?

Thierry

>
> Marcus
>


Reply | Threaded
Open this post in threaded view
|

Re: Modify AST to send a message on Character nodes

Marcus Denker-4

>
> Cool. Intriguing.
>
> I'm sure I can use it to:
> - patch problematic code on the fly without registering an override
> - change the semantics of some smalltalk statement (so that a := becomes self a: or anything else)
>

Yes, it is for “evil” experiments that can not be done else (short of changing the compiler itself).

e.g. last week for an experiment, I wanted a form of “super” where it is not “self, but start lookup in superclass”, but instead
“this object, do a send to it but start lookup in the superclass”.  There are no messages called #super in the image, so you can
so that by transforming all

myObject super doSomething

into

myObject perform: #doSomething withArguments: #() inSuperclass: myObject class superclass.

The needed Opal plugin has this #transform method:

transform
        | superSends new  |
        superSends := ast sendNodes select: [ :each | each selector = #super ].
        superSends do: [ :spnode |
                new := RBMessageNode
                        receiver: spnode receiver copy
                        selector: #perform:withArguments:inSuperclass:
                        arguments: {RBLiteralNode value: spnode parent selector copy .
                                RBArrayNode statements: spnode parent arguments .
                                RBMessageNode receiver: (RBMessageNode receiver: spnode receiver copy selector: #class) selector: #superclass}.
         spnode parent replaceWith: new
        ].
        ^ast

> Would it be possible to couple it with Clement work to have some ability to pre-compile some code in specific classes (strength reduction, once literals) where we know that this is valuable?
>
Good question….

> It would also be nice to have a way not to write bytecode by hand, like, say, in the slots example of a few days back.
>
Yes, the byte code writing for Slots is just a solution that works *today*. With a runtime optimizer you could instead always generate the reflective slow version
and let Sista optimise it.

> Oh, ok, for the literal stuff, I think I know how to do it:
>
> In a method:
> - replace target expression with symbol literal.
> - evaluate target expression in isolation, store value.
> - compile method with symbol literal.
> - in compiled method, replace symbol literal with value stored above.
>
> Would that work?
>

Hmm… messages to known objects without side effect could be evaluated by the compiler.
What makes it hard ist mostly debugging: mapping the generated code back to the original
source….

        Marcus