It took me many hours (and too much coffee) to realized all of this and I want to share with you some tips to help you define the matching pattern you really want to aplly
- Pay attention to the dots! `sel “@.Statements1. self subclassResponsibility. “@.Statements2 is very different to: `sel “@.Statements1 self subclassResponsibility. “@.Statements2
- Matching the selectors is not a simple task
- Is not the same matching an expression that matching a method one line can change everything!
If you say:
</pre> matcher <strong>matchesMethod:</strong> aMatchingExpression
You are particullary saying that aMatchingExpression should be parsed doing: RBParser parseRewriteMethod: aMatchingExpression instead of RBParser parseRewriteExpression: aMatchingExpression
And this mean that:
- Your string is well formed, if you have a syntactic error you will see the window saying that the expression is not correct
- Your string has a method structure
- Your metavariables will play as a message send or as a variable depending on the context
A fast example, imagine this expression:
Let’s play we are the a cool parser and someone told us hey… this is a string, but you should interpret it as a mehod… so:
`anObject = the selector so I want all the unary methods
size = a variable named ‘size’ because it can’t be a parameter because my message is unary, it’s not a variable definition it has to be a variable.
So as a cool parser I say that I will match with all the unary methods that the body is just an unique sentence that contains a variable called ‘size’
Now, imagine someone told us this is an expression… so:
`anObject = the object, I do not know nothing, only that here goes an unique object
size = before I had an object so here I should have an invocation for the message #size.
So as a cool parser I say that I will match with all the methods the expressions that sends the message size
- If you look for a particular message send you should care about the structure:
- Do you want all the senders? for defining the expresion is not the same object messageToFind that object message anotherMessage messageToFind moreMessages
- It can be inside a block?
- It can be invoked as a symbol? object perform: #messageTofind
- It can be in any part of method? (the first sentence? after that can be more message sends?)
- The matcher uses pattern matching! You give an alias and when it matches then is bounded and that’s
`sel “@.Statements1. self messageTofind. “@.Statements1
Does not match with:
example self oneMessage. self messageTofind. self otherMessage.
Because we use the same variable name! Statements1 and in the matching it bounded to the statement self oneMessage that is NOT identical to self otherMessage so we don’t have the match.
But! It should match with:
example self oneMessage. self messageTofind. self oneMessage.
But this feature is really cool if you want to search repeated code in the same method…
- If you are matching inside a method, does the method defines temporary variables?
- Remember that when you parse if the variable definition is wmpty it get’s ignored but if you do not put it in your pattern and the method defines a temp you are excluding it.
example |aTempVar| self messageTofind.
matches with method pattern:
`sel |`@vars| `object messageTofind
but does NOT match with:
`sel `object messageTofind
In the end I can understand that all this “tinny” details are very important… but if you want to match a common case it can be really ugly and it’s VERY easy to do it wrong.
But do not worry too much one big goal for Flamel it’s to offer a simple API to avoid all this commons errors.