Abstraction process

If take a look in the metavariable patterns you can see that it can get as complex as you want.

But, let’s focus in a particular token. We end up with a metavariable, but we can see a pattern from simplicity to complexity:

1. Just abstract the token as a metavariable: we do not care if the method contains the exact word we want everything that contains something acting as that.


aVariable size.

Maybe we do not care about who is the sender of the message #size. In order to do that, we will abstract the variable ‘aVariable’ as a metavariable:

`object size

2. Abstract a list of tokens: we do not care if the method cointain not only one element also a lot of elements.


aVariable size.

If the pattern is `object size we are too specific because we are only matching the send to size whom receiver is an object, if we have something like this:

(aCollection select: #even) asOrderedCollection size.

Is not a result, if we want that, we have to specify that we do not care:

`@lotOfStuff size

3. Abstract a recursive pattern: still maybe we want matches if the pattern is repeated

aVariable size size.

If our pattern is: `object size, this does not match. If it’s: `@some size we have one match when some = ‘aVariable size’.

If we put a recursive pattern:

“@some size

We have two matches: one when some=’aVariable size’ and another when some= ‘aVariable’

4. Abstract a statement: Maybe we do not even care about the hole statement, and for this we should use the dot.



We can think that in the abstraction patterns you have a variety in abstraction, since one more concret with more information until one more abstract.

And for that we can conclude that we have a flow during the metavariable abstraction:

NoAbstraction <=> Simple <=> List <=> Recursive <=>Statement

In order to support this in flamel I’ve added #FlamelAbstractionStep that basically have 3 main responsabilities:

  • next step: abstract
  • previous step: unAbstract
  • pattern: pattern

You can take an expression, obtain the AST representation and then just send to the node the messages abstract and unAbstract to let the abstration proccess to continue, once you finish just use the expression builder to obtain the expression.


| searchExpression variable root expression |
expression := 'aVariable aMessage'.
root := RBParser parseExpression: expression.
variable := root receiver .
variable abstractOnMatching.
searchExpression := FlamelSearchExpressionBuilder new searchExpressionFor: root.
self assert: searchExpression equals: '`aVariable aMessage'

If we do:

variable variable abstractOnMatching.
variable variable abstractOnMatching.

We will end up with: `@aVariable aMessage.

If you want to get fun annotating nodes I added some protocols to maintain the state in a node:

  • abstractOnMatching: instead the source code for the node we are interested in the metavariable. Each time you say abstractOnMatching you are going up in the matching steps
  • deleteOnMatching: when we want to match, we should not include the code contained inside the node
  • ignoreOnMatching: we go to the last step in the matching process
  • unAbstractOnMatching: we want the previous step for the metavariable

I Also wrote a visitor to genrate the matching expression, so in order to obtain the expression, you can evaluate:

FlamelSearchExpressionBuilder new searchExpressionFor: root.

Define a simple rule for matching

Ok let’s start to understand the rewrite engine.

Let’s do it with an example, our goal:Find all the methods that send the consecutives mesages: #globlals #at:

In our example we want as result:


findClassesForCategories: aCollection
| items |
aCollection isEmpty
ifTrue: [ ^ self baseClass withAllSubclasses asSet ].
items := aCollection
gather: [ :category |
((Smalltalk organization listAtCategoryNamed: category)
collect: [ :each | Smalltalk globals at: each ])
select: [ :each | each includesBehavior: self baseClass ] ].
^ items asSet

But not with this variation:

findClassesForCategories: aCollection
| items |
aCollection isEmpty
ifTrue: [ ^ self baseClass withAllSubclasses asSet ].
items := aCollection
gather: [ :category |
((Smalltalk organization listAtCategoryNamed: category)
collect: [ :each | Smalltalk globals at: each ifAbsent: [ "ignore" ]])
select: [ :each | each includesBehavior: self baseClass ] ].
^ items asSet

Why? because in the second example we send the messages #globals (ok we want this!) but then we send #at:ifAbsent: (we don’t want this)

Ok so… Which object do I send wich message to find my “problematics” methods?

Which object?
The answer is very simple a RULE… For each rule you should extend one flavor of rule and define what you want to do. Sounds easy let’s check the rules hierarchy

All of those are abstract classes, so we will take a look into them and choose the one that is better for our case.

  • RBLintRule: defines the protocol used for execute a rule.
    This is a very general class, doesn’t define:
    – what to do when we are cheeking a class, for this we have to implement: #checkClass:. In our case we don’t care about the class, so we can let the default that does nothing with the class
    – what to do when we are cheeking methods, for this we have to implement: #checkMethod:.
    In our case we should obtain the source code form the method and search in the source code all the variants for the consecutive messages #globals #at:, an inocent version of this can be:
    A way to do it:

    checkMethod: aContext
    (aContext compiledMethod source findString: 'globals at:') ~= 0
    ifTrue:["we have a match in aContext selectedClass>> aContext selector we should handle it"]

    I said that it is an innocent implementation because if we have a method with the code: “(…) globals  “yes a comment here!”     at: (…)” or “(…) globals           at: number” we aren’t causing a match and if we have: “(…) globals at: something ifAbsent: (…)” we are and we shouldn’t.
    Probably we should allways use one subclass of LintRule with more features implemented otherwise we have to extend LintRule to define what to do in case of matching, model a result, transforming code (…)

  • RBBasicLintRule: it’s another abstract class that adds a result associated to a rule. We still should redefine checkMethod and/or check class but we have a proposal for a result:
    checkMethod: aContext
    (aContext compiledMethod source findString: 'globals at:') ~= 0
    ifTrue:[result addClass: aContext selectedClass selector: aContext selector ]

    This can be a good extension point, but again… you have a lot to implement here.

  • RBBlockLintRule: it’s an abstract class, that by default specifies that the resultClass corresponds to a selector environment.
    This class doesn’t add a lot of behavior but we reduce errors related to the result handling.
  • RBParseTreeLintRule: here is where everything gets interesting.
    The main point in this class is to offer an implementation for #checkMethod: the implementation motivation is to check methods using ast’s representations.
    We will have a wanted tree and then we will obtain the AST for the checked method, in order to find a match we observe if the wanted tree is subtree of the method tree.
    Also it’s posible to define metavariables where we can specify that we want to match with a node type but not necesary the value of it.
    In our example our matching expression will look like:

    “@lotOfStuffBefore globals at: “@lotOfStuffAfter

    With this expresion we are saying:
    –  “@lotOfStuffBefore: ignore everything before globals (receiver / message send):
    –   “@lotOfStuffAfter: ignore everything after at: (object / messages)
    (For more information about metavariables see my first post)
    The solution implemented for the check method introduces new objects:

    Matcher: Is the responsable for visit an AST and verify the matches. Is the matcher the one who interprets the matching expressions. First of all we have to specify if we are matching with a method (matchesMethod: aString do: aBlock) or an expreesion (matches: aString do: aBlock) pattern.
    We can add more than one matching expression, it’s very important to know that every time we add an expression in the matcher inside we are adding a RBSearchRule for that expression.
    When the tree rule sends the message executeTree: to the matcher at the end the matchers iterates over all the rules visiting the nodes delegating in the RBSearchRules to perform the match.
    It’s important to say that the search rules aren’t deleted automatically, so, if you want to reuse the object probably you should reset the rule, reseting the matcher.
    ParseTreeEnvironment: Is an specialized SelectorEnvironment that makes it possible to detect the selection interval for an expression inside the method, using the ast matcher
    This class is still abstract because we should categorize it, adding a name and initilize the rule with the matching expression patterns.
    In functionality is almost the same that before but we have other abstraction level, the result is handled automatically, and we don’t have to worry about checking a method or a class only to define the desired matching expression.

  • RBCompositeLintRule: Is just a composite for rules.
  • RBTransformationRule: The main idea here is to produce a transformation in the system, for this implements: #checkMethod: in a similar way that RBParseTreeLintRule the diference is that if we find a match we will produce a modification in the code and then we change the method with the new version of the code (recompiling the new method).
    In order to solve this the rule adds some objects:
    RBParseTreeEnvironment: with all the results, the results are: RBAddMethodChange to track a change in a method
    RBParseTreeRewriter: It’s a subclass off the matcher (RBParseTreeSearcher) and again the main point is that this is a visitor that works over a method AST changing it depending in the matching and transforming expression.
    The transforming expression also works with metavariable and usually we use the metavariables defined in the matching expression to specify the transformation.


  1. Before start you should choose if you want to:
    perform a search
    do a match
  2. Implement your rules because all of them are abstract, probably you will end up using the Tree rules because are more automatics and powerfull than to basics.
  3. When you are defining your rule:
    – give a name for it
    – define if you will use a method or an expression type pattern
    – write your patterns and add them to the rule
    – if you are in a search rule to the matcher
    – if you are in a transformation rule rewriteRule
    – define what to do with a result
  4. run your rule
  5. use your results
  6. if you want to reuse it reset your rule, again if it’s a search rule, reset the matcher, if it’s a transformation rule the rewriteRule.

In our example:

  • we want to match, so let’s create an object that extends: RBParseTreeLintRule:
 RBParseTreeLintRule subclass: #SearchGlobalsAtUsage
 instanceVariableNames: ''
 classVariableNames: ''
 poolDictionaries: ''
 category: 'Blog-example'
  •  we have to implement the abstract methods:
 ^ 'Find all potential wrong usage in with globals'
  • I want to match an expression type because I do not care about the rest of the method, I want everything that contains the messages: #globals #at:, we also have to say what to do with the matching node in this example I will open an inspector:
 super initialize.
 self matcher
 matches: '``@lotOfStuffBefore globals at: ``@lotOfStuffAfter'
 do: [:theMatch :theOwner | theMatch inspect].
  • now we should run the rule:

WARNING: this can take a time because you will check the hole system

 SearchGlobalsAtUsage new run.

To avoid this you can restrict the environment for your rule, an example:

 rule := SearchGlobalsAtUsage new.
 environment := RBClassEnvironment class: Result.
 RBSmalllintChecker runRule: rule onEnvironment: (environment).

If you have matches then you will see the inspector.

So, as we can see this is quite complex, and in the sinposis you can see that before doing anything you have to make too many decisions, the idea behind Flamel is to make it easier.

The equivalent code (with a restricted environment) using Flamel for all this is:

FlamelMatchAndTransformRule new
 matchingExpression: '``@lotOfStuffBefore globals at: ``@lotOfStuffAfter';
 scope: environment;

If you evaluate that and inspect it you can search your results 🙂

I think this is quite cool to replace all that code (with class creation included) with 5 lines.

And this was all for understanding a little bit the rewrite engine and see Flamel in action for today


Just want to match!

My face inspecting the empty result set

My face inspecting the empty result set

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:

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:

  1. Your string is well formed, if you have a syntactic error you will see the window saying that the expression is not correct
  2. Your string has a method structure
  3. Your metavariables will play as a message send or as a variable depending on the context

A fast example, imagine this expression:

`anObject size.

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:
  1. Do you want all the senders? for defining the expresion is not the same object messageToFind that object message anotherMessage messageToFind moreMessages
  2. It can be inside a block?
  3. It can be invoked as a symbol? object perform: #messageTofind
  4. 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

This pattern:

`sel “@.Statements1. self messageTofind.  “@.Statements1

Does not match with:

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:

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.

An example

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.

A look into the rewrite tool

Trying to catch up with the current status in the rewrite tool my mentors suggested me to look into The Rewrite Tool, specially in a presentation from John Brant and Don Roberts.

I will write a short summary of what I read and then some conclusions about it.

The grammar of a method definition
The ultimate goal is to transform the code we have written, so we are going to focus in a method definition.
It’s very simple: we have the method name and a sequence of statements.
The method name can be unary, binary or keyword and the sequence node it’s conformed by temporary variables declaration (optional) and statements.

Representing the method definition
In the current implementation of Pharo we have an AST implemented that is very usefull for what we want to achive.
An AST or Abstract Syntax Tree is a tree representation of the syntax of an expresion.
So I will explain the main points in the representation of a method.
We have a MethodNode that contains (mainly) arguments, the selector (as the selector parts) and a body. Inside the body we have a SequenceNode that contains (mainly) the temporaries variables and a collection of statements. The statements can be any kind: AssigmentNode, ReturnNode, etc.
Its easier to inderstand with an example, if we have this method definition:

selector: arg1 and: arg2
|temp1 temp2|

temp1 := OrderedCollection new.
temp2 := arg1, arg2.
^temp1 + temp2

The AST will look like:

Matching an expression
For matching the tool provides the possibility to indicate a pattern, and the ability to specify throw symbols different meta variables for matching.

The real power of the tool is the number of variants that admit, making it really flexible.


Also exists the possibility to use another pattern for matching: {:node | <condition>} the node is a method node and the condition it’s valid Smalltalk code.

Some thoughts

  • In order to win flexibility, the patterns seems quite complex to write from scratch.
  • The real power for matching derives in the combination of symbols, but as the patterns are represented by strings it seems quite confusing.
  • Many times it’s easier to think in examples before writing the pattern.