Blog

Spotting Pragma users with GTSpotter

Finding pieces of code that are annotated in a certain way can be challenging in many IDEs. In Pharo, this is fairly straightforward using GTSpotter.

For example, how can we find all methods annotated with <menu>?

Spawn Spotter, and type menu #pr. This will search for menu and show only the results from categories starting with pr (from Pragmas).

Pragmas.png

Then simply dive in (Cmd+RightArrow) the menu Pragma to find the concrete users.

Pragma-users.png

Posted by Tudor Girba at 9 January 2016, 10:41 pm link
|

GTDebugger in Pharo 5.0

After GTInspector, GTPlayground, and GTSpotter, it is time for GTDebugger to enter the main Pharo arena. GTDebugger is part of the Glamorous Toolkit project and it is mainly driven by Andrei Chis. Since several years it acts as the default debugger in the Moose environment. Still, even if it is a mature implementation, the debugger is a critical development tool in Pharo and a new solution can affect significantly the workflow of developers. This post offers an overview of these differences and some practical information.

We should note from the start that, to make the transition smoother, GTDebugger can be easily turned on/off through a setting.

Gtdebugger-settings.png

The generic stack debugger

The default incarnation of the GTDebugger comes with a slightly different interface than the previous debugger, so let’s take a tour.

Similar to the classic debugger structure, the stack is on top-left, and code is on the top-right, and the variables are offered at the bottom.

In the current state, the GTDebugger is implemented in Glamour, and this influences the way actions are being distributed. Thus, the stack manipulation actions (e.g., step into or step over) are offered in the stack pane, while code related actions (e.g., browse) are offered in the code pane.

Gtdebugger-zerodivide-onlyvars.png

One thing to note is that the variables at the bottom are offered in a fully functional GTInspector.

Gtdebugger-zerodivide-inspector.png

Another particularity is that the stack highlights some of the entries. For example, in the below screenshot you can observe a debugging session corresponding to the start of an inspector. The second method activation is highlighted in blue to denote that it is a method situated in the same class as the current method, and the following two are marked with black to show that they belong to the same package:

Gtdebugger-default-highlight.png

The moldable debugger

While the generic debugger has only minor differences to the classic one, the main difference comes from what cannot be easily seen. Like all other tools from the Glamorous Toolkit, GTDebugger is moldable by design. In the case of the inspector each object can influence the displayed presentations. In the case of the debugger, it is the execution context that can decide the presentation and interaction logic.

This means that we can easily create custom debuggers for different libraries. The main distribution comes with two such custom debuggers: the SUnit debugger, and the bytecode debugger. These are both useful and provide examples of how the debugger can be customized.

The SUnit debugger) provides a simple customization that shows a diff view when assert:equals: is present in the debugged stack. This might sound trivial, and it indeed it is relevant in only some cases, but detecting fine-grained differences between the expected result and the provided result is a problem is every IDE I know. It is indeed simple, but it is one of those examples of how simple things should actually be simple. This is important because simple things add up and they end up constructing the overall user experience.

This extension is found in the GT-SUnitDebugger package and it totals 132 lines of code. That should fall in the inexpensive category.

Let’s now take a look at the bytecode debugger. This one again customizes the presentation in a couple of ways:

  • a new bytecode view appears to the right of the code pane, and
  • the inspector variables appear listed with more bytecode-relevant labels (e.g., 1, rcv1).

Gtdebugger-bytecode.png

Another relevant part in a debugger is the way we can navigate the execution space. Thus, actions such as 'step over' should be controllable by the programmer of a debugger. In the case of the bytecode debugger, a desired action is to be able to step to a specific bytecode.

Gtdebugger-bytecode-actions.png

The implementation of this debugger consists of 165 lines of code.

Summary

The GTDebugger is a new take on debugging. At first glance, it looks similar to any other debugger, but its moldable nature and customization costs measured in only hundreds of lines of code paves the way for a significant departure from classic debugging.

To get you started, the core distribution comes with two concrete custom incarnations. Actually there are three: the generic stack debugger is implemented in the same way. There exists others for different libraries, such as PetitParser or Glamour, but these default ones already offer a beginning of documentation.

You can read more about the GTDebugger here:

Posted by Tudor Girba at 8 January 2016, 11:01 am with tags gt, moose, analysis, pharo link
|

Evaluating the reimplementation of key Context methods in Pharo

The Context class in Pharo is an essential one that models the activation of either a method or a block. A context instance can be obtained through the thisContext variable from anywhere in the code and it offers an entry point to manipulating the current execution.

