Re: How to write a simple Code Rewrite for x -> self x?
Posted by John Brant on Mar 24, 2006; 8:28pm
URL: https://forum.world.st/How-to-write-a-simple-Code-Rewrite-for-x-self-x-tp3377980p3378013.html
TimM wrote:
> I am kind of suprised by the replace pattern complexity. For example
> given how SmaCC lets me easily name expressions and then use that name
> in an action, I was kind of expecting the same from the Code Rewriter?
> Is this just something I wouldn't normally need to do - or is it just
> that you never thought of this? I can't imagine that its technically
> hard - but maybe I wouldn't normally need to do it.
The problem is that the code rewriter works with parse tree nodes not
strings. You can't use a variable parse node as the selector of a
message node. Selectors must be symbols.
I have worked on another system that used the rewriter's searching, but
the replacement expression was string based. When you reference a
matched node, it would just print the matched code in the output. This
would allow you to convert a variable node to a message by using
something like "`var" -> "self `var". This approach seems simpler, but
doesn't work for cascaded messages -- the matched node might not be
contiguous for a string replacement. Also, it is common to forget to add
parentheses in the replacement expression. For example, if you search
for "`@foo bang: `@bar" and replace it with "`@foo ! `@bar", you would
get invalid results when the argument is a binary message (e.g., "var
bang: 1 + 2" becomes "var ! 1 + 2" instead of "var ! (1 + 2)").
If we consider your example, you don't really want to convert all
references to variables to be messages sends. You only want to convert
the instance variable references. Instead of using the code rewriter in
the browser, you could use it directly:
-------------
| class rule |
class := SmaCCParser.
rule := SmalllintChecker
runRule: (TransformationRule
rewrite:
(class instVarNames collect: [:each | Array with: each , ' := ``@a'
with: 'self ' , each, ': ``@a']) ,
(class instVarNames collect: [:each | Array with: each with: 'self '
, each])
methods: false
name: 'Convert inst vars refs to messages')
onEnvironment: (BrowserEnvironment new forClassHierarchyFrom: class).
RewriteChangesBrowser showOn: rule changes
-------------
This will convert all instance variable references in SmaCCParser and
its subclasses to go through accessors (of course, you'll need to define
them first). Instead of looking at all variable references, this is only
looking at variables defined in SmaCCParser.
John Brant