Flamel is growing!

One image it’s a great way to show the current status:

A quick view

A quick view

As you can see we still have (a lot of) work to do… But we can:

  • Choose the scope where we run the run (right now a class/es or a package/packages)
  • Enter the expresion for matching and transforming
  • Search the matches
  • Apply the entire rule (matching expresion + transforming)
  • We have some actions implemented for the menus (same code, containing code, defining a variable)
  • Inspect the result for a Search or Transformation action

But still now I have some thing that I observed: The rewrite engine its in fact very cool, and surely does everything we want to do.

But it’s very complex you have to choose the matcher , modify the pattern (is an expression? is a method? you have multiple options? is about an argument?), set the environment (do you want to run where? each Environment is represented but wait! Which matcher are you using? Because not all have the feature, and they are not all polimorfic when you want to match. And of course do not even talk about  the regular expresions and the usual doubts we have (with temps? with N arguments? previous statements? and don’t forget the dot!), and… before starting… do you want to match? or do you want to transform? You have to choose!

And usually you don’t have all the information to choose that in an early moment, so what I’ve done it’s to implement a rule that delegates in existing components but takes the desitions for you… By example: Do you want to transform? Or just match? That depends… do we have a transformation expression? If that is true we want to search and replace.


testMatchAnUndefinedExpressionNotFind
 | rule |
 rule := FlamelMatchAndTransformRule new.
 rule matchingExpression: 'testFlamelFlamelNotDefinedInAnyPlaceNever'.
 rule scope: (RBClassEnvironment class: FlamelSearchMock ).
 rule run.
 self assert: (rule result isEmpty )

I want to change that to be something like:

testMatchAnUndefinedExpressionNotFind
| rule |
rule := FlamelMatchAndTransformRule new.
rule matchingExpression: 'testFlamelFlamelNotDefinedInAnyPlaceNever'.
rule applyToClass: FlamelSearchMock.
rule run.
self assert: (rule result isEmpty )

So, I have lot of work!

Some known bugs, and some unknown you can check the todo list in a Trello dashboard: https://trello.com/b/XqfJGqeB/flamel

It would be great to improve the UI because it’s quite “rustic”.

And my plan for this week it’s:

  • Implement result views ==> with this one we have a first real prototype for the tool because we can: filter the scope, enter a matching/transforming expression and understand the results
  • Implement actions for transforming menu

And as allways if you want to try download from Smalltalkhubhttp://smalltalkhub.com/mc/gisela/Flamel/main.

To open the browser just:

Flamel new openWithSpec

All the comments that you have are very wellcome, please don’t hestiate in comment or send me an email directly to me: giseladecuzzi@gmail.com.

Have a great week and nice coding!

Advertisements

Developer’s tool in Pharo

I’ve finished an internship in RMOD team in Inria and I was doing some retrospective in the work I’ve done.

The idea for my internship was to improve the developer experience while using Pharo [http://www.pharo-project.org/], (quite challenging!), so in order to do this I was mainly focused on 4 points:

  • Suggestions
  • Code Navigation
  • Syntax Coloring
  • Class Definition representation

Suggestions
While we are coding we usually want to apply actions depending on the element we are writing/seeing, for example if it’s a variable we may want to rename it. But in order to do this, we have big menus to find what we want, usually with lot of options that don’t apply.
The idea in smart suggestions is that based on the context offer only the relevant options.
We use the current AST to do this through RBParser (parseFaultyMethod:parseFaultyExpresion:) and Opal Semantic Analysis.

We choose RBParser because we can parse faulty expressions, with this feature we can offer suggestions while the user types the method.

Opal is the new compiler integrated in Pharo, it’s a very clean implementation and we think that will replace the old compiler, so we didn’t want to couple suggestions with an old compiler. The semantic analysis helps us to complete information form a code, because there is information that we can not know from the code without the context, by example: if we have a temporary variable or an instance one.
With the best AST node for the selection we have the available suggestions and with the semantic analysis we go one level deeper for the variables getting to know the nature: temporary, instance or class to refine the suggestions.

asd

If you want to define a new suggestion you only have to annotate a method with the scope where you would like to offer the suggestion and return an object respecting the SugsSuggestions API.
For returning the object you can extend SugsSuggestion and redefine the desired methods, you can see various examples with the current implementation in the SmartSuggestions-Suggestion package.
Also you can instantiate a generic suggestion: with SugsSuggestion class>>#for:named:icon: where the first parameter is a block with the action to execute and receives a valid SugsAbstractContext.

The available scopes are:

  • <assignmentCommand>
  • <classCommand>
  • <classVarCommand>
  • <instVarCommand>
  • <literalCommand>
  • <messageCommand>
  • <methodCommand>
  • <sourceCodeCommand>
  • <tempVarCommand>
  • <undeclaredVarCommand>
  • <globalCommand>

Here we have an example defining a Dummy action in

DummyAction class >>


newFormattingSuggestion
 <globalCommand>
 ^ SugsSuggestion
 for: [ :context | context formatSourceCode ]
 named: 'My global formater'
 icon: Smalltalk ui icons smallFindIcon

Navigation
Sometimes while browsing code we think in programming terms instead of text, for example we think in a messageSend or a statement instead of word, spaces or symbols.
The idea is to use context information and let the programmer navigate the code thinking in those terms.
In order to do this we find the best ast node through the RBParser and we offer navigations in different directions:
– Parent: The node that contains the selected one. For example if we have the code ‘aNumber between: anotherNumber’ and we are selecting the variable anotherNumber if we navigate to the parent we will go to the message send.
– Sibling: The node in the same level as the selected node. For example in a temporary variables definition: ‘| one two three |’if we are in the variable one we can go to the siblings two or three.
– Child: Node contained by the selected node. For example if we are in a message send: ‘aNumber between: anotherNumber’ we will go the parameter anotherNumber.

It’s very easy to see how the Suggestions + Navigation work together, and how with not too much effort you can improve a lot.
If you want to activate the Node navigation using Command (or Control if unix) + Arrows go to the System Settings and activate: AST Navigation.
ASTColoring
We want to color the syntax we are writing having the most information possible, in order to be able of select the scope where we are or show information associated to that piece of code.
In order to do that we use the AST and the semantic analysis (we need the semantic analysis because we want to show different kinds of variables with different colors, like undeclared variables), through the RBParser (parseFaultyMethod:/parseFaultyExpression:) to obtain the AST representation. The implementation it’s very simple because we can define a new Visitor to which we delegate the coloring algorithm and once we define the coloring from each syntax representation we just visit the tree: ast acceptVisitor: “visitorImplmentation”.
To enable the syntax coloring activate in System Settings: Enable AST based coloring.

Class Definition
Include a representation modeling the arguments and the message as 1st class object. About this point I have written a whole blog post.
Summary
After working with the AST I can say that is a very powerful tool and also is very easy to use. The visitor model is great and very flexible. But we must be careful because we can easily add too many responsibilities there and complicate the design.
Changing the AST structure has an obvious impact in the visitor implementors, and in the current Pharo implementation this can be complicated because we have some interesting users of the AST (like the new Compiler), and if we make a mistake it is very easy to break the image, so if we are going to do some experiments with this it is better to change the compiler first.
Obtaining an AST representation is not so hard to do when we have valid code, but when we are trying to find the best representation for a faulty expression things get nasty, and if we want to colour the text while we are writing we need this feature.

But the main point of everything is the re-affirmation that Pharo is a great tool fordoing experiments, the power of a live environment and reflectivity give us an edge over other environments.
With not so much effort we can implement some tools that improve a lot the programming experience a lot, and everyone can do this!