====== Writing a Target Language Specification ======
;#;
[[lara:tutorial:advanced| ← Advanced LARA ]] | [[lara:tutorial:languagespecification| Language Specification ]] | [[lara:tutorial:larai|Basic larai → ]]
;#;
The most critical element of an aspect-oriented language mechanism is the join point
model, the model that represents the programming language’s points of interest, like method
execution, field gets, etc. The join point model can be different from programming language to programming
language, and also depends on the capability of the weaver to support all the join points inside
the chain. Having so, the join point model cannot be the same for all the concerning
programming languages and each one should have its join point model that illustrates those
supported points of interest.
One of the aspects of the LARA language is that it is partially agnostic to the target language. How LARA knows the join point model, the available attributes, and action that can be applied, is by using an external representation of the target language. This is accomplished by defining three files that represents the join point model and the attributes of a certain programming language, and the actions available in the weaver that will execute the LARA aspects. This approach proves an important feature of LARA that
represents its flexibility and expandability. The three files are defined in an XML format, each with specific tags and attributes.
===== Join Point Model =====
The join point model represents a hierarchical structure of the points of interest one can select on the target application.
...
For this tutorial we are using the join point model structure depicted in the graph below. This graph defines app as the **root** of the join point model hierarchy, and the arrows depict a selectable join point from the source join point. For instance, **app** → **file** means that we can select **files** inside the **app** join point. Some important remarks of this example:
- The gray arrow between **assignExpr** → **expr** means that **assignExpr** inherits everything that **expr** contains, including selectable join points, attributes and actions;
- The arrows between **body** ↔ **loop** defines that **body** is able to select the loops inside itself and, in turn, **loop** is able to select its own body;
- The two arrows connecting **body** → **stmt** means that in the first connection (without label) we are able to select all statements inside the body and in the second connection (with label **first_stmt**) we are going to select one type of statement (the first statement of the body). This is an example of having different selects for the same type of join point.
digraph finite_state_machine {
graph [ dpi = 300 ];
node [shape = square, style=rounded, penwidth=2, bgcolor=white]; app;
node [shape = square, style=rounded, penwidth=1, color=black];
app -> file;
file -> function;
function -> body;
body -> var;
body -> loop;
loop -> body;
body -> assignExpr;
body -> stmt;
body -> stmt [label="first_stmt"];
assignExpr -> expr [label="extends" style=dashed, penwidth=0.5, color="#888888", fontcolor="#888888",fontsize=10px];
}
==== The Join Point List Declaration ====
The join point model is specified in an xml format that starts with a **** element that gather all the available join points.
Inside this element we specify all the join points available in the target language. Each join point is specified inside a **** element, where the attributes **class** (mandatory) and **extends** (optional) are available. The **class** attribute defines the class of the join point we are dealing with. For instance, when the join point specifies the class as **function**, it means that we are defining function as a selectable point in the program. The **extends** attribute defines that the join point extends all the information and functionality that another join point can have. In the following example we are defining the join points specified in the previous graph: **file**, **function**, **body**,etc. Note that the **assignExpr** is extending the **expr** join point, this means that all selectable join points, attributes and actions available in the extended join point will be available in the extending join point.
Now that we have the join points listed, we have to define which one is the **root**, i.e., the top on the hierarchy structure. In the graph above we consider **app** as root. For this, we use the **root_class** and **root_alias** attributes, in the **joinpoints** element, to specify which join point is the root and the alias that we will use inside the LARA language. Since we have named our join point as **application** and the graph uses **app**, we are going to use the last as the alias for the root and the first as the join point class to use, as defined below.
==== Defining the Hierarchy ====
The previous example shows the complete list of join points available in and which one is identified as the joint point root. Since we don't have any associations between the join points, the hierarchy is still missing. The join point hierarchy, i.e. which //descendent// join points can a specific join point select. This may be accomplished by using a list of **