2015-11-09 13:58 GMT+01:00 Mariano Martinez Peck <marianopeck@gmail.com>:
On Mon, Nov 9, 2015 at 6:07 AM, Thierry Goubier <thierry.goubier@gmail.com
wrote:
2015-11-09 6:38 GMT+01:00 Thierry Goubier <thierry.goubier@gmail.com>:
Hi Mariano,
Le 09/11/2015 01:13, Mariano Martinez Peck a écrit :
On Fri, Nov 6, 2015 at 1:59 PM, Mariano Martinez Peck <marianopeck@gmail.com <mailto:marianopeck@gmail.com>> wrote:
...
Hi Thierry,
I am trying to achieve a similar case like the one I commented in this post but I am unable to find the way. Previously I wanted to replace say the literal #oldSelector to #newSelector. Now, I need to use regular expressions. I mean, I would need to find matches of '*oldSelector*' and do the replace with 'newSelector'. For example, the search may find '*pre*oldSelector*post*' and I want it to be replaced by '*pre*newSelector*post'. *And of course, I don't know in advance what pre and post strings there could be.
What you need to do there is to use a match block after the @selector
`{:node | node selector matches: '.*oldSelector.*'}
Which would mean that your patterns become:
rewriter replace: '``@object `oldSelector {:node | node selector matches: '.*oldSelector.*'}' with: '``@object `newSelector {:node | node selector }'.
OK, thanks for the explanation.
Wait, not entirely sure. I think you need to add a dictionary in the block to give the with: argument the pre and post string. And I'm not sure about the regular expression above as well.
I need to have access to the SmaCC code source, so I'll answer to you a bit later.
Ok, here is a first try that make a change pre and post included:
| tree | RBParseTreeRewriter new replace: '`@object `oldSelector `{:node | node selector asString matchesRegex: ''.*oldSelector.*''}' with: '`@object newSelector'; executeTree: (tree := RBParser parseMethod: 'DoIt ^ [:proxy | proxy at: #oldSelector. proxy preoldSelector. proxy oldSelectorAnotherMethod. proxy do: ''oldSelectorAndSomething''. "a comment with #oldSelector " ]'). tree newSource
But it does not replace yet the right selector.
Yes, this one replaced both #oldSelector and #preoldSelector to #newSelector right?
For that, I will recreate a message send:
| tree | RBParseTreeRewriter new replace: '`object `oldSelector `{:node | node selector asString matchesRegex: ''.*oldSelector.*''} `@args' with: '`{RBMessageNode receiver: `object selector: (`oldSelector selector copyReplaceAll: ''oldSelector'' with: ''newSelector'') asSymbol arguments: `@args}'; executeTree: (tree := RBParser parseMethod: 'DoIt ^ [:proxy | proxy at: #oldSelector. proxy preoldSelector. proxy oldSelectorAnotherMethod. proxy do: ''oldSelectorAndSomething''. "a comment with #oldSelector " ]'). tree newSource
Thanks Thierry for your efforts. Very much appreciated. I tried the above but still did not work. I executed the very same example of yours (I pasted it) but the #newSource was:
DoIt ^ [:proxy | proxy at: #oldSelector. proxy preoldSelector. proxy oldSelectorAnotherMethod. proxy do: 'oldSelectorAndSomething'. "a comment with #oldSelector " ]
I am trying in Pharo 4.0. And you?
Pharo 4.0 as well. I made a mistake in my example :(, so I'm adding more test cases to check ;). | tree | RBParseTreeRewriter new replace: '``@object `oldSelector `{:node | node selector asString matchesRegex: ''.*oldSelector.*''}' with: '`{RBMessageNode receiver: ``@object selector: (`oldSelector copyReplaceAll: ''oldSelector'' with: ''newSelector'') asSymbol arguments: #()}'; executeTree: (tree := RBParser parseMethod: 'DoIt ^ [:proxy | proxy at: #oldSelector. proxy preoldSelector. self preoldSelector oldSelectorPost. proxy preoldSelector: proxy. proxy oldSelectorAnotherMethod. proxy do: ''oldSelectorAndSomething''. "a comment with #oldSelector " ]'). tree newSource.
Now, I haven't tested with arguments on the message.
Yes..that's a different story. But for the time being, I can live without that :)
I'm trying it, but I end up in a subscriptOutOfBounds: error :(
Look how you can use pattern variables inside the blocks :)
This is very cool and extremely powerfull.
Yes, I saw it. I wasn't aware of that. Super powerful but I think it has some learning curve to master it, right?
Me too... Time to ask for some help. Thierry
Thierry
Also..do you know where can I find some more info about RB? For example, if I read this:
rewriter replace: '``@object ' , oldSeletor with: '``@object ' , newSelector.
Where can I read that ``@object means XXX .. ?
There is a first level of explanation in the Pharo for the Enterprise book; but, yes the pattern language is fairly complex.
Are you going to Smalltalks? John Brant is there and will give a talk on RB and SmaCC (two talks, I believe).
Thierry
Thanks in advance!
Or a cascade: a RBParseTreeSearcher which matches blocks; on each block node you activate a rewriter.
However, there is an issue in rewriting blocks contents, because it supposes that the method defining the block is recompiled; it's significantly harder to make changes to the code of live blocks (change the bytescode itself? What if the block has multiples instances?).
Thierry
If not, I think my easiest path is to automatically compile dummy/temporal classes/methods from the rules, perform the refactor, then move source from methods to block closures, and finally remove created classes.
Any pointer is appreciated.
best,
-- Mariano http://marianopeck.wordpress.com
-- Mariano http://marianopeck.wordpress.com
-- Mariano http://marianopeck.wordpress.com
-- Mariano http://marianopeck.wordpress.com