For example, it offers information about the sender or about the receiver of the last message. This means that this object offers the entry point for debugging support: essentially the debugger is an inspector of this object. That means that you can do interesting things, such as debugging the debugger with the inspector.

What can I say. It’s a fun object to play with.

But, recently I stumbled across a little problem that Eliot pointed me to. Essentially, for it to work properly, the context object should directly work with the virtual machine and restrain itself from sending messages to the current receiver object. Unfortunately, in Pharo, this is not yet the case, and this leads to unwanted side effects.

Let's identify the culprit methods. Essentially, we want to find all non-extension methods that either:

  • send a message to self receiver, or
  • send a message to the receiver instance variable.

Of course, we do not want to rely on code reading. Even if the class is not very large, code reading is just not appropriate. Instead, we can write a query over the abstract syntax trees of all methods in the Context class:

Context methods select: [ :method |
    method package = method methodClass package and: [
        method parseTree doSemanticAnalysis allChildren
            anySatisfy: [ :each |
            each isMessage and: [
                (each receiver isMessage and: [
                    each receiver selector = #'receiver' ])
                or: [
                    each isMessage and: [
                        each receiver isVariable and: [
                            each receiver isInstance and: [
                                each receiver name = #receiver
                                ] ] ] ] ] ] ] ]

This query is rather long. It took me about 7 minutes. And I did not write it all at once. The way I wrote this was essentially by picking one method that I knew was problematic, and looking at its abstract syntax tree with the GTInspector. This allowed me to understand how the pattern I was looking for is actually represented in the tree, and write the query for it.

Onemethod.png

Inspecting the result of the above query in the GTInspector offers us a quick browser for only the problematic methods. Now we can read the code.

Query.png

Once we have this query, besides obtaining support for browsing, we can also use it for regression testing to ensure that such an important constraint is preserved in the future.

Posted by Tudor Girba at 29 November 2015, 4:57 pm link
|

Pervasive software visualizations - keynote at VISSOFT 2015

On Sunday, I will give a keynote at the IEEE Working Conference on Software Visualization (VISSOFT). This is the premier research venue in the area of software visualization. It’s a real honor especially given that I have officially left the academic research world quite a number of years ago.

I will have 90 minutes to make a point, and mine will be that visualizations should become pervasive in software development. Ok, given the audience, that should not be to be too hard to convey. The more tricky part will be to show why it did not happen until now, and what we can do to change that state of facts.

To lay out the basic arguments, Andrei and I wrote a short paper on Pervasive software visualization. In short, we argue that the development environment has to change radically to allow for a natural inclusion of visualizations in regular development workflows. To this end, the IDE has to become moldable and programmable. Essentially, this direction is based on the humane assessment philosophy of empowering the developer to craft contextual tools. We exemplify this direction with our work on the Glamorous Toolkit.

Posted by Tudor Girba at 25 September 2015, 12:04 am link
|

Understanding Metacello load directives with GTInspector

Metacello is the configuration management engine used throughout the Pharo ecosystem. It's a powerful engine, but when things go slightly wrong it can be painful to debug.

Metacello does offer some debugging support out of the box, but this support comes mainly in terms of a textual output. For example, to debug what gets loaded, you can print the result of:

((ConfigurationOfGlamour project version: #stable) 
 ignoreImage: true)
 record loadDirective

This would produce an output like:

linear load : 
	linear load : 3.3.0 [ConfigurationOfGlamour]
		load : ConfigurationOfMagritte3
	atomic load : 3.3.0 [ConfigurationOfGlamour]
		explicit load : GlamourCore
			load : ConfigurationOfGlamourCore-CyrilFerlicot.74
		linear load : 3.2.1 [ConfigurationOfGlamourCore]
			load : ConfigurationOfRubric
	...

This is not quite ideal. But, wait. We have a moldable inspector. As the data is actually a tree, we can display that output as a ... tree. What's more, as we often need to search, we could also offer a basic search possibility. The screenshot below shows how it looks like in the GTInspector:

The extension code looks like this:

MetacelloVersionLoadDirective>>gtInspectorLoadDirectivesIn: composite
	<gtInspectorPresentationOrder: 1>
	composite tree
		title: 'Load directives';
		display: [ { self } ];
		format: [:each | each label ifEmpty: [each title]];
		rootsExpanded;
		children: #gtInspectorChildren;
		filterOn: [:text :each | '\*', text, '\*' match: each label ]

This extension took about 7 minutes to write. Moldable tools can turn a problem on its head if you use them actively.

Posted by Tudor Girba at 15 September 2015, 1:27 pm link
|
<< 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 >>