> On 5 Jun 2024, at 10:22, Tim Mackinnon <tim@testit.works> wrote:
> 
> Hi Stef - I saw that blog post - which looks like its essentially the help 
> text that comes up in the rewrite tool when you press the help button. I was 
> going to submit to add to the help text as I think a better example that 
> pulls all the ideas together is helpful. However, I have realised the Rewrite 
> tool is not the main pharo-project repo and comes under NewTools? How do I 
> find out where that repo is to submit a pr?
> 
> I think the help button on that tool should launch the normal doc browser 
> with the text in the normal help format vs a seperate window? The help 
> browser could probably use some work but at least if help is one place it all 
> will get updated together?

Yes it can be nice to have a single documentation so that when we improve it 
will benefit directly 
to the tools. 

> 
> I was going to propose the following example which helped me a lot -  if I 
> wanted to rewrite how logging was done in the following example (and separate 
> the Transcript line into 2 lines):
> 
> appLog: anObject
> "Log anObject for debugging"
> | date |
> date := Date today.
> Transcript traceCr: 'debug: ', date printString, anObject printString.
> date isLeapYear ifTrue: [ ^nil ].
> ^anObject
> 
> I could write a match expression like this:
> 
> appLog: `arg
> | `@temps |
> `.@before.
>     Transcript traceCr: `#str , `@exp1, `@exp2.
> `.@after
> 
> and a rewrite rule like this:
> 
> appLog: `arg
> | `@temps |
> `.@before.
>     Transcript cr; traceCr: `#str, `@exp1.
>     `arg traceCr.
> `.@after
> 
> I think this demonstrates most of the concepts that caught me out - namely: 
> you need to call out the variable matching explicitly -= the .@before (list 
> statement matching doesn't match variables - and using @temps will match 0 or 
> more vars, so its safer to include it if matching expressions that may have 
> any otherwise nothing will match.
> 
> If you want to match a string you need to match it as a literal e.g. `#str.
> 
> You may need to match 0 or more statements before and after your target 
> expression hence  `.@before and `.@after but its important to include the 
> trailing "." on the @before.  to cut off before the expression you are trying 
> to match next.
> 
> I didn't fully understand in my example is why I can't match the remaining 
> statements after the transcript string using just `.@exp1. I seem to have to 
> call out both expressions which I now realise (and worth documenting) is 
> because the AST for that line is actually VariableNode(transcript) + 
> MsgNode(MsgNode(Literal+MsgNode(exp1)), MsgNode(exp2) and so you have to call 
> them all out to match things or match the entire sequence with @stmnt (in my 
> case I wanted to pick them apart).  I think the top tip in all of this is to 
> use the handy source code ast inspector to help you reason on the structure.
> 
Sometimes this is arcane to me. 
I think that I would have to concentrate and do a full review of code using 
tons of new tests :)


> The above is probably the gist of the kinds of docs we would need, and happy 
> to submit a pr with this in it.

please do. 
> 
> On Wed, 5 Jun 2024, at 6:35 AM, stephane ducasse wrote:
>> Hi Tim
>> 
>> This is on my todo to have a serious look at the pattern matcher 
>> Now one of the few documentation that we have in the 
>> blog and I ported it in the blog post in /doc folder.
>> 
>> S
>> 
>> 
>> 
>> 
>>> On 4 Jun 2024, at 01:35, Tim Mackinnon <tim@testit.works> wrote:
>>> 
>>> Hey Gabriel - thanks for chipping in - you've made me realise that its 
>>> perhaps easier to give a simpler example (for the multiple replacement)., 
>>> and while trying to explain in simpler terms I managed to solve the problem 
>>> myself - but it does demonstrate the docs around this need a bit more work 
>>> as I didn't find it easy to reason on.
>>> 
>>> I am still confused what the setting  "this rule is for a method" does - so 
>>> am keen for someone to shed light.
>>> 
>>> Anyway for my example it seems that I have to be very specific in how I 
>>> match things for example I had to use the search pattern:
>>> 
>>> taskbarButtonMenu: `arg
>>>   | `@temps |
>>>   `.@before.
>>> 
>>>   moveSubmenu
>>>     addToggle: 'Move right' translated
>>>     target: self
>>>     selector: #taskbarMoveRight
>>>     getStateSelector: nil
>>>     enablementSelector: #canBeMovedToRight.
>>> 
>>>   `.@after
>>> 
>>> And it took me ages to realise that I have to specify the temp vars 
>>> matching, and also understand that the @before and @after both needed the 
>>> "." to represent lists of expressions both before and after and then the 
>>> really subtle  "." after @before which I guess prevents greedy matching.
>>> 
>>> With all of that in place,  could then have the write rule add an extra 
>>> statement after the moveSubmenu (or as many as I want)
>>> 
>>> e.g.
>>> 
>>> taskbarButtonMenu: `arg
>>>   | `@temps |
>>>   `.@before.
>>> 
>>>   moveSubmenu
>>>     addToggle: 'Move right' translated
>>>     target: self
>>>     selector: #taskbarMoveRight
>>>     getStateSelector: nil
>>>     enablementSelector: #canBeMovedToRight.
>>> 
>>>   moveSubmenu
>>>      addToggle: 'Move to...' translated
>>>     target: self
>>>     selector: #taskbarMoveTo
>>>     getStateSelector: nil.
>>> 
>>>   `.@after
>>> 
>>> 
>>> I'm curious now whether there is a more efficient way to do what I have 
>>> done? Possibly the {} syntax could help now i've figured out the basic 
>>> matching.
>>> 
>>> I really find it easy to confuse that if you don't specify the @temps 
>>> section that can leave out a lot of matches (it essentialy means 0 or more 
>>> temps vs. leaving it out means no temps at all). This is a trap that the 
>>> docs should call out better I think.
>>> 
>>> Anyway - now I just need to figure out how to do this programatically - and 
>>> possibly I can write a few more useful refactorings I've also thought it 
>>> was odd that were missing.
>>> 
>>> On Mon, 3 Jun 2024, at 12:19 PM, Gabriel Cotelli wrote:
>>>> I've used the rewrite tool extensively but never tried to create more than 
>>>> one expression from the original one. I think that this probably won't 
>>>> work because in your example the code is just statements, but the matching 
>>>> expression can be in code like this:
>>>> 
>>>> self doSomething: (
>>>> moveSubmenu
>>>>    addToggle: 'Move right' translated
>>>>    target: self
>>>>    selector: #taskbarMoveRight
>>>>    getStateSelector: nil
>>>>    enablementSelector: #canBeMovedToRight)
>>>> 
>>>> and in this case, you cannot replace this with two statements. So I'm 
>>>> tempted to say that what you want is not supported.
>>>> 
>>>> Regards, Gabriel
>>>> 
>>>> On Mon, Jun 3, 2024 at 5:44 AM Tim Mackinnon <tim@testit.works> wrote:
>>>> 
>>>> I've never really learned the rewrite tool but while waiting for changes 
>>>> to propagate through P12, I thought maybe I could use it to safely patch 
>>>> changes until there are official updates (and it was a good chance to get 
>>>> more familiar with it).
>>>> 
>>>> I thought there was more documentation available for how it works 
>>>> (interested in any old articles - but the online help in P12 is ok - 
>>>> although it doesn't display in markdown - in fact give there is markdown 
>>>> support now - I am a bit confused what should appear more readable these 
>>>> days - and how to fix/contribute changes to help).
>>>> 
>>>> This aside - I wanted to patch the SystemWindow>>taskbarButtonMenu: (and 
>>>> add my fix to move tabs to any position).
>>>> 
>>>> I started writing the following search expression - the find the last call 
>>>> to #addToggle:... method call that has a literal referencing 
>>>> #canBeMovedRight - as I want to add my new menu item after it.
>>>> 
>>>> e.g.
>>>> 
>>>> moveSubmenu `@addToggle: `{ :node | node isLiteralNode and: [ node value = 
>>>> #canBeMovedToRight] } 
>>>> 
>>>> but I'm not sure my {} filter block is ever called, as the above matches 
>>>> both addToggle:... calls, and not the one I'm after? I don't understand 
>>>> this - any have ideas on the proper syntax for generic matching?
>>>> 
>>>> Anyway - I decided that in my case there is only one - so I can match it 
>>>> explicitly and so I  search on the full call:
>>>> 
>>>> and I entered this:
>>>> moveSubmenu
>>>>    addToggle: 'Move right' translated
>>>>    target: self
>>>>    selector: #taskbarMoveRight
>>>>    getStateSelector: nil
>>>>    enablementSelector: #canBeMovedToRight.
>>>> 
>>>> Which matches exactly - then I want to replace the single statement with 2 
>>>> statements e.g.
>>>> 
>>>> moveSubmenu
>>>>    addToggle: 'Move right' translated
>>>>    target: self
>>>>    selector: #taskbarMoveRight
>>>>    getStateSelector: nil
>>>>    enablementSelector: #canBeMovedToRight.
>>>> 
>>>> moveSubmenu
>>>>    addToggle: 'Move to' translated
>>>>    target: self
>>>>    selector: #taskbarMoveTo
>>>>    getStateSelector: nil.
>>>> 
>>>> 
>>>> However this gives an error in the rewrite tool (actually it results in a 
>>>> zero change, that then gives an error for EpMonitor).
>>>> 
>>>> But my question is - why can't you rewrite a single statement to multiple 
>>>> ones? I have noticed that in this case I can cascade the message send - 
>>>> and this then rewrites properly - so it looks like it wants to replace a 
>>>> single node with a single node.
>>>> 
>>>> If I couldn't cascade - It seems I would have to rewrite with something 
>>>> like: [ "put multiple expressions here" ] value.
>>>> 
>>>> This seems an odd choice - but am I missing something obvious? 
>>>> 
>>>> Do you have to do what I'm proposing in 2 steps - rewrite to a block (or 
>>>> some equivalent) and then a 2nd rewrite to simplify the expression  (like 
>>>> a refactor step) - so its more provably correct?
>>>> 
>>>> I'm just curious on this - as it seemed time to learn this properly?
>>>> 
>>>> Tim
>> 
>> 
>> Stéphane Ducasse
>> http://stephane.ducasse.free.fr
>> 06 30 93 66 73
>> 
>> "If you knew today was your last day on earth, what would you do 
>> differently? ....ESPECIALLY if, by doing something different, today might 
>> not be your last day on earth.” Calvin & Hobbes

Stéphane Ducasse
http://stephane.ducasse.free.fr
06 30 93 66 73

"If you knew today was your last day on earth, what would you do differently? 
....ESPECIALLY if, by doing something different, today might not be your last 
day on earth.” Calvin & Hobbes





Reply via email to