Annotate Everything! Properties on the Structural Model

November 24, 2020 ☼ pharo

If you look at Pharo, the structure of the whole system is expressed in terms of Objects: Classes and Methods are objects, as they are in ST80.

But in addition, we model packages, defined Variables (yes, every defined instance variable has a meta object!) and even the structure of methods (the AST).

All of them support an API to set and query properties:

propertyAt: propName
propertyAt: propName ifAbsent: aBlock
propertyAt: propName put: propValue
hasProperty: propName
removeProperty: propName
removeProperty: propName ifAbsent: aBlock

These are implemented on:

What is this useful for? For one, properties can be used in the same way as instance variables, with the difference that they are not defined by the class definition. Just add accessors and then use them as if you would use an instance Varianle with accessors.

This is interesting for one as a first step: adding a new ivar to a system class is some cases just not possible (e.g. CompiledMethod), in all cases using a property is often exactly what you need if you are starting with an implementation, even though finally it might be better turned into an instance variable. It, too, simplifies adding state to system classes from your package using extensions (very useful for experimental code).

Another use-case is meta data: properties are per object state. They allow you to easily annoate code with data (without the annotations being textual in the source).

How do we use properties now? We have a number of examples:

Note: all the properties are not persisted with the textual representation, even though they are attached to objects that represent code. This means it is the duty of the client to make sure that they get re-applied in case the structure is re-created from the textual representation. This is especially important for the AST: it is created only on demand and flushed on image save, client have to use properties with this in mind.